+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md b/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md
index 4be2831f309..b93114607e9 100644
--- a/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md
+++ b/erpnext/docs/user/manual/en/education/Attendance/student-attendance.md
@@ -12,4 +12,17 @@ Select the **Student, Course Schedule and Student Group** for which attendance i
**Student Attendance tool** can be used for bulk updation of the attendance based on **Batch, Course or Activity**.
+#### Tutorial Video on Student Attendance
+
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md b/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md
index e22c6e9d688..011d07c94cc 100644
--- a/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md
+++ b/erpnext/docs/user/manual/en/education/Attendance/student-leave-application.md
@@ -10,4 +10,17 @@ Incase the student is not attending the institute in order to participate or rep
Once a Leave Application is recorded for a student it will not be recorded in the absent student report as he has applied for a leave.
+#### Tutorial Video for Student Leave Application
+
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md b/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md
index 97a26c73ceb..5727bc230b8 100644
--- a/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md
+++ b/erpnext/docs/user/manual/en/education/admission/program-enrollment-tool.md
@@ -18,4 +18,16 @@ You can create the Program Enrollment for :
For promoting the students, the new academic year, academic term and program can also be selected for the enrollment of the fetched students list.
+#### Video Tutorial for Program Enrollment Tool
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
index 6fe9692a893..36af3f263eb 100644
--- a/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
+++ b/erpnext/docs/user/manual/en/education/admission/program-enrollment.md
@@ -17,5 +17,15 @@ Student Batch: To categorize student into different sections/batches, you can as
Student Category: For the Institutions having multiple Fees Structure, this field can be used to differentiate the student enrollment in a given fee category.
+#### Video Tutorial For Program Enrollment
-{next}
\ No newline at end of file
+
+
+
+{next}
diff --git a/erpnext/docs/user/manual/en/education/admission/student-applicant.md b/erpnext/docs/user/manual/en/education/admission/student-applicant.md
index 121844cf9a5..fa1b4c2c75b 100644
--- a/erpnext/docs/user/manual/en/education/admission/student-applicant.md
+++ b/erpnext/docs/user/manual/en/education/admission/student-applicant.md
@@ -27,4 +27,16 @@ the system shall create a student against that applicant and redirect you to the

+#### Video Tutorial for Student Application
+
+
+
+
+
{next}
diff --git a/erpnext/docs/user/manual/en/education/fees/fee-structure.md b/erpnext/docs/user/manual/en/education/fees/fee-structure.md
index 2131c4afed9..76d43a47830 100644
--- a/erpnext/docs/user/manual/en/education/fees/fee-structure.md
+++ b/erpnext/docs/user/manual/en/education/fees/fee-structure.md
@@ -20,4 +20,16 @@ You can set the "Income Account" and "Receivable Account" in the Accounts sectio
If you are going to use this in the Fee Schedule, you must select the Accounts carefully as Fee Schedule updates the respected Accounts in bulk.
+#### Video Tutorial for Fee Structure
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/schedule/course-schedule.md b/erpnext/docs/user/manual/en/education/schedule/course-schedule.md
index f5134d59fff..8b8a36eb151 100644
--- a/erpnext/docs/user/manual/en/education/schedule/course-schedule.md
+++ b/erpnext/docs/user/manual/en/education/schedule/course-schedule.md
@@ -5,6 +5,18 @@ You can see the overall course schedule in the Calendar view.

