save saving ui update and current account update priview section

This commit is contained in:
Nitesh Yadav
2026-04-28 16:22:26 +05:30
parent 31b2490f09
commit 0d3d83799b
7 changed files with 476 additions and 53 deletions
@@ -135,20 +135,37 @@ export class CreateCurrentAccountComponent {
const locale = this.settingsService.language.code;
const dateFormat = this.settingsService.dateFormat;
const monthDayFormat = 'dd MMMM';
const currentAccount = {
...this.currentAccount,
const details = this.currentAccount;
const currentAccount: any = {
...details,
...this.currentAccountCurrencyStep.currencyStepData,
...(this.currentAccountDigitalStep?.currentAccountDigital ?? {}),
charges: [],
submittedOnDate: this.dateUtils.formatDate(this.currentAccount.submittedOnDate, dateFormat),
submittedOnDate: this.dateUtils.formatDate(details.submittedOnDate, dateFormat),
dateFormat,
monthDayFormat,
locale
};
if (details.establishmentDate) {
currentAccount.establishmentDate = this.dateUtils.formatDate(details.establishmentDate, dateFormat);
}
if (details.startOperationDate) {
currentAccount.startOperationDate = this.dateUtils.formatDate(details.startOperationDate, dateFormat);
}
// strip UI-only flags not needed by backend
delete currentAccount.isNonIndividualClient;
if (this.currentAccountTemplate.clientId) {
currentAccount.clientId = this.currentAccountTemplate.clientId;
} else {
currentAccount.groupId = this.currentAccountTemplate.groupId;
}
console.log('Current Account Payload:', JSON.stringify(currentAccount, null, 2));
this.currentAccountsService.createCurrentAccount(currentAccount).subscribe((response: any) => {
this.router.navigate(
[
@@ -117,6 +117,8 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
clientCif: string;
sharePercentage: number;
isMandatory: boolean;
signingAuthority?: string;
role?: string;
}> = [];
modeOfOperation = '';
@@ -159,7 +161,12 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
guardianRelationship = '';
minorDob: Date | null = null;
readonly guardianRelationshipOptions = ['Father', 'Mother', 'Legal Guardian', 'Court Appointed Guardian'];
readonly guardianRelationshipOptions = [
'Father',
'Mother',
'Legal Guardian',
'Court Appointed Guardian'
];
constructor() {
this.createCurrentAccountDetailsForm();
@@ -209,8 +216,14 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
createCurrentAccountDetailsForm() {
this.currentAccountDetailsForm = this.formBuilder.group({
productId: ['', Validators.required],
submittedOnDate: ['', Validators.required],
productId: [
'',
Validators.required
],
submittedOnDate: [
'',
Validators.required
],
fieldOfficerId: [''],
externalId: [''],
balanceSwapOption: [false],
@@ -357,7 +370,9 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
alert(`Account holder with CIF ${result.clientCif} is already added.`);
return;
}
this.jointHolders = [...this.jointHolders, { ...result, isMandatory: false }];
this.jointHolders = [
...this.jointHolders,
{ ...result, isMandatory: false }];
this.autoSetModeOfOperation();
}
});
@@ -414,7 +429,9 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
alert(`Partner with CIF ${result.clientCif} is already added.`);
return;
}
this.relatedClients = [...this.relatedClients, { ...result, isMandatory: false }];
this.relatedClients = [
...this.relatedClients,
{ ...result, isMandatory: false }];
this.autoSetSignatoryRights();
}
});
@@ -457,6 +474,48 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
value.introducerName = this.introducerName;
value.introducerCif = this.introducerCif;
}
value.isNonIndividualClient = this.isNonIndividualClient;
// accountStatus applies to all client types
value.accountStatus = this.selectedAccountStatus || null;
if (this.selectedAccountStatus === 'INDIVIDUAL_MALE' && this.selectedSpecialCategory)
value.specialCategory = this.selectedSpecialCategory;
if (this.selectedAccountStatus === 'INDIVIDUAL_FEMALE' && this.selectedWeakerSection)
value.weakerSection = this.selectedWeakerSection;
if (this.selectedAccountStatus === 'JOINT') {
value.modeOfOperation = this.modeOfOperation || null;
value.jointHolders = [
{
clientId: this.primaryClientId,
clientName: this.primaryClientName,
clientCif: this.primaryClientCif,
sharePercentage: this.primaryHolderShare,
isMandatory: true,
isPrimary: true,
signingAuthority: 'Mandatory',
role: 'Primary Account Holder'
},
...this.jointHolders.map((h) => ({
clientId: h.clientId,
clientName: h.clientName,
clientCif: h.clientCif,
sharePercentage: h.sharePercentage,
isMandatory: h.isMandatory,
isPrimary: false,
signingAuthority: h.signingAuthority || (h.isMandatory ? 'Mandatory' : 'Optional'),
role: h.role || 'Co-Holder'
}))
];
}
if (this.selectedAccountStatus === 'MINOR') {
value.guardianClientId = this.guardianClientId;
value.guardianName = this.guardianName;
value.guardianCif = this.guardianCif;
value.guardianRelationship = this.guardianRelationship;
value.minorDob = this.minorDob ? this.dateUtils.formatDate(this.minorDob, 'yyyy-MM-dd') : null;
}
// non-individual: partners are a separate dataset
if (this.isNonIndividualClient) {
value.signatoryRights = this.signatoryRights || null;
value.partners = this.relatedClients.map((c) => ({
@@ -466,33 +525,6 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
sharePercentage: c.sharePercentage,
isMandatory: c.isMandatory
}));
} else {
if (this.selectedAccountStatus) value.accountStatus = this.selectedAccountStatus;
if (this.selectedAccountStatus === 'INDIVIDUAL_MALE' && this.selectedSpecialCategory)
value.specialCategory = this.selectedSpecialCategory;
if (this.selectedAccountStatus === 'INDIVIDUAL_FEMALE' && this.selectedWeakerSection)
value.weakerSection = this.selectedWeakerSection;
if (this.selectedAccountStatus === 'JOINT') {
value.modeOfOperation = this.modeOfOperation || null;
value.jointHolders = [
{
clientId: this.primaryClientId,
clientName: this.primaryClientName,
clientCif: this.primaryClientCif,
sharePercentage: this.primaryHolderShare,
isMandatory: true,
isPrimary: true
},
...this.jointHolders.map((h) => ({ ...h, isPrimary: false }))
];
}
if (this.selectedAccountStatus === 'MINOR') {
value.guardianClientId = this.guardianClientId;
value.guardianName = this.guardianName;
value.guardianCif = this.guardianCif;
value.guardianRelationship = this.guardianRelationship;
value.minorDob = this.minorDob ? this.dateUtils.formatDate(this.minorDob, 'yyyy-MM-dd') : null;
}
}
return value;
}
@@ -42,6 +42,18 @@
<span class="preview-value preview-muted">Unassigned</span>
}
</div>
@if (currentAccount?.establishmentDate) {
<div class="preview-field">
<span class="preview-label">Establishment Date</span>
<span class="preview-value">{{ currentAccount.establishmentDate | dateFormat }}</span>
</div>
}
@if (currentAccount?.startOperationDate) {
<div class="preview-field">
<span class="preview-label">Start of Operation Date</span>
<span class="preview-value">{{ currentAccount.startOperationDate | dateFormat }}</span>
</div>
}
</div>
</div>
</div>
@@ -157,7 +169,262 @@
</div>
}
<!-- ══ 4. Currency & Account Flags ══════════════════════════════ -->
<!-- ══ 4. Status of Account ══════════════════════════════════════ -->
@if (currentAccount?.accountStatus) {
<div class="preview-section">
<div class="preview-section__header">
<i class="fas fa-id-card preview-section__icon"></i>
<span class="preview-section__title">Status of Account</span>
<span class="preview-section__badge">RBI Guidelines</span>
</div>
<div class="preview-body">
<!-- Status Tile -->
<div class="preview-soa-status-row">
<span class="preview-soa-tile">
@switch (currentAccount.accountStatus) {
@case ('INDIVIDUAL_MALE') {
<i class="fas fa-male"></i> Individual (Male)
}
@case ('INDIVIDUAL_FEMALE') {
<i class="fas fa-female"></i> Individual (Female)
}
@case ('SINGLE') {
<i class="fas fa-user-circle"></i> Single Account
}
@case ('JOINT') {
<i class="fas fa-users"></i> Joint Account
}
@case ('MINOR') {
<i class="fas fa-child"></i> Minor Account
}
@case ('SENIOR_CITIZEN') {
<i class="fas fa-user-clock"></i> Senior Citizen
}
@default {
{{ currentAccount.accountStatus }}
}
}
</span>
</div>
<!-- JOINT: Mode of Operation + Holders Table -->
@if (currentAccount.accountStatus === 'JOINT') {
<div class="preview-grid preview-grid--three" style="margin-top: 12px">
<div class="preview-field">
<span class="preview-label">Mode of Operation</span>
<span class="preview-value">
@switch (currentAccount.modeOfOperation) {
@case ('EITHER_OR_SURVIVOR') {
Either or Survivor
}
@case ('FORMER_OR_SURVIVOR') {
Former or Survivor
}
@case ('JOINTLY') {
Jointly
}
@case ('ANYONE_OR_SURVIVOR') {
Anyone or Survivor
}
@default {
{{ currentAccount.modeOfOperation || '—' }}
}
}
</span>
</div>
</div>
@if (currentAccount.jointHolders?.length) {
<div class="preview-soa-table-wrap">
<table class="preview-soa-tbl">
<thead>
<tr>
<th class="preview-soa-th">Sr.</th>
<th class="preview-soa-th">Holder Name</th>
<th class="preview-soa-th">CIF No.</th>
<th class="preview-soa-th">Ownership %</th>
<th class="preview-soa-th">Signing</th>
<th class="preview-soa-th">Role</th>
</tr>
</thead>
<tbody>
@for (holder of currentAccount.jointHolders; track holder.clientId; let i = $index) {
<tr [class.preview-soa-tr--primary]="holder.isPrimary">
<td class="preview-soa-td">{{ i + 1 }}</td>
<td class="preview-soa-td">
{{ holder.clientName || holder.displayName || '—' }}
@if (holder.isPrimary) {
<span class="preview-soa-primary-tag">Primary</span>
}
</td>
<td class="preview-soa-td preview-mono">{{ holder.clientCif || holder.cifNumber || '—' }}</td>
<td class="preview-soa-td">{{ holder.sharePercentage ?? '—' }}%</td>
<td class="preview-soa-td">
<span class="preview-badge" [class.preview-badge--yes]="holder.isMandatory">
{{ holder.signingAuthority || (holder.isMandatory ? 'Mandatory' : 'Optional') }}
</span>
</td>
<td class="preview-soa-td">
{{ holder.role || (holder.isPrimary ? 'Primary Account Holder' : 'Co-Holder') }}
</td>
</tr>
}
</tbody>
</table>
</div>
}
}
<!-- INDIVIDUAL_MALE: Special Category -->
@if (currentAccount.accountStatus === 'INDIVIDUAL_MALE' && currentAccount.specialCategory) {
<div class="preview-grid preview-grid--three" style="margin-top: 12px">
<div class="preview-field">
<span class="preview-label">Special Category</span>
<span class="preview-value">
@switch (currentAccount.specialCategory) {
@case ('DEFENCE') {
Defence Personnel
}
@case ('EX_SERVICEMAN') {
Ex-Serviceman
}
@case ('GOVT_EMPLOYEE') {
Government Employee
}
@case ('PHYSICALLY_CHALLENGED') {
Physically Challenged
}
@case ('NRI') {
NRI (Non-Resident Indian)
}
@case ('NONE') {
None / General
}
@default {
{{ currentAccount.specialCategory }}
}
}
</span>
</div>
</div>
}
<!-- INDIVIDUAL_FEMALE: Weaker Section -->
@if (currentAccount.accountStatus === 'INDIVIDUAL_FEMALE' && currentAccount.weakerSection) {
<div class="preview-grid preview-grid--three" style="margin-top: 12px">
<div class="preview-field">
<span class="preview-label">Weaker Section</span>
<span class="preview-value">
@switch (currentAccount.weakerSection) {
@case ('BPL') {
BPL (Below Poverty Line)
}
@case ('SC_ST') {
SC / ST Category
}
@case ('MINORITY') {
Minority Community
}
@case ('SHG') {
Self Help Group Member
}
@case ('PMJDY') {
PMJDY Beneficiary
}
@case ('NONE') {
None / General
}
@default {
{{ currentAccount.weakerSection }}
}
}
</span>
</div>
</div>
}
<!-- MINOR: Guardian Details -->
@if (currentAccount.accountStatus === 'MINOR') {
<div class="preview-grid preview-grid--three" style="margin-top: 12px">
@if (currentAccount.guardianName) {
<div class="preview-field">
<span class="preview-label">Guardian Name</span>
<span class="preview-value">{{ currentAccount.guardianName }}</span>
</div>
}
@if (currentAccount.guardianCif) {
<div class="preview-field">
<span class="preview-label">Guardian CIF</span>
<span class="preview-value preview-mono">{{ currentAccount.guardianCif }}</span>
</div>
}
@if (currentAccount.guardianRelationship) {
<div class="preview-field">
<span class="preview-label">Relationship</span>
<span class="preview-value">{{ currentAccount.guardianRelationship }}</span>
</div>
}
@if (currentAccount.minorDob) {
<div class="preview-field">
<span class="preview-label">Minor DOB</span>
<span class="preview-value">{{ currentAccount.minorDob | dateFormat }}</span>
</div>
}
</div>
}
</div>
</div>
}
<!-- ══ 4b. Partners / Related Clients (Non-Individual only) ═════ -->
@if (currentAccount?.isNonIndividualClient) {
<div class="preview-section">
<div class="preview-section__header">
<i class="fas fa-handshake preview-section__icon"></i>
<span class="preview-section__title">Partners / Related Clients</span>
@if (currentAccount?.signatoryRights) {
<span class="preview-section__badge preview-section__badge--digital">{{
currentAccount.signatoryRights
}}</span>
}
</div>
<div class="preview-body">
@if (currentAccount?.partners?.length) {
<div class="preview-soa-table-wrap">
<table class="preview-soa-tbl">
<thead>
<tr>
<th class="preview-soa-th">Sr.</th>
<th class="preview-soa-th">Partner / Client Name</th>
<th class="preview-soa-th">CIF No.</th>
<th class="preview-soa-th">Ownership %</th>
<th class="preview-soa-th">Signing</th>
</tr>
</thead>
<tbody>
@for (p of currentAccount.partners; track p.clientId; let i = $index) {
<tr>
<td class="preview-soa-td">{{ i + 1 }}</td>
<td class="preview-soa-td">{{ p.clientName || '—' }}</td>
<td class="preview-soa-td preview-mono">{{ p.clientCif || '—' }}</td>
<td class="preview-soa-td">{{ p.sharePercentage ?? '—' }}%</td>
<td class="preview-soa-td">
<span class="preview-badge" [class.preview-badge--yes]="p.isMandatory">
{{ p.isMandatory ? 'Mandatory' : 'Optional' }}
</span>
</td>
</tr>
}
</tbody>
</table>
</div>
} @else {
<p class="preview-muted">No related clients / partners added.</p>
}
</div>
</div>
}
<!-- ══ 5. Currency & Account Flags ══════════════════════════════ -->
<div class="preview-section">
<div class="preview-section__header">
<i class="fas fa-coins preview-section__icon"></i>
@@ -112,11 +112,6 @@
font-weight: 500;
}
.preview-muted {
color: #94a3b8;
font-style: italic;
}
.preview-mono {
font-family: monospace;
font-size: 0.88rem;
@@ -376,3 +371,91 @@
.margin-t {
margin-top: 1em;
}
// ── Status of Account ─────────────────────────────────────────────
.preview-soa-status-row {
display: flex;
align-items: center;
gap: 10px;
}
.preview-soa-tile {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 8px 20px;
border-radius: 999px;
font-size: 14px;
font-weight: 700;
background: #eff6ff;
color: #1d4ed8;
border: 2px solid #bfdbfe;
i {
font-size: 16px;
}
&--entity {
background: #fef3c7;
color: #92400e;
border-color: #fde68a;
}
}
.preview-soa-table-wrap {
margin-top: 14px;
overflow-x: auto;
border-radius: 8px;
border: 1px solid #e2e8f0;
}
.preview-soa-tbl {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
.preview-soa-th {
background: #f8fafc;
padding: 8px 12px;
text-align: left;
font-weight: 600;
color: #475569;
border-bottom: 1px solid #e2e8f0;
white-space: nowrap;
}
.preview-soa-td {
padding: 10px 12px;
border-bottom: 1px solid #f1f5f9;
color: #0f172a;
vertical-align: middle;
}
.preview-soa-tr--primary {
background: #f0f9ff;
.preview-soa-td {
font-weight: 600;
}
}
.preview-soa-primary-tag {
display: inline-block;
margin-left: 6px;
padding: 1px 8px;
border-radius: 999px;
font-size: 10px;
font-weight: 700;
background: #dbeafe;
color: #1d4ed8;
border: 1px solid #bfdbfe;
vertical-align: middle;
}
.preview-muted {
color: #94a3b8;
font-size: 13px;
font-style: italic;
margin: 0;
}
@@ -105,6 +105,8 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
clientCif: string;
sharePercentage: number;
isMandatory: boolean;
signingAuthority?: string;
role?: string;
}> = [];
modeOfOperation = '';
@@ -147,7 +149,12 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
guardianRelationship = '';
minorDob: Date | null = null;
readonly guardianRelationshipOptions = ['Father', 'Mother', 'Legal Guardian', 'Court Appointed Guardian'];
readonly guardianRelationshipOptions = [
'Father',
'Mother',
'Legal Guardian',
'Court Appointed Guardian'
];
// ── Deposit Account Link ───────────────────────────────────────────────
dalSelectedType: 'SAVINGS' | 'CURRENT' | null = null;
@@ -212,7 +219,9 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
this.dalLoading = false;
this.cdr.detectChanges();
},
error: () => { this.dalLoading = false; }
error: () => {
this.dalLoading = false;
}
});
}
@@ -319,8 +328,14 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
*/
createRecurringDepositsAccountDetailsForm() {
this.recurringDepositAccountDetailsForm = this.formBuilder.group({
productId: ['', Validators.required],
submittedOnDate: ['', Validators.required],
productId: [
'',
Validators.required
],
submittedOnDate: [
'',
Validators.required
],
fieldOfficerId: [''],
externalId: [''],
balanceSwapOption: [false],
@@ -424,7 +439,9 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
alert(`Account holder with CIF ${result.clientCif} is already added.`);
return;
}
this.jointHolders = [...this.jointHolders, { ...result, isMandatory: false }];
this.jointHolders = [
...this.jointHolders,
{ ...result, isMandatory: false }];
this.autoSetModeOfOperation();
}
});
@@ -490,7 +507,9 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
clientCif: this.primaryClientCif,
sharePercentage: this.primaryHolderShare,
isMandatory: true,
isPrimary: true
isPrimary: true,
signingAuthority: 'Mandatory',
role: 'Primary Account Holder'
},
...this.jointHolders.map((h) => ({
clientId: h.clientId,
@@ -498,7 +517,9 @@ export class RecurringDepositsAccountDetailsStepComponent implements OnInit {
clientCif: h.clientCif,
sharePercentage: h.sharePercentage,
isMandatory: h.isMandatory,
isPrimary: false
isPrimary: false,
signingAuthority: h.signingAuthority || (h.isMandatory ? 'Mandatory' : 'Optional'),
role: h.role || 'Co-Holder'
}))
];
}
@@ -416,7 +416,9 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
cifNumber: this.primaryClientCif,
sharePercentage: this.primaryHolderShare,
isMandatory: true,
isPrimary: true
isPrimary: true,
signingAuthority: 'Mandatory',
role: 'Primary Account Holder'
},
...this.jointHolders.map((h) => ({
clientId: h.clientId,
@@ -425,8 +427,8 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
sharePercentage: h.sharePercentage,
isPrimary: false,
isMandatory: h.isMandatory,
signingAuthority: h.signingAuthority || null,
role: h.role || null
signingAuthority: h.signingAuthority || (h.isMandatory ? 'Mandatory' : 'Optional'),
role: h.role || 'Co-Holder'
}))
];
}
+3 -2
View File
@@ -5,12 +5,13 @@
* 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/.
*/
// IMPORTANT: THIS FILE IS AUTO GENERATED! DO NOT MANUALLY EDIT OR CHECKIN!
/* tslint:disable */
export default {
'mifos_x': {
'version': '260427',
'hash': '65345f99'
'version': '260428',
'hash': '31b2490f'
},
'allow_switching_backend_instance': true
};