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>
|
</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 -->
|
<!-- Spouse hint for married clients -->
|
||||||
@if (!nomineeOnly && isMarried && !hasSpouse) {
|
@if (!nomineeOnly && isMarried && !hasSpouse) {
|
||||||
<div class="fm-spouse-hint">
|
<div class="fm-spouse-hint">
|
||||||
|
|||||||
+27
@@ -223,6 +223,33 @@ export class ClientFamilyMembersStepComponent implements OnInit {
|
|||||||
return this.clientFamilyMembers.length > 0;
|
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" */
|
/** Check if client's marital status is "Married" */
|
||||||
get isMarried(): boolean {
|
get isMarried(): boolean {
|
||||||
if (!this.maritalStatusId || !this.maritalStatusOptions?.length) return false;
|
if (!this.maritalStatusId || !this.maritalStatusOptions?.length) return false;
|
||||||
|
|||||||
@@ -238,8 +238,8 @@ export class CreateClientComponent {
|
|||||||
return this.isAddressStepValid();
|
return this.isAddressStepValid();
|
||||||
}
|
}
|
||||||
if (idx === 3) {
|
if (idx === 3) {
|
||||||
// Family tab — relations are optional, always allow.
|
// Family tab — Mother is required, and either Father or a Caretaker.
|
||||||
return true;
|
return !this.clientFamilyMembersStep || this.clientFamilyMembersStep.familyRelationshipRulesMet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -273,6 +273,11 @@ export class CreateClientComponent {
|
|||||||
return `Please fill/correct: ${labels.join(', ')}.`;
|
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.';
|
return 'Please fill all mandatory fields on this tab to continue.';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,6 +574,21 @@ export class CreateClientComponent {
|
|||||||
this.selectedTabIndex = 3;
|
this.selectedTabIndex = 3;
|
||||||
return;
|
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 = '';
|
this.validationError = '';
|
||||||
|
|
||||||
if (this.createdClientId) {
|
if (this.createdClientId) {
|
||||||
|
|||||||
@@ -287,14 +287,20 @@ export class EditClientComponent {
|
|||||||
if (this.legalFormType === 2) {
|
if (this.legalFormType === 2) {
|
||||||
if (idx === 2) return true; // Scheme & Sector — opt-in
|
if (idx === 2) return true; // Scheme & Sector — opt-in
|
||||||
if (idx === 3) return this.isAddressStepValid();
|
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 {
|
} else {
|
||||||
if (idx === 2) return this.isAddressStepValid();
|
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;
|
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 {
|
private isAddressStepValid(): boolean {
|
||||||
const step = this.clientIndiaAddressStep;
|
const step = this.clientIndiaAddressStep;
|
||||||
if (!step) return true;
|
if (!step) return true;
|
||||||
@@ -318,6 +324,12 @@ export class EditClientComponent {
|
|||||||
return `Please fill/correct: ${labels.join(', ')}.`;
|
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.';
|
return 'Please fill all mandatory fields on this tab to continue.';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user