# Form 16 – Full Process: Credit & Debit Notes (Incoming & Outgoing) This document describes the end-to-end flow for Form 16 (Form 16A TDS Credit): 26AS reconciliation, credit/debit note creation, WFM/SAP incoming and outgoing file handling, and how users view SAP responses. --- ## 1. High-Level Flow - **26AS**: TDS entries are uploaded (RE) and aggregated by TAN + Financial Year + Quarter (Section 194Q, Booking F/O only). - **Form 16A submission**: Dealer submits Form 16A (PDF). OCR extracts TAN, FY, Quarter, TDS amount, certificate number, etc. - **Credit note**: When a submission is validated, the system matches it against the latest 26AS aggregate for that TAN/FY/Quarter. On match, a **credit note** is created, ledger updated, quarter marked **SETTLED**, and a CSV is pushed to WFM **INCOMING** for SAP (credit note generation). - **Debit note**: When a new 26AS upload changes the quarter total and that quarter was already **SETTLED**, the system creates a **debit note** (reversing the earlier credit), updates ledger, sets quarter to **DEBIT_ISSUED_PENDING_FORM16**, and pushes a CSV to WFM **INCOMING** for SAP (debit note generation). - **SAP responses**: SAP processes the INCOMING files and drops response CSVs in WFM **OUTGOING**. The backend ingests these (scheduler every 5 min or on-demand Pull), stores them in DB, and users can **View** (and for credit, **Download**) the SAP response. --- ## 2. Paths (WFM Folder Structure) All paths are relative to **WFM_BASE_PATH** (default `C:\WFM`). Can be overridden via `.env` (e.g. `WFM_BASE_PATH=D:\Form-16 Main`). The job also tries `\WFM-QRE\...` if the default path does not exist. | Direction | Type | Default path (under WFM_BASE_PATH) | |------------|--------|-------------------------------------| | **INCOMING** | Credit | `WFM-QRE\INCOMING\WFM_MAIN\FORM16_CRDT` | | **INCOMING** | Debit | `WFM-QRE\INCOMING\WFM_MAIN\FORM16_DEBT` | | **OUTGOING** | Credit | `WFM-QRE\OUTGOING\WFM_SAP_MAIN\FORM16_CRDT` | | **OUTGOING** | Debit | `WFM-QRE\OUTGOING\WFM_SAP_MAIN\FORM16_DBT` | - **INCOMING** = files we **push** to WFM (for SAP to pick up and process). - **OUTGOING** = files **SAP drops** (responses); we read and store them. --- ## 3. Credit Note Flow ### 3.1 When is a credit note created? - On **Form 16A submission validation** (after OCR and 26AS check). - `run26asMatchAndCreditNote(submission)` is called (e.g. from submission validation flow). - Conditions: TAN + FY + Quarter match latest 26AS aggregate (Section 194Q, F/O), amount within tolerance, quarter not already settled with same amount. - On success: create `Form16CreditNote`, ledger entry (CREDIT), set quarter status **SETTLED**, then push **INCOMING** CSV. ### 3.2 Credit note – INCOMING (we push to WFM/SAP) - **Path**: `WFM-QRE\INCOMING\WFM_MAIN\FORM16_CRDT` - **When**: Immediately after credit note is created. - **File name**: `{creditNoteNumber}.csv` (e.g. `CN00628226Q20001.csv`). - **Content** (pipe `|` separated): `TRNS_UNIQ_NO` (e.g. `F16-CN-{submissionId}-{creditNoteId}-{timestamp}`), `TDS_TRNS_ID` (= credit note number), `DEALER_CODE`, `TDS_TRNS_DOC_TYP`, `DLR_TAN_NO`, `FIN_YEAR & QUARTER`, `DOC_DATE`, `TDS_AMT`. - **TDS_TRNS_ID** = credit note number (format: `CN` + 6-digit dealer code + 2-digit FY + quarter + 4-digit sequence, e.g. `CN00628226Q20001`). - A copy is also written to the Form 16 credit archive path (INCOMING archive). ### 3.3 Credit note – OUTGOING (SAP response) - **Path**: `WFM-QRE\OUTGOING\WFM_SAP_MAIN\FORM16_CRDT` - **Who writes**: SAP (response CSVs placed here by SAP/WFM). - **Who reads**: Backend **Form 16 SAP response job** (scheduler every 5 min + on **Pull** button). - **What we do**: Read each CSV, parse first “real” data row, match to credit note by `TRNS_UNIQ_NO` or `creditNoteNumber` (TDS_TRNS_ID in response), upload file to storage, insert/update row in **`form16_sap_responses`** with `type = 'credit'`, `credit_note_id`, `storage_url`, etc. - **User**: Credit notes list shows **View** when a response exists; **View** opens popup with SAP fields and **Download CSV**; **Pull** triggers ingestion and list refresh. --- ## 4. Debit Note Flow ### 4.1 When is a debit note created? - On **26AS upload** that changes the quarter aggregate for a quarter that is already **SETTLED** (had a credit note). - `process26asUploadAggregation(uploadLogId)` is called after 26AS file upload (controller calls it when records are imported). - For each (TAN, FY, Quarter) where new 26AS total ≠ previous snapshot and status is SETTLED: create `Form16DebitNote` (linked to the last credit note for that quarter), ledger entry (DEBIT), set quarter status **DEBIT_ISSUED_PENDING_FORM16**, then push **INCOMING** CSV. ### 4.2 Debit note – INCOMING (we push to WFM/SAP) - **Path**: `WFM-QRE\INCOMING\WFM_MAIN\FORM16_DEBT` - **When**: Immediately after debit note is created in `process26asUploadAggregation`. - **File name**: `{debitNoteNumber}.csv` (e.g. `DN00628226Q20001.csv`). - **Content** (pipe `|` separated): `TRNS_UNIQ_NO` (e.g. `F16-DN-{creditNoteId}-{debitId}-{timestamp}`), **`TDS_TRNS_ID`** = **credit note number** (not debit note number), `DEALER_CODE`, `TDS_TRNS_DOC_TYP`, `Org.Document Number` (= debit id), `DLR_TAN_NO`, `FIN_YEAR & QUARTER`, `DOC_DATE`, `TDS_AMT`. - **TDS_TRNS_ID** in debit incoming = credit note number (same format as credit, e.g. `CN00628226Q20001`). Debit note number = same string with `CN` replaced by `DN` (e.g. `DN00628226Q20001`). - A copy is also written to the Form 16 debit archive path. ### 4.3 Debit note – OUTGOING (SAP response) - **Path**: `WFM-QRE\OUTGOING\WFM_SAP_MAIN\FORM16_DBT` - **Who writes**: SAP (response CSVs placed here). - **Who reads**: Same **Form 16 SAP response job** (every 5 min + **Pull** on Debit Notes page). - **What we do**: Read each CSV, parse, match to debit note by (in order): (1) `TRNS_UNIQ_NO` → `form_16_debit_notes.trns_uniq_no`, (2) `CLAIM_NUMBER` → `form_16_debit_notes.debit_note_number`, (3) **filename (without .csv)** → `form_16_debit_notes.debit_note_number`. Upload file to storage, insert/update row in **`form16_debit_note_sap_responses`** (separate table from credit) with `debit_note_id`, `storage_url`, etc. - **User**: Debit notes list shows **View** when a response exists; **View** opens popup (no download); **Pull** triggers ingestion and list refresh. --- ## 5. Database Tables for SAP Responses | Table | Purpose | |-----------------------------------|--------| | **form16_sap_responses** | Credit note SAP responses only. Columns: `type` ('credit'), `file_name`, `credit_note_id`, `claim_number`, `sap_document_number`, `msg_typ`, `message`, `raw_row`, `storage_url`, timestamps. | | **form16_debit_note_sap_responses**| Debit note SAP responses only. Columns: `file_name`, `debit_note_id`, `claim_number`, `sap_document_number`, `msg_typ`, `message`, `raw_row`, `storage_url`, timestamps. No `type` or `credit_note_id`. | Credit and debit SAP responses are **not** mixed; each has its own table. --- ## 6. Scheduler and Pull - **Scheduler**: `startForm16SapResponseJob()` runs **every 5 minutes** (cron `*/5 * * * *`). It calls `runForm16SapResponseIngestionOnce()`, which: - Scans **OUTGOING** credit dir (`FORM16_CRDT`) and **OUTGOING** debit dir (`FORM16_DBT`) for `.csv` files. - For each file: parse, match to credit or debit note, upload to storage, write to `form16_sap_responses` (credit) or `form16_debit_note_sap_responses` (debit). - **Pull button** (Credit Notes page and Debit Notes page): `POST /api/v1/form16/sap/pull` triggers the **same** `runForm16SapResponseIngestionOnce()`, then the frontend refetches the list. So Pull = one-off run of the same ingestion logic; no separate “pull-only” path. - **View** appears when the corresponding table has a row for that note with a non-null `storage_url` (and for list, we check by `credit_note_id` / `debit_note_id`). --- ## 7. End-to-End Summary | Step | Credit note | Debit note | |------|-------------|------------| | **Trigger** | Form 16A submission validated, 26AS match | 26AS upload changes total for a SETTLED quarter | | **INCOMING (we push)** | CSV to `INCOMING\WFM_MAIN\FORM16_CRDT` | CSV to `INCOMING\WFM_MAIN\FORM16_DEBT` | | **TDS_TRNS_ID in CSV** | Credit note number | Credit note number | | **File name** | `{creditNoteNumber}.csv` | `{debitNoteNumber}.csv` | | **OUTGOING (SAP writes)** | SAP drops response in `OUTGOING\WFM_SAP_MAIN\FORM16_CRDT` | SAP drops response in `OUTGOING\WFM_SAP_MAIN\FORM16_DBT` | | **We read & store** | Job reads CSV, matches, stores in `form16_sap_responses` | Job reads CSV, matches, stores in `form16_debit_note_sap_responses` | | **User action** | View / Download CSV (Pull to refresh) | View only (Pull to refresh) | --- ## 8. Env / Config (relevant) - **WFM_BASE_PATH**: Base folder that contains `WFM-QRE` (e.g. `C:\WFM` or `D:\Form-16 Main`). If not set and default path missing, job tries `process.cwd()\WFM-QRE\...`. - **WFM_FORM16_CREDIT_INCOMING_PATH**, **WFM_FORM16_DEBIT_INCOMING_PATH**: Override INCOMING paths. - **WFM_FORM16_CREDIT_OUTGOING_PATH**, **WFM_FORM16_DEBIT_OUTGOING_PATH**: Override OUTGOING paths.