111 lines
3.3 KiB
TypeScript
111 lines
3.3 KiB
TypeScript
/**
|
||
* Copyright since 2025 Mifos Initiative
|
||
*
|
||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||
*/
|
||
|
||
/**
|
||
* Deductees, their deposit interest and the challans, for the two TDS reports.
|
||
*
|
||
* Everything here is what the platform returned. The challans used to be generated from the
|
||
* computed deductions - challan numbers, BSR codes and deposit dates made up, one quarter
|
||
* deliberately late - so the remittance report reconciled against figures nobody had entered.
|
||
*/
|
||
|
||
import {
|
||
configuredFys,
|
||
Declaration,
|
||
InterestCredit,
|
||
TdsAccountInput
|
||
} from '../letter-mgmt/certificates/form-15gh/tds-15gh.compute';
|
||
|
||
/** The years the reports can show: every year configured on Organization › TDS Configuration. */
|
||
export function tdsFys(): string[] {
|
||
return configuredFys();
|
||
}
|
||
|
||
/** A deposit as the platform reports it: the interest credited and the TDS actually withheld. */
|
||
export interface TdsReportAccount extends TdsAccountInput {
|
||
/** TDS the platform actually deducted from this account in the year. */
|
||
deductions: InterestCredit[];
|
||
/** The account's own holder, when the tax is deducted against somebody else (minor, joint). */
|
||
holderClientId?: number;
|
||
holderName?: string;
|
||
}
|
||
|
||
export interface TdsDeductee {
|
||
clientId: number;
|
||
customerId: string;
|
||
name: string;
|
||
pan: string;
|
||
dob: string;
|
||
branchCode: string;
|
||
/** Declarations on record, keyed by financial year. */
|
||
declarations: Record<string, Declaration>;
|
||
accounts: TdsReportAccount[];
|
||
}
|
||
|
||
/** One challan Head Office entered: tax remitted to the Government. */
|
||
export interface TdsChallan {
|
||
id: number;
|
||
fy: string;
|
||
/** Month the tax was deducted in, e.g. '2026-06'. */
|
||
month: string;
|
||
amount: number;
|
||
challanNo: string;
|
||
bsrCode: string;
|
||
depositedOn: string;
|
||
paidFrom: string;
|
||
remarks: string | null;
|
||
reversed: boolean;
|
||
}
|
||
|
||
/** Tax the platform withheld in one month. */
|
||
export interface TdsDeductedMonth {
|
||
month: string;
|
||
amount: number;
|
||
postings: number;
|
||
}
|
||
|
||
/**
|
||
* The deductees the reports run on, loaded from the platform.
|
||
*
|
||
* It is set once by whoever loads the screen and read by the pure computation, which is why
|
||
* this is a module-level holder rather than a service the compute would have to inject.
|
||
*/
|
||
let liveDeductees: TdsDeductee[] = [];
|
||
|
||
export function setTdsDeductees(deductees: TdsDeductee[]): void {
|
||
liveDeductees = deductees || [];
|
||
// The row cache in the compute is keyed on the financial year alone, so it has to be told that
|
||
// the underlying set changed or it would serve rows built from the previous load.
|
||
tdsDeducteesVersion++;
|
||
}
|
||
|
||
/** Bumped on every load, so memoised rows can tell one data set from the next. */
|
||
export let tdsDeducteesVersion = 0;
|
||
|
||
export function tdsDeductees(): TdsDeductee[] {
|
||
return liveDeductees;
|
||
}
|
||
|
||
/**
|
||
* Statutory date by which tax deducted in a given month must be deposited.
|
||
*
|
||
* The seventh of the following month, except for March, which runs to 30 April.
|
||
*/
|
||
export function depositDueDate(month: string): string {
|
||
const [
|
||
y,
|
||
m
|
||
] = month.split('-').map(Number);
|
||
if (m === 3) {
|
||
return `${y}-04-30`;
|
||
}
|
||
const nextY = m === 12 ? y + 1 : y;
|
||
const nextM = m === 12 ? 1 : m + 1;
|
||
return `${nextY}-${`${nextM}`.padStart(2, '0')}-07`;
|
||
}
|