From 02cc618a1fc52de4fa3e5aaf413f1e045eb35a24 Mon Sep 17 00:00:00 2001 From: ruthra kumar Date: Tue, 6 Dec 2022 17:13:11 +0530 Subject: [PATCH 1/8] fix: index error on customer master (cherry picked from commit cf1e3dc8eac0df6731c333ad207cfeece514b8ab) --- erpnext/selling/doctype/customer/customer.py | 21 +++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/erpnext/selling/doctype/customer/customer.py b/erpnext/selling/doctype/customer/customer.py index d0eb3774e26..60c33567bef 100644 --- a/erpnext/selling/doctype/customer/customer.py +++ b/erpnext/selling/doctype/customer/customer.py @@ -6,7 +6,7 @@ import json import frappe import frappe.defaults -from frappe import _, msgprint +from frappe import _, msgprint, qb from frappe.contacts.address_and_contact import ( delete_contact_and_address, load_address_and_contact, @@ -732,12 +732,15 @@ def make_address(args, is_primary_address=1): @frappe.validate_and_sanitize_search_inputs def get_customer_primary_contact(doctype, txt, searchfield, start, page_len, filters): customer = filters.get("customer") - return frappe.db.sql( - """ - select `tabContact`.name from `tabContact`, `tabDynamic Link` - where `tabContact`.name = `tabDynamic Link`.parent and `tabDynamic Link`.link_name = %(customer)s - and `tabDynamic Link`.link_doctype = 'Customer' - and `tabContact`.name like %(txt)s - """, - {"customer": customer, "txt": "%%%s%%" % txt}, + + con = qb.DocType("Contact") + dlink = qb.DocType("Dynamic Link") + + return ( + qb.from_(con) + .join(dlink) + .on(con.name == dlink.parent) + .select(con.name, con.full_name, con.email_id) + .where((dlink.link_name == customer) & (con.name.like(f"%{txt}%"))) + .run() ) From ef933a8231cc219e5e81d8c8cae7b8b61b6d1dc3 Mon Sep 17 00:00:00 2001 From: barredterra <14891507+barredterra@users.noreply.github.com> Date: Mon, 5 Dec 2022 18:24:22 +0100 Subject: [PATCH 2/8] fix: add translation variable order (cherry picked from commit 748c74ba5276b707125a361b2b241b7b7a978dd0) --- erpnext/controllers/status_updater.py | 2 +- erpnext/translations/de.csv | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/erpnext/controllers/status_updater.py b/erpnext/controllers/status_updater.py index 6e7d2b33c28..bf077282bf8 100644 --- a/erpnext/controllers/status_updater.py +++ b/erpnext/controllers/status_updater.py @@ -349,7 +349,7 @@ class StatusUpdater(Document): def warn_about_bypassing_with_role(self, item, qty_or_amount, role): action = _("Over Receipt/Delivery") if qty_or_amount == "qty" else _("Overbilling") - msg = _("{} of {} {} ignored for item {} because you have {} role.").format( + msg = _("{0} of {1} {2} ignored for item {3} because you have {4} role.").format( action, _(item["target_ref_field"].title()), frappe.bold(item["reduce_by"]), diff --git a/erpnext/translations/de.csv b/erpnext/translations/de.csv index ec9c50247fa..a401983d2ad 100644 --- a/erpnext/translations/de.csv +++ b/erpnext/translations/de.csv @@ -9916,3 +9916,4 @@ Cost and Freight,Kosten und Fracht, Delivered at Place,Geliefert benannter Ort, Delivered at Place Unloaded,Geliefert benannter Ort entladen, Delivered Duty Paid,Geliefert verzollt, +{0} of {1} {2} ignored for item {3} because you have {4} role,"{0} von Artikel {3} mit {1} {2} wurde ignoriert, weil Sie die Rolle {4} haben." From 40621b99c83b8002e76e7e79bd0f526ef846c3fc Mon Sep 17 00:00:00 2001 From: Sabu Siyad Date: Thu, 8 Dec 2022 16:47:50 +0530 Subject: [PATCH 3/8] fix(ecommerce): remove query parameters from referer inclusion of query parameters results in logic failure example: - logic check if referrer is `all-products` - `http://shop.example/all-products` -> `all-products`, valid outcome - `http://shop.example/all-products?start=1` -> `all-products?start=1`, invalid outcome Signed-off-by: Sabu Siyad (cherry picked from commit b6bd408f19fd7b65c8a41fe05c467789eb91b399) --- erpnext/setup/doctype/item_group/item_group.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/setup/doctype/item_group/item_group.py b/erpnext/setup/doctype/item_group/item_group.py index 411176b70af..95bbf84616b 100644 --- a/erpnext/setup/doctype/item_group/item_group.py +++ b/erpnext/setup/doctype/item_group/item_group.py @@ -152,7 +152,7 @@ def get_parent_item_groups(item_group_name, from_item=False): if from_item and frappe.request.environ.get("HTTP_REFERER"): # base page after 'Home' will vary on Item page - last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1] + last_page = frappe.request.environ["HTTP_REFERER"].split("/")[-1].split("?")[0] if last_page and last_page in ("shop-by-category", "all-products"): base_nav_page_title = " ".join(last_page.split("-")).title() base_nav_page = {"name": _(base_nav_page_title), "route": "/" + last_page} From f5205a5b5d27769da3f2c60f0250ee20bd2b6b13 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 1 Dec 2022 21:23:17 +0530 Subject: [PATCH 4/8] fix: Buying and selling check in pricing rule (cherry picked from commit f54838ab56a258eb3d2d77fc9622076dc9b49fa7) --- erpnext/accounts/doctype/pricing_rule/utils.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 35eed49da70..bd489e03175 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -244,6 +244,11 @@ def get_other_conditions(conditions, values, args): and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" values["transaction_date"] = args.get("transaction_date") + if args.get("doctype") in ["Sales Order", "Delivery Note", "Sales Invoice"]: + conditions += """ and ifnull(`tabPricing Rule`.selling, 0) = 1""" + else: + conditions += """ and ifnull(`tabPricing Rule`.buying, 0) = 1""" + return conditions From c726c167026ad99fbb0bfb142a2c441be6a2581f Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Fri, 2 Dec 2022 17:14:06 +0530 Subject: [PATCH 5/8] fix: Reapply pricing rule on qty change (cherry picked from commit b741ae143c514cf832a435db1902986a915efde4) --- erpnext/accounts/doctype/pricing_rule/pricing_rule.py | 4 ++-- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- erpnext/controllers/accounts_controller.py | 2 +- erpnext/public/js/controllers/transaction.js | 11 +++++++---- erpnext/stock/get_item_details.py | 4 ++-- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py index ed46d85e3a4..e2b015bf021 100644 --- a/erpnext/accounts/doctype/pricing_rule/pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/pricing_rule.py @@ -256,7 +256,7 @@ def apply_pricing_rule(args, doc=None): for item in item_list: args_copy = copy.deepcopy(args) args_copy.update(item) - data = get_pricing_rule_for_item(args_copy, item.get("price_list_rate"), doc=doc) + data = get_pricing_rule_for_item(args_copy, doc=doc) out.append(data) if ( @@ -293,7 +293,7 @@ def update_pricing_rule_uom(pricing_rule, args): pricing_rule.uom = row.uom -def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False): +def get_pricing_rule_for_item(args, doc=None, for_validate=False): from erpnext.accounts.doctype.pricing_rule.utils import ( get_applied_pricing_rules, get_pricing_rule_items, diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index bd489e03175..b74fb162185 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -668,7 +668,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None): item_details.free_item_data.append(free_item_data_args) -def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False): +def apply_pricing_rule_for_free_items(doc, pricing_rule_args): if pricing_rule_args: items = tuple((d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item) diff --git a/erpnext/controllers/accounts_controller.py b/erpnext/controllers/accounts_controller.py index 5a051e3bafc..334a2d806d6 100644 --- a/erpnext/controllers/accounts_controller.py +++ b/erpnext/controllers/accounts_controller.py @@ -197,7 +197,7 @@ class AccountsController(TransactionBase): validate_einvoice_fields(self) - if self.doctype != "Material Request": + if self.doctype != "Material Request" and not self.ignore_pricing_rule: apply_pricing_rule_on_transaction(self) def before_cancel(self): diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 46ac80895cf..32268319f2e 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1130,10 +1130,13 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe qty(doc, cdt, cdn) { let item = frappe.get_doc(cdt, cdn); - item.pricing_rules = '' - this.conversion_factor(doc, cdt, cdn, true); - this.calculate_stock_uom_rate(doc, cdt, cdn); - this.apply_pricing_rule(item, true); + // item.pricing_rules = '' + frappe.run_serially([ + () => this.remove_pricing_rule(item), + () => this.conversion_factor(doc, cdt, cdn, true), + () => this.calculate_stock_uom_rate(doc, cdt, cdn), + () => this.apply_pricing_rule(item, true) + ]); } calculate_stock_uom_rate(doc, cdt, cdn) { diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 108611c09bf..a9e8db07424 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -113,7 +113,7 @@ def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=Tru if args.get(key) is None: args[key] = value - data = get_pricing_rule_for_item(args, out.price_list_rate, doc, for_validate=for_validate) + data = get_pricing_rule_for_item(args, doc, for_validate=for_validate) out.update(data) @@ -1305,7 +1305,7 @@ def apply_price_list_on_item(args): item_doc = frappe.db.get_value("Item", args.item_code, ["name", "variant_of"], as_dict=1) item_details = get_price_list_rate(args, item_doc) - item_details.update(get_pricing_rule_for_item(args, item_details.price_list_rate)) + item_details.update(get_pricing_rule_for_item(args)) return item_details From 033b2a4825a060c60997b04802213723e28dd414 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 5 Dec 2022 15:43:03 +0530 Subject: [PATCH 6/8] chore: Add POS Invoices (cherry picked from commit 5f821b93a5832ee3f37d37dc9192ac656be3224e) --- erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py | 2 +- erpnext/accounts/doctype/pricing_rule/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index 79c7c12b413..7f8cc4c63e0 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -997,7 +997,7 @@ def make_pricing_rule(**args): "apply_on": args.apply_on or "Item Code", "applicable_for": args.applicable_for, "selling": args.selling or 0, - "currency": "USD", + "currency": "INR", "apply_discount_on_rate": args.apply_discount_on_rate or 0, "buying": args.buying or 0, "min_qty": args.min_qty or 0.0, diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index b74fb162185..815c2f220e1 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -244,7 +244,7 @@ def get_other_conditions(conditions, values, args): and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" values["transaction_date"] = args.get("transaction_date") - if args.get("doctype") in ["Sales Order", "Delivery Note", "Sales Invoice"]: + if args.get("doctype") in ["Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"]: conditions += """ and ifnull(`tabPricing Rule`.selling, 0) = 1""" else: conditions += """ and ifnull(`tabPricing Rule`.buying, 0) = 1""" From 5e5937d6d020ae910ab9064419bb2700cd0d12c8 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 5 Dec 2022 17:59:02 +0530 Subject: [PATCH 7/8] fix: Remove free items (cherry picked from commit 05810009907560b02509fcb43ae65319daa54e90) --- erpnext/public/js/controllers/transaction.js | 25 ++++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 32268319f2e..58d8de24993 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1360,16 +1360,21 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe var item_list = []; $.each(this.frm.doc["items"] || [], function(i, d) { - if (d.item_code && !d.is_free_item) { - item_list.push({ - "doctype": d.doctype, - "name": d.name, - "item_code": d.item_code, - "pricing_rules": d.pricing_rules, - "parenttype": d.parenttype, - "parent": d.parent, - "price_list_rate": d.price_list_rate - }) + if (d.item_code) { + if (d.is_free_item) { + // Simply remove free items + me.frm.get_field("items").grid.grid_rows[i].remove(); + } else { + item_list.push({ + "doctype": d.doctype, + "name": d.name, + "item_code": d.item_code, + "pricing_rules": d.pricing_rules, + "parenttype": d.parenttype, + "parent": d.parent, + "price_list_rate": d.price_list_rate + }) + } } }); return this.frm.call({ From ad03355333e056c07f975de6611d69f890d4c1f6 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Thu, 8 Dec 2022 18:04:40 +0530 Subject: [PATCH 8/8] chore: Update tests (cherry picked from commit 6192af5cf04e2cec18cc6cb012adb779a0d2966b) --- erpnext/accounts/doctype/pricing_rule/utils.py | 8 +++++++- erpnext/stock/get_item_details.py | 2 +- erpnext/utilities/product.py | 1 + 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 815c2f220e1..ab1d7385f78 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -244,7 +244,13 @@ def get_other_conditions(conditions, values, args): and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" values["transaction_date"] = args.get("transaction_date") - if args.get("doctype") in ["Sales Order", "Delivery Note", "Sales Invoice", "POS Invoice"]: + if args.get("doctype") in [ + "Quotation", + "Sales Order", + "Delivery Note", + "Sales Invoice", + "POS Invoice", + ]: conditions += """ and ifnull(`tabPricing Rule`.selling, 0) = 1""" else: conditions += """ and ifnull(`tabPricing Rule`.buying, 0) = 1""" diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index a9e8db07424..31dccf6944d 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -113,7 +113,7 @@ def get_item_details(args, doc=None, for_validate=False, overwrite_warehouse=Tru if args.get(key) is None: args[key] = value - data = get_pricing_rule_for_item(args, doc, for_validate=for_validate) + data = get_pricing_rule_for_item(args, doc=doc, for_validate=for_validate) out.update(data) diff --git a/erpnext/utilities/product.py b/erpnext/utilities/product.py index 04ee0b3b1eb..afe9654e8ea 100644 --- a/erpnext/utilities/product.py +++ b/erpnext/utilities/product.py @@ -110,6 +110,7 @@ def get_price(item_code, price_list, customer_group, company, qty=1): "conversion_rate": 1, "for_shopping_cart": True, "currency": frappe.db.get_value("Price List", price_list, "currency"), + "doctype": "Quotation", } )