refactor(status): introduce OrderStatus enum, replace string literals
Centralized order status values in api/app/constants.py via a str-valued Enum so comparisons keep working. Replaced literals in: - services: sync_service, sqlite_service, retry_service - routers: sync, dashboard - templates: dashboard.html, logs.html - static JS: shared (ORDER_STATUS mirror), dashboard, logs - tests: requirements, order_items_overwrite, business_rules MALFORMED intentionally NOT added — introduced in follow-up PR2 (per-order failure isolation). Full test suite: 231 unit + 33 e2e pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,16 @@
|
||||
};
|
||||
})();
|
||||
|
||||
// ── Order status constants (mirror of Python OrderStatus enum) ────────────
|
||||
const ORDER_STATUS = Object.freeze({
|
||||
IMPORTED: 'IMPORTED',
|
||||
ALREADY_IMPORTED: 'ALREADY_IMPORTED',
|
||||
SKIPPED: 'SKIPPED',
|
||||
ERROR: 'ERROR',
|
||||
CANCELLED: 'CANCELLED',
|
||||
DELETED_IN_ROA: 'DELETED_IN_ROA',
|
||||
});
|
||||
|
||||
// ── HTML escaping ─────────────────────────────────
|
||||
function esc(s) {
|
||||
if (s == null) return '';
|
||||
@@ -503,12 +513,12 @@ function fmtNum(v) {
|
||||
|
||||
function orderStatusBadge(status) {
|
||||
switch ((status || '').toUpperCase()) {
|
||||
case 'IMPORTED': return '<span class="badge bg-success">Importat</span>';
|
||||
case 'ALREADY_IMPORTED': return '<span class="badge bg-info">Deja importat</span>';
|
||||
case 'SKIPPED': return '<span class="badge bg-warning">Omis</span>';
|
||||
case 'ERROR': return '<span class="badge bg-danger">Eroare</span>';
|
||||
case 'CANCELLED': return '<span class="badge bg-secondary">Anulat</span>';
|
||||
case 'DELETED_IN_ROA': return '<span class="badge bg-dark">Sters din ROA</span>';
|
||||
case ORDER_STATUS.IMPORTED: return '<span class="badge bg-success">Importat</span>';
|
||||
case ORDER_STATUS.ALREADY_IMPORTED: return '<span class="badge bg-info">Deja importat</span>';
|
||||
case ORDER_STATUS.SKIPPED: return '<span class="badge bg-warning">Omis</span>';
|
||||
case ORDER_STATUS.ERROR: return '<span class="badge bg-danger">Eroare</span>';
|
||||
case ORDER_STATUS.CANCELLED: return '<span class="badge bg-secondary">Anulat</span>';
|
||||
case ORDER_STATUS.DELETED_IN_ROA: return '<span class="badge bg-dark">Sters din ROA</span>';
|
||||
default: return `<span class="badge bg-secondary">${esc(status)}</span>`;
|
||||
}
|
||||
}
|
||||
@@ -844,7 +854,7 @@ async function renderOrderDetailModal(orderNumber, opts) {
|
||||
// Retry button (only for ERROR/SKIPPED orders)
|
||||
const retryBtn = document.getElementById('detailRetryBtn');
|
||||
if (retryBtn) {
|
||||
const canRetry = ['ERROR', 'SKIPPED', 'DELETED_IN_ROA'].includes((order.status || '').toUpperCase());
|
||||
const canRetry = [ORDER_STATUS.ERROR, ORDER_STATUS.SKIPPED, ORDER_STATUS.DELETED_IN_ROA].includes((order.status || '').toUpperCase());
|
||||
retryBtn.style.display = canRetry ? '' : 'none';
|
||||
if (canRetry) {
|
||||
retryBtn.onclick = async () => {
|
||||
@@ -879,7 +889,7 @@ async function renderOrderDetailModal(orderNumber, opts) {
|
||||
// Resync button (IMPORTED/ALREADY_IMPORTED only)
|
||||
const resyncBtn = document.getElementById('detailResyncBtn');
|
||||
if (resyncBtn) {
|
||||
const canResync = ['IMPORTED', 'ALREADY_IMPORTED'].includes((order.status || '').toUpperCase());
|
||||
const canResync = [ORDER_STATUS.IMPORTED, ORDER_STATUS.ALREADY_IMPORTED].includes((order.status || '').toUpperCase());
|
||||
resyncBtn.style.display = canResync ? '' : 'none';
|
||||
if (canResync) {
|
||||
const isInvoiced = !!(order.factura_numar);
|
||||
@@ -930,7 +940,7 @@ async function renderOrderDetailModal(orderNumber, opts) {
|
||||
// Delete button (IMPORTED/ALREADY_IMPORTED only)
|
||||
const deleteBtn = document.getElementById('detailDeleteBtn');
|
||||
if (deleteBtn) {
|
||||
const canDelete = ['IMPORTED', 'ALREADY_IMPORTED'].includes((order.status || '').toUpperCase());
|
||||
const canDelete = [ORDER_STATUS.IMPORTED, ORDER_STATUS.ALREADY_IMPORTED].includes((order.status || '').toUpperCase());
|
||||
deleteBtn.style.display = canDelete ? '' : 'none';
|
||||
if (canDelete) {
|
||||
const isInvoiced = !!(order.factura_numar);
|
||||
@@ -1015,20 +1025,20 @@ function inlineConfirmAction(btn, confirmText, actionFn, opts) {
|
||||
// ── Dot helper ────────────────────────────────────
|
||||
function statusDot(status) {
|
||||
switch ((status || '').toUpperCase()) {
|
||||
case 'IMPORTED':
|
||||
case 'ALREADY_IMPORTED':
|
||||
case ORDER_STATUS.IMPORTED:
|
||||
case ORDER_STATUS.ALREADY_IMPORTED:
|
||||
case 'COMPLETED':
|
||||
case 'RESOLVED':
|
||||
return '<span class="dot dot-green"></span>';
|
||||
case 'SKIPPED':
|
||||
case ORDER_STATUS.SKIPPED:
|
||||
case 'UNRESOLVED':
|
||||
case 'INCOMPLETE':
|
||||
return '<span class="dot dot-yellow"></span>';
|
||||
case 'ERROR':
|
||||
case ORDER_STATUS.ERROR:
|
||||
case 'FAILED':
|
||||
return '<span class="dot dot-red"></span>';
|
||||
case 'CANCELLED':
|
||||
case 'DELETED_IN_ROA':
|
||||
case ORDER_STATUS.CANCELLED:
|
||||
case ORDER_STATUS.DELETED_IN_ROA:
|
||||
return '<span class="dot dot-gray"></span>';
|
||||
default:
|
||||
return '<span class="dot dot-gray"></span>';
|
||||
@@ -1168,7 +1178,7 @@ function _renderHeaderInfo(order) {
|
||||
}
|
||||
|
||||
// ERROR orders: muted dashes for ROA fields
|
||||
if (order.status === 'ERROR' && !order.id_comanda) {
|
||||
if (order.status === ORDER_STATUS.ERROR && !order.id_comanda) {
|
||||
document.getElementById('detailIdComanda').innerHTML = '<span class="text-muted">\u2014</span>';
|
||||
document.getElementById('detailIdPartener').innerHTML = '<span class="text-muted">\u2014</span>';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user