From e32e0bc8fac4bae0bbec5045b1b1bc0df7a47eb0 Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Mon, 31 Oct 2022 19:01:54 +0530 Subject: [PATCH 1/8] fix: Reset advance paid amount on Oreder cancel and amend (cherry picked from commit 92f37ca111504eb3aa7092ec61db4513f24b2c61) # Conflicts: # erpnext/buying/doctype/purchase_order/purchase_order.js --- .../doctype/purchase_order/purchase_order.js | 28 +++++++++++++++++++ .../doctype/sales_order/sales_order.js | 5 ++++ 2 files changed, 33 insertions(+) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index b6f5ff92191..1944b08e800 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -84,7 +84,35 @@ frappe.ui.form.on("Purchase Order", { }); }, __('Create')); } +<<<<<<< HEAD } +======= + }, + + onload: function(frm) { + set_schedule_date(frm); + if (!frm.doc.transaction_date){ + frm.set_value('transaction_date', frappe.datetime.get_today()) + } + + erpnext.queries.setup_queries(frm, "Warehouse", function() { + return erpnext.queries.warehouse(frm.doc); + }); + + // On cancel and amending a purchase order with advance payment, reset advance paid amount + if (frm.is_new()) { + frm.set_value("advance_paid", 0) + } + }, + + apply_tds: function(frm) { + if (!frm.doc.apply_tds) { + frm.set_value("tax_withholding_category", ''); + } else { + frm.set_value("tax_withholding_category", frm.supplier_tds); + } + }, +>>>>>>> 92f37ca111 (fix: Reset advance paid amount on Oreder cancel and amend) }); frappe.ui.form.on("Purchase Order Item", { diff --git a/erpnext/selling/doctype/sales_order/sales_order.js b/erpnext/selling/doctype/sales_order/sales_order.js index 213909b9b99..1a40725552d 100644 --- a/erpnext/selling/doctype/sales_order/sales_order.js +++ b/erpnext/selling/doctype/sales_order/sales_order.js @@ -95,6 +95,11 @@ frappe.ui.form.on("Sales Order", { return query; }); + // On cancel and amending a sales order with advance payment, reset advance paid amount + if (frm.is_new()) { + frm.set_value("advance_paid", 0) + } + frm.ignore_doctypes_on_cancel_all = ['Purchase Order']; }, From 4f76ed1c683c7b1dc58cc8e82d6c36b8dea6406d Mon Sep 17 00:00:00 2001 From: Deepesh Garg Date: Tue, 8 Nov 2022 10:39:21 +0530 Subject: [PATCH 2/8] chore: Resolve conflicts --- .../doctype/purchase_order/purchase_order.js | 33 +++---------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.js b/erpnext/buying/doctype/purchase_order/purchase_order.js index 1944b08e800..2559ce76da6 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.js +++ b/erpnext/buying/doctype/purchase_order/purchase_order.js @@ -43,6 +43,11 @@ frappe.ui.form.on("Purchase Order", { erpnext.queries.setup_queries(frm, "Warehouse", function() { return erpnext.queries.warehouse(frm.doc); }); + + // On cancel and amending a purchase order with advance payment, reset advance paid amount + if (frm.is_new()) { + frm.set_value("advance_paid", 0) + } }, apply_tds: function(frm) { @@ -84,35 +89,7 @@ frappe.ui.form.on("Purchase Order", { }); }, __('Create')); } -<<<<<<< HEAD } -======= - }, - - onload: function(frm) { - set_schedule_date(frm); - if (!frm.doc.transaction_date){ - frm.set_value('transaction_date', frappe.datetime.get_today()) - } - - erpnext.queries.setup_queries(frm, "Warehouse", function() { - return erpnext.queries.warehouse(frm.doc); - }); - - // On cancel and amending a purchase order with advance payment, reset advance paid amount - if (frm.is_new()) { - frm.set_value("advance_paid", 0) - } - }, - - apply_tds: function(frm) { - if (!frm.doc.apply_tds) { - frm.set_value("tax_withholding_category", ''); - } else { - frm.set_value("tax_withholding_category", frm.supplier_tds); - } - }, ->>>>>>> 92f37ca111 (fix: Reset advance paid amount on Oreder cancel and amend) }); frappe.ui.form.on("Purchase Order Item", { From a16347f325f70cecd4990537a6ebac609ae2c0df Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Tue, 8 Nov 2022 16:35:34 +0530 Subject: [PATCH 3/8] fix: add Document Date in E-Invoice print format --- .../accounts/print_format/gst_e_invoice/gst_e_invoice.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html index 605ce8383e4..e1b2def2dae 100644 --- a/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html +++ b/erpnext/accounts/print_format/gst_e_invoice/gst_e_invoice.html @@ -50,6 +50,10 @@
{{ einvoice.DocDtls.No }}
+
+
+
{{ einvoice.DocDtls.Dt }}
+
From 1ed0b6e89b9dd98fb89d59c0ead9175a89037d53 Mon Sep 17 00:00:00 2001 From: Maharshi Patel Date: Wed, 9 Nov 2022 14:00:53 +0530 Subject: [PATCH 4/8] fix: Pricing rule item group consider UOM Pricing rule's apply_on_field == "item_group" didn't check for UOM. I have added the required checks. Same as #32566 --- .../doctype/pricing_rule/test_pricing_rule.py | 134 ++++++++++++++++++ .../accounts/doctype/pricing_rule/utils.py | 7 +- 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py index c5dac722bad..4b4bfb18188 100644 --- a/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py +++ b/erpnext/accounts/doctype/pricing_rule/test_pricing_rule.py @@ -712,6 +712,140 @@ class TestPricingRule(unittest.TestCase): item.delete() + def test_item_group_price_with_blank_uom_pricing_rule(self): + group = frappe.get_doc( + doctype="Item Group", + item_group_name="_Test Pricing Rule Item Group", + parent_item_group="All Item Groups", + ) + group.save() + properties = { + "item_code": "Item with Group Blank UOM", + "item_group": "_Test Pricing Rule Item Group", + "stock_uom": "Nos", + "sales_uom": "Box", + "uoms": [dict(uom="Box", conversion_factor=10)], + } + item = make_item(properties=properties) + + make_item_price("Item with Group Blank UOM", "_Test Price List", 100) + + pricing_rule_record = { + "doctype": "Pricing Rule", + "title": "_Test Item with Group Blank UOM Rule", + "apply_on": "Item Group", + "item_groups": [ + { + "item_group": "_Test Pricing Rule Item Group", + } + ], + "selling": 1, + "currency": "INR", + "rate_or_discount": "Rate", + "rate": 101, + "company": "_Test Company", + } + rule = frappe.get_doc(pricing_rule_record) + rule.insert() + + si = create_sales_invoice( + do_not_save=True, item_code="Item with Group Blank UOM", uom="Box", conversion_factor=10 + ) + si.selling_price_list = "_Test Price List" + si.save() + + # If UOM is blank consider it as stock UOM and apply pricing_rule on all UOM. + # rate is 101, Selling UOM is Box that have conversion_factor of 10 so 101 * 10 = 1010 + self.assertEqual(si.items[0].price_list_rate, 1010) + self.assertEqual(si.items[0].rate, 1010) + + si.delete() + + si = create_sales_invoice(do_not_save=True, item_code="Item with Group Blank UOM", uom="Nos") + si.selling_price_list = "_Test Price List" + si.save() + + # UOM is blank so consider it as stock UOM and apply pricing_rule on all UOM. + # rate is 101, Selling UOM is Nos that have conversion_factor of 1 so 101 * 1 = 101 + self.assertEqual(si.items[0].price_list_rate, 101) + self.assertEqual(si.items[0].rate, 101) + + si.delete() + rule.delete() + frappe.get_doc("Item Price", {"item_code": "Item with Group Blank UOM"}).delete() + item.delete() + group.delete() + + def test_item_group_price_with_selling_uom_pricing_rule(self): + group = frappe.get_doc( + doctype="Item Group", + item_group_name="_Test Pricing Rule Item Group UOM", + parent_item_group="All Item Groups", + ) + group.save() + properties = { + "item_code": "Item with Group UOM other than Stock", + "item_group": "_Test Pricing Rule Item Group UOM", + "stock_uom": "Nos", + "sales_uom": "Box", + "uoms": [dict(uom="Box", conversion_factor=10)], + } + item = make_item(properties=properties) + + make_item_price("Item with Group UOM other than Stock", "_Test Price List", 100) + + pricing_rule_record = { + "doctype": "Pricing Rule", + "title": "_Test Item with Group UOM other than Stock Rule", + "apply_on": "Item Group", + "item_groups": [ + { + "item_group": "_Test Pricing Rule Item Group UOM", + "uom": "Box", + } + ], + "selling": 1, + "currency": "INR", + "rate_or_discount": "Rate", + "rate": 101, + "company": "_Test Company", + } + rule = frappe.get_doc(pricing_rule_record) + rule.insert() + + si = create_sales_invoice( + do_not_save=True, + item_code="Item with Group UOM other than Stock", + uom="Box", + conversion_factor=10, + ) + si.selling_price_list = "_Test Price List" + si.save() + + # UOM is Box so apply pricing_rule only on Box UOM. + # Selling UOM is Box and as both UOM are same no need to multiply by conversion_factor. + self.assertEqual(si.items[0].price_list_rate, 101) + self.assertEqual(si.items[0].rate, 101) + + si.delete() + + si = create_sales_invoice( + do_not_save=True, item_code="Item with Group UOM other than Stock", uom="Nos" + ) + si.selling_price_list = "_Test Price List" + si.save() + + # UOM is Box so pricing_rule won't apply as selling_uom is Nos. + # As Pricing Rule is not applied price of 100 will be fetched from Item Price List. + self.assertEqual(si.items[0].price_list_rate, 100) + self.assertEqual(si.items[0].rate, 100) + + si.delete() + rule.delete() + frappe.get_doc("Item Price", {"item_code": "Item with Group UOM other than Stock"}).delete() + item.delete() + group.delete() + def test_pricing_rule_for_different_currency(self): make_item("Test Sanitizer Item") diff --git a/erpnext/accounts/doctype/pricing_rule/utils.py b/erpnext/accounts/doctype/pricing_rule/utils.py index 25f5492d0d1..984a8bae008 100644 --- a/erpnext/accounts/doctype/pricing_rule/utils.py +++ b/erpnext/accounts/doctype/pricing_rule/utils.py @@ -127,7 +127,12 @@ def _get_pricing_rules(apply_on, args, values): values["variant_of"] = args.variant_of elif apply_on_field == "item_group": item_conditions = _get_tree_conditions(args, "Item Group", child_doc, False) - + if args.get("uom", None): + item_conditions += ( + " and ({child_doc}.uom='{item_uom}' or IFNULL({child_doc}.uom, '')='')".format( + child_doc=child_doc, item_uom=args.get("uom") + ) + ) conditions += get_other_conditions(conditions, values, args) warehouse_conditions = _get_tree_conditions(args, "Warehouse", "`tabPricing Rule`") if warehouse_conditions: From 4a177113c6c64cee3ef6419f0341b511abd4bb42 Mon Sep 17 00:00:00 2001 From: Sagar Sharma Date: Thu, 10 Nov 2022 16:18:10 +0530 Subject: [PATCH 5/8] fix: don't set WIP Warehouse if is checked in WO (cherry picked from commit 9730cd0aecd25d32db0334a0f910bff16d996fc5) --- erpnext/manufacturing/doctype/work_order/work_order.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/manufacturing/doctype/work_order/work_order.py b/erpnext/manufacturing/doctype/work_order/work_order.py index 2802310250b..574ca185fee 100644 --- a/erpnext/manufacturing/doctype/work_order/work_order.py +++ b/erpnext/manufacturing/doctype/work_order/work_order.py @@ -145,7 +145,7 @@ class WorkOrder(Document): frappe.throw(_("Sales Order {0} is {1}").format(self.sales_order, status)) def set_default_warehouse(self): - if not self.wip_warehouse: + if not self.wip_warehouse and not self.skip_transfer: self.wip_warehouse = frappe.db.get_single_value( "Manufacturing Settings", "default_wip_warehouse" ) From f09e4273d9133b24bd3b046bdcf4c9db12c1fb7f Mon Sep 17 00:00:00 2001 From: Sagar Sharma Date: Thu, 10 Nov 2022 16:34:10 +0530 Subject: [PATCH 6/8] fix: set `WIP Warehouse` in Job Card (cherry picked from commit e7fa2e08adbc888fe0ca06b74e3019f5231dd53c) --- erpnext/manufacturing/doctype/job_card/job_card.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index f9ed007aed5..3503a352bc9 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -54,6 +54,9 @@ class JobCard(Document): self.set_onload("job_card_excess_transfer", excess_transfer) self.set_onload("work_order_stopped", self.is_work_order_stopped()) + def before_validate(self): + self.set_wip_warehouse() + def validate(self): self.validate_time_logs() self.set_status() @@ -639,6 +642,12 @@ class JobCard(Document): if update_status: self.db_set("status", self.status) + def set_wip_warehouse(self): + if not self.wip_warehouse: + self.wip_warehouse = frappe.db.get_single_value( + "Manufacturing Settings", "default_wip_warehouse" + ) + def validate_operation_id(self): if ( self.get("operation_id") From a19031cf9adcd4168570cdc29c5159f82c7f16f4 Mon Sep 17 00:00:00 2001 From: Abhinav Raut Date: Mon, 7 Nov 2022 17:43:08 +0530 Subject: [PATCH 7/8] fix: repayment schedule regeneration (cherry picked from commit d6ab2b3b87f42c6cb4091da96d3fc081e1018145) --- .../doctype/loan_repayment/loan_repayment.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py index c17de234556..9bc963ab931 100644 --- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py +++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py @@ -577,8 +577,8 @@ def regenerate_repayment_schedule(loan, cancel=0): loan_doc = frappe.get_doc("Loan", loan) next_accrual_date = None accrued_entries = 0 - last_repayment_amount = 0 - last_balance_amount = 0 + last_repayment_amount = None + last_balance_amount = None for term in reversed(loan_doc.get("repayment_schedule")): if not term.is_accrued: @@ -586,9 +586,9 @@ def regenerate_repayment_schedule(loan, cancel=0): loan_doc.remove(term) else: accrued_entries += 1 - if not last_repayment_amount: + if last_repayment_amount is None: last_repayment_amount = term.total_payment - if not last_balance_amount: + if last_balance_amount is None: last_balance_amount = term.balance_loan_amount loan_doc.save() From bd2242b285e5d2b627fda77c9f974069b1273c0c Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 9 Nov 2022 18:56:09 +0530 Subject: [PATCH 8/8] fix: set stock UOM in args to ensure item price is fetched (cherry picked from commit 57038c396937cc4c17b6d2ab1234a34a5b05aa23) --- erpnext/stock/get_item_details.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/stock/get_item_details.py b/erpnext/stock/get_item_details.py index 4db12dcb98b..d44b6ed93c9 100644 --- a/erpnext/stock/get_item_details.py +++ b/erpnext/stock/get_item_details.py @@ -315,6 +315,9 @@ def get_basic_details(args, item, overwrite_warehouse=True): else: args.uom = item.stock_uom + # Set stock UOM in args, so that it can be used while fetching item price + args.stock_uom = item.stock_uom + if args.get("batch_no") and item.name != frappe.get_cached_value( "Batch", args.get("batch_no"), "item" ):