PocketAccountant / src /engine /resico.py
eldinosaur's picture
PocketAccountant: custom ledger UI + deterministic agent (engine, ledger, retrieval, classifier)
c55ab5e verified
Raw
History Blame Contribute Delete
2.19 kB
"""RESICO — Régimen Simplificado de Confianza (Mexico), personas físicas.
The simplest and (for most freelancers) cheapest regime. ISR is a flat rate on
*total monthly income* — no deductions enter the ISR calculation. The rate is
chosen by an income bracket (Art. 113-E LISR), and the whole income is taxed at
that single rate (not marginally).
Eligibility caps annual income at $3,500,000 MXN; the engine flags when a user is
near or over the cap.
"""
from __future__ import annotations
from .money import D, money
from .result import CalcResult
from .tax_tables import (
RESICO_ANNUAL_INCOME_CAP_MX,
RESICO_MONTHLY_MX,
TaxTable,
)
def resico_isr_monthly(
monthly_income, table: TaxTable = RESICO_MONTHLY_MX
) -> CalcResult:
"""Flat-rate ISR on total monthly income under RESICO."""
income = D(monthly_income)
if income <= 0:
return CalcResult(
amount=money(0),
label="ISR RESICO (mensual)",
breakdown=[("Ingresos del mes", money(income))],
source=table.source,
effective_year=table.effective_year,
notes=["No income → no ISR this month."],
)
bracket = next(
b for b in table.brackets if b.upper is None or income <= b.upper
)
tax = income * bracket.rate
notes = []
# Projected annual income vs the eligibility cap (rough 12× signal).
projected_annual = income * 12
if projected_annual > RESICO_ANNUAL_INCOME_CAP_MX:
notes.append(
"At this monthly rate, projected annual income exceeds the "
f"${RESICO_ANNUAL_INCOME_CAP_MX:,.0f} RESICO cap — eligibility at risk."
)
return CalcResult(
amount=money(tax),
label="ISR RESICO (mensual)",
breakdown=[
("Ingresos del mes (amparados por CFDI)", money(income)),
("Tasa aplicable", bracket.rate),
],
source=table.source,
effective_year=table.effective_year,
notes=notes,
)
def resico_eligible(annual_income) -> bool:
"""True if annual income is within the RESICO eligibility cap."""
return D(annual_income) <= RESICO_ANNUAL_INCOME_CAP_MX