bff6d70b17
Aplicatie Flask + SQLite pentru productie alimentara: cantarirea componentelor unui produs finit si tiparirea etichetei prin QZ Tray. - produse finite (retete) formate din componente cantarite - designer vizual de etichete (mm/px, zona sigura, campuri variabile, cod QR cu continut din mai multe bucati) - legare produs finit -> sablon de eticheta - navigare pe doua taburi: Cantarire / Setari - administrare: componente, produse finite, sabloane, campuri, istoric - backup, resetare baza de date, checklist de pregatire, /healthz - CLI de administrare si serviciu systemd pentru productie - vendor/syncpulse-scale-bridge (GPL-3.0-or-later) pentru citirea cantarului
101 lines
3.8 KiB
HTML
101 lines
3.8 KiB
HTML
{% extends "base.html" %}
|
||
{% block title %}Istoric produse finite{% endblock %}
|
||
|
||
{% block content %}
|
||
<section class="page-head">
|
||
<div>
|
||
<h1>Istoric produse finite</h1>
|
||
<p class="subtitle">Filtrează, verifică și exportă pachetele finalizate.</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<form method="get" class="filters">
|
||
<div class="field">
|
||
<label for="date_from">De la</label>
|
||
<input id="date_from" name="date_from" type="date" value="{{ filters.date_from }}">
|
||
</div>
|
||
<div class="field">
|
||
<label for="date_to">Până la</label>
|
||
<input id="date_to" name="date_to" type="date" value="{{ filters.date_to }}">
|
||
</div>
|
||
<div class="field">
|
||
<label for="recipe_id">Produs finit</label>
|
||
<select id="recipe_id" name="recipe_id">
|
||
<option value="">— toate —</option>
|
||
{% for r in recipes %}
|
||
<option value="{{ r.id }}" {{ 'selected' if filters.recipe_id == r.id }}>{{ r.code }} · {{ r.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div class="field">
|
||
<label for="status">Stare</label>
|
||
<select id="status" name="status">
|
||
<option value="">— toate —</option>
|
||
<option value="done" {{ 'selected' if filters.status == 'done' }}>finalizat</option>
|
||
<option value="open" {{ 'selected' if filters.status == 'open' }}>în lucru</option>
|
||
<option value="void" {{ 'selected' if filters.status == 'void' }}>anulat</option>
|
||
</select>
|
||
</div>
|
||
<div class="field grow">
|
||
<label for="q">Căutare</label>
|
||
<input id="q" name="q" type="search" value="{{ filters.query }}" placeholder="produs, lot, operator…">
|
||
</div>
|
||
<div class="field actions-field">
|
||
<button class="btn primary" type="submit">Filtrează</button>
|
||
<a class="btn" href="{{ url_for('history.index') }}">Resetează</a>
|
||
</div>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<div class="card-head">
|
||
<h2>{{ packages|length }} pachete · total {{ total }}</h2>
|
||
<a class="btn ghost"
|
||
href="{{ url_for('history.export_csv', date_from=filters.date_from, date_to=filters.date_to, recipe_id=filters.recipe_id or '', status=filters.status, q=filters.query) }}">Export CSV</a>
|
||
</div>
|
||
|
||
{% if packages %}
|
||
<div class="table-wrap">
|
||
<table class="table">
|
||
<thead>
|
||
<tr>
|
||
<th>Data</th><th>Produs finit</th><th>Componente</th><th class="num">Total</th>
|
||
<th>Lot</th><th>Operator</th><th>Stare</th><th>Tipărit</th><th></th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
{% for p in packages %}
|
||
<tr class="{{ 'row-muted' if p.status != 'done' }}">
|
||
<td class="nowrap">{{ (p.completed_at or p.created_at)|dt }}</td>
|
||
<td>{{ p.recipe_code }} · {{ p.recipe_name }}</td>
|
||
<td class="muted small">{{ p.item_summary or "-" }}</td>
|
||
<td class="num">{{ (p.total_weight or 0)|weight }} {{ p.unit }}</td>
|
||
<td>{{ p.lot or "-" }}</td>
|
||
<td>{{ p.operator or "-" }}</td>
|
||
<td>
|
||
{% if p.status == "done" %}<span class="badge ok">finalizat</span>
|
||
{% elif p.status == "open" %}<span class="badge warn">în lucru</span>
|
||
{% else %}<span class="badge err">anulat</span>{% endif %}
|
||
</td>
|
||
<td class="nowrap">
|
||
{% if p.printed_at %}<span class="badge ok">{{ p.print_count }}×</span>
|
||
{% else %}<span class="muted">—</span>{% endif %}
|
||
</td>
|
||
<td class="right">
|
||
{% if p.status == "done" %}
|
||
<a class="link" target="_blank" rel="noopener"
|
||
href="{{ url_for('printing.print_label', package_id=p.id, auto='0') }}">Etichetă</a>
|
||
{% endif %}
|
||
</td>
|
||
</tr>
|
||
{% endfor %}
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
{% else %}
|
||
<p class="muted">Nicio înregistrare pentru filtrele selectate.</p>
|
||
{% endif %}
|
||
</section>
|
||
{% endblock %}
|