fix: double future qty updates
update_qty_in_future_sle is reprocessing rows which are already
processed by process_sle_against_current_voucher
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 5850ec7..4e2fc83 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
@@ -1183,6 +1183,42 @@
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.")
+
def create_repack_entry(**args):
args = frappe._dict(args)
diff --git a/erpnext/stock/stock_ledger.py b/erpnext/stock/stock_ledger.py
index 7e5c231..5a270d1 100644
--- a/erpnext/stock/stock_ledger.py
+++ b/erpnext/stock/stock_ledger.py
@@ -1303,6 +1303,8 @@
datetime_limit_condition = ""
qty_shift = args.actual_qty
+ args["time_format"] = "%H:%i:%s"
+
# find difference/shift in qty caused by stock reconciliation
if args.voucher_type == "Stock Reconciliation":
qty_shift = get_stock_reco_qty_shift(args)
@@ -1323,12 +1325,8 @@
and warehouse = %(warehouse)s
and voucher_no != %(voucher_no)s
and is_cancelled = 0
- and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
- or (
- timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
- and creation > %(creation)s
- )
- )
+ and timestamp(posting_date, time_format(posting_time, %(time_format)s))
+ > timestamp(%(posting_date)s, time_format(%(posting_time)s, %(time_format)s))
{datetime_limit_condition}
""".format(
qty_shift=qty_shift, datetime_limit_condition=datetime_limit_condition