diff --git a/erpnext/buying/doctype/purchase_order/purchase_order.py b/erpnext/buying/doctype/purchase_order/purchase_order.py index 582bd8d1db8..250faa7c88b 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 c8b37a9c80d..983b3b17e68 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 fdc129b9116..56a214283b3 100644 --- a/erpnext/public/js/controllers/transaction.js +++ b/erpnext/public/js/controllers/transaction.js @@ -1496,12 +1496,15 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({ 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; } // 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; } diff --git a/erpnext/stock/doctype/material_request/material_request.py b/erpnext/stock/doctype/material_request/material_request.py index 415c45cf1fe..55c9ac47e4c 100644 --- a/erpnext/stock/doctype/material_request/material_request.py +++ b/erpnext/stock/doctype/material_request/material_request.py @@ -600,7 +600,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 858481aa7b9..49cfbe2ce27 100644 --- a/erpnext/stock/doctype/pick_list/pick_list.py +++ b/erpnext/stock/doctype/pick_list/pick_list.py @@ -671,8 +671,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 db94beccbcf..cca3f05270c 100644 --- a/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py +++ b/erpnext/stock/doctype/purchase_receipt/purchase_receipt.py @@ -993,6 +993,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.js b/erpnext/stock/doctype/stock_entry/stock_entry.js index 4ec9f1f220f..ad84c36b811 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.js +++ b/erpnext/stock/doctype/stock_entry/stock_entry.js @@ -468,7 +468,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); } } @@ -1069,8 +1071,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) ); } diff --git a/erpnext/stock/doctype/stock_entry/stock_entry.py b/erpnext/stock/doctype/stock_entry/stock_entry.py index f0566b08897..8ff11ee9b80 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry.py @@ -2196,6 +2196,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): @@ -2245,6 +2251,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 85ccc5b13fc..552023c0a6c 100644 --- a/erpnext/stock/doctype/stock_entry/stock_entry_utils.py +++ b/erpnext/stock/doctype/stock_entry/stock_entry_utils.py @@ -133,6 +133,7 @@ def make_stock_entry(**args): ) s.set_stock_entry_type() + if not args.do_not_save: s.insert() if not args.do_not_submit: diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 0c2e77c819c..f824787226b 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -1381,6 +1381,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)