Skip to content

India compliance — unified view

One-page overview of Indian statutory compliance the ERP touches: monthly GST, TDS, and audit-relevant exports. This is the "what's due when and where does it live in the app" reference — the deep mechanics live on the dedicated GST and TDS pages.

Audience: the CA or internal compliance lead who needs to know what the app emits and what still requires manual effort outside it.


1. Deadlines calendar

All dates refer to the month following the period being reported — e.g. GSTR-1 for April transactions is due 11 May.

Cadence Form Due date What it covers App support
Monthly GSTR-1 11th of next month Outward supplies (sales register) Export via Finance → Reports → GST Summary; payload builder in src/lib/gstReports.ts.
Monthly GSTR-3B 20th of next month (staggered for certain states) Summary return + GST payment Export via Finance → Reports → GST Summary; GSTN portal upload is stub.
Monthly TDS Form 281 (challan) 7th of next month TDS deposit to the government Not automated — see §5 gap list.
Quarterly Form 26Q End of month following quarter (31 Jul / 31 Oct / 31 Jan / 31 May) Non-salary TDS return Export CSV via Finance → TDS → Export 26Q (permission: finance.tds.export).
Annual Income Tax audit (3CA/3CD) 30 September Statutory audit package Exports via Reports + Chart of Accounts + exportFinanceWorkbook.ts.
Annual GSTR-9 / 9C 31 December Annual GST return + reconciliation No direct export; pull from GSTR-3B exports and reconcile externally.

Portal upload is still manual

The app builds the GSTR-1 / 3B JSON payload, but pushing it to the GSTN portal is a stub (src/lib/gstnApiClient.ts). Until the GSTN ASP/GSP integration is enabled, a finance user downloads the payload and uploads via the GSTN portal UI.


2. Registration artifacts in the app

2.1 GSTIN — party-level

Columns added by supabase/migrations/20260418150000_gst_primitives.sql:

Table Column Validator Note
Customer gstNumber isValidGstin() in src/lib/gstin.ts:40 Optional; required for B2B invoices to claim input credit.
Supplier gstNumber isValidGstin() Optional; determines whether we post 1400 GST Input Credit on the supplier invoice.
Agent gstNumber isValidGstin() Added in an earlier migration.

Validation is shape-only — the 15-character GSTIN regex. Checksum verification is deferred to the GST portal at upload time.

2.2 PAN — supplier level

Supplier.panNumber column — added by supabase/migrations/20260418150000_tds_scaffolding.sql:141.

  • Required on 26Q (a deductee without a PAN triggers the 20% penal rate per §206AA — the export surfaces this separately).
  • Free-text TEXT column; no DB-level format CHECK. UI-side regex validation lives in the supplier form.

2.3 HSN / SAC — line-item level

Columns added to (20260418150000_gst_primitives.sql):

Table hsnCode sacCode
QuotationLineItem
SupplierTransaction
Invoice
  • HSN = Harmonized System of Nomenclature (goods).
  • SAC = Services Accounting Code (services).
  • No DB CHECK on mutual exclusivity — travel is mostly SAC (998555 Tour operator services, etc.), but the table holds mixed goods + services historically.
  • GroupInvoice / AgentInvoice store line items as JSONB. HSN/SAC lives inside the JSON payload.

2.4 Default section + deducteeType — supplier-level TDS

Columns on Supplier (same migration):

  • tdsSection (text, nullable) — e.g. '194C', '194J', '194Q'.
  • deducteeType (text, default 'company') — one of 'individual' | 'huf' | 'company' | 'any'. Constrained by Supplier_deducteeType_check.

These pre-populate the "Deduct TDS" toggle on the supplier payment form so common cases (professional fees @ 10% to a registered consultant) don't require re-entering the section every time.


3. Month-end workflow (finance lead)

gantt
    title End-of-month compliance (April → May)
    dateFormat  YYYY-MM-DD
    section GST
    Close books for April (period lock)            :done,   book, 2026-04-30, 1d
    Export GSTR-1 JSON                              :active, gstr1, 2026-05-01, 3d
    Reconcile + upload GSTR-1 to portal             :       gstr1b, after gstr1, 5d
    File GSTR-1 (due 11 May)                        :crit,  gstr1c, 2026-05-10, 1d
    Export GSTR-3B payload + pay GST                :       gstr3b, 2026-05-12, 5d
    File GSTR-3B (due 20 May)                       :crit,  gstr3bc, 2026-05-19, 1d
    section TDS
    Generate Form 281 challans                       :      tds281, 2026-05-02, 2d
    Deposit TDS (due 7 May)                          :crit, tds281c, 2026-05-06, 1d
    Mark TDSDeduction rows status=deposited          :      tdsdep, 2026-05-07, 1d

