feat(clients): require Mother + Father/Caretaker as family members before activation
- Add hasMother/hasFather/hasCaretaker/familyRelationshipRulesMet to ClientFamilyMembersStepComponent, matched against the RELATIONSHIP code value label. - Show two independent inline error banners (never merged into one message) when Mother, or both Father and Caretaker, are missing. - Gate "Save & Next" and final Submit on this rule in both the create and edit client flows — the edit flow previously treated the Family tab as unconditionally optional. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+16
@@ -62,6 +62,22 @@
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Mother requirement — shown independently of the Father/Caretaker check below -->
|
||||
@if (!nomineeOnly && clientFamilyMembers.length > 0 && !hasMother) {
|
||||
<div class="fm-step__empty fm-step__empty--required">
|
||||
<mat-icon class="fm-step__empty-icon">error_outline</mat-icon>
|
||||
<span class="fm-step__empty-required">Mother is required.</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Father-or-Caretaker requirement — shown independently of the Mother check above -->
|
||||
@if (!nomineeOnly && clientFamilyMembers.length > 0 && !hasFather && !hasCaretaker) {
|
||||
<div class="fm-step__empty fm-step__empty--required">
|
||||
<mat-icon class="fm-step__empty-icon">error_outline</mat-icon>
|
||||
<span class="fm-step__empty-required">Either Father or a Caretaker is required.</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
<!-- Spouse hint for married clients -->
|
||||
@if (!nomineeOnly && isMarried && !hasSpouse) {
|
||||
<div class="fm-spouse-hint">
|
||||
|
||||
+27
@@ -223,6 +223,33 @@ export class ClientFamilyMembersStepComponent implements OnInit {
|
||||
return this.clientFamilyMembers.length > 0;
|
||||
}
|
||||
|
||||
/** True if a family member with the given relationship (case-insensitive) has been added */
|
||||
private hasRelationship(name: string): boolean {
|
||||
const target = name.toLowerCase();
|
||||
return this.clientFamilyMembers.some((m: any) => {
|
||||
const resolved = this.getRelName(m.relationshipId ?? m.relationship).toLowerCase();
|
||||
if (resolved === target) return true;
|
||||
return typeof m.relationship === 'string' && m.relationship.toLowerCase() === target;
|
||||
});
|
||||
}
|
||||
|
||||
get hasMother(): boolean {
|
||||
return this.hasRelationship('mother');
|
||||
}
|
||||
|
||||
get hasFather(): boolean {
|
||||
return this.hasRelationship('father');
|
||||
}
|
||||
|
||||
get hasCaretaker(): boolean {
|
||||
return this.hasRelationship('caretaker');
|
||||
}
|
||||
|
||||
/** Mother is always required; Father is required unless a Caretaker has been added instead. */
|
||||
get familyRelationshipRulesMet(): boolean {
|
||||
return this.hasMother && (this.hasFather || this.hasCaretaker);
|
||||
}
|
||||
|
||||
/** Check if client's marital status is "Married" */
|
||||
get isMarried(): boolean {
|
||||
if (!this.maritalStatusId || !this.maritalStatusOptions?.length) return false;
|
||||
|
||||
@@ -238,8 +238,8 @@ export class CreateClientComponent {
|
||||
return this.isAddressStepValid();
|
||||
}
|
||||
if (idx === 3) {
|
||||
// Family tab — relations are optional, always allow.
|
||||
return true;
|
||||
// Family tab — Mother is required, and either Father or a Caretaker.
|
||||
return !this.clientFamilyMembersStep || this.clientFamilyMembersStep.familyRelationshipRulesMet;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@@ -273,6 +273,11 @@ export class CreateClientComponent {
|
||||
return `Please fill/correct: ${labels.join(', ')}.`;
|
||||
}
|
||||
}
|
||||
if (idx === 3 && this.legalFormType === 1 && this.clientFamilyMembersStep) {
|
||||
const step = this.clientFamilyMembersStep;
|
||||
if (!step.hasMother) return 'Mother is required as a family member.';
|
||||
if (!step.hasFather && !step.hasCaretaker) return 'Either Father or a Caretaker is required as a family member.';
|
||||
}
|
||||
return 'Please fill all mandatory fields on this tab to continue.';
|
||||
}
|
||||
|
||||
@@ -569,6 +574,21 @@ export class CreateClientComponent {
|
||||
this.selectedTabIndex = 3;
|
||||
return;
|
||||
}
|
||||
// Validate: Mother required, and either Father or a Caretaker (Individual clients)
|
||||
if (
|
||||
this.legalFormType === 1 &&
|
||||
this.clientFamilyMembersStep &&
|
||||
!this.clientFamilyMembersStep.familyRelationshipRulesMet
|
||||
) {
|
||||
const step = this.clientFamilyMembersStep;
|
||||
if (!step.hasMother) {
|
||||
this.validationError = 'Mother is required as a family member.';
|
||||
} else {
|
||||
this.validationError = 'Either Father or a Caretaker is required as a family member.';
|
||||
}
|
||||
this.selectedTabIndex = 3;
|
||||
return;
|
||||
}
|
||||
this.validationError = '';
|
||||
|
||||
if (this.createdClientId) {
|
||||
|
||||
@@ -287,14 +287,20 @@ export class EditClientComponent {
|
||||
if (this.legalFormType === 2) {
|
||||
if (idx === 2) return true; // Scheme & Sector — opt-in
|
||||
if (idx === 3) return this.isAddressStepValid();
|
||||
if (idx === 4) return true; // Family — optional
|
||||
if (idx === 4) return true; // Family — not applicable to non-individual entities
|
||||
} else {
|
||||
if (idx === 2) return this.isAddressStepValid();
|
||||
if (idx === 3) return true; // Family — optional
|
||||
if (idx === 3) return this.isFamilyStepValid(); // Mother required, plus Father or a Caretaker
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Mother is required, and either Father or a Caretaker, for individual clients. */
|
||||
private isFamilyStepValid(): boolean {
|
||||
const step = this.clientFamilyMembersStep;
|
||||
return !step || step.familyRelationshipRulesMet;
|
||||
}
|
||||
|
||||
private isAddressStepValid(): boolean {
|
||||
const step = this.clientIndiaAddressStep;
|
||||
if (!step) return true;
|
||||
@@ -318,6 +324,12 @@ export class EditClientComponent {
|
||||
return `Please fill/correct: ${labels.join(', ')}.`;
|
||||
}
|
||||
}
|
||||
const familyTabIndex = this.legalFormType === 2 ? 4 : 3;
|
||||
if (this.selectedTabIndex === familyTabIndex && this.legalFormType !== 2 && this.clientFamilyMembersStep) {
|
||||
const step = this.clientFamilyMembersStep;
|
||||
if (!step.hasMother) return 'Mother is required as a family member.';
|
||||
if (!step.hasFather && !step.hasCaretaker) return 'Either Father or a Caretaker is required as a family member.';
|
||||
}
|
||||
return 'Please fill all mandatory fields on this tab to continue.';
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user