fix: tenant-config fixes, cashier/share/savings UI bugs, and menu-access hardcoding

- Add Balance Sheet report and disabled-features accounting config
- Point menu-access tenant header and env.js/environment.ts tenant identifier
  at env config instead of hardcoded 'default'/'lincpay' literals
- Surface the real backend error (not a generic "no reference id") when an
  OTP send fails in contact-otp-block
- Fix branch-day "₹null" display bug (null vs undefined) and add a guard
  blocking a branch's first-ever day open before cash denomination migration
- Dynamically size the denomination count input and block re-opening an
  already-open business day from Migrate Cash Denomination
- Lock the denomination-managed cash GL row in Migrate Opening Balances
  (read-only, with a link back to Migrate Cash Denomination)
- Remove duplicate Cancel/Submit action bars on the Share Product and
  Savings Account creation preview steps; align Previous into the same row
- Hide "Apply Collection" on a share account once its advance collection
  is already settled (further purchases go through Apply Additional Shares)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-13 15:19:21 +05:30
co-authored by Claude Sonnet 5
parent 42424dff8b
commit 7b77166b19
39 changed files with 1800 additions and 266 deletions
@@ -49,6 +49,18 @@
</div>
}
@if (firstOpenNeedsCashMigration && !missedOnly) {
<div class="bd-locked">
<mat-icon>lock</mat-icon>
<span>
This branch has never opened a business day, and its Cash at Vault GL account has no opening balance yet. Count
the vault and open the first business day together from
<a [routerLink]="['/accounting/migrate-cash-denomination']">Migrate Cash Denomination</a> — Open Day here is
locked until that is done, so today's cash tracking never starts out of step with the ledger.
</span>
</div>
}
<!-- Missed closes first: these are the ones that need action. -->
@if (missed.length > 0) {
<div class="db-exceptions">
@@ -703,10 +715,10 @@
<span class="db-muted">· {{ timeOnly(d.closedAt) }}</span>
}
</td>
<td class="num">{{ d.closingCash != null ? '₹' + (d.closingCash | number: '1.2-2') : '—' }}</td>
<td class="num">{{ d.bookCash != null ? '₹' + (d.bookCash | number: '1.2-2') : '—' }}</td>
<td class="num">{{ hasValue(d.closingCash) ? '₹' + (d.closingCash | number: '1.2-2') : '—' }}</td>
<td class="num">{{ hasValue(d.bookCash) ? '₹' + (d.bookCash | number: '1.2-2') : '—' }}</td>
<td>
@if (d.cashDifference == null) {
@if (!hasValue(d.cashDifference)) {
—
} @else if (d.cashDifference === 0) {
<span class="db-badge db-badge--ok">Tallied</span>