From bc9006ff3058cf64f6856613b6bea338c0df76e4 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Mon, 18 Sep 2017 13:16:04 +0530 Subject: [PATCH 1/9] Delete GST related doctypes and reports if account is from outside India (#10808) --- erpnext/patches.txt | 3 ++- erpnext/patches/v8_1/setup_gst_india.py | 18 +++++++++++------- ..._gst_doctypes_for_outside_india_accounts.py | 13 +++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 5bfd34e869..74bd37a39c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -436,4 +436,5 @@ erpnext.patches.v8_7.add_more_gst_fields erpnext.patches.v8_7.fix_purchase_receipt_status erpnext.patches.v8_6.rename_bom_update_tool erpnext.patches.v8_9.set_print_zero_amount_taxes -erpnext.patches.v8_9.set_default_customer_group \ No newline at end of file +erpnext.patches.v8_9.set_default_customer_group +erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts \ No newline at end of file diff --git a/erpnext/patches/v8_1/setup_gst_india.py b/erpnext/patches/v8_1/setup_gst_india.py index 566069369c..f329916ed5 100644 --- a/erpnext/patches/v8_1/setup_gst_india.py +++ b/erpnext/patches/v8_1/setup_gst_india.py @@ -2,21 +2,25 @@ import frappe from frappe.email import sendmail_to_system_managers def execute(): - frappe.reload_doc('regional', 'doctype', 'gst_settings') - frappe.reload_doc('regional', 'doctype', 'gst_hsn_code') frappe.reload_doc('stock', 'doctype', 'item') frappe.reload_doc("stock", "doctype", "customs_tariff_number") + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + return + + frappe.reload_doc('regional', 'doctype', 'gst_settings') + frappe.reload_doc('regional', 'doctype', 'gst_hsn_code') + for report_name in ('GST Sales Register', 'GST Purchase Register', 'GST Itemised Sales Register', 'GST Itemised Purchase Register'): frappe.reload_doc('regional', 'report', frappe.scrub(report_name)) - if frappe.db.get_single_value('System Settings', 'country')=='India': - from erpnext.regional.india.setup import setup - delete_custom_field_tax_id_if_exists() - setup(patch=True) - send_gst_update_email() + from erpnext.regional.india.setup import setup + delete_custom_field_tax_id_if_exists() + setup(patch=True) + send_gst_update_email() def delete_custom_field_tax_id_if_exists(): for field in frappe.db.sql_list("""select name from `tabCustom Field` where fieldname='tax_id' diff --git a/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py b/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py new file mode 100644 index 0000000000..2b4ac58a67 --- /dev/null +++ b/erpnext/patches/v8_9/delete_gst_doctypes_for_outside_india_accounts.py @@ -0,0 +1,13 @@ +import frappe + +def execute(): + company = frappe.get_all('Company', filters = {'country': 'India'}) + if not company: + if frappe.db.exists("DocType", "GST Settings"): + frappe.delete_doc("DocType", "GST Settings") + frappe.delete_doc("DocType", "GST HSN Code") + + for report_name in ('GST Sales Register', 'GST Purchase Register', + 'GST Itemised Sales Register', 'GST Itemised Purchase Register'): + + frappe.delete_doc('Report', report_name) \ No newline at end of file From 2222f10720c48c7aabcd31500bb33c4f4be36799 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Sep 2017 15:05:18 +0530 Subject: [PATCH 2/9] [patch] remove employee name salary structure (#10817) * [patch] remove employee name salary structure * Update remove_employee_from_salary_structure_parent.py --- erpnext/patches.txt | 3 ++- .../v8_9/remove_employee_from_salary_structure_parent.py | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 74bd37a39c..1fea30875c 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -437,4 +437,5 @@ erpnext.patches.v8_7.fix_purchase_receipt_status erpnext.patches.v8_6.rename_bom_update_tool erpnext.patches.v8_9.set_print_zero_amount_taxes erpnext.patches.v8_9.set_default_customer_group -erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts \ No newline at end of file +erpnext.patches.v8_9.remove_employee_from_salary_structure_parent +erpnext.patches.v8_9.delete_gst_doctypes_for_outside_india_accounts diff --git a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py new file mode 100644 index 0000000000..53911a15cf --- /dev/null +++ b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py @@ -0,0 +1,5 @@ +import frappe + +def execute(): + if 'employee' in frappe.db.get_table_columns("Salary Structure"): + frappe.db.sql("alter table `tabEmployee` drop column employee") From 3f15bf9828bef21a86f4bf9db1dd4f35f8ed6a2f Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Sep 2017 15:27:24 +0530 Subject: [PATCH 3/9] [fix] query fix for match conditions (#10810) --- .../item_wise_purchase_register.py | 35 ++++++++------ .../item_wise_sales_register.py | 46 ++++++++++++------- 2 files changed, 51 insertions(+), 30 deletions(-) diff --git a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py index b21027ee35..710099ee10 100644 --- a/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py +++ b/erpnext/accounts/report/item_wise_purchase_register/item_wise_purchase_register.py @@ -91,10 +91,10 @@ def get_conditions(filters): conditions = "" for opts in (("company", " and company=%(company)s"), - ("supplier", " and pi.supplier = %(supplier)s"), - ("item_code", " and pi_item.item_code = %(item_code)s"), - ("from_date", " and pi.posting_date>=%(from_date)s"), - ("to_date", " and pi.posting_date<=%(to_date)s"), + ("supplier", " and `tabPurchase Invoice`.supplier = %(supplier)s"), + ("item_code", " and `tabPurchase Invoice Item`.item_code = %(item_code)s"), + ("from_date", " and `tabPurchase Invoice`.posting_date>=%(from_date)s"), + ("to_date", " and `tabPurchase Invoice`.posting_date<=%(to_date)s"), ("mode_of_payment", " and ifnull(mode_of_payment, '') = %(mode_of_payment)s")): if filters.get(opts[0]): conditions += opts[1] @@ -104,20 +104,29 @@ def get_conditions(filters): def get_items(filters, additional_query_columns): conditions = get_conditions(filters) match_conditions = frappe.build_match_conditions("Purchase Invoice") + + if match_conditions: + match_conditions = " and {0} ".format(match_conditions) + if additional_query_columns: additional_query_columns = ', ' + ', '.join(additional_query_columns) return frappe.db.sql(""" select - pi_item.name, pi_item.parent, pi.posting_date, pi.credit_to, pi.company, - pi.supplier, pi.remarks, pi.base_net_total, pi_item.item_code, pi_item.item_name, - pi_item.item_group, pi_item.project, pi_item.purchase_order, pi_item.purchase_receipt, - pi_item.po_detail, pi_item.expense_account, pi_item.stock_qty, pi_item.stock_uom, - pi_item.base_net_rate, pi_item.base_net_amount, - pi.supplier_name, pi.mode_of_payment {0} - from `tabPurchase Invoice` pi, `tabPurchase Invoice Item` pi_item - where pi.name = pi_item.parent and pi.docstatus = 1 %s %s - order by pi.posting_date desc, pi_item.item_code desc + `tabPurchase Invoice Item`.`name`, `tabPurchase Invoice Item`.`parent`, + `tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company, + `tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, `tabPurchase Invoice Item`.`item_code`, + `tabPurchase Invoice Item`.`item_name`, `tabPurchase Invoice Item`.`item_group`, + `tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`, + `tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`, + `tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`, + `tabPurchase Invoice Item`.`stock_uom`, `tabPurchase Invoice Item`.`base_net_rate`, + `tabPurchase Invoice Item`.`base_net_amount`, + `tabPurchase Invoice`.supplier_name, `tabPurchase Invoice`.mode_of_payment {0} + from `tabPurchase Invoice`, `tabPurchase Invoice Item` + where `tabPurchase Invoice`.name = `tabPurchase Invoice Item`.`parent` and + `tabPurchase Invoice`.docstatus = 1 %s %s + order by `tabPurchase Invoice`.posting_date desc, `tabPurchase Invoice Item`.item_code desc """.format(additional_query_columns) % (conditions, match_conditions), filters, as_dict=1) def get_aii_accounts(): diff --git a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py index eb50022688..9892e03f3f 100644 --- a/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py +++ b/erpnext/accounts/report/item_wise_sales_register/item_wise_sales_register.py @@ -93,37 +93,49 @@ def get_conditions(filters): conditions = "" for opts in (("company", " and company=%(company)s"), - ("customer", " and si.customer = %(customer)s"), - ("item_code", " and si_item.item_code = %(item_code)s"), - ("from_date", " and si.posting_date>=%(from_date)s"), - ("to_date", " and si.posting_date<=%(to_date)s")): + ("customer", " and `tabSales Invoice`.customer = %(customer)s"), + ("item_code", " and `tabSales Invoice Item`.item_code = %(item_code)s"), + ("from_date", " and `tabSales Invoice`.posting_date>=%(from_date)s"), + ("to_date", " and `tabSales Invoice`.posting_date<=%(to_date)s")): if filters.get(opts[0]): conditions += opts[1] if filters.get("mode_of_payment"): conditions += """ and exists(select name from `tabSales Invoice Payment` - where parent=si.name - and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)""" + where parent=si.name + and ifnull(`tabSales Invoice Payment`.mode_of_payment, '') = %(mode_of_payment)s)""" return conditions def get_items(filters, additional_query_columns): + conditions = get_conditions(filters) + match_conditions = frappe.build_match_conditions("Sales Invoice") + + if match_conditions: + match_conditions = " and {0} ".format(match_conditions) + if additional_query_columns: additional_query_columns = ', ' + ', '.join(additional_query_columns) - conditions = get_conditions(filters) return frappe.db.sql(""" select - si_item.name, si_item.parent, si.posting_date, si.debit_to, si.project, - si.customer, si.remarks, si.territory, si.company, si.base_net_total, - si_item.item_code, si_item.item_name, si_item.item_group, si_item.sales_order, - si_item.delivery_note, si_item.income_account, si_item.cost_center, - si_item.stock_qty, si_item.stock_uom, si_item.base_net_rate, si_item.base_net_amount, - si.customer_name, si.customer_group, si_item.so_detail, si.update_stock {0} - from `tabSales Invoice` si, `tabSales Invoice Item` si_item - where si.name = si_item.parent and si.docstatus = 1 %s - order by si.posting_date desc, si_item.item_code desc - """.format(additional_query_columns or '') % conditions, filters, as_dict=1) + `tabSales Invoice Item`.name, `tabSales Invoice Item`.parent, + `tabSales Invoice`.posting_date, `tabSales Invoice`.debit_to, + `tabSales Invoice`.project, `tabSales Invoice`.customer, `tabSales Invoice`.remarks, + `tabSales Invoice`.territory, `tabSales Invoice`.company, `tabSales Invoice`.base_net_total, + `tabSales Invoice Item`.item_code, `tabSales Invoice Item`.item_name, + `tabSales Invoice Item`.item_group, `tabSales Invoice Item`.sales_order, + `tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.income_account, + `tabSales Invoice Item`.cost_center, `tabSales Invoice Item`.stock_qty, + `tabSales Invoice Item`.stock_uom, `tabSales Invoice Item`.base_net_rate, + `tabSales Invoice Item`.base_net_amount, `tabSales Invoice`.customer_name, + `tabSales Invoice`.customer_group, `tabSales Invoice Item`.so_detail, + `tabSales Invoice`.update_stock {0} + from `tabSales Invoice`, `tabSales Invoice Item` + where `tabSales Invoice`.name = `tabSales Invoice Item`.parent + and `tabSales Invoice`.docstatus = 1 %s %s + order by `tabSales Invoice`.posting_date desc, `tabSales Invoice Item`.item_code desc + """.format(additional_query_columns or '') % (conditions, match_conditions), filters, as_dict=1) def get_delivery_notes_against_sales_order(item_list): so_dn_map = frappe._dict() From d7e1869a70812ca2621f4f2d47bc2ed91adee749 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Sep 2017 15:43:35 +0530 Subject: [PATCH 4/9] [fix] if item code not exists then exclude item in validate_selling_price (#10800) --- erpnext/controllers/selling_controller.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/controllers/selling_controller.py b/erpnext/controllers/selling_controller.py index d8b4202704..d881f18b33 100644 --- a/erpnext/controllers/selling_controller.py +++ b/erpnext/controllers/selling_controller.py @@ -179,6 +179,9 @@ class SellingController(StockController): return for it in self.get("items"): + if not it.item_code: + continue + last_purchase_rate, is_stock_item = frappe.db.get_value("Item", it.item_code, ["last_purchase_rate", "is_stock_item"]) last_purchase_rate_in_sales_uom = last_purchase_rate / (it.conversion_factor or 1) if flt(it.base_rate) < flt(last_purchase_rate_in_sales_uom): From 590d401e5ff1065361dd54cd10821431ccae833a Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Sep 2017 15:49:19 +0530 Subject: [PATCH 5/9] [fix] if bom specified on purchase order item then don't pull default bom in purchase receipt (#10793) * [fix] if bom specified on purchase order item then don't pull default bom in purchase receipt * Update bom.js * Update stock_entry.py --- erpnext/buying/doctype/purchase_order/purchase_order.py | 1 + erpnext/manufacturing/doctype/bom/bom.js | 2 +- erpnext/stock/doctype/stock_entry/stock_entry.py | 3 ++- erpnext/stock/get_item_details.py | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 26c8c61167..56f3059f2e 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -295,6 +295,7 @@ def make_purchase_receipt(source_name, target_doc=None): "field_map": { "name": "purchase_order_item", "parent": "purchase_order", + "bom": "bom" }, "postprocess": update_item, "condition": lambda doc: abs(doc.received_qty) < abs(doc.qty) and doc.delivered_by_supplier!=1 diff --git a/erpnext/manufacturing/doctype/bom/bom.js b/erpnext/manufacturing/doctype/bom/bom.js index c58c89cd5d..94a2113081 100644 --- a/erpnext/manufacturing/doctype/bom/bom.js +++ b/erpnext/manufacturing/doctype/bom/bom.js @@ -19,7 +19,7 @@ frappe.ui.form.on("BOM", { frm.set_query("source_warehouse", "items", function() { return { filters: { - 'company': frm.doc.company, + 'company': frm.doc.company } }; }); diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index fbadbc54de..fc45f13602 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -631,7 +631,8 @@ class StockEntry(StockController): fetch_exploded = self.use_multi_level_bom) for item in item_dict.values(): - item.from_warehouse = self.from_warehouse or item.default_warehouse + # if source warehouse presents in BOM set from_warehouse as bom source_warehouse + item.from_warehouse = self.from_warehouse or item.source_warehouse or item.default_warehouse return item_dict def get_bom_scrap_material(self, qty): diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 80ef70805a..2a22854677 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -90,7 +90,7 @@ def get_item_details(args): item.lead_time_days) if args.get("is_subcontracted") == "Yes": - out.bom = get_default_bom(args.item_code) + out.bom = args.get('bom') or get_default_bom(args.item_code) get_gross_profit(out) From 9c334c34a6c0b8d3b6b61a29fb4631959331088d Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 18 Sep 2017 16:17:13 +0530 Subject: [PATCH 6/9] [fix]remove employee field from tab salary structure --- .../v8_9/remove_employee_from_salary_structure_parent.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py index 53911a15cf..4ab9cf3ec8 100644 --- a/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py +++ b/erpnext/patches/v8_9/remove_employee_from_salary_structure_parent.py @@ -2,4 +2,4 @@ import frappe def execute(): if 'employee' in frappe.db.get_table_columns("Salary Structure"): - frappe.db.sql("alter table `tabEmployee` drop column employee") + frappe.db.sql("alter table `tabSalary Structure` drop column employee") From bd0beb6c02071ccad3ac04f34cbb3f2cfa93e9ed Mon Sep 17 00:00:00 2001 From: Utkarsh Goswami Date: Mon, 18 Sep 2017 16:44:11 +0530 Subject: [PATCH 7/9] [fix] unknown column in production order (#10828) --- .../v7_1/repost_stock_for_deleted_bins_for_merging_items.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py index 321b0399a6..39b7f6ce91 100644 --- a/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py +++ b/erpnext/patches/v7_1/repost_stock_for_deleted_bins_for_merging_items.py @@ -30,7 +30,7 @@ def execute(): .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) item_warehouses_with_transactions += list(frappe.db.sql(""" - select distinct pr_item.item_code, pr.source_warehouse + select distinct pr_item.item_code, pr_item.source_warehouse from `tabProduction Order` pr, `tabProduction Order Item` pr_item where pr_item.parent and pr.name and pr.docstatus=1 and pr_item.item_code in ({0})""" .format(', '.join(['%s']*len(modified_items))), tuple(modified_items))) From f6d738b3c5ab1a7b4d05b5d2298798f570968242 Mon Sep 17 00:00:00 2001 From: tundebabzy Date: Mon, 18 Sep 2017 12:40:09 +0100 Subject: [PATCH 8/9] Delivery note to billing issue (#10726) (#10766) * allow invoices to be made from sales returns * Update queries.py --- erpnext/controllers/queries.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/erpnext/controllers/queries.py b/erpnext/controllers/queries.py index 11c0790976..7ada8ccc2f 100644 --- a/erpnext/controllers/queries.py +++ b/erpnext/controllers/queries.py @@ -227,21 +227,30 @@ def get_project_name(doctype, txt, searchfield, start, page_len, filters): "_txt": txt.replace('%', '') }) + def get_delivery_notes_to_be_billed(doctype, txt, searchfield, start, page_len, filters, as_dict): return frappe.db.sql(""" select `tabDelivery Note`.name, `tabDelivery Note`.customer, `tabDelivery Note`.posting_date from `tabDelivery Note` where `tabDelivery Note`.`%(key)s` like %(txt)s and - `tabDelivery Note`.docstatus = 1 and `tabDelivery Note`.is_return = 0 + `tabDelivery Note`.docstatus = 1 and status not in ("Stopped", "Closed") %(fcond)s - and (`tabDelivery Note`.per_billed < 100 or `tabDelivery Note`.grand_total = 0) + and ( + (`tabDelivery Note`.is_return = 0 and `tabDelivery Note`.per_billed < 100) + or `tabDelivery Note`.grand_total = 0 + or ( + `tabDelivery Note`.is_return = 1 + and return_against in (select name from `tabDelivery Note` where per_billed < 100) + ) + ) %(mcond)s order by `tabDelivery Note`.`%(key)s` asc """ % { "key": searchfield, "fcond": get_filters_cond(doctype, filters, []), "mcond": get_match_cond(doctype), "txt": "%(txt)s" - }, { "txt": ("%%%s%%" % txt) }, as_dict=as_dict) + }, {"txt": ("%%%s%%" % txt)}, as_dict=as_dict) + def get_batch_no(doctype, txt, searchfield, start, page_len, filters): cond = "" From 703e83712506aaf26d7e323aafb8b2c8e2e72a01 Mon Sep 17 00:00:00 2001 From: Nabin Hait Date: Tue, 19 Sep 2017 12:35:39 +0600 Subject: [PATCH 9/9] bumped to version 8.11.4 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 65ccec47fd..61381b2703 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.11.3' +__version__ = '8.11.4' def get_default_company(user=None): '''Get default company for user'''