fixes and refactor
This commit is contained in:
@@ -14,12 +14,12 @@ from .flexible import FlexibleImport
|
||||
from .support import SupportTicket, TicketResponse, TicketStatus, TicketPriority, TicketCategory
|
||||
from .pensions import (
|
||||
Pension, PensionSchedule, MarriageHistory, DeathBenefit,
|
||||
SeparationAgreement, LifeTable, NumberTable
|
||||
SeparationAgreement, LifeTable, NumberTable, PensionResult
|
||||
)
|
||||
from .lookups import (
|
||||
Employee, FileType, FileStatus, TransactionType, TransactionCode,
|
||||
State, GroupLookup, Footer, PlanInfo, FormIndex, FormList,
|
||||
PrinterSetup, SystemSetup
|
||||
PrinterSetup, SystemSetup, FormKeyword
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
@@ -28,8 +28,8 @@ __all__ = [
|
||||
"Deposit", "Payment", "FileNote", "FormVariable", "ReportVariable", "Document", "FlexibleImport",
|
||||
"SupportTicket", "TicketResponse", "TicketStatus", "TicketPriority", "TicketCategory",
|
||||
"Pension", "PensionSchedule", "MarriageHistory", "DeathBenefit",
|
||||
"SeparationAgreement", "LifeTable", "NumberTable",
|
||||
"SeparationAgreement", "LifeTable", "NumberTable", "PensionResult",
|
||||
"Employee", "FileType", "FileStatus", "TransactionType", "TransactionCode",
|
||||
"State", "GroupLookup", "Footer", "PlanInfo", "FormIndex", "FormList",
|
||||
"PrinterSetup", "SystemSetup"
|
||||
"PrinterSetup", "SystemSetup", "FormKeyword"
|
||||
]
|
||||
@@ -3,7 +3,7 @@ Audit logging models
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, JSON
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from app.models.base import BaseModel
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ class AuditLog(BaseModel):
|
||||
details = Column(JSON, nullable=True) # Additional details as JSON
|
||||
ip_address = Column(String(45), nullable=True) # IPv4/IPv6 address
|
||||
user_agent = Column(Text, nullable=True) # Browser/client information
|
||||
timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
timestamp = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False, index=True)
|
||||
|
||||
# Relationships
|
||||
user = relationship("User", back_populates="audit_logs")
|
||||
@@ -42,7 +42,7 @@ class LoginAttempt(BaseModel):
|
||||
ip_address = Column(String(45), nullable=False)
|
||||
user_agent = Column(Text, nullable=True)
|
||||
success = Column(Integer, default=0) # 1 for success, 0 for failure
|
||||
timestamp = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
timestamp = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False, index=True)
|
||||
failure_reason = Column(String(200), nullable=True) # Reason for failure
|
||||
|
||||
def __repr__(self):
|
||||
@@ -56,8 +56,8 @@ class ImportAudit(BaseModel):
|
||||
__tablename__ = "import_audit"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True, index=True)
|
||||
started_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
finished_at = Column(DateTime, nullable=True, index=True)
|
||||
started_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False, index=True)
|
||||
finished_at = Column(DateTime(timezone=True), nullable=True, index=True)
|
||||
status = Column(String(30), nullable=False, default="running", index=True) # running|success|completed_with_errors|failed
|
||||
|
||||
total_files = Column(Integer, nullable=False, default=0)
|
||||
@@ -94,7 +94,7 @@ class ImportAuditFile(BaseModel):
|
||||
errors = Column(Integer, nullable=False, default=0)
|
||||
message = Column(String(255), nullable=True)
|
||||
details = Column(JSON, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
||||
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False, index=True)
|
||||
|
||||
audit = relationship("ImportAudit", back_populates="files")
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Authentication-related persistence models
|
||||
"""
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
from sqlalchemy import Column, Integer, String, DateTime, Boolean, ForeignKey, UniqueConstraint
|
||||
@@ -19,10 +19,10 @@ class RefreshToken(BaseModel):
|
||||
jti = Column(String(64), nullable=False, unique=True, index=True)
|
||||
user_agent = Column(String(255), nullable=True)
|
||||
ip_address = Column(String(45), nullable=True)
|
||||
issued_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
expires_at = Column(DateTime, nullable=False, index=True)
|
||||
issued_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
||||
expires_at = Column(DateTime(timezone=True), nullable=False, index=True)
|
||||
revoked = Column(Boolean, default=False, nullable=False)
|
||||
revoked_at = Column(DateTime, nullable=True)
|
||||
revoked_at = Column(DateTime(timezone=True), nullable=True)
|
||||
|
||||
# relationships
|
||||
user = relationship("User")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""
|
||||
Lookup table models based on legacy system analysis
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, Float
|
||||
from sqlalchemy import Column, Integer, String, Text, Boolean, Float, ForeignKey
|
||||
from app.models.base import BaseModel
|
||||
|
||||
|
||||
@@ -53,6 +53,9 @@ class FileStatus(BaseModel):
|
||||
description = Column(String(200), nullable=False) # Description
|
||||
active = Column(Boolean, default=True) # Is status active
|
||||
sort_order = Column(Integer, default=0) # Display order
|
||||
# Legacy fields for typed import support
|
||||
send = Column(Boolean, default=True) # Should statements print by default
|
||||
footer_code = Column(String(45), ForeignKey("footers.footer_code")) # Default footer
|
||||
|
||||
def __repr__(self):
|
||||
return f"<FileStatus(code='{self.status_code}', description='{self.description}')>"
|
||||
@@ -169,9 +172,10 @@ class FormIndex(BaseModel):
|
||||
"""
|
||||
__tablename__ = "form_index"
|
||||
|
||||
form_id = Column(String(45), primary_key=True, index=True) # Form identifier
|
||||
form_id = Column(String(45), primary_key=True, index=True) # Form identifier (maps to Name)
|
||||
form_name = Column(String(200), nullable=False) # Form name
|
||||
category = Column(String(45)) # Form category
|
||||
keyword = Column(String(200)) # Legacy FORM_INX Name/Keyword pair
|
||||
active = Column(Boolean, default=True) # Is form active
|
||||
|
||||
def __repr__(self):
|
||||
@@ -189,6 +193,7 @@ class FormList(BaseModel):
|
||||
form_id = Column(String(45), nullable=False) # Form identifier
|
||||
line_number = Column(Integer, nullable=False) # Line number in form
|
||||
content = Column(Text) # Line content
|
||||
status = Column(String(45)) # Legacy FORM_LST Status
|
||||
|
||||
def __repr__(self):
|
||||
return f"<FormList(form_id='{self.form_id}', line={self.line_number})>"
|
||||
@@ -201,12 +206,34 @@ class PrinterSetup(BaseModel):
|
||||
"""
|
||||
__tablename__ = "printers"
|
||||
|
||||
# Core identity and basic configuration
|
||||
printer_name = Column(String(100), primary_key=True, index=True) # Printer name
|
||||
description = Column(String(200)) # Description
|
||||
driver = Column(String(100)) # Print driver
|
||||
port = Column(String(20)) # Port/connection
|
||||
default_printer = Column(Boolean, default=False) # Is default printer
|
||||
active = Column(Boolean, default=True) # Is printer active
|
||||
|
||||
# Legacy numeric printer number (from PRINTERS.csv "Number")
|
||||
number = Column(Integer)
|
||||
|
||||
# Legacy control sequences and formatting (from PRINTERS.csv)
|
||||
page_break = Column(String(50))
|
||||
setup_st = Column(String(200))
|
||||
reset_st = Column(String(200))
|
||||
b_underline = Column(String(100))
|
||||
e_underline = Column(String(100))
|
||||
b_bold = Column(String(100))
|
||||
e_bold = Column(String(100))
|
||||
|
||||
# Optional report configuration toggles (legacy flags)
|
||||
phone_book = Column(Boolean, default=False)
|
||||
rolodex_info = Column(Boolean, default=False)
|
||||
envelope = Column(Boolean, default=False)
|
||||
file_cabinet = Column(Boolean, default=False)
|
||||
accounts = Column(Boolean, default=False)
|
||||
statements = Column(Boolean, default=False)
|
||||
calendar = Column(Boolean, default=False)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Printer(name='{self.printer_name}', description='{self.description}')>"
|
||||
@@ -225,4 +252,19 @@ class SystemSetup(BaseModel):
|
||||
setting_type = Column(String(20), default="STRING") # DATA type (STRING, INTEGER, FLOAT, BOOLEAN)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<SystemSetup(key='{self.setting_key}', value='{self.setting_value}')>"
|
||||
return f"<SystemSetup(key='{self.setting_key}', value='{self.setting_value}')>"
|
||||
|
||||
|
||||
class FormKeyword(BaseModel):
|
||||
"""
|
||||
Form keyword lookup
|
||||
Corresponds to INX_LKUP table in legacy system
|
||||
"""
|
||||
__tablename__ = "form_keywords"
|
||||
|
||||
keyword = Column(String(200), primary_key=True, index=True)
|
||||
description = Column(String(200))
|
||||
active = Column(Boolean, default=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<FormKeyword(keyword='{self.keyword}')>"
|
||||
@@ -60,11 +60,13 @@ class PensionSchedule(BaseModel):
|
||||
file_no = Column(String(45), ForeignKey("files.file_no"), nullable=False)
|
||||
version = Column(String(10), default="01")
|
||||
|
||||
# Schedule details
|
||||
# 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")
|
||||
@@ -85,6 +87,15 @@ class MarriageHistory(BaseModel):
|
||||
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")
|
||||
@@ -105,6 +116,14 @@ class DeathBenefit(BaseModel):
|
||||
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")
|
||||
@@ -138,10 +157,36 @@ class LifeTable(BaseModel):
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
age = Column(Integer, nullable=False) # Age
|
||||
male_expectancy = Column(Float) # Male life expectancy
|
||||
female_expectancy = Column(Float) # Female life expectancy
|
||||
table_year = Column(Integer) # Year of table (e.g., 2023)
|
||||
table_type = Column(String(45)) # Type of table
|
||||
# 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):
|
||||
@@ -152,7 +197,63 @@ class NumberTable(BaseModel):
|
||||
__tablename__ = "number_tables"
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
table_type = Column(String(45), nullable=False) # Type of table
|
||||
key_value = Column(String(45), nullable=False) # Key identifier
|
||||
numeric_value = Column(Float) # Numeric value
|
||||
description = Column(Text) # Description
|
||||
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)
|
||||
@@ -3,7 +3,7 @@ Support ticket models for help desk functionality
|
||||
"""
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, Boolean, ForeignKey, Enum
|
||||
from sqlalchemy.orm import relationship
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
import enum
|
||||
|
||||
from app.models.base import BaseModel
|
||||
@@ -63,9 +63,9 @@ class SupportTicket(BaseModel):
|
||||
ip_address = Column(String(45)) # IP address
|
||||
|
||||
# Timestamps
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
||||
resolved_at = Column(DateTime)
|
||||
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
||||
updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc))
|
||||
resolved_at = Column(DateTime(timezone=True))
|
||||
|
||||
# Admin assignment
|
||||
assigned_to = Column(Integer, ForeignKey("users.id"))
|
||||
@@ -95,7 +95,7 @@ class TicketResponse(BaseModel):
|
||||
author_email = Column(String(100)) # For non-user responses
|
||||
|
||||
# Timestamps
|
||||
created_at = Column(DateTime, default=datetime.utcnow, nullable=False)
|
||||
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
|
||||
|
||||
# Relationships
|
||||
ticket = relationship("SupportTicket", back_populates="responses")
|
||||
|
||||
Reference in New Issue
Block a user