gmao/app_new/core/models/c4.py

110 lines
5.7 KiB
Python

"""Modèles C4 : contrats photocopieurs et stock de consommables partagé."""
from datetime import datetime, timezone
from ...extensions import db
class PhotocopierContract(db.Model):
__tablename__ = "photocopier_contracts"
id = db.Column(db.Integer, primary_key=True)
supplier_id = db.Column(db.Integer, db.ForeignKey("companies.id"), nullable=False, index=True)
name = db.Column(db.String(200), nullable=False)
reference = db.Column(db.String(120), nullable=True)
start_date = db.Column(db.Date, nullable=False)
end_date = db.Column(db.Date, nullable=False)
quota_start_date = db.Column(db.Date, nullable=True)
anniversary_month = db.Column(db.Integer, nullable=False)
anniversary_day = db.Column(db.Integer, nullable=False)
status = db.Column(db.String(20), nullable=False, default="ACTIVE", index=True)
notes = db.Column(db.Text, nullable=True)
created_at = db.Column(db.DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
closed_at = db.Column(db.Date, nullable=True)
supplier = db.relationship("Company")
periods = db.relationship("PhotocopierContractPeriod", back_populates="contract", cascade="all, delete-orphan", order_by="PhotocopierContractPeriod.start_date")
assignments = db.relationship("ContractEquipmentAssignment", back_populates="contract", cascade="all, delete-orphan")
class PhotocopierContractPeriod(db.Model):
__tablename__ = "photocopier_contract_periods"
__table_args__ = (
db.UniqueConstraint("contract_id", "start_date", name="uq_c4_contract_period_start"),
db.CheckConstraint("end_date >= start_date", name="ck_c4_period_dates"),
db.CheckConstraint("(quota_bw IS NULL OR quota_bw >= 0) AND (quota_color IS NULL OR quota_color >= 0)", name="ck_c4_period_quotas"),
)
id = db.Column(db.Integer, primary_key=True)
contract_id = db.Column(db.Integer, db.ForeignKey("photocopier_contracts.id", ondelete="CASCADE"), nullable=False, index=True)
start_date = db.Column(db.Date, nullable=False, index=True)
end_date = db.Column(db.Date, nullable=False, index=True)
quota_bw = db.Column(db.Integer, nullable=True)
quota_color = db.Column(db.Integer, nullable=True)
bw_included_unit_price = db.Column(db.Numeric(12, 6), nullable=True)
bw_overage_unit_price = db.Column(db.Numeric(12, 6), nullable=True)
color_included_unit_price = db.Column(db.Numeric(12, 6), nullable=True)
color_overage_unit_price = db.Column(db.Numeric(12, 6), nullable=True)
status = db.Column(db.String(20), nullable=False, default="OPEN")
contract = db.relationship("PhotocopierContract", back_populates="periods")
class ContractEquipmentAssignment(db.Model):
__tablename__ = "contract_equipment_assignments"
__table_args__ = (
db.UniqueConstraint("contract_id", "equipment_id", "entry_date", name="uq_c4_contract_equipment_entry"),
db.CheckConstraint("exit_date IS NULL OR exit_date >= entry_date", name="ck_c4_assignment_dates"),
)
id = db.Column(db.Integer, primary_key=True)
contract_id = db.Column(db.Integer, db.ForeignKey("photocopier_contracts.id", ondelete="CASCADE"), nullable=False, index=True)
equipment_id = db.Column(db.Integer, db.ForeignKey("equipments.id", ondelete="CASCADE"), nullable=False, index=True)
entry_date = db.Column(db.Date, nullable=False)
exit_date = db.Column(db.Date, nullable=True)
replacement_reason = db.Column(db.String(40), nullable=True)
replacement_comment = db.Column(db.Text, nullable=True)
contract = db.relationship("PhotocopierContract", back_populates="assignments")
equipment = db.relationship("Equipment")
class ConsumableOrder(db.Model):
__tablename__ = "consumable_orders"
__table_args__ = (
db.CheckConstraint("quantity_ordered > 0", name="ck_c4_order_quantity"),
db.CheckConstraint("quantity_received >= 0 AND quantity_received <= quantity_ordered", name="ck_c4_order_received"),
)
id = db.Column(db.Integer, primary_key=True)
consumable_id = db.Column(db.Integer, db.ForeignKey("consumables.id", ondelete="RESTRICT"), nullable=False, index=True)
supplier_id = db.Column(db.Integer, db.ForeignKey("companies.id"), nullable=True, index=True)
quantity_ordered = db.Column(db.Integer, nullable=False)
quantity_received = db.Column(db.Integer, nullable=False, default=0)
status = db.Column(db.String(30), nullable=False, default="TO_ORDER", index=True)
ordered_at = db.Column(db.DateTime, nullable=True)
received_at = db.Column(db.DateTime, nullable=True)
comment = db.Column(db.Text, nullable=True)
created_by_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
consumable = db.relationship("Consumable")
supplier = db.relationship("Company")
created_by = db.relationship("User")
receipts = db.relationship("ConsumableReceipt", back_populates="order", cascade="all, delete-orphan")
@property
def remaining_quantity(self):
return max((self.quantity_ordered or 0) - (self.quantity_received or 0), 0)
class ConsumableReceipt(db.Model):
__tablename__ = "consumable_receipts"
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, db.ForeignKey("consumable_orders.id", ondelete="CASCADE"), nullable=False, index=True)
quantity = db.Column(db.Integer, nullable=False)
received_at = db.Column(db.DateTime, nullable=False, default=lambda: datetime.now(timezone.utc))
received_by_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
comment = db.Column(db.Text, nullable=True)
order = db.relationship("ConsumableOrder", back_populates="receipts")
received_by = db.relationship("User")