feat: merge updates - current account, savings, recurring deposits and shared components
This commit is contained in:
+20
-3
@@ -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(
|
||||
[
|
||||
|
||||
+19
-3
@@ -42,9 +42,23 @@ export class AddRelatedClientDialogComponent implements OnDestroy {
|
||||
Validators.min(1),
|
||||
Validators.max(100)
|
||||
]
|
||||
]
|
||||
],
|
||||
signingAuthority: [null],
|
||||
role: [null]
|
||||
});
|
||||
|
||||
readonly signingAuthorityOptions = [
|
||||
{ value: 'SINGLE', label: 'Single' },
|
||||
{ value: 'JOINTLY', label: 'Jointly' },
|
||||
{ value: 'EITHER_OR_SURVIVOR', label: 'Either or Survivor' }
|
||||
];
|
||||
|
||||
readonly roleOptions = [
|
||||
{ value: 'PRIMARY', label: 'Primary' },
|
||||
{ value: 'JOINT', label: 'Joint' },
|
||||
{ value: 'NOMINEE', label: 'Nominee' }
|
||||
];
|
||||
|
||||
searchResults: any[] = [];
|
||||
selectedClient: any = null;
|
||||
isSearching = false;
|
||||
@@ -89,8 +103,10 @@ export class AddRelatedClientDialogComponent implements OnDestroy {
|
||||
this.dialogRef.close({
|
||||
clientId: this.selectedClient.id,
|
||||
clientName: this.selectedClient.displayName,
|
||||
clientCif: this.selectedClient.cifNumber || this.selectedClient.accountNumber || '',
|
||||
sharePercentage: this.form.get('sharePercentage').value
|
||||
clientCif: this.selectedClient.cifNumber || this.selectedClient.cifNo || '',
|
||||
sharePercentage: this.form.get('sharePercentage').value,
|
||||
signingAuthority: this.form.get('signingAuthority').value || null,
|
||||
role: this.form.get('role').value || null
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+580
-2
@@ -59,6 +59,22 @@
|
||||
<mat-label>{{ 'labels.inputs.External ID' | translate }}</mat-label>
|
||||
<input matInput formControlName="externalId" />
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="sad-field" (click)="establishmentDatePicker.open()">
|
||||
<mat-label>Establishment Date</mat-label>
|
||||
<input matInput [matDatepicker]="establishmentDatePicker" formControlName="establishmentDate" />
|
||||
<mat-datepicker-toggle matSuffix [for]="establishmentDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #establishmentDatePicker></mat-datepicker>
|
||||
<mat-hint>Date of entity / business establishment</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="sad-field" (click)="startOperationDatePicker.open()">
|
||||
<mat-label>Start of Operation Date</mat-label>
|
||||
<input matInput [matDatepicker]="startOperationDatePicker" formControlName="startOperationDate" />
|
||||
<mat-datepicker-toggle matSuffix [for]="startOperationDatePicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #startOperationDatePicker></mat-datepicker>
|
||||
<mat-hint>Date when operations commenced</mat-hint>
|
||||
</mat-form-field>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
@@ -74,12 +90,20 @@
|
||||
<div class="sad-grid sad-grid--classification">
|
||||
<mat-form-field appearance="outline" class="sad-field">
|
||||
<mat-label>Account Type</mat-label>
|
||||
<input matInput [value]="productTemplate.accountType || ''" readonly />
|
||||
<mat-select [(ngModel)]="selectedAccountType" [ngModelOptions]="{ standalone: true }">
|
||||
@for (opt of accountTypeOptions; track opt) {
|
||||
<mat-option [value]="opt">{{ opt }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="sad-field">
|
||||
<mat-label>Customer Segment</mat-label>
|
||||
<input matInput [value]="productTemplate.customerSegment || ''" readonly />
|
||||
<mat-select [(ngModel)]="selectedCustomerSegment" [ngModelOptions]="{ standalone: true }">
|
||||
@for (opt of customerSegmentOptions; track opt) {
|
||||
<mat-option [value]="opt">{{ opt }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="sad-field">
|
||||
@@ -131,6 +155,560 @@
|
||||
}
|
||||
}
|
||||
|
||||
<!-- ══ Status of Account (RBI) — Individual Clients Only ════════ -->
|
||||
@if (currentAccountProductSelected) {
|
||||
<div class="soa-card">
|
||||
<div class="soa-card__header">
|
||||
<div class="soa-card__header-left">
|
||||
<div class="soa-card__icon">
|
||||
<i class="fas fa-id-card"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="soa-card__title">Status of Account</h3>
|
||||
<span class="soa-card__sub">As per RBI guidelines — select account holder type</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="soa-pill">RBI Compliant</span>
|
||||
</div>
|
||||
|
||||
<!-- Auto-detected client info bar -->
|
||||
@if (clientDob) {
|
||||
<div class="soa-client-info-bar">
|
||||
<div class="soa-client-info-bar__item">
|
||||
<mat-icon>cake</mat-icon>
|
||||
<span
|
||||
>Date of Birth: <strong>{{ formatTemplateDate(clientDob) }}</strong></span
|
||||
>
|
||||
</div>
|
||||
<div class="soa-client-info-bar__item">
|
||||
<mat-icon>person_pin</mat-icon>
|
||||
<span
|
||||
>Age: <strong>{{ clientAge }} years</strong></span
|
||||
>
|
||||
</div>
|
||||
@if (clientAge !== null && clientAge < 18) {
|
||||
<span class="soa-auto-pill soa-auto-pill--minor">
|
||||
<mat-icon>child_care</mat-icon> Auto-detected: Minor
|
||||
</span>
|
||||
} @else if (clientAge !== null && clientAge >= 60) {
|
||||
<span class="soa-auto-pill soa-auto-pill--senior">
|
||||
<mat-icon>elderly</mat-icon> Auto-detected: Senior Citizen
|
||||
</span>
|
||||
} @else {
|
||||
<span class="soa-auto-pill soa-auto-pill--ok"><mat-icon>check_circle</mat-icon> Age Verified</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Status selector tiles -->
|
||||
<div class="soa-tiles">
|
||||
@for (opt of accountStatusOptions; track opt.value) {
|
||||
<button
|
||||
type="button"
|
||||
class="soa-tile"
|
||||
[class.soa-tile--selected]="selectedAccountStatus === opt.value"
|
||||
[class.soa-tile--disabled]="isTileDisabled(opt.value)"
|
||||
[disabled]="isTileDisabled(opt.value)"
|
||||
(click)="!isTileDisabled(opt.value) && (selectedAccountStatus = opt.value)"
|
||||
[title]="getTileTooltip(opt.value)"
|
||||
>
|
||||
<mat-icon class="soa-tile__icon" [style.color]="isTileDisabled(opt.value) ? '#cbd5e1' : opt.color">
|
||||
{{ opt.icon }}
|
||||
</mat-icon>
|
||||
<span class="soa-tile__label">{{ opt.label }}</span>
|
||||
@if (isTileDisabled(opt.value)) {
|
||||
<span class="soa-tile__lock"><mat-icon>lock</mat-icon></span>
|
||||
}
|
||||
@if (selectedAccountStatus === opt.value) {
|
||||
<mat-icon class="soa-tile__check">check_circle</mat-icon>
|
||||
}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- ── JOINT ACCOUNT ─────────────────────────────────────────── -->
|
||||
@if (selectedAccountStatus === 'JOINT') {
|
||||
<div class="soa-block">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #8b5cf6">A</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Joint Account Holders</span>
|
||||
<span class="soa-block__hint">Add all co-applicants linked to this joint current account</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="button"
|
||||
class="soa-add-btn"
|
||||
(click)="openAddJointHolderDialog()"
|
||||
>
|
||||
<mat-icon>person_add</mat-icon> Add Holder
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="soa-table-wrap">
|
||||
<table class="soa-tbl">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="soa-th soa-th--sr">Sr.</th>
|
||||
<th class="soa-th">Holder Name</th>
|
||||
<th class="soa-th">CIF No.</th>
|
||||
<th class="soa-th soa-th--center">Ownership %</th>
|
||||
<th class="soa-th soa-th--center">Signing Authority</th>
|
||||
<th class="soa-th soa-th--center">Role</th>
|
||||
<th class="soa-th soa-th--center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<!-- Primary account holder row (non-removable) -->
|
||||
<tr class="soa-tr soa-tr--primary">
|
||||
<td class="soa-td soa-td--sr">1</td>
|
||||
<td class="soa-td">
|
||||
<div class="soa-client-cell">
|
||||
<div class="soa-avatar soa-avatar--primary">
|
||||
{{ primaryClientName ? primaryClientName[0].toUpperCase() : '?' }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="soa-client-name">{{ primaryClientName || 'Primary Holder' }}</span>
|
||||
<span class="soa-primary-tag">Primary Account Holder</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="soa-td">
|
||||
<span class="soa-mono">{{ primaryClientCif || '—' }}</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<input
|
||||
class="soa-pct-input"
|
||||
type="number"
|
||||
min="0"
|
||||
max="100"
|
||||
[(ngModel)]="primaryHolderShare"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
placeholder="0"
|
||||
/>
|
||||
<span class="soa-pct-unit">%</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<span class="soa-sign-toggle soa-sign-toggle--mandatory">
|
||||
<mat-icon>lock</mat-icon> Mandatory
|
||||
</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">Primary Account Holder</td>
|
||||
<td class="soa-td soa-td--center"><span class="soa-no-action">—</span></td>
|
||||
</tr>
|
||||
|
||||
<!-- Co-holders -->
|
||||
@for (h of jointHolders; track h; let i = $index) {
|
||||
<tr class="soa-tr" [class.soa-tr--mandatory]="h.isMandatory">
|
||||
<td class="soa-td soa-td--sr">{{ i + 2 }}</td>
|
||||
<td class="soa-td">
|
||||
<div class="soa-client-cell">
|
||||
<div class="soa-avatar" [class.soa-avatar--mandatory]="h.isMandatory">
|
||||
{{ h.clientName[0].toUpperCase() }}
|
||||
</div>
|
||||
<div>
|
||||
<span class="soa-client-name">{{ h.clientName }}</span>
|
||||
@if (h.isMandatory) {
|
||||
<span class="soa-mandatory-tag">Mandatory Signatory</span>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="soa-td">
|
||||
<span class="soa-mono">{{ h.clientCif || '—' }}</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<span class="soa-pct-badge" [class.soa-pct-badge--full]="h.sharePercentage === 100">
|
||||
{{ h.sharePercentage }}%
|
||||
</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<button
|
||||
type="button"
|
||||
class="soa-sign-toggle"
|
||||
[class.soa-sign-toggle--mandatory]="h.isMandatory"
|
||||
[class.soa-sign-toggle--optional]="!h.isMandatory"
|
||||
(click)="toggleJointHolderMandatory(h)"
|
||||
>
|
||||
<mat-icon>{{ h.isMandatory ? 'lock' : 'lock_open' }}</mat-icon>
|
||||
{{ h.isMandatory ? 'Mandatory' : 'Optional' }}
|
||||
</button>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">Co-Holder</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<button mat-icon-button color="warn" type="button" (click)="removeJointHolder(i)">
|
||||
<mat-icon>delete_outline</mat-icon>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr class="soa-tr-total">
|
||||
<td colspan="3" class="soa-td soa-td--total-label">Total Ownership</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<span
|
||||
class="soa-pct-badge"
|
||||
[class.soa-pct-badge--ok]="totalJointSharePercentage === 100"
|
||||
[class.soa-pct-badge--warn]="totalJointSharePercentage !== 100"
|
||||
>
|
||||
{{ totalJointSharePercentage }}%
|
||||
</span>
|
||||
</td>
|
||||
<td class="soa-td soa-td--center">
|
||||
<span class="soa-mandatory-count">
|
||||
<mat-icon>lock</mat-icon> {{ mandatoryJointCount + 1 }} Mandatory
|
||||
</span>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@if (jointHolders.length === 0) {
|
||||
<div class="soa-empty" style="margin-top: 8px">
|
||||
<mat-icon>group_add</mat-icon>
|
||||
<span>Click <strong>Add Holder</strong> to add joint account holders.</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (totalJointSharePercentage !== 100) {
|
||||
<div class="soa-alert soa-alert--warn" style="margin-top: 8px">
|
||||
<mat-icon>warning_amber</mat-icon>
|
||||
Total ownership is {{ totalJointSharePercentage }}%. It must equal 100%.
|
||||
</div>
|
||||
} @else {
|
||||
<div class="soa-alert soa-alert--ok" style="margin-top: 8px">
|
||||
<mat-icon>check_circle</mat-icon>
|
||||
Ownership allocation is complete (100%).
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<!-- Mode of Operation -->
|
||||
<div class="soa-block soa-block--sep">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #7c3aed">B</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Mode of Operation</span>
|
||||
<span class="soa-block__hint">Auto-set from mandatory holders — override manually if required</span>
|
||||
</div>
|
||||
</div>
|
||||
@if (modeOfOperation) {
|
||||
<span class="soa-auto-badge"><mat-icon>auto_awesome</mat-icon> Auto</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (jointHolders.length === 0) {
|
||||
<div class="soa-empty">
|
||||
<mat-icon>how_to_vote</mat-icon>
|
||||
<span>Add joint holders in Section A first.</span>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="soa-mode-grid">
|
||||
@for (opt of modeOfOperationOptions; track opt.value) {
|
||||
<button
|
||||
type="button"
|
||||
class="soa-mode-card"
|
||||
[class.soa-mode-card--selected]="modeOfOperation === opt.value"
|
||||
(click)="modeOfOperation = opt.value"
|
||||
>
|
||||
<mat-icon class="soa-mode-card__icon">{{ opt.icon }}</mat-icon>
|
||||
<div class="soa-mode-card__code">{{ opt.label }}</div>
|
||||
<div class="soa-mode-card__desc">{{ opt.sublabel }}</div>
|
||||
@if (modeOfOperation === opt.value) {
|
||||
<mat-icon class="soa-mode-card__check">check_circle</mat-icon>
|
||||
}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="soa-mode-summary" [class.soa-mode-summary--set]="modeOfOperation">
|
||||
@if (modeOfOperation) {
|
||||
<mat-icon>how_to_vote</mat-icon>
|
||||
<span
|
||||
>Mode of Operation: <strong>{{ selectedModeLabel }}</strong></span
|
||||
>
|
||||
<span class="soa-mode-summary__from">
|
||||
({{ mandatoryJointCount }} Mandatory + {{ jointHolders.length - mandatoryJointCount }} Optional)
|
||||
</span>
|
||||
} @else {
|
||||
<mat-icon>info</mat-icon>
|
||||
<span>Set Mandatory/Optional for holders above to auto-select mode.</span>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── MINOR ACCOUNT ─────────────────────────────────────────── -->
|
||||
@if (selectedAccountStatus === 'MINOR') {
|
||||
<div class="soa-block">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #f59e0b">
|
||||
<mat-icon style="font-size: 14px; height: 14px; width: 14px">child_care</mat-icon>
|
||||
</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Minor Account Details</span>
|
||||
<span class="soa-block__hint">As per RBI — guardian must be an existing registered client</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="soa-pill soa-pill--minor">Guardian Required</span>
|
||||
</div>
|
||||
|
||||
<div class="soa-minor-grid">
|
||||
<mat-form-field appearance="outline" class="soa-field" (click)="minorDobPicker.open()">
|
||||
<mat-label>Minor's Date of Birth</mat-label>
|
||||
<input
|
||||
matInput
|
||||
[matDatepicker]="minorDobPicker"
|
||||
[max]="maxDate"
|
||||
[(ngModel)]="minorDob"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
/>
|
||||
<mat-datepicker-toggle matSuffix [for]="minorDobPicker"></mat-datepicker-toggle>
|
||||
<mat-datepicker #minorDobPicker></mat-datepicker>
|
||||
@if (clientDob) {
|
||||
<mat-hint>Auto-filled from client profile</mat-hint>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="soa-field">
|
||||
<mat-label>Age</mat-label>
|
||||
<input matInput [value]="clientAge !== null ? clientAge + ' years' : '—'" readonly />
|
||||
<mat-hint>Must be below 18 years</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="soa-field">
|
||||
<mat-label>Date of Majority (Auto)</mat-label>
|
||||
<input matInput [value]="majorityDate" readonly />
|
||||
<mat-hint>Auto-calculated: DOB + 18 years</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="soa-field">
|
||||
<mat-label>Guardian Relationship</mat-label>
|
||||
<mat-select [(ngModel)]="guardianRelationship" [ngModelOptions]="{ standalone: true }">
|
||||
@for (rel of guardianRelationshipOptions; track rel) {
|
||||
<mat-option [value]="rel">{{ rel }}</mat-option>
|
||||
}
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="soa-guardian-search">
|
||||
<div class="soa-guardian-search__label">
|
||||
<mat-icon>manage_accounts</mat-icon>
|
||||
<span>Search & Link Guardian (existing client)</span>
|
||||
</div>
|
||||
<mifosx-introducer-search (introducerChange)="onGuardianChange($event)"></mifosx-introducer-search>
|
||||
|
||||
@if (guardianName) {
|
||||
<div class="soa-guardian-selected">
|
||||
<mat-icon class="soa-guardian-selected__icon">verified_user</mat-icon>
|
||||
<div>
|
||||
<div class="soa-guardian-selected__name">{{ guardianName }}</div>
|
||||
<div class="soa-guardian-selected__cif">CIF: {{ guardianCif || 'N/A' }}</div>
|
||||
</div>
|
||||
<span class="soa-pill soa-pill--ok">Guardian Linked</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="soa-info-banner soa-info-banner--minor">
|
||||
<mat-icon>info</mat-icon>
|
||||
<ul>
|
||||
<li>Minor below 10 years — Guardian must operate the account.</li>
|
||||
<li>Minor above 10 years — Can operate independently (bank discretion).</li>
|
||||
<li>Account must be converted to regular savings on attaining majority.</li>
|
||||
<li>Fresh KYC of the minor must be done on majority.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── SENIOR CITIZEN ────────────────────────────────────────── -->
|
||||
@if (selectedAccountStatus === 'SENIOR_CITIZEN') {
|
||||
<div class="soa-block">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #10b981">
|
||||
<mat-icon style="font-size: 14px; height: 14px; width: 14px">elderly</mat-icon>
|
||||
</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Senior Citizen Account</span>
|
||||
<span class="soa-block__hint">Age ≥ 60 years — eligible for preferential banking services</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="soa-pill soa-pill--senior">Age ≥ 60</span>
|
||||
</div>
|
||||
|
||||
<div class="soa-minor-grid" style="margin-bottom: 16px">
|
||||
<mat-form-field appearance="outline" class="soa-field">
|
||||
<mat-label>Date of Birth</mat-label>
|
||||
<input matInput [value]="formatTemplateDate(clientDob)" readonly />
|
||||
<mat-hint>From client profile</mat-hint>
|
||||
</mat-form-field>
|
||||
|
||||
<mat-form-field appearance="outline" class="soa-field">
|
||||
<mat-label>Age</mat-label>
|
||||
<input matInput [value]="clientAge !== null ? clientAge + ' years' : '—'" readonly />
|
||||
<mat-hint>Age ≥ 60 required for Senior Citizen</mat-hint>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="soa-sc-benefits">
|
||||
<div class="soa-sc-benefit">
|
||||
<mat-icon>priority_high</mat-icon>
|
||||
<div>
|
||||
<strong>Priority Service</strong>
|
||||
<span>Dedicated counters / assisted banking at branches</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="soa-sc-benefit">
|
||||
<mat-icon>percent</mat-icon>
|
||||
<div>
|
||||
<strong>Preferential Interest Rate</strong>
|
||||
<span>Additional 0.25%–0.50% on deposits (as per product)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="soa-sc-benefit">
|
||||
<mat-icon>health_and_safety</mat-icon>
|
||||
<div>
|
||||
<strong>Doorstep Banking</strong>
|
||||
<span>Eligible for home banking services (RBI circular)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="soa-sc-benefit">
|
||||
<mat-icon>gavel</mat-icon>
|
||||
<div>
|
||||
<strong>Nomination Mandatory</strong>
|
||||
<span>RBI mandate — ensure nomination is registered</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="soa-info-banner soa-info-banner--senior">
|
||||
<mat-icon>info</mat-icon>
|
||||
<ul>
|
||||
<li>Age proof (DOB document) mandatory at time of account opening.</li>
|
||||
<li>Nomination registration is compulsory (Form DA-1).</li>
|
||||
<li>Bank must offer dedicated helpline and priority grievance redressal.</li>
|
||||
<li>Door-step banking services must be offered (RBI Master Direction 2023).</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── INDIVIDUAL MALE ───────────────────────────────────────── -->
|
||||
@if (selectedAccountStatus === 'INDIVIDUAL_MALE') {
|
||||
<div class="soa-block">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #3b82f6">
|
||||
<mat-icon style="font-size: 14px; height: 14px; width: 14px">person</mat-icon>
|
||||
</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Individual Account (Male)</span>
|
||||
<span class="soa-block__hint"
|
||||
>Select special category if applicable — governs applicable schemes & benefits</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<span class="soa-pill" style="background: #dbeafe; color: #1d4ed8; border-color: #bfdbfe"
|
||||
>Special Category</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="soa-category-grid">
|
||||
@for (opt of specialCategoryOptions; track opt.value) {
|
||||
<button
|
||||
type="button"
|
||||
class="soa-cat-tile"
|
||||
[class.soa-cat-tile--selected]="selectedSpecialCategory === opt.value"
|
||||
[class.soa-cat-tile--male]="true"
|
||||
(click)="selectedSpecialCategory = opt.value"
|
||||
>
|
||||
<mat-icon class="soa-cat-tile__icon">{{ opt.icon }}</mat-icon>
|
||||
<span class="soa-cat-tile__label">{{ opt.label }}</span>
|
||||
@if (selectedSpecialCategory === opt.value) {
|
||||
<mat-icon class="soa-cat-tile__check">check_circle</mat-icon>
|
||||
}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="soa-info-banner soa-info-banner--male">
|
||||
<mat-icon>info</mat-icon>
|
||||
<ul>
|
||||
<li>Valid KYC documents required (Aadhaar / PAN / Passport).</li>
|
||||
<li>Nomination registration is mandatory (Form DA-1).</li>
|
||||
<li>Defence / Ex-Serviceman — eligible for special savings schemes (DSSP).</li>
|
||||
<li>NRI — FCNR / NRE / NRO account rules apply as per FEMA guidelines.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ── INDIVIDUAL FEMALE ──────────────────────────────────────── -->
|
||||
@if (selectedAccountStatus === 'INDIVIDUAL_FEMALE') {
|
||||
<div class="soa-block">
|
||||
<div class="soa-block__head">
|
||||
<div class="soa-block__head-left">
|
||||
<span class="soa-block__letter" style="background: #ec4899">
|
||||
<mat-icon style="font-size: 14px; height: 14px; width: 14px">person_outline</mat-icon>
|
||||
</span>
|
||||
<div>
|
||||
<span class="soa-block__title">Individual Account (Female)</span>
|
||||
<span class="soa-block__hint"
|
||||
>Select weaker section category if applicable — governs PMJDY & priority schemes</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<span class="soa-pill" style="background: #fce7f3; color: #be185d; border-color: #f9a8d4"
|
||||
>Weaker Section</span
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="soa-category-grid">
|
||||
@for (opt of weakerSectionOptions; track opt.value) {
|
||||
<button
|
||||
type="button"
|
||||
class="soa-cat-tile"
|
||||
[class.soa-cat-tile--selected]="selectedWeakerSection === opt.value"
|
||||
[class.soa-cat-tile--female]="true"
|
||||
(click)="selectedWeakerSection = opt.value"
|
||||
>
|
||||
<mat-icon class="soa-cat-tile__icon">{{ opt.icon }}</mat-icon>
|
||||
<span class="soa-cat-tile__label">{{ opt.label }}</span>
|
||||
@if (selectedWeakerSection === opt.value) {
|
||||
<mat-icon class="soa-cat-tile__check">check_circle</mat-icon>
|
||||
}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="soa-info-banner soa-info-banner--female">
|
||||
<mat-icon>info</mat-icon>
|
||||
<ul>
|
||||
<li>Valid KYC documents required (Aadhaar / PAN / Passport).</li>
|
||||
<li>Nomination registration is mandatory (Form DA-1).</li>
|
||||
<li>BPL / SC-ST / Minority — eligible for zero-balance accounts (RBI Priority Sector norms).</li>
|
||||
<li>PMJDY beneficiary — ₹10,000 overdraft facility & accident insurance cover applicable.</li>
|
||||
<li>SHG members — group linkage lending & special deposit rates applicable.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- ══ Non-Individual Account Details (Indian Banking Style) ═════ -->
|
||||
@if (isNonIndividualClient && currentAccountProductSelected) {
|
||||
<div class="ni-card">
|
||||
|
||||
+935
@@ -712,6 +712,941 @@ $ni-bg: #f9fafb;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Status of Account (RBI) ───────────────────────────────────────────────
|
||||
|
||||
.soa-card {
|
||||
margin-top: 16px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
overflow: visible;
|
||||
|
||||
&__header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 12px 24px;
|
||||
background: #f8f9fa;
|
||||
border-bottom: 1px solid #e8eaed;
|
||||
border-radius: 10px 10px 0 0;
|
||||
}
|
||||
|
||||
&__header-left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: 8px;
|
||||
background: #ede9fe;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
i {
|
||||
font-size: 16px;
|
||||
color: #7c3aed;
|
||||
}
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #202124;
|
||||
}
|
||||
|
||||
&__sub {
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 3px 12px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
background: #ede9fe;
|
||||
color: #7c3aed;
|
||||
border: 1px solid #ddd6fe;
|
||||
|
||||
&--minor {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
border-color: #fde68a;
|
||||
}
|
||||
|
||||
&--senior {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
border-color: #a7f3d0;
|
||||
}
|
||||
|
||||
&--ok {
|
||||
background: #dcfce7;
|
||||
color: #15803d;
|
||||
border-color: #bbf7d0;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-client-info-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
padding: 10px 24px;
|
||||
background: #f0f9ff;
|
||||
border-bottom: 1px solid #bae6fd;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
color: #0369a1;
|
||||
|
||||
mat-icon {
|
||||
font-size: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.soa-auto-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
margin-left: auto;
|
||||
|
||||
mat-icon {
|
||||
font-size: 13px;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
&--minor {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
border: 1px solid #fde68a;
|
||||
}
|
||||
|
||||
&--senior {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
border: 1px solid #a7f3d0;
|
||||
}
|
||||
|
||||
&--ok {
|
||||
background: #dcfce7;
|
||||
color: #15803d;
|
||||
border: 1px solid #bbf7d0;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-tiles {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 1fr);
|
||||
gap: 12px;
|
||||
padding: 16px 24px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
|
||||
@media (width <= 900px) {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
|
||||
@media (width <= 600px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.soa-tile {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 14px 10px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color 0.15s,
|
||||
box-shadow 0.15s;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
border-color: #a5b4fc;
|
||||
box-shadow: 0 2px 8px rgb(99 102 241 / 12%);
|
||||
}
|
||||
|
||||
&--selected {
|
||||
border-color: #6366f1;
|
||||
background: #eef2ff;
|
||||
box-shadow: 0 2px 12px rgb(99 102 241 / 20%);
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: 28px;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__check {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
font-size: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
color: #6366f1;
|
||||
}
|
||||
|
||||
&__lock {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
right: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
mat-icon {
|
||||
font-size: 13px;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
opacity: 0.45;
|
||||
cursor: not-allowed;
|
||||
background: #f8fafc;
|
||||
border-color: #e2e8f0;
|
||||
box-shadow: none;
|
||||
|
||||
&:hover {
|
||||
border-color: #e2e8f0;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.soa-block {
|
||||
padding: 16px 24px;
|
||||
|
||||
&--sep {
|
||||
border-top: 1px dashed #e2e8f0;
|
||||
}
|
||||
|
||||
&__head {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
&__head-left {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
&__letter {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
&__title {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&__hint {
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-table-wrap {
|
||||
overflow-x: auto;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
.soa-tbl {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.soa-th {
|
||||
padding: 10px 14px;
|
||||
background: #f8fafc;
|
||||
text-align: left;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
color: #64748b;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
border-bottom: 1px solid #e2e8f0;
|
||||
|
||||
&--sr {
|
||||
width: 44px;
|
||||
}
|
||||
|
||||
&--center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-td {
|
||||
padding: 10px 14px;
|
||||
border-bottom: 1px solid #f1f5f9;
|
||||
vertical-align: middle;
|
||||
|
||||
&--sr {
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #94a3b8;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&--center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&--total-label {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #475569;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-tr {
|
||||
transition: background 0.1s;
|
||||
|
||||
&:hover {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
&--mandatory {
|
||||
background: #fdf4ff;
|
||||
}
|
||||
|
||||
&--primary {
|
||||
background: #f0f9ff;
|
||||
border-left: 3px solid #0891b2;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-avatar--primary {
|
||||
background: #cffafe;
|
||||
color: #0e7490;
|
||||
}
|
||||
|
||||
.soa-primary-tag {
|
||||
font-size: 10px;
|
||||
color: #0e7490;
|
||||
font-weight: 600;
|
||||
background: #cffafe;
|
||||
padding: 1px 7px;
|
||||
border-radius: 999px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.soa-pct-input {
|
||||
width: 56px;
|
||||
padding: 4px 6px;
|
||||
border: 1px solid #cbd5e1;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
text-align: center;
|
||||
color: #1f2937;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: #0891b2;
|
||||
box-shadow: 0 0 0 2px rgb(8 145 178 / 15%);
|
||||
}
|
||||
|
||||
&::-webkit-inner-spin-button,
|
||||
&::-webkit-outer-spin-button {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-pct-unit {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #64748b;
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
.soa-no-action {
|
||||
color: #cbd5e1;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.soa-tr-total {
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.soa-client-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.soa-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 50%;
|
||||
background: #dbeafe;
|
||||
color: #1d4ed8;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--mandatory {
|
||||
background: #ede9fe;
|
||||
color: #7c3aed;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-client-name {
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
color: #1f2937;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.soa-mandatory-tag {
|
||||
font-size: 10px;
|
||||
color: #7c3aed;
|
||||
font-weight: 600;
|
||||
background: #ede9fe;
|
||||
padding: 1px 7px;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.soa-mono {
|
||||
font-family: 'Roboto Mono', monospace;
|
||||
font-size: 12px;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
.soa-pct-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 2px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
background: #f1f5f9;
|
||||
color: #475569;
|
||||
|
||||
&--full,
|
||||
&--ok {
|
||||
background: #dcfce7;
|
||||
color: #15803d;
|
||||
}
|
||||
|
||||
&--warn {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-sign-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
border: 1px solid #e2e8f0;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
|
||||
mat-icon {
|
||||
font-size: 14px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
&--mandatory {
|
||||
background: #ede9fe;
|
||||
color: #7c3aed;
|
||||
border-color: #ddd6fe;
|
||||
}
|
||||
|
||||
&--optional {
|
||||
background: #f8fafc;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-mandatory-count {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: #7c3aed;
|
||||
|
||||
mat-icon {
|
||||
font-size: 14px;
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-alert {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
|
||||
mat-icon {
|
||||
font-size: 18px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
&--warn {
|
||||
background: #fef3c7;
|
||||
color: #b45309;
|
||||
}
|
||||
|
||||
&--ok {
|
||||
background: #dcfce7;
|
||||
color: #15803d;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-empty {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 20px;
|
||||
background: #f8fafc;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
color: #64748b;
|
||||
|
||||
mat-icon {
|
||||
color: #94a3b8;
|
||||
font-size: 22px;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-add-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.soa-mode-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 10px;
|
||||
|
||||
@media (width <= 700px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.soa-mode-card {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 12px 8px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
|
||||
&:hover {
|
||||
border-color: #a5b4fc;
|
||||
}
|
||||
|
||||
&--selected {
|
||||
border-color: #7c3aed;
|
||||
background: #faf5ff;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: 24px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
color: #7c3aed;
|
||||
}
|
||||
|
||||
&__code {
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
&__desc {
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__check {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
font-size: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
color: #7c3aed;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-mode-summary {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 12px;
|
||||
padding: 8px 14px;
|
||||
border-radius: 8px;
|
||||
font-size: 13px;
|
||||
background: #f8fafc;
|
||||
color: #64748b;
|
||||
|
||||
mat-icon {
|
||||
font-size: 18px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
&--set {
|
||||
background: #faf5ff;
|
||||
color: #7c3aed;
|
||||
}
|
||||
|
||||
&__from {
|
||||
font-size: 11px;
|
||||
color: #94a3b8;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-auto-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 3px 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
background: #fef9c3;
|
||||
color: #854d0e;
|
||||
border: 1px solid #fde68a;
|
||||
|
||||
mat-icon {
|
||||
font-size: 13px;
|
||||
height: 13px;
|
||||
width: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-minor-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 4px 16px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
@media (width <= 700px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-field {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.soa-guardian-search {
|
||||
margin-bottom: 12px;
|
||||
|
||||
&__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
margin-bottom: 8px;
|
||||
|
||||
mat-icon {
|
||||
font-size: 18px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
color: #7c3aed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.soa-guardian-selected {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 10px 14px;
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #bbf7d0;
|
||||
border-radius: 8px;
|
||||
margin-top: 10px;
|
||||
|
||||
&__icon {
|
||||
font-size: 24px;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
color: #16a34a;
|
||||
}
|
||||
|
||||
&__name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #1f2937;
|
||||
}
|
||||
|
||||
&__cif {
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-sc-benefits {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 10px;
|
||||
margin-bottom: 14px;
|
||||
|
||||
@media (width <= 600px) {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-sc-benefit {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 12px;
|
||||
background: #f0fdf4;
|
||||
border: 1px solid #bbf7d0;
|
||||
border-radius: 8px;
|
||||
|
||||
mat-icon {
|
||||
color: #16a34a;
|
||||
font-size: 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
strong {
|
||||
display: block;
|
||||
font-size: 13px;
|
||||
color: #1f2937;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
color: #6b7280;
|
||||
}
|
||||
}
|
||||
|
||||
.soa-category-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
margin-bottom: 16px;
|
||||
|
||||
@media (width <= 700px) {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.soa-cat-tile {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 14px 10px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition: all 0.15s;
|
||||
|
||||
&:hover {
|
||||
border-color: #a5b4fc;
|
||||
box-shadow: 0 2px 8px rgb(99 102 241 / 12%);
|
||||
}
|
||||
|
||||
&--selected {
|
||||
&.soa-cat-tile--male {
|
||||
border-color: #3b82f6;
|
||||
background: #eff6ff;
|
||||
box-shadow: 0 2px 12px rgb(59 130 246 / 20%);
|
||||
}
|
||||
|
||||
&.soa-cat-tile--female {
|
||||
border-color: #ec4899;
|
||||
background: #fdf2f8;
|
||||
box-shadow: 0 2px 12px rgb(236 72 153 / 20%);
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
font-size: 26px;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
color: #64748b;
|
||||
}
|
||||
|
||||
&--selected.soa-cat-tile--male &__icon {
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
&--selected.soa-cat-tile--female &__icon {
|
||||
color: #ec4899;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #374151;
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
&__check {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
font-size: 16px;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
|
||||
.soa-cat-tile--male & {
|
||||
color: #3b82f6;
|
||||
}
|
||||
|
||||
.soa-cat-tile--female & {
|
||||
color: #ec4899;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.soa-info-banner {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
padding: 12px 14px;
|
||||
border-radius: 8px;
|
||||
font-size: 12px;
|
||||
background: #eff6ff;
|
||||
border: 1px solid #bfdbfe;
|
||||
color: #1e40af;
|
||||
|
||||
mat-icon {
|
||||
font-size: 18px;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 4px 0 0;
|
||||
padding-left: 18px;
|
||||
|
||||
li {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&--minor {
|
||||
background: #fefce8;
|
||||
border-color: #fde68a;
|
||||
color: #92400e;
|
||||
}
|
||||
|
||||
&--senior {
|
||||
background: #f0fdf4;
|
||||
border-color: #bbf7d0;
|
||||
color: #065f46;
|
||||
}
|
||||
|
||||
&--male {
|
||||
background: #eff6ff;
|
||||
border-color: #bfdbfe;
|
||||
color: #1e40af;
|
||||
}
|
||||
|
||||
&--female {
|
||||
background: #fdf2f8;
|
||||
border-color: #f9a8d4;
|
||||
color: #9d174d;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Account Feature Toggles ────────────────────────────────────────────────
|
||||
.sad-toggles {
|
||||
display: flex;
|
||||
|
||||
+274
-63
@@ -8,7 +8,7 @@
|
||||
|
||||
/** Angular Imports */
|
||||
import { Component, OnInit, Input, Output, EventEmitter, inject, ChangeDetectorRef } from '@angular/core';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule } from '@angular/forms';
|
||||
import { UntypedFormGroup, UntypedFormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms';
|
||||
import { Dates } from 'app/core/utils/dates';
|
||||
|
||||
/** Custom Services */
|
||||
@@ -17,20 +17,7 @@ import { SettingsService } from 'app/settings/settings.service';
|
||||
import { ClientsService } from 'app/clients/clients.service';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatStepperPrevious, MatStepperNext } from '@angular/material/stepper';
|
||||
import {
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderCell,
|
||||
MatCellDef,
|
||||
MatCell,
|
||||
MatHeaderRowDef,
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow
|
||||
} from '@angular/material/table';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
|
||||
import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
|
||||
import { IntroducerSearchComponent } from 'app/shared/introducer-search/introducer-search.component';
|
||||
@@ -49,16 +36,6 @@ import { AddRelatedClientDialogComponent } from './add-related-client-dialog/add
|
||||
FaIconComponent,
|
||||
MatStepperNext,
|
||||
IntroducerSearchComponent,
|
||||
MatTable,
|
||||
MatColumnDef,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderCell,
|
||||
MatCellDef,
|
||||
MatCell,
|
||||
MatHeaderRowDef,
|
||||
MatHeaderRow,
|
||||
MatRowDef,
|
||||
MatRow,
|
||||
MatIcon,
|
||||
FormsModule
|
||||
]
|
||||
@@ -72,20 +49,13 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
private dateUtils = inject(Dates);
|
||||
private cdr = inject(ChangeDetectorRef);
|
||||
|
||||
/** Current Account Template */
|
||||
@Input() currentAccountTemplate: any;
|
||||
|
||||
/** Minimum date allowed. */
|
||||
minDate = new Date(2000, 0, 1);
|
||||
/** Maximum date allowed. */
|
||||
maxDate = new Date();
|
||||
/** Product Data */
|
||||
productData: any;
|
||||
/** Field Officer Data */
|
||||
fieldOfficerData: any;
|
||||
/** For edit current account form */
|
||||
isFieldOfficerPatched = false;
|
||||
/** Current Account Details Form */
|
||||
currentAccountDetailsForm: UntypedFormGroup;
|
||||
|
||||
currentAccountProductSelected = false;
|
||||
@@ -93,7 +63,7 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
introducerName: string | null = null;
|
||||
introducerCif: string | null = null;
|
||||
|
||||
/** Non-Individual section */
|
||||
// ── Non-Individual (existing) ──────────────────────────────────────────
|
||||
isNonIndividualClient = false;
|
||||
relatedClients: Array<{
|
||||
clientId: number;
|
||||
@@ -111,11 +81,92 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
{ value: 'ONLY_ONE', label: 'Single', sublabel: 'Only 1 Person', icon: 'person' }
|
||||
];
|
||||
|
||||
/** Current Account Template with product data */
|
||||
@Output() currentAccountProductTemplate = new EventEmitter();
|
||||
|
||||
/** Local copy of product template for displaying classification info */
|
||||
productTemplate: any = null;
|
||||
accountTypeOptions: string[] = [];
|
||||
customerSegmentOptions: string[] = [];
|
||||
selectedAccountType: string | null = null;
|
||||
selectedCustomerSegment: string | null = null;
|
||||
|
||||
// ── Client info (auto-fetched) ─────────────────────────────────────────
|
||||
clientDob: Date | null = null;
|
||||
clientAge: number | null = null;
|
||||
clientGender: string | null = null;
|
||||
primaryClientName = '';
|
||||
primaryClientCif = '';
|
||||
primaryClientId: number | null = null;
|
||||
primaryHolderShare = 0;
|
||||
|
||||
// ── Status of Account (RBI) ────────────────────────────────────────────
|
||||
readonly accountStatusOptions = [
|
||||
{ value: 'INDIVIDUAL_MALE', label: 'Individual (Male)', icon: 'person', color: '#3b82f6' },
|
||||
{ value: 'INDIVIDUAL_FEMALE', label: 'Individual (Female)', icon: 'person_outline', color: '#ec4899' },
|
||||
{ value: 'SINGLE', label: 'Single Account', icon: 'account_circle', color: '#0891b2' },
|
||||
{ value: 'JOINT', label: 'Joint Account', icon: 'group', color: '#8b5cf6' },
|
||||
{ value: 'MINOR', label: 'Minor Account', icon: 'child_care', color: '#f59e0b' },
|
||||
{ value: 'SENIOR_CITIZEN', label: 'Senior Citizen', icon: 'elderly', color: '#10b981' }
|
||||
];
|
||||
|
||||
selectedAccountStatus = '';
|
||||
|
||||
// ── Joint Account (Status of Account) ─────────────────────────────────
|
||||
jointHolders: Array<{
|
||||
clientId: number;
|
||||
clientName: string;
|
||||
clientCif: string;
|
||||
sharePercentage: number;
|
||||
isMandatory: boolean;
|
||||
signingAuthority?: string;
|
||||
role?: string;
|
||||
}> = [];
|
||||
|
||||
modeOfOperation = '';
|
||||
|
||||
readonly modeOfOperationOptions = [
|
||||
{ value: 'EITHER_OR_SURVIVOR', label: 'E or S', sublabel: 'Either or Survivor', icon: 'how_to_vote' },
|
||||
{ value: 'FORMER_OR_SURVIVOR', label: 'F or S', sublabel: 'Former or Survivor', icon: 'person' },
|
||||
{ value: 'JOINTLY', label: 'Jointly', sublabel: 'All Must Sign', icon: 'groups' },
|
||||
{ value: 'ANYONE_OR_SURVIVOR', label: 'Anyone', sublabel: 'Anyone or Survivor', icon: 'group' }
|
||||
];
|
||||
|
||||
// ── Individual Male — Special Category ────────────────────────────────
|
||||
selectedSpecialCategory = '';
|
||||
|
||||
readonly specialCategoryOptions = [
|
||||
{ value: 'DEFENCE', label: 'Defence Personnel', icon: 'military_tech' },
|
||||
{ value: 'EX_SERVICEMAN', label: 'Ex-Serviceman', icon: 'shield' },
|
||||
{ value: 'GOVT_EMPLOYEE', label: 'Government Employee', icon: 'account_balance' },
|
||||
{ value: 'PHYSICALLY_CHALLENGED', label: 'Physically Challenged', icon: 'accessible' },
|
||||
{ value: 'NRI', label: 'NRI (Non-Resident Indian)', icon: 'flight' },
|
||||
{ value: 'NONE', label: 'None / General', icon: 'person' }
|
||||
];
|
||||
|
||||
// ── Individual Female — Weaker Section ────────────────────────────────
|
||||
selectedWeakerSection = '';
|
||||
|
||||
readonly weakerSectionOptions = [
|
||||
{ value: 'BPL', label: 'BPL (Below Poverty Line)', icon: 'volunteer_activism' },
|
||||
{ value: 'SC_ST', label: 'SC / ST Category', icon: 'groups' },
|
||||
{ value: 'MINORITY', label: 'Minority Community', icon: 'diversity_3' },
|
||||
{ value: 'SHG', label: 'Self Help Group Member', icon: 'handshake' },
|
||||
{ value: 'PMJDY', label: 'PMJDY Beneficiary', icon: 'savings' },
|
||||
{ value: 'NONE', label: 'None / General', icon: 'person_outline' }
|
||||
];
|
||||
|
||||
// ── Minor Account ──────────────────────────────────────────────────────
|
||||
guardianClientId: number | null = null;
|
||||
guardianName = '';
|
||||
guardianCif = '';
|
||||
guardianRelationship = '';
|
||||
minorDob: Date | null = null;
|
||||
|
||||
readonly guardianRelationshipOptions = [
|
||||
'Father',
|
||||
'Mother',
|
||||
'Legal Guardian',
|
||||
'Court Appointed Guardian'
|
||||
];
|
||||
|
||||
constructor() {
|
||||
this.createCurrentAccountDetailsForm();
|
||||
@@ -124,9 +175,23 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
ngOnInit() {
|
||||
this.maxDate = this.settingsService.businessDate;
|
||||
this.buildDependencies();
|
||||
if (this.currentAccountTemplate?.clientId) {
|
||||
this.clientsService.getClientData(String(this.currentAccountTemplate.clientId)).subscribe((client: any) => {
|
||||
|
||||
const clientId = this.currentAccountTemplate?.clientId;
|
||||
if (clientId) {
|
||||
this.primaryClientId = clientId;
|
||||
this.clientsService.getClientData(String(clientId)).subscribe((client: any) => {
|
||||
this.isNonIndividualClient = client?.legalForm?.id === 2;
|
||||
this.primaryClientName = client?.displayName ?? client?.fullname ?? '';
|
||||
this.primaryClientCif = client?.cifNumber ?? client?.cifNo ?? '';
|
||||
if (client?.dateOfBirth) {
|
||||
const dob = this.parseClientDob(client.dateOfBirth);
|
||||
if (dob) {
|
||||
this.clientDob = dob;
|
||||
this.clientAge = this.calculateAge(dob);
|
||||
this.clientGender = client.gender?.name?.toLowerCase() ?? null;
|
||||
this.autoDetectAccountStatus();
|
||||
}
|
||||
}
|
||||
this.cdr.detectChanges();
|
||||
});
|
||||
}
|
||||
@@ -149,9 +214,6 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates current account details form.
|
||||
*/
|
||||
createCurrentAccountDetailsForm() {
|
||||
this.currentAccountDetailsForm = this.formBuilder.group({
|
||||
productId: [
|
||||
@@ -166,22 +228,19 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
externalId: [''],
|
||||
balanceSwapOption: [false],
|
||||
msme: [false],
|
||||
autoDebitFacility: [false]
|
||||
autoDebitFacility: [false],
|
||||
establishmentDate: [''],
|
||||
startOperationDate: ['']
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches current account product template on productId value changes
|
||||
*/
|
||||
buildDependencies() {
|
||||
const entityId = this.currentAccountTemplate.groupId || this.currentAccountTemplate.clientId;
|
||||
this.currentAccountDetailsForm.get('productId').valueChanges.subscribe((productId: string) => {
|
||||
this.currentAccountsService
|
||||
.getCurrentAccountTemplate(entityId, productId, this.currentAccountTemplate.groupId ? true : false)
|
||||
.subscribe((response: any) => {
|
||||
// Ensure currency is included in the product template
|
||||
if (!response.currency) {
|
||||
// Try to get currency from the selected product
|
||||
const selectedProduct = this.currentAccountTemplate.productOptions?.find(
|
||||
(product: any) => product.id == productId
|
||||
);
|
||||
@@ -192,10 +251,13 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
this.productTemplate = response;
|
||||
this.accountTypeOptions = this.extractOptions(response.accountTypeOptions, response.accountType);
|
||||
this.customerSegmentOptions = this.extractOptions(response.customerSegmentOptions, response.customerSegment);
|
||||
this.selectedAccountType = response.accountType ?? null;
|
||||
this.selectedCustomerSegment = response.customerSegment ?? null;
|
||||
this.currentAccountProductTemplate.emit(response);
|
||||
this.fieldOfficerData = response.fieldOfficerOptions;
|
||||
this.currentAccountProductSelected = true;
|
||||
// Pre-populate toggles from product defaults (user can override)
|
||||
this.currentAccountDetailsForm.patchValue({
|
||||
balanceSwapOption: !!response.balanceSwapOption,
|
||||
msme: !!response.msme,
|
||||
@@ -212,13 +274,15 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats template dates into the current CBS date format.
|
||||
*/
|
||||
formatTemplateDate(value: any): string {
|
||||
if (!value) {
|
||||
return '';
|
||||
private extractOptions(options: any[], fallback?: string): string[] {
|
||||
if (Array.isArray(options) && options.length > 0) {
|
||||
return options.map((o: any) => o.value ?? o.name ?? o);
|
||||
}
|
||||
return fallback ? [fallback] : [];
|
||||
}
|
||||
|
||||
formatTemplateDate(value: any): string {
|
||||
if (!value) return '';
|
||||
let dateValue: Date | null = null;
|
||||
if (value instanceof Date) {
|
||||
dateValue = value;
|
||||
@@ -233,15 +297,125 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
return this.dateUtils.formatDate(dateValue, 'M/d/yyyy') || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current account form value.
|
||||
*/
|
||||
// ── Client DOB helpers ─────────────────────────────────────────────────
|
||||
private parseClientDob(dob: any): Date | null {
|
||||
if (!dob) return null;
|
||||
if (Array.isArray(dob) && dob.length >= 3) return new Date(dob[0], dob[1] - 1, dob[2]);
|
||||
const d = new Date(dob);
|
||||
return isNaN(d.getTime()) ? null : d;
|
||||
}
|
||||
|
||||
private calculateAge(dob: Date): number {
|
||||
const today = this.settingsService.businessDate ?? new Date();
|
||||
let age = today.getFullYear() - dob.getFullYear();
|
||||
const m = today.getMonth() - dob.getMonth();
|
||||
if (m < 0 || (m === 0 && today.getDate() < dob.getDate())) age--;
|
||||
return age;
|
||||
}
|
||||
|
||||
private autoDetectAccountStatus(): void {
|
||||
if (this.clientAge === null) return;
|
||||
if (this.clientAge < 18) {
|
||||
this.selectedAccountStatus = 'MINOR';
|
||||
this.minorDob = this.clientDob;
|
||||
} else if (this.clientAge >= 60) {
|
||||
this.selectedAccountStatus = 'SENIOR_CITIZEN';
|
||||
} else if (this.clientGender === 'female') {
|
||||
this.selectedAccountStatus = 'INDIVIDUAL_FEMALE';
|
||||
} else {
|
||||
this.selectedAccountStatus = 'INDIVIDUAL_MALE';
|
||||
}
|
||||
}
|
||||
|
||||
isTileDisabled(value: string): boolean {
|
||||
if (value === 'MINOR') return this.clientAge === null || this.clientAge >= 18;
|
||||
if (value === 'SENIOR_CITIZEN') return this.clientAge === null || this.clientAge < 60;
|
||||
return false;
|
||||
}
|
||||
|
||||
getTileTooltip(value: string): string {
|
||||
if (value === 'MINOR' && this.clientAge !== null && this.clientAge >= 18)
|
||||
return `Age ${this.clientAge} yrs — Minor only allowed below 18 years`;
|
||||
if (value === 'SENIOR_CITIZEN' && this.clientAge !== null && this.clientAge < 60)
|
||||
return `Age ${this.clientAge} yrs — Senior Citizen only allowed at 60+ years`;
|
||||
if (value === 'MINOR' && this.clientAge === null) return 'DOB not available — cannot verify age';
|
||||
if (value === 'SENIOR_CITIZEN' && this.clientAge === null) return 'DOB not available — cannot verify age';
|
||||
return '';
|
||||
}
|
||||
|
||||
// ── Introducer ─────────────────────────────────────────────────────────
|
||||
onIntroducerChange(event: { clientId: number; displayName: string; cifNumber?: string } | null): void {
|
||||
this.introducerId = event?.clientId ?? null;
|
||||
this.introducerName = event?.displayName ?? null;
|
||||
this.introducerCif = event?.cifNumber ?? null;
|
||||
}
|
||||
|
||||
onGuardianChange(event: { clientId: number; displayName: string; cifNumber?: string } | null): void {
|
||||
this.guardianClientId = event?.clientId ?? null;
|
||||
this.guardianName = event?.displayName ?? '';
|
||||
this.guardianCif = event?.cifNumber ?? '';
|
||||
}
|
||||
|
||||
// ── Joint Account (Status of Account) ─────────────────────────────────
|
||||
openAddJointHolderDialog(): void {
|
||||
const ref = this.dialog.open(AddRelatedClientDialogComponent, {
|
||||
width: '500px',
|
||||
panelClass: 'arc-dialog-panel',
|
||||
disableClose: true
|
||||
});
|
||||
ref.afterClosed().subscribe((result) => {
|
||||
if (result) {
|
||||
const duplicate = this.jointHolders.some((h) => h.clientCif && h.clientCif === result.clientCif);
|
||||
if (duplicate) {
|
||||
alert(`Account holder with CIF ${result.clientCif} is already added.`);
|
||||
return;
|
||||
}
|
||||
this.jointHolders = [
|
||||
...this.jointHolders,
|
||||
{ ...result, isMandatory: false }];
|
||||
this.autoSetModeOfOperation();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
removeJointHolder(index: number): void {
|
||||
this.jointHolders = this.jointHolders.filter((_, i) => i !== index);
|
||||
this.autoSetModeOfOperation();
|
||||
}
|
||||
|
||||
toggleJointHolderMandatory(holder: any): void {
|
||||
holder.isMandatory = !holder.isMandatory;
|
||||
this.autoSetModeOfOperation();
|
||||
}
|
||||
|
||||
autoSetModeOfOperation(): void {
|
||||
const mandatory = this.jointHolders.filter((h) => h.isMandatory).length;
|
||||
if (mandatory === 0) this.modeOfOperation = 'EITHER_OR_SURVIVOR';
|
||||
else if (mandatory === 1) this.modeOfOperation = 'FORMER_OR_SURVIVOR';
|
||||
else this.modeOfOperation = 'JOINTLY';
|
||||
}
|
||||
|
||||
get totalJointSharePercentage(): number {
|
||||
return (this.primaryHolderShare || 0) + this.jointHolders.reduce((sum, h) => sum + (h.sharePercentage || 0), 0);
|
||||
}
|
||||
|
||||
get mandatoryJointCount(): number {
|
||||
return this.jointHolders.filter((h) => h.isMandatory).length;
|
||||
}
|
||||
|
||||
get selectedModeLabel(): string {
|
||||
return this.modeOfOperationOptions.find((o) => o.value === this.modeOfOperation)?.sublabel ?? '';
|
||||
}
|
||||
|
||||
get majorityDate(): string {
|
||||
const dob = this.minorDob ?? this.clientDob;
|
||||
if (!dob) return '';
|
||||
const d = new Date(dob);
|
||||
d.setFullYear(d.getFullYear() + 18);
|
||||
return this.dateUtils.formatDate(d, 'M/d/yyyy') || '';
|
||||
}
|
||||
|
||||
// ── Non-Individual (existing) helpers ──────────────────────────────────
|
||||
openAddRelatedClientDialog(): void {
|
||||
const ref = this.dialog.open(AddRelatedClientDialogComponent, {
|
||||
width: '500px',
|
||||
@@ -273,16 +447,11 @@ export class CurrentAccountDetailsStepComponent implements OnInit {
|
||||
this.autoSetSignatoryRights();
|
||||
}
|
||||
|
||||
/** Auto-compute Mode of Operation based on mandatory count */
|
||||
autoSetSignatoryRights(): void {
|
||||
const mandatory = this.relatedClients.filter((c) => c.isMandatory).length;
|
||||
if (mandatory === 0) {
|
||||
this.signatoryRights = 'ANYONE';
|
||||
} else if (mandatory === 1) {
|
||||
this.signatoryRights = 'ONE_MANDATORY';
|
||||
} else {
|
||||
this.signatoryRights = 'TWO_MANDATORY';
|
||||
}
|
||||
if (mandatory === 0) this.signatoryRights = 'ANYONE';
|
||||
else if (mandatory === 1) this.signatoryRights = 'ONE_MANDATORY';
|
||||
else this.signatoryRights = 'TWO_MANDATORY';
|
||||
}
|
||||
|
||||
get totalSharePercentage(): number {
|
||||
@@ -305,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) => ({
|
||||
|
||||
+268
-1
@@ -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>
|
||||
|
||||
+88
-5
@@ -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;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,11 @@ export class CurrentAccountsService {
|
||||
return this.http.get(`/currentaccounts/${accountId}`, { params: httpParams });
|
||||
}
|
||||
|
||||
getClientCurrentAccounts(clientId: string): Observable<any> {
|
||||
const httpParams = new HttpParams().set('clientId', clientId);
|
||||
return this.http.get('/currentaccounts', { params: httpParams });
|
||||
}
|
||||
|
||||
/**
|
||||
* @param accountId Current Account Id of account to get data for.
|
||||
* @returns {Observable<any>} Current account and template.
|
||||
|
||||
Reference in New Issue
Block a user