fix: kit discount amount + price sync no auto-insert + repackaging kit detection

Kit discount: v_disc_amt is per-kit, not per-unit — remove division by
v_cantitate_web so discount lines compute correctly (e.g. -2 x 5 = -10).

Price sync: stop auto-inserting missing articles into price policies
(was inserting with wrong proc_tvav from GoMag). Log warning instead.

Kit detection: extend to single-component repackagings (cantitate_roa > 1)
in both PL/SQL package and price sync/validation services.

Add repackaging kit pricing test for separate_line and distributed modes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-21 11:04:09 +00:00
parent 10c1afca01
commit 61ae58ef25
6 changed files with 245 additions and 49 deletions

View File

@@ -62,35 +62,6 @@ async def get_price_sync_status() -> dict:
await db.close()
def _insert_component_price(id_articol: int, id_pol: int, price_cu_tva: float,
proc_tvav: float, conn):
"""Insert a new price entry in crm_politici_pret_art for a kit component."""
with conn.cursor() as cur:
cur.execute("""
SELECT PRETURI_CU_TVA, ID_VALUTA FROM CRM_POLITICI_PRETURI WHERE ID_POL = :pol
""", {"pol": id_pol})
row = cur.fetchone()
if not row:
return
preturi_cu_tva, id_valuta = row
if preturi_cu_tva == 1:
pret = price_cu_tva
else:
pret = round(price_cu_tva / proc_tvav, 4)
cur.execute("""
INSERT INTO CRM_POLITICI_PRET_ART
(ID_POL, ID_ARTICOL, PRET, ID_VALUTA,
ID_UTIL, DATAORA, PROC_TVAV, PRETFTVA, PRETCTVA)
VALUES
(:id_pol, :id_articol, :pret, :id_valuta,
-3, SYSDATE, :proc_tvav, 0, 0)
""", {"id_pol": id_pol, "id_articol": id_articol, "pret": pret,
"id_valuta": id_valuta, "proc_tvav": proc_tvav})
conn.commit()
async def run_catalog_price_sync(run_id: str):
global _current_price_sync
async with _price_sync_lock:
@@ -176,7 +147,11 @@ async def run_catalog_price_sync(run_id: str):
price_cu_tva = price * (1 + vat / 100)
# For kits, sync each component individually from standalone GoMag prices
if sku in mapped_data and len(mapped_data[sku]) > 1:
mapped_comps = mapped_data.get(sku, [])
is_kit = len(mapped_comps) > 1 or (
len(mapped_comps) == 1 and (mapped_comps[0].get("cantitate_roa") or 1) > 1
)
if is_kit:
for comp in mapped_data[sku]:
comp_codmat = comp["codmat"]
comp_product = products_by_sku.get(comp_codmat)
@@ -208,21 +183,14 @@ async def run_catalog_price_sync(run_id: str):
updated += 1
_log(f" {comp_codmat}: {result['old_price']:.2f}{result['new_price']:.2f} (kit {sku})")
elif result is None:
# No price entry — insert one with correct price
proc_tvav = 1 + (comp_vat / 100)
await asyncio.to_thread(
_insert_component_price,
comp["id_articol"], comp_pol, comp_price_cu_tva, proc_tvav, conn
)
updated += 1
_log(f" {comp_codmat}: NOU → {comp_price_cu_tva:.2f} (kit {sku})")
_log(f" {comp_codmat}: LIPSESTE din politica {comp_pol} — adauga manual in ROA (kit {sku})")
continue
# Determine id_articol and policy
id_articol = None
cantitate_roa = 1
if sku in mapped_data and len(mapped_data[sku]) == 1:
if sku in mapped_data and len(mapped_data[sku]) == 1 and (mapped_data[sku][0].get("cantitate_roa") or 1) <= 1:
comp = mapped_data[sku][0]
id_articol = comp["id_articol"]
cantitate_roa = comp.get("cantitate_roa") or 1
@@ -236,7 +204,7 @@ async def run_catalog_price_sync(run_id: str):
# Determine policy
cont = None
if sku in mapped_data and len(mapped_data[sku]) == 1:
if sku in mapped_data and len(mapped_data[sku]) == 1 and (mapped_data[sku][0].get("cantitate_roa") or 1) <= 1:
cont = mapped_data[sku][0].get("cont")
elif sku in direct_id_map:
cont = direct_id_map[sku].get("cont")

View File

@@ -450,8 +450,10 @@ def validate_kit_component_prices(mapped_codmat_data: dict, id_pol: int,
try:
with conn.cursor() as cur:
for sku, components in mapped_codmat_data.items():
if len(components) <= 1:
continue # Not a kit
if len(components) == 0:
continue
if len(components) == 1 and (components[0].get("cantitate_roa") or 1) <= 1:
continue # True 1:1 mapping, no kit pricing needed
sku_missing = []
for comp in components:
cont = str(comp.get("cont") or "").strip()