KYC management: stage-wise notices, pagination, RD base chart
This commit is contained in:
+211
@@ -0,0 +1,211 @@
|
||||
<!--
|
||||
Copyright since 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public
|
||||
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
-->
|
||||
|
||||
<section class="identity-check" [class.identity-check--blocking]="status === 'matched' || status === 'conflict'">
|
||||
<header class="identity-check__header">
|
||||
<mat-icon class="identity-check__icon">fingerprint</mat-icon>
|
||||
<div>
|
||||
<h3 class="identity-check__title">Existing customer check</h3>
|
||||
<p class="identity-check__hint">
|
||||
@if (isEntity) {
|
||||
Enter the company's GSTIN or PAN. If either is already on file in any branch, it is the same customer and a
|
||||
new one is not created.
|
||||
} @else {
|
||||
Enter PAN or Aadhaar. If either is already on file in any branch, it is the same customer and a new one is not
|
||||
created. Nothing found? What you enter here is filled into the KYC step for you.
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@if (form) {
|
||||
<form [formGroup]="form" class="identity-check__fields">
|
||||
@if (isEntity) {
|
||||
<mat-form-field appearance="outline" class="identity-check__field">
|
||||
<mat-label>GSTIN</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="gstin"
|
||||
class="identity-check__upper"
|
||||
maxlength="15"
|
||||
mifosxRestrictInput="gstin"
|
||||
[errorStateMatcher]="errorMatcher"
|
||||
placeholder="e.g. 22AAAAA0000A1Z5"
|
||||
(input)="capitalise('gstin', $event)"
|
||||
/>
|
||||
@if (form.get('gstin')?.hasError('pattern')) {
|
||||
<mat-error>Invalid GSTIN. It has 15 characters, like 22AAAAA0000A1Z5</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
|
||||
<mat-form-field appearance="outline" class="identity-check__field">
|
||||
<mat-label>{{ isEntity ? 'Company PAN' : 'PAN' }}</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="pan"
|
||||
class="identity-check__upper"
|
||||
maxlength="10"
|
||||
mifosxRestrictInput="pan"
|
||||
[errorStateMatcher]="errorMatcher"
|
||||
placeholder="e.g. ABCDE1234F"
|
||||
(input)="capitalise('pan', $event)"
|
||||
/>
|
||||
@if (form.get('pan')?.hasError('pattern')) {
|
||||
<mat-error>Invalid PAN. Use 5 letters, 4 digits, 1 letter, like ABCDE1234F</mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
@if (!isEntity) {
|
||||
<mat-form-field appearance="outline" class="identity-check__field">
|
||||
<mat-label>Aadhaar</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="aadhaar"
|
||||
maxlength="12"
|
||||
inputmode="numeric"
|
||||
mifosxRestrictInput="digits"
|
||||
[errorStateMatcher]="errorMatcher"
|
||||
placeholder="12 digits"
|
||||
/>
|
||||
@if (form.get('aadhaar')?.hasError('pattern')) {
|
||||
<mat-error>Invalid Aadhaar. It must be exactly 12 digits</mat-error>
|
||||
} @else {
|
||||
<mat-hint>Only a fingerprint of this number is sent, never the number</mat-hint>
|
||||
}
|
||||
</mat-form-field>
|
||||
}
|
||||
</form>
|
||||
}
|
||||
|
||||
@switch (status) {
|
||||
@case ('checking') {
|
||||
<div class="identity-check__status identity-check__status--info">
|
||||
<mat-progress-spinner mode="indeterminate" diameter="18"></mat-progress-spinner>
|
||||
Checking all branches…
|
||||
</div>
|
||||
}
|
||||
@case ('not-found') {
|
||||
<div class="identity-check__status identity-check__status--ok">
|
||||
<mat-icon>check_circle</mat-icon>
|
||||
<span>
|
||||
No existing customer found. You can continue; these details will be filled into the KYC step so you do not
|
||||
type them again.
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
@case ('error') {
|
||||
<div class="identity-check__status identity-check__status--warn">
|
||||
<mat-icon>warning</mat-icon>
|
||||
<span>
|
||||
Could not check right now. You can continue; the PAN, Aadhaar and GSTIN are checked again when the KYC is
|
||||
saved.
|
||||
</span>
|
||||
<button mat-button type="button" (click)="recheck()">Check again</button>
|
||||
</div>
|
||||
}
|
||||
@case ('conflict') {
|
||||
<div class="identity-check__status identity-check__status--error">
|
||||
<mat-icon>report</mat-icon>
|
||||
<span>
|
||||
These details belong to <strong>different customers</strong>. Check what was typed. If they are correct, ask a
|
||||
manager to review before continuing.
|
||||
</span>
|
||||
</div>
|
||||
@for (m of matches; track m.clientId) {
|
||||
<div class="identity-check__card">
|
||||
<strong>{{ m.displayName }}</strong>
|
||||
<span class="identity-check__meta">CIF {{ m.cifNumber }} · {{ m.officeName }}</span>
|
||||
<span class="identity-check__chips">
|
||||
@for (by of m.matchedBy; track by) {
|
||||
<span class="identity-check__chip">{{ matchedByLabel(by) }} matches</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@case ('matched') {
|
||||
@if (match; as m) {
|
||||
<div class="identity-check__status identity-check__status--error">
|
||||
<mat-icon>person_search</mat-icon>
|
||||
<span> This is an <strong>existing customer</strong>. A new client is not created for the same person. </span>
|
||||
</div>
|
||||
<div class="identity-check__card">
|
||||
<div class="identity-check__card-head">
|
||||
<strong>{{ m.displayName }}</strong>
|
||||
<span class="identity-check__chips">
|
||||
@for (by of m.matchedBy; track by) {
|
||||
<span class="identity-check__chip">{{ matchedByLabel(by) }} matches</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
<dl class="identity-check__facts">
|
||||
<div>
|
||||
<dt>CIF</dt>
|
||||
<dd>{{ m.cifNumber }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Home branch</dt>
|
||||
<dd>{{ m.officeName }}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>Type</dt>
|
||||
<dd>{{ legalFormLabel(m) }}</dd>
|
||||
</div>
|
||||
@if (m.panMasked) {
|
||||
<div>
|
||||
<dt>PAN</dt>
|
||||
<dd>{{ m.panMasked }}</dd>
|
||||
</div>
|
||||
}
|
||||
@if (m.aadhaarMasked) {
|
||||
<div>
|
||||
<dt>Aadhaar</dt>
|
||||
<dd>{{ m.aadhaarMasked }}</dd>
|
||||
</div>
|
||||
}
|
||||
@if (m.gstinMasked) {
|
||||
<div>
|
||||
<dt>GSTIN</dt>
|
||||
<dd>{{ m.gstinMasked }}</dd>
|
||||
</div>
|
||||
}
|
||||
</dl>
|
||||
|
||||
@if (m.visibleToCaller) {
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="button"
|
||||
class="identity-check__action"
|
||||
[routerLink]="['/clients', m.clientId, 'general']"
|
||||
>
|
||||
Open this customer
|
||||
</button>
|
||||
} @else {
|
||||
<p class="identity-check__note">
|
||||
This customer is registered at <strong>{{ m.officeName }}</strong
|
||||
>. They stay a single customer (one CIF). Open their page, then choose which account to open for them at
|
||||
this branch. They are listed under this branch once an account is opened here.
|
||||
</p>
|
||||
<button
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
type="button"
|
||||
class="identity-check__action"
|
||||
[disabled]="linking"
|
||||
(click)="openAccountHere(m)"
|
||||
>
|
||||
{{ linking ? 'Please wait…' : 'Open account for this customer' }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
}
|
||||
</section>
|
||||
Reference in New Issue
Block a user