static update
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<div class="fdrd-dlg">
|
||||
<!-- HEADER -->
|
||||
<div class="fdrd-head">
|
||||
<div class="fdrd-head-left">
|
||||
<div class="fdrd-head-ic"><fa-icon icon="piggy-bank"></fa-icon></div>
|
||||
<div>
|
||||
<h2 class="fdrd-title">FD / RD Entry</h2>
|
||||
<p class="fdrd-sub">Open a new Fixed Deposit or Recurring Deposit account.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fdrd-head-actions">
|
||||
<span class="fdrd-meta"> <fa-icon icon="university"></fa-icon> {{ bank.name }} </span>
|
||||
<span class="fdrd-meta"> <fa-icon icon="map-marker-alt"></fa-icon> {{ bank.branch }} </span>
|
||||
<button class="fdrd-close" (click)="close()" matTooltip="Close" aria-label="Close">✕</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fdrd-body">
|
||||
<!-- Success banner -->
|
||||
<div class="fdrd-success" *ngIf="saved">
|
||||
<fa-icon icon="check-circle"></fa-icon>
|
||||
<div>
|
||||
<strong>{{ lastAccountNo }}</strong> created for <strong>{{ lastClientName }}</strong>
|
||||
<div class="fdrd-success-sub">You can enter another deposit below, or close this dialog.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FORM -->
|
||||
<div class="fdrd-section">
|
||||
<!-- Row 1: Deposit Info | Client & Amount -->
|
||||
<div class="ws-group-row">
|
||||
<div class="ws-group">
|
||||
<span class="ws-caption">Deposit Info</span>
|
||||
<div class="ws-group__fields">
|
||||
<div class="ws-f" style="width: 200px">
|
||||
<label class="ws-f__lbl">Deposit Type</label>
|
||||
<select class="ws-f__ctl" [(ngModel)]="depositType" (ngModelChange)="onDepositTypeChange()">
|
||||
<option *ngFor="let dt of depositTypes" [value]="dt.code">{{ dt.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ws-f" style="width: 150px">
|
||||
<label class="ws-f__lbl">Pay Mode</label>
|
||||
<select class="ws-f__ctl" [(ngModel)]="payMode">
|
||||
<option *ngFor="let m of payModes" [value]="m">{{ m }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ws-vdivider"></div>
|
||||
|
||||
<div class="ws-group ws-group--flex">
|
||||
<span class="ws-caption">Client & Amount</span>
|
||||
<div class="ws-group__fields">
|
||||
<div class="ws-f" style="flex: 1.5; min-width: 180px">
|
||||
<label class="ws-f__lbl">Client</label>
|
||||
<select class="ws-f__ctl" [(ngModel)]="clientId">
|
||||
<option value="" disabled>-- Select Client --</option>
|
||||
<option *ngFor="let c of clients" [value]="c.id">{{ c.name }} ({{ c.id }})</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ws-f" style="flex: 1; min-width: 120px">
|
||||
<label class="ws-f__lbl">{{ isRecurring ? 'Monthly Instalment (₹)' : 'Deposit Amount (₹)' }}</label>
|
||||
<input
|
||||
class="ws-f__ctl ws-f__ctl--mono"
|
||||
type="number"
|
||||
min="0"
|
||||
[(ngModel)]="principal"
|
||||
placeholder="e.g. 100000"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 2: Term & Rate | Instructions -->
|
||||
<div class="ws-group-row ws-group-row--mt">
|
||||
<div class="ws-group">
|
||||
<span class="ws-caption">Interest & Tenure</span>
|
||||
<div class="ws-group__fields">
|
||||
<div class="ws-f" style="width: 110px">
|
||||
<label class="ws-f__lbl">Int. Rate (% p.a.)</label>
|
||||
<input class="ws-f__ctl" type="number" min="0" step="0.05" [(ngModel)]="interestRate" />
|
||||
</div>
|
||||
<div class="ws-f" style="width: 240px">
|
||||
<label class="ws-f__lbl">Tenure</label>
|
||||
<div class="fdrd-tenure-row">
|
||||
<input class="ws-f__ctl" type="number" min="0" [(ngModel)]="tenureYears" />
|
||||
<span>Yrs</span>
|
||||
<input class="ws-f__ctl" type="number" min="0" max="11" [(ngModel)]="tenureMonths" />
|
||||
<span>Mo</span>
|
||||
<input class="ws-f__ctl" type="number" min="0" max="30" [(ngModel)]="tenureDays" />
|
||||
<span>Days</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ws-vdivider"></div>
|
||||
|
||||
<div class="ws-group ws-group--flex">
|
||||
<span class="ws-caption">Nominee & Maturity Details</span>
|
||||
<div class="ws-group__fields">
|
||||
<div class="ws-f" style="flex: 1; min-width: 120px">
|
||||
<label class="ws-f__lbl">Interest Payout</label>
|
||||
<select class="ws-f__ctl" [(ngModel)]="interestPayout">
|
||||
<option *ngFor="let o of interestPayoutOptions" [value]="o">{{ o }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="ws-f" style="flex: 1; min-width: 130px">
|
||||
<label class="ws-f__lbl">Nominee Name (optional)</label>
|
||||
<input class="ws-f__ctl" type="text" [(ngModel)]="nomineeName" placeholder="Spouse / Child name" />
|
||||
</div>
|
||||
<div class="ws-f" style="flex: 1.2; min-width: 160px">
|
||||
<label class="ws-f__lbl">Maturity Instruction</label>
|
||||
<select class="ws-f__ctl" [(ngModel)]="maturityInstruction">
|
||||
<option *ngFor="let m of maturityInstructions" [value]="m">{{ m }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SUMMARY -->
|
||||
<div class="fdrd-summary">
|
||||
<div class="fdrd-stat">
|
||||
<div class="fdrd-stat-l">Principal</div>
|
||||
<div class="fdrd-stat-v">₹ {{ principal || 0 | number: '1.0-2' }}</div>
|
||||
</div>
|
||||
<div class="fdrd-stat">
|
||||
<div class="fdrd-stat-l">Tenure</div>
|
||||
<div class="fdrd-stat-v">{{ tenureYears }}y {{ tenureMonths }}m {{ tenureDays }}d</div>
|
||||
</div>
|
||||
<div class="fdrd-stat">
|
||||
<div class="fdrd-stat-l">Maturity Date</div>
|
||||
<div class="fdrd-stat-v">{{ maturityDate | date: 'dd-MM-yyyy' }}</div>
|
||||
</div>
|
||||
<div class="fdrd-stat fdrd-stat-good">
|
||||
<div class="fdrd-stat-l">Maturity Amount</div>
|
||||
<div class="fdrd-stat-v">₹ {{ maturityAmount | number: '1.2-2' }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FOOTER -->
|
||||
<div class="fdrd-foot">
|
||||
<div class="fdrd-foot-l">
|
||||
<fa-icon icon="info-circle"></fa-icon> Demo entry — quarterly-compounded interest, no real account is
|
||||
created.
|
||||
</div>
|
||||
<div class="fdrd-foot-actions">
|
||||
<button mat-stroked-button class="fdrd-btn-ghost" (click)="resetForm()">
|
||||
<fa-icon icon="undo"></fa-icon> Reset
|
||||
</button>
|
||||
<button mat-stroked-button class="fdrd-btn-save" [disabled]="!isValid" (click)="save()">
|
||||
<fa-icon icon="save"></fa-icon> Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,395 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
font-family: 'Hanken Grotesk', Inter, sans-serif;
|
||||
color: #1a2a3e;
|
||||
}
|
||||
|
||||
.fdrd-dlg {
|
||||
background: #fff;
|
||||
border-radius: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
/* HEADER - Matches .ws-header in clerk dashboard */
|
||||
.fdrd-head {
|
||||
padding: 0 12px;
|
||||
height: 32px;
|
||||
background: linear-gradient(90deg, #0d1b2e 0%, #162542 100%);
|
||||
border-bottom: 2px solid #e87722;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.fdrd-head-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.fdrd-head-ic {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 6px;
|
||||
background: #e87722;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.fdrd-title {
|
||||
margin: 0;
|
||||
font-family: Newsreader, Georgia, serif;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #e8f0fb;
|
||||
letter-spacing: 0.01em;
|
||||
}
|
||||
|
||||
.fdrd-sub {
|
||||
display: none; /* Hide subtitle in header to match clean style */
|
||||
}
|
||||
|
||||
.fdrd-head-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.fdrd-meta {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
font-size: 11px;
|
||||
color: #7a95b0;
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0;
|
||||
|
||||
fa-icon {
|
||||
color: #5a7589;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.fdrd-close {
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #7a95b0;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.15s;
|
||||
|
||||
&:hover {
|
||||
background: rgb(255 255 255 / 10%);
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
/* BODY - Styled like canvas + card grid */
|
||||
.fdrd-body {
|
||||
padding: 16px 20px;
|
||||
overflow-y: auto;
|
||||
flex: 1;
|
||||
background: #f0f4f9;
|
||||
}
|
||||
|
||||
.fdrd-success {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 12px 16px;
|
||||
border-radius: 10px;
|
||||
background: #dcfce7;
|
||||
color: #15803d;
|
||||
margin-bottom: 14px;
|
||||
font-size: 13px;
|
||||
|
||||
fa-icon {
|
||||
font-size: 16px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.fdrd-success-sub {
|
||||
margin-top: 2px;
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* Card container for form */
|
||||
.fdrd-section {
|
||||
background: #fff;
|
||||
border: 1px solid #dce4ef;
|
||||
border-radius: 10px;
|
||||
padding: 16px 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/* Transaction Entry Style Layout mappings */
|
||||
.ws-group-row {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
gap: 0;
|
||||
|
||||
&--mt {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.ws-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--flex {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
&__fields {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 8px;
|
||||
flex-wrap: nowrap;
|
||||
height: 100%;
|
||||
align-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.ws-caption {
|
||||
font-family: Newsreader, Georgia, serif;
|
||||
font-style: italic;
|
||||
font-size: 11px;
|
||||
color: #7a95b0;
|
||||
padding-bottom: 2px;
|
||||
}
|
||||
|
||||
.ws-vdivider {
|
||||
width: 1px;
|
||||
background: #dce4ef;
|
||||
margin: 12px 10px 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ws-f {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3px;
|
||||
flex-shrink: 0;
|
||||
|
||||
&__lbl {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: #7a95b0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&__ctl {
|
||||
height: 26px;
|
||||
padding: 0 7px;
|
||||
border: 1px solid #c8d8eb;
|
||||
border-radius: 6px;
|
||||
font-family: 'Hanken Grotesk', Inter, sans-serif;
|
||||
font-size: 11.5px;
|
||||
color: #1a2a3e;
|
||||
background: #f4f7fc;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
transition:
|
||||
border-color 0.15s,
|
||||
box-shadow 0.15s;
|
||||
|
||||
&:hover {
|
||||
border-color: #9ab5d0;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #2563eb;
|
||||
box-shadow: 0 0 0 3px rgb(37 99 235 / 12%);
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
&--mono {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-size: 11.5px;
|
||||
letter-spacing: 0.03em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fdrd-tenure-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
|
||||
.ws-f__ctl {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: #7a95b0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
|
||||
/* SUMMARY - Styled like info summary block */
|
||||
.fdrd-summary {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 12px;
|
||||
padding: 12px 16px;
|
||||
background: #f4f7fc;
|
||||
border: 1px solid #c8d8eb;
|
||||
border-radius: 10px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.fdrd-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.fdrd-stat-l {
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
color: #7a95b0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.fdrd-stat-v {
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
color: #1a2a3e;
|
||||
}
|
||||
|
||||
.fdrd-stat-good .fdrd-stat-v {
|
||||
color: #1a7a4a;
|
||||
}
|
||||
|
||||
/* FOOTER - Styled like action panel */
|
||||
.fdrd-foot {
|
||||
padding: 10px 16px;
|
||||
border-top: 1px solid #dce4ef;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
flex-shrink: 0;
|
||||
background: #f0f4f9;
|
||||
}
|
||||
|
||||
.fdrd-foot-l {
|
||||
font-size: 11px;
|
||||
color: #7a95b0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.fdrd-foot-actions {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.fdrd-btn-ghost {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 28px;
|
||||
padding: 0 12px !important;
|
||||
border-radius: 7px;
|
||||
border: 1px solid #dce4ef !important;
|
||||
background: #fff !important;
|
||||
color: #1a2a3e !important;
|
||||
font-family: 'Hanken Grotesk', sans-serif;
|
||||
font-size: 11.5px !important;
|
||||
font-weight: 600 !important;
|
||||
cursor: pointer;
|
||||
box-shadow: none !important;
|
||||
|
||||
&:hover {
|
||||
background: #f0f4f9 !important;
|
||||
border-color: #a8bdd4 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.fdrd-btn-save {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
height: 28px;
|
||||
padding: 0 16px !important;
|
||||
border-radius: 7px;
|
||||
border: none !important;
|
||||
background: #e87722 !important;
|
||||
color: #fff !important;
|
||||
font-family: 'Hanken Grotesk', sans-serif;
|
||||
font-size: 11.5px !important;
|
||||
font-weight: 700 !important;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 8px rgb(232 119 34 / 30%) !important;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
filter: brightness(1.08);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.4;
|
||||
cursor: not-allowed;
|
||||
background: #c8d8eb !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (width <= 768px) {
|
||||
.ws-group-row {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.ws-vdivider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ws-group__fields {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.fdrd-summary {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
/**
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { CommonModule, DecimalPipe } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { MatDialogRef, MatDialogModule } from '@angular/material/dialog';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
|
||||
type DepositType = 'FD-SINGLE' | 'FD-JOINT' | 'RD-MONTHLY' | 'RD-QUARTERLY';
|
||||
|
||||
interface DemoClient {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'mifosx-fd-rd-entry-dialog',
|
||||
standalone: true,
|
||||
templateUrl: './fd-rd-entry-dialog.component.html',
|
||||
styleUrls: ['./fd-rd-entry-dialog.component.scss'],
|
||||
imports: [CommonModule, DecimalPipe, FormsModule, MatDialogModule, MatButtonModule, MatTooltipModule, FaIconComponent]
|
||||
})
|
||||
export class FdRdEntryDialogComponent {
|
||||
private dialogRef = inject(MatDialogRef<FdRdEntryDialogComponent>);
|
||||
private snackBar = inject(MatSnackBar);
|
||||
|
||||
bank = {
|
||||
name: 'CBSNexora Bank Ltd',
|
||||
branch: 'Head Office'
|
||||
};
|
||||
|
||||
depositTypes: { code: DepositType; label: string; defaultRate: number }[] = [
|
||||
{ code: 'FD-SINGLE', label: 'Fixed Deposit — Single A/c', defaultRate: 7.25 },
|
||||
{ code: 'FD-JOINT', label: 'Fixed Deposit — Joint A/c', defaultRate: 7.25 },
|
||||
{ code: 'RD-MONTHLY', label: 'Recurring Deposit — Monthly', defaultRate: 7.0 },
|
||||
{ code: 'RD-QUARTERLY', label: 'Recurring Deposit — Quarterly', defaultRate: 7.0 }
|
||||
];
|
||||
|
||||
clients: DemoClient[] = [
|
||||
{ id: 'C-10231', name: 'Ramesh Kumar Sharma' },
|
||||
{ id: 'C-10344', name: 'Priya Enterprises' },
|
||||
{ id: 'C-10412', name: 'Anjali Verma' },
|
||||
{ id: 'C-10567', name: 'Suresh & Sons HUF' },
|
||||
{ id: 'C-10689', name: 'Vikram Traders' }
|
||||
];
|
||||
|
||||
payModes = ['Cash', 'Cheque', 'Transfer from Savings A/c'];
|
||||
interestPayoutOptions = ['Cumulative (Paid on Maturity)', 'Monthly Payout', 'Quarterly Payout'];
|
||||
maturityInstructions = [
|
||||
'Renew Principal & Interest',
|
||||
'Renew Principal Only, Payout Interest',
|
||||
'Payout on Maturity (No Renewal)'
|
||||
];
|
||||
|
||||
depositType: DepositType = 'FD-SINGLE';
|
||||
clientId = '';
|
||||
principal: number | null = null;
|
||||
interestRate = 7.25;
|
||||
tenureYears = 1;
|
||||
tenureMonths = 0;
|
||||
tenureDays = 0;
|
||||
interestPayout = this.interestPayoutOptions[0];
|
||||
payMode = this.payModes[0];
|
||||
nomineeName = '';
|
||||
maturityInstruction = this.maturityInstructions[0];
|
||||
|
||||
saved = false;
|
||||
lastAccountNo = '';
|
||||
lastClientName = '';
|
||||
|
||||
get selectedClient(): DemoClient | undefined {
|
||||
return this.clients.find((c) => c.id === this.clientId);
|
||||
}
|
||||
|
||||
onDepositTypeChange(): void {
|
||||
const dt = this.depositTypes.find((d) => d.code === this.depositType);
|
||||
if (dt) this.interestRate = dt.defaultRate;
|
||||
}
|
||||
|
||||
get isRecurring(): boolean {
|
||||
return this.depositType.startsWith('RD');
|
||||
}
|
||||
|
||||
get tenureInYears(): number {
|
||||
return this.tenureYears + this.tenureMonths / 12 + this.tenureDays / 365;
|
||||
}
|
||||
|
||||
get maturityDate(): Date {
|
||||
const d = new Date();
|
||||
d.setFullYear(d.getFullYear() + this.tenureYears);
|
||||
d.setMonth(d.getMonth() + this.tenureMonths);
|
||||
d.setDate(d.getDate() + this.tenureDays);
|
||||
return d;
|
||||
}
|
||||
|
||||
/** Quarterly-compounded maturity value, the standard FD/RD convention */
|
||||
get maturityAmount(): number {
|
||||
const p = this.principal || 0;
|
||||
const t = this.tenureInYears;
|
||||
if (p <= 0 || t <= 0) return 0;
|
||||
return p * Math.pow(1 + this.interestRate / 100 / 4, 4 * t);
|
||||
}
|
||||
|
||||
get isValid(): boolean {
|
||||
return !!this.clientId && (this.principal ?? 0) > 0 && this.tenureInYears > 0;
|
||||
}
|
||||
|
||||
save(): void {
|
||||
if (!this.isValid) return;
|
||||
const prefix = this.isRecurring ? 'RD' : 'FD';
|
||||
this.lastAccountNo = `${prefix}${Math.floor(1000000 + Math.random() * 8999999)}`;
|
||||
this.lastClientName = this.selectedClient?.name ?? '';
|
||||
this.saved = true;
|
||||
this.snackBar.open(`${prefix} account ${this.lastAccountNo} created for ${this.lastClientName}`, 'Close', {
|
||||
duration: 4000
|
||||
});
|
||||
}
|
||||
|
||||
resetForm(): void {
|
||||
this.depositType = 'FD-SINGLE';
|
||||
this.clientId = '';
|
||||
this.principal = null;
|
||||
this.interestRate = 7.25;
|
||||
this.tenureYears = 1;
|
||||
this.tenureMonths = 0;
|
||||
this.tenureDays = 0;
|
||||
this.nomineeName = '';
|
||||
this.interestPayout = this.interestPayoutOptions[0];
|
||||
this.payMode = this.payModes[0];
|
||||
this.maturityInstruction = this.maturityInstructions[0];
|
||||
this.saved = false;
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user