From c68ba45cebb36d7153e64e0f356fa51cab099ec1 Mon Sep 17 00:00:00 2001 From: HotSwapp <47397945+HotSwapp@users.noreply.github.com> Date: Tue, 7 Oct 2025 10:12:00 -0500 Subject: [PATCH] Add legacy SQLAlchemy models mapped from docs/legacy-schema.md: ROLODEX, PHONE, FILES (+R/V), LEDGER, FILESTAT, FOOTERS, EMPLOYEE, STATES, GRUPLKUP, PRINTERS, SETUP, DEPOSITS, PAYMENTS (legacy), TRNSTYPE, TRNSLKUP, PLANINFO, QDROS, PENSIONS (+RESULTS/MARRIAGE/DEATH/SCHEDULE/SEPARATE). Add appropriate FKs and indexes; keep modern models intact. --- app/models.py | 467 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 1 deletion(-) diff --git a/app/models.py b/app/models.py index adeb69f..93fd068 100644 --- a/app/models.py +++ b/app/models.py @@ -4,7 +4,7 @@ SQLAlchemy models for the Delphi database. All models inherit from Base which is configured in the database module. """ -from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Float, Text, Boolean +from sqlalchemy import Column, Integer, String, DateTime, ForeignKey, Float, Text, Boolean, Date, Numeric, Index, UniqueConstraint, ForeignKeyConstraint from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import func @@ -218,3 +218,468 @@ class ImportLog(Base): def __repr__(self): return f"" + + +# ----------------------------- +# Legacy schema models (read-only/migration support) +# Derived from docs/legacy-schema.md +# ----------------------------- + + +class Rolodex(Base): + """ + Legacy ROLODEX master table. + + Primary key is the human-readable `Id`. + """ + __tablename__ = "rolodex" + + id = Column(String, primary_key=True, index=True) # Id (TEXT) + prefix = Column(String) + first = Column(String) + middle = Column(String) + last = Column(String, index=True) + suffix = Column(String) + title = Column(String) + a1 = Column(String) + a2 = Column(String) + a3 = Column(String) + city = Column(String) + abrev = Column(String(2)) # state abbreviation + st = Column(String) # state name + zip = Column(String(10)) + email = Column(String) + dob = Column(Date) + ss = Column(String) # SS# + legal_status = Column(String) + group = Column(String) + memo = Column(Text) + + __table_args__ = ( + Index("ix_rolodex_last_first", "last", "first"), + Index("ix_rolodex_group", "group"), + Index("ix_rolodex_email", "email"), + ) + + +class LegacyPhone(Base): + """ + Legacy PHONE table (phones by Rolodex Id). + + Composite PK on (id, phone) to prevent duplicates per person. + """ + __tablename__ = "phone" + + id = Column(String, ForeignKey("rolodex.id", ondelete="CASCADE"), primary_key=True, index=True) + phone = Column(String, primary_key=True) + location = Column(String) + + __table_args__ = ( + Index("ix_phone_id", "id"), + ) + + +class TrnsType(Base): + """TRNSTYPE (transaction groups).""" + __tablename__ = "trnstype" + + t_type = Column(String, primary_key=True) + t_type_l = Column(String) + header = Column(String) + footer = Column(String) + + +class TrnsLkup(Base): + """TRNSLKUP (transaction codes).""" + __tablename__ = "trnslkup" + + t_code = Column(String, primary_key=True) + t_type = Column(String, ForeignKey("trnstype.t_type"), index=True) + t_type_l = Column(String) + amount = Column(Numeric(12, 2)) + description = Column(Text) + + +class Footers(Base): + """FOOTERS table for footer codes and labels.""" + __tablename__ = "footers" + + f_code = Column(String, primary_key=True) + f_footer = Column(Text) + + +class FileStat(Base): + """FILESTAT table for file statuses.""" + __tablename__ = "filestat" + + status = Column(String, primary_key=True) + definition = Column(Text) + send = Column(String) + footer_code = Column(String, ForeignKey("footers.f_code"), index=True) + + +class Employee(Base): + """EMPLOYEE table linking employees to `Rolodex` and rate.""" + __tablename__ = "employee" + + empl_num = Column(String, primary_key=True) + empl_id = Column(String, ForeignKey("rolodex.id"), index=True) + rate_per_hour = Column(Numeric(12, 2)) + + +class States(Base): + """STATES reference table.""" + __tablename__ = "states" + + abrev = Column(String(2), primary_key=True) + st = Column(String) + + +class GroupLkup(Base): + """GRUPLKUP reference table.""" + __tablename__ = "gruplkup" + + code = Column(String, primary_key=True) + description = Column(Text) + title = Column(String) + + +class Printers(Base): + """PRINTERS configuration table.""" + __tablename__ = "printers" + + number = Column(Integer, primary_key=True) + name = Column(String) + port = Column(String) + page_break = Column(String) + setup_st = Column(String) + phone_book = Column(String) + rolodex_info = Column(String) + envelope = Column(String) + file_cabinet = Column(String) + accounts = Column(String) + statements = Column(String) + calendar = Column(String) + reset_st = Column(String) + b_underline = Column(String) + e_underline = Column(String) + b_bold = Column(String) + e_bold = Column(String) + + +class Setup(Base): + """ + SETUP application configuration. Not strictly keyed in legacy; introduce surrogate PK. + """ + __tablename__ = "setup" + + id = Column(Integer, primary_key=True, autoincrement=True) + appl_title = Column(String) + l_head1 = Column(String) + l_head2 = Column(String) + l_head3 = Column(String) + l_head4 = Column(String) + l_head5 = Column(String) + l_head6 = Column(String) + l_head7 = Column(String) + l_head8 = Column(String) + l_head9 = Column(String) + l_head10 = Column(String) + default_printer = Column(Integer, ForeignKey("printers.number"), index=True) + + +class LegacyFile(Base): + """ + FILES (file cabinet) primary table. + """ + __tablename__ = "files" + + file_no = Column(String, primary_key=True, index=True) + id = Column(String, ForeignKey("rolodex.id"), index=True) + file_type = Column(String, index=True) + regarding = Column(Text) + opened = Column(Date) + closed = Column(Date) + empl_num = Column(String, ForeignKey("employee.empl_num"), index=True) + rate_per_hour = Column(Numeric(12, 2)) + status = Column(String, ForeignKey("filestat.status"), index=True) + footer_code = Column(String, ForeignKey("footers.f_code"), index=True) + opposing = Column(String, ForeignKey("rolodex.id"), index=True) + hours = Column(Numeric(12, 2)) + hours_p = Column(Numeric(12, 2)) + trust_bal = Column(Numeric(12, 2)) + trust_bal_p = Column(Numeric(12, 2)) + hourly_fees = Column(Numeric(12, 2)) + hourly_fees_p = Column(Numeric(12, 2)) + flat_fees = Column(Numeric(12, 2)) + flat_fees_p = Column(Numeric(12, 2)) + disbursements = Column(Numeric(12, 2)) + disbursements_p = Column(Numeric(12, 2)) + credit_bal = Column(Numeric(12, 2)) + credit_bal_p = Column(Numeric(12, 2)) + total_charges = Column(Numeric(12, 2)) + total_charges_p = Column(Numeric(12, 2)) + amount_owing = Column(Numeric(12, 2)) + amount_owing_p = Column(Numeric(12, 2)) + transferable = Column(Numeric(12, 2)) + memo = Column(Text) + + __table_args__ = ( + Index("ix_files_id", "id"), + Index("ix_files_opposing", "opposing"), + Index("ix_files_status", "status"), + Index("ix_files_type", "file_type"), + ) + + +class FilesR(Base): + """FILES_R relationships per file.""" + __tablename__ = "files_r" + + file_no = Column(String, ForeignKey("files.file_no", ondelete="CASCADE"), primary_key=True) + relationship = Column(String, primary_key=True) + rolodex_id = Column(String, ForeignKey("rolodex.id", ondelete="CASCADE"), primary_key=True) + + __table_args__ = ( + Index("ix_files_r_rolodex_id", "rolodex_id"), + ) + + +class FilesV(Base): + """FILES_V variables per file.""" + __tablename__ = "files_v" + + file_no = Column(String, ForeignKey("files.file_no", ondelete="CASCADE"), primary_key=True) + identifier = Column(String, primary_key=True) + response = Column(Text) + + +class Ledger(Base): + """LEDGER entries for time/charges per file.""" + __tablename__ = "ledger" + + file_no = Column(String, ForeignKey("files.file_no", ondelete="CASCADE"), primary_key=True) + date = Column(Date, index=True) + item_no = Column(Integer, primary_key=True) + empl_num = Column(String, ForeignKey("employee.empl_num"), index=True) + t_code = Column(String, ForeignKey("trnslkup.t_code"), index=True) + t_type = Column(String, ForeignKey("trnstype.t_type"), index=True) + t_type_l = Column(String) + quantity = Column(Numeric(12, 2)) + rate = Column(Numeric(12, 2)) + amount = Column(Numeric(12, 2)) + billed = Column(String(1)) # 'Y' or 'N' + note = Column(Text) + + __table_args__ = ( + Index("ix_ledger_file_date", "file_no", "date"), + ) + + +class Deposits(Base): + """DEPOSITS daily totals.""" + __tablename__ = "deposits" + + deposit_date = Column(Date, primary_key=True) + total = Column(Numeric(12, 2)) + + +class LegacyPayment(Base): + """PAYMENTS legacy payments (separate from modern `payments`).""" + __tablename__ = "payments_legacy" + + id = Column(Integer, primary_key=True, autoincrement=True) + deposit_date = Column(Date, ForeignKey("deposits.deposit_date"), index=True) + file_no = Column(String, ForeignKey("files.file_no"), index=True) + rolodex_id = Column(String, ForeignKey("rolodex.id"), index=True) + regarding = Column(Text) + amount = Column(Numeric(12, 2)) + note = Column(Text) + + +class PlanInfo(Base): + """PLANINFO reference table.""" + __tablename__ = "planinfo" + + plan_id = Column(String, primary_key=True) + plan_name = Column(String) + plan_type = Column(String) + empl_id_no = Column(String) + plan_no = Column(String) + nra = Column(String) + era = Column(String) + errf = Column(String) + colas = Column(String) + divided_by = Column(String) + drafted = Column(String) + benefit_c = Column(String) + qdro_c = Column(String) + rev = Column(String) # ^REV + pa = Column(String) # ^PA + form_name = Column(String) + drafted_on = Column(Date) + memo = Column(Text) + + +class Qdros(Base): + """QDROS table for QDRO case data.""" + __tablename__ = "qdros" + + file_no = Column(String, ForeignKey("files.file_no"), primary_key=True) + version = Column(String, primary_key=True) + plan_id = Column(String, ForeignKey("planinfo.plan_id"), index=True) + _1 = Column(String) # ^1 + _2 = Column(String) # ^2 + part = Column(String) # ^Part + altp = Column(String) # ^AltP + pet = Column(String) # ^Pet + res = Column(String) # ^Res + case_type = Column(String) + case_code = Column(String) + section = Column(String) + case_number = Column(String) + judgment_date = Column(Date) + valuation_date = Column(Date) + married_on = Column(Date) + percent_awarded = Column(Numeric(12, 2)) + ven_city = Column(String) + ven_cnty = Column(String) + ven_st = Column(String(2)) + draft_out = Column(Date) + draft_apr = Column(Date) + final_out = Column(Date) + judge = Column(String) + form_name = Column(String) + + +class Pensions(Base): + """PENSIONS primary table; composite key (file_no, version).""" + __tablename__ = "pensions" + + file_no = Column(String, ForeignKey("files.file_no"), primary_key=True) + version = Column(String, primary_key=True) + plan_id = Column(String, ForeignKey("planinfo.plan_id"), index=True) + plan_name = Column(String) + title = Column(String) + first = Column(String) + last = Column(String) + birth = Column(Date) + race = Column(String) + sex = Column(String) + info = Column(Date) + valu = Column(Date) + accrued = Column(Numeric(12, 2)) + vested_per = Column(Numeric(12, 2)) + start_age = Column(Numeric(12, 2)) + cola = Column(Numeric(12, 2)) + max_cola = Column(Numeric(12, 2)) + withdrawal = Column(Numeric(12, 2)) + pre_dr = Column(Numeric(12, 2)) + post_dr = Column(Numeric(12, 2)) + tax_rate = Column(Numeric(12, 2)) + + +class PensionResults(Base): + """RESULTS derived values per pension (by file_no, version).""" + __tablename__ = "pension_results" + + file_no = Column(String, primary_key=True) + version = Column(String, primary_key=True) + + accrued = Column(Numeric(12, 2)) + start_age = Column(Numeric(12, 2)) + cola = Column(Numeric(12, 2)) + withdrawal = Column(Numeric(12, 2)) + pre_dr = Column(Numeric(12, 2)) + post_dr = Column(Numeric(12, 2)) + tax_rate = Column(Numeric(12, 2)) + age = Column(Numeric(12, 2)) + years_from = Column(Numeric(12, 2)) + life_exp = Column(Numeric(12, 2)) + ev_monthly = Column(Numeric(12, 2)) + payments = Column(Numeric(12, 2)) + pay_out = Column(Numeric(12, 2)) + fund_value = Column(Numeric(12, 2)) + pv = Column(Numeric(12, 2)) + mortality = Column(Numeric(12, 2)) + pv_am = Column(Numeric(12, 2)) + pv_amt = Column(Numeric(12, 2)) + pv_pre_db = Column(Numeric(12, 2)) + pv_annuity = Column(Numeric(12, 2)) + wv_at = Column(Numeric(12, 2)) + pv_plan = Column(Numeric(12, 2)) + years_married = Column(Numeric(12, 2)) + years_service = Column(Numeric(12, 2)) + marr_per = Column(Numeric(12, 2)) + marr_amt = Column(Numeric(12, 2)) + + __table_args__ = ( + ForeignKeyConstraint(["file_no", "version"], ["pensions.file_no", "pensions.version"], ondelete="CASCADE"), + Index("ix_pension_results_file_version", "file_no", "version"), + ) + + +class PensionMarriage(Base): + """MARRIAGE periods related to pensions.""" + __tablename__ = "pension_marriage" + + id = Column(Integer, primary_key=True, autoincrement=True) + file_no = Column(String, nullable=False) + version = Column(String, nullable=False) + married_from = Column(Date) + married_to = Column(Date) + married_years = Column(Numeric(12, 2)) + service_from = Column(Date) + service_to = Column(Date) + service_years = Column(Numeric(12, 2)) + marital_pct = Column(Numeric(12, 2)) + + __table_args__ = ( + ForeignKeyConstraint(["file_no", "version"], ["pensions.file_no", "pensions.version"], ondelete="CASCADE"), + Index("ix_pension_marriage_file_version", "file_no", "version"), + ) + + +class PensionDeath(Base): + """DEATH related amounts for pensions.""" + __tablename__ = "pension_death" + + file_no = Column(String, primary_key=True) + version = Column(String, primary_key=True) + lump1 = Column(Numeric(12, 2)) + lump2 = Column(Numeric(12, 2)) + growth1 = Column(Numeric(12, 2)) + growth2 = Column(Numeric(12, 2)) + disc1 = Column(Numeric(12, 2)) + disc2 = Column(Numeric(12, 2)) + + __table_args__ = ( + ForeignKeyConstraint(["file_no", "version"], ["pensions.file_no", "pensions.version"], ondelete="CASCADE"), + ) + + +class PensionSchedule(Base): + """SCHEDULE vesting schedule for pensions.""" + __tablename__ = "pension_schedule" + + file_no = Column(String, primary_key=True) + version = Column(String, primary_key=True) + vests_on = Column(Date) + vests_at = Column(Numeric(12, 2)) + + __table_args__ = ( + ForeignKeyConstraint(["file_no", "version"], ["pensions.file_no", "pensions.version"], ondelete="CASCADE"), + ) + + +class PensionSeparate(Base): + """SEPARATE calculations for pensions.""" + __tablename__ = "pension_separate" + + file_no = Column(String, primary_key=True) + version = Column(String, primary_key=True) + separation_rate = Column(Numeric(12, 2)) + + __table_args__ = ( + ForeignKeyConstraint(["file_no", "version"], ["pensions.file_no", "pensions.version"], ondelete="CASCADE"), + )