from datetime import date from sqlalchemy import Column, Date, ForeignKey, Integer, Numeric, String, Text, Enum from sqlalchemy.orm import relationship import enum from app.db.session import Base from app.models.base import Base as CustomBase class InvoiceStatus(str, enum.Enum): """Enum for invoice statuses.""" DRAFT = "draft" SENT = "sent" PAID = "paid" OVERDUE = "overdue" CANCELLED = "cancelled" class Invoice(Base, CustomBase): """Invoice model for managing invoices.""" invoice_number = Column(String(50), nullable=False, index=True) status = Column(Enum(InvoiceStatus), default=InvoiceStatus.DRAFT) issue_date = Column(Date, nullable=False, default=date.today) due_date = Column(Date, nullable=False) subtotal = Column(Numeric(10, 2), nullable=False, default=0.00) tax_amount = Column(Numeric(10, 2), nullable=False, default=0.00) discount = Column(Numeric(10, 2), nullable=False, default=0.00) total = Column(Numeric(10, 2), nullable=False, default=0.00) notes = Column(Text, nullable=True) terms = Column(Text, nullable=True) # Foreign keys user_id = Column(Integer, ForeignKey("user.id"), nullable=False) customer_id = Column(Integer, ForeignKey("customer.id"), nullable=False) # Relationships user = relationship("User", back_populates="invoices") customer = relationship("Customer", back_populates="invoices") items = relationship("InvoiceItem", back_populates="invoice", cascade="all, delete-orphan") payments = relationship("Payment", back_populates="invoice", cascade="all, delete-orphan") class InvoiceItem(Base, CustomBase): """Model for items within an invoice.""" description = Column(String(255), nullable=False) quantity = Column(Numeric(10, 2), nullable=False, default=1.00) unit_price = Column(Numeric(10, 2), nullable=False) tax_rate = Column(Numeric(5, 2), nullable=False, default=0.00) tax_amount = Column(Numeric(10, 2), nullable=False, default=0.00) subtotal = Column(Numeric(10, 2), nullable=False) total = Column(Numeric(10, 2), nullable=False) # Foreign keys invoice_id = Column(Integer, ForeignKey("invoice.id"), nullable=False) product_id = Column(Integer, ForeignKey("product.id"), nullable=True) # Relationships invoice = relationship("Invoice", back_populates="items") product = relationship("Product", back_populates="invoice_items")