Files
yara724api/src/claim-request-management/fanavaran-policy-selection.ts
s.hajizadeh 8d396762a2 fix(fanavaran): select latest active policy by end date
Why:
- Fanavaran policy inquiry response order is inconsistent, so selecting the last item can choose an old or expired policy.

Changes:
- Select the policy with the latest Jalali EndDate.
- Reject empty policy responses, expired latest policies, and latest policies without a valid PolicyId.
- Stop Fanavaran submission when PolicyId cannot be resolved.

Impact:
- Fanavaran submit now fails clearly instead of continuing with PolicyId: null.
2026-06-30 11:51:11 +03:30

96 lines
2.9 KiB
TypeScript

import { BadRequestException } from "@nestjs/common";
import { jalaliToGregorianDate } from "src/helpers/date-jalali";
import { gregorianDateInIran } from "src/helpers/iran-datetime";
export type FanavaranPolicyInquiryRow = {
PolicyId?: unknown;
EndDate?: unknown;
};
export type SelectedFanavaranPolicy = {
policy: FanavaranPolicyInquiryRow;
policyId: number;
endDate: string;
endDateGregorian: string;
};
type DatedFanavaranPolicy = {
policy: FanavaranPolicyInquiryRow;
endDate: string;
endDateGregorian: string;
};
const NO_POLICY_MESSAGE =
"No Fanavaran policies were found for the insurer national code. PolicyId is required; contact the administrator.";
const EXPIRED_POLICY_MESSAGE =
"The latest insurance policy is expired and cannot be sent to Fanavaran. Contact the administrator.";
const INVALID_POLICY_MESSAGE =
"Fanavaran policy inquiry returned policies without a valid PolicyId or EndDate. PolicyId is required; contact the administrator.";
function parsePolicyId(value: unknown): number | null {
if (value === null || value === undefined) return null;
if (typeof value === "string" && value.trim() === "") return null;
const id = Number(value);
return Number.isFinite(id) && id > 0 ? id : null;
}
function normalizeEndDate(value: unknown): {
endDate: string;
endDateGregorian: string;
} | null {
if (value === null || value === undefined) return null;
const endDate = String(value).trim();
if (!endDate) return null;
const endDateGregorian = jalaliToGregorianDate(endDate);
if (!endDateGregorian) return null;
return { endDate, endDateGregorian };
}
export function selectLatestActiveFanavaranPolicy(
policies: unknown,
todayGregorian: string = gregorianDateInIran(new Date()),
): SelectedFanavaranPolicy {
if (!Array.isArray(policies) || policies.length === 0) {
throw new BadRequestException(NO_POLICY_MESSAGE);
}
const candidates = policies
.map((policy) => {
if (!policy || typeof policy !== "object") return null;
const row = policy as FanavaranPolicyInquiryRow;
const endDate = normalizeEndDate(row.EndDate);
if (!endDate) return null;
return {
policy: row,
endDate: endDate.endDate,
endDateGregorian: endDate.endDateGregorian,
};
})
.filter((policy): policy is DatedFanavaranPolicy => policy !== null);
if (candidates.length === 0) {
throw new BadRequestException(INVALID_POLICY_MESSAGE);
}
const latest = candidates.reduce((currentLatest, candidate) =>
candidate.endDateGregorian > currentLatest.endDateGregorian
? candidate
: currentLatest,
);
if (latest.endDateGregorian < todayGregorian) {
throw new BadRequestException(EXPIRED_POLICY_MESSAGE);
}
const policyId = parsePolicyId(latest.policy.PolicyId);
if (policyId === null) {
throw new BadRequestException(INVALID_POLICY_MESSAGE);
}
return { ...latest, policyId };
}