refactor(controllers): convert make_variant_item_code lookup to query builder

make_variant_item_code used a raw frappe.db.sql left join over Item Attribute /
Item Attribute Value. Convert to frappe.qb. The attribute_value comparison
casts the param with cstr() so Postgres does not error on `varchar = numeric`
for numeric attributes (where that side is irrelevant, since numeric_values == 1
already satisfies the OR). MariaDB-identical.

Surgical re-apply: develop's get_attribute_value_renames /
update_variant_attribute_values helpers and the Case import are preserved.
Covered by test_item_variant on both engines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mihir Kandoi
2026-06-21 05:47:32 +05:30
parent 08f39c5345
commit af2f53bee1

View File

@@ -443,13 +443,21 @@ def make_variant_item_code(template_item_code, template_item_name, variant):
abbreviations = []
for attr in variant.attributes:
item_attribute = frappe.db.sql(
"""select i.numeric_values, v.abbr
from `tabItem Attribute` i left join `tabItem Attribute Value` v
on (i.name=v.parent)
where i.name=%(attribute)s and (v.attribute_value=%(attribute_value)s or i.numeric_values = 1)""",
{"attribute": attr.attribute, "attribute_value": attr.attribute_value},
as_dict=True,
ia = frappe.qb.DocType("Item Attribute")
iav = frappe.qb.DocType("Item Attribute Value")
item_attribute = (
frappe.qb.from_(ia)
.left_join(iav)
.on(ia.name == iav.parent)
.select(ia.numeric_values, iav.abbr)
.where(
(ia.name == attr.attribute)
# attribute_value is a varchar column; cast the param to str so postgres doesn't choke on
# `varchar = numeric` for numeric attributes (where this side is irrelevant anyway, since
# numeric_values == 1 already satisfies the OR). Non-numeric values are already strings.
& ((iav.attribute_value == cstr(attr.attribute_value)) | (ia.numeric_values == 1))
)
.run(as_dict=True)
)
if not item_attribute: