Files
Alby96andClaude Sonnet 4.6 b6b6759b9a 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>
2026-06-17 11:47:32 +02:00

101 lines
5.7 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}{{ movement.doc_no }} - Mago4 Demo{% endblock %}
{% block window_tabs %}
<a href="/inventory-movements" class="window-tab"><i class="material-icons">swap_vert</i> Movimenti</a>
<a href="/inventory-movements/{{ movement.id }}" class="window-tab active"><i class="material-icons">inventory</i> {{ movement.doc_no }}</a>
{% endblock %}
{% block content %}
<div class="module-bar">
<div class="module-title">Movimento di Magazzino — {{ movement.doc_no }}</div>
<div class="breadcrumb"><a href="/">Mago4</a><span class="sep">»</span><a href="/magazzino">Logistica</a><span class="sep">»</span><a href="/inventory-movements">Movimenti</a><span class="sep">»</span><span class="current">{{ movement.doc_no }}</span></div>
</div>
<div class="doc-toolbar">
<button class="tb-btn" title="Precedente"><i class="material-icons">chevron_left</i></button>
<button class="tb-btn" title="Successivo"><i class="material-icons">chevron_right</i></button>
<div class="tb-sep"></div>
<button class="tb-btn" title="Modifica"><i class="material-icons">edit</i></button>
<button class="tb-btn" title="Salva"><i class="material-icons">save</i></button>
<button class="tb-btn" title="Stampa"><i class="material-icons">print</i></button>
<div class="tb-sep"></div>
{% if not movement.posted %}
<button class="btn btn-primary" style="margin-left:6px;" onclick="postMovement({{ movement.id }})"><i class="material-icons">check</i> Conferma e aggiorna giacenze</button>
{% endif %}
<a class="tb-btn" href="/inventory-movements" title="Chiudi" style="margin-left:auto;"><i class="material-icons">logout</i></a>
</div>
<div style="background:#fff;border-bottom:1px solid var(--border);padding:14px 20px;">
<div class="form-grid-2" style="margin-bottom:0;">
<div>
<div class="field-row"><label>Numero</label><div class="field-value text-bold">{{ movement.doc_no }}</div></div>
<div class="field-row"><label>Data Documento</label><div class="field-value">{{ movement.doc_date.strftime("%d/%m/%Y") }}</div></div>
<div class="field-row"><label>Data Registrazione</label><div class="field-value">{{ movement.posting_date.strftime("%d/%m/%Y") }}</div></div>
<div class="field-row"><label>Deposito</label><div class="field-value">{{ movement.storage }}</div></div>
</div>
<div>
<div class="field-row"><label>Causale</label><div class="field-value"><span class="mono">{{ movement.reason_code }}</span> — {{ movement.reason_description }}</div></div>
<div class="field-row"><label>Segno</label><div class="field-value">
{% if movement.sign.value == 'load' %}<span class="badge badge-load"><i class="material-icons">add</i> Carico (+)</span>
{% else %}<span class="badge badge-unload"><i class="material-icons">remove</i> Scarico ()</span>{% endif %}
</div></div>
<div class="field-row"><label>Cliente/Fornitore</label><div class="field-value">{{ movement.custsupp_name or '—' }}</div></div>
<div class="field-row"><label>Stato</label><div class="field-value" id="statusField">
{% if movement.posted %}<span class="badge badge-success"><i class="material-icons">check</i> Confermato</span>
{% else %}<span class="badge badge-grey">Bozza</span>{% endif %}
</div></div>
</div>
</div>
</div>
<div class="content-pad">
<div class="panel">
<div class="panel-header"><h3><i class="material-icons">list</i> Righe Movimento</h3></div>
<table class="data-table">
<thead><tr><th>#</th><th>Articolo</th><th>Descrizione</th><th class="text-center">UM</th><th class="text-right">Q.tà</th><th class="text-right">Valore Unit.</th><th class="text-right">Importo</th><th>Lotto</th><th>Ubicazione</th></tr></thead>
<tbody>
{% for l in movement.lines %}
<tr>
<td>{{ l.line_no }}</td>
<td class="mono text-bold">{{ l.item_code }}</td>
<td>{{ l.description }}</td>
<td class="text-center">{{ l.uom }}</td>
<td class="text-right {% if movement.sign.value == 'load' %}text-success{% else %}text-danger{% endif %} text-bold">
{{ '+' if movement.sign.value == 'load' else '' }}{{ "%.2f"|format(l.quantity) }}
</td>
<td class="text-right">€ {{ "%.2f"|format(l.unit_value) }}</td>
<td class="text-right text-bold">€ {{ "%.2f"|format(l.line_amount) }}</td>
<td>{{ l.lot or '—' }}</td>
<td>{{ l.location or '—' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if movement.notes %}
<div class="panel">
<div class="panel-header"><h3><i class="material-icons">notes</i> Note</h3></div>
<div class="panel-body padded">{{ movement.notes }}</div>
</div>
{% endif %}
</div>
<div class="totals-box">
<div class="t-item grand"><div class="t-label">VALORE TOTALE MOVIMENTO</div><div class="t-value">€ {{ "%.2f"|format(movement.total_amount) }}</div></div>
</div>
<script>
function postMovement(id) {
if (!confirm('Confermare il movimento? Le giacenze degli articoli verranno aggiornate.')) return;
fetch(`/inventory-movements/${id}/post`, { method: 'POST' })
.then(r => r.json())
.then(d => {
showNotification('Movimento confermato — giacenze aggiornate');
setTimeout(() => location.reload(), 800);
})
.catch(() => showNotification('Errore nella conferma', 'error'));
}
</script>
{% endblock %}