kyc exception at client creation time and some tds work
This commit is contained in:
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import * as ExcelJS from 'exceljs';
|
||||
|
||||
import { BranchScopeService } from '../core/branch-scope.service';
|
||||
import { FY_TAX_CONFIG, QUARTER_LABEL } from '../letter-mgmt/certificates/form-15gh/tds-15gh.compute';
|
||||
import { TDS_AS_AT, TDS_FYS } from './tds-reports-data';
|
||||
import { Tds26qSummary, TdsRemittanceRow, tds26qSummary, tdsRemittanceRows } from './tds-reports.compute';
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-tds-remittance-report',
|
||||
templateUrl: './tds-remittance-report.component.html',
|
||||
styleUrls: ['./tds-reports.shared.scss'],
|
||||
imports: [
|
||||
...STANDALONE_SHARED_IMPORTS,
|
||||
FaIconComponent,
|
||||
FormsModule
|
||||
]
|
||||
})
|
||||
export class TdsRemittanceReportComponent {
|
||||
private scope = inject(BranchScopeService);
|
||||
|
||||
readonly financialYears = TDS_FYS;
|
||||
readonly quarterLabel = QUARTER_LABEL;
|
||||
readonly asAt = TDS_AS_AT;
|
||||
|
||||
fy = TDS_FYS[0];
|
||||
exporting = false;
|
||||
|
||||
/**
|
||||
* Provision and return references for the selected year. The quarterly return
|
||||
* became Form 140 under the 2025 Act, so the labels are read from the config
|
||||
* rather than written into the template.
|
||||
*/
|
||||
get statute(): { section: string; statement: string; frequency: string } {
|
||||
const cfg = FY_TAX_CONFIG[this.fy];
|
||||
return {
|
||||
section: cfg?.interestTdsSection ?? '—',
|
||||
statement: cfg?.tdsStatementForm ?? '—',
|
||||
frequency: cfg?.declarationStatementFrequency === 'MONTHLY' ? 'monthly' : 'quarterly'
|
||||
};
|
||||
}
|
||||
|
||||
get scopeLabel(): string {
|
||||
return this.scope.isHeadOffice ? 'Bank as a whole' : this.scope.officeName;
|
||||
}
|
||||
|
||||
get rows(): TdsRemittanceRow[] {
|
||||
return tdsRemittanceRows(this.fy, this.asAt);
|
||||
}
|
||||
|
||||
get summary(): Tds26qSummary {
|
||||
return tds26qSummary(this.fy, this.asAt);
|
||||
}
|
||||
|
||||
/**
|
||||
* The control that matters. Tax deducted must equal tax deposited plus tax
|
||||
* still within its due date. Anything else means something has gone missing
|
||||
* and must be found before the return is filed.
|
||||
*/
|
||||
get reconciled(): boolean {
|
||||
return this.summary.difference === 0;
|
||||
}
|
||||
|
||||
get totalDefaultInterest(): number {
|
||||
return this.summary.defaultInterest;
|
||||
}
|
||||
|
||||
trackRow(_: number, row: TdsRemittanceRow): string {
|
||||
return `${row.fy}-${row.quarter}`;
|
||||
}
|
||||
|
||||
async exportWorkbook(): Promise<void> {
|
||||
this.exporting = true;
|
||||
try {
|
||||
const s = this.summary;
|
||||
const wb = new ExcelJS.Workbook();
|
||||
|
||||
const challan = wb.addWorksheet('Challans');
|
||||
challan.addRow([`TDS remitted to Government — FY ${this.fy}`]);
|
||||
challan.addRow([`Scope: ${this.scopeLabel} · as at ${this.asAt}`]);
|
||||
challan.addRow([]);
|
||||
challan.addRow([
|
||||
'Quarter',
|
||||
'Deduction month',
|
||||
'Amount deducted',
|
||||
'Due date',
|
||||
'Deposited on',
|
||||
'Challan no.',
|
||||
'BSR code',
|
||||
'Status',
|
||||
'Delay (months)',
|
||||
'Late-deposit interest',
|
||||
`${this.statute.statement} due`
|
||||
]);
|
||||
for (const r of this.rows) {
|
||||
challan.addRow([
|
||||
`Q${r.quarter}`,
|
||||
r.month,
|
||||
r.amount,
|
||||
r.dueDate,
|
||||
r.depositedOn ?? 'PENDING',
|
||||
r.challanNo ?? '',
|
||||
r.bsrCode ?? '',
|
||||
r.overdue ? 'OVERDUE' : r.late ? 'LATE' : r.depositedOn ? 'On time' : 'Within due date',
|
||||
r.delayMonths || '',
|
||||
r.defaultInterest || '',
|
||||
r.returnDueDate
|
||||
]);
|
||||
}
|
||||
challan.getRow(1).font = { bold: true, size: 13 };
|
||||
challan.getRow(4).font = { bold: true };
|
||||
challan.columns.forEach((c) => (c.width = 18));
|
||||
|
||||
const recon = wb.addWorksheet('Return Summary');
|
||||
recon.addRow([`${this.statute.statement} year-end position — FY ${this.fy}`]);
|
||||
recon.addRow([]);
|
||||
const lines: [string, number | string][] = [
|
||||
[
|
||||
'Deductees',
|
||||
s.deductees
|
||||
],
|
||||
[
|
||||
'Total interest paid on time deposits',
|
||||
s.totalInterestPaid
|
||||
],
|
||||
[
|
||||
' — with tax deducted',
|
||||
s.interestWithDeduction
|
||||
],
|
||||
[
|
||||
' — without deduction (declaration on record)',
|
||||
s.interestWithoutDeduction
|
||||
],
|
||||
[
|
||||
'TDS at standard rate (PAN on record)',
|
||||
s.tdsAtStandardRate
|
||||
],
|
||||
[
|
||||
'TDS at higher rate (no PAN)',
|
||||
s.tdsAtHigherRate
|
||||
],
|
||||
[
|
||||
'Total TDS deducted',
|
||||
s.totalDeducted
|
||||
],
|
||||
[
|
||||
'Total deposited with Government',
|
||||
s.totalDeposited
|
||||
],
|
||||
[
|
||||
'Still within due date',
|
||||
s.pendingDeposit
|
||||
],
|
||||
[
|
||||
'DIFFERENCE (must be zero)',
|
||||
s.difference
|
||||
],
|
||||
[
|
||||
'Interest payable for late deposit',
|
||||
s.defaultInterest
|
||||
],
|
||||
[
|
||||
'Challans deposited late',
|
||||
s.lateChallans
|
||||
],
|
||||
[
|
||||
'Challans overdue',
|
||||
s.overdueChallans
|
||||
]
|
||||
];
|
||||
for (const line of lines) {
|
||||
recon.addRow(line);
|
||||
}
|
||||
recon.getRow(1).font = { bold: true, size: 13 };
|
||||
recon.columns.forEach((c) => (c.width = 42));
|
||||
recon.getColumn(2).width = 20;
|
||||
|
||||
const buffer = await wb.xlsx.writeBuffer();
|
||||
const blob = new Blob([buffer], {
|
||||
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
||||
});
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `TDS-Remittance-FY${this.fy}.xlsx`;
|
||||
a.click();
|
||||
URL.revokeObjectURL(url);
|
||||
} finally {
|
||||
this.exporting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user