diff --git a/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.html b/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.html
index 4786e7d46..b4656e131 100644
--- a/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.html
+++ b/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.html
@@ -219,7 +219,8 @@
| Date |
Voucher / Ref No |
- Account / Reference |
+ Account No |
+ Account Name / Reference |
Particulars |
Debit |
Credit |
@@ -230,12 +231,10 @@
| {{ asOnDate }} |
- {{ t.voucherNo }}
- |
-
- {{ t.accountName }}
- {{ t.accountNo }}
+ {{ display(t.voucherNo) }}
|
+ {{ display(t.accountNo) }} |
+ {{ t.accountName }} |
{{ t.particulars }} |
@if (t.debit > 0) {
@@ -250,13 +249,13 @@
|
} @empty {
- | No transactions for this filter. |
+ No transactions for this filter. |
}
- | Total |
+ Total |
₹{{ txnTotal(filteredTxns, 'debit') | number: '1.2-2' }} |
₹{{ txnTotal(filteredTxns, 'credit') | number: '1.2-2' }} |
diff --git a/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.ts b/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.ts
index 9e636da20..0399b5d66 100644
--- a/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.ts
+++ b/src/app/cashier/cash-clearing-transfer-summary/cash-clearing-transfer-summary.component.ts
@@ -34,6 +34,9 @@ interface Branch {
name: string;
/** Relative size vs the base dataset below (which represents the Head Office main branch, scale 1). */
scale: number;
+ /** Numeric offset used to derive this branch's own account numbers / IFSC serials — keeps the
+ * standard 12-digit / IFSC format intact instead of just tagging a prefix onto Branch 1's values. */
+ acctShift: number;
}
type TabKey = 'cash' | 'transfer' | 'clearing' | 'digital';
@@ -84,8 +87,8 @@ export class CashClearingTransferSummaryComponent {
* of its own Transaction Details).
*/
branches: Branch[] = [
- { code: 'BR1', name: 'Branch 1', scale: 1 },
- { code: 'BR2', name: 'Branch 2', scale: 0.7 }
+ { code: 'BR1', name: 'Branch 1', scale: 1, acctShift: 0 },
+ { code: 'BR2', name: 'Branch 2', scale: 0.7, acctShift: 400 }
];
/** 'ALL' = consolidated across both branches; otherwise a Branch.code. Only meaningful for Head Office users. */
@@ -131,7 +134,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0141',
- accountNo: 'Teller-01',
+ accountNo: 'TIL-0001',
accountName: 'Teller Counter 1 Cash Deposits (Aggregated)',
particulars: 'Cash Deposit - Savings/Current Accounts',
debit: 0,
@@ -140,7 +143,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0142',
- accountNo: 'Teller-02',
+ accountNo: 'TIL-0002',
accountName: 'Teller Counter 2 Cash Deposits (Aggregated)',
particulars: 'Cash Deposit - Savings/Current Accounts',
debit: 0,
@@ -176,7 +179,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0146',
- accountNo: 'Branch ATM',
+ accountNo: 'ATM-0001',
accountName: 'ATM Excess Cash Retraction',
particulars: 'Excess Cash Surrendered by ATM to Vault',
debit: 0,
@@ -203,7 +206,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0149',
- accountNo: 'Branch ATM',
+ accountNo: 'ATM-0001',
accountName: 'ATM 1 Cash Loading',
particulars: 'Vault to ATM Cash Transfer',
debit: 700000,
@@ -212,7 +215,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0150',
- accountNo: 'Extension Counter ATM',
+ accountNo: 'ATM-0002',
accountName: 'ATM 2 Cash Loading',
particulars: 'Vault to ATM Cash Transfer',
debit: 500000,
@@ -239,7 +242,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0153',
- accountNo: 'Currency Chest',
+ accountNo: 'CCH-0001',
accountName: 'Currency Chest Remittance',
particulars: 'Surplus Cash Remitted to Currency Chest',
debit: 400000,
@@ -266,7 +269,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: '100001',
voucherNo: 'CSH/2607/0156',
- accountNo: 'Vault',
+ accountNo: 'VLT-0001',
accountName: 'Vault Denomination Exchange Adjustment',
particulars: 'Shortage Adjustment - Denomination Exchange',
debit: 205000,
@@ -1171,7 +1174,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44521',
- accountNo: 'NPCI-UPI-SETL-IN-01',
+ accountNo: 'RRN-UPI26073100145',
accountName: 'UPI Inward Settlement - Morning Batch (00:00-12:00)',
particulars: 'UPI Collect - Merchant/P2P Inward (Aggregated)',
debit: 0,
@@ -1180,7 +1183,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44522',
- accountNo: 'NPCI-UPI-SETL-IN-02',
+ accountNo: 'RRN-UPI26073100289',
accountName: 'UPI Inward Settlement - Afternoon Batch (12:00-18:00)',
particulars: 'UPI Collect - Merchant/P2P Inward (Aggregated)',
debit: 0,
@@ -1189,7 +1192,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44523',
- accountNo: 'NPCI-UPI-SETL-IN-03',
+ accountNo: 'RRN-UPI26073100356',
accountName: 'UPI Inward Settlement - Evening Batch (18:00-24:00)',
particulars: 'UPI Collect - Merchant/P2P Inward (Aggregated)',
debit: 0,
@@ -1198,7 +1201,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44524',
- accountNo: 'NPCI-UPI-SETL-OUT-01',
+ accountNo: 'RRN-UPI26073100478',
accountName: 'UPI Outward Settlement - Morning Batch (00:00-12:00)',
particulars: 'UPI Pay - Merchant/P2P Outward (Aggregated)',
debit: 1850000,
@@ -1207,7 +1210,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44525',
- accountNo: 'NPCI-UPI-SETL-OUT-02',
+ accountNo: 'RRN-UPI26073100512',
accountName: 'UPI Outward Settlement - Afternoon Batch (12:00-18:00)',
particulars: 'UPI Pay - Merchant/P2P Outward (Aggregated)',
debit: 2050000,
@@ -1216,7 +1219,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'UPI',
voucherNo: 'UPI/2607/44526',
- accountNo: 'NPCI-UPI-SETL-OUT-03',
+ accountNo: 'RRN-UPI26073100634',
accountName: 'UPI Outward Settlement - Evening Batch (18:00-24:00)',
particulars: 'UPI Pay - Merchant/P2P Outward (Aggregated)',
debit: 1490000,
@@ -1226,7 +1229,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'ATM',
voucherNo: 'ATM/2607/9081',
- accountNo: 'ATM-SETL-CR-01',
+ accountNo: 'RRN-ATM26073100118',
accountName: 'ATM Cash Deposits - Own Branch ATM (Aggregated)',
particulars: 'ATM Cash Deposit - Own Branch ATM',
debit: 0,
@@ -1235,7 +1238,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'ATM',
voucherNo: 'ATM/2607/9082',
- accountNo: 'ATM-SETL-CR-02',
+ accountNo: 'RRN-ATM26073100224',
accountName: 'ATM Cash Deposits - Extension Counter ATM (Aggregated)',
particulars: 'ATM Cash Deposit - Extension Counter ATM',
debit: 0,
@@ -1244,7 +1247,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'ATM',
voucherNo: 'ATM/2607/9083',
- accountNo: 'ATM-SETL-DR-01',
+ accountNo: 'RRN-ATM26073100337',
accountName: 'ATM Cash Withdrawals - Own Branch ATM (Aggregated)',
particulars: 'ATM Cash Withdrawal - Own Branch ATM',
debit: 420000,
@@ -1253,7 +1256,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'ATM',
voucherNo: 'ATM/2607/9084',
- accountNo: 'ATM-SETL-DR-02',
+ accountNo: 'RRN-ATM26073100449',
accountName: 'ATM Cash Withdrawals - Other Bank ATM, NFS Switch (Aggregated)',
particulars: 'ATM Cash Withdrawal - Other Bank ATM (NFS)',
debit: 265000,
@@ -1263,7 +1266,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'NACH',
voucherNo: 'NACH/2607/3304',
- accountNo: 'NACH-SETL-CR-01',
+ accountNo: 'UMRN-NACH26073100112',
accountName: 'NACH Credits - Corporate Payroll Disbursement (Aggregated)',
particulars: 'NACH Credit - Salary Disbursement Batch',
debit: 0,
@@ -1272,7 +1275,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'NACH',
voucherNo: 'NACH/2607/3305',
- accountNo: 'NACH-SETL-CR-02',
+ accountNo: 'UMRN-NACH26073100156',
accountName: 'NACH Credits - Government Subsidy (DBT) Disbursement (Aggregated)',
particulars: 'NACH Credit - Subsidy Disbursement Batch',
debit: 0,
@@ -1281,7 +1284,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'NACH',
voucherNo: 'NACH/2607/3306',
- accountNo: 'NACH-SETL-DR-01',
+ accountNo: 'UMRN-NACH26073100198',
accountName: 'NACH Debits - Retail Loan EMI Collection (Aggregated)',
particulars: 'NACH Debit - Loan EMI Collection Batch',
debit: 560000,
@@ -1290,7 +1293,7 @@ export class CashClearingTransferSummaryComponent {
{
glCode: 'NACH',
voucherNo: 'NACH/2607/3307',
- accountNo: 'NACH-SETL-DR-02',
+ accountNo: 'UMRN-NACH26073100233',
accountName: 'NACH Debits - Gold Loan EMI Collection (Aggregated)',
particulars: 'NACH Debit - Gold Loan EMI Collection Batch',
debit: 305000,
@@ -1298,9 +1301,14 @@ export class CashClearingTransferSummaryComponent {
}
];
+ /** YYMM tag baked into every dummy voucher/reference number (e.g. "2607" for Jul 2026) — kept
+ * in sync with the real current date so it never goes stale in a future month. */
+ private dateTag = '2607';
+
constructor() {
const d = new Date();
this.asOnDate = `${String(d.getDate()).padStart(2, '0')}-${String(d.getMonth() + 1).padStart(2, '0')}-${d.getFullYear()}`;
+ this.dateTag = `${String(d.getFullYear()).slice(-2)}${String(d.getMonth() + 1).padStart(2, '0')}`;
const creds = this.auth.getCredentials();
this.isHeadOffice = this.auth.isHeadOfficeUser();
@@ -1318,6 +1326,11 @@ export class CashClearingTransferSummaryComponent {
}
}
+ /** Renders a voucher/reference number with the baked-in "2607" swapped for today's real YYMM tag. */
+ display(value: string): string {
+ return (value || '').replace(/2607/g, this.dateTag);
+ }
+
private baseRowsFor(tab: TabKey): SummaryRow[] {
switch (tab) {
case 'cash':
@@ -1355,15 +1368,36 @@ export class CashClearingTransferSummaryComponent {
return rows.map((r) => ({ ...r, opening: this.roundAmt(r.opening * factor) }));
}
- private scaleTxns(txns: TxnRow[], factor: number, branchTag?: string): TxnRow[] {
- if (factor === 1) {
+ /**
+ * Re-derives a customer account number or bank IFSC code for a different branch by shifting
+ * its numeric segment — NOT by tagging a prefix onto Branch 1's value, since real account
+ * numbers and IFSC codes have a fixed, standard shape and a "BR2-" prefix would look fake.
+ * Everything else (UTR/RRN/UMRN/DD/PO/TDS/GST/cheque/branch/settlement references) keeps the
+ * simpler branch-tag prefix, since those are already free-form internal reference formats.
+ */
+ private scaleAccountNo(accountNo: string, branch: Branch): string {
+ if (/^\d{12}$/.test(accountNo)) {
+ const branchSeg = (parseInt(accountNo.slice(0, 3), 10) + branch.acctShift) % 1000;
+ return String(branchSeg).padStart(3, '0') + accountNo.slice(3);
+ }
+ const ifsc = accountNo.match(/^([A-Z]{4}0)(\d{6})$/);
+ if (ifsc) {
+ const serial = (parseInt(ifsc[2], 10) + branch.acctShift) % 1000000;
+ return ifsc[1] + String(serial).padStart(6, '0');
+ }
+ return `${branch.code}-${accountNo}`;
+ }
+
+ private scaleTxns(txns: TxnRow[], branch: Branch | null): TxnRow[] {
+ if (!branch || branch.scale === 1) {
return txns;
}
return txns.map((t) => ({
...t,
- voucherNo: branchTag ? `${branchTag}-${t.voucherNo}` : t.voucherNo,
- debit: this.roundAmt(t.debit * factor),
- credit: this.roundAmt(t.credit * factor)
+ voucherNo: `${branch.code}-${t.voucherNo}`,
+ accountNo: this.scaleAccountNo(t.accountNo, branch),
+ debit: this.roundAmt(t.debit * branch.scale),
+ credit: this.roundAmt(t.credit * branch.scale)
}));
}
@@ -1387,13 +1421,13 @@ export class CashClearingTransferSummaryComponent {
private effectiveTxns(tab: TabKey): TxnRow[] {
const base = this.baseTxnsFor(tab);
if (!this.isHeadOffice) {
- return this.ownBranch ? this.scaleTxns(base, this.ownBranch.scale, this.ownBranch.code) : base;
+ return this.scaleTxns(base, this.ownBranch);
}
if (this.selectedBranchCode === 'ALL') {
- return this.branches.flatMap((b) => this.scaleTxns(base, b.scale, b.code));
+ return this.branches.flatMap((b) => this.scaleTxns(base, b));
}
const branch = this.branches.find((b) => b.code === this.selectedBranchCode);
- return this.scaleTxns(base, branch ? branch.scale : 1, branch?.code);
+ return this.scaleTxns(base, branch ?? null);
}
get rowsForActiveTab(): SummaryRow[] {
@@ -1524,7 +1558,7 @@ export class CashClearingTransferSummaryComponent {
return this.branches.map((b) => {
const pairs = this.allTabs.map((tab) => ({
rows: this.scaleRows(this.baseRowsFor(tab), b.scale),
- txns: this.scaleTxns(this.baseTxnsFor(tab), b.scale, b.code)
+ txns: this.scaleTxns(this.baseTxnsFor(tab), b)
}));
const opening = pairs.reduce((sum, c) => sum + this.total(c.rows, c.txns, 'opening'), 0);
const credit = pairs.reduce((sum, c) => sum + this.total(c.rows, c.txns, 'credit'), 0);
diff --git a/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts b/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
index 5cbc3b024..123c9d596 100644
--- a/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
+++ b/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
@@ -533,6 +533,8 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
screeningLogId: number | null = null;
/** Snapshot of the name that was last verified — used to invalidate verification when name changes */
private verifiedName: string = '';
+ /** True while prefillForEdit() is patching historical monthly/annual values — see linkMonthlyAnnual(). */
+ private suppressMonthlyAnnualLink = false;
/**
* @param {FormBuilder} formBuilder Form Builder
@@ -709,6 +711,12 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
const data = this.clientData;
this.loadExistingSeniorPwdDocuments();
+ // Loading an existing client's independently-saved monthly/annual values must not run
+ // through the auto-calc in linkMonthlyAnnual() — patching monthlyIncome then annualIncome
+ // (or vice versa) would otherwise have each overwrite the other via its valueChanges,
+ // instead of keeping the exact historical values as saved.
+ this.suppressMonthlyAnnualLink = true;
+
// Patch all base controls that exist on the form
this.createClientForm.patchValue({
officeId: data.officeId,
@@ -743,6 +751,7 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
? new Date(data.timeline.submittedOnDate)
: this.settingsService.businessDate
});
+ this.suppressMonthlyAnnualLink = false;
// Patch name fields (already created by buildDependencies via legalFormId subscription)
const legalFormId = data.legalForm?.id || LegalFormId.PERSON;
@@ -954,6 +963,43 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
Validators.required
]
});
+
+ this.linkMonthlyAnnual('monthlyIncome', 'annualIncome');
+ this.linkMonthlyAnnual('monthlyTurnover', 'annualTurnover');
+ }
+
+ /**
+ * Keeps a Monthly/Annual pair of amount fields in sync at a 12x ratio — typing into either
+ * one auto-fills the other. Uses { emitEvent: false } on the write side so the two
+ * subscriptions don't trigger each other back and forth.
+ */
+ /** Rounds to at most 2 decimals without padding whole numbers with a trailing ".00". */
+ private round2(n: number): string {
+ return (Math.round(n * 100) / 100).toString();
+ }
+
+ private linkMonthlyAnnual(monthlyControlName: string, annualControlName: string): void {
+ const monthly = this.createClientForm.get(monthlyControlName);
+ const annual = this.createClientForm.get(annualControlName);
+ if (!monthly || !annual) {
+ return;
+ }
+
+ monthly.valueChanges.subscribe((value) => {
+ if (this.suppressMonthlyAnnualLink) {
+ return;
+ }
+ const num = parseFloat(value);
+ annual.setValue(!isNaN(num) && num >= 0 ? this.round2(num * 12) : '', { emitEvent: false });
+ });
+
+ annual.valueChanges.subscribe((value) => {
+ if (this.suppressMonthlyAnnualLink) {
+ return;
+ }
+ const num = parseFloat(value);
+ monthly.setValue(!isNaN(num) && num >= 0 ? this.round2(num / 12) : '', { emitEvent: false });
+ });
}
/**