fix(cashier): tag GL-entry denomination to the vault, show both voucher legs

- Transaction Entry's manual GL-entry screen was recording its denomination
  breakdown against whichever GL account the teller selected, not the vault
  account whose physical notes actually moved -- resolve and use the Cash
  Vault GL's own code/name dynamically instead
- Closing Cash Report's GL Entries table showed only the one account its
  denomination row knew about; now shows both the debit and credit account
  of each voucher (backend now returns debitParty/creditParty), matching
  what My Vouchers already shows for the same entries

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-14 07:19:50 +05:30
co-authored by Claude Sonnet 5
parent 7b77166b19
commit ab58d7f74c
2 changed files with 36 additions and 6 deletions
@@ -303,8 +303,8 @@
<tr> <tr>
<th class="gl-th--voucher">Voucher No</th> <th class="gl-th--voucher">Voucher No</th>
<th class="gl-th--date">Date</th> <th class="gl-th--date">Date</th>
<th>A/C No</th> <th>Debit</th>
<th>A/C Name</th> <th>Credit</th>
<th class="gl-th--pt">Payment Type</th> <th class="gl-th--pt">Payment Type</th>
<th class="gl-th--teller">Teller</th> <th class="gl-th--teller">Teller</th>
<th class="num gl-th--dr">DR (₹)</th> <th class="num gl-th--dr">DR (₹)</th>
@@ -326,8 +326,25 @@
<div class="gl-time">{{ r.txnTime }}</div> <div class="gl-time">{{ r.txnTime }}</div>
} }
</td> </td>
<td class="gl-acno">{{ r.acNo }}</td> <!-- Both legs of the voucher, the same pair My Vouchers shows — not just the one
<td class="gl-acname">{{ r.acName }}</td> side this row's own denomination breakdown happens to know about. Falls back
to that one side (acNo/acName) when the voucher predates m_voucher_line. -->
<td class="gl-acname">
<div>{{ r.debitParty || r.acName }}</div>
@if (r.debitAccount || r.acNo) {
<div class="gl-acno">{{ r.debitAccount || r.acNo }}</div>
}
</td>
<td class="gl-acname">
@if (r.creditParty) {
<div>{{ r.creditParty }}</div>
@if (r.creditAccount) {
<div class="gl-acno">{{ r.creditAccount }}</div>
}
} @else {
<span class="gl-pt-none">—</span>
}
</td>
<td class="gl-pt"> <td class="gl-pt">
@if (r.paymentType) { @if (r.paymentType) {
<span class="gl-pt-badge">{{ r.paymentType }}</span> <span class="gl-pt-badge">{{ r.paymentType }}</span>
@@ -1617,6 +1617,13 @@ export class TransactionEntryComponent implements OnInit, OnDestroy {
private lastLoadedAcNo = ''; private lastLoadedAcNo = '';
private acNoInput$ = new Subject<{ row: TxnRow; index: number; value: string }>(); private acNoInput$ = new Subject<{ row: TxnRow; index: number; value: string }>();
cashVaultGlId: number | null = null; cashVaultGlId: number | null = null;
/** The Cash Vault GL account's own code and name — the denomination breakdown for a manual GL
* entry has to be filed against THIS account, not whichever account the teller typed in, since
* that account is never the one physical notes actually moved through (see submitGlJournalEntry).
* Both resolved dynamically off whatever this tenant's own financial-activity mapping names as
* its cash/vault account (see loadCashVaultGl) — never a literal account name or code. */
cashVaultGlCode: string | null = null;
cashVaultGlName: string | null = null;
// Joint holder expanded details (keyed by index) // Joint holder expanded details (keyed by index)
expandedHolder: number | null = null; expandedHolder: number | null = null;
@@ -3121,6 +3128,8 @@ export class TransactionEntryComponent implements OnInit, OnDestroy {
byName(/vault/i) ?? byName(/cash/i) ?? items.find((a: any) => a.glAccountData?.type?.value === 'ASSET'); byName(/vault/i) ?? byName(/cash/i) ?? items.find((a: any) => a.glAccountData?.type?.value === 'ASSET');
if (found?.glAccountData?.id) { if (found?.glAccountData?.id) {
this.cashVaultGlId = found.glAccountData.id; this.cashVaultGlId = found.glAccountData.id;
this.cashVaultGlCode = found.glAccountData.glCode ?? null;
this.cashVaultGlName = found.glAccountData.name ?? found.financialActivityData?.name ?? null;
} }
}); });
} }
@@ -5648,11 +5657,15 @@ export class TransactionEntryComponent implements OnInit, OnDestroy {
count: this.countFor(d), count: this.countFor(d),
subtotal: this.subtotalFor(d) subtotal: this.subtotalFor(d)
})); }));
// Filed against the Cash Vault GL, not the account the teller selected on screen: that
// selected account (e.g. Sundry Creditors) is the other leg of the journal entry, and
// never the one whose physical notes actually changed hands. Tagging the breakdown to it
// instead of the vault is why this cash never reached the cashier/vault position.
this.http this.http
.post('/cashier/gl-denomination', { .post('/cashier/gl-denomination', {
txnId: res.transactionId ?? res.resourceId, txnId: res.transactionId ?? res.resourceId,
accountNo: this.accountDetails?.glCode ?? row.acNo, accountNo: this.cashVaultGlCode ?? row.acNo,
accountName: this.accountDetails?.name ?? '', accountName: this.cashVaultGlName ?? 'Cash at Vault',
txnType: isDeposit ? 'DEPOSIT' : 'WITHDRAWAL', txnType: isDeposit ? 'DEPOSIT' : 'WITHDRAWAL',
txnDate: txnDateIso, txnDate: txnDateIso,
paymentTypeName: selectedPt?.name ?? 'Cash', paymentTypeName: selectedPt?.name ?? 'Cash',