+#### Video Tutorial on Course Scheduling
+
+
+
+
### Marking Attendance
You can mark attendance for a Student Group against a Course Schedule.
diff --git a/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md b/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md
index 08a7fa9ec0c..087c933fe3b 100644
--- a/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md
+++ b/erpnext/docs/user/manual/en/education/schedule/scheduling-tool.md
@@ -20,4 +20,14 @@ This tool can be used to create 'Course Schedules'.
- Check the 'Reschedule' checkbox and then click 'Schedule Course' button.
- System will delete existing Course Schedules for specified Course within the mentioned Course Start Date and Course End Date and crate new Course Schedules.
+#### Video Tutorial on Scheduling Tool
+
+
+
{next}
diff --git a/erpnext/docs/user/manual/en/education/setup/course.md b/erpnext/docs/user/manual/en/education/setup/course.md
index 0d6e5ac5eb7..ec7d813056d 100644
--- a/erpnext/docs/user/manual/en/education/setup/course.md
+++ b/erpnext/docs/user/manual/en/education/setup/course.md
@@ -12,4 +12,18 @@ Once a **Course** is created, a course schedule can defined for the same.
The Course form is further linked to **Program, Student Group and Assessment Plan** doctypes. The links allow to view/create the related documents for a **Course**.
+#### Video Tutorial for Course
+
+
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/setup/instructor.md b/erpnext/docs/user/manual/en/education/setup/instructor.md
index 219413d275e..5af4cc098e0 100644
--- a/erpnext/docs/user/manual/en/education/setup/instructor.md
+++ b/erpnext/docs/user/manual/en/education/setup/instructor.md
@@ -16,5 +16,16 @@ While creating the **Assessment Plan** for a Student Group, **Instructor** can b
Further, the log for the Instructor can be entered in the Instructor Log table which can be used for keeping the records of subjects taught by that Instructor.
+#### Video Tutorial for Instructor
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/setup/program.md b/erpnext/docs/user/manual/en/education/setup/program.md
index 25e390eb87b..0d2a4d2994c 100644
--- a/erpnext/docs/user/manual/en/education/setup/program.md
+++ b/erpnext/docs/user/manual/en/education/setup/program.md
@@ -4,7 +4,7 @@ An educational program is a program written by the institutions which determines
To create a Program go to :
-###education >> Setup >> Program >> New Program
+> Education > Setup > Program > New Program
Enter a unique code for every **Program**. You can also link the **Program** to the department under which it is conducted.
@@ -16,4 +16,16 @@ Add the relevant Course and the Fee details for a program.
The Program Doctype is further linked to the **Student applicant**, **Program enrollment, Student group, Fee structre and Fee**. The links allow to view or create the related document for a Program.
+#### Video Tutorial on Program and Courses
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/setup/school-settings.md b/erpnext/docs/user/manual/en/education/setup/school-settings.md
index 44f9c44ed11..74e5ed561fc 100644
--- a/erpnext/docs/user/manual/en/education/setup/school-settings.md
+++ b/erpnext/docs/user/manual/en/education/setup/school-settings.md
@@ -2,7 +2,7 @@
The Education Settings page allow you to setup basic settings like **Academic Year and Term** for the educational setup.
-

+

The checkbox to Validate Batch for Students in Student Group enables the Student Batch validation for every Student from the Program Enrollment for the **Batch** based on **Student Group**
diff --git a/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md b/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md
index aeedd97a2e5..d27f4f74f64 100644
--- a/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md
+++ b/erpnext/docs/user/manual/en/education/student/student-group-creation-tool.md
@@ -4,7 +4,7 @@ The Student group creation tool allows you to create student groups in bulk.
To create Student group using this tool go to
-##education >>Student >> Student Group creation tool
+> Education > Student > Student Group creation tool
Select the **Academic Term** and the **Program** for which a student group is to be created.
@@ -14,4 +14,16 @@ By default the student group is created based on the **Course** only. The check
You can leave it unchecked if you don't want to consider batch while making course based groups.
+#### Tutorial Video on Student Group Creation Tool
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/student/student-group.md b/erpnext/docs/user/manual/en/education/student/student-group.md
index 467fb3e84e6..be68df1e731 100644
--- a/erpnext/docs/user/manual/en/education/student/student-group.md
+++ b/erpnext/docs/user/manual/en/education/student/student-group.md
@@ -6,9 +6,9 @@ A Student Group needs to be created for every course for **Academic Term** and *
To create a Student Group go to:
-education >> Student >> New Student Group
+> Education > Student > New Student Group
-

+

To create a Student group based on **Batch**, select the **Progam** and **Batch**, where as to create a Student group based on **Course**, you will only have to select the Course Code. Creating a student group based on activity allows you to group of student for events and activities happening in the institute.
@@ -18,5 +18,18 @@ Once a student group is created you can mark attendance for the group.
You can also update the **Email Group** for the Student Group. Click on Update Email Group to add all the email ids of the gaurdians in the respective email group and **Newsletter** can be created and sent to the Email group.
+#### Tutorial Video on Student Groups
+
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/docs/user/manual/en/education/student/student.md b/erpnext/docs/user/manual/en/education/student/student.md
index fce5d7ba8a8..9799e80a690 100644
--- a/erpnext/docs/user/manual/en/education/student/student.md
+++ b/erpnext/docs/user/manual/en/education/student/student.md
@@ -4,9 +4,21 @@ A Student is a person who has enrolled at your institute and you have accepted t
The Student doctype maintains detials like personal information, date of birth, address etc. It also records the **Guardian** and sibling details.

