# tdsdesk

tdsdesk is a command-line TDS desk for Indian businesses. It reads a payments register and a deductee master, works out the
section, rate and tax for every payment under FY-versioned rules (thresholds with catch-up, 206AA, 206AB, section 197
certificates, GST exclusion), allocates challans, computes section 201(1A) interest and the 234E fee, prepares 26Q
return data and 16A certificate data, and reconciles against a 26AS-style statement.

## Features

- FY-versioned rules data (`2024-25`, `2025-26`) with citations; no rates in code. Effective-dated slabs (194H changed on 1-Oct-2024).
- Sections 194C, 194J (professional and technical), 194I (plant and machinery, land and building), 194H, 194A, 194Q.
- Per deductee, per section threshold tracking with catch-up deduction at the crossing payment; 194Q on the excess only.
- Higher-rate rules 206AA (missing or inoperative PAN) and 206AB, and lower-deduction certificates with limit and validity window.
- TDS on the amount excluding separately stated GST; earlier-of-credit-and-payment date.
- Deposit due dates (7th, 30 April for March), interest 1% / 1.5% per month or part, late filing fee 234E.
- FIFO challan allocation by section group with shortfall and excess flags.
- 26Q deductee annexure (NSDL RPU-style columns, an intermediate format), section summary, challan details and 16A data as CSV.
- `explain` prints the whole derivation for one payment; `reconcile` compares with a 26AS-style CSV.

## Install

```bash
cd tdsdesk
uv venv .venv && uv pip install -p .venv/bin/python -e '.[dev]'
source .venv/bin/activate
```

## Quickstart

```bash
cd examples
tdsdesk compute payments.csv --deductees deductees.csv --fy 2025-26 -o tds.csv
tdsdesk thresholds --fy 2025-26 --only-crossed
tdsdesk interest -c challans.csv --as-on 2026-03-31
tdsdesk return 26Q --quarter Q2 --fy 2025-26 -c challans.csv -o out/ --filing-date 2025-11-10
tdsdesk explain P0046 -c challans.csv --as-on 2026-03-31
tdsdesk reconcile 26as.csv -c challans.csv --as-on 2026-03-31
```

`payments.csv`, `deductees.csv` and `challans.csv` are read from the current directory unless `-p`, `-d`, `-c` say otherwise.

## Input files

`deductees.csv`: `deductee_id, name, pan, type (individual|huf|company|firm), resident (Y/N), ldc_cert_no, ldc_section, ldc_limit, ldc_rate, ldc_valid_from, ldc_valid_to, specified_206ab (Y/N), pan_aadhaar_operative (Y/N)`

`payments.csv`: `payment_id, credit_date, payment_date, deductee_id, nature, amount, gst_amount, invoice_ref, deduction_date`
(`amount` includes GST; `gst_amount` is the separately stated part; dates `YYYY-MM-DD`; `deduction_date` is optional and defaults to the earlier of credit and payment date.)
Natures: `contract, professional_fees, technical_services, rent_land_building, rent_plant_machinery, commission, interest, purchase_of_goods`.

`challans.csv`: `bsr_code, date, challan_serial, amount, section` (section as `194C`, `94J`, `94JB` and similar).

`26as.csv`: `pan, section, amount_paid, tax_deducted, tax_deposited`.

## Usage with real output

The `examples/` data set is synthetic: 60 deductees (3 without PAN, 1 with an inoperative PAN, 1 non-resident, a 206AB-flagged vendor,
a section 197 certificate that expires on 30 Sep 2025), 900 payments across all sections, GST on most services, a few late
deductions, late challans and one short-paid challan. Regenerate it with `python examples/generate.py`.

### compute

```
$ tdsdesk compute payments.csv --deductees deductees.csv --fy 2025-26 -o tds.csv
warning: non-resident deductee D056 Khan Enterprises & Co: payments skipped (27Q / sec. 195 is out of scope)
                     TDS computation FY 2025-26                     
┏━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Section   ┃ Payments ┃ Base (excl. GST) ┃ Taxable base ┃     TDS ┃
┡━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ 194A      │       63 │          253,100 │      253,100 │  28,510 │
│ 194C      │      234 │        9,749,100 │    9,749,100 │ 141,492 │
│ 194H      │      108 │          577,600 │      511,500 │  21,948 │
│ 194I_LB   │      108 │        5,242,500 │    3,280,000 │ 328,000 │
│ 194I_PM   │       27 │          720,000 │            0 │       0 │
│ 194J_PROF │      162 │        4,229,500 │    4,229,500 │ 378,614 │
│ 194J_TECH │       90 │        3,140,100 │    3,140,100 │  62,802 │
│ 194Q      │       90 │       44,153,600 │    8,551,800 │  23,654 │
│ TOTAL     │      882 │       68,065,500 │   29,715,100 │ 985,020 │
└───────────┴──────────┴──────────────────┴──────────────┴─────────┘
882 payments computed (18 skipped) -> /tmp/claude-1000/tds.csv
```

