diff --git a/TODOS.md b/TODOS.md
index 8022878..685aff7 100644
--- a/TODOS.md
+++ b/TODOS.md
@@ -27,10 +27,3 @@
**Effort:** S (human: ~2h / CC: ~10min)
**Context:** TIER 2 matched county+city without street, reusing VFP-era addresses with wrong streets. After removal (2026-04-06), new imports create correct addresses. Old wrong addresses stay. Could identify them by: address has id_loc but no linked order rows, and was last modified before 2026-04-06.
**Depends on:** TIER 2 removal deployed and verified.
-
-## P3: Extract match-column badge styles to CSS classes
-**What:** Replace inline styles on Kit and Disc. badges (in shared.js) with CSS classes (e.g., `.match-badge-kit`, `.match-badge-disc`).
-**Why:** Currently both badges use identical inline `style="background:var(--X-light);color:var(--X-text);font-size:10px;padding:2px 6px"`. If a 3rd badge type appears, inline styles become a maintenance burden.
-**Effort:** XS (human: ~30min / CC: ~5min)
-**Context:** Low priority. Two inline-styled badges is fine. Trigger: when a 3rd badge type is needed in the price match column.
-**Depends on:** Quantity discount feature shipped.
diff --git a/api/app/routers/sync.py b/api/app/routers/sync.py
index 335ff72..b41513b 100644
--- a/api/app/routers/sync.py
+++ b/api/app/routers/sync.py
@@ -46,6 +46,9 @@ async def backfill_price_match():
from ..database import get_sqlite
db = await get_sqlite()
try:
+ # Reset all cached price_match to re-evaluate with current logic
+ await db.execute("UPDATE orders SET price_match = NULL WHERE price_match IS NOT NULL")
+ await db.commit()
cursor = await db.execute("""
SELECT order_number FROM orders
WHERE status IN ('IMPORTED', 'ALREADY_IMPORTED')
@@ -465,9 +468,6 @@ async def order_detail(order_number: str):
item["price_match"] = pi.get("match")
if pi.get("kit"):
item["kit"] = True
- if pi.get("quantity_discount"):
- item["quantity_discount"] = True
- item["baseprice"] = pi.get("baseprice")
order_price_check = price_data.get("summary", {})
# Cache price_match in SQLite if changed
if order_price_check.get("oracle_available") is not False:
diff --git a/api/app/services/validation_service.py b/api/app/services/validation_service.py
index bca7f02..b70733d 100644
--- a/api/app/services/validation_service.py
+++ b/api/app/services/validation_service.py
@@ -714,13 +714,6 @@ def get_prices_for_order(items: list[dict], app_settings: dict, conn=None) -> di
result_items[idx]["kit"] = True
continue
- # Quantity discount: baseprice > price means GoMag applied a volume discount
- baseprice = float(item.get("baseprice") or 0)
- if baseprice > 0 and baseprice > pret_gomag + 0.01:
- result_items[idx]["quantity_discount"] = True
- result_items[idx]["baseprice"] = baseprice
- continue
-
pret_roa_total = 0.0
all_resolved = True
@@ -766,7 +759,7 @@ def get_prices_for_order(items: list[dict], app_settings: dict, conn=None) -> di
continue
pret_roa = round(pret_roa_total, 4)
- match = abs(pret_gomag - pret_roa) < 0.01
+ match = pret_gomag <= pret_roa + 0.01
result_items[idx]["pret_roa"] = pret_roa
result_items[idx]["match"] = match
checked += 1
diff --git a/api/app/static/js/dashboard.js b/api/app/static/js/dashboard.js
index 974f70b..773ec74 100644
--- a/api/app/static/js/dashboard.js
+++ b/api/app/static/js/dashboard.js
@@ -510,7 +510,7 @@ function diffDots(o, mobile) {
if (o.address_mismatch===1)
d += ``;
if (o.price_match===false)
- d += ``;
+ d += ``;
return d;
}
diff --git a/api/app/static/js/shared.js b/api/app/static/js/shared.js
index 99bc467..0a4829d 100644
--- a/api/app/static/js/shared.js
+++ b/api/app/static/js/shared.js
@@ -614,11 +614,9 @@ async function renderOrderDetailModal(orderNumber, opts) {
const valoare = (Number(item.price || 0) * Number(item.quantity || 0));
const clickAttr = opts.onQuickMap ? `onclick="_sharedModalQuickMap('${esc(item.sku)}','${esc(item.product_name||'')}','${esc(orderNumber)}',${idx})"` : '';
const priceInfo = { pret_roa: item.pret_roa, match: item.price_match };
- const priceMismatchHtml = item.quantity_discount
- ? `
Disc. ${fmtNum(item.baseprice)} ${fmtNum(item.price)} lei
`
- : (priceInfo.match === false
- ? `ROA: ${fmtNum(priceInfo.pret_roa)} lei
`
- : '');
+ const priceMismatchHtml = priceInfo.match === false
+ ? `ROA: ${fmtNum(priceInfo.pret_roa)} lei
`
+ : '';
return `
${esc(item.sku)}
@@ -690,10 +688,6 @@ async function renderOrderDetailModal(orderNumber, opts) {
if (item.kit) {
matchDot = 'Kit';
rowStyle = '';
- } else if (item.quantity_discount) {
- const bpTitle = item.baseprice ? `Catalog: ${fmtNum(item.baseprice)} lei` : 'Discount GoMag';
- matchDot = `Disc.`;
- rowStyle = '';
} else if (priceInfo.pret_roa == null && priceInfo.match == null) {
matchDot = '';
rowStyle = '';
@@ -709,7 +703,7 @@ async function renderOrderDetailModal(orderNumber, opts) {
${esc(item.product_name || '-')} |
${renderCodmatCell(item)} |
${item.quantity || 0} |
- ${item.quantity_discount && item.baseprice ? `${fmtNum(item.baseprice)} ${fmtNum(item.price)}` : (item.price != null ? fmtNum(item.price) : '-')} |
+ ${item.price != null ? fmtNum(item.price) : '-'} |
${pretRoaHtml} |
${item.vat != null ? Number(item.vat) : '-'} |
${fmtNum(valoare)} |
diff --git a/api/app/templates/base.html b/api/app/templates/base.html
index 0ac16f9..10d34bf 100644
--- a/api/app/templates/base.html
+++ b/api/app/templates/base.html
@@ -168,7 +168,7 @@
-
+
+
{% endblock %}
diff --git a/api/tests/test_business_rules.py b/api/tests/test_business_rules.py
index b9a23cd..4e15105 100644
--- a/api/tests/test_business_rules.py
+++ b/api/tests/test_business_rules.py
@@ -636,49 +636,39 @@ class TestGetPricesForOrderCantitateRoa:
assert result["summary"]["mismatches"] == 0
-class TestGetPricesForOrderQuantityDiscount:
- """baseprice > price means GoMag applied a discount — skip price comparison."""
+class TestGetPricesDirectionalMatch:
+ """Price match is directional: gomag <= roa is OK, gomag > roa is mismatch."""
- def test_discount_detected(self):
- """baseprice > price: quantity_discount=True, match=None, mismatches=0."""
+ def test_gomag_below_roa_is_match(self):
+ """GoMag price lower than ROA (promo/volume discount) → match=True."""
items = [{"sku": "SKU-DISC", "price": 28.59, "baseprice": 33.0, "quantity": 48,
"codmat_details": [{"codmat": "COD1", "cantitate_roa": 1,
"id_articol": 100, "cont": "345"}]}]
conn = _mock_oracle_conn(pol_cu_tva=True, price_map={100: (28.99, 1.19)})
result = get_prices_for_order(items, {"id_pol": "1"}, conn=conn)
- assert result["items"][0].get("quantity_discount") is True
- assert result["items"][0]["match"] is None
+ assert result["items"][0]["match"] is True
+ assert result["items"][0]["pret_roa"] == 28.99
assert result["summary"]["mismatches"] == 0
- def test_no_discount_when_baseprice_equals_price(self):
- """baseprice == price: normal comparison."""
- items = [{"sku": "SKU-FULL", "price": 28.99, "baseprice": 28.99, "quantity": 1,
+ def test_gomag_above_roa_is_mismatch(self):
+ """GoMag price higher than ROA → match=False, mismatch counted."""
+ items = [{"sku": "SKU-HIGH", "price": 30.00, "quantity": 1,
"codmat_details": [{"codmat": "COD2", "cantitate_roa": 1,
"id_articol": 200, "cont": "345"}]}]
conn = _mock_oracle_conn(pol_cu_tva=True, price_map={200: (28.99, 1.19)})
result = get_prices_for_order(items, {"id_pol": "1"}, conn=conn)
- assert result["items"][0].get("quantity_discount") is not True
- assert result["items"][0]["match"] is True
+ assert result["items"][0]["match"] is False
+ assert result["summary"]["mismatches"] == 1
- def test_no_discount_when_baseprice_missing(self):
- """baseprice=0 (missing): normal comparison."""
- items = [{"sku": "SKU-OLD", "price": 28.99, "quantity": 1,
+ def test_gomag_equals_roa_is_match(self):
+ """GoMag price equals ROA → match=True."""
+ items = [{"sku": "SKU-FULL", "price": 28.99, "quantity": 1,
"codmat_details": [{"codmat": "COD3", "cantitate_roa": 1,
"id_articol": 300, "cont": "345"}]}]
conn = _mock_oracle_conn(pol_cu_tva=True, price_map={300: (28.99, 1.19)})
result = get_prices_for_order(items, {"id_pol": "1"}, conn=conn)
- assert result["items"][0].get("quantity_discount") is not True
assert result["items"][0]["match"] is True
-
- def test_kit_takes_precedence_over_discount(self):
- """Kit check runs before discount check — kit wins."""
- items = [{"sku": "SKU-KITDISC", "price": 20.0, "baseprice": 25.0, "quantity": 10,
- "codmat_details": [{"codmat": "COD4", "cantitate_roa": 2,
- "id_articol": 400, "cont": "345"}]}]
- conn = _mock_oracle_conn(pol_cu_tva=True, price_map={400: (10.0, 1.19)})
- result = get_prices_for_order(items, {"id_pol": "1"}, conn=conn)
- assert result["items"][0].get("kit") is True
- assert result["items"][0].get("quantity_discount") is not True
+ assert result["summary"]["mismatches"] == 0
# ── normalize_company_name (II, PFA, INTREPRINDERE INDIVIDUALA) ──