from datetime import datetime from sqlalchemy import Column, Integer, String, Float, DateTime, ForeignKey, Enum, Text, JSON from sqlalchemy.orm import relationship, DeclarativeBase import enum class Base(DeclarativeBase): pass class UserRole(str, enum.Enum): USER = "user" ADMIN = "admin" class UserStatus(str, enum.Enum): ACTIVE = "active" PENDING = "pending" DISABLED = "disabled" class DebtStatus(str, enum.Enum): ACTIVE = "active" PAID = "paid" OVERDUE = "overdue" CLOSED = "closed" class RateType(str, enum.Enum): ANNUAL = "annual" MONTHLY = "monthly" class RepaymentMethod(str, enum.Enum): EQUAL_INSTALLMENT = "equal_installment" INTEREST_FIRST = "interest_first" LUMP_SUM = "lump_sum" class PlanStatus(str, enum.Enum): PENDING = "pending" PAID = "paid" OVERDUE = "overdue" class NotificationType(str, enum.Enum): REPAYMENT_DUE = "repayment_due" REPAYMENT_OVERDUE = "repayment_overdue" SYSTEM = "system" ACCOUNT = "account" class Group(Base): __tablename__ = "groups" id = Column(Integer, primary_key=True, index=True) name = Column(String(100), nullable=False) description = Column(Text, default="") created_at = Column(DateTime, default=lambda: datetime.utcnow()) members = relationship("User", back_populates="group") class User(Base): __tablename__ = "users" id = Column(Integer, primary_key=True, index=True) email = Column(String(255), unique=True, index=True, nullable=False) real_email = Column(String(255), default="") password_hash = Column(String(255), nullable=False) nickname = Column(String(100), default="") role = Column(String(20), default=UserRole.USER.value) status = Column(String(20), default=UserStatus.ACTIVE.value) group_id = Column(Integer, ForeignKey("groups.id"), nullable=True) created_at = Column(DateTime, default=lambda: datetime.utcnow()) group = relationship("Group", back_populates="members") debts = relationship("Debt", back_populates="user") audit_logs = relationship("AuditLog", back_populates="user") class Debt(Base): __tablename__ = "debts" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False) creditor_name = Column(String(255), nullable=False) amount = Column(Integer, nullable=False) borrow_date = Column(DateTime, nullable=False) interest_rate = Column(Float, nullable=False) rate_type = Column(String(20), default=RateType.ANNUAL.value) repayment_method = Column(String(30), nullable=False) period_count = Column(Integer, nullable=False) period_unit = Column(String(10), default="month") status = Column(String(20), default=DebtStatus.ACTIVE.value) purpose = Column(String(255), default="") notes = Column(Text, default="") created_at = Column(DateTime, default=lambda: datetime.utcnow()) schedule_data = Column(JSON, default=list) paid_periods = Column(JSON, default=list) user = relationship("User", back_populates="debts") plans = relationship("RepaymentPlan", back_populates="debt", cascade="all, delete-orphan") records = relationship("RepaymentRecord", back_populates="debt", cascade="all, delete-orphan") class RepaymentPlan(Base): __tablename__ = "repayment_plans" id = Column(Integer, primary_key=True, index=True) debt_id = Column(Integer, ForeignKey("debts.id"), nullable=False) due_date = Column(DateTime, nullable=False) principal_due = Column(Integer, nullable=False) interest_due = Column(Integer, nullable=False) total_due = Column(Integer, nullable=False) status = Column(String(20), default=PlanStatus.PENDING.value) debt = relationship("Debt", back_populates="plans") records = relationship("RepaymentRecord", back_populates="plan") class RepaymentRecord(Base): __tablename__ = "repayment_records" id = Column(Integer, primary_key=True, index=True) debt_id = Column(Integer, ForeignKey("debts.id"), nullable=False) plan_id = Column(Integer, ForeignKey("repayment_plans.id"), nullable=True) amount = Column(Integer, nullable=False) paid_date = Column(DateTime, nullable=False) notes = Column(Text, default="") created_at = Column(DateTime, default=lambda: datetime.utcnow()) debt = relationship("Debt", back_populates="records") plan = relationship("RepaymentPlan", back_populates="records") class SystemSetting(Base): __tablename__ = "system_settings" key = Column(String(100), primary_key=True) value = Column(Text, nullable=False) class AuditLog(Base): __tablename__ = "audit_logs" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=True) action = Column(String(50), nullable=False) target_type = Column(String(50), default="") target_id = Column(Integer, nullable=True) details = Column(JSON, default=dict) created_at = Column(DateTime, default=lambda: datetime.utcnow()) user = relationship("User", back_populates="audit_logs") class Notification(Base): __tablename__ = "notifications" id = Column(Integer, primary_key=True, index=True) user_id = Column(Integer, ForeignKey("users.id"), nullable=False, index=True) title = Column(String(255), nullable=False) message = Column(Text, nullable=False) type = Column(String(30), default=NotificationType.SYSTEM.value) is_read = Column(Integer, default=0) related_debt_id = Column(Integer, nullable=True) related_plan_id = Column(Integer, nullable=True) created_at = Column(DateTime, default=lambda: datetime.utcnow()) user = relationship("User", backref="notifications")