`tds.csv` holds one row per payment: status, catch-up base, taxable base, effective rate, rate basis and TDS.

### thresholds

```
                                                Thresholds FY 2025-26                                                
┏━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ID   ┃ Deductee                  ┃ Section   ┃ Aggregate ┃ Threshold ┃ Headroom ┃ Pending ┃ State                 ┃
┡━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━┩
│ D001 │ Neha Gupta                │ 194C      │   807,300 │   100,000 │        - │       - │ crossed on 2025-05-09 │
│ D002 │ Sanjay Gupta              │ 194J_PROF │   288,700 │    50,000 │        - │       - │ crossed on 2025-05-06 │
│ D003 │ Tara Khan                 │ 194I_LB   │   895,000 │   600,000 │        - │       - │ crossed on 2025-09-18 │
│ D004 │ Meera Patil               │ 194C      │   319,000 │   100,000 │        - │       - │ crossed on 2025-07-14 │
│ D004 │ Meera Patil               │ 194H      │    31,700 │    20,000 │        - │       - │ crossed on 2026-02-21 │
```

### interest and challan allocation

```
                                                 Interest u/s 201(1A), FY 2025-26                                                 
┏━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━┓
┃ Payment ┃ Section   ┃   TDS ┃ Deducted   ┃ Due        ┃ Late deduction ┃ Late deposit ┃ Undeposited ┃ Undeposited int. ┃ Total ┃
┡━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━┩
│ P0006   │ 194C      │   798 │ 2025-05-09 │ 2025-06-07 │             16 │           24 │           0 │                0 │    40 │
│ P0059   │ 194C      │   790 │ 2025-06-03 │ 2025-07-07 │             16 │            0 │           0 │                0 │    16 │
│ P0081   │ 194C      │   653 │ 2025-05-03 │ 2025-06-07 │              0 │           29 │           0 │                0 │    29 │
│ P0083   │ 194C      │   408 │ 2025-05-04 │ 2025-06-07 │              0 │           18 │           0 │                0 │    18 │
│ P0087   │ 194C      │   365 │ 2025-05-06 │ 2025-06-07 │              0 │           11 │           0 │                0 │    11 │
└─────────┴───────────┴───────┴────────────┴────────────┴────────────────┴──────────────┴─────────────┴──────────────────┴───────┘
TDS deducted 985,020; deposited via challans 983,520; interest payable 811
flag: SHORTFALL P0894 (194C, deducted 2026-03-29): 404 not covered by any challan
flag: SHORTFALL P0895 (194C, deducted 2026-03-30): 1096 not covered by any challan
```

### return 26Q

```
                             Form 26Q Q2 FY 2025-26                             
┏━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Section ┃ Deductees ┃ Amount paid ┃ TDS deducted ┃ TDS deposited ┃ Shortfall ┃
┡━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ 94A     │         6 │      79,000 │        9,070 │         9,070 │         0 │
│ 94C     │        13 │   2,587,800 │       41,517 │        41,517 │         0 │
│ 94H     │         7 │     147,400 │        9,536 │         9,536 │         0 │
│ 94IB    │         1 │     635,000 │       63,500 │        63,500 │         0 │
│ 94JA    │         4 │     788,500 │       15,770 │        15,770 │         0 │
│ 94JB    │        10 │   1,182,600 │       92,108 │        92,108 │         0 │
│ TOTAL   │        36 │   5,420,300 │      231,501 │       231,501 │         0 │
└─────────┴───────────┴─────────────┴──────────────┴───────────────┴───────────┘
annexure      out/26Q_2025-26_Q2_deductee_annexure.csv
summary       out/26Q_2025-26_Q2_summary.csv
challans      out/26Q_2025-26_Q2_challans.csv
certificates  out/16A_2025-26_Q2.csv
Due date 2025-10-31; filed 2025-11-10: 10 day(s) late, sec. 234E fee 2,000
```

Files written to `out/`: the deductee annexure, section summary, challan details and `16A_...csv`.

### explain

A catch-up crossing with GST excluded:

```
Payment P0046  (INV/2504/0046)
Deductee      D026 Kestrel Software Pvt Ltd  PAN TEGCC1123B  type company
Nature        technical_services -> section 194J_TECH (Fees for technical services / royalty on sale of films), NSDL code 94JA
Authority     Sec. 194J(1)(ba): 2% on technical services, call centre and royalty for sale/distribution/exhibition of cinematographic films; same threshold proviso
Event date    2025-04-16 (earlier of credit 2025-04-16 / payment None)
Amount        42716 less GST 6516 = TDS base 36200
Threshold     aggregate threshold 50000; aggregate 39600 -> 75800
Status        aggregate_threshold_crossed
Catch-up      39600 of earlier payments deducted now, taxable base 75800 = 39600 + 36200
Rate          2% (before any section 197 certificate)
  75800 x 2% = 1516  [normal]
TDS           1516 (rounded to the nearest rupee, sec. 288B)
Deducted on   2025-04-16 (quarter Q1); deposit due 2025-05-07
Challan       0510308/30002 dated 2025-05-06: 1516
Interest      201(1A)(i) late deduction 0; 201(1A)(ii) late deposit 0; undeposited 0; total 0
Note          GST of 6516 excluded as separately stated
```

A deductee without PAN (206AA, 20%):

```
Payment P0298  (INV/2507/0298)
Deductee      D034 Harbor Freight Pvt Ltd  PAN not available  type company
Nature        commission -> section 194H (Commission or brokerage), NSDL code 94H
Authority     Sec. 194H: rate 5% reduced to 2% w.e.f. 1-Oct-2024 (Finance (No.2) Act 2024); threshold per FY
Event date    2025-07-20 (earlier of credit 2025-07-20 / payment None)
Amount        8614 less GST 1314 = TDS base 7300
Threshold     aggregate threshold 20000; aggregate 18000 -> 25300
Status        aggregate_threshold_crossed
Catch-up      18000 of earlier payments deducted now, taxable base 25300 = 18000 + 7300
Rate          20% (before any section 197 certificate)
  25300 x 20% = 5060  [206AA (no/inoperative PAN)]
TDS           5060 (rounded to the nearest rupee, sec. 288B)
Deducted on   2025-07-20 (quarter Q2); deposit due 2025-08-07
Challan       0510308/30013 dated 2025-08-04: 5060
Interest      201(1A)(i) late deduction 0; 201(1A)(ii) late deposit 0; undeposited 0; total 0
Note          GST of 1314 excluded as separately stated
```

A catch-up under a section 197 certificate at 2%:

```
Payment P0058  (INV/2504/0058)
Deductee      D031 Prism Consulting Pvt Ltd  PAN NWSCW8150J  type company
Nature        professional_fees -> section 194J_PROF (Fees for professional services), NSDL code 94JB
Authority     Sec. 194J(1)(b): 10% on professional services; proviso: no deduction if aggregate in FY does not exceed threshold
Event date    2025-04-21 (earlier of credit 2025-04-21 / payment 2025-05-30)
Amount        30916 less GST 4716 = TDS base 26200
Threshold     aggregate threshold 50000; aggregate 36700 -> 62900
Status        aggregate_threshold_crossed
Catch-up      36700 of earlier payments deducted now, taxable base 62900 = 36700 + 26200
Rate          10% (before any section 197 certificate)
  62900 x 2% = 1258  [197 certificate LDC/2025/0042]
TDS           1258 (rounded to the nearest rupee, sec. 288B)
Deducted on   2025-04-21 (quarter Q1); deposit due 2025-05-07
Challan       0510308/30002 dated 2025-05-06: 1258
Interest      201(1A)(i) late deduction 0; 201(1A)(ii) late deposit 0; undeposited 0; total 0
Note          GST of 4716 excluded as separately stated
```

206AB on FY 2024-25 (small hand-written data set in `examples/fy2024-25/`; the section was omitted from FY 2025-26):

