Re_Backend/docs/FORM16_CREDIT_DEBIT_PROCESS.md
2026-03-18 12:59:20 +05:30

9.1 KiB
Raw Permalink Blame History

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 <process.cwd()>\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_NOform_16_debit_notes.trns_uniq_no,
    (2) CLAIM_NUMBERform_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.