+
The student is enrolled in a **Program** when the application is approved. Once the enrollement is done the **Student Applicant** status is update to Admitted.
You can view every doctype created for a particular student. Eg : Fees, Student Group, etc
+#### Video Tutorial on Student Management
+
+
+
{next}
\ No newline at end of file
diff --git a/erpnext/education/doctype/guardian/guardian.py b/erpnext/education/doctype/guardian/guardian.py
index 3741a06a908..e82cc546af4 100644
--- a/erpnext/education/doctype/guardian/guardian.py
+++ b/erpnext/education/doctype/guardian/guardian.py
@@ -37,7 +37,6 @@ def invite_guardian(guardian):
frappe.throw(_("Please set Email Address"))
else:
guardian_as_user = frappe.get_value('User', dict(email=guardian_doc.email_address))
- print guardian_as_user
if guardian_as_user:
frappe.msgprint(_("User {0} already exists").format(getlink("User", guardian_as_user)))
return guardian_as_user
diff --git a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
index 7206e4b58c3..0d3d6e76508 100644
--- a/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
+++ b/erpnext/healthcare/doctype/healthcare_settings/healthcare_settings.py
@@ -9,60 +9,60 @@ from frappe.core.doctype.sms_settings.sms_settings import send_sms
import json
class HealthcareSettings(Document):
- def validate(self):
- for key in ["collect_registration_fee","manage_customer","patient_master_name",
- "require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
- frappe.db.set_default(key, self.get(key, ""))
- if(self.collect_registration_fee):
- if self.registration_fee <= 0 :
- frappe.throw("Registration fee can not be Zero")
+ def validate(self):
+ for key in ["collect_registration_fee","manage_customer","patient_master_name",
+ "require_test_result_approval","require_sample_collection", "default_medical_code_standard"]:
+ frappe.db.set_default(key, self.get(key, ""))
+ if(self.collect_registration_fee):
+ if self.registration_fee <= 0 :
+ frappe.throw("Registration fee can not be Zero")
@frappe.whitelist()
def get_sms_text(doc):
- sms_text = {}
- doc = frappe.get_doc("Lab Test",doc)
- #doc = json.loads(doc)
- context = {"doc": doc, "alert": doc, "comments": None}
- emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed")
- sms_text['emailed'] = frappe.render_template(emailed, context)
- printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed")
- sms_text['printed'] = frappe.render_template(printed, context)
- return sms_text
+ sms_text = {}
+ doc = frappe.get_doc("Lab Test",doc)
+ #doc = json.loads(doc)
+ context = {"doc": doc, "alert": doc, "comments": None}
+ emailed = frappe.db.get_value("Healthcare Settings", None, "sms_emailed")
+ sms_text['emailed'] = frappe.render_template(emailed, context)
+ printed = frappe.db.get_value("Healthcare Settings", None, "sms_printed")
+ sms_text['printed'] = frappe.render_template(printed, context)
+ return sms_text
def send_registration_sms(doc):
- if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'):
- if doc.mobile:
- context = {"doc": doc, "alert": doc, "comments": None}
- if doc.get("_comments"):
- context["comments"] = json.loads(doc.get("_comments"))
- messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg")
- messages = frappe.render_template(messages, context)
- number = [doc.mobile]
- send_sms(number,messages)
- else:
- frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True)
+ if (frappe.db.get_value("Healthcare Settings", None, "reg_sms")=='1'):
+ if doc.mobile:
+ context = {"doc": doc, "alert": doc, "comments": None}
+ if doc.get("_comments"):
+ context["comments"] = json.loads(doc.get("_comments"))
+ messages = frappe.db.get_value("Healthcare Settings", None, "reg_msg")
+ messages = frappe.render_template(messages, context)
+ number = [doc.mobile]
+ send_sms(number,messages)
+ else:
+ frappe.msgprint(doc.name + " Has no mobile number to send registration SMS", alert=True)
def get_receivable_account(company):
- receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company)
- if receivable_account:
- return receivable_account
- return frappe.db.get_value("Company", company, "default_receivable_account")
+ receivable_account = get_account(None, "receivable_account", "Healthcare Settings", company)
+ if receivable_account:
+ return receivable_account
+ return frappe.db.get_value("Company", company, "default_receivable_account")
def get_income_account(physician, company):
- if(physician):
- income_account = get_account("Physician", None, physician, company)
- if income_account:
- return income_account
- income_account = get_account(None, "income_account", "Healthcare Settings", company)
- if income_account:
- return income_account
- return frappe.db.get_value("Company", company, "default_income_account")
+ if(physician):
+ income_account = get_account("Physician", None, physician, company)
+ if income_account:
+ return income_account
+ income_account = get_account(None, "income_account", "Healthcare Settings", company)
+ if income_account:
+ return income_account
+ return frappe.db.get_value("Company", company, "default_income_account")
def get_account(parent_type, parent_field, parent, company):
- if(parent_type):
- return frappe.db.get_value("Party Account",
- {"parenttype": parent_type, "parent": parent, "company": company}, "account")
- if(parent_field):
- return frappe.db.get_value("Party Account",
- {"parentfield": parent_field, "parent": parent, "company": company}, "account")
+ if(parent_type):
+ return frappe.db.get_value("Party Account",
+ {"parenttype": parent_type, "parent": parent, "company": company}, "account")
+ if(parent_field):
+ return frappe.db.get_value("Party Account",
+ {"parentfield": parent_field, "parent": parent, "company": company}, "account")
diff --git a/erpnext/manufacturing/doctype/bom/bom.py b/erpnext/manufacturing/doctype/bom/bom.py
index a06645ad9fa..fb52d5260cc 100644
--- a/erpnext/manufacturing/doctype/bom/bom.py
+++ b/erpnext/manufacturing/doctype/bom/bom.py
@@ -592,7 +592,7 @@ def validate_bom_no(item, bom_no):
@frappe.whitelist()
def get_children(doctype, parent=None, is_root=False, **filters):
- if not parent:
+ if not parent or parent=="BOM":
frappe.msgprint(_('Please select a BOM'))
return
diff --git a/erpnext/manufacturing/doctype/bom/bom_tree.js b/erpnext/manufacturing/doctype/bom/bom_tree.js
index 854f6334d73..6cbd7a2ab16 100644
--- a/erpnext/manufacturing/doctype/bom/bom_tree.js
+++ b/erpnext/manufacturing/doctype/bom/bom_tree.js
@@ -11,7 +11,8 @@ frappe.treeview_settings["BOM"] = {
title: "BOM",
breadcrumb: "Manufacturing",
disable_add_node: true,
- root_label: "All Bill of Materials", //fieldname from filters
+ root_label: "BOM", //fieldname from filters
+ get_tree_root: false,
get_label: function(node) {
if(node.data.qty) {
return node.data.qty + " x " + node.data.item_code;
@@ -19,6 +20,23 @@ frappe.treeview_settings["BOM"] = {
return node.data.item_code || node.data.value;
}
},
+ onload: function(me) {
+ var label = frappe.get_route()[0] + "/" + frappe.get_route()[1];
+ if(frappe.pages[label]) {
+ delete frappe.pages[label];
+ }
+
+ var filter = me.opts.filters[0];
+ if(frappe.route_options && frappe.route_options[filter.fieldname]) {
+ var val = frappe.route_options[filter.fieldname];
+ delete frappe.route_options[filter.fieldname];
+ filter.default = "";
+ me.args[filter.fieldname] = val;
+ me.root_label = val;
+ me.page.set_title(val);
+ }
+ me.make_tree();
+ },
toolbar: [
{ toggle_btn: true },
{
diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py
index 7cfbab002a7..d3b7c5a4980 100644
--- a/erpnext/manufacturing/doctype/production_order/production_order.py
+++ b/erpnext/manufacturing/doctype/production_order/production_order.py
@@ -490,7 +490,7 @@ class ProductionOrder(Document):
and detail.parent = entry.name
and detail.item_code = %s''', (self.name, d.item_code))[0][0]
- d.db_set('transferred_qty', transferred_qty, update_modified = False)
+ d.db_set('transferred_qty', flt(transferred_qty), update_modified = False)
@frappe.whitelist()
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index d300285c676..f5953e2c492 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -345,7 +345,7 @@ erpnext.patches.v7_0.repost_bin_qty_and_item_projected_qty
erpnext.patches.v7_1.set_prefered_contact_email
execute:frappe.reload_doc('accounts', 'doctype', 'accounts_settings')
execute:frappe.db.set_value("Accounts Settings", "Accounts Settings", "unlink_payment_on_cancellation_of_invoice", 0)
-execute:frappe.db.sql("update `tabStock Entry` set total_amount = null where purpose in('Repack', 'Manufacture')")
+execute:frappe.db.sql("update `tabStock Entry` set total_amount = 0 where purpose in('Repack', 'Manufacture')")
erpnext.patches.v7_1.save_stock_settings
erpnext.patches.v7_0.repost_gle_for_pi_with_update_stock #2016-11-01
erpnext.patches.v7_1.add_account_user_role_for_timesheet
diff --git a/erpnext/patches/v7_0/update_status_of_po_so.py b/erpnext/patches/v7_0/update_status_of_po_so.py
index c0b6f59eaf5..d630e8f0f2d 100644
--- a/erpnext/patches/v7_0/update_status_of_po_so.py
+++ b/erpnext/patches/v7_0/update_status_of_po_so.py
@@ -20,7 +20,10 @@ def update_po_per_received_per_billed():
where parent = `tabPurchase Order`.name), 2),
`tabPurchase Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabPurchase Order Item`
- where parent = `tabPurchase Order`.name), 2), 0)""")
+ where parent = `tabPurchase Order`.name), 2), 0)
+ where
+ net_total > 0
+ """)
def update_so_per_delivered_per_billed():
frappe.db.sql("""
@@ -32,7 +35,10 @@ def update_so_per_delivered_per_billed():
where parent = `tabSales Order`.name), 2),
`tabSales Order`.per_billed = ifnull(round((select sum( if(amount > ifnull(billed_amt, 0),
ifnull(billed_amt, 0), amount)) / sum(amount) *100 from `tabSales Order Item`
- where parent = `tabSales Order`.name), 2), 0)""")
+ where parent = `tabSales Order`.name), 2), 0)
+ where
+ net_total > 0
+ """)
def update_status():
frappe.db.sql("""
diff --git a/erpnext/patches/v7_1/set_currency_exchange_date.py b/erpnext/patches/v7_1/set_currency_exchange_date.py
index 7d8e4f0415d..630b7d42293 100644
--- a/erpnext/patches/v7_1/set_currency_exchange_date.py
+++ b/erpnext/patches/v7_1/set_currency_exchange_date.py
@@ -5,5 +5,5 @@ def execute():
frappe.db.sql("""
update `tabCurrency Exchange`
set `date` = '2010-01-01'
- where date is null or date = '' or date = '0000-00-00'
+ where date is null or date = '0000-00-00'
""")
\ No newline at end of file
diff --git a/erpnext/patches/v7_2/rename_att_date_attendance.py b/erpnext/patches/v7_2/rename_att_date_attendance.py
index f7caf706db5..b2658ba7f12 100644
--- a/erpnext/patches/v7_2/rename_att_date_attendance.py
+++ b/erpnext/patches/v7_2/rename_att_date_attendance.py
@@ -7,7 +7,7 @@ def execute():
frappe.reload_doc("hr", "doctype", "attendance")
frappe.db.sql("""update `tabAttendance`
set attendance_date = att_date
- where attendance_date is null or attendance_date = '' or attendance_date = '0000-00-00'""")
+ where attendance_date is null or attendance_date = '0000-00-00'""")
update_reports("Attendance", "att_date", "attendance_date")
update_users_report_view_settings("Attendance", "att_date", "attendance_date")
diff --git a/erpnext/patches/v7_2/update_salary_slips.py b/erpnext/patches/v7_2/update_salary_slips.py
index 22bb1d82dc9..c6bca8e7b9b 100644
--- a/erpnext/patches/v7_2/update_salary_slips.py
+++ b/erpnext/patches/v7_2/update_salary_slips.py
@@ -9,8 +9,7 @@ def execute():
salary_slips = frappe.db.sql("""select month, name, fiscal_year from `tabSalary Slip`
where (month is not null and month != '') and
- (start_date is null or start_date = '') and
- (end_date is null or end_date = '') and docstatus != 2""", as_dict=True)
+ start_date is null and end_date is null and docstatus != 2""", as_dict=True)
for salary_slip in salary_slips:
if not cint(salary_slip.month):
diff --git a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
index aa5cbc50bcc..2e815710722 100644
--- a/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
+++ b/erpnext/patches/v8_1/set_delivery_date_in_so_item.py
@@ -8,7 +8,7 @@ def execute():
frappe.db.sql("""
update `tabSales Order`
set delivery_date = final_delivery_date
- where (delivery_date is null or delivery_date = '' or delivery_date = '0000-00-00')
+ where (delivery_date is null or delivery_date = '0000-00-00')
and order_type = 'Sales'""")
frappe.db.sql("""
@@ -16,8 +16,6 @@ def execute():
set so_item.delivery_date = so.delivery_date
where so.name = so_item.parent
and so.order_type = 'Sales'
- and (so_item.delivery_date is null or so_item.delivery_date = ''
- or so_item.delivery_date = '0000-00-00')
- and (so.delivery_date is not null and so.delivery_date != ''
- and so.delivery_date != '0000-00-00')
- """)
+ and (so_item.delivery_date is null or so_item.delivery_date = '0000-00-00')
+ and (so.delivery_date is not null and so.delivery_date != '0000-00-00')
+ """)
\ No newline at end of file
diff --git a/erpnext/selling/doctype/customer/customer.json b/erpnext/selling/doctype/customer/customer.json
index ecc14624e54..8a57f6d64d4 100644
--- a/erpnext/selling/doctype/customer/customer.json
+++ b/erpnext/selling/doctype/customer/customer.json
@@ -1066,9 +1066,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "depends_on": "",
- "fieldname": "payment_terms",
- "fieldtype": "Link",
+ "default": "0",
+ "fieldname": "bypass_credit_limit_check_at_sales_order",
+ "fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1076,10 +1076,9 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Default Payment Terms Template",
+ "label": "Bypass credit limit check at Sales Order",
"length": 0,
"no_copy": 0,
- "options": "Payment Terms Template",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -1098,9 +1097,8 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
- "default": "0",
- "fieldname": "bypass_credit_limit_check_at_sales_order",
- "fieldtype": "Check",
+ "fieldname": "column_break_34",
+ "fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -1108,7 +1106,6 @@
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
- "label": "Bypass credit limit check at Sales Order",
"length": 0,
"no_copy": 0,
"permlevel": 0,
@@ -1123,6 +1120,38 @@
"set_only_once": 0,
"unique": 0
},
+ {
+ "allow_bulk_edit": 0,
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "columns": 0,
+ "depends_on": "",
+ "fieldname": "payment_terms",
+ "fieldtype": "Link",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_global_search": 0,
+ "in_list_view": 0,
+ "in_standard_filter": 0,
+ "label": "Default Payment Terms Template",
+ "length": 0,
+ "no_copy": 0,
+ "options": "Payment Terms Template",
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "remember_last_selected_value": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
+ },
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py
index f19173eaa9b..d0db648ba6c 100644
--- a/erpnext/selling/doctype/customer/customer.py
+++ b/erpnext/selling/doctype/customer/customer.py
@@ -70,12 +70,12 @@ class Customer(TransactionBase):
def fetch_primary_address_and_contact_detail(self):
if(self.customer_primary_contact):
primary_contact_doc = frappe.get_doc("Contact",self.customer_primary_contact)
- self.db_set('mobile_no', primary_contact_doc.mobile_no)
- self.db_set('email_id', primary_contact_doc.email_id)
+ self.mobile_no = primary_contact_doc.mobile_no
+ self.email_id = primary_contact_doc.email_id
if(self.customer_primary_address):
primary_address_doc = frappe.get_doc("Address",self.customer_primary_address)
- self.db_set('primary_address', "
" + primary_address_doc.get_display())
+ self.primary_address = "
" + primary_address_doc.get_display()
def create_primary_contact(self):
if not self.customer_primary_contact and not self.lead_name:
@@ -197,12 +197,14 @@ def get_customer_list(doctype, txt, searchfield, start, page_len, filters):
("%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, "%%%s%%" % txt, start, page_len))
-def check_credit_limit(customer, company):
- customer_outstanding = get_customer_outstanding(customer, company)
+def check_credit_limit(customer, company, ignore_outstanding_sales_order=False, extra_amount=0):
+ customer_outstanding = get_customer_outstanding(customer, company, ignore_outstanding_sales_order)
+ if extra_amount > 0:
+ customer_outstanding += flt(extra_amount)
credit_limit = get_credit_limit(customer, company)
if credit_limit > 0 and flt(customer_outstanding) > credit_limit:
- msgprint(_("Credit limit has been crossed for customer {0} {1}/{2}")
+ msgprint(_("Credit limit has been crossed for customer {0} ({1}/{2})")
.format(customer, customer_outstanding, credit_limit))
# If not authorized person raise exception
@@ -243,7 +245,8 @@ def get_customer_outstanding(customer, company, ignore_outstanding_sales_order=F
and dn.customer=%s and dn.company=%s
and dn.docstatus = 1 and dn.status not in ('Closed', 'Stopped')
and ifnull(dn_item.against_sales_order, '') = ''
- and ifnull(dn_item.against_sales_invoice, '') = ''""", (customer, company), as_dict=True)
+ and ifnull(dn_item.against_sales_invoice, '') = ''
+ """, (customer, company), as_dict=True)
outstanding_based_on_dn = 0.0
diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py
index 5bacf28bb82..60046c819fb 100644
--- a/erpnext/selling/doctype/sales_order/sales_order.py
+++ b/erpnext/selling/doctype/sales_order/sales_order.py
@@ -484,11 +484,6 @@ def make_delivery_note(source_name, target_doc=None):
else:
target.po_no = source.po_no
- # Since the credit limit check is bypassed at sales order level,
- # we need to check it at delivery note
- if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")):
- check_credit_limit(source.customer, source.company)
-
target.ignore_pricing_rule = 1
target.run_method("set_missing_values")
target.run_method("calculate_taxes_and_totals")
@@ -553,10 +548,6 @@ def make_sales_invoice(source_name, target_doc=None, ignore_permissions=False):
target.run_method("set_missing_values")
target.run_method("calculate_taxes_and_totals")
- # Since the credit limit check is bypassed at sales order level, we need to check it at sales invoice
- if cint(frappe.db.get_value("Customer", source.customer, "bypass_credit_limit_check_at_sales_order")):
- check_credit_limit(source.customer, source.company)
-
# set company address
target.update(get_company_address(target.company))
if target.company_address:
diff --git a/erpnext/selling/page/point_of_sale/point_of_sale.js b/erpnext/selling/page/point_of_sale/point_of_sale.js
index 29238ea8058..2da5431e980 100644
--- a/erpnext/selling/page/point_of_sale/point_of_sale.js
+++ b/erpnext/selling/page/point_of_sale/point_of_sale.js
@@ -468,6 +468,7 @@ erpnext.pos.PointOfSale = class PointOfSale {
if (r.message) {
this.frm.meta.default_print_format = r.message.print_format || 'POS Invoice';
+ this.frm.allow_edit_rate = r.message.allow_edit_rate;
}
}
@@ -739,6 +740,7 @@ class POSCart {
disable_highlight: ['Qty', 'Disc', 'Rate', 'Pay'],
reset_btns: ['Qty', 'Disc', 'Rate', 'Pay'],
del_btn: 'Del',
+ disable_btns: !this.frm.allow_edit_rate ? ['Rate']: [],
wrapper: this.wrapper.find('.number-pad-container'),
onclick: (btn_value) => {
// on click
@@ -1269,7 +1271,7 @@ class NumberPad {
constructor({
wrapper, onclick, button_array,
add_class={}, disable_highlight=[],
- reset_btns=[], del_btn='',
+ reset_btns=[], del_btn='', disable_btns
}) {
this.wrapper = wrapper;
this.onclick = onclick;
@@ -1278,6 +1280,7 @@ class NumberPad {
this.disable_highlight = disable_highlight;
this.reset_btns = reset_btns;
this.del_btn = del_btn;
+ this.disable_btns = disable_btns;
this.make_dom();
this.bind_events();
this.value = '';
@@ -1308,6 +1311,14 @@ class NumberPad {
}
this.set_class();
+
+ this.disable_btns.forEach((btn) => {
+ const $btn = this.get_btn(btn);
+ $btn.prop("disabled", true)
+ $btn.hover(() => {
+ $btn.css('cursor','not-allowed');
+ })
+ })
}
set_class() {
diff --git a/erpnext/setup/setup_wizard/setup_wizard.py b/erpnext/setup/setup_wizard/setup_wizard.py
index 2c5f7e84563..d6491a8659c 100644
--- a/erpnext/setup/setup_wizard/setup_wizard.py
+++ b/erpnext/setup/setup_wizard/setup_wizard.py
@@ -5,7 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe import _
-from operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data
+from .operations import install_fixtures, taxes_setup, defaults_setup, company_setup, sample_data
def get_setup_stages(args=None):
if frappe.db.sql("select name from tabCompany"):
diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py
index bcbc35ee7ec..1673a96ef6b 100644
--- a/erpnext/stock/doctype/batch/batch.py
+++ b/erpnext/stock/doctype/batch/batch.py
@@ -203,7 +203,7 @@ def set_batch_nos(doc, warehouse_field, throw=False):
else:
batch_qty = get_batch_qty(batch_no=d.batch_no, warehouse=warehouse)
if flt(batch_qty, d.precision("qty")) < flt(qty, d.precision("qty")):
- frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, d.stock_qty))
+ frappe.throw(_("Row #{0}: The batch {1} has only {2} qty. Please select another batch which has {3} qty available or split the row into multiple rows, to deliver/issue from multiple batches").format(d.idx, d.batch_no, batch_qty, qty))
@frappe.whitelist()
diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.py b/erpnext/stock/doctype/delivery_note/delivery_note.py
index dd00398695b..65f384f6d90 100644
--- a/erpnext/stock/doctype/delivery_note/delivery_note.py
+++ b/erpnext/stock/doctype/delivery_note/delivery_note.py
@@ -235,13 +235,22 @@ class DeliveryNote(SellingController):
def check_credit_limit(self):
from erpnext.selling.doctype.customer.customer import check_credit_limit
+ extra_amount = 0
validate_against_credit_limit = False
- for d in self.get("items"):
- if not (d.against_sales_order or d.against_sales_invoice):
- validate_against_credit_limit = True
- break
+ bypass_credit_limit_check_at_sales_order = cint(frappe.db.get_value("Customer", self.customer,
+ "bypass_credit_limit_check_at_sales_order"))
+ if bypass_credit_limit_check_at_sales_order:
+ validate_against_credit_limit = True
+ extra_amount = self.base_grand_total
+ else:
+ for d in self.get("items"):
+ if not (d.against_sales_order or d.against_sales_invoice):
+ validate_against_credit_limit = True
+ break
+
if validate_against_credit_limit:
- check_credit_limit(self.customer, self.company)
+ check_credit_limit(self.customer, self.company,
+ bypass_credit_limit_check_at_sales_order, extra_amount)
def validate_packed_qty(self):
"""
diff --git a/erpnext/stock/doctype/item/item.js b/erpnext/stock/doctype/item/item.js
index c7719e4b8cd..104eeb82ac1 100644
--- a/erpnext/stock/doctype/item/item.js
+++ b/erpnext/stock/doctype/item/item.js
@@ -317,11 +317,6 @@ $.extend(erpnext.item, {
show_multiple_variants_dialog: function(frm) {
var me = this;
- if(me.multiple_variant_dialog) {
- me.multiple_variant_dialog.show();
- return;
- }
-
let promises = [];
let attr_val_fields = {};
diff --git a/erpnext/templates/generators/item.html b/erpnext/templates/generators/item.html
index de544930cc3..6fec94e99cd 100644
--- a/erpnext/templates/generators/item.html
+++ b/erpnext/templates/generators/item.html
@@ -57,6 +57,21 @@