diff --git a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py index 6561362c3a..b4fac82935 100644 --- a/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py +++ b/erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py @@ -2,7 +2,7 @@ # See license.txt import json -from operator import itemgetter +from datetime import timedelta from uuid import uuid4 import frappe @@ -10,6 +10,7 @@ from frappe.core.page.permission_manager.permission_manager import reset from frappe.custom.doctype.property_setter.property_setter import make_property_setter from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, today +from frappe.utils.data import add_to_date from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note @@ -1067,6 +1068,64 @@ class TestStockLedgerEntry(FrappeTestCase): receipt2 = make_stock_entry(item_code=item, target=warehouse, qty=15, rate=15) self.assertSLEs(receipt2, [{"stock_queue": [[5, 15]], "stock_value_difference": 175}]) + def test_dependent_gl_entry_reposting(self): + def _get_stock_credit(doc): + return frappe.db.get_value( + "GL Entry", + { + "voucher_no": doc.name, + "voucher_type": doc.doctype, + "is_cancelled": 0, + "account": "Stock In Hand - TCP1", + }, + "sum(credit)", + ) + + def _day(days): + return add_to_date(date=today(), days=days) + + item = make_item().name + A = "Stores - TCP1" + B = "Work In Progress - TCP1" + C = "Finished Goods - TCP1" + + make_stock_entry(item_code=item, to_warehouse=A, qty=5, rate=10, posting_date=_day(0)) + make_stock_entry(item_code=item, from_warehouse=A, to_warehouse=B, qty=5, posting_date=_day(1)) + depdendent_consumption = make_stock_entry( + item_code=item, from_warehouse=B, qty=5, posting_date=_day(2) + ) + self.assertEqual(50, _get_stock_credit(depdendent_consumption)) + + # backdated receipt - should trigger GL repost of all previous stock entries + bd_receipt = make_stock_entry( + item_code=item, to_warehouse=A, qty=5, rate=20, posting_date=_day(-1) + ) + self.assertEqual(100, _get_stock_credit(depdendent_consumption)) + + # cancelling receipt should reset it back + bd_receipt.cancel() + self.assertEqual(50, _get_stock_credit(depdendent_consumption)) + + bd_receipt2 = make_stock_entry( + item_code=item, to_warehouse=A, qty=2, rate=20, posting_date=_day(-2) + ) + # total as per FIFO -> 2 * 20 + 3 * 10 = 70 + self.assertEqual(70, _get_stock_credit(depdendent_consumption)) + + # transfer WIP material to final destination and consume it all + depdendent_consumption.cancel() + make_stock_entry(item_code=item, from_warehouse=B, to_warehouse=C, qty=5, posting_date=_day(3)) + final_consumption = make_stock_entry( + item_code=item, from_warehouse=C, qty=5, posting_date=_day(4) + ) + # exact amount gets consumed + self.assertEqual(70, _get_stock_credit(final_consumption)) + + # cancel original backdated receipt - should repost A -> B -> C + bd_receipt2.cancel() + # original amount + self.assertEqual(50, _get_stock_credit(final_consumption)) + def create_repack_entry(**args): args = frappe._dict(args)