Restyle UI to match Mago4 and add invoicing, warehouse, scadenzario
Rework the demo into a faithful Mago4 look-and-feel and expand it with core ERP modules modelled on the real Mago4 database schema. UI (ispirata a Mago4): - Blue header with logo/search/operation date, desktop-style window tabs - White sidebar with coloured module icons (Anagrafiche, Vendite, Acquisti, Amministrazione, Logistica) - Card-based module landing pages with breadcrumb + tab strip - Document detail forms with left tabs, line grid and totals box Fatturazione (InvoiceMng / MA_SaleDoc): - Document types (Fattura Immediata, DDT, Nota di Credito, ProForma) - Lines with discount/IVA, automatic taxable/tax/total computation - Document states (draft -> printed -> issued / posted_to_inventory) Magazzino (Inventory / MA_InventoryEntries + MA_InventoryReasons): - Inventory movements with load/unload reasons (DebitCreditSign) - Posting a movement actually updates item balances - Causali and stock valuation pages Amministrazione / Scadenzario (AP_AR / MA_PyblsRcvbls): - Open items (receivables/payables) with due date, method, state - Settle action closes the item and recomputes the cash forecast Dashboard riprogettata (focus su scadenze e to-do): - Overdue alert banner, KPI for overdue payables/receivables - Upcoming deadlines table, prioritised "Cose da fare" action list - 30-day cash-flow forecast and customer credit-limit check Adds REST endpoints for invoices, movements, schedules and dashboard data. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+59
-119
@@ -1,131 +1,77 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block title %}Magazzino - Mago4 Demo{% endblock %}
|
||||
{% block page_title %}Magazzino{% endblock %}
|
||||
{% block title %}Giacenze - Mago4 Demo{% endblock %}
|
||||
{% block window_tabs %}<a href="/warehouse" class="window-tab active"><i class="material-icons">inventory</i> Giacenze</a>{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="page-header">
|
||||
<div class="module-bar">
|
||||
<div class="module-title">Giacenze Articoli</div>
|
||||
<div class="breadcrumb"><a href="/">Mago4</a><span class="sep">»</span><a href="/magazzino">Logistica</a><span class="sep">»</span><span class="current">Giacenze</span></div>
|
||||
</div>
|
||||
<div class="tab-strip">
|
||||
<a href="/magazzino">Magazzino</a>
|
||||
<a href="/inventory-movements">Movimenti</a>
|
||||
<a href="/warehouse" class="active">Giacenze</a>
|
||||
<a href="/inventory-reasons">Causali</a>
|
||||
</div>
|
||||
|
||||
<div class="content-pad">
|
||||
<div class="kpi-grid">
|
||||
<div class="kpi-card" style="border-left-color: var(--c-blue)">
|
||||
<div class="kpi-title">Articoli in Catalogo</div>
|
||||
<div class="kpi-row"><div class="kpi-icon"><i class="material-icons" style="color:var(--c-blue)">inventory_2</i></div><div class="kpi-value">{{ products|length }}</div></div>
|
||||
</div>
|
||||
<div class="kpi-card" style="border-left-color: var(--c-red)">
|
||||
<div class="kpi-title">Articoli Sotto Scorta</div>
|
||||
<div class="kpi-row"><div class="kpi-icon"><i class="material-icons" style="color:var(--c-red)">warning</i></div><div class="kpi-value">{{ low_stock|length }}</div></div>
|
||||
</div>
|
||||
<div class="kpi-card" style="border-left-color: var(--c-purple)">
|
||||
<div class="kpi-title">Valore Magazzino (a costo)</div>
|
||||
<div class="kpi-row"><div class="kpi-icon"><i class="material-icons" style="color:var(--c-purple)">euro_symbol</i></div><div class="kpi-value">€ {{ "{:,.0f}".format(warehouse_value) }}</div></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if low_stock %}
|
||||
<div class="alert alert-danger" style="flex: 1;">
|
||||
<i class="material-icons">error</i>
|
||||
<strong>Attenzione!</strong> {{ low_stock|length }} articolo/i in sottosorta
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Summary Stats -->
|
||||
<div class="widget-row" style="margin-bottom: 20px;">
|
||||
<div class="widget-card stat-card" style="border-left-color: var(--color-blue)">
|
||||
<div class="widget-header">
|
||||
<h3 class="widget-title">Articoli in Catalogo</h3>
|
||||
</div>
|
||||
<div class="widget-body stat-body">
|
||||
<div class="stat-value">{{ products|length }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="widget-card stat-card" style="border-left-color: var(--color-red)">
|
||||
<div class="widget-header">
|
||||
<h3 class="widget-title">Articoli in Sottosorta</h3>
|
||||
</div>
|
||||
<div class="widget-body stat-body">
|
||||
<div class="stat-icon" style="color: var(--color-red)">
|
||||
<i class="material-icons">warning</i>
|
||||
</div>
|
||||
<div class="stat-value">{{ low_stock|length }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Low Stock Alert -->
|
||||
{% if low_stock %}
|
||||
<div class="widget-card">
|
||||
<div class="widget-header">
|
||||
<h3 class="widget-title">
|
||||
<i class="material-icons">warning</i> Articoli Sotto Soglia Riordino
|
||||
</h3>
|
||||
</div>
|
||||
<div class="widget-body">
|
||||
<div class="panel">
|
||||
<div class="panel-header"><h3><i class="material-icons" style="color:var(--c-red)">warning</i> Articoli Sotto Scorta Minima</h3></div>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Codice</th>
|
||||
<th>Descrizione</th>
|
||||
<th>Giacenza</th>
|
||||
<th>Soglia Riordino</th>
|
||||
<th>Scostamento</th>
|
||||
<th>Azioni</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead><tr><th>Codice</th><th>Descrizione</th><th class="text-right">Giacenza</th><th class="text-right">Scorta Min.</th><th class="text-right">Da Riordinare</th><th></th></tr></thead>
|
||||
<tbody>
|
||||
{% for product in low_stock %}
|
||||
<tr class="highlight-danger">
|
||||
<td><strong>{{ product.code }}</strong></td>
|
||||
<td>{{ product.description }}</td>
|
||||
<td class="text-danger text-bold">{{ product.quantity_in_stock }}</td>
|
||||
<td class="text-right">{{ product.reorder_level }}</td>
|
||||
<td class="text-right text-danger">
|
||||
-{{ product.reorder_level - product.quantity_in_stock }} unità
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-small btn-primary" onclick="createPOForProduct({{ product.id }})">
|
||||
<i class="material-icons">add_shopping_cart</i>
|
||||
</button>
|
||||
</td>
|
||||
{% for p in low_stock %}
|
||||
<tr class="low-stock">
|
||||
<td class="text-bold mono">{{ p.code }}</td>
|
||||
<td>{{ p.description }}</td>
|
||||
<td class="text-right text-danger text-bold">{{ p.quantity_in_stock }} {{ p.uom }}</td>
|
||||
<td class="text-right">{{ p.reorder_level }} {{ p.uom }}</td>
|
||||
<td class="text-right text-danger">{{ p.max_stock - p.quantity_in_stock }} {{ p.uom }}</td>
|
||||
<td class="text-center"><button class="btn-icon-sm act-cart" title="Genera ordine" onclick="alert('Genera ordine di acquisto (demo)')"><i class="material-icons">add_shopping_cart</i></button></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
||||
<!-- All Products -->
|
||||
<div class="widget-card">
|
||||
<div class="widget-header">
|
||||
<h3 class="widget-title">Inventario Completo</h3>
|
||||
</div>
|
||||
<div class="widget-body">
|
||||
<div class="panel">
|
||||
<div class="panel-header"><h3><i class="material-icons">inventory</i> Inventario Completo — Deposito MAG01</h3></div>
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Codice</th>
|
||||
<th>Descrizione</th>
|
||||
<th>Categoria</th>
|
||||
<th>Giacenza</th>
|
||||
<th>Soglia Riordino</th>
|
||||
<th>Prezzo Unit.</th>
|
||||
<th>Valore Magazzino</th>
|
||||
<th>Stato</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<thead><tr><th>Codice</th><th>Descrizione</th><th>Categoria</th><th class="text-right">Giacenza</th><th class="text-right">Scorta Min.</th><th class="text-right">Costo Unit.</th><th class="text-right">Valore</th><th class="text-center">Stato</th></tr></thead>
|
||||
<tbody>
|
||||
{% for product in products %}
|
||||
<tr class="{% if product.quantity_in_stock <= product.reorder_level %}low-stock{% endif %}">
|
||||
<td><strong>{{ product.code }}</strong></td>
|
||||
<td>{{ product.description }}</td>
|
||||
<td>{{ product.category }}</td>
|
||||
<td class="text-right {% if product.quantity_in_stock <= product.reorder_level %}text-danger text-bold{% endif %}">
|
||||
{{ product.quantity_in_stock }}
|
||||
</td>
|
||||
<td class="text-right">{{ product.reorder_level }}</td>
|
||||
<td class="text-right">€ {{ "%.2f"|format(product.unit_price) }}</td>
|
||||
<td class="text-right text-bold">
|
||||
€ {{ "%.2f"|format(product.quantity_in_stock * product.unit_price) }}
|
||||
</td>
|
||||
<td>
|
||||
{% if product.quantity_in_stock <= product.reorder_level %}
|
||||
<span class="badge badge-danger">
|
||||
<i class="material-icons">warning</i> SOTTOSORTA
|
||||
</span>
|
||||
{% elif product.quantity_in_stock <= product.reorder_level + 20 %}
|
||||
<span class="badge badge-warning">
|
||||
<i class="material-icons">info</i> PROSSIMA SOGLIA
|
||||
</span>
|
||||
{% for p in products %}
|
||||
<tr class="{% if p.quantity_in_stock <= p.reorder_level %}low-stock{% endif %}">
|
||||
<td class="text-bold mono">{{ p.code }}</td>
|
||||
<td>{{ p.description }}</td>
|
||||
<td>{{ p.category }}</td>
|
||||
<td class="text-right {% if p.quantity_in_stock <= p.reorder_level %}text-danger text-bold{% endif %}">{{ p.quantity_in_stock }} {{ p.uom }}</td>
|
||||
<td class="text-right">{{ p.reorder_level }} {{ p.uom }}</td>
|
||||
<td class="text-right text-mute">€ {{ "%.2f"|format(p.purchase_price) }}</td>
|
||||
<td class="text-right text-bold">€ {{ "%.2f"|format(p.quantity_in_stock * p.purchase_price) }}</td>
|
||||
<td class="text-center">
|
||||
{% if p.quantity_in_stock <= p.reorder_level %}
|
||||
<span class="badge badge-danger"><i class="material-icons">warning</i> Sottoscorta</span>
|
||||
{% elif p.quantity_in_stock <= p.reorder_level + 20 %}
|
||||
<span class="badge badge-warning"><i class="material-icons">info</i> In esaurimento</span>
|
||||
{% else %}
|
||||
<span class="badge badge-success">
|
||||
<i class="material-icons">check</i> OK
|
||||
</span>
|
||||
<span class="badge badge-success"><i class="material-icons">check</i> OK</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -134,10 +80,4 @@
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function createPOForProduct(productId) {
|
||||
alert('Creazione ordine di acquisto per articolo #' + productId + ' (da implementare)');
|
||||
}
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user