mirror of
https://github.com/frappe/erpnext.git
synced 2026-08-13 22:51:49 +00:00
fix(stock): make Repost Item Valuation dedup Postgres-valid (TIMESTAMP→CombineDatetime)
deduplicate_similar_repost used a raw UPDATE with the MySQL-only two-arg TIMESTAMP(posting_date, posting_time) constructor, which is invalid on Postgres. Convert the UPDATE to frappe.qb and replace TIMESTAMP() with CombineDatetime on the column (portable, and preserves the original NULL semantics so rows with a NULL posting_time stay excluded); the right-hand side is this document's own always-set posting datetime, computed in Python via get_combine_datetime to avoid wrapping literals in a SQL datetime function. Surgical re-apply: develop's recalculate_valuation_rate field / _recalculate_valuation_rate method / repost() branch are left intact. The existing test_repost_item_valuation.test_deduplication directly exercises this UPDATE; it errors on develop's Postgres and now passes on MariaDB and Postgres. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,7 @@ from erpnext.stock.stock_ledger import (
|
||||
get_items_to_be_repost,
|
||||
repost_future_sle,
|
||||
)
|
||||
from erpnext.stock.utils import get_combine_datetime
|
||||
|
||||
RecoverableErrors = (JobTimeoutException, QueryDeadlockError, QueryTimeoutError)
|
||||
|
||||
@@ -321,28 +322,26 @@ class RepostItemValuation(Document):
|
||||
if self.based_on != "Item and Warehouse":
|
||||
return
|
||||
|
||||
filters = {
|
||||
"item_code": self.item_code,
|
||||
"warehouse": self.warehouse,
|
||||
"name": self.name,
|
||||
"posting_date": self.posting_date,
|
||||
"posting_time": self.posting_time,
|
||||
}
|
||||
|
||||
frappe.db.sql(
|
||||
"""
|
||||
update `tabRepost Item Valuation`
|
||||
set status = 'Skipped'
|
||||
WHERE item_code = %(item_code)s
|
||||
and warehouse = %(warehouse)s
|
||||
and name != %(name)s
|
||||
and TIMESTAMP(posting_date, posting_time) > TIMESTAMP(%(posting_date)s, %(posting_time)s)
|
||||
and docstatus = 1
|
||||
and status = 'Queued'
|
||||
and based_on = 'Item and Warehouse'
|
||||
""",
|
||||
filters,
|
||||
)
|
||||
riv = frappe.qb.DocType("Repost Item Valuation")
|
||||
(
|
||||
frappe.qb.update(riv)
|
||||
.set(riv.status, "Skipped")
|
||||
.where(
|
||||
(riv.item_code == self.item_code)
|
||||
& (riv.warehouse == self.warehouse)
|
||||
& (riv.name != self.name)
|
||||
# CombineDatetime on the column is portable (TIMESTAMP() is MySQL-only) and keeps the
|
||||
# original NULL semantics (rows with NULL posting_time stay excluded); the RHS is this
|
||||
# doc's own (always-set) posting datetime, computed in Python.
|
||||
& (
|
||||
CombineDatetime(riv.posting_date, riv.posting_time)
|
||||
> get_combine_datetime(self.posting_date, self.posting_time)
|
||||
)
|
||||
& (riv.docstatus == 1)
|
||||
& (riv.status == "Queued")
|
||||
& (riv.based_on == "Item and Warehouse")
|
||||
)
|
||||
).run()
|
||||
|
||||
def _recalculate_valuation_rate(self):
|
||||
doc = frappe.get_doc(self.voucher_type, self.voucher_no)
|
||||
|
||||
Reference in New Issue
Block a user