From 78c8bb251eff8450ece23a312bae3e82962a2beb Mon Sep 17 00:00:00 2001 From: Rohit Waghchaure Date: Mon, 4 Jul 2022 20:24:18 +0530 Subject: [PATCH] fix: timeout error while reposting --- .../doctype/stock_entry/test_stock_entry.py | 134 +++++++++++++++++- erpnext/stock/stock_ledger.py | 19 +-- 2 files changed, 139 insertions(+), 14 deletions(-) diff --git a/erpnext/stock/doctype/stock_entry/test_stock_entry.py b/erpnext/stock/doctype/stock_entry/test_stock_entry.py index 6f4c910c7f..a2f9978670 100644 --- a/erpnext/stock/doctype/stock_entry/test_stock_entry.py +++ b/erpnext/stock/doctype/stock_entry/test_stock_entry.py @@ -5,7 +5,7 @@ import frappe from frappe.permissions import add_user_permission, remove_user_permission from frappe.tests.utils import FrappeTestCase, change_settings -from frappe.utils import flt, nowdate, nowtime +from frappe.utils import add_days, flt, nowdate, nowtime from erpnext.accounts.doctype.account.test_account import get_inventory_account from erpnext.stock.doctype.item.test_item import ( @@ -1457,6 +1457,138 @@ class TestStockEntry(FrappeTestCase): self.assertEqual(se.items[0].item_name, item.item_name) self.assertEqual(se.items[0].stock_uom, item.stock_uom) + def test_reposting_for_depedent_warehouse(self): + from erpnext.stock.doctype.repost_item_valuation.repost_item_valuation import repost_sl_entries + from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse + + # Inward at WH1 warehouse (Component) + # 1st Repack (Component (WH1) - Subcomponent (WH2)) + # 2nd Repack (Subcomponent (WH2) - FG Item (WH3)) + # Material Transfer of FG Item -> WH 3 -> WH2 -> Wh1 (Two transfer entries) + # Backdated transction which should update valuation rate in repack as well trasfer entries + + for item_code in ["FG Item 1", "Sub Component 1", "Component 1"]: + create_item(item_code) + + for warehouse in ["WH 1", "WH 2", "WH 3"]: + create_warehouse(warehouse) + + make_stock_entry( + item_code="Component 1", + rate=100, + purpose="Material Receipt", + qty=10, + to_warehouse="WH 1 - _TC", + posting_date=add_days(nowdate(), -10), + ) + + repack1 = make_stock_entry( + item_code="Component 1", + purpose="Repack", + do_not_save=True, + qty=10, + from_warehouse="WH 1 - _TC", + posting_date=add_days(nowdate(), -9), + ) + + repack1.append( + "items", + { + "item_code": "Sub Component 1", + "qty": 10, + "t_warehouse": "WH 2 - _TC", + "transfer_qty": 10, + "uom": "Nos", + "stock_uom": "Nos", + "conversion_factor": 1.0, + }, + ) + + repack1.save() + repack1.submit() + + self.assertEqual(repack1.items[1].basic_rate, 100) + self.assertEqual(repack1.items[1].amount, 1000) + + repack2 = make_stock_entry( + item_code="Sub Component 1", + purpose="Repack", + do_not_save=True, + qty=10, + from_warehouse="WH 2 - _TC", + posting_date=add_days(nowdate(), -8), + ) + + repack2.append( + "items", + { + "item_code": "FG Item 1", + "qty": 10, + "t_warehouse": "WH 3 - _TC", + "transfer_qty": 10, + "uom": "Nos", + "stock_uom": "Nos", + "conversion_factor": 1.0, + }, + ) + + repack2.save() + repack2.submit() + + self.assertEqual(repack2.items[1].basic_rate, 100) + self.assertEqual(repack2.items[1].amount, 1000) + + transfer1 = make_stock_entry( + item_code="FG Item 1", + purpose="Material Transfer", + qty=10, + from_warehouse="WH 3 - _TC", + to_warehouse="WH 2 - _TC", + posting_date=add_days(nowdate(), -7), + ) + + self.assertEqual(transfer1.items[0].basic_rate, 100) + self.assertEqual(transfer1.items[0].amount, 1000) + + transfer2 = make_stock_entry( + item_code="FG Item 1", + purpose="Material Transfer", + qty=10, + from_warehouse="WH 2 - _TC", + to_warehouse="WH 1 - _TC", + posting_date=add_days(nowdate(), -6), + ) + + self.assertEqual(transfer2.items[0].basic_rate, 100) + self.assertEqual(transfer2.items[0].amount, 1000) + + # Backdated transaction + receipt2 = make_stock_entry( + item_code="Component 1", + rate=200, + purpose="Material Receipt", + qty=10, + to_warehouse="WH 1 - _TC", + posting_date=add_days(nowdate(), -15), + ) + + self.assertEqual(receipt2.items[0].basic_rate, 200) + self.assertEqual(receipt2.items[0].amount, 2000) + + repost_name = frappe.db.get_value( + "Repost Item Valuation", {"voucher_no": receipt2.name, "docstatus": 1}, "name" + ) + + doc = frappe.get_doc("Repost Item Valuation", repost_name) + repost_sl_entries(doc) + + for obj in [repack1, repack2, transfer1, transfer2]: + obj.load_from_db() + + index = 1 if obj.purpose == "Repack" else 0 + self.assertEqual(obj.items[index].basic_rate, 200) + self.assertEqual(obj.items[index].basic_amount, 2000) + def make_serialized_item(**args): args = frappe._dict(args) diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py index ba2d3c1512..01c5aa9e31 100644 --- a/erpnext/stock/stock_ledger.py +++ b/erpnext/stock/stock_ledger.py @@ -250,16 +250,11 @@ def repost_future_sle( data.sle_changed = False i += 1 - if doc and i % 2 == 0: + if doc: update_args_in_repost_item_valuation( doc, i, args, distinct_item_warehouses, affected_transactions ) - if doc and args: - update_args_in_repost_item_valuation( - doc, i, args, distinct_item_warehouses, affected_transactions - ) - def validate_item_warehouse(args): for field in ["item_code", "warehouse", "posting_date", "posting_time"]: @@ -501,7 +496,8 @@ class update_entries_after(object): elif dependant_sle.item_code == self.item_code and dependant_sle.warehouse in self.data: return entries_to_fix else: - return self.append_future_sle_for_dependant(dependant_sle, entries_to_fix) + self.append_future_sle_for_dependant(dependant_sle, entries_to_fix) + return entries_to_fix def update_distinct_item_warehouses(self, dependant_sle): key = (dependant_sle.item_code, dependant_sle.warehouse) @@ -520,14 +516,11 @@ class update_entries_after(object): def append_future_sle_for_dependant(self, dependant_sle, entries_to_fix): self.initialize_previous_data(dependant_sle) - - args = self.data[dependant_sle.warehouse].previous_sle or frappe._dict( - {"item_code": self.item_code, "warehouse": dependant_sle.warehouse} + self.distinct_item_warehouses[(self.item_code, dependant_sle.warehouse)] = frappe._dict( + {"sle": dependant_sle} ) - future_sle_for_dependant = list(self.get_sle_after_datetime(args)) - entries_to_fix.extend(future_sle_for_dependant) - return sorted(entries_to_fix, key=lambda k: k["timestamp"]) + self.new_items_found = True def process_sle(self, sle): from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos