From 3f59cc6b91df33fed60a44a45a8d95b8422ecd2d Mon Sep 17 00:00:00 2001 From: Nitesh Yadav Date: Wed, 23 Sep 2026 14:27:16 +0530 Subject: [PATCH] fix(cashier): route FD/RD cashier deposits through maker-checker approval SYMPTOM A cashier could credit an FD or RD account with cash from Transaction Entry and the money moved in instantly, with no Manager approval - unlike a Savings/Current deposit from the same screen, which correctly creates a PENDING request under Approvals. ROOT CAUSE confirmSubmit()'s maker-checker branch for a cashier deposit only matched row.acTyp in ('SD','CA','CB','GL'): if (!this.isClerk && !this.reviewMode && isDeposit && (row.acTyp === 'SD' || row.acTyp === 'CA' || row.acTyp === 'CB' || row.acTyp === 'GL')) { this.submitCashierDepositRequest(row, ...); return; } 'FD' and 'RD' are their own distinct account-type codes in this component (see creditEntryAccountType(): 'FD' -> 'FIXED_DEPOSIT', 'RD' -> 'RECURRING_DEPOSIT', separate from 'SD'/'CA'/'CB') and were simply never in this list, so a deposit into either fell through every later branch (all of which are withdrawal/disbursement-only) straight to the generic, unguarded direct POST at the bottom of confirmSubmit(). Found by tracing why a real FD funding deposit never showed up under Branch Ops -> Approvals: it had posted directly, no request record ever existed for it, and it later showed up as an unexplained cash "Excess" in the Branch Day Register close (the money was physically counted by the cashier via denominationBreakdown in the same direct POST, but the approved-requests-only "book" total never counted it - see the paired backend commit for the matching approve()-side fix and how that stale data artifact was cleaned up). FIX Added 'FD' and 'RD' to the account-type list in that gate, so a cashier's FD/RD deposit now creates a PENDING m_cashier_deposit_request via submitCashierDepositRequest() exactly like SD/CA/CB/GL already did. buildDepositPayload() needed no changes - it already resolves accountType via creditEntryAccountType() and sets savingsAccountId to the FD/RD account's own id correctly; only this one gate condition excluded them. SCOPE This one condition, in this one method. Every other account type's existing deposit/withdrawal behavior on this screen is unchanged. IF THIS BREAKS SOMETHING LATER - A cashier FD/RD deposit posting instantly again (no PENDING request created) -> check this gate's account-type list still includes 'FD'/'RD', and that isClerk/reviewMode aren't being set unexpectedly for a cashier session. - The backend rejecting or misrouting the resulting APPROVED request -> see the paired fix in CashierDepositRequestApiResource (cbsnexora-backend), resolveDepositAccountCategory() / executeFixedDepositDeposit() / executeRecurringDepositDeposit(). - A "Vault + Cashiers" vs "book" Excess reappearing in Branch Day Register close for a specific FD/RD deposit -> that combination (physically counted denomination with no approved request) should be impossible with this fix in place; if it recurs, this fix (or its backend half) has regressed. Co-Authored-By: Claude Sonnet 5 --- .../transaction-entry/transaction-entry.component.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/app/cashier/transaction-entry/transaction-entry.component.ts b/src/app/cashier/transaction-entry/transaction-entry.component.ts index 0c916bfe4..aa4c8ca6f 100644 --- a/src/app/cashier/transaction-entry/transaction-entry.component.ts +++ b/src/app/cashier/transaction-entry/transaction-entry.component.ts @@ -5804,13 +5804,21 @@ export class TransactionEntryComponent implements OnInit, OnDestroy { return; } - // Cashier deposit (savings/current/GL) → route through maker-checker (create PENDING request, no direct credit) + // Cashier deposit (savings/current/FD/RD/GL) → route through maker-checker (create PENDING request, + // no direct credit). FD and RD are their own account-type codes (see creditEntryAccountType()) and + // belong here just as much as a plain savings deposit -- a cashier crediting an FD/RD must not be + // able to move money in without a manager's approval either. // Use the dialog-confirmed amount — for cash that is the denomination total if ( !this.isClerk && !this.reviewMode && isDeposit && - (row.acTyp === 'SD' || row.acTyp === 'CA' || row.acTyp === 'CB' || row.acTyp === 'GL') + (row.acTyp === 'SD' || + row.acTyp === 'CA' || + row.acTyp === 'CB' || + row.acTyp === 'FD' || + row.acTyp === 'RD' || + row.acTyp === 'GL') ) { this.submitCashierDepositRequest(row, this.confirmData?.amount ?? amount); return;