Files
roaauto/backend/app/pdf/templates/deviz.html
Marius Mutu 3bdafad22a feat(backend): PDF deviz + portal client + SMS + invoice service
- PDF generation with WeasyPrint: deviz and factura templates (A4, branding)
- GET /orders/{id}/pdf/deviz returns PDF with order lines and totals
- Client portal (public, no auth): GET /p/{token}, POST /p/{token}/accept|reject
- SMS service (SMSAPI.ro) - skips in dev when no token configured
- Invoice service: create from validated order, auto-number (F-YYYY-NNNN)
- GET /invoices/{id}/pdf returns factura PDF
- Order status_client field for client accept/reject tracking
- Alembic migration for status_client
- 19 passing tests (auth + sync + orders + pdf + portal + invoices)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 17:34:36 +02:00

68 lines
2.4 KiB
HTML

<!DOCTYPE html>
<html lang="ro"><head>
<meta charset="UTF-8">
<style>
@page { size: A4; margin: 2cm; }
body { font-family: DejaVu Sans, sans-serif; font-size: 11pt; color: #111; }
.header { display: flex; justify-content: space-between; margin-bottom: 24px; }
h2 { margin: 0; font-size: 16pt; }
h3 { font-size: 11pt; margin: 16px 0 6px; color: #374151; }
table { width: 100%; border-collapse: collapse; }
th { background: #f3f4f6; padding: 6px 8px; text-align: left; font-size: 10pt; }
td { padding: 5px 8px; border-bottom: 1px solid #e5e7eb; font-size: 10pt; }
.totals { margin-top: 20px; text-align: right; }
.totals div { margin-bottom: 4px; }
.total-final { font-weight: bold; font-size: 13pt; border-top: 2px solid #111; padding-top: 6px; }
</style>
</head><body>
<div class="header">
<div>
<strong>{{ tenant.nume }}</strong><br>
{% if tenant.cui %}CUI: {{ tenant.cui }}<br>{% endif %}
{% if tenant.adresa %}{{ tenant.adresa }}<br>{% endif %}
{% if tenant.telefon %}Tel: {{ tenant.telefon }}{% endif %}
</div>
<div style="text-align:right">
<h2>DEVIZ Nr. {{ order.nr_comanda or order.id[:8]|upper }}</h2>
<div>Data: {{ order.data_comanda }}</div>
<div>Auto: <strong>{{ order.nr_auto }}</strong></div>
<div>{{ order.marca_denumire or '' }} {{ order.model_denumire or '' }}</div>
<div>Client: {{ order.client_nume or '' }}</div>
</div>
</div>
{% if manopera %}
<h3>Operatii manopera</h3>
<table>
<tr><th>Descriere</th><th>Ore</th><th>Pret/ora (RON)</th><th>Total (RON)</th></tr>
{% for l in manopera %}
<tr>
<td>{{ l.descriere }}</td><td>{{ l.ore }}</td>
<td>{{ "%.2f"|format(l.pret_ora or 0) }}</td>
<td>{{ "%.2f"|format(l.total or 0) }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if materiale %}
<h3>Materiale</h3>
<table>
<tr><th>Descriere</th><th>UM</th><th>Cant.</th><th>Pret unit. (RON)</th><th>Total (RON)</th></tr>
{% for l in materiale %}
<tr>
<td>{{ l.descriere }}</td><td>{{ l.um }}</td><td>{{ l.cantitate }}</td>
<td>{{ "%.2f"|format(l.pret_unitar or 0) }}</td>
<td>{{ "%.2f"|format(l.total or 0) }}</td>
</tr>
{% endfor %}
</table>
{% endif %}
<div class="totals">
<div>Manopera: {{ "%.2f"|format(order.total_manopera or 0) }} RON</div>
<div>Materiale: {{ "%.2f"|format(order.total_materiale or 0) }} RON</div>
<div class="total-final">TOTAL: {{ "%.2f"|format(order.total_general or 0) }} RON</div>
</div>
</body></html>