v1.4.0 — 16 servizi reali Ianni, sala unica, ricevuta PDF

- Migration: services.price_cents, services.availability_text
- Migration: bookings.receipt_number (trigger annuale IANNI-YYYY-NNNN) + receipt_token
- Constraint EXCLUDE bookings_no_overlap (sala unica, status confirmed/completed)
- availability.py: calcolo slot globale (non più per-provider)
- 16 servizi reali da Servizi.xls inseriti, 9 demo archiviati con FK preservata
- provider_services: 3 profili orari (lun-sab 9-19, lun-mar 9-13, lun-gio 9-13)
- Endpoint GET /api/receipts/{token} → PDF WeasyPrint
- Template HTML ricevuta con palette Ianni
- Dockerfile: deps sistema weasyprint (pango/cairo/fonts)
- requirements: +weasyprint>=63.0
- Frontend index.html: prezzo + fascia oraria nelle card servizio, link Scarica ricevuta nella conferma
This commit is contained in:
ECO
2026-05-14 12:31:45 +00:00
parent c33ec8450e
commit a3f1d3291a
9 changed files with 260 additions and 69 deletions

View File

@@ -14,6 +14,8 @@ class Service(Base):
duration_min = Column(Integer, nullable=False, default=15)
description = Column(Text)
category = Column(Text, default="generale")
price_cents = Column(Integer)
availability_text = Column(Text)
active = Column(Boolean, default=True)
sort_order = Column(Integer, default=0)
created_at = Column(DateTime(timezone=True), server_default=func.now())
@@ -63,6 +65,8 @@ class Booking(Base):
end_at = Column(DateTime(timezone=True), nullable=False)
status = Column(Text, default="confirmed")
google_event_id = Column(Text)
receipt_number = Column(Text)
receipt_token = Column(Text)
notes = Column(Text)
reminder_sent = Column(Boolean, default=False)
created_at = Column(DateTime(timezone=True), server_default=func.now())