forked from Yara724/api
740 lines
21 KiB
TypeScript
740 lines
21 KiB
TypeScript
import {
|
|
BadRequestException,
|
|
Injectable,
|
|
Logger,
|
|
NotFoundException,
|
|
} from "@nestjs/common";
|
|
import {
|
|
resolveFanavaranClientKey,
|
|
resolveFanavaranProductContractId,
|
|
} from "src/core/config/fanavaran-client.config";
|
|
import {
|
|
FANAVARAN_REMOTE_LOOKUPS,
|
|
type FanavaranRemoteLookupDefinition,
|
|
TEJARAT_STATIC_ACCIDENT_FILES,
|
|
} from "src/fanavaran/fanavaran-lookup.config";
|
|
import { FanavaranLookupService } from "src/fanavaran/fanavaran-lookup.service";
|
|
import {
|
|
parseJalaliDateParts,
|
|
selectFanavaranDriverId,
|
|
} from "src/claim-request-management/fanavaran-driver-inquiry";
|
|
import { LookupDbService } from "./entities/db-service/lookup.db.service";
|
|
import {
|
|
asObjectRecord,
|
|
filterPoliciesByLine,
|
|
insuranceLineIdForProduct,
|
|
insuranceLineLabel,
|
|
isPolicyActiveOn,
|
|
parseFanavaranId,
|
|
parseLastCarPolicyInput,
|
|
pickVehicleId,
|
|
selectLastAmongCarMatches,
|
|
sortPoliciesNewestEndDateFirst,
|
|
toAppPlaque,
|
|
vehicleMatchesCar,
|
|
type FanavaranCarPolicyProduct,
|
|
type HydratedFanavaranCarPolicy,
|
|
} from "./fanavaran-last-car-policy";
|
|
import { gregorianDateInIran } from "src/helpers/iran-datetime";
|
|
|
|
type TejaratAccidentReasonRow = {
|
|
id: number;
|
|
persianLabel: string;
|
|
fanavaranID: number;
|
|
};
|
|
|
|
type TejaratAccidentLabelRow = {
|
|
id: number;
|
|
persianLabel: string;
|
|
};
|
|
|
|
@Injectable()
|
|
export class LookupsService {
|
|
private readonly logger = new Logger(LookupsService.name);
|
|
|
|
constructor(
|
|
private readonly lookupDbService: LookupDbService,
|
|
private readonly fanavaranLookupService: FanavaranLookupService,
|
|
) {}
|
|
|
|
private activeClientKey() {
|
|
return resolveFanavaranClientKey();
|
|
}
|
|
|
|
listFanavaranRemoteLookups(): FanavaranRemoteLookupDefinition[] {
|
|
return FANAVARAN_REMOTE_LOOKUPS;
|
|
}
|
|
|
|
private findRemoteLookup(name: string) {
|
|
const lookup = FANAVARAN_REMOTE_LOOKUPS.find((item) => item.name === name);
|
|
if (!lookup) {
|
|
throw new NotFoundException(`Unknown Fanavaran remote lookup: ${name}`);
|
|
}
|
|
return lookup;
|
|
}
|
|
|
|
/**
|
|
* Returns stored `response` for a lookup document by `name` in the lookups collection.
|
|
* Legacy Tejarat seed data — used as fallback when live fetch is unavailable.
|
|
*/
|
|
async getLookup(lookupName: string): Promise<any> {
|
|
const doc = await this.lookupDbService.findOne({ name: lookupName });
|
|
if (!doc) {
|
|
this.logger.warn(`Lookup not found in database: ${lookupName}`);
|
|
throw new NotFoundException(`Lookup "${lookupName}" not found`);
|
|
}
|
|
return doc.response;
|
|
}
|
|
|
|
async getClientRemoteLookup(lookupName: string): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
const definition = this.findRemoteLookup(lookupName);
|
|
|
|
// Parsian: file → lookups collection → Fanavaran (default inside FanavaranLookupService)
|
|
// Tejaratno: file → Fanavaran → DB on API failure
|
|
return this.fanavaranLookupService.getRemoteLookup(
|
|
clientKey,
|
|
definition.url,
|
|
definition.cacheFile,
|
|
clientKey === "tejaratno"
|
|
? { dbSource: () => this.getLookup(lookupName) }
|
|
: undefined,
|
|
);
|
|
}
|
|
|
|
async getAccidentCauses(): Promise<any> {
|
|
return await this.getClientRemoteLookup("accident-causes");
|
|
}
|
|
|
|
async getAccidentReportType(): Promise<any> {
|
|
return await this.getClientRemoteLookup("accident-report-type");
|
|
}
|
|
|
|
async getVehicleUseTypes(): Promise<any> {
|
|
return await this.getClientRemoteLookup("vehicle-use-types");
|
|
}
|
|
|
|
async getDmgPayMethod(): Promise<any> {
|
|
return await this.getClientRemoteLookup("dmg-pay-method");
|
|
}
|
|
|
|
async getDrivingLicenceTypes(): Promise<any> {
|
|
return await this.getClientRemoteLookup("driving-licence-types");
|
|
}
|
|
|
|
async getAccidentCulpritType(): Promise<any> {
|
|
return await this.getClientRemoteLookup("accident-culprit-type");
|
|
}
|
|
|
|
async getInspectionPlace(): Promise<any> {
|
|
return await this.getClientRemoteLookup("inspection-place");
|
|
}
|
|
|
|
async getDropAmountStatus(): Promise<any> {
|
|
return await this.getClientRemoteLookup("drop-amount-status");
|
|
}
|
|
|
|
async getCarComponents(): Promise<any> {
|
|
return await this.getClientRemoteLookup("car-components");
|
|
}
|
|
|
|
async getAccidentLevel(): Promise<any> {
|
|
return await this.getClientRemoteLookup("accident-level");
|
|
}
|
|
|
|
async getExpertStatus(): Promise<any> {
|
|
return await this.getClientRemoteLookup("expert-status");
|
|
}
|
|
|
|
async getVehicleKinds(): Promise<any> {
|
|
return await this.getClientRemoteLookup("vehicle-kinds");
|
|
}
|
|
|
|
async getPersonRole(): Promise<any> {
|
|
return await this.getClientRemoteLookup("person-role");
|
|
}
|
|
|
|
async getFileTypes(): Promise<any> {
|
|
return await this.getClientRemoteLookup("file-types");
|
|
}
|
|
|
|
async getCities(): Promise<any> {
|
|
return await this.getClientRemoteLookup("cities");
|
|
}
|
|
|
|
async getProvinces(): Promise<any> {
|
|
return await this.getClientRemoteLookup("provinces");
|
|
}
|
|
|
|
async getDmgCaseType(): Promise<any> {
|
|
return await this.getClientRemoteLookup("dmg-case-type");
|
|
}
|
|
|
|
async getDmgHistoryStatus(): Promise<any> {
|
|
return await this.getClientRemoteLookup("dmg-history-status");
|
|
}
|
|
|
|
async getUsedPlace(): Promise<any> {
|
|
return await this.getClientRemoteLookup("used-place");
|
|
}
|
|
|
|
async getDmgBusinessLine(): Promise<any> {
|
|
return await this.getClientRemoteLookup("dmg-business-line");
|
|
}
|
|
|
|
async inquiryByUniqueIdentifier(query: {
|
|
nationalCode?: string;
|
|
birthday?: string;
|
|
birthYear?: string | number;
|
|
birthMonth?: string | number;
|
|
birthDay?: string | number;
|
|
}): Promise<unknown> {
|
|
const nationalCode = String(query.nationalCode ?? "").trim();
|
|
if (!nationalCode) {
|
|
throw new BadRequestException("nationalCode is required");
|
|
}
|
|
|
|
const fromParts = {
|
|
year: Number(query.birthYear),
|
|
month: Number(query.birthMonth),
|
|
day: Number(query.birthDay),
|
|
};
|
|
const parsed =
|
|
Number.isFinite(fromParts.year) &&
|
|
fromParts.year > 0 &&
|
|
Number.isFinite(fromParts.month) &&
|
|
fromParts.month > 0 &&
|
|
Number.isFinite(fromParts.day) &&
|
|
fromParts.day > 0
|
|
? fromParts
|
|
: parseJalaliDateParts(query.birthday);
|
|
|
|
if (!parsed) {
|
|
throw new BadRequestException(
|
|
"birthday (e.g. 13480313) or birthYear+birthMonth+birthDay is required",
|
|
);
|
|
}
|
|
|
|
const clientKey = this.activeClientKey();
|
|
const rows = await this.fanavaranLookupService.inquiryByUniqueIdentifier(
|
|
clientKey,
|
|
{
|
|
nationalCode,
|
|
birthYear: parsed.year,
|
|
birthMonth: parsed.month,
|
|
birthDay: parsed.day,
|
|
},
|
|
);
|
|
return {
|
|
nationalCode,
|
|
birthday: parsed,
|
|
driverId: selectFanavaranDriverId(rows, undefined),
|
|
insurerId: selectFanavaranDriverId(rows, true),
|
|
parties: rows,
|
|
};
|
|
}
|
|
|
|
async inquiryByVin(vin: string): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
const raw = await this.fanavaranLookupService.inquiryByVin(clientKey, vin);
|
|
if (Array.isArray(raw)) {
|
|
if (raw.length === 0) {
|
|
throw new NotFoundException(
|
|
`Fanavaran vehicle for VIN ${vin} was not found.`,
|
|
);
|
|
}
|
|
return Promise.all(
|
|
raw.map(async (item) => {
|
|
const vehicle = asObjectRecord(item);
|
|
return vehicle ? this.enrichVehicle(vehicle) : item;
|
|
}),
|
|
);
|
|
}
|
|
const vehicle = asObjectRecord(raw);
|
|
if (!vehicle) {
|
|
throw new NotFoundException(
|
|
`Fanavaran vehicle for VIN ${vin} was not found.`,
|
|
);
|
|
}
|
|
return this.enrichVehicle(vehicle);
|
|
}
|
|
|
|
async myPolicies(
|
|
nationalCode: string,
|
|
insuranceLineId: number = 5,
|
|
): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
return this.fanavaranLookupService.myPolicies(
|
|
clientKey,
|
|
nationalCode,
|
|
insuranceLineId,
|
|
);
|
|
}
|
|
|
|
async findLastProcessedCarPolicy(
|
|
product: FanavaranCarPolicyProduct,
|
|
query: {
|
|
nationalCode?: string;
|
|
vin?: string;
|
|
plaqueLeft?: string;
|
|
plaqueLetter?: string;
|
|
plaqueRight?: string;
|
|
plaqueSerial?: string;
|
|
},
|
|
): Promise<{
|
|
product: FanavaranCarPolicyProduct;
|
|
insuranceLine: "CAR_BODY" | "THIRD_PARTY" | null;
|
|
insuranceLineId: number;
|
|
policyId: number;
|
|
policy: any;
|
|
customer: Record<string, unknown> | null;
|
|
vehicle: Record<string, unknown> | null;
|
|
}> {
|
|
const parsed = parseLastCarPolicyInput(query);
|
|
if ("error" in parsed) {
|
|
throw new BadRequestException(parsed.error);
|
|
}
|
|
|
|
const clientKey = this.activeClientKey();
|
|
const insuranceLineId = insuranceLineIdForProduct(product);
|
|
const contractIdOverride = resolveFanavaranProductContractId(
|
|
clientKey,
|
|
product,
|
|
);
|
|
const requestOptions = { contractIdOverride };
|
|
|
|
const listed = await this.fanavaranLookupService.myPolicies(
|
|
clientKey,
|
|
parsed.nationalCode,
|
|
insuranceLineId,
|
|
requestOptions,
|
|
);
|
|
const candidates = sortPoliciesNewestEndDateFirst(
|
|
filterPoliciesByLine(listed, insuranceLineId),
|
|
);
|
|
|
|
let vinVehicleId: number | null = null;
|
|
if (parsed.vin) {
|
|
try {
|
|
const inquired = await this.fanavaranLookupService.inquiryByVin(
|
|
clientKey,
|
|
parsed.vin,
|
|
requestOptions,
|
|
);
|
|
vinVehicleId = pickVehicleId(inquired);
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`VIN vehicle helper failed; continuing with policy hydrate: ${
|
|
error instanceof Error ? error.message : error
|
|
}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const matches: HydratedFanavaranCarPolicy[] = [];
|
|
let hydrationFailures = 0;
|
|
|
|
for (const row of candidates) {
|
|
const policyId = parseFanavaranId(row.PolicyId);
|
|
if (policyId === null) continue;
|
|
|
|
let policyRaw: unknown;
|
|
try {
|
|
policyRaw =
|
|
product === "car-body"
|
|
? await this.fanavaranLookupService.bodyPolicyById(
|
|
clientKey,
|
|
policyId,
|
|
requestOptions,
|
|
)
|
|
: await this.fanavaranLookupService.thirdPartyPolicyById(
|
|
clientKey,
|
|
policyId,
|
|
requestOptions,
|
|
);
|
|
} catch (error) {
|
|
hydrationFailures += 1;
|
|
this.logger.warn(
|
|
`Policy GET failed for PolicyId=${policyId}: ${
|
|
error instanceof Error ? error.message : error
|
|
}`,
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const policy = asObjectRecord(policyRaw);
|
|
if (!policy) continue;
|
|
|
|
const vehicleId = pickVehicleId(policy.VehicleId ?? policy.vehicleId);
|
|
if (
|
|
parsed.vin &&
|
|
vinVehicleId !== null &&
|
|
vehicleId !== null &&
|
|
vehicleId !== vinVehicleId
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
let vehicle: Record<string, unknown> | null = null;
|
|
if (vehicleId !== null) {
|
|
try {
|
|
vehicle = asObjectRecord(
|
|
await this.fanavaranLookupService.vehicleById(
|
|
clientKey,
|
|
vehicleId,
|
|
undefined,
|
|
requestOptions,
|
|
),
|
|
);
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`Vehicle GET failed for VehicleId=${vehicleId} (PolicyId=${policyId}): ${
|
|
error instanceof Error ? error.message : error
|
|
}`,
|
|
);
|
|
}
|
|
}
|
|
|
|
const matchedByVinVehicleId =
|
|
parsed.vin != null &&
|
|
vinVehicleId != null &&
|
|
vehicleId != null &&
|
|
vinVehicleId === vehicleId;
|
|
|
|
if (
|
|
!matchedByVinVehicleId &&
|
|
!vehicleMatchesCar(vehicle, parsed, vinVehicleId)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
matches.push({
|
|
policyId,
|
|
beginDate: policy.BeginDate ?? row.BeginDate,
|
|
endDate: policy.EndDate ?? row.EndDate,
|
|
vehicleId,
|
|
policy,
|
|
vehicle,
|
|
});
|
|
}
|
|
|
|
const selected = selectLastAmongCarMatches(matches);
|
|
if (!selected) {
|
|
if (candidates.length === 0) {
|
|
throw new NotFoundException(
|
|
`No Fanavaran ${product} policy was found for this national code and car.`,
|
|
);
|
|
}
|
|
if (hydrationFailures === candidates.length) {
|
|
throw new NotFoundException(
|
|
`Fanavaran ${product} policy details could not be loaded for this national code.`,
|
|
);
|
|
}
|
|
throw new NotFoundException(
|
|
`No Fanavaran ${product} policy of that line was found for this car.`,
|
|
);
|
|
}
|
|
|
|
// A CAR_BODY case is payable only with current hull coverage. The generic
|
|
// selector may intentionally return the latest expired policy for history;
|
|
// that fallback is not valid for a new CAR_BODY case.
|
|
if (
|
|
product === "car-body" &&
|
|
!isPolicyActiveOn(selected, gregorianDateInIran(new Date()))
|
|
) {
|
|
throw new NotFoundException(
|
|
"No active Fanavaran car-body policy was found for this car.",
|
|
);
|
|
}
|
|
|
|
return {
|
|
product,
|
|
insuranceLine: insuranceLineLabel(insuranceLineId),
|
|
insuranceLineId,
|
|
policyId: selected.policyId,
|
|
policy: await this.mapPolicyDetails(selected.policy),
|
|
customer: await this.fetchCustomer(
|
|
clientKey,
|
|
parseFanavaranId(selected.policy.CustomerId),
|
|
requestOptions,
|
|
),
|
|
vehicle: await this.enrichVehicle(selected.vehicle),
|
|
};
|
|
}
|
|
|
|
private async fetchCustomer(
|
|
clientKey: ReturnType<LookupsService["activeClientKey"]>,
|
|
customerId: number | null,
|
|
requestOptions: { contractIdOverride?: string },
|
|
): Promise<Record<string, unknown> | null> {
|
|
if (customerId === null) return null;
|
|
try {
|
|
return asObjectRecord(
|
|
await this.fanavaranLookupService.customerById(
|
|
clientKey,
|
|
customerId,
|
|
requestOptions,
|
|
),
|
|
);
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`Customer GET failed for CustomerId=${customerId}: ${
|
|
error instanceof Error ? error.message : error
|
|
}`,
|
|
);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private async lookupRowById(
|
|
lookupName: string,
|
|
id: number | null,
|
|
): Promise<Record<string, unknown> | null> {
|
|
if (id === null) return null;
|
|
try {
|
|
const rows = await this.getClientRemoteLookup(lookupName);
|
|
if (!Array.isArray(rows)) return null;
|
|
const match = rows.find(
|
|
(row) => parseFanavaranId((row as { Id?: unknown })?.Id) === id,
|
|
);
|
|
return asObjectRecord(match);
|
|
} catch (error) {
|
|
this.logger.warn(
|
|
`Failed to resolve ${lookupName} id=${id}: ${
|
|
error instanceof Error ? error.message : error
|
|
}`,
|
|
);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private async enrichVehicle(
|
|
vehicle: Record<string, unknown> | null,
|
|
): Promise<Record<string, unknown> | null> {
|
|
if (!vehicle) return null;
|
|
const vehicleKindId = parseFanavaranId(vehicle.VehicleKindId);
|
|
const usedId = parseFanavaranId(vehicle.UsedId);
|
|
return {
|
|
...vehicle,
|
|
color: null,
|
|
vehicleKind: await this.lookupRowById("vehicle-kinds", vehicleKindId),
|
|
used: await this.lookupRowById("vehicle-use-types", usedId),
|
|
plaque: toAppPlaque(vehicle),
|
|
};
|
|
}
|
|
|
|
async mapPolicyDetails(policy: any): Promise<any> {
|
|
if (!policy || typeof policy !== "object") {
|
|
return policy;
|
|
}
|
|
|
|
const mappedPolicy = { ...policy };
|
|
|
|
// 1. Map PreviousInsuranceCorpId and TransferorInsuranceCorpId
|
|
try {
|
|
const companies = (await this.getClientRemoteLookup("insurance-corp")) as any[];
|
|
if (Array.isArray(companies)) {
|
|
if (typeof policy.PreviousInsuranceCorpId === "number") {
|
|
const match = companies.find((c) => c.Id === policy.PreviousInsuranceCorpId);
|
|
if (match) {
|
|
mappedPolicy.PreviousInsuranceCorpName = match.Caption;
|
|
}
|
|
}
|
|
if (typeof policy.TransferorInsuranceCorpId === "number") {
|
|
const match = companies.find((c) => c.Id === policy.TransferorInsuranceCorpId);
|
|
if (match) {
|
|
mappedPolicy.TransferorInsuranceCorpName = match.Caption;
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
this.logger.warn(`Failed to map insurance-corp lookups: ${e.message}`);
|
|
}
|
|
|
|
// 2. Map PolicyUsageTypeId
|
|
try {
|
|
const useTypes = (await this.getClientRemoteLookup("vehicle-use-types")) as any[];
|
|
if (Array.isArray(useTypes) && typeof policy.PolicyUsageTypeId === "number") {
|
|
const match = useTypes.find((t) => t.Id === policy.PolicyUsageTypeId);
|
|
if (match) {
|
|
mappedPolicy.PolicyUsageTypeName = match.Caption;
|
|
}
|
|
}
|
|
} catch (e) {
|
|
this.logger.warn(`Failed to map vehicle-use-types lookups: ${e.message}`);
|
|
}
|
|
|
|
return mappedPolicy;
|
|
}
|
|
|
|
async thirdPartyPolicyById(policyId: number): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
const policy = await this.fanavaranLookupService.thirdPartyPolicyById(clientKey, policyId);
|
|
return this.mapPolicyDetails(policy);
|
|
}
|
|
|
|
async bodyPolicyById(policyId: number): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
const policy = await this.fanavaranLookupService.bodyPolicyById(
|
|
clientKey,
|
|
policyId,
|
|
{
|
|
contractIdOverride: resolveFanavaranProductContractId(
|
|
clientKey,
|
|
"car-body",
|
|
),
|
|
},
|
|
);
|
|
return this.mapPolicyDetails(policy);
|
|
}
|
|
|
|
async vehicleById(vehicleId: number, versionNo?: number): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
const vehicle = asObjectRecord(
|
|
await this.fanavaranLookupService.vehicleById(
|
|
clientKey,
|
|
vehicleId,
|
|
versionNo,
|
|
),
|
|
);
|
|
if (!vehicle) {
|
|
throw new NotFoundException(
|
|
`Fanavaran vehicle ${vehicleId} was not found.`,
|
|
);
|
|
}
|
|
return this.enrichVehicle(vehicle);
|
|
}
|
|
|
|
async customerById(customerId: number): Promise<unknown> {
|
|
const clientKey = this.activeClientKey();
|
|
return this.fanavaranLookupService.customerById(clientKey, customerId);
|
|
}
|
|
|
|
async getAccidentWay(): Promise<{ id: number; label: string }[]> {
|
|
const clientKey = this.activeClientKey();
|
|
const fileName = TEJARAT_STATIC_ACCIDENT_FILES.accidentWay;
|
|
|
|
const cached = await this.fanavaranLookupService.readCacheFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(clientKey, fileName);
|
|
const raw =
|
|
cached ??
|
|
(clientKey === "tejaratno"
|
|
? await this.fanavaranLookupService.readTejaratStaticAccidentFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(fileName)
|
|
: null);
|
|
|
|
if (!raw) {
|
|
this.logger.warn(
|
|
`No accident-way lookup for client ${clientKey}; falling back to tejarat static file`,
|
|
);
|
|
const fallback =
|
|
await this.fanavaranLookupService.readTejaratStaticAccidentFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(fileName);
|
|
return fallback.map((item) => ({
|
|
id: item.id,
|
|
label: item.persianLabel,
|
|
}));
|
|
}
|
|
|
|
return raw.map((item) => ({ id: item.id, label: item.persianLabel }));
|
|
}
|
|
|
|
async getAccidentReason(): Promise<
|
|
{ id: number; label: string; fanavaran: number }[]
|
|
> {
|
|
const clientKey = this.activeClientKey();
|
|
|
|
if (clientKey === "parsian") {
|
|
const cacheFile = "accident-reason-options.json";
|
|
const cached = await this.fanavaranLookupService.readCacheFile<
|
|
{ id: number; label: string; fanavaran: number }[]
|
|
>(clientKey, cacheFile);
|
|
if (cached) {
|
|
return cached;
|
|
}
|
|
|
|
const causes = await this.getAccidentCauses();
|
|
const mapped =
|
|
this.fanavaranLookupService.mapFanavaranAccidentCausesToReasonOptions(
|
|
causes,
|
|
);
|
|
await this.fanavaranLookupService.writeCacheFile(
|
|
clientKey,
|
|
cacheFile,
|
|
mapped,
|
|
);
|
|
return mapped;
|
|
}
|
|
|
|
const fileName = TEJARAT_STATIC_ACCIDENT_FILES.accidentReason;
|
|
const cached = await this.fanavaranLookupService.readCacheFile<
|
|
TejaratAccidentReasonRow[]
|
|
>(clientKey, fileName);
|
|
const raw =
|
|
cached ??
|
|
(await this.fanavaranLookupService.readTejaratStaticAccidentFile<
|
|
TejaratAccidentReasonRow[]
|
|
>(fileName));
|
|
|
|
return raw.map((item) => ({
|
|
id: item.id,
|
|
label: item.persianLabel,
|
|
fanavaran: item.fanavaranID,
|
|
}));
|
|
}
|
|
|
|
async getAccidentType(): Promise<{ id: number; label: string }[]> {
|
|
const clientKey = this.activeClientKey();
|
|
const fileName = TEJARAT_STATIC_ACCIDENT_FILES.accidentType;
|
|
|
|
const cached = await this.fanavaranLookupService.readCacheFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(clientKey, fileName);
|
|
const raw =
|
|
cached ??
|
|
(clientKey === "tejaratno"
|
|
? await this.fanavaranLookupService.readTejaratStaticAccidentFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(fileName)
|
|
: null);
|
|
|
|
if (!raw) {
|
|
this.logger.warn(
|
|
`No accident-type lookup for client ${clientKey}; falling back to tejarat static file`,
|
|
);
|
|
const fallback =
|
|
await this.fanavaranLookupService.readTejaratStaticAccidentFile<
|
|
TejaratAccidentLabelRow[]
|
|
>(fileName);
|
|
return fallback.map((item) => ({
|
|
id: item.id,
|
|
label: item.persianLabel,
|
|
}));
|
|
}
|
|
|
|
return raw.map((item) => ({ id: item.id, label: item.persianLabel }));
|
|
}
|
|
|
|
async getAccidentFields(): Promise<{
|
|
accidentWay: { id: number; label: string }[];
|
|
accidentReason: { id: number; label: string; fanavaran: number }[];
|
|
accidentType: { id: number; label: string }[];
|
|
client: string;
|
|
}> {
|
|
const [accidentWay, accidentReason, accidentType] = await Promise.all([
|
|
this.getAccidentWay(),
|
|
this.getAccidentReason(),
|
|
this.getAccidentType(),
|
|
]);
|
|
return {
|
|
client: this.activeClientKey(),
|
|
accidentWay,
|
|
accidentReason,
|
|
accidentType,
|
|
};
|
|
}
|
|
}
|