From e16ec0c891104080d50072dcfdb038b6c51cee75 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 28 Jul 2017 12:43:07 +0530 Subject: [PATCH 01/12] [minor] change docs_base_url --- .../user/manual/en/schools/admission/program-enrollment.md | 2 +- .../user/manual/en/schools/admission/student-applicant.md | 4 ++-- erpnext/docs/user/manual/en/schools/fees/fee-category.md | 2 +- erpnext/docs/user/manual/en/schools/fees/fee-structure.md | 2 +- erpnext/docs/user/manual/en/schools/fees/fees.md | 2 +- erpnext/docs/user/manual/en/schools/fees/index.md | 2 +- erpnext/docs/user/manual/en/schools/index.md | 2 +- .../docs/user/manual/en/schools/schedule/course-schedule.md | 6 +++--- erpnext/docs/user/manual/en/schools/schedule/examination.md | 2 +- erpnext/docs/user/manual/en/schools/schedule/index.md | 2 +- .../docs/user/manual/en/schools/schedule/scheduling-tool.md | 2 +- .../user/manual/en/schools/schedule/student-attendance.md | 2 +- erpnext/docs/user/manual/en/schools/setup/academic-term.md | 2 +- erpnext/docs/user/manual/en/schools/setup/academic-year.md | 2 +- erpnext/docs/user/manual/en/schools/setup/course.md | 2 +- erpnext/docs/user/manual/en/schools/setup/index.md | 2 +- erpnext/docs/user/manual/en/schools/setup/instructor.md | 2 +- erpnext/docs/user/manual/en/schools/setup/program.md | 2 +- erpnext/docs/user/manual/en/schools/setup/room.md | 2 +- .../docs/user/manual/en/schools/student/student-batch.md | 2 +- .../en/schools/student/student-group-creation-tool.md | 2 +- .../docs/user/manual/en/schools/student/student-group.md | 2 +- erpnext/docs/user/manual/en/schools/student/student-log.md | 2 +- erpnext/docs/user/manual/en/schools/student/student.md | 2 +- 24 files changed, 27 insertions(+), 27 deletions(-) diff --git a/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md b/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md index 060033cba0..f1d1b0f5df 100644 --- a/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md +++ b/erpnext/docs/user/manual/en/schools/admission/program-enrollment.md @@ -1,5 +1,5 @@ This form allows you to enroll a student to a program. A student can be enrolled to multiple programs. -Student Applicant Enrollment +Student Applicant Enrollment {next} diff --git a/erpnext/docs/user/manual/en/schools/admission/student-applicant.md b/erpnext/docs/user/manual/en/schools/admission/student-applicant.md index 2b33cf957f..0a08f1105c 100644 --- a/erpnext/docs/user/manual/en/schools/admission/student-applicant.md +++ b/erpnext/docs/user/manual/en/schools/admission/student-applicant.md @@ -3,7 +3,7 @@ A Student Applicant record needs to be created when a student applies for a program at your institute. You can Approve or Reject a student applicant. By accepting a student applicant you can add them to the student master. -Student Applicant +Student Applicant ### Application Status @@ -23,6 +23,6 @@ You can Approve or Reject a student applicant. By accepting a student applicant Once you approve a Student Applicant you can enroll them to a program. When you click the 'Enroll' buttom, the system shall create a student against that applicant and redirect you to the [Program Enrollment form]({{docs_base_url}}/user/manual/en/schools/student/program-enrollment.html). -Student Applicant Enrollment +Student Applicant Enrollment {next} diff --git a/erpnext/docs/user/manual/en/schools/fees/fee-category.md b/erpnext/docs/user/manual/en/schools/fees/fee-category.md index d6694b503d..b333ffecc0 100644 --- a/erpnext/docs/user/manual/en/schools/fees/fee-category.md +++ b/erpnext/docs/user/manual/en/schools/fees/fee-category.md @@ -2,6 +2,6 @@ List of all different type of fees collected. -Fees Category +Fees Category {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/fees/fee-structure.md b/erpnext/docs/user/manual/en/schools/fees/fee-structure.md index 08d09e545e..a796b0cd2b 100644 --- a/erpnext/docs/user/manual/en/schools/fees/fee-structure.md +++ b/erpnext/docs/user/manual/en/schools/fees/fee-structure.md @@ -2,6 +2,6 @@ A Fee Structure is a template that can be used while making fee records. -Fees Structure +Fees Structure {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/fees/fees.md b/erpnext/docs/user/manual/en/schools/fees/fees.md index 242abf8797..5745ec1b6a 100644 --- a/erpnext/docs/user/manual/en/schools/fees/fees.md +++ b/erpnext/docs/user/manual/en/schools/fees/fees.md @@ -3,6 +3,6 @@ Maintain a record of fees collected from students. The [Fee Structure]({{docs_base_url}}/user/manual/en/schools/fees/fee-structure.html) is fetched based on the selected Program and Academic Term. -Fees +Fees {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/fees/index.md b/erpnext/docs/user/manual/en/schools/fees/index.md index f75c53774f..ab07182738 100644 --- a/erpnext/docs/user/manual/en/schools/fees/index.md +++ b/erpnext/docs/user/manual/en/schools/fees/index.md @@ -2,7 +2,7 @@ This section contains 'Fee' related documents. -Fees Section +Fees Section ### Topics diff --git a/erpnext/docs/user/manual/en/schools/index.md b/erpnext/docs/user/manual/en/schools/index.md index e2172ff916..16fd31d534 100644 --- a/erpnext/docs/user/manual/en/schools/index.md +++ b/erpnext/docs/user/manual/en/schools/index.md @@ -1,6 +1,6 @@ The School Modules is designed to meet requirements of Schools, Colleges & Educational Institutes. -Fees Section +Fees Section {index} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/schedule/course-schedule.md b/erpnext/docs/user/manual/en/schools/schedule/course-schedule.md index 9c27f61ac7..d766f66f79 100644 --- a/erpnext/docs/user/manual/en/schools/schedule/course-schedule.md +++ b/erpnext/docs/user/manual/en/schools/schedule/course-schedule.md @@ -3,13 +3,13 @@ Course Schedule is the schedule of a session conducted by an Instructor for a particular Course. You can see the overall course schedule in the Calendar view. -Course Schedule +Course Schedule ### Marking Attendance You can mark attendance for a Student Group against a Course Schedule. -Course Schedule Attendance +Course Schedule Attendance - To make attendance, expand the attendance section. - Check the students who were present for that session. @@ -20,6 +20,6 @@ You can mark attendance for a Student Group against a Course Schedule. Once you have marked Attendance against a Course Schedule the Attendance section in the Course Schedule shall be hidden. A View Attendance button shall appear. Click on that button to view all attendance records created against that Course Schedule. -Course Schedule Attendance +Course Schedule Attendance {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/schedule/examination.md b/erpnext/docs/user/manual/en/schools/schedule/examination.md index cd5d8386b6..14bc182739 100644 --- a/erpnext/docs/user/manual/en/schools/schedule/examination.md +++ b/erpnext/docs/user/manual/en/schools/schedule/examination.md @@ -2,7 +2,7 @@ The Examination record can be used to track the exam schedule and the results of that exam. -Examination +Examination {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/schedule/index.md b/erpnext/docs/user/manual/en/schools/schedule/index.md index 3fd993ed03..8d343bf663 100644 --- a/erpnext/docs/user/manual/en/schools/schedule/index.md +++ b/erpnext/docs/user/manual/en/schools/schedule/index.md @@ -1,6 +1,6 @@ # Schedule -Schedule Section +Schedule Section ### Topics diff --git a/erpnext/docs/user/manual/en/schools/schedule/scheduling-tool.md b/erpnext/docs/user/manual/en/schools/schedule/scheduling-tool.md index 84b3908b17..a5eb9f250b 100644 --- a/erpnext/docs/user/manual/en/schools/schedule/scheduling-tool.md +++ b/erpnext/docs/user/manual/en/schools/schedule/scheduling-tool.md @@ -2,7 +2,7 @@ This tool can be used to create 'Course Schedules'. -Scheduling Tool +Scheduling Tool ### Creating Course Schedules diff --git a/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md b/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md index 474b543b50..ef89e5da85 100644 --- a/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md +++ b/erpnext/docs/user/manual/en/schools/schedule/student-attendance.md @@ -2,6 +2,6 @@ Maintains attendance record of the student. Attendance Records can be created against Course Schedules. -Student Attendance +Student Attendance {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/academic-term.md b/erpnext/docs/user/manual/en/schools/setup/academic-term.md index dbce6d92ea..f268fd0566 100644 --- a/erpnext/docs/user/manual/en/schools/setup/academic-term.md +++ b/erpnext/docs/user/manual/en/schools/setup/academic-term.md @@ -1,6 +1,6 @@ # Academic Term -Academic Term +Academic Term {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/academic-year.md b/erpnext/docs/user/manual/en/schools/setup/academic-year.md index 4a153932bc..1d836f843d 100644 --- a/erpnext/docs/user/manual/en/schools/setup/academic-year.md +++ b/erpnext/docs/user/manual/en/schools/setup/academic-year.md @@ -1,5 +1,5 @@ # Academic Year -Academic Year +Academic Year {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/course.md b/erpnext/docs/user/manual/en/schools/setup/course.md index da5fa379be..b6c1aca240 100644 --- a/erpnext/docs/user/manual/en/schools/setup/course.md +++ b/erpnext/docs/user/manual/en/schools/setup/course.md @@ -1,5 +1,5 @@ # Course -Course +Course {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/index.md b/erpnext/docs/user/manual/en/schools/setup/index.md index 5a360ddecc..23054ad291 100644 --- a/erpnext/docs/user/manual/en/schools/setup/index.md +++ b/erpnext/docs/user/manual/en/schools/setup/index.md @@ -1,6 +1,6 @@ # Setup -Setup Section +Setup Section ### Topics diff --git a/erpnext/docs/user/manual/en/schools/setup/instructor.md b/erpnext/docs/user/manual/en/schools/setup/instructor.md index adbfe2a2f8..7bfd348457 100644 --- a/erpnext/docs/user/manual/en/schools/setup/instructor.md +++ b/erpnext/docs/user/manual/en/schools/setup/instructor.md @@ -1,5 +1,5 @@ # Instructor -Instructor +Instructor {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/program.md b/erpnext/docs/user/manual/en/schools/setup/program.md index 813019bfce..2f1c207f4f 100644 --- a/erpnext/docs/user/manual/en/schools/setup/program.md +++ b/erpnext/docs/user/manual/en/schools/setup/program.md @@ -1,5 +1,5 @@ # Program -Program +Program {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/setup/room.md b/erpnext/docs/user/manual/en/schools/setup/room.md index 052e96204a..9ec39e8788 100644 --- a/erpnext/docs/user/manual/en/schools/setup/room.md +++ b/erpnext/docs/user/manual/en/schools/setup/room.md @@ -1,6 +1,6 @@ # Room -Room +Room {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-batch.md b/erpnext/docs/user/manual/en/schools/student/student-batch.md index 0f29d46031..3a6c82fce9 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-batch.md +++ b/erpnext/docs/user/manual/en/schools/student/student-batch.md @@ -2,6 +2,6 @@ Student batch is a collection of students from Student Groups. -Student +Student {next} diff --git a/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md b/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md index 1fcd87c745..c5e23b7086 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md +++ b/erpnext/docs/user/manual/en/schools/student/student-group-creation-tool.md @@ -1,6 +1,6 @@ This tool allows you to create student groups in bulk. You can specify multiple parameters to create them. -Student Group Creation Tool +Student Group Creation Tool {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-group.md b/erpnext/docs/user/manual/en/schools/student/student-group.md index eaa60f78b0..91118c7d19 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-group.md +++ b/erpnext/docs/user/manual/en/schools/student/student-group.md @@ -3,6 +3,6 @@ A student group is a collection of students taking a same course. You can create Course Schedules and Examinations against a Student Group. A student group needs to be created for every course in a particular academic term and academic year. -Student Group +Student Group {next} \ No newline at end of file diff --git a/erpnext/docs/user/manual/en/schools/student/student-log.md b/erpnext/docs/user/manual/en/schools/student/student-log.md index 787dacb471..028d136b60 100644 --- a/erpnext/docs/user/manual/en/schools/student/student-log.md +++ b/erpnext/docs/user/manual/en/schools/student/student-log.md @@ -3,6 +3,6 @@ You can make a note of student activities using student log. Logs can be categorised as 'General', 'Academic', 'Medical' or 'Achievement' -Student +Student {next} diff --git a/erpnext/docs/user/manual/en/schools/student/student.md b/erpnext/docs/user/manual/en/schools/student/student.md index a86d36e8cc..2caaf066ba 100644 --- a/erpnext/docs/user/manual/en/schools/student/student.md +++ b/erpnext/docs/user/manual/en/schools/student/student.md @@ -5,6 +5,6 @@ The student doctype maintains personal details of the student. You can view everything related to a particular student on this page. Eg : Fees, Student Group, etc -Student +Student {next} From 4d2e782e42e9875429b5c55934c41dbc5d1d7b20 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jul 2017 15:21:22 +0530 Subject: [PATCH 02/12] [Fix] Error in sales invoice and POS if customer group not defined in the customer (#10148) --- .../doctype/pos_profile/pos_profile.json | 222 ++++++++++++------ .../doctype/pos_profile/pos_profile.py | 8 + .../doctype/pos_profile/test_pos_profile.js | 23 ++ .../doctype/pos_profile/test_pos_profile.py | 1 + erpnext/accounts/doctype/sales_invoice/pos.py | 20 +- erpnext/accounts/page/pos/pos.js | 2 + erpnext/accounts/party.py | 5 +- erpnext/patches.txt | 3 +- .../update_customer_group_in_POS_profile.py | 8 + 9 files changed, 221 insertions(+), 71 deletions(-) create mode 100644 erpnext/accounts/doctype/pos_profile/test_pos_profile.js create mode 100644 erpnext/patches/v8_5/update_customer_group_in_POS_profile.py diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 93aca1b361..6991da2888 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -721,38 +721,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tc_name", - "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": "Terms and Conditions", - "length": 0, - "no_copy": 0, - "oldfieldname": "tc_name", - "oldfieldtype": "Link", - "options": "Terms and Conditions", - "permlevel": 0, - "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, @@ -782,39 +750,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "territory", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Territory", - "length": 0, - "no_copy": 0, - "oldfieldname": "territory", - "oldfieldtype": "Link", - "options": "Territory", - "permlevel": 0, - "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, @@ -847,6 +782,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tc_name", + "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": "Terms and Conditions", + "length": 0, + "no_copy": 0, + "oldfieldname": "tc_name", + "oldfieldtype": "Link", + "options": "Terms and Conditions", + "permlevel": 0, + "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, @@ -910,6 +877,129 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer_details", + "fieldtype": "Section Break", + "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": "New Customer Details", + "length": 0, + "no_copy": 0, + "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, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "territory", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Territory", + "length": 0, + "no_copy": 0, + "oldfieldname": "territory", + "oldfieldtype": "Link", + "options": "Territory", + "permlevel": 0, + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "column_break_31", + "fieldtype": "Column Break", + "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, + "length": 0, + "no_copy": 0, + "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, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "customer_group", + "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": "Customer Group", + "length": 0, + "no_copy": 0, + "options": "Customer Group", + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 1, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1201,7 +1291,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-06-16 17:04:33.165676", + "modified": "2017-07-28 03:40:03.253088", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index ef497bfe29..86682d3c2a 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -14,6 +14,7 @@ class POSProfile(Document): self.check_for_duplicate() self.validate_all_link_fields() self.validate_duplicate_groups() + self.validate_customer_territory_group() def check_for_duplicate(self): res = frappe.db.sql("""select name, user from `tabPOS Profile` @@ -48,6 +49,13 @@ class POSProfile(Document): if len(customer_groups) != len(set(customer_groups)): frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group") + def validate_customer_territory_group(self): + if not self.territory: + frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field") + + if not self.customer_group: + frappe.throw(_("Customer Group is Required in POS Profile"), title="Mandatory Field") + def before_save(self): set_account_for_mode_of_payment(self) diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js new file mode 100644 index 0000000000..42e5b7f92f --- /dev/null +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: POS Profile", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially('POS Profile', [ + // insert a new POS Profile + () => frappe.tests.make([ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index 9c6a11487c..534abb65fa 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -42,6 +42,7 @@ def make_pos_profile(): "naming_series": "_T-POS Profile-", "selling_price_list": "_Test Price List", "territory": "_Test Territory", + "customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'), "warehouse": "_Test Warehouse - _TC", "write_off_account": "_Test Write Off - _TC", "write_off_cost_center": "_Test Write Off Cost Center - _TC" diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index f61931a562..3c9de12fc0 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals import frappe, json +from frappe import _ from frappe.utils import nowdate from erpnext.setup.utils import get_exchange_rate from frappe.core.doctype.communication.email import make @@ -20,6 +21,7 @@ def get_pos_data(): if pos_profile.get('name'): pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name')) + pos_profile.validate() company_data = get_company_data(doc.company) update_pos_profile_data(doc, pos_profile, company_data) @@ -378,13 +380,27 @@ def add_customer(data): customer_doc.customer_name = data.get('full_name') or data.get('customer') customer_doc.customer_pos_id = data.get('customer_pos_id') customer_doc.customer_type = 'Company' - customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') - customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory') + customer_doc.customer_group = get_customer_group(data) + customer_doc.territory = get_territory(data) customer_doc.flags.ignore_mandatory = True customer_doc.save(ignore_permissions = True) frappe.db.commit() return customer_doc.name +def get_territory(data): + if data.get('territory'): + return data.get('territory') + + return frappe.db.get_single_value('Selling Settings', + 'territory') or _('All Territories') + +def get_customer_group(data): + if data.get('customer_group'): + return data.get('customer_group') + + return frappe.db.get_single_value('Selling Settings', + 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name') + def make_contact(args,customer): if args.get('email_id') or args.get('phone'): name = frappe.db.get_value('Dynamic Link', diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index a5f9b3c286..d69a306670 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -979,6 +979,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ get_prompt_details: function() { this.prompt_details = this.customer_doc.get_values(); this.prompt_details['country'] = this.pos_profile_data.country; + this.prompt_details['territory'] = this.pos_profile_data["territory"]; + this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"]; this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value; return JSON.stringify(this.prompt_details) }, diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 005abe646d..0f8b92ffc9 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -273,6 +273,7 @@ def get_due_date(posting_date, party_type, party, company): return due_date def get_credit_days(party_type, party, company): + credit_days = 0 if party_type and party: if party_type == "Customer": credit_days_based_on, credit_days, customer_group = \ @@ -282,10 +283,10 @@ def get_credit_days(party_type, party, company): frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "supplier_type"]) if not credit_days_based_on: - if party_type == "Customer": + if party_type == "Customer" and customer_group: credit_days_based_on, credit_days = \ frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) - else: + elif party_type == "Supplier" and supplier_type: credit_days_based_on, credit_days = \ frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"]) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index fb8f02e94b..e3a2e58b27 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -423,4 +423,5 @@ erpnext.patches.v8_3.set_restrict_to_domain_for_module_def erpnext.patches.v8_1.update_expense_claim_status erpnext.patches.v8_3.update_company_total_sales erpnext.patches.v8_1.set_delivery_date_in_so_item -erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs \ No newline at end of file +erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs +erpnext.patches.v8_5.update_customer_group_in_POS_profile \ No newline at end of file diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py new file mode 100644 index 0000000000..9a5fef90c8 --- /dev/null +++ b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py @@ -0,0 +1,8 @@ +import frappe + +def execute(): + frappe.reload_doctype('POS Profile') + customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') + if customer_group: + frappe.db.sql(""" update `tabPOS Profile` + set customer_group = %s where customer_group is null """, (customer_group)) \ No newline at end of file From 8af33a513b07d5ed17a2295bac38f596f720a30e Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 28 Jul 2017 15:34:20 +0530 Subject: [PATCH 03/12] [fix] test --- erpnext/selling/doctype/sales_order/test_sales_order.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 8c0711870b..f87a659e46 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -16,7 +16,7 @@ class TestSalesOrder(unittest.TestCase): frappe.set_user("Administrator") for role in ("Stock User", "Sales User"): - set_user_permission_doctypes(doctype="Sales Order", role=role, + set_user_permission_doctypes(doctypes="Sales Order", role=role, apply_user_permissions=0, user_permission_doctypes=None) def test_make_material_request(self): @@ -257,7 +257,7 @@ class TestSalesOrder(unittest.TestCase): def test_warehouse_user(self): for role in ("Stock User", "Sales User"): - set_user_permission_doctypes(doctype="Sales Order", role=role, + set_user_permission_doctypes(doctypes="Sales Order", role=role, apply_user_permissions=1, user_permission_doctypes=["Warehouse"]) frappe.permissions.add_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com") From 8bccaed35af93c8ef51666b0b851b26c7d32912b Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Fri, 28 Jul 2017 15:43:23 +0530 Subject: [PATCH 04/12] Revert "[Fix] Error in sales invoice and POS if customer group not defined in the customer (#10148)" (#10159) This reverts commit 4d2e782e42e9875429b5c55934c41dbc5d1d7b20. --- .../doctype/pos_profile/pos_profile.json | 222 ++++++------------ .../doctype/pos_profile/pos_profile.py | 8 - .../doctype/pos_profile/test_pos_profile.js | 23 -- .../doctype/pos_profile/test_pos_profile.py | 1 - erpnext/accounts/doctype/sales_invoice/pos.py | 20 +- erpnext/accounts/page/pos/pos.js | 2 - erpnext/accounts/party.py | 5 +- erpnext/patches.txt | 3 +- .../update_customer_group_in_POS_profile.py | 8 - 9 files changed, 71 insertions(+), 221 deletions(-) delete mode 100644 erpnext/accounts/doctype/pos_profile/test_pos_profile.js delete mode 100644 erpnext/patches/v8_5/update_customer_group_in_POS_profile.py diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.json b/erpnext/accounts/doctype/pos_profile/pos_profile.json index 6991da2888..93aca1b361 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.json +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.json @@ -721,6 +721,38 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "tc_name", + "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": "Terms and Conditions", + "length": 0, + "no_copy": 0, + "oldfieldname": "tc_name", + "oldfieldtype": "Link", + "options": "Terms and Conditions", + "permlevel": 0, + "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, @@ -750,6 +782,39 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "description": "", + "fieldname": "territory", + "fieldtype": "Link", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 1, + "in_standard_filter": 0, + "label": "Territory", + "length": 0, + "no_copy": 0, + "oldfieldname": "territory", + "oldfieldtype": "Link", + "options": "Territory", + "permlevel": 0, + "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, @@ -782,38 +847,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "tc_name", - "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": "Terms and Conditions", - "length": 0, - "no_copy": 0, - "oldfieldname": "tc_name", - "oldfieldtype": "Link", - "options": "Terms and Conditions", - "permlevel": 0, - "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, @@ -877,129 +910,6 @@ "set_only_once": 0, "unique": 0 }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_details", - "fieldtype": "Section Break", - "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": "New Customer Details", - "length": 0, - "no_copy": 0, - "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, - "bold": 0, - "collapsible": 0, - "columns": 0, - "description": "", - "fieldname": "territory", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Territory", - "length": 0, - "no_copy": 0, - "oldfieldname": "territory", - "oldfieldtype": "Link", - "options": "Territory", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_31", - "fieldtype": "Column Break", - "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, - "length": 0, - "no_copy": 0, - "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, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "customer_group", - "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": "Customer Group", - "length": 0, - "no_copy": 0, - "options": "Customer Group", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 1, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, { "allow_bulk_edit": 0, "allow_on_submit": 0, @@ -1291,7 +1201,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-07-28 03:40:03.253088", + "modified": "2017-06-16 17:04:33.165676", "modified_by": "Administrator", "module": "Accounts", "name": "POS Profile", diff --git a/erpnext/accounts/doctype/pos_profile/pos_profile.py b/erpnext/accounts/doctype/pos_profile/pos_profile.py index 86682d3c2a..ef497bfe29 100644 --- a/erpnext/accounts/doctype/pos_profile/pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/pos_profile.py @@ -14,7 +14,6 @@ class POSProfile(Document): self.check_for_duplicate() self.validate_all_link_fields() self.validate_duplicate_groups() - self.validate_customer_territory_group() def check_for_duplicate(self): res = frappe.db.sql("""select name, user from `tabPOS Profile` @@ -49,13 +48,6 @@ class POSProfile(Document): if len(customer_groups) != len(set(customer_groups)): frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group") - def validate_customer_territory_group(self): - if not self.territory: - frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field") - - if not self.customer_group: - frappe.throw(_("Customer Group is Required in POS Profile"), title="Mandatory Field") - def before_save(self): set_account_for_mode_of_payment(self) diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js b/erpnext/accounts/doctype/pos_profile/test_pos_profile.js deleted file mode 100644 index 42e5b7f92f..0000000000 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.js +++ /dev/null @@ -1,23 +0,0 @@ -/* eslint-disable */ -// rename this file from _test_[name] to test_[name] to activate -// and remove above this line - -QUnit.test("test: POS Profile", function (assert) { - let done = assert.async(); - - // number of asserts - assert.expect(1); - - frappe.run_serially('POS Profile', [ - // insert a new POS Profile - () => frappe.tests.make([ - // values to be set - {key: 'value'} - ]), - () => { - assert.equal(cur_frm.doc.key, 'value'); - }, - () => done() - ]); - -}); diff --git a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py index 534abb65fa..9c6a11487c 100644 --- a/erpnext/accounts/doctype/pos_profile/test_pos_profile.py +++ b/erpnext/accounts/doctype/pos_profile/test_pos_profile.py @@ -42,7 +42,6 @@ def make_pos_profile(): "naming_series": "_T-POS Profile-", "selling_price_list": "_Test Price List", "territory": "_Test Territory", - "customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'), "warehouse": "_Test Warehouse - _TC", "write_off_account": "_Test Write Off - _TC", "write_off_cost_center": "_Test Write Off Cost Center - _TC" diff --git a/erpnext/accounts/doctype/sales_invoice/pos.py b/erpnext/accounts/doctype/sales_invoice/pos.py index 3c9de12fc0..f61931a562 100644 --- a/erpnext/accounts/doctype/sales_invoice/pos.py +++ b/erpnext/accounts/doctype/sales_invoice/pos.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe, json -from frappe import _ from frappe.utils import nowdate from erpnext.setup.utils import get_exchange_rate from frappe.core.doctype.communication.email import make @@ -21,7 +20,6 @@ def get_pos_data(): if pos_profile.get('name'): pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name')) - pos_profile.validate() company_data = get_company_data(doc.company) update_pos_profile_data(doc, pos_profile, company_data) @@ -380,27 +378,13 @@ def add_customer(data): customer_doc.customer_name = data.get('full_name') or data.get('customer') customer_doc.customer_pos_id = data.get('customer_pos_id') customer_doc.customer_type = 'Company' - customer_doc.customer_group = get_customer_group(data) - customer_doc.territory = get_territory(data) + customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') + customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory') customer_doc.flags.ignore_mandatory = True customer_doc.save(ignore_permissions = True) frappe.db.commit() return customer_doc.name -def get_territory(data): - if data.get('territory'): - return data.get('territory') - - return frappe.db.get_single_value('Selling Settings', - 'territory') or _('All Territories') - -def get_customer_group(data): - if data.get('customer_group'): - return data.get('customer_group') - - return frappe.db.get_single_value('Selling Settings', - 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name') - def make_contact(args,customer): if args.get('email_id') or args.get('phone'): name = frappe.db.get_value('Dynamic Link', diff --git a/erpnext/accounts/page/pos/pos.js b/erpnext/accounts/page/pos/pos.js index d69a306670..a5f9b3c286 100644 --- a/erpnext/accounts/page/pos/pos.js +++ b/erpnext/accounts/page/pos/pos.js @@ -979,8 +979,6 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({ get_prompt_details: function() { this.prompt_details = this.customer_doc.get_values(); this.prompt_details['country'] = this.pos_profile_data.country; - this.prompt_details['territory'] = this.pos_profile_data["territory"]; - this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"]; this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value; return JSON.stringify(this.prompt_details) }, diff --git a/erpnext/accounts/party.py b/erpnext/accounts/party.py index 0f8b92ffc9..005abe646d 100644 --- a/erpnext/accounts/party.py +++ b/erpnext/accounts/party.py @@ -273,7 +273,6 @@ def get_due_date(posting_date, party_type, party, company): return due_date def get_credit_days(party_type, party, company): - credit_days = 0 if party_type and party: if party_type == "Customer": credit_days_based_on, credit_days, customer_group = \ @@ -283,10 +282,10 @@ def get_credit_days(party_type, party, company): frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "supplier_type"]) if not credit_days_based_on: - if party_type == "Customer" and customer_group: + if party_type == "Customer": credit_days_based_on, credit_days = \ frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"]) - elif party_type == "Supplier" and supplier_type: + else: credit_days_based_on, credit_days = \ frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"]) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e3a2e58b27..fb8f02e94b 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -423,5 +423,4 @@ erpnext.patches.v8_3.set_restrict_to_domain_for_module_def erpnext.patches.v8_1.update_expense_claim_status erpnext.patches.v8_3.update_company_total_sales erpnext.patches.v8_1.set_delivery_date_in_so_item -erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs -erpnext.patches.v8_5.update_customer_group_in_POS_profile \ No newline at end of file +erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs \ No newline at end of file diff --git a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py b/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py deleted file mode 100644 index 9a5fef90c8..0000000000 --- a/erpnext/patches/v8_5/update_customer_group_in_POS_profile.py +++ /dev/null @@ -1,8 +0,0 @@ -import frappe - -def execute(): - frappe.reload_doctype('POS Profile') - customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group') - if customer_group: - frappe.db.sql(""" update `tabPOS Profile` - set customer_group = %s where customer_group is null """, (customer_group)) \ No newline at end of file From be4fd1100d265963365603e37e161193fc90d75a Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 28 Jul 2017 15:54:07 +0530 Subject: [PATCH 05/12] [fix] test --- .../stock/doctype/stock_entry/test_stock_entry.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index fdb65cda53..92de229a8c 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -32,7 +32,7 @@ class TestStockEntry(unittest.TestCase): set_perpetual_inventory(0) for role in ("Stock User", "Sales User"): - set_user_permission_doctypes(doctype="Stock Entry", role=role, + set_user_permission_doctypes(doctypes="Stock Entry", role=role, apply_user_permissions=0, user_permission_doctypes=None) def test_fifo(self): @@ -188,18 +188,18 @@ class TestStockEntry(unittest.TestCase): [["_Test Item", "_Test Warehouse - _TC", -45.0], ["_Test Item", "_Test Warehouse 1 - _TC", 45.0]]) stock_in_hand_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse) - + fixed_asset_account = get_inventory_account(mtn.company, mtn.get("items")[0].t_warehouse) - + if stock_in_hand_account == fixed_asset_account: # no gl entry as both source and target warehouse has linked to same account. self.assertFalse(frappe.db.sql("""select * from `tabGL Entry` where voucher_type='Stock Entry' and voucher_no=%s""", mtn.name)) - + else: stock_value_diff = abs(frappe.db.get_value("Stock Ledger Entry", {"voucher_type": "Stock Entry", "voucher_no": mtn.name, "warehouse": "_Test Warehouse - _TC"}, "stock_value_difference")) - + self.check_gl_entries("Stock Entry", mtn.name, sorted([ [stock_in_hand_account, 0.0, stock_value_diff], @@ -467,7 +467,7 @@ class TestStockEntry(unittest.TestCase): # permission tests def test_warehouse_user(self): for role in ("Stock User", "Sales User"): - set_user_permission_doctypes(doctype="Stock Entry", role=role, + set_user_permission_doctypes(doctypes="Stock Entry", role=role, apply_user_permissions=1, user_permission_doctypes=["Warehouse"]) frappe.defaults.add_default("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com", "User Permission") From 353af64197675e431c6fa84b0624723dcc8667b3 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jul 2017 15:55:46 +0530 Subject: [PATCH 06/12] [Fix] Unable to save asset because of float error issue (#10157) --- erpnext/accounts/doctype/asset/asset.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/asset/asset.py b/erpnext/accounts/doctype/asset/asset.py index 986beb76a3..dd1e491680 100644 --- a/erpnext/accounts/doctype/asset/asset.py +++ b/erpnext/accounts/doctype/asset/asset.py @@ -147,8 +147,9 @@ class Asset(Document): accumulated_depreciation_after_full_schedule = \ max([d.accumulated_depreciation_amount for d in self.get("schedules")]) - asset_value_after_full_schedule = (flt(self.gross_purchase_amount) - - flt(accumulated_depreciation_after_full_schedule)) + asset_value_after_full_schedule = flt(flt(self.gross_purchase_amount) - + flt(accumulated_depreciation_after_full_schedule), + self.precision('expected_value_after_useful_life')) if self.expected_value_after_useful_life < asset_value_after_full_schedule: frappe.throw(_("Expected value after useful life must be greater than or equal to {0}") From 2b420f7038de0887c485fa6638ae96b885bec562 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Fri, 28 Jul 2017 16:33:52 +0600 Subject: [PATCH 07/12] bumped to version 8.6.4 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index b0692038f8..7ee4dee416 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -4,7 +4,7 @@ import inspect import frappe from erpnext.hooks import regional_overrides -__version__ = '8.6.3' +__version__ = '8.6.4' def get_default_company(user=None): '''Get default company for user''' From 11a3d5177419c9c6b731abb423219ae9d060f7a8 Mon Sep 17 00:00:00 2001 From: Rushabh Mehta Date: Fri, 28 Jul 2017 17:10:45 +0530 Subject: [PATCH 08/12] [test] test_sales_order.py --- .../doctype/sales_order/test_sales_order.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index f87a659e46..91d51079bb 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -137,10 +137,10 @@ class TestSalesOrder(unittest.TestCase): total_projected_qty = get_total_projected_qty('_Test Item') item_doc_after_cancel = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc_after_cancel.total_projected_qty) - + def test_reserved_qty_for_over_delivery_via_sales_invoice(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - + # set over-delivery tolerance frappe.db.set_value('Item', "_Test Item", 'tolerance', 50) @@ -158,9 +158,9 @@ class TestSalesOrder(unittest.TestCase): total_projected_qty = get_total_projected_qty('_Test Item') item_doc = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc.total_projected_qty) - + self.assertEqual(get_reserved_qty(), existing_reserved_qty) - + so.load_from_db() self.assertEqual(so.get("items")[0].delivered_qty, 12) self.assertEqual(so.per_delivered, 100) @@ -170,7 +170,7 @@ class TestSalesOrder(unittest.TestCase): total_projected_qty = get_total_projected_qty('_Test Item') item_doc = frappe.get_doc('Item', '_Test Item') self.assertEqual(total_projected_qty, item_doc.total_projected_qty) - + so.load_from_db() self.assertEqual(so.get("items")[0].delivered_qty, 0) self.assertEqual(so.per_delivered, 0) @@ -178,8 +178,8 @@ class TestSalesOrder(unittest.TestCase): def test_reserved_qty_for_partial_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) - - + + existing_reserved_qty_item1 = get_reserved_qty("_Test Item") existing_reserved_qty_item2 = get_reserved_qty("_Test Item Home Desktop 100") @@ -227,7 +227,7 @@ class TestSalesOrder(unittest.TestCase): def test_reserved_qty_for_over_delivery_with_packing_list(self): make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) make_stock_entry(item="_Test Item Home Desktop 100", target="_Test Warehouse - _TC", qty=10, rate=100) - + # set over-delivery tolerance frappe.db.set_value('Item', "_Test Product Bundle Item", 'tolerance', 50) @@ -283,6 +283,7 @@ class TestSalesOrder(unittest.TestCase): frappe.set_user("test2@example.com") so.insert() + frappe.set_user("Administrator") frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 1 - _TC", "test@example.com") frappe.permissions.remove_user_permission("Warehouse", "_Test Warehouse 2 - _TC1", "test2@example.com") frappe.permissions.remove_user_permission("Company", "_Test Company 1", "test2@example.com") @@ -363,7 +364,7 @@ class TestSalesOrder(unittest.TestCase): from erpnext.buying.doctype.purchase_order.purchase_order import update_status make_stock_entry(target="_Test Warehouse - _TC", qty=10, rate=100) - + po_item = make_item("_Test Item for Drop Shipping", {"is_stock_item": 1, "delivered_by_supplier": 1, 'default_supplier': '_Test Supplier', "expense_account": "_Test Account Cost for Goods Sold - _TC", From 4c7709efbd8ea3a6567a1265cf07da68d75af00c Mon Sep 17 00:00:00 2001 From: Britlog Date: Fri, 28 Jul 2017 15:24:22 +0200 Subject: [PATCH 09/12] Portal breadcrumbs (#10095) --- erpnext/hooks.py | 14 +++++++------- erpnext/support/web_form/issues/issues.json | 6 ++++-- erpnext/templates/pages/order.html | 2 +- erpnext/templates/pages/order.py | 1 + 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 37fd8692e5..3a8569b677 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -62,49 +62,49 @@ website_route_rules = [ {"from_route": "/orders/", "to_route": "order", "defaults": { "doctype": "Sales Order", - "parents": [{"title": _("Orders"), "name": "orders"}] + "parents": [{"label": _("Orders"), "route": "orders"}] } }, {"from_route": "/invoices", "to_route": "Sales Invoice"}, {"from_route": "/invoices/", "to_route": "order", "defaults": { "doctype": "Sales Invoice", - "parents": [{"title": _("Invoices"), "name": "invoices"}] + "parents": [{"label": _("Invoices"), "route": "invoices"}] } }, {"from_route": "/supplier-quotations", "to_route": "Supplier Quotation"}, {"from_route": "/supplier-quotations/", "to_route": "order", "defaults": { "doctype": "Supplier Quotation", - "parents": [{"title": _("Supplier Quotation"), "name": "quotations"}] + "parents": [{"label": _("Supplier Quotation"), "route": "quotations"}] } }, {"from_route": "/quotations", "to_route": "Quotation"}, {"from_route": "/quotations/", "to_route": "order", "defaults": { "doctype": "Quotation", - "parents": [{"title": _("Quotations"), "name": "quotation"}] + "parents": [{"label": _("Quotations"), "route": "quotation"}] } }, {"from_route": "/shipments", "to_route": "Delivery Note"}, {"from_route": "/shipments/", "to_route": "order", "defaults": { "doctype": "Delivery Note", - "parents": [{"title": _("Shipments"), "name": "shipments"}] + "parents": [{"label": _("Shipments"), "route": "shipments"}] } }, {"from_route": "/rfq", "to_route": "Request for Quotation"}, {"from_route": "/rfq/", "to_route": "rfq", "defaults": { "doctype": "Request for Quotation", - "parents": [{"title": _("Request for Quotation"), "name": "rfq"}] + "parents": [{"label": _("Request for Quotation"), "route": "rfq"}] } }, {"from_route": "/addresses", "to_route": "Address"}, {"from_route": "/addresses/", "to_route": "addresses", "defaults": { "doctype": "Address", - "parents": [{"title": _("Addresses"), "name": "addresses"}] + "parents": [{"label": _("Addresses"), "route": "addresses"}] } }, {"from_route": "/jobs", "to_route": "Job Opening"}, diff --git a/erpnext/support/web_form/issues/issues.json b/erpnext/support/web_form/issues/issues.json index 6474799277..264b9dfbc2 100644 --- a/erpnext/support/web_form/issues/issues.json +++ b/erpnext/support/web_form/issues/issues.json @@ -7,16 +7,18 @@ "allow_multiple": 1, "allow_print": 0, "amount": 0.0, - "breadcrumbs": "[{\"title\":\"Issues\", \"name\":\"issues\"}]", + "amount_based_on_field": 0, + "breadcrumbs": "[{\"label\":_(\"Issues\"), \"route\":\"issues\"}]", "creation": "2016-06-24 15:50:33.186483", "doc_type": "Issue", "docstatus": 0, "doctype": "Web Form", "idx": 0, + "introduction_text": "", "is_standard": 1, "login_required": 1, "max_attachment_size": 0, - "modified": "2016-12-07 04:26:13.917693", + "modified": "2017-07-25 22:49:10.762704", "modified_by": "Administrator", "module": "Support", "name": "issues", diff --git a/erpnext/templates/pages/order.html b/erpnext/templates/pages/order.html index da9eb33c89..3e4eca3a98 100644 --- a/erpnext/templates/pages/order.html +++ b/erpnext/templates/pages/order.html @@ -80,7 +80,7 @@

