chore: commit all pending changes including deploy scripts and Windows config

- deploy.ps1, iis-web.config: Windows Server deployment scripts
- api/app/routers/sync.py, dashboard.py: router updates
- api/app/services/import_service.py, sync_service.py: service updates
- api/app/static/css/style.css, js/*.js: UI updates
- api/database-scripts/08_PACK_FACTURARE.pck: Oracle package
- .gitignore: add .gittoken
- CLAUDE.md, agent configs: documentation updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Claude Agent
2026-03-16 15:05:04 +00:00
parent ee60a17f00
commit a9d0cead79
16 changed files with 17798 additions and 329 deletions

View File

@@ -10,6 +10,10 @@ let currentQmOrderNumber = '';
let ordersSortColumn = 'order_date';
let ordersSortDirection = 'desc';
function fmtCost(v) {
return v > 0 ? Number(v).toFixed(2) : '';
}
function fmtDuration(startedAt, finishedAt) {
if (!startedAt || !finishedAt) return '-';
const diffMs = new Date(finishedAt) - new Date(startedAt);
@@ -151,19 +155,21 @@ async function loadRunOrders(runId, statusFilter, page) {
const orders = data.orders || [];
if (orders.length === 0) {
tbody.innerHTML = '<tr><td colspan="7" class="text-center text-muted py-3">Nicio comanda</td></tr>';
tbody.innerHTML = '<tr><td colspan="9" class="text-center text-muted py-3">Nicio comanda</td></tr>';
} else {
tbody.innerHTML = orders.map((o, i) => {
const dateStr = fmtDate(o.order_date);
const orderTotal = o.order_total != null ? Number(o.order_total).toFixed(2) : '-';
return `<tr style="cursor:pointer" onclick="openOrderDetail('${esc(o.order_number)}')">
<td>${statusDot(o.status)}</td>
<td>${(ordersPage - 1) * 50 + i + 1}</td>
<td>${dateStr}</td>
<td class="text-nowrap">${dateStr}</td>
<td><code>${esc(o.order_number)}</code></td>
<td>${esc(o.customer_name)}</td>
<td class="fw-bold">${esc(o.customer_name)}</td>
<td>${o.items_count || 0}</td>
<td class="text-end">${orderTotal}</td>
<td class="text-nowrap">${statusDot(o.status)} ${logStatusText(o.status)}</td>
<td class="text-end text-muted">${fmtCost(o.delivery_cost)}</td>
<td class="text-end text-muted">${fmtCost(o.discount_total)}</td>
<td class="text-end fw-bold">${orderTotal}</td>
</tr>`;
}).join('');
}
@@ -185,8 +191,8 @@ async function loadRunOrders(runId, statusFilter, page) {
return `<div class="flat-row" onclick="openOrderDetail('${esc(o.order_number)}')" style="font-size:0.875rem">
${statusDot(o.status)}
<span style="color:#6b7280" class="text-nowrap">${dateFmt}</span>
<span class="grow truncate">${esc(o.customer_name || '—')}</span>
<span class="text-nowrap">x${o.items_count || 0}${totalStr ? ' · ' + totalStr : ''}</span>
<span class="grow truncate fw-bold">${esc(o.customer_name || '—')}</span>
<span class="text-nowrap">x${o.items_count || 0}${totalStr ? ' · <strong>' + totalStr + '</strong>' : ''}</span>
</div>`;
}).join('');
}
@@ -222,7 +228,7 @@ async function loadRunOrders(runId, statusFilter, page) {
}
} catch (err) {
document.getElementById('runOrdersBody').innerHTML =
`<tr><td colspan="6" class="text-center text-danger">${esc(err.message)}</td></tr>`;
`<tr><td colspan="9" class="text-center text-danger">${esc(err.message)}</td></tr>`;
}
}
@@ -318,16 +324,12 @@ async function openOrderDetail(orderNumber) {
document.getElementById('detailIdPartener').textContent = '-';
document.getElementById('detailIdAdresaFact').textContent = '-';
document.getElementById('detailIdAdresaLivr').textContent = '-';
document.getElementById('detailItemsBody').innerHTML = '<tr><td colspan="8" class="text-center">Se incarca...</td></tr>';
document.getElementById('detailItemsBody').innerHTML = '<tr><td colspan="6" class="text-center">Se incarca...</td></tr>';
document.getElementById('detailError').style.display = 'none';
const detailItemsTotal = document.getElementById('detailItemsTotal');
if (detailItemsTotal) detailItemsTotal.textContent = '-';
const detailOrderTotal = document.getElementById('detailOrderTotal');
if (detailOrderTotal) detailOrderTotal.textContent = '-';
const deliveryWrap = document.getElementById('detailDeliveryWrap');
if (deliveryWrap) deliveryWrap.style.display = 'none';
const discountWrap = document.getElementById('detailDiscountWrap');
if (discountWrap) discountWrap.style.display = 'none';
const mobileContainer = document.getElementById('detailItemsMobile');
if (mobileContainer) mobileContainer.innerHTML = '';
@@ -359,25 +361,15 @@ async function openOrderDetail(orderNumber) {
document.getElementById('detailError').style.display = '';
}
// Show delivery cost
const dlvWrap = document.getElementById('detailDeliveryWrap');
const dlvEl = document.getElementById('detailDeliveryCost');
if (order.delivery_cost && Number(order.delivery_cost) > 0) {
if (dlvEl) dlvEl.textContent = Number(order.delivery_cost).toFixed(2) + ' lei';
if (dlvWrap) dlvWrap.style.display = '';
}
if (dlvEl) dlvEl.textContent = order.delivery_cost > 0 ? Number(order.delivery_cost).toFixed(2) + ' lei' : '';
// Show discount
const dscWrap = document.getElementById('detailDiscountWrap');
const dscEl = document.getElementById('detailDiscount');
if (order.discount_total && Number(order.discount_total) > 0) {
if (dscEl) dscEl.textContent = '-' + Number(order.discount_total).toFixed(2) + ' lei';
if (dscWrap) dscWrap.style.display = '';
}
if (dscEl) dscEl.textContent = order.discount_total > 0 ? '' + Number(order.discount_total).toFixed(2) + ' lei' : '';
const items = data.items || [];
if (items.length === 0) {
document.getElementById('detailItemsBody').innerHTML = '<tr><td colspan="8" class="text-center text-muted">Niciun articol</td></tr>';
document.getElementById('detailItemsBody').innerHTML = '<tr><td colspan="6" class="text-center text-muted">Niciun articol</td></tr>';
return;
}
@@ -386,53 +378,38 @@ async function openOrderDetail(orderNumber) {
document.getElementById('detailItemsTotal').textContent = itemsTotal.toFixed(2) + ' lei';
document.getElementById('detailOrderTotal').textContent = order.order_total != null ? Number(order.order_total).toFixed(2) + ' lei' : '-';
// Mobile article cards
// Mobile article flat list
const mobileContainer = document.getElementById('detailItemsMobile');
if (mobileContainer) {
mobileContainer.innerHTML = items.map(item => {
let statusLabel = '';
switch (item.mapping_status) {
case 'mapped': statusLabel = '<span class="badge bg-success">Mapat</span>'; break;
case 'direct': statusLabel = '<span class="badge bg-info">Direct</span>'; break;
case 'missing': statusLabel = '<span class="badge bg-warning">Lipsa</span>'; break;
default: statusLabel = '<span class="badge bg-secondary">?</span>';
}
const codmat = item.codmat || '-';
return `<div class="detail-item-card">
<div class="card-sku">${esc(item.sku)}</div>
<div class="card-name">${esc(item.product_name || '-')}</div>
<div class="card-details">
<span>x${item.quantity || 0}</span>
<span>${item.price != null ? Number(item.price).toFixed(2) : '-'} lei</span>
<span><code>${esc(codmat)}</code></span>
<span>${statusLabel}</span>
mobileContainer.innerHTML = '<div class="detail-item-flat">' + items.map((item, idx) => {
const codmatList = item.codmat_details?.length
? item.codmat_details.map(d => `<span class="dif-codmat-link" onclick="openQuickMap('${esc(item.sku)}','${esc(item.product_name||'')}','${esc(orderNumber)}')">${esc(d.codmat)}</span>`).join(' ')
: `<span class="dif-codmat-link" onclick="openQuickMap('${esc(item.sku)}','${esc(item.product_name||'')}','${esc(orderNumber)}')">${esc(item.codmat || '')}</span>`;
const valoare = (Number(item.price || 0) * Number(item.quantity || 0)).toFixed(2);
return `<div class="dif-item">
<div class="dif-row">
<span class="dif-sku">${esc(item.sku)}</span>
${codmatList}
</div>
<div class="dif-row">
<span class="dif-name">${esc(item.product_name || '')}</span>
<span class="dif-qty">x${item.quantity || 0}</span>
<span class="dif-val">${valoare} lei</span>
</div>
</div>`;
}).join('');
}).join('') + '</div>';
}
document.getElementById('detailItemsBody').innerHTML = items.map(item => {
let statusBadge;
switch (item.mapping_status) {
case 'mapped': statusBadge = '<span class="badge bg-success">Mapat</span>'; break;
case 'direct': statusBadge = '<span class="badge bg-info">Direct</span>'; break;
case 'missing': statusBadge = '<span class="badge bg-warning">Lipsa</span>'; break;
default: statusBadge = '<span class="badge bg-secondary">?</span>';
}
const action = item.mapping_status === 'missing'
? `<a href="#" class="btn-map-icon" onclick="openQuickMap('${esc(item.sku)}', '${esc(item.product_name || '')}', '${esc(orderNumber)}'); return false;" title="Mapeaza"><i class="bi bi-link-45deg"></i></a>`
: '';
const valoare = (Number(item.price || 0) * Number(item.quantity || 0)).toFixed(2);
const codmatCell = `<span class="codmat-link" onclick="openQuickMap('${esc(item.sku)}', '${esc(item.product_name || '')}', '${esc(orderNumber)}')" title="Click pentru mapare">${renderCodmatCell(item)}</span>`;
return `<tr>
<td><code>${esc(item.sku)}</code></td>
<td>${esc(item.product_name || '-')}</td>
<td>${codmatCell}</td>
<td>${item.quantity || 0}</td>
<td>${item.price != null ? Number(item.price).toFixed(2) : '-'}</td>
<td>${item.vat != null ? Number(item.vat).toFixed(2) : '-'}</td>
<td>${renderCodmatCell(item)}</td>
<td>${statusBadge}</td>
<td>${action}</td>
<td class="text-end">${valoare}</td>
</tr>`;
}).join('');
} catch (err) {