feat(sqlite): refactor orders schema + dashboard period filter

Replace import_orders (insert-per-run) with orders table (one row per
order, upsert on conflict). Eliminates dedup CTE on every dashboard
query and prevents unbounded row growth at 4-500 orders/sync.

Key changes:
- orders table: PK order_number, upsert via ON CONFLICT DO UPDATE;
  COALESCE preserves id_comanda once set; times_skipped auto-increments
- sync_run_orders: lightweight junction (sync_run_id, order_number)
  replaces sync_run_id column on orders
- order_items: PK changed to (order_number, sku), INSERT OR IGNORE
- Auto-migration in init_sqlite(): import_orders → orders on first boot,
  old table renamed to import_orders_bak
- /api/dashboard/orders: period_days param (3/7/30/0=all, default 7)
- Dashboard: period selector buttons in orders card header
- start.sh: stop existing process on port 5003 before restart;
  remove --reload (broken on WSL2 /mnt/e/)
- Add invoice_service, E2E Playwright tests, Oracle package updates

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 16:18:57 +02:00
parent 650e98539e
commit 82196b9dc0
32 changed files with 4164 additions and 1192 deletions

View File

@@ -9,7 +9,8 @@
<button class="btn btn-sm btn-outline-secondary" onclick="downloadTemplate()"><i class="bi bi-file-earmark-arrow-down"></i> Template CSV</button>
<button class="btn btn-sm btn-outline-secondary" onclick="exportCsv()"><i class="bi bi-download"></i> Export CSV</button>
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal" data-bs-target="#importModal"><i class="bi bi-upload"></i> Import CSV</button>
<button class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#addModal"><i class="bi bi-plus-lg"></i> Adauga Mapare</button>
<button class="btn btn-sm btn-primary" onclick="showInlineAddRow()"><i class="bi bi-plus-lg"></i> Adauga Mapare</button>
<button class="btn btn-sm btn-outline-secondary" data-bs-toggle="modal" data-bs-target="#addModal"><i class="bi bi-box-arrow-up-right"></i> Formular complet</button>
</div>
</div>
@@ -23,6 +24,18 @@
</div>
</div>
<!-- Filter controls -->
<div class="d-flex align-items-center mb-3 gap-3">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="showInactive" onchange="loadMappings()">
<label class="form-check-label" for="showInactive">Arata inactive</label>
</div>
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="showDeleted" onchange="loadMappings()">
<label class="form-check-label" for="showDeleted">Arata sterse</label>
</div>
</div>
<!-- Table -->
<div class="card">
<div class="card-body p-0">
@@ -30,17 +43,19 @@
<table class="table table-hover mb-0">
<thead>
<tr>
<th>SKU</th>
<th>CODMAT</th>
<th>Denumire</th>
<th>Cantitate ROA</th>
<th>Procent Pret</th>
<th>Activ</th>
<th class="sortable" onclick="sortBy('sku')">SKU <span class="sort-icon" data-col="sku"></span></th>
<th>Produs Web</th>
<th class="sortable" onclick="sortBy('codmat')">CODMAT <span class="sort-icon" data-col="codmat"></span></th>
<th class="sortable" onclick="sortBy('denumire')">Denumire <span class="sort-icon" data-col="denumire"></span></th>
<th>UM</th>
<th class="sortable" onclick="sortBy('cantitate_roa')">Cantitate ROA <span class="sort-icon" data-col="cantitate_roa"></span></th>
<th class="sortable" onclick="sortBy('procent_pret')">Procent Pret <span class="sort-icon" data-col="procent_pret"></span></th>
<th class="sortable" onclick="sortBy('activ')">Activ <span class="sort-icon" data-col="activ"></span></th>
<th style="width:100px">Actiuni</th>
</tr>
</thead>
<tbody id="mappingsBody">
<tr><td colspan="7" class="text-center text-muted py-4">Se incarca...</td></tr>
<tr><td colspan="9" class="text-center text-muted py-4">Se incarca...</td></tr>
</tbody>
</table>
</div>
@@ -53,9 +68,9 @@
</div>
</div>
<!-- Add/Edit Modal -->
<!-- Add/Edit Modal with multi-CODMAT support (R11) -->
<div class="modal fade" id="addModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="addModalTitle">Adauga Mapare</h5>
@@ -66,22 +81,17 @@
<label class="form-label">SKU</label>
<input type="text" class="form-control" id="inputSku" placeholder="Ex: 8714858124284">
</div>
<div class="mb-3 position-relative">
<label class="form-label">CODMAT (Articol ROA)</label>
<input type="text" class="form-control" id="inputCodmat" placeholder="Cauta codmat sau denumire..." autocomplete="off">
<div class="autocomplete-dropdown d-none" id="autocompleteDropdown"></div>
<small class="text-muted" id="selectedArticle"></small>
<div class="mb-2" id="addModalProductName" style="display:none;">
<small class="text-muted">Produs web:</small> <strong id="inputProductName"></strong>
</div>
<div class="row">
<div class="col-6 mb-3">
<label class="form-label">Cantitate ROA</label>
<input type="number" class="form-control" id="inputCantitate" value="1" step="0.001" min="0.001">
</div>
<div class="col-6 mb-3">
<label class="form-label">Procent Pret (%)</label>
<input type="number" class="form-control" id="inputProcent" value="100" step="0.01" min="0" max="100">
</div>
<hr>
<div id="codmatLines">
<!-- Dynamic CODMAT lines will be added here -->
</div>
<button type="button" class="btn btn-sm btn-outline-secondary mt-2" onclick="addCodmatLine()">
<i class="bi bi-plus"></i> Adauga CODMAT
</button>
<div id="pctWarning" class="text-danger mt-2" style="display:none;"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Anuleaza</button>
@@ -111,6 +121,36 @@
</div>
</div>
</div>
<!-- Delete Confirmation Modal -->
<div class="modal fade" id="deleteConfirmModal" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Confirmare stergere</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
Sigur vrei sa stergi maparea?<br>
SKU: <code id="deleteSkuText"></code><br>
CODMAT: <code id="deleteCodmatText"></code>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Anuleaza</button>
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">Sterge</button>
</div>
</div>
</div>
</div>
<!-- Toast container for undo actions -->
<div class="toast-container position-fixed bottom-0 end-0 p-3" style="z-index:1080">
<div id="undoToast" class="toast" role="alert" data-bs-autohide="true" data-bs-delay="5000">
<div class="toast-body d-flex align-items-center gap-2">
<span id="toastMessage"></span>
<button class="btn btn-sm btn-outline-primary ms-auto" id="toastUndoBtn">Anuleaza</button>
</div>
</div>
</div>
{% endblock %}
{% block scripts %}