fix: add us-cpa tax year rules and package metadata
This commit is contained in:
@@ -32,6 +32,13 @@ TOPIC_RULES = [
|
||||
]
|
||||
|
||||
|
||||
RISK_BY_CONFIDENCE = {
|
||||
"high": "low",
|
||||
"medium": "medium",
|
||||
"low": "high",
|
||||
}
|
||||
|
||||
|
||||
def _normalize_question(question: str) -> str:
|
||||
return question.strip().lower()
|
||||
|
||||
@@ -98,6 +105,7 @@ class QuestionEngine:
|
||||
"authorities": authorities,
|
||||
"conclusion": {"answer": answer, "summary": summary},
|
||||
"confidence": rule["confidence"],
|
||||
"riskLevel": RISK_BY_CONFIDENCE[rule["confidence"]],
|
||||
"followUpQuestions": [],
|
||||
"primaryLawRequired": False,
|
||||
}
|
||||
@@ -115,6 +123,7 @@ class QuestionEngine:
|
||||
"summary": "This question needs primary-law analysis before a reliable answer can be given.",
|
||||
},
|
||||
"confidence": "low",
|
||||
"riskLevel": "high",
|
||||
"followUpQuestions": [
|
||||
"What facts drive the section-level issue?",
|
||||
"Is there an existing return position or drafted treatment to review?",
|
||||
@@ -125,6 +134,9 @@ class QuestionEngine:
|
||||
|
||||
def render_analysis(analysis: dict[str, Any]) -> str:
|
||||
lines = [analysis["conclusion"]["summary"]]
|
||||
lines.append(
|
||||
f"Confidence: {analysis['confidence']}. Risk: {analysis['riskLevel']}."
|
||||
)
|
||||
if analysis["factsUsed"]:
|
||||
facts = ", ".join(f"{item['field']}={item['value']}" for item in analysis["factsUsed"])
|
||||
lines.append(f"Facts used: {facts}.")
|
||||
@@ -160,6 +172,8 @@ def render_memo(analysis: dict[str, Any]) -> str:
|
||||
"",
|
||||
"## Analysis",
|
||||
analysis["conclusion"]["summary"],
|
||||
f"Confidence: {analysis['confidence']}",
|
||||
f"Risk level: {analysis['riskLevel']}",
|
||||
"",
|
||||
"## Conclusion",
|
||||
analysis["conclusion"]["answer"],
|
||||
|
||||
@@ -1,45 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
STANDARD_DEDUCTION_2025 = {
|
||||
"single": 15750.0,
|
||||
"married_filing_jointly": 31500.0,
|
||||
"head_of_household": 23625.0,
|
||||
}
|
||||
|
||||
|
||||
TAX_BRACKETS_2025 = {
|
||||
"single": [
|
||||
(11925.0, 0.10),
|
||||
(48475.0, 0.12),
|
||||
(103350.0, 0.22),
|
||||
(197300.0, 0.24),
|
||||
(250525.0, 0.32),
|
||||
(626350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"married_filing_jointly": [
|
||||
(23850.0, 0.10),
|
||||
(96950.0, 0.12),
|
||||
(206700.0, 0.22),
|
||||
(394600.0, 0.24),
|
||||
(501050.0, 0.32),
|
||||
(751600.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"head_of_household": [
|
||||
(17000.0, 0.10),
|
||||
(64850.0, 0.12),
|
||||
(103350.0, 0.22),
|
||||
(197300.0, 0.24),
|
||||
(250500.0, 0.32),
|
||||
(626350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
}
|
||||
from us_cpa.tax_years import tax_year_rules
|
||||
|
||||
|
||||
def _as_float(value: Any) -> float:
|
||||
@@ -48,9 +11,9 @@ def _as_float(value: Any) -> float:
|
||||
return float(value)
|
||||
|
||||
|
||||
def tax_on_ordinary_income(amount: float, filing_status: str) -> float:
|
||||
def tax_on_ordinary_income(amount: float, filing_status: str, tax_year: int) -> float:
|
||||
taxable = max(0.0, amount)
|
||||
brackets = TAX_BRACKETS_2025[filing_status]
|
||||
brackets = tax_year_rules(tax_year)["ordinaryIncomeBrackets"][filing_status]
|
||||
lower = 0.0
|
||||
tax = 0.0
|
||||
for upper, rate in brackets:
|
||||
@@ -72,6 +35,7 @@ def resolve_required_forms(normalized: dict[str, Any]) -> list[str]:
|
||||
|
||||
|
||||
def normalize_case_facts(facts: dict[str, Any], tax_year: int) -> dict[str, Any]:
|
||||
rules = tax_year_rules(tax_year)
|
||||
filing_status = facts.get("filingStatus", "single")
|
||||
wages = _as_float(facts.get("wages"))
|
||||
interest = _as_float(facts.get("taxableInterest"))
|
||||
@@ -79,9 +43,9 @@ def normalize_case_facts(facts: dict[str, Any], tax_year: int) -> dict[str, Any]
|
||||
withholding = _as_float(facts.get("federalWithholding"))
|
||||
|
||||
adjusted_gross_income = wages + interest + business_income
|
||||
standard_deduction = STANDARD_DEDUCTION_2025[filing_status]
|
||||
standard_deduction = rules["standardDeduction"][filing_status]
|
||||
taxable_income = max(0.0, adjusted_gross_income - standard_deduction)
|
||||
income_tax = tax_on_ordinary_income(taxable_income, filing_status)
|
||||
income_tax = tax_on_ordinary_income(taxable_income, filing_status, tax_year)
|
||||
self_employment_tax = round(max(0.0, business_income) * 0.9235 * 0.153, 2)
|
||||
total_tax = round(income_tax + self_employment_tax, 2)
|
||||
total_payments = withholding
|
||||
|
||||
93
skills/us-cpa/src/us_cpa/tax_years.py
Normal file
93
skills/us-cpa/src/us_cpa/tax_years.py
Normal file
@@ -0,0 +1,93 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
TAX_YEAR_DATA: dict[int, dict[str, Any]] = {
|
||||
2024: {
|
||||
"standardDeduction": {
|
||||
"single": 14600.0,
|
||||
"married_filing_jointly": 29200.0,
|
||||
"head_of_household": 21900.0,
|
||||
},
|
||||
"ordinaryIncomeBrackets": {
|
||||
"single": [
|
||||
(11600.0, 0.10),
|
||||
(47150.0, 0.12),
|
||||
(100525.0, 0.22),
|
||||
(191950.0, 0.24),
|
||||
(243725.0, 0.32),
|
||||
(609350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"married_filing_jointly": [
|
||||
(23200.0, 0.10),
|
||||
(94300.0, 0.12),
|
||||
(201050.0, 0.22),
|
||||
(383900.0, 0.24),
|
||||
(487450.0, 0.32),
|
||||
(731200.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"head_of_household": [
|
||||
(16550.0, 0.10),
|
||||
(63100.0, 0.12),
|
||||
(100500.0, 0.22),
|
||||
(191950.0, 0.24),
|
||||
(243700.0, 0.32),
|
||||
(609350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
},
|
||||
},
|
||||
2025: {
|
||||
"standardDeduction": {
|
||||
"single": 15750.0,
|
||||
"married_filing_jointly": 31500.0,
|
||||
"head_of_household": 23625.0,
|
||||
},
|
||||
"ordinaryIncomeBrackets": {
|
||||
"single": [
|
||||
(11925.0, 0.10),
|
||||
(48475.0, 0.12),
|
||||
(103350.0, 0.22),
|
||||
(197300.0, 0.24),
|
||||
(250525.0, 0.32),
|
||||
(626350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"married_filing_jointly": [
|
||||
(23850.0, 0.10),
|
||||
(96950.0, 0.12),
|
||||
(206700.0, 0.22),
|
||||
(394600.0, 0.24),
|
||||
(501050.0, 0.32),
|
||||
(751600.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
"head_of_household": [
|
||||
(17000.0, 0.10),
|
||||
(64850.0, 0.12),
|
||||
(103350.0, 0.22),
|
||||
(197300.0, 0.24),
|
||||
(250500.0, 0.32),
|
||||
(626350.0, 0.35),
|
||||
(float("inf"), 0.37),
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def supported_tax_years() -> list[int]:
|
||||
return sorted(TAX_YEAR_DATA)
|
||||
|
||||
|
||||
def tax_year_rules(tax_year: int) -> dict[str, Any]:
|
||||
try:
|
||||
return TAX_YEAR_DATA[tax_year]
|
||||
except KeyError as exc:
|
||||
years = ", ".join(str(year) for year in supported_tax_years())
|
||||
raise ValueError(
|
||||
f"Unsupported tax year {tax_year}. Supported tax years: {years}."
|
||||
) from exc
|
||||
Reference in New Issue
Block a user