Pay {{ doc.get_formatted("grand_total") }} + class="btn btn-primary btn-sm">{{ _("Pay") }} {{ doc.get_formatted("grand_total") }}

{% endif %} diff --git a/erpnext/templates/pages/order.py b/erpnext/templates/pages/order.py index b453c7e3e7..7551a0f9bb 100644 --- a/erpnext/templates/pages/order.py +++ b/erpnext/templates/pages/order.py @@ -18,6 +18,7 @@ def get_context(context): context.attachments = get_attachments(frappe.form_dict.doctype, frappe.form_dict.name) context.parents = frappe.form_dict.parents + context.title = frappe.form_dict.name context.payment_ref = frappe.db.get_value("Payment Request", {"reference_name": frappe.form_dict.name}, "name") From 569011fb2136ea8f142a10df4d17ba663ef8bbce Mon Sep 17 00:00:00 2001 From: Vishal Dhayagude Date: Fri, 28 Jul 2017 19:36:50 +0530 Subject: [PATCH 10/12] [UI Test] Test for Product Bundle added (#10158) --- erpnext/crm/doctype/item/test_item.js | 7 ++++ .../product_bundle/test_product_bundle.js | 36 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 3 +- 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 erpnext/selling/doctype/product_bundle/test_product_bundle.js diff --git a/erpnext/crm/doctype/item/test_item.js b/erpnext/crm/doctype/item/test_item.js index 2f50ebedc3..704e762b1c 100644 --- a/erpnext/crm/doctype/item/test_item.js +++ b/erpnext/crm/doctype/item/test_item.js @@ -65,6 +65,13 @@ QUnit.test("test: item", function (assert) { {item_group: "Products"} ] ), + () => frappe.tests.make( + "Item", [ + {item_code: "Computer"}, + {item_group: "Products"}, + {is_stock_item: 0}, + ] + ), // Create a scrap item () => frappe.tests.make( diff --git a/erpnext/selling/doctype/product_bundle/test_product_bundle.js b/erpnext/selling/doctype/product_bundle/test_product_bundle.js new file mode 100644 index 0000000000..ba5ba0dc3b --- /dev/null +++ b/erpnext/selling/doctype/product_bundle/test_product_bundle.js @@ -0,0 +1,36 @@ +QUnit.test("test sales order", function(assert) { + assert.expect(4); + let done = assert.async(); + frappe.run_serially([ + () => { + return frappe.tests.make('Product Bundle', [ + {new_item_code: 'Computer'}, + {items: [ + [ + {item_code:'CPU'}, + {qty:1} + ], + [ + {item_code:'Screen'}, + {qty:1} + ], + [ + {item_code:'Keyboard'}, + {qty:1} + ] + ]}, + ]); + }, + () => cur_frm.save(), + () => { + // get_item_details + assert.ok(cur_frm.doc.items[0].item_code=='CPU', "Item Code correct"); + assert.ok(cur_frm.doc.items[1].item_code=='Screen', "Item Code correct"); + assert.ok(cur_frm.doc.items[2].item_code=='Keyboard', "Item Code correct"); + assert.ok(cur_frm.doc.new_item_code == "Computer", "Parent Item correct"); + }, + () => frappe.timeout(0.3), + () => done() + ]); +}); + diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index b86f1eefd4..60ca47cfda 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -29,4 +29,5 @@ erpnext/schools/doctype/school_settings/test_school_settings.js erpnext/schools/doctype/student_batch_name/test_student_batch_name.js erpnext/schools/doctype/student_category/test_student_category.js erpnext/schools/doctype/room/test_room.js -erpnext/schools/doctype/instructor/test_instructor.js \ No newline at end of file +erpnext/schools/doctype/instructor/test_instructor.js +erpnext/selling/doctype/product_bundle/test_product_bundle.js \ No newline at end of file From 8990af458b815cb3a165c2125a1438956420a0d6 Mon Sep 17 00:00:00 2001 From: Utkarsh Yadav Date: Fri, 28 Jul 2017 19:37:15 +0530 Subject: [PATCH 11/12] [ui test] leave application in HR (#10151) * added test for leave application * minor changes and path added * travis fixes * minor changes --- .../test_leave_application.js | 50 +++++++++++++++++++ erpnext/tests/ui/tests.txt | 1 + 2 files changed, 51 insertions(+) create mode 100644 erpnext/hr/doctype/leave_application/test_leave_application.js diff --git a/erpnext/hr/doctype/leave_application/test_leave_application.js b/erpnext/hr/doctype/leave_application/test_leave_application.js new file mode 100644 index 0000000000..51e8ed623c --- /dev/null +++ b/erpnext/hr/doctype/leave_application/test_leave_application.js @@ -0,0 +1,50 @@ +QUnit.module('hr'); + +QUnit.test("Test: Leave application [HR]", function (assert) { + assert.expect(5); + let done = assert.async(); + let today_date = frappe.datetime.nowdate(); + let leave_date = frappe.datetime.add_days(today_date, 1); // leave for tomorrow + + frappe.run_serially([ + // test creating leave application + () => frappe.db.get_value('Employee', {'employee_name':'Test Employee 1'}, 'name'), + (employee) => { + return frappe.tests.make('Leave Application', [ + {leave_type: "Test Leave type"}, + {from_date: leave_date}, // for today + {to_date: leave_date}, + {half_day: 1}, + {employee: employee.message.name}, + {leave_approver: "Administrator"}, + {follow_via_email: 0} + ]); + }, + () => frappe.timeout(1), + // check calculated total leave days + () => assert.equal("0.5", cur_frm.doc.total_leave_days, + "leave application for half day"), + () => assert.ok(!cur_frm.doc.docstatus, + "leave application not submitted with status as open"), + () => cur_frm.set_value("status", "Approved"), // approve the application [as administrator] + () => frappe.timeout(0.5), + // save form + () => cur_frm.save(), + () => frappe.timeout(1), + () => cur_frm.savesubmit(), + () => frappe.timeout(1), + () => frappe.click_button('Yes'), + () => frappe.timeout(1), + () => assert.ok(cur_frm.doc.docstatus, + "leave application submitted after approval"), + // check auto filled posting date [today] + () => assert.equal(today_date, cur_frm.doc.posting_date, + "posting date correctly set"), + () => frappe.set_route("List", "Leave Application", "List"), + () => frappe.timeout(1), + // check approved application in list + () => assert.deepEqual(["Test Employee 1", "Approved"], [cur_list.data[0].employee_name, cur_list.data[0].status], + "leave for correct employee is approved"), + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 60ca47cfda..a8c1a7e5bb 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -23,6 +23,7 @@ erpnext/hr/doctype/attendance/test_attendance.js erpnext/hr/doctype/leave_type/test_leave_type.js erpnext/hr/doctype/leave_control_panel/test_leave_control_panel.js erpnext/hr/doctype/leave_allocation/test_leave_allocation.js +erpnext/hr/doctype/leave_application/test_leave_application.js erpnext/schools/doctype/academic_year/test_academic_year.js erpnext/schools/doctype/academic_term/test_academic_term.js erpnext/schools/doctype/school_settings/test_school_settings.js From 482331b98767d1f0e86b029e0ce24d423b4f37b8 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Fri, 28 Jul 2017 20:58:39 +0530 Subject: [PATCH 12/12] [fix] Default Warehouse not obeying form value (#10153) --- erpnext/stock/doctype/item/item.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/item/item.py b/erpnext/stock/doctype/item/item.py index 14e1dcce09..5dc97f623b 100644 --- a/erpnext/stock/doctype/item/item.py +++ b/erpnext/stock/doctype/item/item.py @@ -132,7 +132,8 @@ class Item(WebsiteGenerator): from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry # default warehouse, or Stores - default_warehouse = (frappe.db.get_single_value('Stock Settings', 'default_warehouse') + default_warehouse = (self.default_warehouse + or frappe.db.get_single_value('Stock Settings', 'default_warehouse') or frappe.db.get_value('Warehouse', {'warehouse_name': _('Stores')})) if default_warehouse: