from datetime import date from sqlalchemy import ( Column, Integer, String, Float, Date, Boolean, ForeignKey, Enum, Text ) from sqlalchemy.orm import relationship import enum from database import Base class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) username = Column(String(50), unique=True, nullable=False, index=True) email = Column(String(200)) hashed_password = Column(String(200), nullable=False) is_admin = Column(Boolean, default=False) actif = Column(Boolean, default=True) created_at = Column(Date, default=date.today) class StatutDevis(str, enum.Enum): brouillon = "brouillon" envoye = "envoye" accepte = "accepte" refuse = "refuse" class StatutFacture(str, enum.Enum): emise = "emise" payee = "payee" annulee = "annulee" class Client(Base): __tablename__ = "clients" id = Column(Integer, primary_key=True, index=True) nom = Column(String(200), nullable=False) adresse = Column(String(300), nullable=False) code_postal = Column(String(10), nullable=False) ville = Column(String(100), nullable=False) email = Column(String(200)) telephone = Column(String(20)) siret = Column(String(14)) actif = Column(Boolean, default=True) devis = relationship("Devis", back_populates="client") factures = relationship("Facture", back_populates="client") class LigneDevis(Base): __tablename__ = "lignes_devis" id = Column(Integer, primary_key=True, index=True) devis_id = Column(Integer, ForeignKey("devis.id"), nullable=False) description = Column(Text, nullable=False) quantite = Column(Float, nullable=False, default=1.0) prix_unitaire_ht = Column(Float, nullable=False) ordre = Column(Integer, default=0) devis = relationship("Devis", back_populates="lignes") @property def total_ht(self): return self.quantite * self.prix_unitaire_ht class Devis(Base): __tablename__ = "devis" id = Column(Integer, primary_key=True, index=True) numero = Column(String(20), unique=True, nullable=False) date_emission = Column(Date, nullable=False, default=date.today) date_validite = Column(Date, nullable=False) client_id = Column(Integer, ForeignKey("clients.id"), nullable=False) statut = Column(Enum(StatutDevis), default=StatutDevis.brouillon) notes = Column(Text) conditions = Column(Text) client = relationship("Client", back_populates="devis") lignes = relationship("LigneDevis", back_populates="devis", order_by="LigneDevis.ordre", cascade="all, delete-orphan") factures = relationship("Facture", back_populates="devis_origine") @property def total_ht(self): return sum(l.total_ht for l in self.lignes) class LigneFacture(Base): __tablename__ = "lignes_factures" id = Column(Integer, primary_key=True, index=True) facture_id = Column(Integer, ForeignKey("factures.id"), nullable=False) description = Column(Text, nullable=False) quantite = Column(Float, nullable=False, default=1.0) prix_unitaire_ht = Column(Float, nullable=False) ordre = Column(Integer, default=0) facture = relationship("Facture", back_populates="lignes") @property def total_ht(self): return self.quantite * self.prix_unitaire_ht class Facture(Base): __tablename__ = "factures" id = Column(Integer, primary_key=True, index=True) numero = Column(String(20), unique=True, nullable=False) date_emission = Column(Date, nullable=False, default=date.today) date_echeance = Column(Date, nullable=False) client_id = Column(Integer, ForeignKey("clients.id"), nullable=False) devis_id = Column(Integer, ForeignKey("devis.id"), nullable=True) statut = Column(Enum(StatutFacture), default=StatutFacture.emise) notes = Column(Text) conditions_reglement = Column(Text, default="Paiement à réception de facture.") date_paiement = Column(Date, nullable=True) client = relationship("Client", back_populates="factures") devis_origine = relationship("Devis", back_populates="factures") lignes = relationship("LigneFacture", back_populates="facture", order_by="LigneFacture.ordre", cascade="all, delete-orphan") @property def total_ht(self): return sum(l.total_ht for l in self.lignes)