Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | 43x 26x 26x 7x | /**
* The TDS gate (FR-M-7).
*
* Above a threshold of payments in one Indian financial year we cannot pay a
* partner without their PAN, because past that point the payment is one we have
* to deduct tax at source on and report against a PAN. The threshold is
* ₹15,000 by default and lives in `program_config` so it can follow the law
* without a deploy.
*
* This is arithmetic only — no clock of its own, no database. `fyStart` in
* `lib/rrm/time.ts` decides which payments count; this decides what to do about
* the total. Keeping them apart is what makes the 1-April boundary testable
* without a ledger fixture.
*
* PAISE, integers. Same rule as the rest of the money path.
*/
export type TdsGate =
| { blocked: false }
| {
blocked: true;
/** Already paid this FY, excluding the request being assessed. */
fyPaidPaise: number;
/** What this payment would take the FY total to. */
wouldTotalPaise: number;
thresholdPaise: number;
};
/**
* May this payment be made?
*
* Assessed on the total INCLUDING the payment in question, not on what has
* already been paid. The obligation attaches to the payment that crosses the
* threshold, so checking afterwards means the one payment we most needed a PAN
* for is the one that went out without it.
*
* A partner with a PAN on file is never blocked — recording the deduction is
* then an accounting step, not a reason to withhold someone's money.
*/
export function tdsGate(input: {
/** Sum of payments already made to this partner this financial year. */
fyPaidPaise: number;
/** The payment being assessed. */
requestPaise: number;
thresholdPaise: number;
/** Whether `partners.pan_last4` is populated. Never the value itself. */
hasPan: boolean;
}): TdsGate {
if (input.hasPan) return { blocked: false };
const wouldTotalPaise = input.fyPaidPaise + input.requestPaise;
if (wouldTotalPaise < input.thresholdPaise) return { blocked: false };
return {
blocked: true,
fyPaidPaise: input.fyPaidPaise,
wouldTotalPaise,
thresholdPaise: input.thresholdPaise,
};
}
|