Bobs_Tax_Project / user_session.py
rmd826's picture
Upload 9 files
a54f28a verified
Raw History Blame Contribute Delete
3.3 kB
# -*- coding: utf-8 -*-
"""
User session / profile management for the Tax Torpedo Analyzer.
Minimal profile with just the 3 inputs needed for torpedo analysis.
"""
from __future__ import annotations
from dataclasses import dataclass
from typing import Optional
@dataclass
class UserProfile:
"""Minimal financial profile for the Tax Torpedo Analyzer."""
filing_status: str = "MFJ"
ssb_annual: float = 0.0
other_income: float = 0.0
# Computed (cached after analysis)
tax_zone: Optional[str] = None
zero_point: Optional[float] = None # analyst convention (ref. TI)
confluence_point: Optional[float] = None # analyst convention (ref. TI)
zero_point_oi: Optional[float] = None # raw other income value
confluence_point_oi: Optional[float] = None # raw other income value
ref_taxable_income: Optional[float] = None
def to_dict(self) -> dict:
return {
"filing_status": self.filing_status,
"ssb_annual": self.ssb_annual,
"other_income": self.other_income,
"tax_zone": self.tax_zone,
"zero_point": self.zero_point,
"confluence_point": self.confluence_point,
"zero_point_oi": self.zero_point_oi,
"confluence_point_oi": self.confluence_point_oi,
"ref_taxable_income": self.ref_taxable_income,
}
@classmethod
def from_dict(cls, d: dict) -> "UserProfile":
if not d:
return cls()
return cls(
filing_status=d.get("filing_status", "MFJ"),
ssb_annual=d.get("ssb_annual", 0.0),
other_income=d.get("other_income", 0.0),
tax_zone=d.get("tax_zone"),
zero_point=d.get("zero_point"),
confluence_point=d.get("confluence_point"),
zero_point_oi=d.get("zero_point_oi"),
confluence_point_oi=d.get("confluence_point_oi"),
ref_taxable_income=d.get("ref_taxable_income"),
)
def summary_text(self) -> str:
"""Human-readable summary for system prompt context."""
lines = [
f"Filing Status: {self.filing_status_display(self.filing_status)}",
f"Annual Social Security Benefit: ${self.ssb_annual:,.0f}",
f"Total Other Taxable Income: ${self.other_income:,.0f}",
]
if self.tax_zone:
lines.append(f"Tax Zone: {self.tax_zone}")
if self.zero_point is not None:
lines.append(f"Zero Point (ref. taxable income): ${self.zero_point:,.0f}")
if self.confluence_point is not None:
lines.append(f"Confluence Point (ref. taxable income): ${self.confluence_point:,.0f}")
if self.zero_point_oi is not None:
lines.append(f"Zero Point (other income): ${self.zero_point_oi:,.0f}")
if self.confluence_point_oi is not None:
lines.append(f"Confluence Point (other income): ${self.confluence_point_oi:,.0f}")
return "\n".join(lines)
@staticmethod
def filing_status_display(code: str) -> str:
mapping = {
"SGL": "Single",
"MFJ": "Married Filing Jointly",
"HOH": "Head of Household",
"MFS": "Married Filing Separately",
}
return mapping.get(code, code)