```
Payment A2  (INV/002)
Deductee      V1 Redwood Services Pvt Ltd  PAN AABCR1234K  type company
Nature        professional_fees -> section 194J_PROF (Fees for professional services), NSDL code 94JB
Authority     Sec. 194J(1)(b): 10% on professional services; proviso: no deduction if aggregate in FY does not exceed threshold
Event date    2024-07-12 (earlier of credit 2024-07-12 / payment None)
Amount        118000 less GST 18000 = TDS base 100000
Threshold     aggregate threshold 30000; aggregate 0 -> 100000
Status        aggregate_threshold_crossed
Rate          20% (before any section 197 certificate)
  100000 x 20% = 20000  [206AB (specified person)]
TDS           20000 (rounded to the nearest rupee, sec. 288B)
Deducted on   2024-07-12 (quarter Q2); deposit due 2024-08-07
Challan       20000 not covered by any challan
Interest      201(1A)(i) late deduction 0; 201(1A)(ii) late deposit 0; undeposited 2700; total 2700
              - 20000 not deposited as on 2025-03-31: 9 month(s) at 1.5%
Note          GST of 18000 excluded as separately stated
```

### reconcile

`examples/26as.csv` has a changed tax figure, a changed amount, a missing row and an extra row planted in it.

```
                                                     Reconciliation                                                      
┏━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ PAN        ┃ Section ┃ Status           ┃ Detail                                                                      ┃
┡━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ CLPCX5938P │ 94H     │ MISMATCH         │ tds_deducted: books 1124 vs 26AS 624; tds_deposited: books 1124 vs 26AS 624 │
│ HFGCX7136P │ 94JB    │ MISMATCH         │ amount: books 104000 vs 26AS 129000                                         │
│ HYTPK7791G │ 94H     │ MISSING_IN_26AS  │                                                                             │
│ PANNOTAVBL │ 94A     │ MISSING_IN_26AS  │                                                                             │
│ PANNOTAVBL │ 94H     │ MISSING_IN_26AS  │                                                                             │
│ PANNOTAVBL │ 94Q     │ MISSING_IN_26AS  │                                                                             │
│ ZZZPZ9999Z │ 94C     │ MISSING_IN_BOOKS │                                                                             │
└────────────┴─────────┴──────────────────┴─────────────────────────────────────────────────────────────────────────────┘
63 PAN/section pairs: 56 match, 7 need attention
```

Deductees without a PAN always appear as missing in 26AS, which is the expected result.

## Configuration

No config file. Options common to all commands: `--fy` (default `2025-26`), `-d/--deductees`, `-p/--payments`, `-c/--challans`,
`--as-on` (date for undeposited-tax interest, default today) and `--no-194q` (buyer turnover did not exceed 10 crore).
Exit status is 2 with a one-line message for bad input (unknown FY, bad CSV value with file and line, unknown nature).
Rules are the JSON files in `src/tdsdesk/data/`.

## Architecture

| Module | Role |
|---|---|
| `rules.py`, `data/fy_*.json` | Load FY rules into typed objects |
| `loaders.py` | CSV parsing and validation with line numbers |
| `engine.py` | Thresholds, catch-up, rate selection, rounding |
| `challans.py` | FIFO challan allocation |
| `interest.py` | 201(1A) interest and 234E fee |
| `dates.py` | Month-or-part counting, due dates, quarters, FY |
| `returns.py` | 26Q, summary, challan and 16A CSVs |
| `recon.py` | 26AS reconciliation |
| `explain.py` | Narrative derivation |
| `pipeline.py`, `cli.py` | Wiring and the Click commands |

Deeper documents: [docs/rules.md](docs/rules.md) (sections, rates, citations), [docs/algorithms.md](docs/algorithms.md)
(catch-up, precedence, interest and FIFO with worked examples), [docs/limitations.md](docs/limitations.md).

## Tests

```bash
.venv/bin/pytest
```

75 tests: every section's rate and threshold in both FYs including exact-boundary and catch-up cases, 206AA / 206AB / 197
precedence, GST exclusion, rounding, month-or-part table, due dates including March, hand-computed interest and fee,
challan FIFO, return CSV shape and totals, explain, reconcile, loaders and the CLI against the example data.

## Limitations

Resident deductees and Form 26Q only; the 26Q output is an intermediate CSV, not an FVU file; some precedence rules and
thresholds are marked illustrative. Rules data should be verified against current law before use. See
[docs/limitations.md](docs/limitations.md). This tool is not tax advice.
