feat(deposits): sync linked account with maturity terms, add deposit certificate printing
build-run / Run Lint, Build and Deploy (push) Canceled after 0s
Publish Image in Docker Hub / build (push) Canceled after 0s
Playwright E2E Tests / Run Playwright Tests (push) Canceled after 0s
Tests / testRigor (push) Canceled after 0s

Fixed and Recurring Deposit wizards now bidirectionally sync the Product tab's
linked-account selection with the new Terms tab's Transfer-to-Savings account,
disable the Withdraw Deposit maturity instruction end-to-end, and card-style
the Transfer to Savings picker to match the existing linked-account UI. Adds
a printable FD/RD deposit certificate from the account view page, following
the existing letter-mgmt certificate pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-20 11:05:25 +05:30
co-authored by Claude Sonnet 5
parent 1b2ef5126e
commit e58fd3c79a
34 changed files with 2079 additions and 15 deletions
@@ -0,0 +1,160 @@
<!--
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/.
-->
<h2 mat-dialog-title class="dialog-header no-print">
<span>{{ accountType === 'FD' ? 'Fixed Deposit' : 'Recurring Deposit' }} Certificate</span>
<span class="flex-auto"></span>
</h2>
<div mat-dialog-content class="dialog-content-container">
<!-- Certificate Page Frame -->
<div class="certificate-container" id="deposit-certificate-print">
<div class="certificate-border-outer">
<div class="certificate-border-inner">
<!-- Certificate Watermark Icon/Seal -->
<div class="certificate-watermark">
<mat-icon class="watermark-icon">{{ accountType === 'FD' ? 'savings' : 'event_repeat' }}</mat-icon>
</div>
<div class="certificate-header">
<div class="bank-name">Nexora Co-operative Bank Ltd.</div>
<div class="bank-sub">Mumbai, Maharashtra, India</div>
<div class="cert-title">
{{ accountType === 'FD' ? 'FIXED DEPOSIT CERTIFICATE' : 'RECURRING DEPOSIT CERTIFICATE' }}
</div>
<div class="cert-subtitle">Issued under the Common Seal of the Bank</div>
</div>
<div class="cert-meta-row">
<div class="meta-item">
<span class="meta-label">Certificate No.</span>
<span class="meta-value">{{ certificateNo }}</span>
</div>
<div class="meta-item">
<span class="meta-label">Account No.</span>
<span class="meta-value">{{ accountData.accountNo }}</span>
</div>
<div class="meta-item">
<span class="meta-label">Date of Issue</span>
<span class="meta-value">{{ issueDate | dateFormat }}</span>
</div>
</div>
<div class="cert-body-section">
<p class="cert-main-text">
This is to certify that
<strong class="highlight-text">{{ accountData.clientName || accountData.groupName }}</strong>
holds a {{ accountType === 'FD' ? 'Fixed Deposit' : 'Recurring Deposit' }} account bearing account number
<strong class="highlight-text">{{ accountData.accountNo }}</strong>
with <strong class="highlight-text">Nexora Co-operative Bank Ltd.</strong>, as per the particulars set out
below.
</p>
<div class="issued-to-details">
<div class="issued-to-title">ISSUED TO:</div>
<div class="client-name-details">{{ accountData.clientName || accountData.groupName }}</div>
<div class="client-ids">
<span *ngIf="accountData.clientAccountNo"
><strong>Customer ID:</strong> {{ accountData.clientAccountNo }}</span
>
<span *ngIf="panNumber && panNumber !== 'Not Available'">
&middot; <strong>PAN:</strong> {{ panNumber }}</span
>
</div>
<div class="client-address" *ngIf="clientAddress">
{{ clientAddress }}
</div>
</div>
</div>
<!-- Details Grid -->
<table class="certificate-details-table">
<tbody>
<tr>
<td class="lbl-col">Product</td>
<td class="val-col">{{ accountData.depositProductName }}</td>
<td class="lbl-col">{{ accountType === 'FD' ? 'Deposit Date' : 'First Deposit Date' }}</td>
<td class="val-col">{{ depositDate | dateFormat }}</td>
</tr>
<tr *ngIf="accountType === 'FD'">
<td class="lbl-col">Deposit Amount</td>
<td class="val-col">
{{ accountData.depositAmount | currency: accountData.currency.code : 'symbol-narrow' }}
</td>
<td class="lbl-col">Tenure</td>
<td class="val-col">{{ tenureLabel }}</td>
</tr>
<tr *ngIf="accountType === 'RD'">
<td class="lbl-col">Installment Amount</td>
<td class="val-col">
{{
accountData.mandatoryRecommendedDepositAmount | currency: accountData.currency.code : 'symbol-narrow'
}}
</td>
<td class="lbl-col">Installment Frequency</td>
<td class="val-col">
Every {{ accountData.recurringFrequency }} {{ accountData.recurringFrequencyType?.value }}
</td>
</tr>
<tr *ngIf="accountType === 'RD'">
<td class="lbl-col">Tenure</td>
<td class="val-col">{{ tenureLabel }}</td>
<td class="lbl-col">Interest Rate (p.a.)</td>
<td class="val-col">{{ accountData.nominalAnnualInterestRate }}%</td>
</tr>
<tr *ngIf="accountType === 'FD'">
<td class="lbl-col">Interest Rate (p.a.)</td>
<td class="val-col">{{ accountData.nominalAnnualInterestRate }}%</td>
<td class="lbl-col">Interest Compounding</td>
<td class="val-col">{{ accountData.interestCompoundingPeriodType?.value }}</td>
</tr>
<tr>
<td class="lbl-col">Maturity Date</td>
<td class="val-col">{{ accountData.maturityDate | dateFormat }}</td>
<td class="lbl-col">Current Balance</td>
<td class="val-col">
{{ accountData.summary?.accountBalance | currency: accountData.currency.code : 'symbol-narrow' }}
</td>
</tr>
<tr class="highlight-row">
<td colspan="2" class="lbl-col-highlight">MATURITY AMOUNT</td>
<td colspan="2" class="val-col-highlight">
{{ accountData.maturityAmount | currency: accountData.currency.code : 'symbol-narrow' }}
</td>
</tr>
</tbody>
</table>
<div class="cert-footer">
<div class="seal-container">
<div class="seal-ring">
<div class="seal-text">COMMON SEAL</div>
</div>
</div>
<div class="closing-text">
Given under the common seal of the bank this {{ issueDate | date: 'd' }} day of
{{ issueDate | date: 'MMMM yyyy' }}.
</div>
<div class="signatures-container">
<div class="signature-block">
<div class="signature-line"></div>
<div class="signatory-title">Authorised Signatory</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<mat-dialog-actions align="end" class="no-print">
<button mat-button mat-dialog-close>{{ 'labels.buttons.Close' | translate }}</button>
<button mat-raised-button color="primary" (click)="printCertificate()">
<mat-icon class="m-r-5">print</mat-icon>
Print Certificate
</button>
</mat-dialog-actions>