landvex: Fixar och tester klara för alla komponenter
- Datafabrik: Dockerfile fix, agentorkestrering fungerar - Vision: Identify-modell, FAISS, OCR alla testade - API: Alla 7 integrationstester passerade - Upplösare: Entitetsupplösning verifierad
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
"""Billing and subscription models."""
|
||||
from datetime import datetime, date
|
||||
from decimal import Decimal
|
||||
from enum import Enum
|
||||
from uuid import UUID, uuid4
|
||||
|
||||
from sqlalchemy import String, ForeignKey, Date, Numeric, JSON
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.database import Base
|
||||
|
||||
|
||||
class SubscriptionPlan(Base):
|
||||
__tablename__ = "subscription_plans"
|
||||
|
||||
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
||||
name: Mapped[str] = mapped_column(String(100), nullable=False)
|
||||
slug: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
|
||||
description: Mapped[str | None]
|
||||
price_monthly: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
price_yearly: Mapped[Decimal | None] = mapped_column(Numeric(10, 2))
|
||||
features: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
limits: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
is_public: Mapped[bool] = mapped_column(default=True)
|
||||
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
tenants: Mapped[list["Tenant"]] = relationship(back_populates="plan")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<SubscriptionPlan {self.slug}>"
|
||||
|
||||
|
||||
class InvoiceStatus(str, Enum):
|
||||
DRAFT = "draft"
|
||||
SENT = "sent"
|
||||
PAID = "paid"
|
||||
OVERDUE = "overdue"
|
||||
CANCELLED = "cancelled"
|
||||
|
||||
|
||||
class Invoice(Base):
|
||||
__tablename__ = "invoices"
|
||||
|
||||
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
||||
tenant_id: Mapped[UUID] = mapped_column(
|
||||
ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
invoice_number: Mapped[str] = mapped_column(String(50), unique=True, nullable=False)
|
||||
period_start: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
period_end: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
tax_amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
total_amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
currency: Mapped[str] = mapped_column(String(3), default="SEK")
|
||||
status: Mapped[InvoiceStatus] = mapped_column(default=InvoiceStatus.DRAFT)
|
||||
paid_at: Mapped[datetime | None]
|
||||
stripe_invoice_id: Mapped[str | None] = mapped_column(String(100))
|
||||
pdf_url: Mapped[str | None]
|
||||
due_date: Mapped[date] = mapped_column(Date, nullable=False)
|
||||
created_at: Mapped[datetime] = mapped_column(default=datetime.utcnow)
|
||||
|
||||
# Relationships
|
||||
tenant: Mapped["Tenant"] = relationship(back_populates="invoices")
|
||||
items: Mapped[list["InvoiceItem"]] = relationship(
|
||||
back_populates="invoice", cascade="all, delete-orphan"
|
||||
)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<Invoice {self.invoice_number}>"
|
||||
|
||||
|
||||
class InvoiceItem(Base):
|
||||
__tablename__ = "invoice_items"
|
||||
|
||||
id: Mapped[UUID] = mapped_column(primary_key=True, default=uuid4)
|
||||
invoice_id: Mapped[UUID] = mapped_column(
|
||||
ForeignKey("invoices.id", ondelete="CASCADE"), nullable=False
|
||||
)
|
||||
description: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
quantity: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
unit_price: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
amount: Mapped[Decimal] = mapped_column(Numeric(10, 2), nullable=False)
|
||||
metadata: Mapped[dict] = mapped_column(JSON, default=dict)
|
||||
|
||||
# Relationships
|
||||
invoice: Mapped["Invoice"] = relationship(back_populates="items")
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"<InvoiceItem {self.description}>"
|
||||
Reference in New Issue
Block a user