-
-
- Financial & Classification
-
-
}
diff --git a/src/app/clients/client-stepper/client-general-step/client-general-step.component.scss b/src/app/clients/client-stepper/client-general-step/client-general-step.component.scss
index d00f4ee37..05affe65b 100644
--- a/src/app/clients/client-stepper/client-general-step/client-general-step.component.scss
+++ b/src/app/clients/client-stepper/client-general-step/client-general-step.component.scss
@@ -13,7 +13,7 @@ form {
.section-block {
margin-bottom: 24px;
padding-bottom: 16px;
- border-bottom: 1px solid rgba(0, 0, 0, 0.06);
+ border-bottom: 1px solid rgb(0 0 0 / 6%);
&:last-child {
border-bottom: none;
@@ -28,7 +28,7 @@ form {
font-size: 15px;
font-weight: 600;
color: #333;
- margin: 0 0 16px 0;
+ margin: 0 0 16px;
.section-icon {
color: var(--md-sys-color-primary, #1074b9);
@@ -235,7 +235,7 @@ form {
border-radius: 12px;
overflow: hidden;
background: #fff;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
+ box-shadow: 0 2px 8px rgb(0 0 0 / 4%);
}
.guardian-section__header {
@@ -268,7 +268,7 @@ form {
.guardian-section__sub {
font-size: 11px;
- color: rgba(255, 255, 255, 0.55);
+ color: rgb(255 255 255 / 55%);
}
.guardian-section__age-chips {
@@ -280,9 +280,9 @@ form {
.guardian-age-chip {
font-size: 11px;
font-weight: 500;
- color: rgba(255, 255, 255, 0.8);
+ color: rgb(255 255 255 / 80%);
padding: 3px 10px;
- background: rgba(255, 255, 255, 0.1);
+ background: rgb(255 255 255 / 10%);
border-radius: 10px;
strong {
@@ -408,7 +408,10 @@ form {
.guardian-cancel-link {
color: #94a3b8 !important;
margin-top: 8px;
- &:hover { color: #ef4444 !important; }
+
+ &:hover {
+ color: #ef4444 !important;
+ }
}
/* ═══ Guardian Row Table ═══ */
@@ -437,7 +440,10 @@ form {
align-items: center;
padding: 10px 12px;
transition: background 0.1s;
- &:hover { background: #f8fafc; }
+
+ &:hover {
+ background: #f8fafc;
+ }
}
.guardian-row__col {
@@ -445,12 +451,33 @@ form {
font-size: 13px;
color: #1e293b;
- &--photo { flex: 0 0 50px; }
- &--name { flex: 1; min-width: 0; }
- &--rel { flex: 0 0 120px; }
- &--cif { flex: 0 0 130px; }
- &--status { flex: 0 0 80px; }
- &--actions { flex: 0 0 110px; display: flex; gap: 2px; justify-content: flex-end; }
+ &--photo {
+ flex: 0 0 50px;
+ }
+
+ &--name {
+ flex: 1;
+ min-width: 0;
+ }
+
+ &--rel {
+ flex: 0 0 120px;
+ }
+
+ &--cif {
+ flex: 0 0 130px;
+ }
+
+ &--status {
+ flex: 0 0 80px;
+ }
+
+ &--actions {
+ flex: 0 0 110px;
+ display: flex;
+ gap: 2px;
+ justify-content: flex-end;
+ }
}
.guardian-row__avatar {
@@ -543,14 +570,22 @@ form {
color: #64748b;
}
- &:hover mat-icon { color: #1074b9; }
- &--delete:hover mat-icon { color: #ef4444; }
+ &:hover mat-icon {
+ color: #1074b9;
+ }
+
+ &--delete:hover mat-icon {
+ color: #ef4444;
+ }
}
.guardian-row__zoomable {
cursor: zoom-in;
transition: transform 0.15s;
- &:hover { transform: scale(1.05); }
+
+ &:hover {
+ transform: scale(1.05);
+ }
}
/* Expandable detail panel */
@@ -558,12 +593,19 @@ form {
border-top: 1px solid #e2e8f0;
background: #f8fafc;
padding: 16px 20px;
- animation: guardianSlideDown 0.2s ease-out;
+ animation: guardian-slide-down 0.2s ease-out;
}
-@keyframes guardianSlideDown {
- from { opacity: 0; max-height: 0; }
- to { opacity: 1; max-height: 500px; }
+@keyframes guardian-slide-down {
+ from {
+ opacity: 0;
+ max-height: 0;
+ }
+
+ to {
+ opacity: 1;
+ max-height: 500px;
+ }
}
.guardian-expand__grid {
@@ -638,12 +680,13 @@ form {
padding: 0 !important;
border-radius: 12px !important;
}
+
.mdc-dialog__surface {
border-radius: 12px !important;
}
}
-@media (max-width: 768px) {
+@media (width <= 768px) {
.guardian-section__header {
flex-direction: column;
align-items: flex-start;
@@ -665,7 +708,9 @@ form {
width: 100%;
}
- .guardian-row__header { display: none; }
+ .guardian-row__header {
+ display: none;
+ }
.guardian-row__data {
flex-wrap: wrap;
@@ -673,10 +718,23 @@ form {
}
.guardian-row__col {
- &--photo { flex: 0 0 40px; }
- &--name { flex: 1 1 200px; }
- &--rel, &--cif, &--status { flex: 0 0 auto; }
- &--actions { flex: 0 0 auto; }
+ &--photo {
+ flex: 0 0 40px;
+ }
+
+ &--name {
+ flex: 1 1 200px;
+ }
+
+ &--rel,
+ &--cif,
+ &--status {
+ flex: 0 0 auto;
+ }
+
+ &--actions {
+ flex: 0 0 auto;
+ }
}
.guardian-expand__grid {
@@ -738,7 +796,7 @@ form {
background: #fff;
border: 1px solid #e2e8f0;
border-radius: 10px;
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12);
+ box-shadow: 0 8px 24px rgb(0 0 0 / 12%);
max-height: 280px;
overflow-y: auto;
}
@@ -776,8 +834,13 @@ form {
transition: background 0.1s;
border-bottom: 1px solid #f1f5f9;
- &:last-child { border-bottom: none; }
- &:hover { background: #f0f7ff; }
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:hover {
+ background: #f0f7ff;
+ }
}
.guardian-result-item__avatar {
@@ -834,7 +897,7 @@ form {
border-radius: 12px;
overflow: hidden;
background: #fff;
- box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
+ box-shadow: 0 1px 4px rgb(0 0 0 / 6%);
}
.guardian-card__header {
@@ -881,7 +944,10 @@ form {
.guardian-card__remove {
color: #94a3b8 !important;
- &:hover { color: #ef4444 !important; }
+
+ &:hover {
+ color: #ef4444 !important;
+ }
}
.guardian-card__body {
@@ -898,8 +964,13 @@ form {
border-bottom: 1px solid #f1f5f9;
border-right: 1px solid #f1f5f9;
- &:nth-child(2n) { border-right: none; }
- &:nth-last-child(-n+2) { border-bottom: none; }
+ &:nth-child(2n) {
+ border-right: none;
+ }
+
+ &:nth-last-child(-n + 2) {
+ border-bottom: none;
+ }
}
.guardian-card__label {
@@ -945,7 +1016,7 @@ form {
height: 16px;
border-radius: 3px;
overflow: hidden;
- box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+ box-shadow: 0 0 0 1px rgb(0 0 0 / 10%);
flex-shrink: 0;
}
@@ -1030,7 +1101,7 @@ form {
width: 24px;
height: 24px;
border: none;
- background: rgba(255, 255, 255, 0.15);
+ background: rgb(255 255 255 / 15%);
border-radius: 4px;
color: #fff;
cursor: pointer;
@@ -1040,7 +1111,7 @@ form {
font-size: 12px;
&:hover {
- background: rgba(255, 255, 255, 0.25);
+ background: rgb(255 255 255 / 25%);
}
}
@@ -1068,10 +1139,22 @@ form {
color: #0f172a;
}
- .row-micro td { background: #ecfdf5; }
- .row-small td { background: #e0f2fe; }
- .row-medium td { background: #fffbeb; }
- .row-large td { background: #f8fafc; color: #94a3b8; }
+ .row-micro td {
+ background: #ecfdf5;
+ }
+
+ .row-small td {
+ background: #e0f2fe;
+ }
+
+ .row-medium td {
+ background: #fffbeb;
+ }
+
+ .row-large td {
+ background: #f8fafc;
+ color: #94a3b8;
+ }
}
.msme-dot {
@@ -1081,10 +1164,21 @@ form {
border-radius: 50%;
margin-right: 6px;
- &.green { background: #10b981; }
- &.blue { background: #0ea5e9; }
- &.amber { background: #f59e0b; }
- &.gray { background: #cbd5e1; }
+ &.green {
+ background: #10b981;
+ }
+
+ &.blue {
+ background: #0ea5e9;
+ }
+
+ &.amber {
+ background: #f59e0b;
+ }
+
+ &.gray {
+ background: #cbd5e1;
+ }
}
.msme-class-table-footer {
@@ -1201,6 +1295,7 @@ form {
.mdc-notched-outline__trailing {
border-color: #10b981 !important;
}
+
input:disabled {
color: #059669 !important;
-webkit-text-fill-color: #059669 !important;
@@ -1213,6 +1308,7 @@ form {
.mdc-notched-outline__trailing {
border-color: #0ea5e9 !important;
}
+
input:disabled {
color: #0284c7 !important;
-webkit-text-fill-color: #0284c7 !important;
@@ -1225,6 +1321,7 @@ form {
.mdc-notched-outline__trailing {
border-color: #f59e0b !important;
}
+
input:disabled {
color: #d97706 !important;
-webkit-text-fill-color: #d97706 !important;
@@ -1390,7 +1487,7 @@ form {
}
}
-@media (max-width: 768px) {
+@media (width <= 768px) {
.form-grid {
grid-template-columns: 1fr;
}
@@ -1495,18 +1592,68 @@ form {
border-bottom: 1px solid #f1f5f9;
transition: background 0.15s;
- &:last-child { border-bottom: none; }
- &:hover { background: #f8fafc; }
+ &:last-child {
+ border-bottom: none;
+ }
+
+ &:hover {
+ background: #f8fafc;
+ }
}
.sig-table__col {
- &--sno { flex: 0 0 32px; text-align: center; color: #94a3b8; font-size: 12px; }
- &--photo { flex: 0 0 40px; }
- &--name { flex: 1; font-size: 13px; display: flex; align-items: center; gap: 6px; }
- &--id { flex: 0 0 100px; font-size: 12px; color: #64748b; }
- &--pan { flex: 0 0 120px; font-size: 12px; color: #1e293b; display: flex; align-items: center; gap: 3px; }
- &--status { flex: 0 0 80px; }
- &--actions { flex: 0 0 80px; display: flex; gap: 2px; }
+ &--sno {
+ flex: 0 0 32px;
+ text-align: center;
+ color: #94a3b8;
+ font-size: 12px;
+ }
+
+ &--photo {
+ flex: 0 0 40px;
+ }
+
+ &--name {
+ flex: 1;
+ font-size: 13px;
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ }
+
+ &--id {
+ flex: 0 0 100px;
+ font-size: 12px;
+ color: #64748b;
+ }
+
+ &--pan {
+ flex: 0 0 120px;
+ font-size: 12px;
+ color: #1e293b;
+ display: flex;
+ align-items: center;
+ gap: 3px;
+ }
+
+ &--din {
+ flex: 0 0 140px;
+ font-size: 12px;
+ color: #1e293b;
+ display: flex;
+ align-items: center;
+ gap: 3px;
+ }
+
+ &--status {
+ flex: 0 0 80px;
+ }
+
+ &--actions {
+ flex: 0 0 80px;
+ display: flex;
+ gap: 2px;
+ }
}
.sig-table__avatar {
@@ -1521,11 +1668,21 @@ form {
font-size: 12px;
overflow: hidden;
- &.has-photo { padding: 0; }
- .avatar-photo { width: 100%; height: 100%; object-fit: cover; border-radius: 50%; }
+ &.has-photo {
+ padding: 0;
+ }
+
+ .avatar-photo {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ border-radius: 50%;
+ }
}
-.sig-inline-spinner { display: inline-block; }
+.sig-inline-spinner {
+ display: inline-block;
+}
.verify-tick-sm {
font-size: 14px !important;
@@ -1534,11 +1691,40 @@ form {
color: #22c55e;
}
+.verify-cross-sm {
+ font-size: 14px !important;
+ width: 14px !important;
+ height: 14px !important;
+ color: #f59e0b;
+}
+
+.din-verify-btn {
+ font-size: 11px !important;
+ padding: 2px 8px !important;
+ min-height: 24px !important;
+ line-height: 20px !important;
+ border-radius: 6px !important;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ color: #1074b9 !important;
+ border-color: #93c5fd !important;
+
+ .din-verify-icon {
+ font-size: 14px !important;
+ width: 14px !important;
+ height: 14px !important;
+ }
+}
+
.sig-status-chip {
font-size: 11px;
font-weight: 600;
color: #94a3b8;
- &.active { color: #22c55e; }
+
+ &.active {
+ color: #22c55e;
+ }
}
.sig-action-icon {
@@ -1546,7 +1732,10 @@ form {
width: 18px !important;
height: 18px !important;
color: #64748b;
- &.remove { color: #ef4444; }
+
+ &.remove {
+ color: #ef4444;
+ }
}
.sig-add-wrapper {
@@ -1561,11 +1750,13 @@ form {
overflow: visible !important;
max-height: none !important;
}
+
.mdc-dialog__surface {
border-radius: 12px !important;
overflow: visible !important;
max-height: none !important;
}
+
.mat-mdc-dialog-content {
max-height: none !important;
overflow: visible !important;
@@ -1625,7 +1816,7 @@ form {
&__sub {
font-size: 11px;
- color: rgba(255, 255, 255, 0.5);
+ color: rgb(255 255 255 / 50%);
margin: 2px 0 0;
}
}
diff --git a/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts b/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
index ab92a3241..a091246e0 100644
--- a/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
+++ b/src/app/clients/client-stepper/client-general-step/client-general-step.component.ts
@@ -7,7 +7,17 @@
*/
/** Angular Imports */
-import { Component, OnInit, OnDestroy, OnChanges, SimpleChanges, Input, Output, EventEmitter, inject } from '@angular/core';
+import {
+ Component,
+ OnInit,
+ OnDestroy,
+ OnChanges,
+ SimpleChanges,
+ Input,
+ Output,
+ EventEmitter,
+ inject
+} from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import {
@@ -40,6 +50,7 @@ import { STANDALONE_SHARED_IMPORTS } from 'app/standalone-shared.module';
import { DateFormatPipe } from '../../../pipes/date-format.pipe';
import { SanctionsVerifyDialogComponent } from './sanctions-verify-dialog.component';
import { DipVerifyDialogComponent } from './dip-verify-dialog.component';
+import { DinVerifyDialogComponent } from './din-verify-dialog.component';
/**
* Create Client Component
@@ -165,17 +176,149 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
alternateDipTimestamp: string | null = null;
/** Constitution Types Master with KYC field metadata */
constitutionTypesMaster = [
- { value: 'PRIVATE_LIMITED', label: 'Private Limited Company', icon: 'business', panLabel: 'PAN of Company', panHint: 'PAN mandatory. CIN from MCA.', regHint: 'Certificate of Incorporation No.', showCin: true, additionalField: 'Constitution as per Articles of Association', documents: 'Certificate of Incorporation, Memorandum & Articles of Association, PAN, Board Resolution', signatoryKyc: 'KYC of all Authorized Signatories (OVDs + PAN + Photo)', note: 'Board Resolution to specify authorized signatories' },
- { value: 'PUBLIC_LIMITED', label: 'Public Limited Company', icon: 'domain', panLabel: 'PAN of Company', panHint: 'PAN mandatory. CIN from MCA.', regHint: 'Certificate of Incorporation No.', showCin: true, additionalField: 'Constitution as per Articles of Association', documents: 'Certificate of Incorporation, Memorandum & Articles of Association, PAN, Board Resolution', signatoryKyc: 'KYC of all Authorized Signatories (OVDs + PAN + Photo)', note: 'Board Resolution to specify authorized signatories' },
- { value: 'LLP', label: 'Limited Liability Partnership (LLP)', icon: 'handshake', panLabel: 'PAN of LLP', panHint: 'PAN mandatory. LLPIN from MCA.', regHint: 'Certificate of Incorporation No.', showCin: true, additionalField: 'LLP Agreement', documents: 'Certificate of Incorporation, LLP Agreement, PAN, Designated Partners Resolution', signatoryKyc: 'KYC of all Designated Partners / Authorized Signatories', note: 'LLPIN from MCA required' },
- { value: 'PARTNERSHIP', label: 'Partnership Firm', icon: 'handshake', panLabel: 'PAN of Firm', panHint: 'PAN of Firm mandatory', regHint: 'Registration Certificate No. (if registered)', showCin: false, additionalField: 'Partners Names (linked client-wise)', documents: 'Partnership Deed, Registration Certificate (if registered), PAN of Firm', signatoryKyc: 'KYC of all Partners / Authorized Signatories', note: 'Registration optional but preferred' },
- { value: 'PROPRIETORSHIP', label: 'Proprietorship', icon: 'person', panLabel: 'PAN of Proprietor', panHint: 'PAN of Proprietor (no separate entity PAN needed)', regHint: 'GST / Shop License No.', showCin: false, additionalField: '', documents: 'GST Certificate / Shop License / Utility Bill, PAN of Proprietor', signatoryKyc: "Proprietor's individual KYC (same as individual requirements)", note: 'At least 2 proofs of business existence required. Proprietor name = Client name.' },
- { value: 'HUF', label: 'HUF (Hindu Undivided Family)', icon: 'family_restroom', panLabel: 'PAN of HUF', panHint: 'PAN of HUF mandatory', regHint: 'HUF Declaration / Deed No.', showCin: false, additionalField: 'Karta Name', documents: 'HUF Declaration/Deed, PAN of HUF', signatoryKyc: 'KYC of Karta', note: '' },
- { value: 'TRUST', label: 'Trust', icon: 'verified_user', panLabel: 'PAN of Trust', panHint: 'PAN of Trust mandatory', regHint: 'Trust Deed / Registration No.', showCin: false, additionalField: 'Purpose of Trust', documents: 'Trust Deed, Registration Certificate, PAN of Trust', signatoryKyc: 'KYC of Trustees / Authorized Signatories', note: 'Foreign contribution rules apply if applicable' },
- { value: 'SOCIETY', label: 'Society', icon: 'groups', panLabel: 'PAN of Society', panHint: 'PAN of Society mandatory', regHint: 'Registration Certificate No.', showCin: false, additionalField: 'Managing Committee Details', documents: 'Registration Certificate, PAN of Society, Resolution authorizing signatories', signatoryKyc: 'KYC of Authorized Signatories', note: 'Governed by Societies Registration Act' },
- { value: 'ASSOCIATION', label: 'Association / Club', icon: 'diversity_3', panLabel: 'PAN', panHint: 'PAN mandatory', regHint: 'Registration Certificate No.', showCin: false, additionalField: 'Club Constitution Document', documents: 'Registration Certificate, PAN, Resolution authorizing signatories', signatoryKyc: 'KYC of Authorized Signatories', note: 'Committee approval needed for account' },
- { value: 'GOVT_PSU', label: 'Government Dept / PSU', icon: 'account_balance', panLabel: 'PAN (if applicable)', panHint: 'PAN if applicable', regHint: 'Govt. Notification / Order No.', showCin: false, additionalField: 'Gazette Notification Reference', documents: 'Relevant Government Notification / Order, PAN (if applicable)', signatoryKyc: 'Authorized Signatory KYC', note: 'Special KYC norms as per RBI circular' },
- { value: 'COOPERATIVE', label: 'Cooperative Society / Cooperative Bank', icon: 'hub', panLabel: 'PAN', panHint: 'PAN mandatory. RBI license if bank.', regHint: 'Registration Certificate No.', showCin: false, additionalField: 'Bye-laws of the Cooperative', documents: 'Registration Certificate, PAN, Resolution authorizing signatories', signatoryKyc: 'KYC of Authorized Signatories', note: 'Separate RBI licensing check for cooperative banks' }
+ {
+ value: 'PRIVATE_LIMITED',
+ label: 'Private Limited Company',
+ icon: 'business',
+ panLabel: 'PAN of Company',
+ panHint: 'PAN mandatory. CIN from MCA.',
+ regHint: 'Certificate of Incorporation No.',
+ showCin: true,
+ additionalField: 'Constitution as per Articles of Association',
+ documents: 'Certificate of Incorporation, Memorandum & Articles of Association, PAN, Board Resolution',
+ signatoryKyc: 'KYC of all Authorized Signatories (OVDs + PAN + Photo)',
+ note: 'Board Resolution to specify authorized signatories'
+ },
+ {
+ value: 'PUBLIC_LIMITED',
+ label: 'Public Limited Company',
+ icon: 'domain',
+ panLabel: 'PAN of Company',
+ panHint: 'PAN mandatory. CIN from MCA.',
+ regHint: 'Certificate of Incorporation No.',
+ showCin: true,
+ additionalField: 'Constitution as per Articles of Association',
+ documents: 'Certificate of Incorporation, Memorandum & Articles of Association, PAN, Board Resolution',
+ signatoryKyc: 'KYC of all Authorized Signatories (OVDs + PAN + Photo)',
+ note: 'Board Resolution to specify authorized signatories'
+ },
+ {
+ value: 'LLP',
+ label: 'Limited Liability Partnership (LLP)',
+ icon: 'handshake',
+ panLabel: 'PAN of LLP',
+ panHint: 'PAN mandatory. LLPIN from MCA.',
+ regHint: 'Certificate of Incorporation No.',
+ showCin: true,
+ additionalField: 'LLP Agreement',
+ documents: 'Certificate of Incorporation, LLP Agreement, PAN, Designated Partners Resolution',
+ signatoryKyc: 'KYC of all Designated Partners / Authorized Signatories',
+ note: 'LLPIN from MCA required'
+ },
+ {
+ value: 'PARTNERSHIP',
+ label: 'Partnership Firm',
+ icon: 'handshake',
+ panLabel: 'PAN of Firm',
+ panHint: 'PAN of Firm mandatory',
+ regHint: 'Registration Certificate No. (if registered)',
+ showCin: false,
+ additionalField: 'Partners Names (linked client-wise)',
+ documents: 'Partnership Deed, Registration Certificate (if registered), PAN of Firm',
+ signatoryKyc: 'KYC of all Partners / Authorized Signatories',
+ note: 'Registration optional but preferred'
+ },
+ {
+ value: 'PROPRIETORSHIP',
+ label: 'Proprietorship',
+ icon: 'person',
+ panLabel: 'PAN of Proprietor',
+ panHint: 'PAN of Proprietor (no separate entity PAN needed)',
+ regHint: 'GST / Shop License No.',
+ showCin: false,
+ additionalField: '',
+ documents: 'GST Certificate / Shop License / Utility Bill, PAN of Proprietor',
+ signatoryKyc: "Proprietor's individual KYC (same as individual requirements)",
+ note: 'At least 2 proofs of business existence required. Proprietor name = Client name.'
+ },
+ {
+ value: 'HUF',
+ label: 'HUF (Hindu Undivided Family)',
+ icon: 'family_restroom',
+ panLabel: 'PAN of HUF',
+ panHint: 'PAN of HUF mandatory',
+ regHint: 'HUF Declaration / Deed No.',
+ showCin: false,
+ additionalField: 'Karta Name',
+ documents: 'HUF Declaration/Deed, PAN of HUF',
+ signatoryKyc: 'KYC of Karta',
+ note: ''
+ },
+ {
+ value: 'TRUST',
+ label: 'Trust',
+ icon: 'verified_user',
+ panLabel: 'PAN of Trust',
+ panHint: 'PAN of Trust mandatory',
+ regHint: 'Trust Deed / Registration No.',
+ showCin: false,
+ additionalField: 'Purpose of Trust',
+ documents: 'Trust Deed, Registration Certificate, PAN of Trust',
+ signatoryKyc: 'KYC of Trustees / Authorized Signatories',
+ note: 'Foreign contribution rules apply if applicable'
+ },
+ {
+ value: 'SOCIETY',
+ label: 'Society',
+ icon: 'groups',
+ panLabel: 'PAN of Society',
+ panHint: 'PAN of Society mandatory',
+ regHint: 'Registration Certificate No.',
+ showCin: false,
+ additionalField: 'Managing Committee Details',
+ documents: 'Registration Certificate, PAN of Society, Resolution authorizing signatories',
+ signatoryKyc: 'KYC of Authorized Signatories',
+ note: 'Governed by Societies Registration Act'
+ },
+ {
+ value: 'ASSOCIATION',
+ label: 'Association / Club',
+ icon: 'diversity_3',
+ panLabel: 'PAN',
+ panHint: 'PAN mandatory',
+ regHint: 'Registration Certificate No.',
+ showCin: false,
+ additionalField: 'Club Constitution Document',
+ documents: 'Registration Certificate, PAN, Resolution authorizing signatories',
+ signatoryKyc: 'KYC of Authorized Signatories',
+ note: 'Committee approval needed for account'
+ },
+ {
+ value: 'GOVT_PSU',
+ label: 'Government Dept / PSU',
+ icon: 'account_balance',
+ panLabel: 'PAN (if applicable)',
+ panHint: 'PAN if applicable',
+ regHint: 'Govt. Notification / Order No.',
+ showCin: false,
+ additionalField: 'Gazette Notification Reference',
+ documents: 'Relevant Government Notification / Order, PAN (if applicable)',
+ signatoryKyc: 'Authorized Signatory KYC',
+ note: 'Special KYC norms as per RBI circular'
+ },
+ {
+ value: 'COOPERATIVE',
+ label: 'Cooperative Society / Cooperative Bank',
+ icon: 'hub',
+ panLabel: 'PAN',
+ panHint: 'PAN mandatory. RBI license if bank.',
+ regHint: 'Registration Certificate No.',
+ showCin: false,
+ additionalField: 'Bye-laws of the Cooperative',
+ documents: 'Registration Certificate, PAN, Resolution authorizing signatories',
+ signatoryKyc: 'KYC of Authorized Signatories',
+ note: 'Separate RBI licensing check for cooperative banks'
+ }
];
/** Currently selected constitution metadata */
@@ -205,18 +348,18 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
this.maxDate = this.settingsService.businessDate;
this.setOptions();
// Fetch marital status options from code values
- this.clientService.getCodeValuesByName('MaritalStatus').subscribe(options => {
+ this.clientService.getCodeValuesByName('MaritalStatus').subscribe((options) => {
this.maritalStatusOptions = options || [];
});
// Fetch all constitution options from code ID 17
- this.clientService.getCodeValuesById(17).subscribe(options => {
+ this.clientService.getCodeValuesById(17).subscribe((options) => {
if (options?.length) {
this.constitutionOptions = options;
// Sort master by value length descending so longer/more-specific keys match first
const sortedMaster = [...this.constitutionTypesMaster].sort((a, b) => b.value.length - a.value.length);
this.enrichedConstitutionOptions = options.map((opt: any) => {
const normalized = opt.name?.toUpperCase().replace(/[\s_-]+/g, '') || '';
- const master = sortedMaster.find(m => normalized.includes(m.value.replace(/_/g, '')));
+ const master = sortedMaster.find((m) => normalized.includes(m.value.replace(/_/g, '')));
return {
id: opt.id,
value: master?.value || opt.name,
@@ -263,7 +406,9 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
occupationId: data.occupation?.id || data.occupationId || '',
monthlyIncome: data.monthlyIncome || '',
annualTurnover: data.annualTurnover || '',
- submittedOnDate: data.timeline?.submittedOnDate ? new Date(data.timeline.submittedOnDate) : this.settingsService.businessDate
+ submittedOnDate: data.timeline?.submittedOnDate
+ ? new Date(data.timeline.submittedOnDate)
+ : this.settingsService.businessDate
});
// Patch name fields (already created by buildDependencies via legalFormId subscription)
@@ -323,19 +468,55 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
active: [false],
addSavings: [false],
accountNo: [''],
- genderId: ['', Validators.required],
+ genderId: [
+ '',
+ Validators.required
+ ],
maritalStatusId: [''],
- mobileNo: ['', [Validators.required, Validators.pattern(/^[6-9]\d{9}$/), Validators.maxLength(10)]],
- alternateMobileNo: ['', [Validators.pattern(/^[6-9]\d{9}$/), Validators.maxLength(10)]],
+ mobileNo: [
+ '',
+ [
+ Validators.required,
+ Validators.pattern(/^[6-9]\d{9}$/),
+ Validators.maxLength(10)
+ ]
+ ],
+ alternateMobileNo: [
+ '',
+ [
+ Validators.pattern(/^[6-9]\d{9}$/),
+ Validators.maxLength(10)
+ ]
+ ],
emailAddress: [
'',
- [Validators.required, Validators.email, Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/), Validators.maxLength(100)]
+ [
+ Validators.required,
+ Validators.email,
+ Validators.pattern(/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/),
+ Validators.maxLength(100)
+ ]
+ ],
+ dateOfBirth: [
+ '',
+ Validators.required
],
- dateOfBirth: ['', Validators.required],
occupationCategoryId: [''],
occupationId: [''],
- monthlyIncome: ['', [Validators.pattern(/^\d+(\.\d{1,2})?$/), Validators.min(0)]],
- annualTurnover: ['', [Validators.pattern(/^\d+(\.\d{1,2})?$/), Validators.min(0)]],
+ monthlyIncome: [
+ '',
+ [
+ Validators.pattern(/^\d+(\.\d{1,2})?$/),
+ Validators.min(0)
+ ]
+ ],
+ annualTurnover: [
+ '',
+ [
+ Validators.pattern(/^\d+(\.\d{1,2})?$/),
+ Validators.min(0)
+ ]
+ ],
submittedOnDate: [
this.settingsService.businessDate,
Validators.required
@@ -387,7 +568,13 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
Validators.maxLength(50)
])
);
- this.createClientForm.addControl('middlename', new UntypedFormControl('', [Validators.pattern(/^[A-Za-z][A-Za-z\s.'-]*$/), Validators.maxLength(50)]));
+ this.createClientForm.addControl(
+ 'middlename',
+ new UntypedFormControl('', [
+ Validators.pattern(/^[A-Za-z][A-Za-z\s.'-]*$/),
+ Validators.maxLength(50)
+ ])
+ );
this.createClientForm.addControl(
'lastname',
new UntypedFormControl('', [
@@ -417,7 +604,10 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
this.createClientForm.addControl(
'clientNonPersonDetails',
this.formBuilder.group({
- constitutionId: ['', Validators.required],
+ constitutionId: [
+ '',
+ Validators.required
+ ],
mainBusinessLineId: [''],
incorpNumber: [''],
authorizedSignatory: [''],
@@ -466,10 +656,19 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
this.isMinor = years < 10;
// Add/remove guardian form group based on minor status
if (this.isMinor && !wasMinor) {
- this.createClientForm.addControl('guardianDetails', this.formBuilder.group({
- guardianClientId: ['', Validators.required],
- guardianRelation: ['', Validators.required]
- }));
+ this.createClientForm.addControl(
+ 'guardianDetails',
+ this.formBuilder.group({
+ guardianClientId: [
+ '',
+ Validators.required
+ ],
+ guardianRelation: [
+ '',
+ Validators.required
+ ]
+ })
+ );
this.selectedGuardian = null;
this.guardianSearchText = '';
this.guardianSearchResults = [];
@@ -522,13 +721,15 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
});
// Reset DIP verification when mobile number changes
- this.createClientForm.get('mobileNo')
+ this.createClientForm
+ .get('mobileNo')
.valueChanges.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.mobileVerified = false;
});
- this.createClientForm.get('alternateMobileNo')
+ this.createClientForm
+ .get('alternateMobileNo')
.valueChanges.pipe(takeUntil(this.destroy$))
.subscribe(() => {
this.alternateMobileVerified = false;
@@ -699,7 +900,9 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
target.officeName = data.officeName || null;
target._loading = false;
},
- error: () => { target._loading = false; }
+ error: () => {
+ target._loading = false;
+ }
});
this.clientService.getClientKyc(cid).subscribe({
@@ -709,24 +912,36 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
target.aadhaarMasked = kyc?.aadhaarNumberMasked || '-';
target.aadhaarVerified = kyc?.aadhaarVerified || false;
},
- error: () => { target.panNumber = '-'; target.aadhaarMasked = '-'; }
+ error: () => {
+ target.panNumber = '-';
+ target.aadhaarMasked = '-';
+ }
});
this.clientService.getClientAccountData(cid).subscribe({
next: (accts: any) => {
const savings = accts?.savingsAccounts || [];
const active = savings.find((a: any) => a.status?.active) || savings[0];
- target.accountType = active ? (active.productName || 'Savings') : '-';
+ target.accountType = active ? active.productName || 'Savings' : '-';
target.accountNo = active?.accountNo || '-';
},
- error: () => { target.accountType = '-'; target.accountNo = '-'; }
+ error: () => {
+ target.accountType = '-';
+ target.accountNo = '-';
+ }
});
this.clientService.getClientAddressData(cid).subscribe({
next: (addresses: any[]) => {
if (addresses?.length) {
const addr = addresses[0];
- const parts = [addr.addressLine1, addr.townVillage, addr.city, addr.countyDistrict, addr.addressLine3].filter(Boolean);
+ const parts = [
+ addr.addressLine1,
+ addr.townVillage,
+ addr.city,
+ addr.countyDistrict,
+ addr.addressLine3
+ ].filter(Boolean);
if (parts.length) {
target.fullAddress = parts.join(', ') + (addr.postalCode ? ' - ' + addr.postalCode : '');
}
@@ -748,8 +963,8 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
// Fetch signature image
this.clientService.getClientDocuments(cid).subscribe({
next: (docs: any[]) => {
- const sigDoc = docs?.find((d: any) =>
- d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature')
+ const sigDoc = docs?.find(
+ (d: any) => d.name?.toLowerCase().includes('signature') || d.description?.toLowerCase().includes('signature')
);
if (sigDoc) {
this.clientService.getClientSignatureImage(cid, sigDoc.id.toString()).subscribe({
@@ -800,19 +1015,29 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
onSignatorySearch(text: string): void {
this.signatorySearchText = text;
clearTimeout(this.signatorySearchTimer);
- if (!text || text.length < 2) { this.signatorySearchResults = []; return; }
+ if (!text || text.length < 2) {
+ this.signatorySearchResults = [];
+ return;
+ }
this.signatorySearching = true;
this.signatorySearchTimer = setTimeout(() => {
this.clientService.searchByText(text, 0, 10).subscribe({
- next: (data: any) => { this.signatorySearchResults = data?.content || []; this.signatorySearching = false; this.clientService.enrichSearchResults(this.signatorySearchResults); },
- error: () => { this.signatorySearchResults = []; this.signatorySearching = false; }
+ next: (data: any) => {
+ this.signatorySearchResults = data?.content || [];
+ this.signatorySearching = false;
+ this.clientService.enrichSearchResults(this.signatorySearchResults);
+ },
+ error: () => {
+ this.signatorySearchResults = [];
+ this.signatorySearching = false;
+ }
});
}, 400);
}
addSignatory(client: any): void {
// Prevent duplicates
- if (this.signatories.find(s => s.id === client.id)) {
+ if (this.signatories.find((s) => s.id === client.id)) {
this.signatorySearchResults = [];
this.signatorySearchText = '';
return;
@@ -824,6 +1049,49 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
this.syncSignatoryNames();
this.fetchClientFullDetails(client.id, sig);
+ this.openDinVerifyDialog(sig);
+ }
+
+ /** Open DIN verification dialog for a signatory */
+ openDinVerifyDialog(sig: any): void {
+ const cid = sig.id?.toString();
+ if (!cid) return;
+
+ const entityName = this.createClientForm.get('fullname')?.value || '';
+
+ const openDialog = (kycId: string, panFromKyc?: string) => {
+ const ref = this.dialog.open(DinVerifyDialogComponent, {
+ width: '620px',
+ maxWidth: '95vw',
+ disableClose: false,
+ autoFocus: true,
+ data: {
+ clientId: cid,
+ kycId,
+ signatoryName: sig.displayName || '',
+ cifNumber: sig.cifNumber || sig.accountNumber || cid,
+ panNumber: sig.panNumber || panFromKyc || '-',
+ entityName
+ }
+ });
+ ref.afterClosed().subscribe((result: any) => {
+ if (result && !result.skipped) {
+ sig.dinNumber = result.dinNumber || '';
+ sig.dinVerified = result.dinVerified || false;
+ sig.directorName = result.directorName || '';
+ sig.dinStatus = result.dinStatus || '';
+ sig.dinDesignation = result.dinDesignation || '';
+ sig.companyMatch = result.companyMatch ?? null;
+ sig.matchedCompany = result.matchedCompany || '';
+ }
+ });
+ };
+
+ // Fetch KYC ID first, then open dialog
+ this.clientService.getClientKyc(cid).subscribe({
+ next: (kyc: any) => openDialog(kyc?.id?.toString() || '', kyc?.panNumber),
+ error: () => openDialog('')
+ });
}
removeSignatoryAt(index: number): void {
@@ -842,26 +1110,26 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
}
private syncSignatoryNames(): void {
- const names = this.signatories.map(s => s.displayName).join(', ');
+ const names = this.signatories.map((s) => s.displayName).join(', ');
this.createClientForm.get('clientNonPersonDetails')?.patchValue({ authorizedSignatory: names });
}
/** Watch MSME turnover & investment for auto-classification */
/** Maps salutation name to gender. Returns gender option or null. */
private salutationGenderMap: Record
= {
- 'mr': 'male',
+ mr: 'male',
'mr.': 'male',
- 'shri': 'male',
- 'sri': 'male',
- 'master': 'male',
- 'mrs': 'female',
+ shri: 'male',
+ sri: 'male',
+ master: 'male',
+ mrs: 'female',
'mrs.': 'female',
- 'ms': 'female',
+ ms: 'female',
'ms.': 'female',
- 'miss': 'female',
- 'smt': 'female',
+ miss: 'female',
+ smt: 'female',
'smt.': 'female',
- 'kumari': 'female',
+ kumari: 'female'
// Dr, Er, CA, Adv etc. are gender-neutral — no auto-fill
};
@@ -875,39 +1143,41 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
const salCtrl = this.createClientForm.get('salutationId');
if (!salCtrl) return;
- this.salutationSub = salCtrl.valueChanges
- .pipe(takeUntil(this.destroy$))
- .subscribe((salutationId: any) => {
- if (!salutationId || !this.salutationOptions?.length || !this.genderOptions?.length) return;
+ this.salutationSub = salCtrl.valueChanges.pipe(takeUntil(this.destroy$)).subscribe((salutationId: any) => {
+ if (!salutationId || !this.salutationOptions?.length || !this.genderOptions?.length) return;
- // Find the salutation name from the selected ID
- const salutation = this.salutationOptions.find((s: any) => s.id === salutationId);
- if (!salutation) return;
+ // Find the salutation name from the selected ID
+ const salutation = this.salutationOptions.find((s: any) => s.id === salutationId);
+ if (!salutation) return;
- const salName = (salutation.name || '').toLowerCase().trim().replace(/\.$/, '');
- const mappedGender = this.salutationGenderMap[salName] || this.salutationGenderMap[salName + '.'];
- if (!mappedGender) return;
+ const salName = (salutation.name || '').toLowerCase().trim().replace(/\.$/, '');
+ const mappedGender = this.salutationGenderMap[salName] || this.salutationGenderMap[salName + '.'];
+ if (!mappedGender) return;
- // Find matching gender option by name
- const genderOption = this.genderOptions.find((g: any) =>
- (g.name || '').toLowerCase().trim() === mappedGender
- );
+ // Find matching gender option by name
+ const genderOption = this.genderOptions.find((g: any) => (g.name || '').toLowerCase().trim() === mappedGender);
- if (genderOption) {
- this.createClientForm.get('genderId')?.setValue(genderOption.id);
- }
- });
+ if (genderOption) {
+ this.createClientForm.get('genderId')?.setValue(genderOption.id);
+ }
+ });
}
/** Returns capitalized full name preview from first + middle + last */
get fullNamePreview(): string {
- const capitalize = (s: string) => s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '';
+ const capitalize = (s: string) => (s ? s.charAt(0).toUpperCase() + s.slice(1).toLowerCase() : '');
const salutationId = this.createClientForm?.get('salutationId')?.value;
const salutation = this.salutationOptions?.find((s: any) => s.id === salutationId)?.name || '';
const first = capitalize(this.createClientForm?.get('firstname')?.value || '');
const middle = capitalize(this.createClientForm?.get('middlename')?.value || '');
const last = capitalize(this.createClientForm?.get('lastname')?.value || '');
- const full = [first, middle, last].filter(Boolean).join(' ');
+ const full = [
+ first,
+ middle,
+ last
+ ]
+ .filter(Boolean)
+ .join(' ');
return salutation ? `${salutation} ${full}` : full;
}
@@ -985,7 +1255,7 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
getSelectedNationality(): any {
const val = this.createClientForm.get('nationalityId')?.value;
- return this.nationalityOptions.find(n => n.value === val) || null;
+ return this.nationalityOptions.find((n) => n.value === val) || null;
}
getSelectedBusiness(): any {
@@ -1111,14 +1381,17 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
}
const unsupportedFields = [
- 'guardianDetails', 'addressDetails', 'entityKycDetails'
+ 'guardianDetails',
+ 'addressDetails',
+ 'entityKycDetails'
];
- unsupportedFields.forEach(f => delete generalDetails[f]);
+ unsupportedFields.forEach((f) => delete generalDetails[f]);
// Format dateOfRegistration if present
if (generalDetails.clientNonPersonDetails?.dateOfRegistration instanceof Date) {
generalDetails.clientNonPersonDetails.dateOfRegistration = this.dateUtils.formatDate(
- generalDetails.clientNonPersonDetails.dateOfRegistration, dateFormat
+ generalDetails.clientNonPersonDetails.dateOfRegistration,
+ dateFormat
);
}
@@ -1198,14 +1471,18 @@ export class ClientGeneralStepComponent implements OnInit, OnDestroy, OnChanges
credit_card PAN
{{ data.panNumber || '-' }}
- @if (data.panVerified) { check_circle }
+ @if (data.panVerified) {
+ check_circle
+ }