123 lines
5.1 KiB
Python
123 lines
5.1 KiB
Python
"""
|
|
Modèle Company - GMAO Collège
|
|
Gestion des entreprises et pièces
|
|
Compatible avec la base de données existante
|
|
"""
|
|
from datetime import datetime, timezone
|
|
from ...extensions import db
|
|
|
|
|
|
class Company(db.Model):
|
|
"""Entreprise externe."""
|
|
__tablename__ = "companies"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(200), nullable=False)
|
|
trade_name = db.Column(db.String(200), nullable=True)
|
|
siret = db.Column(db.String(14), nullable=True)
|
|
contact_name = db.Column(db.String(150), nullable=True)
|
|
contact_email = db.Column(db.String(200), nullable=True)
|
|
contact_phone = db.Column(db.String(20), nullable=True)
|
|
address = db.Column(db.Text, nullable=True)
|
|
specialty = db.Column(db.String(200), nullable=True)
|
|
rating = db.Column(db.Integer, nullable=True)
|
|
notes = db.Column(db.Text, nullable=True)
|
|
is_active = db.Column(db.Boolean, default=True)
|
|
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
|
|
tech1_name = db.Column(db.String(150), nullable=True)
|
|
tech1_phone = db.Column(db.String(20), nullable=True)
|
|
tech1_email = db.Column(db.String(200), nullable=True)
|
|
tech2_name = db.Column(db.String(150), nullable=True)
|
|
tech2_phone = db.Column(db.String(20), nullable=True)
|
|
tech2_email = db.Column(db.String(200), nullable=True)
|
|
tech3_name = db.Column(db.String(150), nullable=True)
|
|
tech3_phone = db.Column(db.String(20), nullable=True)
|
|
tech3_email = db.Column(db.String(200), nullable=True)
|
|
|
|
def __repr__(self):
|
|
return f"<Company {self.name}>"
|
|
|
|
|
|
class Part(db.Model):
|
|
"""Pièce détachée."""
|
|
__tablename__ = "parts"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(200), nullable=False)
|
|
reference = db.Column(db.String(100), nullable=True)
|
|
description = db.Column(db.Text, nullable=True)
|
|
category = db.Column(db.String(100), nullable=True)
|
|
unit = db.Column(db.String(20), nullable=True)
|
|
quantity = db.Column(db.Integer, default=0)
|
|
min_quantity = db.Column(db.Integer, default=0)
|
|
unit_price = db.Column(db.Float, nullable=True)
|
|
supplier = db.Column(db.String(200), nullable=True)
|
|
location = db.Column(db.String(200), 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 - utiliser back_populates pour éviter conflit
|
|
usages_list = db.relationship("InterventionPart", back_populates="part", lazy="dynamic")
|
|
stock_movements = db.relationship("PartStockMovement", back_populates="part", lazy="dynamic",
|
|
cascade="all, delete-orphan")
|
|
|
|
@property
|
|
def is_low_stock(self):
|
|
"""Vérifie si le stock est faible."""
|
|
return self.quantity <= self.min_quantity
|
|
|
|
def __repr__(self):
|
|
return f"<Part {self.name}>"
|
|
|
|
|
|
class PartStockMovement(db.Model):
|
|
"""Journal immuable des entrées, sorties et corrections de stock."""
|
|
__tablename__ = "part_stock_movements"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
part_id = db.Column(db.Integer, db.ForeignKey("parts.id", ondelete="CASCADE"), nullable=False, index=True)
|
|
user_id = db.Column(db.Integer, db.ForeignKey("users.id", ondelete="SET NULL"), nullable=True)
|
|
movement_type = db.Column(db.String(20), nullable=False)
|
|
quantity_delta = db.Column(db.Integer, nullable=False)
|
|
quantity_before = db.Column(db.Integer, nullable=False)
|
|
quantity_after = db.Column(db.Integer, nullable=False)
|
|
reason = db.Column(db.String(255), nullable=False)
|
|
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc), nullable=False)
|
|
|
|
part = db.relationship("Part", back_populates="stock_movements")
|
|
user = db.relationship("User")
|
|
|
|
|
|
class Alert(db.Model):
|
|
"""Alerte système."""
|
|
__tablename__ = "alerts"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
alert_type = db.Column(db.String(50), nullable=False)
|
|
title = db.Column(db.String(255), nullable=False)
|
|
message = db.Column(db.Text, nullable=False)
|
|
priority = db.Column(db.String(20), default="normale")
|
|
is_read = db.Column(db.Boolean, default=False)
|
|
is_resolved = db.Column(db.Boolean, default=False)
|
|
related_id = db.Column(db.Integer, nullable=True)
|
|
related_type = db.Column(db.String(50), nullable=True)
|
|
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
|
|
resolved_at = db.Column(db.DateTime, nullable=True)
|
|
resolved_by = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=True)
|
|
|
|
def __repr__(self):
|
|
return f"<Alert {self.title}>"
|
|
|
|
|
|
class Service(db.Model):
|
|
"""Service du collège."""
|
|
__tablename__ = "services"
|
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
name = db.Column(db.String(100), nullable=False)
|
|
description = db.Column(db.Text, nullable=True)
|
|
is_active = db.Column(db.Boolean, default=True)
|
|
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
|
|
|
|
def __repr__(self):
|
|
return f"<Service {self.name}>"
|