from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import Response from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.db.models.invoice import Invoice from app.db.models.order import Order from app.db.models.order_line import OrderLine from app.db.models.tenant import Tenant from app.db.models.vehicle import Vehicle from app.db.session import get_db from app.deps import get_tenant_id from app.invoices import service from app.pdf.service import generate_factura router = APIRouter() @router.post("") async def create_invoice( data: dict, tenant_id: str = Depends(get_tenant_id), db: AsyncSession = Depends(get_db), ): order_id = data.get("order_id") if not order_id: raise HTTPException(status_code=422, detail="order_id required") try: invoice = await service.create_invoice(db, tenant_id, order_id) return {"id": invoice.id, "nr_factura": invoice.nr_factura} except ValueError as e: raise HTTPException(status_code=422, detail=str(e)) @router.get("/{invoice_id}/pdf") async def get_invoice_pdf( invoice_id: str, tenant_id: str = Depends(get_tenant_id), db: AsyncSession = Depends(get_db), ): r = await db.execute( select(Invoice).where( Invoice.id == invoice_id, Invoice.tenant_id == tenant_id ) ) invoice = r.scalar_one_or_none() if not invoice: raise HTTPException(status_code=404, detail="Invoice not found") r = await db.execute(select(Order).where(Order.id == invoice.order_id)) order = r.scalar_one() r = await db.execute(select(Vehicle).where(Vehicle.id == order.vehicle_id)) vehicle = r.scalar_one_or_none() r = await db.execute(select(Tenant).where(Tenant.id == tenant_id)) tenant = r.scalar_one() r = await db.execute( select(OrderLine).where(OrderLine.order_id == order.id) ) lines = r.scalars().all() order_data = { "id": order.id, "nr_auto": vehicle.nr_inmatriculare if vehicle else "", "client_nume": vehicle.client_nume if vehicle else "", "client_cui": vehicle.client_cui if vehicle else "", "client_adresa": vehicle.client_adresa if vehicle else "", "total_manopera": order.total_manopera, "total_materiale": order.total_materiale, "total_general": order.total_general, } invoice_data = { "nr_factura": invoice.nr_factura, "data_factura": invoice.data_factura, "total": invoice.total, } tenant_data = { "nume": tenant.nume, "cui": tenant.cui, "reg_com": tenant.reg_com, "adresa": tenant.adresa, "iban": tenant.iban, "banca": tenant.banca, } lines_data = [ { "tip": l.tip, "descriere": l.descriere, "ore": l.ore, "pret_ora": l.pret_ora, "cantitate": l.cantitate, "pret_unitar": l.pret_unitar, "um": l.um, "total": l.total, } for l in lines ] pdf_bytes = generate_factura(invoice_data, order_data, lines_data, tenant_data) return Response( content=pdf_bytes, media_type="application/pdf", headers={ "Content-Disposition": f'inline; filename="factura-{invoice.nr_factura}.pdf"' }, )