|
1 | 1 | """ |
2 | | -Deterministic ITR-2 tax calculator for FY 2025-26 (AY 2026-27). |
3 | | -Source: https://www.incometaxindia.gov.in/ |
| 2 | +Deterministic ITR-2 tax calculator. |
| 3 | +Slab rates, rebate, cess and the capital-gains / VDA special rates are loaded |
| 4 | +from the single source of truth (tax_rules.json via app.core.tax_rules), |
| 5 | +grounded in https://www.incometaxindia.gov.in/. |
4 | 6 |
|
5 | 7 | Reads from the new schema structure (schemas.jsonc). |
6 | 8 | """ |
7 | 9 | from app.core.field_calculator import _sum_list, _sum_nf_list, _nf |
| 10 | +from app.core import tax_rules |
8 | 11 |
|
9 | 12 |
|
10 | 13 | def calculate_itr2_tax(itr_doc: dict) -> dict: |
@@ -49,8 +52,8 @@ def calculate_itr2_tax(itr_doc: dict) -> dict: |
49 | 52 | for i in cg.get("long_term_gains", []) |
50 | 53 | if isinstance(i, dict) |
51 | 54 | ) |
52 | | - # LTCG exemption: 1L under Sec 112A for listed shares |
53 | | - ltg_taxable = max(ltg - 100000.0, 0.0) |
| 55 | + # LTCG exemption under Sec 112A for listed shares (rate from single source) |
| 56 | + ltg_taxable = max(ltg - tax_rules.capital_gains_rates()["ltcg_exemption"], 0.0) |
54 | 57 | else: |
55 | 58 | stg = ltg_taxable = 0.0 |
56 | 59 |
|
@@ -91,30 +94,21 @@ def calculate_itr2_tax(itr_doc: dict) -> dict: |
91 | 94 | regular_income = gross_salary + hp_income + other_income |
92 | 95 | taxable_income = max(regular_income - total_deductions, 0.0) |
93 | 96 |
|
94 | | - # ── Tax slabs on regular income only ───────────────────────────────── |
| 97 | + # ── Tax on regular slab income (rates from the single source of truth) ─ |
95 | 98 | tax_regime = itr_doc.get("tax_regime", "NEW").upper() |
96 | | - if tax_regime == "OLD": |
97 | | - tax = _compute_old_regime_tax(taxable_income) |
98 | | - rebate_limit = 500000.0 |
99 | | - rebate_max = 12500.0 |
100 | | - else: |
101 | | - tax = _compute_new_regime_tax(taxable_income) |
102 | | - rebate_limit = 700000.0 |
103 | | - rebate_max = 25000.0 |
104 | | - |
105 | | - # STCG at 15% (Sec 111A), LTCG at 10% (Sec 112A), VDA at 30% — special flat rates |
106 | | - stg_tax = stg * 0.15 |
107 | | - ltg_tax = ltg_taxable * 0.10 |
108 | | - vda_tax = vda_income * 0.30 |
109 | | - tax = tax + stg_tax + ltg_tax + vda_tax |
| 99 | + regular_tax = tax_rules.slab_tax(taxable_income, tax_regime) |
| 100 | + # Section 87A rebate / marginal relief applies only to regular slab tax, |
| 101 | + # never to the special-rate capital-gains / VDA income. |
| 102 | + regular_tax = tax_rules.apply_rebate_and_relief(taxable_income, regular_tax, tax_regime) |
110 | 103 |
|
111 | | - # Section 87A rebate applies only to regular slab tax (not CG/VDA) |
112 | | - if taxable_income <= rebate_limit: |
113 | | - regular_tax = tax - stg_tax - ltg_tax - vda_tax |
114 | | - rebate = min(regular_tax, rebate_max) |
115 | | - tax = max(tax - rebate, 0.0) |
| 104 | + # Special flat rates: STCG (Sec 111A), LTCG (Sec 112A), VDA (Sec 115BBH) |
| 105 | + rates = tax_rules.capital_gains_rates() |
| 106 | + stg_tax = stg * rates["stcg_rate"] |
| 107 | + ltg_tax = ltg_taxable * rates["ltcg_rate"] |
| 108 | + vda_tax = vda_income * rates["vda_rate"] |
| 109 | + tax = regular_tax + stg_tax + ltg_tax + vda_tax |
116 | 110 |
|
117 | | - tax = round(tax * 1.04, 2) # 4% cess |
| 111 | + tax = round(tax * (1.0 + tax_rules.cess_rate(tax_regime)), 2) # health & education cess |
118 | 112 |
|
119 | 113 | # ── Taxes paid ──────────────────────────────────────────────────────── |
120 | 114 | tp = itr_doc.get("taxes_paid", {}) |
@@ -145,35 +139,3 @@ def calculate_itr2_tax(itr_doc: dict) -> dict: |
145 | 139 | "refund_due": round(refund_due, 2), |
146 | 140 | "tax_regime": tax_regime |
147 | 141 | } |
148 | | - |
149 | | - |
150 | | -def _compute_old_regime_tax(income: float) -> float: |
151 | | - tax = 0.0 |
152 | | - if income > 1000000: |
153 | | - tax += (income - 1000000) * 0.30 |
154 | | - income = 1000000.0 |
155 | | - if income > 500000: |
156 | | - tax += (income - 500000) * 0.20 |
157 | | - income = 500000.0 |
158 | | - if income > 250000: |
159 | | - tax += (income - 250000) * 0.05 |
160 | | - return tax |
161 | | - |
162 | | - |
163 | | -def _compute_new_regime_tax(income: float) -> float: |
164 | | - tax = 0.0 |
165 | | - if income > 1500000: |
166 | | - tax += (income - 1500000) * 0.30 |
167 | | - income = 1500000.0 |
168 | | - if income > 1200000: |
169 | | - tax += (income - 1200000) * 0.20 |
170 | | - income = 1200000.0 |
171 | | - if income > 900000: |
172 | | - tax += (income - 900000) * 0.15 |
173 | | - income = 900000.0 |
174 | | - if income > 600000: |
175 | | - tax += (income - 600000) * 0.10 |
176 | | - income = 600000.0 |
177 | | - if income > 300000: |
178 | | - tax += (income - 300000) * 0.05 |
179 | | - return tax |
0 commit comments