from typing import Any, List from fastapi import APIRouter, Depends, HTTPException from fastapi.responses import StreamingResponse from sqlalchemy.orm import Session from app import models, schemas from app.core.deps import get_current_active_user, get_db from app.services.invoice import invoice_service from app.services.customer import customer_service from app.services.pdf_generator import pdf_generator router = APIRouter() @router.get("/", response_model=List[schemas.Invoice]) def read_invoices( db: Session = Depends(get_db), skip: int = 0, limit: int = 100, current_user: models.User = Depends(get_current_active_user), ) -> Any: invoices = invoice_service.get_multi_by_user(db, user_id=current_user.id, skip=skip, limit=limit) return invoices @router.post("/", response_model=schemas.Invoice) def create_invoice( *, db: Session = Depends(get_db), invoice_in: schemas.InvoiceCreate, current_user: models.User = Depends(get_current_active_user), ) -> Any: customer = customer_service.get(db=db, customer_id=invoice_in.customer_id) if not customer or customer.user_id != current_user.id: raise HTTPException(status_code=400, detail="Customer not found or not owned by user") existing_invoice = invoice_service.get_by_number(db=db, invoice_number=invoice_in.invoice_number) if existing_invoice: raise HTTPException(status_code=400, detail="Invoice number already exists") invoice = invoice_service.create(db=db, obj_in=invoice_in, user_id=current_user.id) return invoice @router.put("/{invoice_id}", response_model=schemas.Invoice) def update_invoice( *, db: Session = Depends(get_db), invoice_id: int, invoice_in: schemas.InvoiceUpdate, current_user: models.User = Depends(get_current_active_user), ) -> Any: invoice = invoice_service.get(db=db, invoice_id=invoice_id) if not invoice: raise HTTPException(status_code=404, detail="Invoice not found") if invoice.user_id != current_user.id: raise HTTPException(status_code=400, detail="Not enough permissions") if invoice_in.customer_id: customer = customer_service.get(db=db, customer_id=invoice_in.customer_id) if not customer or customer.user_id != current_user.id: raise HTTPException(status_code=400, detail="Customer not found or not owned by user") invoice = invoice_service.update(db=db, db_obj=invoice, obj_in=invoice_in) return invoice @router.get("/{invoice_id}", response_model=schemas.Invoice) def read_invoice( *, db: Session = Depends(get_db), invoice_id: int, current_user: models.User = Depends(get_current_active_user), ) -> Any: invoice = invoice_service.get(db=db, invoice_id=invoice_id) if not invoice: raise HTTPException(status_code=404, detail="Invoice not found") if invoice.user_id != current_user.id: raise HTTPException(status_code=400, detail="Not enough permissions") return invoice @router.delete("/{invoice_id}", response_model=schemas.Invoice) def delete_invoice( *, db: Session = Depends(get_db), invoice_id: int, current_user: models.User = Depends(get_current_active_user), ) -> Any: invoice = invoice_service.get(db=db, invoice_id=invoice_id) if not invoice: raise HTTPException(status_code=404, detail="Invoice not found") if invoice.user_id != current_user.id: raise HTTPException(status_code=400, detail="Not enough permissions") invoice = invoice_service.remove(db=db, invoice_id=invoice_id) return invoice @router.get("/{invoice_id}/pdf") def download_invoice_pdf( *, db: Session = Depends(get_db), invoice_id: int, current_user: models.User = Depends(get_current_active_user), ) -> StreamingResponse: invoice = invoice_service.get(db=db, invoice_id=invoice_id) if not invoice: raise HTTPException(status_code=404, detail="Invoice not found") if invoice.user_id != current_user.id: raise HTTPException(status_code=400, detail="Not enough permissions") pdf_buffer = pdf_generator.generate_invoice_pdf(invoice) return StreamingResponse( iter([pdf_buffer.read()]), media_type="application/pdf", headers={"Content-Disposition": f"attachment; filename=invoice_{invoice.invoice_number}.pdf"} )