refactor(stock): convert LCV serial-rate update to qb + fix cost_center GROUP BY (PG)

Convert the `update tabSerial No set purchase_rate ... where name in (...)` to
frappe.qb.update(isin). Also fix the #39 Postgres bug in
set_landed_cost_voucher_amount: `.select(Sum(applicable_charges), cost_center)`
selected a non-grouped column with no GROUP BY (GroupingError on PG) -> wrap it
in `Max(cost_center)` (deterministic representative; per (receipt_document,
receipt_item) the matching LCV items share a cost_center -> MariaDB-identical).
Covered by the existing landed-cost tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mihir Kandoi
2026-06-20 19:42:00 +05:30
parent c76c0d85ba
commit afb7c25141

View File

@@ -9,7 +9,7 @@ from frappe import _
from frappe.model.document import Document
from frappe.model.meta import get_field_precision
from frappe.query_builder.custom import ConstantColumn
from frappe.query_builder.functions import Sum
from frappe.query_builder.functions import Max, Sum
from frappe.utils import cint, flt
import erpnext
@@ -395,12 +395,12 @@ class LandedCostVoucher(Document):
if not item.is_fixed_asset and item.serial_no:
serial_nos = get_serial_nos(item.serial_no)
if serial_nos:
frappe.db.sql(
"update `tabSerial No` set purchase_rate=%s where name in ({})".format(
", ".join(["%s"] * len(serial_nos))
),
tuple([item.valuation_rate, *serial_nos]),
)
serial_no = frappe.qb.DocType("Serial No")
(
frappe.qb.update(serial_no)
.set(serial_no.purchase_rate, item.valuation_rate)
.where(serial_no.name.isin(serial_nos))
).run()
@frappe.whitelist()
def get_vendor_invoice_amount(self, vendor_invoice: str):
@@ -532,7 +532,7 @@ def set_landed_cost_voucher_amount(doc):
lcv_item = frappe.qb.DocType("Landed Cost Item")
query = (
frappe.qb.from_(lcv_item)
.select(Sum(lcv_item.applicable_charges), lcv_item.cost_center)
.select(Sum(lcv_item.applicable_charges), Max(lcv_item.cost_center))
.where((lcv_item.docstatus == 1) & (lcv_item.receipt_document == doc.name))
)