from sqlalchemy import Column, Integer, String, Text, Boolean, Float, Date, TIMESTAMP, ARRAY, ForeignKey, func from sqlalchemy.orm import relationship from database import Base class ChargerType(Base): __tablename__ = "charger_types" id = Column(Integer, primary_key=True) name = Column(String(100), nullable=False) description = Column(Text) created_at = Column(TIMESTAMP, server_default=func.now()) chargers = relationship("Charger", back_populates="charger_type") class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True) username = Column(String(50), unique=True, nullable=False) password_hash = Column(String(255), nullable=False) role = Column(String(20), nullable=False) company = Column(String(100)) name = Column(String(50), nullable=False) phone = Column(String(20)) email = Column(String(100)) is_active = Column(Boolean, default=True) created_at = Column(TIMESTAMP, server_default=func.now()) class Charger(Base): __tablename__ = "chargers" id = Column(String(50), primary_key=True) charger_type_id = Column(Integer, ForeignKey("charger_types.id")) name = Column(String(100), nullable=False) station_name = Column(String(100), nullable=False) location_detail = Column(Text) cpo_name = Column(String(100)) installed_at = Column(Date) gps_lat = Column(Float) gps_lng = Column(Float) is_active = Column(Boolean, default=True) created_at = Column(TIMESTAMP, server_default=func.now()) charger_type = relationship("ChargerType", back_populates="chargers") reports = relationship("Report", back_populates="charger") class Report(Base): __tablename__ = "reports" id = Column(Integer, primary_key=True) charger_id = Column(String(50), ForeignKey("chargers.id")) issue_types = Column(ARRAY(Text), nullable=False) issue_detail = Column(Text) error_code = Column(String(100)) occurred_at = Column(TIMESTAMP) contact = Column(String(20)) consent = Column(Boolean, default=False) gps_lat = Column(Float) gps_lng = Column(Float) status = Column(String(30), default="pending") reported_at = Column(TIMESTAMP, server_default=func.now()) charger = relationship("Charger", back_populates="reports") photos = relationship("ReportPhoto", back_populates="report", cascade="all, delete-orphan") repair_links = relationship("RepairReport", back_populates="report") class ReportPhoto(Base): __tablename__ = "report_photos" id = Column(Integer, primary_key=True) report_id = Column(Integer, ForeignKey("reports.id", ondelete="CASCADE")) file_path = Column(String(255), nullable=False) uploaded_at = Column(TIMESTAMP, server_default=func.now()) report = relationship("Report", back_populates="photos") class Repair(Base): __tablename__ = "repairs" id = Column(Integer, primary_key=True) mechanic_id = Column(Integer, ForeignKey("users.id")) repair_types = Column(ARRAY(Text), nullable=False) description = Column(Text, nullable=False) started_at = Column(TIMESTAMP, nullable=False) completed_at = Column(TIMESTAMP) result_status = Column(String(20), default="done") mechanic = relationship("User", foreign_keys=[mechanic_id]) report_links = relationship("RepairReport", back_populates="repair", cascade="all, delete-orphan") photos = relationship("RepairPhoto", back_populates="repair", cascade="all, delete-orphan") cost = relationship("RepairCost", back_populates="repair", uselist=False) class RepairReport(Base): __tablename__ = "repair_reports" repair_id = Column(Integer, ForeignKey("repairs.id", ondelete="CASCADE"), primary_key=True) report_id = Column(Integer, ForeignKey("reports.id", ondelete="CASCADE"), primary_key=True) repair = relationship("Repair", back_populates="report_links") report = relationship("Report", back_populates="repair_links") class RepairPhoto(Base): __tablename__ = "repair_photos" id = Column(Integer, primary_key=True) repair_id = Column(Integer, ForeignKey("repairs.id", ondelete="CASCADE")) photo_type = Column(String(10), default="after") file_path = Column(String(255), nullable=False) uploaded_at = Column(TIMESTAMP, server_default=func.now()) repair = relationship("Repair", back_populates="photos") class RepairCost(Base): __tablename__ = "repair_costs" id = Column(Integer, primary_key=True) repair_id = Column(Integer, ForeignKey("repairs.id", ondelete="CASCADE"), unique=True) root_cause = Column(Text) admin_note = Column(Text) cost_party_type = Column(String(20)) cost_party_manufacturer_id = Column(Integer, ForeignKey("users.id")) cost_party_custom = Column(String(100)) cost_amount = Column(Integer, default=0) cost_status = Column(String(20), default="pending") reviewed_by = Column(Integer, ForeignKey("users.id")) reviewed_at = Column(TIMESTAMP) repair = relationship("Repair", back_populates="cost") reviewer = relationship("User", foreign_keys=[reviewed_by]) manufacturer = relationship("User", foreign_keys=[cost_party_manufacturer_id]) class Improvement(Base): __tablename__ = "improvements" id = Column(Integer, primary_key=True) title = Column(String(200), nullable=False) category = Column(String(20), nullable=False) description = Column(Text, nullable=False) priority = Column(String(10), default="normal") part_name = Column(String(100)) status = Column(String(20), default="registered") manufacturer_id = Column(Integer, ForeignKey("users.id")) created_by = Column(Integer, ForeignKey("users.id")) sw_deploy_target = Column(Date) sw_deployed_at = Column(Date) manufacturer_memo = Column(Text) created_at = Column(TIMESTAMP, server_default=func.now()) manufacturer = relationship("User", foreign_keys=[manufacturer_id]) creator = relationship("User", foreign_keys=[created_by]) report_links = relationship("ImprovementReport", back_populates="improvement", cascade="all, delete-orphan") attachments = relationship("ImprovementAttachment", back_populates="improvement", cascade="all, delete-orphan") logs = relationship("ImprovementLog", back_populates="improvement", cascade="all, delete-orphan") class ImprovementReport(Base): __tablename__ = "improvement_reports" improvement_id = Column(Integer, ForeignKey("improvements.id", ondelete="CASCADE"), primary_key=True) report_id = Column(Integer, ForeignKey("reports.id", ondelete="CASCADE"), primary_key=True) improvement = relationship("Improvement", back_populates="report_links") report = relationship("Report") class ImprovementAttachment(Base): __tablename__ = "improvement_attachments" id = Column(Integer, primary_key=True) improvement_id = Column(Integer, ForeignKey("improvements.id", ondelete="CASCADE")) file_path = Column(String(255), nullable=False) file_name = Column(String(255)) uploaded_at = Column(TIMESTAMP, server_default=func.now()) improvement = relationship("Improvement", back_populates="attachments") class ImprovementLog(Base): __tablename__ = "improvement_logs" id = Column(Integer, primary_key=True) improvement_id = Column(Integer, ForeignKey("improvements.id", ondelete="CASCADE")) changed_by = Column(Integer, ForeignKey("users.id")) old_status = Column(String(20)) new_status = Column(String(20)) memo = Column(Text) changed_at = Column(TIMESTAMP, server_default=func.now()) improvement = relationship("Improvement", back_populates="logs") changer = relationship("User") class SystemSetting(Base): __tablename__ = "system_settings" key = Column(String(100), primary_key=True) value = Column(Text, nullable=False) updated_at = Column(TIMESTAMP, server_default=func.now(), onupdate=func.now())