
- Set up project structure with modular organization - Implement database models for users, organizations, clients, invoices - Create Alembic migration scripts for database setup - Implement JWT-based authentication and authorization - Create API endpoints for users, organizations, clients, invoices - Add PDF generation for invoices using ReportLab - Add comprehensive documentation in README
53 lines
2.0 KiB
Python
53 lines
2.0 KiB
Python
import enum
|
|
from sqlalchemy import Column, String, Text, ForeignKey, Integer, Enum, Float, Date, Boolean
|
|
from sqlalchemy.orm import relationship
|
|
|
|
from app.db.base_class import Base
|
|
|
|
|
|
class InvoiceStatus(str, enum.Enum):
|
|
DRAFT = "draft"
|
|
SENT = "sent"
|
|
PAID = "paid"
|
|
OVERDUE = "overdue"
|
|
CANCELLED = "cancelled"
|
|
|
|
|
|
class Invoice(Base):
|
|
invoice_number = Column(String, index=True, nullable=False)
|
|
status = Column(Enum(InvoiceStatus), default=InvoiceStatus.DRAFT)
|
|
issue_date = Column(Date, nullable=False)
|
|
due_date = Column(Date, nullable=False)
|
|
subtotal = Column(Float(precision=2), nullable=False)
|
|
tax_rate = Column(Float(precision=2), default=0.0)
|
|
tax_amount = Column(Float(precision=2), default=0.0)
|
|
discount = Column(Float(precision=2), default=0.0)
|
|
total = Column(Float(precision=2), nullable=False)
|
|
notes = Column(Text)
|
|
terms = Column(Text)
|
|
is_recurring = Column(Boolean, default=False)
|
|
recurring_interval = Column(String)
|
|
|
|
# Foreign keys
|
|
client_id = Column(Integer, ForeignKey("client.id", ondelete="CASCADE"))
|
|
organization_id = Column(Integer, ForeignKey("organization.id", ondelete="CASCADE"))
|
|
created_by_id = Column(Integer, ForeignKey("user.id", ondelete="SET NULL"), nullable=True)
|
|
|
|
# Relationships
|
|
items = relationship("InvoiceItem", back_populates="invoice", cascade="all, delete-orphan")
|
|
client = relationship("Client", back_populates="invoices")
|
|
organization = relationship("Organization", back_populates="invoices")
|
|
created_by = relationship("User", back_populates="invoices")
|
|
|
|
|
|
class InvoiceItem(Base):
|
|
description = Column(String, nullable=False)
|
|
quantity = Column(Float(precision=2), nullable=False)
|
|
unit_price = Column(Float(precision=2), nullable=False)
|
|
amount = Column(Float(precision=2), nullable=False)
|
|
|
|
# Foreign key
|
|
invoice_id = Column(Integer, ForeignKey("invoice.id", ondelete="CASCADE"))
|
|
|
|
# Relationship
|
|
invoice = relationship("Invoice", back_populates="items") |