gmao/app_new/contracts/models.py
2026-08-14 16:02:25 +00:00

112 lines
No EOL
4.2 KiB
Python

"""
Modele Contract - GMAO College
Suivi des contrats d'entreprise pour les equipements/lots.
"""
from datetime import datetime, timezone, date
from ..extensions import db
class Contract(db.Model):
"""Contrat d'entreprise pour un lot ou un equipement."""
__tablename__ = "contracts"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(200), nullable=False)
contract_number = db.Column(db.String(100), nullable=True)
# Liaison : un contrat est lie a un lot et/ou un equipement
lot_id = db.Column(db.Integer, db.ForeignKey("lots.id"), nullable=True)
equipment_id = db.Column(db.Integer, db.ForeignKey("equipments.id"), nullable=True)
company_id = db.Column(db.Integer, db.ForeignKey("companies.id"), nullable=True)
# Dates
signed_date = db.Column(db.Date, nullable=True)
start_date = db.Column(db.Date, nullable=False)
end_date = db.Column(db.Date, nullable=True) # NULL = duree indeterminee
# Tacite reconduction
tacit_renewal = db.Column(db.Boolean, default=True)
renewal_period_days = db.Column(db.Integer, default=365) # reconduction par periode de X jours
# Delai de preavis pour resilier (en jours avant la date de fin)
notice_period_days = db.Column(db.Integer, nullable=True)
notice_deadline = db.Column(db.Date, nullable=True) # date limite pour envoyer le preavis
# Montant
annual_amount = db.Column(db.Float, nullable=True)
currency = db.Column(db.String(3), default="EUR")
# Statut
status = db.Column(db.String(20), default="actif") # actif, expire, resilie, en_attente
notes = db.Column(db.Text, nullable=True)
# Documents
contract_file = db.Column(db.String(500), nullable=True)
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
updated_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
# Relations
lot = db.relationship("Lot", backref=db.backref("contracts", lazy="dynamic"))
equipment = db.relationship("Equipment", backref=db.backref("contracts", lazy="dynamic"))
company = db.relationship("Company", backref=db.backref("contracts", lazy="dynamic"))
@property
def is_active(self):
"""True si le contrat est actif aujourd'hui."""
if self.status != "actif":
return False
today = date.today()
if self.start_date and today < self.start_date:
return False
if self.end_date and today > self.end_date:
return False
return True
@property
def is_expiring_soon(self):
"""True si le contrat expire dans les 90 prochains jours."""
if not self.end_date:
return False
days_left = (self.end_date - date.today()).days
return 0 <= days_left <= 90
@property
def days_until_expiry(self):
"""Nombre de jours avant l'expiration (negatif = expire)."""
if not self.end_date:
return None
return (self.end_date - date.today()).days
@property
def notice_deadline_calculated(self):
"""Calcule la date limite de preavis si pas definie manuellement."""
if self.notice_deadline:
return self.notice_deadline
if self.end_date and self.notice_period_days:
from datetime import timedelta
return self.end_date - timedelta(days=self.notice_period_days)
return None
@property
def must_send_notice_now(self):
"""True si le preavis doit etre envoye maintenant (deadline proche)."""
deadline = self.notice_deadline_calculated
if not deadline:
return False
days_left = (deadline - date.today()).days
return days_left <= 60 # alerte 60 jours avant
@property
def status_color(self):
"""Couleur du badge."""
if not self.is_active:
return "danger" if self.status == "expire" else "secondary"
if self.is_expiring_soon:
return "warning"
if self.must_send_notice_now:
return "warning"
return "success"
def __repr__(self):
return f"<Contract {self.name} ({self.status})>"