Spaces:
Sleeping
Sleeping
File size: 6,211 Bytes
f9ba6a9 6153aab ea7352f d7dc866 cd9bdbe d7dc866 cd9bdbe d7dc866 cd9bdbe d7dc866 cd9bdbe 6153aab 49c4331 9cdda17 6153aab 49c4331 6153aab 49c4331 67d26ff 49c4331 6153aab b9ec576 6153aab 49c4331 6153aab 49c4331 6153aab 2b9b19c 6153aab 49c4331 6153aab 49c4331 5e6e3b3 49c4331 6153aab 49c4331 4b8a633 49c4331 c370c93 49c4331 6153aab 5e6e3b3 6153aab 49c4331 6153aab 4b8a633 5e6e3b3 6153aab c370c93 49c4331 c370c93 49c4331 c370c93 49c4331 886a6a9 dce516f f9ba6a9 dce516f 886a6a9 f9ba6a9 dce516f 9cdda17 886a6a9 f9ba6a9 dce516f 4b4aa27 f9ba6a9 4b4aa27 f9ba6a9 4b4aa27 f9ba6a9 b9ec576 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from datetime import datetime
from typing import Optional, List
from pydantic import BaseModel
# SMART IMPORT for both environments
try:
from backend.models.invoice import Invoice, InvoiceItem # Add InvoiceItem here
from backend.core.database import get_db
except ImportError:
from models.invoice import Invoice, InvoiceItem # And add it here
from core.database import get_db
router = APIRouter(prefix="/invoices", tags=["Invoices"])
class ItemCreate(BaseModel):
# These are now defined for every single row
patient_name: str
shade: str
description: str
quantity: int
price_per_unit: float
class InvoiceCreate(BaseModel):
# General Info (Header)
date: Optional[datetime] = None
doctor_name: str
clinic_name: str
# Financials & Notes
received_amount: float = 0.0
notes: Optional[str] = None
# The list of rows containing the patient info
items: List[ItemCreate]
class InvoiceUpdate(BaseModel):
date: Optional[datetime] = None
doctor_name: str
clinic_name: str
received_amount: float = 0.0
notes: Optional[str] = None
items: List[ItemCreate]
@router.post("/")
def create_invoice(data: InvoiceCreate, db: Session = Depends(get_db)):
# 1. Calculate the total by summing all items in the list
total_amount = sum(item.quantity * item.price_per_unit for item in data.items)
# 2. Create the Main Invoice (The Header)
new_invoice = Invoice(
date=data.date or datetime.utcnow(),
doctor_name=data.doctor_name,
clinic_name=data.clinic_name,
total_amount=total_amount,
received_amount=data.received_amount,
remaining_balance=total_amount - data.received_amount,
notes=data.notes,
invoice_no=None # Placeholder for the flush
)
db.add(new_invoice)
db.flush() # Secure the ID from the database
# Generate the professional ID (e.g., INV-0042)
new_invoice.invoice_no = f"INV-{new_invoice.id:04d}"
# 3. Save each row (The Items)
for item in data.items:
db.add(InvoiceItem(
invoice_id=new_invoice.id,
patient_name=item.patient_name, # Row-specific
shade=item.shade, # Row-specific
description=item.description,
quantity=item.quantity,
price_per_unit=item.price_per_unit,
total_price=item.quantity * item.price_per_unit
))
try:
db.commit()
db.refresh(new_invoice)
return {"status": "success", "invoice_no": new_invoice.invoice_no, "id": new_invoice.id}
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@router.get("/{invoice_id}")
def get_invoice(invoice_id: int, db: Session = Depends(get_db)):
# Look for the invoice and include its items
invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
if not invoice:
raise HTTPException(status_code=404, detail="Invoice not found")
return {
"id": invoice.id,
"invoice_no": invoice.invoice_number,
"date": invoice.date,
"doctor_name": invoice.doctor_name,
"clinic_name": invoice.clinic_name,
"total_amount": invoice.total_amount,
"received_amount": invoice.received_amount,
"remaining_balance": invoice.remaining_balance,
"items": [
{
"patient_name": item.patient_name,
"shade": item.shade,
"description": item.description,
"quantity": item.quantity,
"price_per_unit": item.price_per_unit,
"total_price": item.total_price
} for item in invoice.items
]
}
@router.get("/")
def get_all_invoices(db: Session = Depends(get_db)):
invoices = db.query(Invoice).order_by(Invoice.id.desc()).all()
# Include the formatted invoice_no in the response
return [{
"id": inv.id,
"invoice_no": inv.invoice_number,
"doctor_name": inv.doctor_name,
"clinic_name": inv.clinic_name,
"total_amount": inv.total_amount,
"received_amount": inv.received_amount,
"date": inv.date
} for inv in invoices]
# DELETE an invoice
@router.delete("/{invoice_id}")
def delete_invoice(invoice_id: int, db: Session = Depends(get_db)):
db_invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
if not db_invoice:
raise HTTPException(status_code=404, detail="Invoice not found")
db.delete(db_invoice)
db.commit()
return {"message": "Deleted successfully"}
@router.put("/{invoice_id}")
def update_invoice(invoice_id: int, data: InvoiceUpdate, db: Session = Depends(get_db)):
invoice = db.query(Invoice).filter(Invoice.id == invoice_id).first()
if not invoice:
raise HTTPException(status_code=404, detail="Invoice not found")
total_amount = sum(item.quantity * item.price_per_unit for item in data.items)
invoice.date = data.date or datetime.utcnow()
invoice.doctor_name = data.doctor_name
invoice.clinic_name = data.clinic_name
invoice.total_amount = total_amount
invoice.received_amount = data.received_amount
invoice.remaining_balance = total_amount - data.received_amount
invoice.notes = data.notes
# Delete old items and replace with new ones
db.query(InvoiceItem).filter(InvoiceItem.invoice_id == invoice_id).delete()
for item in data.items:
db.add(InvoiceItem(
invoice_id=invoice.id,
patient_name=item.patient_name,
shade=item.shade,
description=item.description,
quantity=item.quantity,
price_per_unit=item.price_per_unit,
total_price=item.quantity * item.price_per_unit
))
try:
db.commit()
db.refresh(invoice)
return {"status": "success", "invoice_no": invoice.invoice_no, "id": invoice.id}
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
|