diff --git a/CLAUDE.md b/CLAUDE.md
index ecb8a4e..19e9237 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -34,7 +34,7 @@ python api/test_integration.py # cu Oracle
1. Download GoMag API → JSON → parse → validate SKU-uri → import Oracle
2. Ordinea: **parteneri** (cauta/creeaza) → **adrese** → **comanda** → **factura cache**
3. SKU lookup: ARTICOLE_TERTI (mapped) are prioritate fata de NOM_ARTICOLE (direct)
-4. Complex sets: un SKU → multiple CODMAT-uri cu `procent_pret` (trebuie sa fie sum=100%)
+4. Complex sets (kituri/pachete): un SKU → multiple CODMAT-uri cu `cantitate_roa`; preturile se preiau din lista de preturi Oracle
5. Comenzi anulate (GoMag statusId=7): verifica daca au factura inainte de stergere din Oracle
### Statusuri comenzi
@@ -51,6 +51,11 @@ python api/test_integration.py # cu Oracle
- Dual policy: articolele sunt rutate la `id_pol_vanzare` sau `id_pol_productie` pe baza contului contabil (341/345 = productie)
- Daca pretul lipseste, se insereaza automat pret=0
+### Dashboard paginare
+- Contorul din paginare arata **totalul comenzilor** din perioada selectata (ex: "378 comenzi"), NU doar cele filtrate
+- Butoanele de filtru (Importat, Omise, Erori, Facturate, Nefacturate, Anulate) arata fiecare cate comenzi are pe langa total
+- Aceasta este comportamentul dorit: userul vede cate comenzi totale sunt, din care cate importate, cu erori etc.
+
### Invoice cache
- Coloanele `factura_*` pe `orders` (SQLite), populate lazy din Oracle (`vanzari WHERE sters=0`)
- Refresh complet: verifica facturi noi + facturi sterse + comenzi sterse din ROA
diff --git a/api/app/services/gomag_client.py b/api/app/services/gomag_client.py
index e1f7bd4..3ca523a 100644
--- a/api/app/services/gomag_client.py
+++ b/api/app/services/gomag_client.py
@@ -157,7 +157,12 @@ async def download_products(
products = data.get("products", [])
if isinstance(products, dict):
- products = [products]
+ # GoMag returns products as {"1": {...}, "2": {...}} dict
+ first_val = next(iter(products.values()), None) if products else None
+ if isinstance(first_val, dict):
+ products = list(products.values())
+ else:
+ products = [products]
if isinstance(products, list):
for p in products:
if isinstance(p, dict) and p.get("sku"):
diff --git a/api/app/static/js/dashboard.js b/api/app/static/js/dashboard.js
index 215b26d..3f7b2fc 100644
--- a/api/app/static/js/dashboard.js
+++ b/api/app/static/js/dashboard.js
@@ -484,7 +484,7 @@ function renderCodmatCell(item) {
return `${esc(d.codmat)}`;
}
return item.codmat_details.map(d =>
- `
${esc(d.codmat)} \xd7${d.cantitate_roa} (${d.procent_pret}%)
`
+ `${esc(d.codmat)} \xd7${d.cantitate_roa}
`
).join('');
}
@@ -792,7 +792,7 @@ function openQuickMap(sku, productName, orderNumber, itemIdx) {
// Pre-populate with existing codmat_details if available
if (details && details.length > 0) {
details.forEach(d => {
- addQmCodmatLine({ codmat: d.codmat, cantitate: d.cantitate_roa, procent: d.procent_pret, denumire: d.denumire });
+ addQmCodmatLine({ codmat: d.codmat, cantitate: d.cantitate_roa, denumire: d.denumire });
});
} else {
addQmCodmatLine();
@@ -807,7 +807,6 @@ function addQmCodmatLine(prefill) {
const idx = container.children.length;
const codmatVal = prefill?.codmat || '';
const cantVal = prefill?.cantitate || 1;
- const pctVal = prefill?.procent || 100;
const denumireVal = prefill?.denumire || '';
const div = document.createElement('div');
div.className = 'qm-line';
@@ -818,7 +817,6 @@ function addQmCodmatLine(prefill) {
-
${idx > 0 ? `` : ''}
${escHtml(denumireVal)}
@@ -870,30 +868,19 @@ async function saveQuickMapping() {
for (const line of lines) {
const codmat = line.querySelector('.qm-codmat').value.trim();
const cantitate = parseFloat(line.querySelector('.qm-cantitate').value) || 1;
- const procent = parseFloat(line.querySelector('.qm-procent').value) || 100;
if (!codmat) continue;
- mappings.push({ codmat, cantitate_roa: cantitate, procent_pret: procent });
+ mappings.push({ codmat, cantitate_roa: cantitate });
}
if (mappings.length === 0) { alert('Selecteaza cel putin un CODMAT'); return; }
- if (mappings.length > 1) {
- const totalPct = mappings.reduce((s, m) => s + m.procent_pret, 0);
- if (Math.abs(totalPct - 100) > 0.01) {
- document.getElementById('qmPctWarning').textContent = `Suma procentelor trebuie sa fie 100% (actual: ${totalPct.toFixed(2)}%)`;
- document.getElementById('qmPctWarning').style.display = '';
- return;
- }
- }
- document.getElementById('qmPctWarning').style.display = 'none';
-
try {
let res;
if (mappings.length === 1) {
res = await fetch('/api/mappings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ sku: currentQmSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa, procent_pret: mappings[0].procent_pret })
+ body: JSON.stringify({ sku: currentQmSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa })
});
} else {
res = await fetch('/api/mappings/batch', {
diff --git a/api/app/static/js/logs.js b/api/app/static/js/logs.js
index cc17658..6cf8a97 100644
--- a/api/app/static/js/logs.js
+++ b/api/app/static/js/logs.js
@@ -310,7 +310,7 @@ function renderCodmatCell(item) {
}
// Multi-CODMAT: compact list
return item.codmat_details.map(d =>
- `${esc(d.codmat)} \xd7${d.cantitate_roa} (${d.procent_pret}%)
`
+ `${esc(d.codmat)} \xd7${d.cantitate_roa}
`
).join('');
}
@@ -456,11 +456,7 @@ function addQmCodmatLine() {
-
-
-
-
-
@@ -513,31 +509,19 @@ async function saveQuickMapping() {
for (const line of lines) {
const codmat = line.querySelector('.qm-codmat').value.trim();
const cantitate = parseFloat(line.querySelector('.qm-cantitate').value) || 1;
- const procent = parseFloat(line.querySelector('.qm-procent').value) || 100;
if (!codmat) continue;
- mappings.push({ codmat, cantitate_roa: cantitate, procent_pret: procent });
+ mappings.push({ codmat, cantitate_roa: cantitate });
}
if (mappings.length === 0) { alert('Selecteaza cel putin un CODMAT'); return; }
- // Validate percentage sum for multi-line
- if (mappings.length > 1) {
- const totalPct = mappings.reduce((s, m) => s + m.procent_pret, 0);
- if (Math.abs(totalPct - 100) > 0.01) {
- document.getElementById('qmPctWarning').textContent = `Suma procentelor trebuie sa fie 100% (actual: ${totalPct.toFixed(2)}%)`;
- document.getElementById('qmPctWarning').style.display = '';
- return;
- }
- }
- document.getElementById('qmPctWarning').style.display = 'none';
-
try {
let res;
if (mappings.length === 1) {
res = await fetch('/api/mappings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ sku: currentQmSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa, procent_pret: mappings[0].procent_pret })
+ body: JSON.stringify({ sku: currentQmSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa })
});
} else {
res = await fetch('/api/mappings/batch', {
diff --git a/api/app/templates/dashboard.html b/api/app/templates/dashboard.html
index 96af8a2..2c5ab21 100644
--- a/api/app/templates/dashboard.html
+++ b/api/app/templates/dashboard.html
@@ -201,5 +201,5 @@
{% endblock %}
{% block scripts %}
-
+
{% endblock %}
diff --git a/api/app/templates/logs.html b/api/app/templates/logs.html
index a10c9ce..1f8b7ef 100644
--- a/api/app/templates/logs.html
+++ b/api/app/templates/logs.html
@@ -183,5 +183,5 @@
{% endblock %}
{% block scripts %}
-
+
{% endblock %}
diff --git a/api/app/templates/missing_skus.html b/api/app/templates/missing_skus.html
index fe3c35a..9a2719c 100644
--- a/api/app/templates/missing_skus.html
+++ b/api/app/templates/missing_skus.html
@@ -289,9 +289,6 @@ function addMapCodmatLine() {
-
-
-
@@ -343,30 +340,19 @@ async function saveQuickMap() {
for (const line of lines) {
const codmat = line.querySelector('.mc-codmat').value.trim();
const cantitate = parseFloat(line.querySelector('.mc-cantitate').value) || 1;
- const procent = parseFloat(line.querySelector('.mc-procent').value) || 100;
if (!codmat) continue;
- mappings.push({ codmat, cantitate_roa: cantitate, procent_pret: procent });
+ mappings.push({ codmat, cantitate_roa: cantitate });
}
if (mappings.length === 0) { alert('Selecteaza cel putin un CODMAT'); return; }
- if (mappings.length > 1) {
- const totalPct = mappings.reduce((s, m) => s + m.procent_pret, 0);
- if (Math.abs(totalPct - 100) > 0.01) {
- document.getElementById('mapPctWarning').textContent = `Suma procentelor trebuie sa fie 100% (actual: ${totalPct.toFixed(2)}%)`;
- document.getElementById('mapPctWarning').style.display = '';
- return;
- }
- }
- document.getElementById('mapPctWarning').style.display = 'none';
-
try {
let res;
if (mappings.length === 1) {
res = await fetch('/api/mappings', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ sku: currentMapSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa, procent_pret: mappings[0].procent_pret })
+ body: JSON.stringify({ sku: currentMapSku, codmat: mappings[0].codmat, cantitate_roa: mappings[0].cantitate_roa })
});
} else {
res = await fetch('/api/mappings/batch', {