Outline:

  1. Close April books. Lock AccountingPeriod for April — blocks any further postings into the month (overview.md §3).
  2. GSTR-1 (by 11 May). Finance → Reports → GST Summary → select April, export JSON. Upload to GSTN portal. Reconcile any discrepancies and file.
  3. TDS deposit (by 7 May). Review the TDS Deduction ledger for April with status pending. Generate challans (manual). Deposit via Income Tax portal. Mark rows deposited and stash challanNo
  4. challanDate.
  5. GSTR-3B (by 20 May). Export the 3B summary from the GST Summary report. Calculate net tax = output GST (2400) − input credit (1400). Pay on portal. File.
  6. Quarterly 26Q (at end of July for Q1 Apr–Jun). Export 26Q CSV (Finance → TDS → Export 26Q, permission finance.tds.export). File via TRACES / NSDL.

4. Where each artifact is produced

Artifact File / helper Entry point in UI
GSTIN validator src/lib/gstin.ts Runs client-side on every form that captures a GSTIN.
GSTR-1 / GSTR-3B payload builder src/lib/gstReports.ts Finance → Reports → GST Summary → Export.
GSTN portal client (stub) src/lib/gstnApiClient.ts Not yet wired to a button.
TDS calculator + thresholds src/lib/tds.ts Supplier payment form → "Deduct TDS" panel.
TDS rate seed supabase/migrations/20260418150000_tds_scaffolding.sql:113-134 Editable via a TDS rate master UI.
26Q CSV src/lib/tds.ts (exporter function) Finance → TDS → Export 26Q.
Statutory reports (TB, P&L, BS) src/lib/api.ts + RPC migrations (20260415180*_finance_*_rpc.sql) Finance → Reports.
Workbook export src/lib/exportFinanceWorkbook.ts Finance → Reports → Export Workbook.

5. Gap list (not yet automated)

Tracked work items the finance team should expect to do manually until these ship:

Gap What's missing Workaround today
GSTN portal direct upload gstnApiClient.ts is a stub. Download the generated JSON and upload via the portal UI.
TDS Form 281 challan generation No PDF / IT portal integration. Use the Income Tax portal directly with the figures from the TDS Deduction ledger.
TDSDeduction.status = deposited → certificate_issued flow No PATCH wired from the UI. Update the row directly in the admin console, or via /admin if a field-editor exists.
26AS reconciliation No import of the 26AS TDS-from-customers report. Download 26AS manually; reconcile in Excel against our AgentReceivable / customer invoices.
GSTR-9 / 9C annual return No dedicated export. Aggregate the monthly GSTR-1 + 3B exports externally.
Reverse charge (RCM) No explicit RCM flag on SupplierTransaction. Currently posted as a regular 1400 input credit; RCM detail lives in the memo.
E-invoicing (IRN) No IRN generation for B2B invoices > ₹5 Cr-threshold. Generate IRN on the portal and stamp it onto the invoice manually.
GSTIN checksum validation isValidGstin() does shape only. Portal rejects bad checksums at upload.
PAN format validation at DB level No CHECK constraint on Supplier.panNumber. UI regex only.
Period-lock audit signal Attempted posts into a locked period are rejected by the trigger but not logged to AuditLog. Check Postgres warning logs if needed.

6. What auditors will ask for, and where it lives

Ask Source
Full GL (chart + posted journals, period-bounded) Finance → Reports → Day Book export + Trial Balance; direct SQL on JournalEntry + JournalLine as a backstop.
Approval log for every journal (maker ≠ checker) AuditLog filtered to finance.voucher.approve; cross-join with JournalEntry.createdBy. See audit-trail.md §6.
GST input credit schedule Ledger of account 1400 GST Input Credit in the period.
GST output (payable) schedule Ledger of account 2400 GST Payable in the period.
TDS deduction register TDSDeduction table for the period, pulled via Finance → TDS → Export.
Opening / closing balances Trial Balance export at period boundary.
Fixed-asset register Ledgers of 1500 / 1510 / 1520 / 1530. Depreciation posting is manual journal via 6600 Depreciation.

7. Cross-references

  • GST (India) — GSTIN, HSN/SAC, GSTR-1 / 3B deep dive.
  • TDS (India) — sections, calculator, 26Q CSV.
  • Chart of accounts1400 GST Input Credit, 2400 GST Payable, 2401 TDS Payable.
  • Audit trail — statutory auditor's queries.
  • Reports — report catalog including GST Summary.
  • docs/PERMISSIONS.md §4.4 — finance.tds.* and finance.reports.gst_summary.* permissions.