From 226083893392546b2cb4133cdce078fe62077817 Mon Sep 17 00:00:00 2001 From: Faris Ansari Date: Wed, 7 Aug 2019 17:21:22 +0530 Subject: [PATCH 01/17] fix(Item Template): Fallback description string Fixes #18572 --- erpnext/templates/generators/item/item_details.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/templates/generators/item/item_details.html b/erpnext/templates/generators/item/item_details.html index 8e560333ae..4cbecb0215 100644 --- a/erpnext/templates/generators/item/item_details.html +++ b/erpnext/templates/generators/item/item_details.html @@ -9,9 +9,9 @@

-{% if frappe.utils.strip_html(doc.web_long_description) %} +{% if frappe.utils.strip_html(doc.web_long_description or '') %} {{ doc.web_long_description | safe }} -{% elif frappe.utils.strip_html(doc.description) %} +{% elif frappe.utils.strip_html(doc.description or '') %} {{ doc.description | safe }} {% else %} {{ _("No description given") }} From 9839a9afb0f4c38e1a008b263e0d8212de6b6fab Mon Sep 17 00:00:00 2001 From: marination Date: Fri, 9 Aug 2019 15:54:18 +0530 Subject: [PATCH 02/17] fix: Fixed error message in Payment Entry for outstanding invoices not found via filters --- erpnext/accounts/doctype/payment_entry/payment_entry.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/payment_entry/payment_entry.py b/erpnext/accounts/doctype/payment_entry/payment_entry.py index da6b167880..401d1806f2 100644 --- a/erpnext/accounts/doctype/payment_entry/payment_entry.py +++ b/erpnext/accounts/doctype/payment_entry/payment_entry.py @@ -624,7 +624,7 @@ def get_outstanding_reference_documents(args): data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed if not data: - frappe.msgprint(_("No outstanding invoices found for the {0} {1}.") + frappe.msgprint(_("No outstanding invoices found for the {0} {1} which qualify the filters you have specified") .format(args.get("party_type").lower(), args.get("party"))) return data From dabcb6b5314886433663d720218ac221c7d85b18 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 10:58:16 +0530 Subject: [PATCH 03/17] fix: GSTR 3B report fixes --- .../doctype/gstr_3b_report/gstr_3b_report.js | 8 +- .../gstr_3b_report/gstr_3b_report.json | 304 ++++-------------- .../doctype/gstr_3b_report/gstr_3b_report.py | 48 +-- 3 files changed, 90 insertions(+), 270 deletions(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js index 0d6cef0792..a1cea8f609 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.js @@ -2,7 +2,7 @@ // For license information, please see license.txt frappe.ui.form.on('GSTR 3B Report', { - refresh : function(frm){ + refresh : function(frm) { if(!frm.is_new()) { frm.set_intro(__("Please save the report again to rebuild or update")); frm.add_custom_button(__('Download JSON'), function() { @@ -39,9 +39,13 @@ frappe.ui.form.on('GSTR 3B Report', { }); }); } + + let current_year = new Date().getFullYear(); + let options = [current_year, current_year-1, current_year-2]; + frm.set_df_property('year', 'options', options); }, - setup: function(frm){ + setup: function(frm) { frm.set_query('company_address', function(doc) { if(!doc.company) { frappe.throw(__('Please set Company')); diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json index 7b0462fd4b..548d40b974 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.json @@ -1,259 +1,73 @@ { - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "format:GSTR3B-{month}-{year}-{company_address}", - "beta": 0, - "creation": "2019-02-04 11:35:55.964639", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "", - "editable_grid": 1, - "engine": "InnoDB", + "autoname": "format:GSTR3B-{month}-{year}-{company_address}", + "creation": "2019-02-04 11:35:55.964639", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "company_address", + "year", + "month", + "json_output", + "missing_field_invoices" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company", - "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": "Company", - "length": 0, - "no_copy": 0, - "options": "Company", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "company_address", - "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": "Company Address", - "length": 0, - "no_copy": 0, - "options": "Address", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "company_address", + "fieldtype": "Link", + "label": "Company Address", + "options": "Address" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "year", - "fieldtype": "Data", - "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": "Year", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "year", + "fieldtype": "Select", + "label": "Year" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "month", - "fieldtype": "Select", - "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": "Month", - "length": 0, - "no_copy": 0, - "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "month", + "fieldtype": "Select", + "label": "Month", + "options": "January\nFebruary\nMarch\nApril\nMay\nJune\nJuly\nAugust\nSeptember\nOctober\nNovember\nDecember" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "json_output", - "fieldtype": "Code", - "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": "JSON Output", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "json_output", + "fieldtype": "Code", + "label": "JSON Output" + }, { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "missing_field_invoices", - "fieldtype": "Small Text", - "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": "Invoices with no Place Of Supply", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "fieldname": "missing_field_invoices", + "fieldtype": "Small Text", + "label": "Invoices with no Place Of Supply", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-03-04 10:04:44.767655", - "modified_by": "Administrator", - "module": "Regional", - "name": "GSTR 3B Report", - "name_case": "", - "owner": "Administrator", + ], + "modified": "2019-08-10 22:30:26.727038", + "modified_by": "Administrator", + "module": "Regional", + "name": "GSTR 3B Report", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 } \ No newline at end of file diff --git a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py index aad267e90a..79dace7925 100644 --- a/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/gstr_3b_report.py @@ -329,28 +329,29 @@ class GSTR3BReport(Document): d.gst_category, [] ) - if state_number != d.place_of_supply.split("-")[0]: - inter_state_supply_details[d.gst_category].append({ - "pos": d.place_of_supply, - "txval": flt(d.total, 2), - "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) - }) - else: - osup_det = self.report_dict["sup_details"]["osup_det"] - osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) - osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) - osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + if d.place_of_supply: + if state_number != d.place_of_supply.split("-")[0]: + inter_state_supply_details[d.gst_category].append({ + "pos": d.place_of_supply.split("-")[0], + "txval": flt(d.total, 2), + "iamt": flt(inter_state_supply_tax_mapping.get(d.place_of_supply), 2) + }) + else: + osup_det = self.report_dict["sup_details"]["osup_det"] + osup_det["txval"] = flt(osup_det["txval"] + d.total, 2) + osup_det["camt"] = flt(osup_det["camt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) + osup_det["samt"] = flt(osup_det["samt"] + inter_state_supply_tax_mapping.get(d.place_of_supply)/2, 2) return inter_state_supply_details def get_inward_nil_exempt(self, state): - inward_nil_exempt = frappe.db.sql(""" select a.gst_state, sum(i.base_amount) as base_amount, - i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i, `tabAddress` a - where p.docstatus = 1 and p.name = i.parent and p.supplier_address = a.name + inward_nil_exempt = frappe.db.sql(""" select p.place_of_supply, sum(i.base_amount) as base_amount, + i.is_nil_exempt, i.is_non_gst from `tabPurchase Invoice` p , `tabPurchase Invoice Item` i + where p.docstatus = 1 and p.name = i.parent and i.is_nil_exempt = 1 or i.is_non_gst = 1 and month(p.posting_date) = %s and year(p.posting_date) = %s and p.company = %s and p.company_gstin = %s - group by a.gst_state """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) + group by p.place_of_supply """, (self.month_no, self.year, self.company, self.gst_details.get("gstin")), as_dict=1) inward_nil_exempt_details = { "gst": { @@ -364,14 +365,15 @@ class GSTR3BReport(Document): } for d in inward_nil_exempt: - if d.is_nil_exempt == 1 and state == d.gst_state: - inward_nil_exempt_details["gst"]["intra"] += d.base_amount - elif d.is_nil_exempt == 1 and state != d.gst_state: - inward_nil_exempt_details["gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state == d.gst_state: - inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount - elif d.is_non_gst == 1 and state != d.gst_state: - inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + if d.place_of_supply: + if d.is_nil_exempt == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["intra"] += d.base_amount + elif d.is_nil_exempt == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["gst"]["inter"] += d.base_amount + elif d.is_non_gst == 1 and state == d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["intra"] += d.base_amount + elif d.is_non_gst == 1 and state != d.place_of_supply.split("-")[1]: + inward_nil_exempt_details["non_gst"]["inter"] += d.base_amount return inward_nil_exempt_details From b87c5d83de06a4f3b4c55bba11e047abc68d910b Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 12:40:45 +0530 Subject: [PATCH 04/17] fix: Test Cases --- erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index de150f466e..fa33541e60 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -176,6 +176,9 @@ def create_purchase_invoices(): do_not_save=1 ) + pi1.place_of_supply = "29-Karnataka" + pi1.save() + pi1.submit() def make_suppliers(): From db017438851cf0b73abf23477f93bc75b8dc00b2 Mon Sep 17 00:00:00 2001 From: deepeshgarg007 Date: Sun, 11 Aug 2019 15:47:35 +0530 Subject: [PATCH 05/17] fix: Test Case --- erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py index fa33541e60..fef73d9a0a 100644 --- a/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py +++ b/erpnext/regional/doctype/gstr_3b_report/test_gstr_3b_report.py @@ -176,7 +176,7 @@ def create_purchase_invoices(): do_not_save=1 ) - pi1.place_of_supply = "29-Karnataka" + pi1.shipping_address = "_Test Supplier GST-1-Billing" pi1.save() pi1.submit() @@ -221,6 +221,7 @@ def make_suppliers(): "link_name": "_Test Registered Supplier" }) + address.is_shipping_address = 1 address.save() if not frappe.db.exists('Address', '_Test Supplier GST-2-Billing'): From a0b9b3cef5fe786977f00107872f6618ea799939 Mon Sep 17 00:00:00 2001 From: sahil28297 <37302950+sahil28297@users.noreply.github.com> Date: Mon, 12 Aug 2019 11:49:14 +0530 Subject: [PATCH 06/17] fix(patch): force reload child docs (#18671) --- .../v12_0/update_pricing_rule_fields.py | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/erpnext/patches/v12_0/update_pricing_rule_fields.py b/erpnext/patches/v12_0/update_pricing_rule_fields.py index 8f8349e9b5..985613a973 100644 --- a/erpnext/patches/v12_0/update_pricing_rule_fields.py +++ b/erpnext/patches/v12_0/update_pricing_rule_fields.py @@ -5,67 +5,67 @@ from __future__ import unicode_literals import frappe parentfield = { - 'item_code': 'items', - 'item_group': 'item_groups', - 'brand': 'brands' + 'item_code': 'items', + 'item_group': 'item_groups', + 'brand': 'brands' } def execute(): - if not frappe.get_all('Pricing Rule', limit=1): - return + if not frappe.get_all('Pricing Rule', limit=1): + return - frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') - doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', - 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', - 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} + frappe.reload_doc('accounts', 'doctype', 'pricing_rule_detail') + doctypes = {'Supplier Quotation': 'buying', 'Purchase Order': 'buying', 'Purchase Invoice': 'accounts', + 'Purchase Receipt': 'stock', 'Quotation': 'selling', 'Sales Order': 'selling', + 'Sales Invoice': 'accounts', 'Delivery Note': 'stock'} - for doctype, module in doctypes.items(): - frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) + for doctype, module in doctypes.items(): + frappe.reload_doc(module, 'doctype', frappe.scrub(doctype)) - child_doc = frappe.scrub(doctype) + '_item' - frappe.reload_doc(module, 'doctype', child_doc) + child_doc = frappe.scrub(doctype) + '_item' + frappe.reload_doc(module, 'doctype', child_doc, force=True) - child_doctype = doctype + ' Item' + child_doctype = doctype + ' Item' - frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule - WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' - """.format(child_doctype= child_doctype)) + frappe.db.sql(""" UPDATE `tab{child_doctype}` SET pricing_rules = pricing_rule + WHERE docstatus < 2 and pricing_rule is not null and pricing_rule != '' + """.format(child_doctype= child_doctype)) - data = frappe.db.sql(""" SELECT pricing_rule, name, parent, - parenttype, creation, modified, docstatus, modified_by, owner, name - FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null - and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) + data = frappe.db.sql(""" SELECT pricing_rule, name, parent, + parenttype, creation, modified, docstatus, modified_by, owner, name + FROM `tab{child_doc}` where docstatus < 2 and pricing_rule is not null + and pricing_rule != ''""".format(child_doc=child_doctype), as_dict=1) - values = [] - for d in data: - values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, - d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.pricing_rule, d.name, d.parent, 'pricing_rules', d.parenttype, + d.creation, d.modified, d.docstatus, d.modified_by, d.owner, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, - `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) - VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) + if values: + frappe.db.sql(""" INSERT INTO + `tabPricing Rule Detail` (`pricing_rule`, `child_docname`, `parent`, `parentfield`, `parenttype`, + `creation`, `modified`, `docstatus`, `modified_by`, `owner`, `name`) + VALUES {values} """.format(values=', '.join(['%s'] * len(values))), tuple(values)) - frappe.reload_doc('accounts', 'doctype', 'pricing_rule') + frappe.reload_doc('accounts', 'doctype', 'pricing_rule') - for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', - 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): - frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) + for doctype, apply_on in {'Pricing Rule Item Code': 'Item Code', + 'Pricing Rule Item Group': 'Item Group', 'Pricing Rule Brand': 'Brand'}.items(): + frappe.reload_doc('accounts', 'doctype', frappe.scrub(doctype)) - field = frappe.scrub(apply_on) - data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", - "owner", "modified_by"], filters= {'apply_on': apply_on}) + field = frappe.scrub(apply_on) + data = frappe.get_all('Pricing Rule', fields=[field, "name", "creation", "modified", + "owner", "modified_by"], filters= {'apply_on': apply_on}) - values = [] - for d in data: - values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', - d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) + values = [] + for d in data: + values.append((d.get(field), d.name, parentfield.get(field), 'Pricing Rule', + d.creation, d.modified, d.owner, d.modified_by, frappe.generate_hash("", 10))) - if values: - frappe.db.sql(""" INSERT INTO - `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, - owner, modified_by, name) - VALUES {values} """.format(doctype=doctype, - field=field, values=', '.join(['%s'] * len(values))), tuple(values)) \ No newline at end of file + if values: + frappe.db.sql(""" INSERT INTO + `tab{doctype}` ({field}, parent, parentfield, parenttype, creation, modified, + owner, modified_by, name) + VALUES {values} """.format(doctype=doctype, + field=field, values=', '.join(['%s'] * len(values))), tuple(values)) From 83705af0b336ec7b87a7f32854e3c4a6aacd5690 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Mon, 12 Aug 2019 11:51:27 +0530 Subject: [PATCH 07/17] fix: Filters for portal quotation list (#18689) * fix: Filters for portal quotation list * fix: Remove unwanted import --- .../controllers/website_list_for_contact.py | 59 ++++++++----------- erpnext/templates/pages/rfq.py | 7 +-- 2 files changed, 29 insertions(+), 37 deletions(-) diff --git a/erpnext/controllers/website_list_for_contact.py b/erpnext/controllers/website_list_for_contact.py index 187eaed107..0738fd506f 100644 --- a/erpnext/controllers/website_list_for_contact.py +++ b/erpnext/controllers/website_list_for_contact.py @@ -21,42 +21,45 @@ def get_list_context(context=None): def get_transaction_list(doctype, txt=None, filters=None, limit_start=0, limit_page_length=20, order_by="modified"): user = frappe.session.user - key = None + ignore_permissions = False if not filters: filters = [] if doctype == 'Supplier Quotation': - filters.append((doctype, "docstatus", "<", 2)) + filters.append((doctype, 'docstatus', '<', 2)) else: - filters.append((doctype, "docstatus", "=", 1)) + filters.append((doctype, 'docstatus', '=', 1)) - if (user != "Guest" and is_website_user()) or doctype == 'Request for Quotation': + if (user != 'Guest' and is_website_user()) or doctype == 'Request for Quotation': parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype # find party for this contact customers, suppliers = get_customers_suppliers(parties_doctype, user) - if not customers and not suppliers: return [] - - key, parties = get_party_details(customers, suppliers) - - if doctype == 'Request for Quotation': - return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) - - filters.append((doctype, key, "in", parties)) - - if key: - return post_process(doctype, get_list_for_transactions(doctype, txt, - filters=filters, fields="name",limit_start=limit_start, - limit_page_length=limit_page_length,ignore_permissions=True, - order_by="modified desc")) + if customers: + if doctype == 'Quotation': + filters.append(('quotation_to', '=', 'Customer')) + filters.append(('party_name', 'in', customers)) + else: + filters.append(('customer', 'in', customers)) + elif suppliers: + filters.append(('supplier', 'in', suppliers)) else: return [] - return post_process(doctype, get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, - fields="name", order_by="modified desc")) + if doctype == 'Request for Quotation': + parties = customers or suppliers + return rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length) + + # Since customers and supplier do not have direct access to internal doctypes + ignore_permissions = True + + transactions = get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length, + fields='name', ignore_permissions=ignore_permissions, order_by='modified desc') + + return post_process(doctype, transactions) def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_length=20, - ignore_permissions=False,fields=None, order_by=None): + ignore_permissions=False, fields=None, order_by=None): """ Get List of transactions like Invoices, Orders """ from frappe.www.list import get_list meta = frappe.get_meta(doctype) @@ -83,16 +86,6 @@ def get_list_for_transactions(doctype, txt, filters, limit_start, limit_page_len return data -def get_party_details(customers, suppliers): - if customers: - key, parties = "customer", customers - elif suppliers: - key, parties = "supplier", suppliers - else: - key, parties = "customer", [] - - return key, parties - def rfq_transaction_list(parties_doctype, doctype, parties, limit_start, limit_page_length): data = frappe.db.sql("""select distinct parent as name, supplier from `tab{doctype}` where supplier = '{supplier}' and docstatus=1 order by modified desc limit {start}, {len}""". @@ -159,7 +152,7 @@ def has_website_permission(doc, ptype, user, verbose=False): doctype = doc.doctype customers, suppliers = get_customers_suppliers(doctype, user) if customers: - return frappe.db.exists(doctype, filters=get_customer_filter(doc, customers)) + return frappe.db.exists(doctype, get_customer_filter(doc, customers)) elif suppliers: fieldname = 'suppliers' if doctype == 'Request for Quotation' else 'supplier' return frappe.db.exists(doctype, filters={ @@ -175,7 +168,7 @@ def get_customer_filter(doc, customers): filters.name = doc.name filters[get_customer_field_name(doctype)] = ['in', customers] if doctype == 'Quotation': - filters.party_type = 'Customer' + filters.quotation_to = 'Customer' return filters def get_customer_field_name(doctype): diff --git a/erpnext/templates/pages/rfq.py b/erpnext/templates/pages/rfq.py index 62ec60966b..67679a1a7d 100644 --- a/erpnext/templates/pages/rfq.py +++ b/erpnext/templates/pages/rfq.py @@ -5,8 +5,7 @@ from __future__ import unicode_literals import frappe from frappe import _ from frappe.utils import formatdate -from erpnext.controllers.website_list_for_contact import (get_customers_suppliers, - get_party_details) +from erpnext.controllers.website_list_for_contact import get_customers_suppliers def get_context(context): context.no_cache = 1 @@ -23,8 +22,8 @@ def get_supplier(): doctype = frappe.form_dict.doctype parties_doctype = 'Request for Quotation Supplier' if doctype == 'Request for Quotation' else doctype customers, suppliers = get_customers_suppliers(parties_doctype, frappe.session.user) - key, parties = get_party_details(customers, suppliers) - return parties[0] if key == 'supplier' else '' + + return suppliers[0] if suppliers else '' def check_supplier_has_docname_access(supplier): status = True From 677c522f01b9aa583de64cd5bc78162550fdec87 Mon Sep 17 00:00:00 2001 From: Andrew McLeod Date: Mon, 12 Aug 2019 07:36:23 +0100 Subject: [PATCH 08/17] fix: Python3 urllib use in item_group.py (now uses six.moves) (#18642) --- erpnext/setup/doctype/item_group/item_group.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index cab21162c7..33ab992568 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import frappe -import urllib import copy from frappe.utils import nowdate, cint, cstr from frappe.utils.nestedset import NestedSet @@ -12,6 +11,7 @@ from frappe.website.render import clear_cache from frappe.website.doctype.website_slideshow.website_slideshow import get_slideshow from erpnext.shopping_cart.product_info import set_product_info_for_website from erpnext.utilities.product import get_qty_in_stock +from six.moves.urllib.parse import quote class ItemGroup(NestedSet, WebsiteGenerator): nsm_parent_field = 'parent_item_group' @@ -165,7 +165,7 @@ def get_item_for_list_in_html(context): # add missing absolute link in files # user may forget it during upload if (context.get("website_image") or "").startswith("files/"): - context["website_image"] = "/" + urllib.quote(context["website_image"]) + context["website_image"] = "/" + quote(context["website_image"]) context["show_availability_status"] = cint(frappe.db.get_single_value('Products Settings', 'show_availability_status')) @@ -218,4 +218,4 @@ def get_item_group_defaults(item, company): row.pop("name") return row - return frappe._dict() \ No newline at end of file + return frappe._dict() From 19199baf29024233ded5138336c1b0c1622af1d1 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 12 Aug 2019 12:17:28 +0530 Subject: [PATCH 09/17] fix: miscellaneous fixes (#18615) --- erpnext/stock/doctype/item/item.json | 1 - erpnext/stock/doctype/purchase_receipt/purchase_receipt.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/item/item.json b/erpnext/stock/doctype/item/item.json index a142bb9035..383fb61f51 100644 --- a/erpnext/stock/doctype/item/item.json +++ b/erpnext/stock/doctype/item/item.json @@ -468,7 +468,6 @@ }, { "default": "0", - "depends_on": "has_batch_no", "fieldname": "retain_sample", "fieldtype": "Check", "label": "Retain Sample" diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js index 7da648aad9..8266055d69 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.js @@ -190,7 +190,7 @@ erpnext.stock.PurchaseReceiptController = erpnext.buying.BuyingController.extend frappe.set_route("Form", doc.doctype, doc.name); } else { - frappe.msgprint(__("Retention Stock Entry already created or Sample Quantity not provided")); + frappe.msgprint(__("Purchase Receipt doesn't have any Item for which Retain Sample is enabled.")); } } }); From cfce53103b9c206afdb1fd5d5cfa231f57961bd1 Mon Sep 17 00:00:00 2001 From: DeeMysterio Date: Mon, 12 Aug 2019 13:03:55 +0530 Subject: [PATCH 10/17] fix(delivery note): change the text invoice to sales invoice on make button (#18666) --- erpnext/stock/doctype/delivery_note/delivery_note.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/stock/doctype/delivery_note/delivery_note.js b/erpnext/stock/doctype/delivery_note/delivery_note.js index 569a03a8f1..a88bb2ad1e 100644 --- a/erpnext/stock/doctype/delivery_note/delivery_note.js +++ b/erpnext/stock/doctype/delivery_note/delivery_note.js @@ -197,7 +197,7 @@ erpnext.stock.DeliveryNoteController = erpnext.selling.SellingController.extend( }); if(!from_sales_invoice) { - this.frm.add_custom_button(__('Invoice'), function() { me.make_sales_invoice() }, + this.frm.add_custom_button(__('Sales Invoice'), function() { me.make_sales_invoice() }, __('Create')); } } From f841afd48dd7d1f4bfeb7db53d209c7f51071f5b Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 13 Aug 2019 15:04:18 +0550 Subject: [PATCH 11/17] bumped to version 12.0.6 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index 0a735a1da1..e1c3d78d3f 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.5' +__version__ = '12.0.6' def get_default_company(user=None): '''Get default company for user''' From e14a00b887beb062c45e72b310ccb3347f3f036f Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Tue, 13 Aug 2019 17:26:56 +0530 Subject: [PATCH 12/17] fix: v12 patches sequence (#18609) --- erpnext/patches.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/patches.txt b/erpnext/patches.txt index 33d4f55ae0..b6ea542554 100644 --- a/erpnext/patches.txt +++ b/erpnext/patches.txt @@ -596,6 +596,7 @@ erpnext.patches.v12_0.rename_pricing_rule_child_doctypes erpnext.patches.v12_0.move_target_distribution_from_parent_to_child erpnext.patches.v12_0.stock_entry_enhancements erpnext.patches.v10_0.item_barcode_childtable_migrate # 16-02-2019 #25-06-2019 +erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.move_item_tax_to_item_tax_template erpnext.patches.v11_1.set_variant_based_on erpnext.patches.v11_1.woocommerce_set_creation_user @@ -606,7 +607,6 @@ erpnext.patches.v11_1.delete_scheduling_tool erpnext.patches.v12_0.rename_tolerance_fields erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019 execute:frappe.delete_doc_if_exists("Page", "support-analytics") -erpnext.patches.v12_0.make_item_manufacturer erpnext.patches.v12_0.remove_patient_medical_record_page erpnext.patches.v11_1.move_customer_lead_to_dynamic_column erpnext.patches.v11_1.set_default_action_for_quality_inspection From 81d5265385393a2b78c936613fddffd528f3bc62 Mon Sep 17 00:00:00 2001 From: Anurag Mishra Date: Tue, 13 Aug 2019 19:40:36 +0530 Subject: [PATCH 13/17] fix: removed hard coded string --- erpnext/setup/doctype/company/company.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/company/company.py b/erpnext/setup/doctype/company/company.py index da29d20503..584391e1e0 100644 --- a/erpnext/setup/doctype/company/company.py +++ b/erpnext/setup/doctype/company/company.py @@ -252,7 +252,7 @@ class Company(NestedSet): def set_mode_of_payment_account(self): cash = frappe.db.get_value('Mode of Payment', {'type': 'Cash'}, 'name') if cash and self.default_cash_account \ - and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': 'Cash'}): + and not frappe.db.get_value('Mode of Payment Account', {'company': self.name, 'parent': cash}): mode_of_payment = frappe.get_doc('Mode of Payment', cash) mode_of_payment.append('accounts', { 'company': self.name, From 78690d7b8b91dd825fe80593e54dea1e7172bc4b Mon Sep 17 00:00:00 2001 From: Anurag Mishra <32095923+Anurag810@users.noreply.github.com> Date: Wed, 14 Aug 2019 15:03:58 +0530 Subject: [PATCH 14/17] fix:payment ammount validation for pos invoices (#18663) --- .../accounts/doctype/sales_invoice/sales_invoice.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py index 874230052a..4f80b78c88 100644 --- a/erpnext/accounts/doctype/sales_invoice/sales_invoice.py +++ b/erpnext/accounts/doctype/sales_invoice/sales_invoice.py @@ -78,6 +78,7 @@ class SalesInvoice(SellingController): self.so_dn_required() self.validate_proj_cust() + self.validate_pos_return() self.validate_with_previous_doc() self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("uom", "qty") @@ -199,6 +200,16 @@ class SalesInvoice(SellingController): if "Healthcare" in active_domains: manage_invoice_submit_cancel(self, "on_submit") + def validate_pos_return(self): + + if self.is_pos and self.is_return: + total_amount_in_payments = 0 + for payment in self.payments: + total_amount_in_payments += payment.amount + + if total_amount_in_payments < self.rounded_total: + frappe.throw(_("Total payments amount can't be greater than {}".format(-self.rounded_total))) + def validate_pos_paid_amount(self): if len(self.payments) == 0 and self.is_pos: frappe.throw(_("At least one mode of payment is required for POS invoice.")) From c97a7fb845302c7d3fe7e661ab228946b3e4545d Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Wed, 14 Aug 2019 17:38:44 +0530 Subject: [PATCH 15/17] fix: restrict the payment order to non received type payment entries --- erpnext/accounts/doctype/payment_order/payment_order.js | 1 + 1 file changed, 1 insertion(+) diff --git a/erpnext/accounts/doctype/payment_order/payment_order.js b/erpnext/accounts/doctype/payment_order/payment_order.js index f2f00cebcb..ce9cfe527c 100644 --- a/erpnext/accounts/doctype/payment_order/payment_order.js +++ b/erpnext/accounts/doctype/payment_order/payment_order.js @@ -66,6 +66,7 @@ frappe.ui.form.on('Payment Order', { get_query_filters: { bank: frm.doc.bank, docstatus: 1, + payment_type: ("!=", "Receive"), bank_account: frm.doc.company_bank_account, paid_from: frm.doc.account, payment_order_status: ["=", "Initiated"], From d5b4b1fdaff341df5697f1e37c0b19ffd9238791 Mon Sep 17 00:00:00 2001 From: rohitwaghchaure Date: Tue, 20 Aug 2019 12:35:15 +0530 Subject: [PATCH 16/17] fix: group by voucher consolidated showing incorrect data for deferred entries (#18777) --- .../report/general_ledger/general_ledger.py | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/erpnext/accounts/report/general_ledger/general_ledger.py b/erpnext/accounts/report/general_ledger/general_ledger.py index 86fd1088f5..ec3fb1fc9c 100644 --- a/erpnext/accounts/report/general_ledger/general_ledger.py +++ b/erpnext/accounts/report/general_ledger/general_ledger.py @@ -119,19 +119,11 @@ def get_gl_entries(filters): select_fields = """, debit, credit, debit_in_account_currency, credit_in_account_currency """ - group_by_statement = '' order_by_statement = "order by posting_date, account" if filters.get("group_by") == _("Group by Voucher"): order_by_statement = "order by posting_date, voucher_type, voucher_no" - if filters.get("group_by") == _("Group by Voucher (Consolidated)"): - group_by_statement = "group by voucher_type, voucher_no, account, cost_center" - - select_fields = """, sum(debit) as debit, sum(credit) as credit, - sum(debit_in_account_currency) as debit_in_account_currency, - sum(credit_in_account_currency) as credit_in_account_currency""" - if filters.get("include_default_book_entries"): filters['company_fb'] = frappe.db.get_value("Company", filters.get("company"), 'default_finance_book') @@ -144,11 +136,10 @@ def get_gl_entries(filters): against_voucher_type, against_voucher, account_currency, remarks, against, is_opening {select_fields} from `tabGL Entry` - where company=%(company)s {conditions} {group_by_statement} + where company=%(company)s {conditions} {order_by_statement} """.format( select_fields=select_fields, conditions=get_conditions(filters), - group_by_statement=group_by_statement, order_by_statement=order_by_statement ), filters, as_dict=1) @@ -185,7 +176,8 @@ def get_conditions(filters): if not (filters.get("account") or filters.get("party") or filters.get("group_by") in ["Group by Account", "Group by Party"]): conditions.append("posting_date >=%(from_date)s") - conditions.append("posting_date <=%(to_date)s") + + conditions.append("(posting_date <=%(to_date)s or is_opening = 'Yes')") if filters.get("project"): conditions.append("project in %(project)s") @@ -286,6 +278,7 @@ def initialize_gle_map(gl_entries, filters): def get_accountwise_gle(filters, gl_entries, gle_map): totals = get_totals_dict() entries = [] + consolidated_gle = OrderedDict() group_by = group_by_field(filters.get('group_by')) def update_value_in_dict(data, key, gle): @@ -310,12 +303,20 @@ def get_accountwise_gle(filters, gl_entries, gle_map): update_value_in_dict(totals, 'total', gle) if filters.get("group_by") != _('Group by Voucher (Consolidated)'): gle_map[gle.get(group_by)].entries.append(gle) - else: - entries.append(gle) + elif filters.get("group_by") == _('Group by Voucher (Consolidated)'): + key = (gle.get("voucher_type"), gle.get("voucher_no"), + gle.get("account"), gle.get("cost_center")) + if key not in consolidated_gle: + consolidated_gle.setdefault(key, gle) + else: + update_value_in_dict(consolidated_gle, key, gle) update_value_in_dict(gle_map[gle.get(group_by)].totals, 'closing', gle) update_value_in_dict(totals, 'closing', gle) + for key, value in consolidated_gle.items(): + entries.append(value) + return totals, entries def get_result_as_list(data, filters): From a8403cde168982d582563e0629f4ab38b1f7bae6 Mon Sep 17 00:00:00 2001 From: Sahil Khan Date: Tue, 20 Aug 2019 16:20:26 +0550 Subject: [PATCH 17/17] bumped to version 12.0.7 --- erpnext/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/__init__.py b/erpnext/__init__.py index e1c3d78d3f..8c47111e01 100644 --- a/erpnext/__init__.py +++ b/erpnext/__init__.py @@ -5,7 +5,7 @@ import frappe from erpnext.hooks import regional_overrides from frappe.utils import getdate -__version__ = '12.0.6' +__version__ = '12.0.7' def get_default_company(user=None): '''Get default company for user'''