Merge branch 'feature/account-charges' of https://git.zeptic.in/CBSNexora/Angular-UI-CBS-Main into feature/account-charges

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jaanu423
2026-05-21 21:19:03 +05:30
co-authored by Claude Sonnet 4.6
98 changed files with 8573 additions and 2572 deletions
@@ -57,13 +57,6 @@
</mat-select>
</mat-form-field>
}
@if (savingsProductSelected) {
<mat-form-field appearance="outline" class="sad-field">
<mat-label>{{ 'labels.inputs.External ID' | translate }}</mat-label>
<input matInput formControlName="externalId" />
</mat-form-field>
}
</div>
</div>
@@ -82,6 +82,10 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
primaryClientCif = '';
primaryClientId: number | null = null;
primaryHolderShare = 0;
/** Best-effort string label of the client's entity type
* (e.g. "Individual", "Corporate", "MSME") — used to auto-fill the
* Customer Segment dropdown when the product template lands. */
private clientEntityType: string | null = null;
// ── Status of Account (RBI) ────────────────────────────────────────────
readonly accountStatusOptions = [
@@ -167,8 +171,7 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
productId: this.savingsAccountTemplate.savingsProductId,
submittedOnDate:
this.savingsAccountTemplate.timeline.submittedOnDate &&
new Date(this.savingsAccountTemplate.timeline.submittedOnDate),
externalId: this.savingsAccountTemplate.externalId
new Date(this.savingsAccountTemplate.timeline.submittedOnDate)
});
} else {
this.savingsAccountDetailsForm.patchValue({
@@ -193,11 +196,49 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
this.autoDetectAccountStatus();
}
}
this.clientEntityType = this.deriveEntityType(client);
// Product template may have already arrived before the client did —
// try the segment-apply both here and when the template lands.
this.applyInferredCustomerSegment();
this.cdr.detectChanges();
});
}
}
/**
* Build a best-effort label for the client's entity / customer type.
* Tries `clientType` first (the explicit master), then falls back to
* `clientClassification` and finally `legalForm`.
*/
private deriveEntityType(client: any): string | null {
if (!client) return null;
const direct =
client.clientType?.value ??
client.clientType?.name ??
client.clientClassification?.value ??
client.clientClassification?.name;
if (direct && typeof direct === 'string') return direct;
const legalForm = client.legalForm?.value ?? client.legalForm?.code ?? client.legalForm?.name;
return typeof legalForm === 'string' ? legalForm : null;
}
/**
* If `clientEntityType` and `customerSegmentOptions` are both ready, try
* to match an option (exact then case-insensitive substring) and set it
* as the selected Customer Segment. Falls through silently otherwise so
* the existing product default stays in place.
*/
private applyInferredCustomerSegment(): void {
if (!this.clientEntityType || !this.customerSegmentOptions?.length) return;
const needle = this.clientEntityType.trim().toLowerCase();
const match =
this.customerSegmentOptions.find((o) => o.toLowerCase() === needle) ||
this.customerSegmentOptions.find((o) => o.toLowerCase().includes(needle) || needle.includes(o.toLowerCase()));
if (match) {
this.selectedCustomerSegment = match;
}
}
/** Parse DOB from backend — handles array [yyyy, mm, dd] or string */
private parseClientDob(dob: any): Date | null {
if (!dob) return null;
@@ -263,8 +304,7 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
'',
Validators.required
],
fieldOfficerId: [''],
externalId: ['']
fieldOfficerId: ['']
});
}
@@ -279,6 +319,9 @@ export class SavingsAccountDetailsStepComponent implements OnInit {
this.customerSegmentOptions = this.extractOptions(response.customerSegmentOptions, response.customerSegment);
this.selectedAccountType = response.accountType ?? null;
this.selectedCustomerSegment = response.customerSegment ?? null;
// Override the product's default segment with the one inferred
// from the client's entity type when an option matches.
this.applyInferredCustomerSegment();
this.savingsAccountProductTemplate.emit(response);
this.fieldOfficerData = response.fieldOfficerOptions;
this.savingsProductSelected = true;
@@ -575,15 +575,18 @@
}
</div>
<div class="layout-row responsive-column align-center gap-2px margin-t">
<button mat-raised-button matStepperPrevious>
<fa-icon icon="arrow-left" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Previous' | translate }}
</button>
<button mat-raised-button [routerLink]="['../..']">
<!--
Submit & Cancel — Previous lives in the parent wizard's tab action bar
now that this component renders inside a mat-tab-group rather than a
mat-stepper. Re-introducing matStepperPrevious here would require a
CdkStepper ancestor and would crash the view on init.
-->
<div class="preview-submit-row">
<button mat-stroked-button [routerLink]="['../..']">
{{ 'labels.buttons.Cancel' | translate }}
</button>
<button mat-raised-button color="primary" (click)="submitEvent.emit()">
<button mat-raised-button color="primary" class="preview-submit-row__primary" (click)="submitEvent.emit()">
<fa-icon icon="check" class="m-r-10"></fa-icon>
{{ 'labels.buttons.Submit' | translate }}
</button>
</div>
@@ -13,6 +13,31 @@
padding: 0.5rem 0;
}
/* Submit + Cancel row at the bottom of the preview. Previous lives in the
parent wizard's tab action bar. */
.preview-submit-row {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 12px;
margin-top: 18px;
padding-top: 16px;
border-top: 1px solid #f1f5f9;
button {
height: 42px !important;
border-radius: 10px !important;
font-weight: 600 !important;
padding: 0 22px !important;
}
&__primary {
background: linear-gradient(135deg, #10b981 0%, #047857 100%) !important;
color: #fff !important;
box-shadow: 0 4px 12px -2px rgb(4 120 87 / 35%) !important;
}
}
.preview-section {
border: 1px solid #e2e8f0;
border-radius: 10px;
@@ -23,7 +23,6 @@ import {
} from '@angular/material/table';
import { MatDivider } from '@angular/material/divider';
import { ExternalIdentifierComponent } from '../../../shared/external-identifier/external-identifier.component';
import { MatStepperPrevious } from '@angular/material/stepper';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { FindPipe } from '../../../pipes/find.pipe';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
@@ -52,7 +51,6 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
MatHeaderRow,
MatRowDef,
MatRow,
MatStepperPrevious,
FaIconComponent,
FindPipe,
DateFormatPipe,