259 lines
8.4 KiB
Python
259 lines
8.4 KiB
Python
"""
|
|
Pension calculation models based on legacy PENSION.SC analysis
|
|
"""
|
|
from sqlalchemy import Column, Integer, String, Date, Text, Float, ForeignKey
|
|
from sqlalchemy.orm import relationship
|
|
from app.models.base import BaseModel
|
|
|
|
|
|
class Pension(BaseModel):
|
|
"""
|
|
Pension calculation data
|
|
Corresponds to PENSIONS table in legacy system
|
|
"""
|
|
__tablename__ = "pensions"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
|
version = Column(String(10), default="01") # Version number
|
|
plan_id = Column(String(45)) # Plan identifier
|
|
plan_name = Column(String(200)) # Name of pension plan
|
|
|
|
# Participant information
|
|
title = Column(String(10)) # Mr., Mrs., Ms., etc.
|
|
first = Column(String(50)) # First name
|
|
last = Column(String(100)) # Last name
|
|
birth = Column(Date) # Date of birth
|
|
race = Column(String(1)) # Race code
|
|
sex = Column(String(1)) # M/F
|
|
|
|
# Pension calculation data
|
|
info = Column(Text) # Additional pension information
|
|
valu = Column(Float, default=0.0) # Pension valuation
|
|
accrued = Column(Float, default=0.0) # Accrued benefit
|
|
vested_per = Column(Float, default=0.0) # Vested percentage
|
|
start_age = Column(Integer) # Starting age for benefits
|
|
|
|
# Cost of living and withdrawal details
|
|
cola = Column(Float, default=0.0) # Cost of living adjustment
|
|
max_cola = Column(Float, default=0.0) # Maximum COLA
|
|
withdrawal = Column(String(45)) # Withdrawal method
|
|
pre_dr = Column(Float, default=0.0) # Pre-retirement discount rate
|
|
post_dr = Column(Float, default=0.0) # Post-retirement discount rate
|
|
tax_rate = Column(Float, default=0.0) # Tax rate
|
|
|
|
# Relationships
|
|
file = relationship("File", back_populates="pensions")
|
|
|
|
def __repr__(self):
|
|
return f"<Pension(file_no='{self.file_no}', plan_name='{self.plan_name}')>"
|
|
|
|
|
|
class PensionSchedule(BaseModel):
|
|
"""
|
|
Pension payment schedules
|
|
Corresponds to SCHEDULE table in legacy system
|
|
"""
|
|
__tablename__ = "pension_schedules"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
|
version = Column(String(10), default="01")
|
|
|
|
# Schedule details (legacy vesting fields)
|
|
start_date = Column(Date) # Start date for payments
|
|
end_date = Column(Date) # End date for payments
|
|
payment_amount = Column(Float, default=0.0) # Payment amount
|
|
frequency = Column(String(20)) # Monthly, quarterly, etc.
|
|
vests_on = Column(Date) # Legacy SCHEDULE.csv Vests_On
|
|
vests_at = Column(Float, default=0.0) # Legacy SCHEDULE.csv Vests_At (percent)
|
|
|
|
# Relationships
|
|
file = relationship("File", back_populates="pension_schedules")
|
|
|
|
|
|
class MarriageHistory(BaseModel):
|
|
"""
|
|
Marriage/divorce history for pension calculations
|
|
Corresponds to MARRIAGE table in legacy system
|
|
"""
|
|
__tablename__ = "marriage_history"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
|
|
|
# Marriage details
|
|
marriage_date = Column(Date) # Date of marriage
|
|
divorce_date = Column(Date) # Date of divorce/separation
|
|
spouse_name = Column(String(100)) # Spouse name
|
|
notes = Column(Text) # Additional notes
|
|
|
|
# Legacy MARRIAGE.csv fields
|
|
married_from = Column(Date)
|
|
married_to = Column(Date)
|
|
married_years = Column(Float, default=0.0)
|
|
service_from = Column(Date)
|
|
service_to = Column(Date)
|
|
service_years = Column(Float, default=0.0)
|
|
marital_percent = Column(Float, default=0.0)
|
|
|
|
# Relationships
|
|
file = relationship("File", back_populates="marriage_history")
|
|
|
|
|
|
class DeathBenefit(BaseModel):
|
|
"""
|
|
Death benefit information
|
|
Corresponds to DEATH table in legacy system
|
|
"""
|
|
__tablename__ = "death_benefits"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
|
|
|
# Death benefit details
|
|
beneficiary_name = Column(String(100)) # Beneficiary name
|
|
benefit_amount = Column(Float, default=0.0) # Benefit amount
|
|
benefit_type = Column(String(45)) # Type of death benefit
|
|
notes = Column(Text) # Additional notes
|
|
|
|
# Legacy DEATH.csv fields
|
|
lump1 = Column(Float, default=0.0)
|
|
lump2 = Column(Float, default=0.0)
|
|
growth1 = Column(Float, default=0.0)
|
|
growth2 = Column(Float, default=0.0)
|
|
disc1 = Column(Float, default=0.0)
|
|
disc2 = Column(Float, default=0.0)
|
|
|
|
# Relationships
|
|
file = relationship("File", back_populates="death_benefits")
|
|
|
|
|
|
class SeparationAgreement(BaseModel):
|
|
"""
|
|
Separation agreement details
|
|
Corresponds to SEPARATE table in legacy system
|
|
"""
|
|
__tablename__ = "separation_agreements"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
|
|
|
# Agreement details
|
|
agreement_date = Column(Date) # Date of agreement
|
|
terms = Column(Text) # Terms of separation
|
|
notes = Column(Text) # Additional notes
|
|
|
|
# Relationships
|
|
file = relationship("File", back_populates="separation_agreements")
|
|
|
|
|
|
class LifeTable(BaseModel):
|
|
"""
|
|
Life expectancy tables for actuarial calculations
|
|
Corresponds to LIFETABL table in legacy system
|
|
"""
|
|
__tablename__ = "life_tables"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
age = Column(Integer, nullable=False) # Age
|
|
# Rich typed columns reflecting legacy LIFETABL.csv headers
|
|
# LE_* = Life Expectancy, NA_* = Number Alive/Survivors
|
|
le_aa = Column(Float)
|
|
na_aa = Column(Float)
|
|
le_am = Column(Float)
|
|
na_am = Column(Float)
|
|
le_af = Column(Float)
|
|
na_af = Column(Float)
|
|
le_wa = Column(Float)
|
|
na_wa = Column(Float)
|
|
le_wm = Column(Float)
|
|
na_wm = Column(Float)
|
|
le_wf = Column(Float)
|
|
na_wf = Column(Float)
|
|
le_ba = Column(Float)
|
|
na_ba = Column(Float)
|
|
le_bm = Column(Float)
|
|
na_bm = Column(Float)
|
|
le_bf = Column(Float)
|
|
na_bf = Column(Float)
|
|
le_ha = Column(Float)
|
|
na_ha = Column(Float)
|
|
le_hm = Column(Float)
|
|
na_hm = Column(Float)
|
|
le_hf = Column(Float)
|
|
na_hf = Column(Float)
|
|
|
|
# Optional metadata retained for future variations
|
|
table_year = Column(Integer) # Year/version of table if known
|
|
table_type = Column(String(45)) # Source/type of table (optional)
|
|
|
|
|
|
class NumberTable(BaseModel):
|
|
"""
|
|
Numerical tables for calculations
|
|
Corresponds to NUMBERAL table in legacy system
|
|
"""
|
|
__tablename__ = "number_tables"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
month = Column(Integer, nullable=False)
|
|
# Rich typed NA_* columns reflecting legacy NUMBERAL.csv headers
|
|
na_aa = Column(Float)
|
|
na_am = Column(Float)
|
|
na_af = Column(Float)
|
|
na_wa = Column(Float)
|
|
na_wm = Column(Float)
|
|
na_wf = Column(Float)
|
|
na_ba = Column(Float)
|
|
na_bm = Column(Float)
|
|
na_bf = Column(Float)
|
|
na_ha = Column(Float)
|
|
na_hm = Column(Float)
|
|
na_hf = Column(Float)
|
|
|
|
# Optional metadata retained for future variations
|
|
table_type = Column(String(45))
|
|
description = Column(Text)
|
|
|
|
|
|
class PensionResult(BaseModel):
|
|
"""
|
|
Computed pension results summary
|
|
Corresponds to RESULTS table in legacy system
|
|
"""
|
|
__tablename__ = "pension_results"
|
|
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
|
|
# Optional linkage if present in future exports
|
|
file_no = Column(String(45))
|
|
version = Column(String(10))
|
|
|
|
# Columns observed in legacy RESULTS.csv header
|
|
accrued = Column(Float)
|
|
start_age = Column(Integer)
|
|
cola = Column(Float)
|
|
withdrawal = Column(String(45))
|
|
pre_dr = Column(Float)
|
|
post_dr = Column(Float)
|
|
tax_rate = Column(Float)
|
|
age = Column(Integer)
|
|
years_from = Column(Float)
|
|
life_exp = Column(Float)
|
|
ev_monthly = Column(Float)
|
|
payments = Column(Float)
|
|
pay_out = Column(Float)
|
|
fund_value = Column(Float)
|
|
pv = Column(Float)
|
|
mortality = Column(Float)
|
|
pv_am = Column(Float)
|
|
pv_amt = Column(Float)
|
|
pv_pre_db = Column(Float)
|
|
pv_annuity = Column(Float)
|
|
wv_at = Column(Float)
|
|
pv_plan = Column(Float)
|
|
years_married = Column(Float)
|
|
years_service = Column(Float)
|
|
marr_per = Column(Float)
|
|
marr_amt = Column(Float) |