fix: price sync kit components + vat_included type bug

- Fix vat_included comparison: GoMag API returns int 1, not str "1",
  causing all prices to be multiplied by TVA again (double TVA)
- Normalize vat_included to string in gomag_client at parse time
- Price sync now processes kit components individually by looking up
  each component's CODMAT as standalone GoMag product
- Add _insert_component_price for components without existing Oracle price
- resolve_mapped_codmats: ROW_NUMBER dedup for CODMATs with multiple
  NOM_ARTICOLE entries, prefer article with current stock
- pack_import_comenzi: merge_or_insert_articol to merge quantities when
  same article appears from kit + individual on same order

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-20 15:07:53 +00:00
parent 0666d6bcdf
commit b221b257a3
5 changed files with 189 additions and 37 deletions

View File

@@ -364,14 +364,26 @@ def validate_and_ensure_prices_dual(codmats: set[str], id_pol_vanzare: int,
return codmat_policy_map
def resolve_mapped_codmats(mapped_skus: set[str], conn) -> dict[str, list[dict]]:
def resolve_mapped_codmats(mapped_skus: set[str], conn,
id_gestiuni: list[int] = None) -> dict[str, list[dict]]:
"""For mapped SKUs, get their underlying CODMATs from ARTICOLE_TERTI + nom_articole.
Uses ROW_NUMBER to pick the best id_articol per (SKU, CODMAT) pair:
prefers article with stock in current month, then MAX(id_articol) as fallback.
This avoids inflating results when a CODMAT has multiple NOM_ARTICOLE entries.
Returns: {sku: [{"codmat": str, "id_articol": int, "cont": str|None, "cantitate_roa": float|None}]}
"""
if not mapped_skus:
return {}
# Build stoc subquery gestiune filter (same pattern as resolve_codmat_ids)
if id_gestiuni:
gest_placeholders = ",".join([f":g{k}" for k in range(len(id_gestiuni))])
stoc_filter = f"AND s.id_gestiune IN ({gest_placeholders})"
else:
stoc_filter = ""
result = {}
sku_list = list(mapped_skus)
@@ -380,12 +392,30 @@ def resolve_mapped_codmats(mapped_skus: set[str], conn) -> dict[str, list[dict]]
batch = sku_list[i:i+500]
placeholders = ",".join([f":s{j}" for j in range(len(batch))])
params = {f"s{j}": sku for j, sku in enumerate(batch)}
if id_gestiuni:
for k, gid in enumerate(id_gestiuni):
params[f"g{k}"] = gid
cur.execute(f"""
SELECT at.sku, at.codmat, na.id_articol, na.cont, at.cantitate_roa
FROM ARTICOLE_TERTI at
JOIN NOM_ARTICOLE na ON na.codmat = at.codmat AND na.sters = 0 AND na.inactiv = 0
WHERE at.sku IN ({placeholders}) AND at.activ = 1 AND at.sters = 0
SELECT sku, codmat, id_articol, cont, cantitate_roa FROM (
SELECT at.sku, at.codmat, na.id_articol, na.cont, at.cantitate_roa,
ROW_NUMBER() OVER (
PARTITION BY at.sku, at.codmat
ORDER BY
CASE WHEN EXISTS (
SELECT 1 FROM stoc s
WHERE s.id_articol = na.id_articol
{stoc_filter}
AND s.an = EXTRACT(YEAR FROM SYSDATE)
AND s.luna = EXTRACT(MONTH FROM SYSDATE)
AND s.cants + s.cant - s.cante > 0
) THEN 0 ELSE 1 END,
na.id_articol DESC
) AS rn
FROM ARTICOLE_TERTI at
JOIN NOM_ARTICOLE na ON na.codmat = at.codmat AND na.sters = 0 AND na.inactiv = 0
WHERE at.sku IN ({placeholders}) AND at.activ = 1 AND at.sters = 0
) WHERE rn = 1
""", params)
for row in cur:
sku = row[0]