fix: double future qty updates
update_qty_in_future_sle is reprocessing rows which are already
processed by process_sle_against_current_voucher
(cherry picked from commit 7c839c4503)
# Conflicts:
# erpnext/stock/doctype/stock_ledger_entry/test_stock_ledger_entry.py
This commit is contained in:
@@ -683,6 +683,102 @@ class TestStockLedgerEntry(FrappeTestCase):
|
|||||||
# original amount
|
# original amount
|
||||||
self.assertEqual(50, _get_stock_credit(final_consumption))
|
self.assertEqual(50, _get_stock_credit(final_consumption))
|
||||||
|
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
|
def test_tie_breaking(self):
|
||||||
|
frappe.flags.dont_execute_stock_reposts = True
|
||||||
|
self.addCleanup(frappe.flags.pop, "dont_execute_stock_reposts")
|
||||||
|
|
||||||
|
item = make_item().name
|
||||||
|
warehouse = "_Test Warehouse - _TC"
|
||||||
|
|
||||||
|
posting_date = "2022-01-01"
|
||||||
|
posting_time = "00:00:01"
|
||||||
|
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
|
|
||||||
|
def ordered_qty_after_transaction():
|
||||||
|
return (
|
||||||
|
frappe.qb.from_(sle)
|
||||||
|
.select("qty_after_transaction")
|
||||||
|
.where((sle.item_code == item) & (sle.warehouse == warehouse) & (sle.is_cancelled == 0))
|
||||||
|
.orderby(CombineDatetime(sle.posting_date, sle.posting_time))
|
||||||
|
.orderby(sle.creation)
|
||||||
|
).run(pluck=True)
|
||||||
|
|
||||||
|
first = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
to_warehouse=warehouse,
|
||||||
|
qty=10,
|
||||||
|
posting_time=posting_time,
|
||||||
|
posting_date=posting_date,
|
||||||
|
do_not_submit=True,
|
||||||
|
)
|
||||||
|
second = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
to_warehouse=warehouse,
|
||||||
|
qty=1,
|
||||||
|
posting_date=posting_date,
|
||||||
|
posting_time=posting_time,
|
||||||
|
do_not_submit=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
first.submit()
|
||||||
|
second.submit()
|
||||||
|
|
||||||
|
self.assertEqual([10, 11], ordered_qty_after_transaction())
|
||||||
|
|
||||||
|
first.cancel()
|
||||||
|
self.assertEqual([1], ordered_qty_after_transaction())
|
||||||
|
|
||||||
|
backdated = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
to_warehouse=warehouse,
|
||||||
|
qty=1,
|
||||||
|
posting_date="2021-01-01",
|
||||||
|
posting_time=posting_time,
|
||||||
|
)
|
||||||
|
self.assertEqual([1, 2], ordered_qty_after_transaction())
|
||||||
|
|
||||||
|
backdated.cancel()
|
||||||
|
self.assertEqual([1], ordered_qty_after_transaction())
|
||||||
|
|
||||||
|
def test_timestamp_clash(self):
|
||||||
|
|
||||||
|
item = make_item().name
|
||||||
|
warehouse = "_Test Warehouse - _TC"
|
||||||
|
|
||||||
|
reciept = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
to_warehouse=warehouse,
|
||||||
|
qty=100,
|
||||||
|
rate=10,
|
||||||
|
posting_date="2021-01-01",
|
||||||
|
posting_time="01:00:00",
|
||||||
|
)
|
||||||
|
|
||||||
|
consumption = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
from_warehouse=warehouse,
|
||||||
|
qty=50,
|
||||||
|
posting_date="2021-01-01",
|
||||||
|
posting_time="02:00:00.1234", # ms are possible when submitted without editing posting time
|
||||||
|
)
|
||||||
|
|
||||||
|
backdated_receipt = make_stock_entry(
|
||||||
|
item_code=item,
|
||||||
|
to_warehouse=warehouse,
|
||||||
|
qty=100,
|
||||||
|
posting_date="2021-01-01",
|
||||||
|
rate=10,
|
||||||
|
posting_time="02:00:00", # same posting time as consumption but ms part stripped
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
backdated_receipt.cancel()
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Double processing of qty for clashing timestamp.")
|
||||||
|
|
||||||
|
>>>>>>> 7c839c4503 (fix: double future qty updates)
|
||||||
|
|
||||||
def create_repack_entry(**args):
|
def create_repack_entry(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
@@ -1241,6 +1241,8 @@ def update_qty_in_future_sle(args, allow_negative_stock=False):
|
|||||||
datetime_limit_condition = ""
|
datetime_limit_condition = ""
|
||||||
qty_shift = args.actual_qty
|
qty_shift = args.actual_qty
|
||||||
|
|
||||||
|
args["time_format"] = "%H:%i:%s"
|
||||||
|
|
||||||
# find difference/shift in qty caused by stock reconciliation
|
# find difference/shift in qty caused by stock reconciliation
|
||||||
if args.voucher_type == "Stock Reconciliation":
|
if args.voucher_type == "Stock Reconciliation":
|
||||||
qty_shift = get_stock_reco_qty_shift(args)
|
qty_shift = get_stock_reco_qty_shift(args)
|
||||||
@@ -1261,12 +1263,8 @@ def update_qty_in_future_sle(args, allow_negative_stock=False):
|
|||||||
and warehouse = %(warehouse)s
|
and warehouse = %(warehouse)s
|
||||||
and voucher_no != %(voucher_no)s
|
and voucher_no != %(voucher_no)s
|
||||||
and is_cancelled = 0
|
and is_cancelled = 0
|
||||||
and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
|
and timestamp(posting_date, time_format(posting_time, %(time_format)s))
|
||||||
or (
|
> timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s))
|
||||||
timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
|
|
||||||
and creation > %(creation)s
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{datetime_limit_condition}
|
{datetime_limit_condition}
|
||||||
""".format(
|
""".format(
|
||||||
qty_shift=qty_shift, datetime_limit_condition=datetime_limit_condition
|
qty_shift=qty_shift, datetime_limit_condition=datetime_limit_condition
|
||||||
|
|||||||
Reference in New Issue
Block a user