From 4d2e782e42e9875429b5c55934c41dbc5d1d7b20 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jul 2017 15:21:22 +0530 Subject: [PATCH 01/13] [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 8bccaed35af93c8ef51666b0b851b26c7d32912b Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Fri, 28 Jul 2017 15:43:23 +0530 Subject: [PATCH 02/13] 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 353af64197675e431c6fa84b0624723dcc8667b3 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jul 2017 15:55:46 +0530 Subject: [PATCH 03/13] [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 04/13] 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 e2176b852e3a0c5a344b151508fe0995ab99098f Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Fri, 28 Jul 2017 20:52:02 +0530 Subject: [PATCH 05/13] [Fix] Error in sales invoice and POS if customer group not defined in the customer (#10160) --- .../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 41c954b8b34561548c2fc5f41f514518dd162cdd Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Fri, 28 Jul 2017 16:35:15 +0100 Subject: [PATCH 06/13] Set billing hours to 0 in timesheet #9535 (#10139) * `update_billing_hours` to use flt not cint * if not billable, reset billable hours * if not billable, reset time rates * test --- .../doctype/timesheet/test_timesheet.py | 16 +++++++++++--- .../projects/doctype/timesheet/timesheet.js | 21 ++++++++++++++++--- .../projects/doctype/timesheet/timesheet.py | 16 +++++++++++--- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/erpnext/projects/doctype/timesheet/test_timesheet.py b/erpnext/projects/doctype/timesheet/test_timesheet.py index 1db0610e89..955a2b0fe3 100644 --- a/erpnext/projects/doctype/timesheet/test_timesheet.py +++ b/erpnext/projects/doctype/timesheet/test_timesheet.py @@ -14,8 +14,8 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal class TestTimesheet(unittest.TestCase): def test_timesheet_billing_amount(self): - salary_structure = make_salary_structure("_T-Employee-0001") - timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1) + make_salary_structure("_T-Employee-0001") + timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1) self.assertEquals(timesheet.total_hours, 2) self.assertEquals(timesheet.total_billable_hours, 2) @@ -23,6 +23,16 @@ class TestTimesheet(unittest.TestCase): self.assertEquals(timesheet.time_logs[0].billing_amount, 100) self.assertEquals(timesheet.total_billable_amount, 100) + def test_timesheet_billing_amount_not_billable(self): + make_salary_structure("_T-Employee-0001") + timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=0) + + self.assertEquals(timesheet.total_hours, 2) + self.assertEquals(timesheet.total_billable_hours, 0) + self.assertEquals(timesheet.time_logs[0].billing_rate, 0) + self.assertEquals(timesheet.time_logs[0].billing_amount, 0) + self.assertEquals(timesheet.total_billable_amount, 0) + def test_salary_slip_from_timesheet(self): salary_structure = make_salary_structure("_T-Employee-0001") timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1) @@ -43,7 +53,7 @@ class TestTimesheet(unittest.TestCase): self.assertEquals(timesheet.status, 'Submitted') def test_sales_invoice_from_timesheet(self): - timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable = 1) + timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1) sales_invoice = make_sales_invoice(timesheet.name) sales_invoice.customer = "_Test Customer" sales_invoice.due_date = nowdate() diff --git a/erpnext/projects/doctype/timesheet/timesheet.js b/erpnext/projects/doctype/timesheet/timesheet.js index 441ab1afb0..9b330e7811 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.js +++ b/erpnext/projects/doctype/timesheet/timesheet.js @@ -105,7 +105,9 @@ frappe.ui.form.on("Timesheet Detail", { }, billable: function(frm, cdt, cdn) { - calculate_billing_costing_amount(frm, cdt, cdn) + update_billing_hours(frm, cdt, cdn); + update_time_rates(frm, cdt, cdn); + calculate_billing_costing_amount(frm, cdt, cdn); }, activity_type: function(frm, cdt, cdn) { @@ -148,8 +150,21 @@ var calculate_end_time = function(frm, cdt, cdn) { } } +var update_billing_hours = function(frm, cdt, cdn){ + var child = locals[cdt][cdn]; + if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0); +} + +var update_time_rates = function(frm, cdt, cdn){ + var child = locals[cdt][cdn]; + if(!child.billable){ + frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0); + frappe.model.set_value(cdt, cdn, 'costing_rate', 0.0); + } +} + var calculate_billing_costing_amount = function(frm, cdt, cdn){ - var child = locals[cdt][cdn] + var child = locals[cdt][cdn]; var billing_amount = 0.0; var costing_amount = 0.0; @@ -160,7 +175,7 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){ frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount); frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount); - calculate_time_and_amount(frm) + calculate_time_and_amount(frm); } var calculate_time_and_amount = function(frm) { diff --git a/erpnext/projects/doctype/timesheet/timesheet.py b/erpnext/projects/doctype/timesheet/timesheet.py index 6416176190..bb3d9020a7 100644 --- a/erpnext/projects/doctype/timesheet/timesheet.py +++ b/erpnext/projects/doctype/timesheet/timesheet.py @@ -46,6 +46,7 @@ class Timesheet(Document): for d in self.get("time_logs"): self.update_billing_hours(d) + self.update_time_rates(d) self.total_hours += flt(d.hours) if d.billable: @@ -61,8 +62,11 @@ class Timesheet(Document): self.per_billed = (self.total_billed_amount * 100) / self.total_billable_amount def update_billing_hours(self, args): - if cint(args.billing_hours) == 0: - args.billing_hours = args.hours + if args.billable: + if flt(args.billing_hours) == 0.0: + args.billing_hours = args.hours + else: + args.billing_hours = 0 def set_status(self): self.status = { @@ -263,13 +267,19 @@ class Timesheet(Document): for data in self.time_logs: if data.activity_type and data.billable: rate = get_activity_cost(self.employee, data.activity_type) - hours = data.billing_hours or 0 + hours = data.billing_hours or 0 if rate: data.billing_rate = flt(rate.get('billing_rate')) if flt(data.billing_rate) == 0 else data.billing_rate data.costing_rate = flt(rate.get('costing_rate')) if flt(data.costing_rate) == 0 else data.costing_rate data.billing_amount = data.billing_rate * hours data.costing_amount = data.costing_rate * hours + def update_time_rates(self, ts_detail): + if not ts_detail.billable: + ts_detail.billing_rate = 0.0 + ts_detail.costing_rate = 0.0 + + @frappe.whitelist() def get_projectwise_timesheet_data(project, parent=None): cond = '' From 33977827c41a356da3164a9edb2756ae556afbe1 Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Fri, 28 Jul 2017 17:45:12 +0530 Subject: [PATCH 07/13] [Fix] Timesheet Company Issue --- .../doctype/production_order/production_order.py | 5 +++-- .../production_order/test_production_order.py | 3 ++- erpnext/patches.txt | 3 ++- erpnext/patches/v8_6/__init__.py | 0 .../v8_6/update_timesheet_company_from_PO.py | 15 +++++++++++++++ 5 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 erpnext/patches/v8_6/__init__.py create mode 100644 erpnext/patches/v8_6/update_timesheet_company_from_PO.py diff --git a/erpnext/manufacturing/doctype/production_order/production_order.py b/erpnext/manufacturing/doctype/production_order/production_order.py index 95336137cb..022e9f3d18 100644 --- a/erpnext/manufacturing/doctype/production_order/production_order.py +++ b/erpnext/manufacturing/doctype/production_order/production_order.py @@ -273,7 +273,7 @@ class ProductionOrder(Document): timesheets = [] plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30 - timesheet = make_timesheet(self.name) + timesheet = make_timesheet(self.name, self.company) timesheet.set('time_logs', []) for i, d in enumerate(self.operations): @@ -575,10 +575,11 @@ def get_events(start, end, filters=None): return data @frappe.whitelist() -def make_timesheet(production_order): +def make_timesheet(production_order, company): timesheet = frappe.new_doc("Timesheet") timesheet.employee = "" timesheet.production_order = production_order + timesheet.company = company return timesheet @frappe.whitelist() diff --git a/erpnext/manufacturing/doctype/production_order/test_production_order.py b/erpnext/manufacturing/doctype/production_order/test_production_order.py index 18aa51d874..1d555f7c0c 100644 --- a/erpnext/manufacturing/doctype/production_order/test_production_order.py +++ b/erpnext/manufacturing/doctype/production_order/test_production_order.py @@ -87,6 +87,7 @@ class TestProductionOrder(unittest.TestCase): name = frappe.db.get_value('Timesheet', {'production_order': prod_order.name}, 'name') time_sheet_doc = frappe.get_doc('Timesheet', name) + self.assertEqual(prod_order.company, time_sheet_doc.company) time_sheet_doc.submit() @@ -107,7 +108,7 @@ class TestProductionOrder(unittest.TestCase): self.assertEqual(prod_order.operations[0].actual_operation_time, 60) self.assertEqual(prod_order.operations[0].actual_operating_cost, 100) - time_sheet_doc1 = make_timesheet(prod_order.name) + time_sheet_doc1 = make_timesheet(prod_order.name, prod_order.company) self.assertEqual(len(time_sheet_doc1.get('time_logs')), 0) time_sheet_doc.cancel() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index e3a2e58b27..6e2284f493 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -424,4 +424,5 @@ 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.update_customer_group_in_POS_profile +erpnext.patches.v8_6.update_timesheet_company_from_PO \ No newline at end of file diff --git a/erpnext/patches/v8_6/__init__.py b/erpnext/patches/v8_6/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/erpnext/patches/v8_6/update_timesheet_company_from_PO.py b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py new file mode 100644 index 0000000000..5bab961c04 --- /dev/null +++ b/erpnext/patches/v8_6/update_timesheet_company_from_PO.py @@ -0,0 +1,15 @@ +# Copyright (c) 2017, Frappe and Contributors +# License: GNU General Public License v3. See license.txt + +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doctype('Timesheet') + company = frappe.get_all('Company') + + #Check more than one company exists + if len(company) > 1: + frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company = + (select company from `tabProduction Order` where name = `tabTimesheet`.production_order) + where production_order is not null and production_order !=''""") \ No newline at end of file From 495ef67caaf30a3286ea81a54c5087877eaf4ea7 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 31 Jul 2017 11:25:51 +0530 Subject: [PATCH 08/13] Added delivery date in SO parent form. Fixes #10104 (#10155) * Added delivery date in SO parent form. Fixes #10104 * UI tests for sales order delivery date --- .../tests/test_recurring_document.py | 3 +- erpnext/demo/user/sales.py | 3 +- erpnext/patches.txt | 2 +- .../v8_1/set_delivery_date_in_so_item.py | 10 +++- .../doctype/quotation/test_quotation.py | 6 +- .../doctype/sales_order/sales_order.js | 20 ++++++- .../doctype/sales_order/sales_order.json | 12 ++-- .../doctype/sales_order/sales_order.py | 27 +++++---- .../doctype/sales_order/sales_order_list.js | 6 +- .../doctype/sales_order/test_sales_order.js | 59 +++++++++++++++++++ .../doctype/sales_order/test_sales_order.py | 3 +- .../sales_order_item/sales_order_item.json | 4 +- erpnext/tests/ui/tests.txt | 3 +- 13 files changed, 119 insertions(+), 39 deletions(-) create mode 100644 erpnext/selling/doctype/sales_order/test_sales_order.js diff --git a/erpnext/controllers/tests/test_recurring_document.py b/erpnext/controllers/tests/test_recurring_document.py index e218fa6c9b..d47c5c7701 100644 --- a/erpnext/controllers/tests/test_recurring_document.py +++ b/erpnext/controllers/tests/test_recurring_document.py @@ -27,8 +27,7 @@ def test_recurring_document(obj, test_records): base_doc.set(date_field, today) if base_doc.doctype == "Sales Order": - for d in base_doc.get("items"): - d.set("delivery_date", add_days(today, 15)) + base_doc.set("delivery_date", add_days(today, 15)) # monthly doc1 = frappe.copy_doc(base_doc) diff --git a/erpnext/demo/user/sales.py b/erpnext/demo/user/sales.py index 666e201716..ddd36efc36 100644 --- a/erpnext/demo/user/sales.py +++ b/erpnext/demo/user/sales.py @@ -118,8 +118,7 @@ def make_sales_order(): from erpnext.selling.doctype.quotation.quotation import make_sales_order so = frappe.get_doc(make_sales_order(q)) so.transaction_date = frappe.flags.current_date - for d in so.get("items"): - d.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10) + so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10) so.insert() frappe.db.commit() so.submit() diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 6e2284f493..2923d6dc9d 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -422,7 +422,7 @@ erpnext.patches.v8_1.add_indexes_in_transaction_doctypes 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_1.set_delivery_date_in_so_item #2017-07-28 erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs erpnext.patches.v8_5.update_customer_group_in_POS_profile erpnext.patches.v8_6.update_timesheet_company_from_PO \ No newline at end of file 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 6840424774..963b82a4de 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 @@ -4,10 +4,18 @@ def execute(): frappe.reload_doctype("Sales Order") frappe.reload_doctype("Sales Order Item") - frappe.db.sql("""update `tabSales Order` set final_delivery_date = delivery_date where docstatus=1""") + if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"): + 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') + and order_type = 'Sales'""") frappe.db.sql(""" update `tabSales Order` so, `tabSales Order Item` so_item 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') """) \ No newline at end of file diff --git a/erpnext/selling/doctype/quotation/test_quotation.py b/erpnext/selling/doctype/quotation/test_quotation.py index 7fb40748f0..fa69df418a 100644 --- a/erpnext/selling/doctype/quotation/test_quotation.py +++ b/erpnext/selling/doctype/quotation/test_quotation.py @@ -27,8 +27,7 @@ class TestQuotation(unittest.TestCase): self.assertEquals(sales_order.get("items")[0].prevdoc_docname, quotation.name) self.assertEquals(sales_order.customer, "_Test Customer") - for d in sales_order.get("items"): - d.delivery_date = "2014-01-01" + sales_order.delivery_date = "2014-01-01" sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = "2013-05-12" sales_order.insert() @@ -54,8 +53,7 @@ class TestQuotation(unittest.TestCase): sales_order = make_sales_order(quotation.name) sales_order.naming_series = "_T-Quotation-" sales_order.transaction_date = "2016-01-01" - for d in sales_order.get("items"): - d.delivery_date = "2016-01-02" + sales_order.delivery_date = "2016-01-02" sales_order.insert() diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 2e01a08359..80dc4f23ec 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -34,11 +34,20 @@ frappe.ui.form.on("Sales Order", { erpnext.queries.setup_warehouse_query(frm); }, + + delivery_date: function(frm) { + $.each(frm.doc.items || [], function(i, d) { + if(!d.delivery_date) d.delivery_date = frm.doc.delivery_date; + }); + refresh_field("items"); + } }); frappe.ui.form.on("Sales Order Item", { delivery_date: function(frm, cdt, cdn) { - erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date"); + if(!frm.doc.delivery_date) { + erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date"); + } } }); @@ -416,8 +425,13 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend( items_add: function(doc, cdt, cdn) { var row = frappe.get_doc(cdt, cdn); - this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]); + if(doc.delivery_date) { + row.delivery_date = doc.delivery_date; + refresh_field("delivery_date", cdn, "items"); + } else { + this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]); + } } }); -$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm})); +$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm})); \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order/sales_order.json b/erpnext/selling/doctype/sales_order/sales_order.json index 596bf2f9dd..bf2ccf78f8 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.json +++ b/erpnext/selling/doctype/sales_order/sales_order.json @@ -367,23 +367,23 @@ "bold": 0, "collapsible": 0, "columns": 0, - "fieldname": "final_delivery_date", + "fieldname": "delivery_date", "fieldtype": "Date", - "hidden": 1, + "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": "Final Delivery Date", + "label": "Delivery Date", "length": 0, "no_copy": 1, "permlevel": 0, "precision": "", - "print_hide": 1, + "print_hide": 0, "print_hide_if_no_value": 0, - "read_only": 1, + "read_only": 0, "remember_last_selected_value": 0, "report_hide": 0, "reqd": 0, @@ -3659,7 +3659,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2017-07-25 13:45:02.965353", + "modified": "2017-07-28 14:03:33.373347", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order", diff --git a/erpnext/selling/doctype/sales_order/sales_order.py b/erpnext/selling/doctype/sales_order/sales_order.py index fd80dc8662..c6dbd7043b 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.py +++ b/erpnext/selling/doctype/sales_order/sales_order.py @@ -101,20 +101,20 @@ class SalesOrder(SellingController): super(SalesOrder, self).validate_order_type() def validate_delivery_date(self): - self.final_delivery_date = None if self.order_type == 'Sales': - for d in self.get("items"): - if not d.delivery_date: - frappe.throw(_("Row #{0}: Please enter Delivery Date against item {1}") - .format(d.idx, d.item_code)) + if not self.delivery_date: + self.delivery_date = max([d.delivery_date for d in self.get("items")]) - if getdate(self.transaction_date) > getdate(d.delivery_date): - frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"), - indicator='orange', title=_('Warning')) - - if not self.final_delivery_date or \ - (d.delivery_date and getdate(d.delivery_date) > getdate(self.final_delivery_date)): - self.final_delivery_date = d.delivery_date + if self.delivery_date: + for d in self.get("items"): + if not d.delivery_date: + d.delivery_date = self.delivery_date + + if getdate(self.transaction_date) > getdate(d.delivery_date): + frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"), + indicator='orange', title=_('Warning')) + else: + frappe.throw(_("Please enter Delivery Date")) self.validate_sales_mntc_quotation() @@ -347,6 +347,9 @@ class SalesOrder(SellingController): def on_recurring(self, reference_doc): mcount = month_map[reference_doc.recurring_type] + self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount, + cint(reference_doc.repeat_on_day_of_month))) + for d in self.get("items"): reference_delivery_date = frappe.db.get_value("Sales Order Item", {"parent": reference_doc.name, "item_code": d.item_code, "idx": d.idx}, "delivery_date") diff --git a/erpnext/selling/doctype/sales_order/sales_order_list.js b/erpnext/selling/doctype/sales_order/sales_order_list.js index 0ee9cf34f0..9751935183 100644 --- a/erpnext/selling/doctype/sales_order/sales_order_list.js +++ b/erpnext/selling/doctype/sales_order/sales_order_list.js @@ -1,14 +1,14 @@ frappe.listview_settings['Sales Order'] = { - add_fields: ["base_grand_total", "customer_name", "currency", "final_delivery_date", + add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date", "per_delivered", "per_billed", "status", "order_type", "name"], get_indicator: function(doc) { if(doc.status==="Closed"){ return [__("Closed"), "green", "status,=,Closed"]; } else if (doc.order_type !== "Maintenance" - && flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.final_delivery_date) < 0) { + && flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) { // to bill & overdue - return [__("Overdue"), "red", "per_delivered,<,100|final_delivery_date,<,Today|status,!=,Closed"]; + return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"]; } else if (doc.order_type !== "Maintenance" && flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") { diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.js b/erpnext/selling/doctype/sales_order/test_sales_order.js new file mode 100644 index 0000000000..87f0e965c2 --- /dev/null +++ b/erpnext/selling/doctype/sales_order/test_sales_order.js @@ -0,0 +1,59 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Sales Order", function (assert) { + assert.expect(2); + let done = assert.async(); + let delivery_date = frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1); + + frappe.run_serially([ + // insert a new Sales Order + () => { + return frappe.tests.make('Sales Order', [ + {customer: "Test Customer 1"}, + {delivery_date: delivery_date}, + {order_type: 'Sales'}, + {items: [ + [ + {"item_code": "Test Product 1"}, + {"qty": 5}, + {'rate': 100}, + ]] + } + ]) + }, + () => { + assert.ok(cur_frm.doc.items[0].delivery_date == delivery_date); + }, + () => frappe.timeout(1), + // make SO without delivery date in parent, + // parent delivery date should be set based on final delivery date entered in item + () => { + return frappe.tests.make('Sales Order', [ + {customer: "Test Customer 1"}, + {order_type: 'Sales'}, + {items: [ + [ + {"item_code": "Test Product 1"}, + {"qty": 5}, + {'rate': 100}, + {'delivery_date': delivery_date} + ], + [ + {"item_code": "Test Product 2"}, + {"qty": 5}, + {'rate': 100}, + {'delivery_date': frappe.datetime.add_days(delivery_date, 5)} + ]] + } + ]) + }, + () => cur_frm.save(), + () => frappe.timeout(1), + () => { + assert.ok(cur_frm.doc.delivery_date == frappe.datetime.add_days(delivery_date, 5)); + }, + () => done() + ]); +}); \ No newline at end of file diff --git a/erpnext/selling/doctype/sales_order/test_sales_order.py b/erpnext/selling/doctype/sales_order/test_sales_order.py index 8c0711870b..ce8c18af41 100644 --- a/erpnext/selling/doctype/sales_order/test_sales_order.py +++ b/erpnext/selling/doctype/sales_order/test_sales_order.py @@ -532,8 +532,7 @@ def make_sales_order(**args): "rate": args.rate or 100 }) - for d in so.get("items"): - d.delivery_date = add_days(so.transaction_date, 10) + so.delivery_date = add_days(so.transaction_date, 10) if not args.do_not_save: so.insert() diff --git a/erpnext/selling/doctype/sales_order_item/sales_order_item.json b/erpnext/selling/doctype/sales_order_item/sales_order_item.json index f14f50dedd..47bc1b6077 100644 --- a/erpnext/selling/doctype/sales_order_item/sales_order_item.json +++ b/erpnext/selling/doctype/sales_order_item/sales_order_item.json @@ -220,7 +220,7 @@ "no_copy": 1, "permlevel": 0, "precision": "", - "print_hide": 0, + "print_hide": 1, "print_hide_if_no_value": 0, "read_only": 0, "remember_last_selected_value": 0, @@ -1963,7 +1963,7 @@ "istable": 1, "max_attachments": 0, "menu_index": 0, - "modified": "2017-07-18 18:26:36.870342", + "modified": "2017-07-28 14:04:04.289428", "modified_by": "Administrator", "module": "Selling", "name": "Sales Order Item", diff --git a/erpnext/tests/ui/tests.txt b/erpnext/tests/ui/tests.txt index 42233dc800..40b1c590e0 100644 --- a/erpnext/tests/ui/tests.txt +++ b/erpnext/tests/ui/tests.txt @@ -2,4 +2,5 @@ erpnext/tests/ui/make_fixtures.js #long erpnext/accounts/doctype/account/test_account.js erpnext/crm/doctype/lead/test_lead.js erpnext/crm/doctype/opportunity/test_opportunity.js -erpnext/selling/doctype/quotation/test_quotation.js \ No newline at end of file +erpnext/selling/doctype/quotation/test_quotation.js +erpnext/selling/doctype/sales_order/test_sales_order.js \ No newline at end of file From 892cd615f899eed216a71f6691fba7ba38d39e32 Mon Sep 17 00:00:00 2001 From: mbauskar Date: Mon, 31 Jul 2017 12:51:35 +0600 Subject: [PATCH 09/13] bumped to version 8.6.5 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 7ee4dee416..833ddff223 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.4' +__version__ = '8.6.5' def get_default_company(user=None): '''Get default company for user''' From 9b2b42dfc14bb131ed8929f28a87de0f54353a39 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 1 Aug 2017 11:10:09 +0530 Subject: [PATCH 10/13] Minor fix in bom_stock_qty patch --- erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py index 9e95eb0c23..1f937bb8af 100644 --- a/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py +++ b/erpnext/patches/v8_0/update_stock_qty_value_in_bom_item.py @@ -10,4 +10,5 @@ def execute(): frappe.reload_doc('manufacturing', 'doctype', 'bom_scrap_item') frappe.db.sql("update `tabBOM Item` set stock_qty = qty, uom = stock_uom, conversion_factor = 1") frappe.db.sql("update `tabBOM Explosion Item` set stock_qty = qty") - frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file + if "qty" in frappe.db.get_table_columns("BOM Scrap Item"): + frappe.db.sql("update `tabBOM Scrap Item` set stock_qty = qty") \ No newline at end of file From ec9430dae7027ad299aa33ec690f707613777880 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Wed, 2 Aug 2017 18:16:13 +0530 Subject: [PATCH 11/13] [Fix] Default selling settings not fetched on customer quick entry form (#10243) --- erpnext/startup/boot.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/erpnext/startup/boot.py b/erpnext/startup/boot.py index ceeceaa3c9..6b503b3eec 100644 --- a/erpnext/startup/boot.py +++ b/erpnext/startup/boot.py @@ -16,8 +16,10 @@ def boot_session(bootinfo): update_page_info(bootinfo) load_country_and_currency(bootinfo) - bootinfo.sysdefaults.territory = get_root_of('Territory') - bootinfo.sysdefaults.customer_group = get_root_of('Customer Group') + bootinfo.sysdefaults.territory = frappe.db.get_single_value('Selling Settings', + 'territory') or get_root_of('Territory') + bootinfo.sysdefaults.customer_group = frappe.db.get_single_value('Selling Settings', + 'customer_group') or get_root_of('Customer Group') bootinfo.notification_settings = frappe.get_doc("Notification Control", "Notification Control") From ce436b7698fc395df8ddc6fd45d012fd9beaeb6e Mon Sep 17 00:00:00 2001 From: Makarand Bauskar Date: Wed, 2 Aug 2017 18:16:53 +0530 Subject: [PATCH 12/13] [minor] set description to '' if template description is not available (#10244) --- erpnext/controllers/item_variant.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/item_variant.py b/erpnext/controllers/item_variant.py index 226b17f7a2..967c1339f1 100644 --- a/erpnext/controllers/item_variant.py +++ b/erpnext/controllers/item_variant.py @@ -169,7 +169,6 @@ def create_variant(item, args): return variant - def copy_attributes_to_variant(item, variant): from frappe.model import no_value_fields @@ -189,6 +188,8 @@ def copy_attributes_to_variant(item, variant): variant.set(field.fieldname, item.get(field.fieldname)) variant.variant_of = item.name variant.has_variants = 0 + if not variant.description: + variant.description = '' if item.variant_based_on=='Item Attribute': if variant.attributes: From 4d49a7f6d12927912498440adb365e3db353c68b Mon Sep 17 00:00:00 2001 From: mbauskar Date: Wed, 2 Aug 2017 18:48:14 +0600 Subject: [PATCH 13/13] bumped to version 8.6.6 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 833ddff223..618d106390 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.5' +__version__ = '8.6.6' def get_default_company(user=None): '''Get default company for user'''