180 lines
4.9 KiB
Python

import os
from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.responses import FileResponse
from sqlalchemy.orm import Session
from app.core.auth import get_current_active_user
from app.crud import invoice as crud_invoice
from app.db.session import get_db
from app.models.invoice import InvoiceStatus
from app.models.user import User
from app.schemas.invoice import Invoice, InvoiceCreate, InvoiceUpdate
from app.services.invoice_generator import InvoiceGenerator
router = APIRouter()
@router.get("", response_model=List[Invoice])
def read_invoices(
db: Session = Depends(get_db),
skip: int = 0,
limit: int = 100,
status: Optional[InvoiceStatus] = None,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Retrieve invoices for the current user.
"""
invoices = crud_invoice.get_invoices(
db, user_id=current_user.id, skip=skip, limit=limit, status=status
)
return invoices
@router.post("", response_model=Invoice, status_code=status.HTTP_201_CREATED)
def create_invoice(
*,
db: Session = Depends(get_db),
invoice_in: InvoiceCreate,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Create new invoice for the current user.
"""
invoice = crud_invoice.create_invoice(
db, user_id=current_user.id, invoice_in=invoice_in
)
return invoice
@router.get("/{invoice_id}", response_model=Invoice)
def read_invoice(
*,
db: Session = Depends(get_db),
invoice_id: int,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Get invoice by ID.
"""
invoice = crud_invoice.get_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
if not invoice:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invoice not found",
)
return invoice
@router.patch("/{invoice_id}", response_model=Invoice)
def update_invoice(
*,
db: Session = Depends(get_db),
invoice_id: int,
invoice_in: InvoiceUpdate,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Update an invoice.
"""
invoice = crud_invoice.get_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
if not invoice:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invoice not found",
)
invoice = crud_invoice.update_invoice(
db, user_id=current_user.id, db_invoice=invoice, invoice_in=invoice_in
)
return invoice
@router.delete("/{invoice_id}", response_model=Invoice)
def delete_invoice(
*,
db: Session = Depends(get_db),
invoice_id: int,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Delete an invoice.
"""
invoice = crud_invoice.get_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
if not invoice:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invoice not found",
)
invoice = crud_invoice.delete_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
return invoice
@router.patch("/{invoice_id}/status", response_model=Invoice)
def update_invoice_status(
*,
db: Session = Depends(get_db),
invoice_id: int,
status: InvoiceStatus,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Update an invoice status.
"""
invoice = crud_invoice.get_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
if not invoice:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invoice not found",
)
invoice = crud_invoice.update_invoice_status(
db, user_id=current_user.id, invoice_id=invoice_id, status=status
)
return invoice
@router.get("/{invoice_id}/pdf")
def generate_invoice_pdf(
*,
db: Session = Depends(get_db),
invoice_id: int,
current_user: User = Depends(get_current_active_user)
) -> Any:
"""
Generate a PDF for an invoice.
"""
invoice = crud_invoice.get_invoice(
db, user_id=current_user.id, invoice_id=invoice_id
)
if not invoice:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Invoice not found",
)
# Generate PDF
generator = InvoiceGenerator()
pdf_path = generator.generate_invoice_pdf(invoice)
if not pdf_path or not os.path.exists(pdf_path):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="Failed to generate invoice PDF",
)
# Return the PDF as a file
return FileResponse(
pdf_path,
media_type="application/pdf",
filename=f"invoice_{invoice.invoice_number}.pdf"
)