PocketAccountant: custom ledger UI + deterministic agent (engine, ledger, retrieval, classifier)
c55ab5e verified | """IVA — Impuesto al Valor Agregado (Mexico). | |
| IVA is a flow-through tax. Each month you net: | |
| IVA a cargo (payable) = IVA trasladado (collected on sales) | |
| − IVA acreditable (paid on deductible purchases) | |
| − IVA retenido (withheld from you by clients) | |
| A negative result is a *saldo a favor* (credit) you can carry forward or request | |
| back. The model never computes this — it calls ``iva_monthly`` and explains the | |
| ``breakdown``. | |
| """ | |
| from __future__ import annotations | |
| from .money import D, money | |
| from .result import CalcResult | |
| from .tax_tables import IVA_BORDER_MX, IVA_STANDARD_MX, IVA_ZERO_MX | |
| def iva_on_amount(amount, rate=IVA_STANDARD_MX) -> CalcResult: | |
| """IVA charged on a single taxable amount.""" | |
| base = D(amount) | |
| iva = base * D(rate) | |
| return CalcResult( | |
| amount=money(iva), | |
| label="IVA sobre el monto", | |
| breakdown=[("Base", money(base)), ("Tasa", D(rate)), ("IVA", money(iva))], | |
| source="LIVA Art. 1", | |
| ) | |
| def iva_monthly( | |
| iva_trasladado=0, iva_acreditable=0, iva_retenido=0 | |
| ) -> CalcResult: | |
| """Monthly net IVA position. | |
| Positive amount → IVA a cargo (you pay the SAT). | |
| Negative amount → saldo a favor (credit carried forward). | |
| """ | |
| trasladado = D(iva_trasladado) | |
| acreditable = D(iva_acreditable) | |
| retenido = D(iva_retenido) | |
| net = trasladado - acreditable - retenido | |
| if net >= 0: | |
| label = "IVA a cargo (mensual)" | |
| notes = [] | |
| else: | |
| label = "Saldo a favor de IVA (mensual)" | |
| notes = ["Negative net → credit; carry forward or request a refund."] | |
| return CalcResult( | |
| amount=money(net), | |
| label=label, | |
| breakdown=[ | |
| ("IVA trasladado (cobrado en ventas)", money(trasladado)), | |
| ("IVA acreditable (pagado en compras)", money(acreditable)), | |
| ("IVA retenido por clientes", money(retenido)), | |
| ("Neto", money(net)), | |
| ], | |
| source="LIVA Art. 5-D", | |
| notes=notes, | |
| ) | |
| # Convenience rate lookups so callers don't import tax_tables directly. | |
| RATE_STANDARD = IVA_STANDARD_MX | |
| RATE_BORDER = IVA_BORDER_MX | |
| RATE_ZERO = IVA_ZERO_MX | |