From 1ce45f623ec66c3055a265a843340a71d6195409 Mon Sep 17 00:00:00 2001 From: marination Date: Mon, 9 May 2022 13:00:00 +0530 Subject: [PATCH 1/4] fix: Set actual qty and basic rate in SE on warehouse triggers (`get_warehouse_details`) - set `actual_qty` on source and target warehouse change --- erpnext/stock/doctype/stock_entry/stock_entry.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 1df56ef7b4..540ad186e1 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -470,7 +470,9 @@ frappe.ui.form.on('Stock Entry', { }, callback: function(r) { if (!r.exc) { - $.extend(child, r.message); + ["actual_qty", "basic_rate"].forEach((field) => { + frappe.model.set_value(cdt, cdn, field, (r.message[field] || 0.0)); + }); frm.events.calculate_basic_amount(frm, child); } } @@ -1057,8 +1059,8 @@ function attach_bom_items(bom_no) { function check_should_not_attach_bom_items(bom_no) { return ( - bom_no === undefined || - (erpnext.stock.bom && erpnext.stock.bom.name === bom_no) + bom_no === undefined || + (erpnext.stock.bom && erpnext.stock.bom.name === bom_no) ); } From 494ddd1eb4926df9e78b2e0cba89e2094d965ecb Mon Sep 17 00:00:00 2001 From: marination Date: Tue, 10 May 2022 14:02:43 +0530 Subject: [PATCH 2/4] fix: Calculate totals even though pricing rule is not applied on mapped doc - `apply_pricing_rule` is triggered due to change in some data which most likely contributes to Total. --- erpnext/public/js/controllers/transaction.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 767221e99d..920254cdce 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1390,6 +1390,9 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe // Target doc created from a mapped doc if (this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list) { + // Calculate totals even though pricing rule is not applied. + // `apply_pricing_rule` is triggered due to change in data which most likely contributes to Total. + if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); return; } From 90a8e924f5683147ae0f9f450ad0593d4081b80a Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 May 2022 14:54:22 +0530 Subject: [PATCH 3/4] fix: `set_missing_values` in SE and re-use the same on all SE mappings - `set_missing_values` in SE will set actual qty, transfer qty and calculate rate/amount - Re-use `set_missing_values` wherever SE is doc is being mapped --- erpnext/buying/doctype/purchase_order/purchase_order.py | 4 +++- erpnext/manufacturing/doctype/job_card/job_card.py | 2 -- erpnext/public/js/controllers/transaction.js | 4 ++-- erpnext/stock/doctype/batch/batch.py | 1 + erpnext/stock/doctype/material_request/material_request.py | 2 +- erpnext/stock/doctype/pick_list/pick_list.py | 3 +-- erpnext/stock/doctype/purchase_receipt/purchase_receipt.py | 1 + erpnext/stock/doctype/stock_entry/stock_entry.py | 7 +++++++ erpnext/stock/doctype/stock_entry/stock_entry_utils.py | 2 ++ 9 files changed, 18 insertions(+), 8 deletions(-) diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 5860c4c8ae..9189f18373 100644 --- a/erpnext/buying/doctype/purchase_order/purchase_order.py +++ b/erpnext/buying/doctype/purchase_order/purchase_order.py @@ -637,6 +637,8 @@ def make_rm_stock_entry(purchase_order, rm_items): } } stock_entry.add_to_stock_entry_detail(items_dict) + + stock_entry.set_missing_values() return stock_entry.as_dict() else: frappe.throw(_("No Items selected for transfer")) @@ -724,7 +726,7 @@ def make_return_stock_entry_for_subcontract(available_materials, po_doc, po_deta add_items_in_ste(ste_doc, value, value.qty, po_details) ste_doc.set_stock_entry_type() - ste_doc.calculate_rate_and_amount() + ste_doc.set_missing_values() return ste_doc diff --git a/erpnext/manufacturing/doctype/job_card/job_card.py b/erpnext/manufacturing/doctype/job_card/job_card.py index bf4f82f57e..a98fc94868 100644 --- a/erpnext/manufacturing/doctype/job_card/job_card.py +++ b/erpnext/manufacturing/doctype/job_card/job_card.py @@ -764,8 +764,6 @@ def make_stock_entry(source_name, target_doc=None): pending_fg_qty = flt(source.get("for_quantity", 0)) - flt(source.get("transferred_qty", 0)) target.fg_completed_qty = pending_fg_qty if pending_fg_qty > 0 else 0 - target.set_transfer_qty() - target.calculate_rate_and_amount() target.set_missing_values() target.set_stock_entry_type() diff --git a/erpnext/public/js/controllers/transaction.js b/erpnext/public/js/controllers/transaction.js index 920254cdce..c3812f3848 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1384,7 +1384,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe var me = this; var args = this._get_args(item); if (!(args.items && args.items.length)) { - if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); + if (calculate_taxes_and_totals) me.calculate_taxes_and_totals(); return; } @@ -1392,7 +1392,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe if (this.frm.doc.__onload && this.frm.doc.__onload.ignore_price_list) { // Calculate totals even though pricing rule is not applied. // `apply_pricing_rule` is triggered due to change in data which most likely contributes to Total. - if(calculate_taxes_and_totals) me.calculate_taxes_and_totals(); + if (calculate_taxes_and_totals) me.calculate_taxes_and_totals(); return; } diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index aac6cd386c..77640db976 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -244,6 +244,7 @@ def split_batch(batch_no, item_code, warehouse, qty, new_batch_id=None): ) ) stock_entry.set_stock_entry_type() + stock_entry.set_missing_values() stock_entry.insert() stock_entry.submit() diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index a70ff171a9..c998629e76 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -597,7 +597,7 @@ def make_stock_entry(source_name, target_doc=None): if source.material_request_type == "Customer Provided": target.purpose = "Material Receipt" - target.run_method("calculate_rate_and_amount") + target.set_missing_values() target.set_stock_entry_type() target.set_job_card_data() diff --git a/erpnext/stock/doctype/pick_list/pick_list.py b/erpnext/stock/doctype/pick_list/pick_list.py index 70d2f23070..d552c097f3 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -672,8 +672,7 @@ def create_stock_entry(pick_list): else: stock_entry = update_stock_entry_items_with_no_reference(pick_list, stock_entry) - stock_entry.set_actual_qty() - stock_entry.calculate_rate_and_amount() + stock_entry.set_missing_values() return stock_entry.as_dict() diff --git a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py index ec0e809aa6..fcf0cd182d 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -1036,6 +1036,7 @@ def make_stock_entry(source_name, target_doc=None): def set_missing_values(source, target): target.stock_entry_type = "Material Transfer" target.purpose = "Material Transfer" + target.set_missing_values() doclist = get_mapped_doc( "Purchase Receipt", diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index 27a6eaf08b..2a7354de93 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2197,6 +2197,12 @@ class StockEntry(StockController): return sorted(list(set(get_serial_nos(self.pro_doc.serial_no)) - set(used_serial_nos))) + def set_missing_values(self): + "Updates rate and availability of all the items of mapped doc." + self.set_transfer_qty() + self.set_actual_qty() + self.calculate_rate_and_amount() + @frappe.whitelist() def move_sample_to_retention_warehouse(company, items): @@ -2246,6 +2252,7 @@ def move_sample_to_retention_warehouse(company, items): def make_stock_in_entry(source_name, target_doc=None): def set_missing_values(source, target): target.set_stock_entry_type() + target.set_missing_values() def update_item(source_doc, target_doc, source_parent): target_doc.t_warehouse = "" diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index b3df7286ea..cf1032c5ac 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -132,6 +132,8 @@ def make_stock_entry(**args): ) s.set_stock_entry_type() + s.set_missing_values() + if not args.do_not_save: s.insert() if not args.do_not_submit: From 4fa15b50caf48cac8251c047e9fdd5abd0dca1da Mon Sep 17 00:00:00 2001 From: marination Date: Wed, 11 May 2022 17:58:48 +0530 Subject: [PATCH 4/4] test: Test for mapped SE and fix for failing tests - Remove `set_missing_values` from mapper util function since a lot of item data is set after this function is run - `split_batch` can skip `set_missing_values` since no warehouses are set on mapping and relies on user input --- erpnext/stock/doctype/batch/batch.py | 1 - .../doctype/stock_entry/stock_entry_utils.py | 1 - .../doctype/stock_entry/test_stock_entry.py | 19 +++++++++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/erpnext/stock/doctype/batch/batch.py b/erpnext/stock/doctype/batch/batch.py index 77640db976..aac6cd386c 100644 --- a/erpnext/stock/doctype/batch/batch.py +++ b/erpnext/stock/doctype/batch/batch.py @@ -244,7 +244,6 @@ def split_batch(batch_no, item_code, warehouse, qty, new_batch_id=None): ) ) stock_entry.set_stock_entry_type() - stock_entry.set_missing_values() stock_entry.insert() stock_entry.submit() diff --git a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py index cf1032c5ac..c5c0cefe51 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -132,7 +132,6 @@ def make_stock_entry(**args): ) s.set_stock_entry_type() - s.set_missing_values() if not args.do_not_save: s.insert() diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index b9c57c1ecf..71baf9f53f 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -1424,6 +1424,25 @@ class TestStockEntry(FrappeTestCase): self.assertRaises(frappe.ValidationError, se.save) + def test_mapped_stock_entry(self): + "Check if rate and stock details are populated in mapped SE given warehouse." + from erpnext.stock.doctype.purchase_receipt.purchase_receipt import make_stock_entry + from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt + + item_code = "_TestMappedItem" + create_item(item_code, is_stock_item=True) + + pr = make_purchase_receipt( + item_code=item_code, qty=2, rate=100, company="_Test Company", warehouse="Stores - _TC" + ) + + mapped_se = make_stock_entry(pr.name) + + self.assertEqual(mapped_se.items[0].s_warehouse, "Stores - _TC") + self.assertEqual(mapped_se.items[0].actual_qty, 2) + self.assertEqual(mapped_se.items[0].basic_rate, 100) + self.assertEqual(mapped_se.items[0].basic_amount, 200) + def make_serialized_item(**args): args = frappe._dict(args)