feat(order-detail): show CODMAT for direct SKUs + mapping validations

- Enrich order detail items with NOM_ARTICOLE data for direct SKUs
  (SKU=CODMAT) that have no ARTICOLE_TERTI entry
- Validate CODMAT exists in nomenclator before saving mapping (400)
- Block redundant self-mapping when SKU is already direct CODMAT (409)
- Show "direct" badge in CODMAT column for direct SKUs
- Show info alert in quick map modal for direct SKUs
- Display backend validation errors inline in modal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-17 13:10:20 +00:00
parent f74322beab
commit 7dd39f9712
4 changed files with 93 additions and 10 deletions

View File

@@ -478,6 +478,9 @@ function renderCodmatCell(item) {
}
if (item.codmat_details.length === 1) {
const d = item.codmat_details[0];
if (d.direct) {
return `<code>${esc(d.codmat)}</code> <span class="badge bg-secondary" style="font-size:0.6rem;vertical-align:middle">direct</span>`;
}
return `<code>${esc(d.codmat)}</code>`;
}
return item.codmat_details.map(d =>
@@ -596,7 +599,7 @@ async function openDashOrderDetail(orderNumber) {
if (mobileContainer) {
mobileContainer.innerHTML = '<div class="detail-item-flat">' + items.map((item, idx) => {
const codmatText = item.codmat_details?.length
? item.codmat_details.map(d => `<code>${esc(d.codmat)}</code>`).join(' ')
? item.codmat_details.map(d => `<code>${esc(d.codmat)}</code>${d.direct ? ' <span class="badge bg-secondary" style="font-size:0.55rem">direct</span>' : ''}`).join(' ')
: `<code>${esc(item.codmat || '')}</code>`;
const valoare = (Number(item.price || 0) * Number(item.quantity || 0)).toFixed(2);
return `<div class="dif-item">
@@ -642,15 +645,34 @@ function openQuickMap(sku, productName, orderNumber, itemIdx) {
const container = document.getElementById('qmCodmatLines');
container.innerHTML = '';
// Pre-populate with existing codmat_details if available
// Check if this is a direct SKU (SKU=CODMAT in NOM_ARTICOLE)
const item = (window._detailItems || [])[itemIdx];
const details = item?.codmat_details;
if (details && details.length > 0) {
details.forEach(d => {
addQmCodmatLine({ codmat: d.codmat, cantitate: d.cantitate_roa, procent: d.procent_pret, denumire: d.denumire });
});
} else {
const isDirect = details?.length === 1 && details[0].direct === true;
const directInfo = document.getElementById('qmDirectInfo');
const saveBtn = document.getElementById('qmSaveBtn');
if (isDirect) {
if (directInfo) {
directInfo.innerHTML = `<i class="bi bi-info-circle"></i> SKU = CODMAT direct in nomenclator (<code>${escHtml(details[0].codmat)}</code> — ${escHtml(details[0].denumire || '')}).<br><small class="text-muted">Poti suprascrie cu un alt CODMAT daca e necesar (ex: reambalare).</small>`;
directInfo.style.display = '';
}
if (saveBtn) {
saveBtn.textContent = 'Suprascrie mapare';
}
addQmCodmatLine();
} else {
if (directInfo) directInfo.style.display = 'none';
if (saveBtn) saveBtn.textContent = 'Salveaza';
// 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 });
});
} else {
addQmCodmatLine();
}
}
new bootstrap.Modal(document.getElementById('quickMapModal')).show();
@@ -762,7 +784,9 @@ async function saveQuickMapping() {
if (currentQmOrderNumber) openDashOrderDetail(currentQmOrderNumber);
loadDashOrders();
} else {
alert('Eroare: ' + (data.error || 'Unknown'));
const msg = data.detail || data.error || 'Unknown';
document.getElementById('qmPctWarning').textContent = msg;
document.getElementById('qmPctWarning').style.display = '';
}
} catch (err) {
alert('Eroare: ' + err.message);