1
0
forked from Yara724/api

Compare commits

..

20 Commits

Author SHA1 Message Date
80122e7772 Merge pull request 'main' (#180) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#180
2026-07-07 18:53:35 +03:30
f409d78ede merge upstream 2026-07-07 18:53:01 +03:30
Soheil Hajizadeh
24340eb810 claim request management change 2026-07-07 18:52:07 +03:30
41d1de77eb Merge pull request 'main' (#179) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#179
2026-07-07 17:30:48 +03:30
0aadc64cd3 merge upstream 2026-07-07 17:30:23 +03:30
Soheil Hajizadeh
1e6c36cbd4 lookup of person role added + inquiry by unique identifier + put driver id in payload 2026-07-07 17:29:48 +03:30
ae23a10d33 Merge pull request 'main' (#178) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#178
2026-07-07 13:47:07 +03:30
1c6678d8e4 merge upstream 2026-07-07 13:46:27 +03:30
Soheil Hajizadeh
ad5ff28be4 fanavaran damage case updated 2026-07-07 13:42:06 +03:30
1fe2c77c70 Merge pull request 'main' (#177) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#177
2026-07-05 15:49:53 +03:30
45a51f2c24 merge upstream 2026-07-05 15:47:59 +03:30
Soheil Hajizadeh
0514548136 policyCINumber added to the payload 2026-07-05 15:45:39 +03:30
5b4cc0560f Merge pull request 'V4: add WAITING_FOR_FILE_REVIEWER claim status; fix select-outer-parts for split flow' (#176) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#176
2026-07-05 15:16:43 +03:30
8ab49c9a35 Merge pull request 'Fixed reviewer flow' (#175) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#175
2026-07-05 11:47:11 +03:30
3205a89611 Merge pull request 'Fixed GET APIs for FileMaker and FileReviewer getting their own files' (#174) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#174
2026-07-05 11:35:48 +03:30
1fe66b2d91 Merge pull request 'Adding file makers and file reviewers to global roles' (#173) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#173
2026-07-04 14:21:17 +03:30
f05891a112 Merge pull request 'Fixed outer parts flow bug in v4' (#172) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#172
2026-07-04 10:29:10 +03:30
ae83100ef4 Merge pull request 'Added roles for GET car parts APIs' (#171) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#171
2026-07-02 13:17:37 +03:30
ced08fc1f7 Merge pull request 'fix it' (#170) from s.hajizadeh/yara724api:main into main
Reviewed-on: Yara724/api#170
2026-07-01 18:06:07 +03:30
d525b8dd0d fix it 2026-07-01 18:05:09 +03:30
6 changed files with 327 additions and 17 deletions

View File

@@ -241,6 +241,15 @@ const FANAVARAN_ACCIDENT_LOCATION_ADDRESS = "استان تهران شهر تهر
const FANAVARAN_DEFAULT_ACCIDENT_CAUSE_ID = 6; const FANAVARAN_DEFAULT_ACCIDENT_CAUSE_ID = 6;
const FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT = 1000; const FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT = 1000;
/** Local carType → Fanavaran vehicle-kind Caption keywords for matching. */
const VEHICLE_KIND_KEYWORDS: Record<ClaimVehicleTypeV2, string[]> = {
[ClaimVehicleTypeV2.SEDAN]: ["سواری", "سواري", "sedan"],
[ClaimVehicleTypeV2.SUV]: ["شاسی", "شاسي", "suv", "بلند"],
[ClaimVehicleTypeV2.HATCHBACK]: ["هاچبک", "هاچ بک", "hatchback"],
[ClaimVehicleTypeV2.PICKUP]: ["وانت", "پیکاپ", "pick", "pickup"],
[ClaimVehicleTypeV2.VAN]: ["ون", "van"],
};
const FANAVARAN_PLATE_LETTER_CODE: Record<string, number> = { const FANAVARAN_PLATE_LETTER_CODE: Record<string, number> = {
الف: 1, الف: 1,
ب: 2, ب: 2,
@@ -3593,10 +3602,146 @@ export class ClaimRequestManagementService {
return `${plate.centerDigits}${plate.centerAlphabet}${plate.leftDigits}`; return `${plate.centerDigits}${plate.centerAlphabet}${plate.leftDigits}`;
} }
private buildFanavaranDamageCasePayload(input: { private async resolveVehicleKindId(
clientKey: FanavaranClientKey,
carType?: string,
): Promise<number | null> {
if (!carType) return null;
const vehicleType = carType as ClaimVehicleTypeV2;
const keywords = VEHICLE_KIND_KEYWORDS[vehicleType];
if (!keywords) return null;
try {
const lookup = this.fanavaranLookupService;
const definition = FANAVARAN_REMOTE_LOOKUPS.find(
(l) => l.name === "vehicle-kinds",
);
if (!definition) return null;
const data = (await lookup.getRemoteLookup(
clientKey,
definition.url,
definition.cacheFile,
)) as Array<{ Id?: number; Caption?: string; IsActive?: number }>;
if (!Array.isArray(data)) return null;
const normalizedKeywords = keywords.map((k) => k.toLowerCase());
const match = data.find((item) => {
if (!item.Caption || item.IsActive === 0) return false;
const caption = item.Caption.toLowerCase();
return normalizedKeywords.some((kw) => caption.includes(kw));
});
return match?.Id ?? null;
} catch {
this.logger.warn(
`Failed to resolve VehicleKindId for carType=${carType}`,
);
return null;
}
}
private parseJalaliBirthday(
birthday: string | number | null | undefined,
): { year: number; month: number; day: number } | null {
if (birthday == null) return null;
const str = String(birthday).trim();
// Compact format: "13640610" → year=1364, month=06, day=10
if (/^\d{8}$/.test(str)) {
const year = parseInt(str.slice(0, 4), 10);
const month = parseInt(str.slice(4, 6), 10);
const day = parseInt(str.slice(6, 8), 10);
if (isNaN(year) || isNaN(month) || isNaN(day)) return null;
return { year, month, day };
}
// Delimited formats: "1364/06/10" or "1364-06-10"
const parts = str.split(/[/\-]/);
if (parts.length < 3) return null;
const year = parseInt(parts[0], 10);
const month = parseInt(parts[1], 10);
const day = parseInt(parts[2], 10);
if (isNaN(year) || isNaN(month) || isNaN(day)) return null;
return { year, month, day };
}
private async resolveDriverFanavaranId(
clientKey: FanavaranClientKey,
nationalCode: string | null | undefined,
driverBirthday: string | null | undefined,
driverIsInsurer: boolean | undefined,
): Promise<number | null> {
if (!nationalCode) {
this.logger.warn(
`resolveDriverFanavaranId: no nationalCode provided, skipping party inquiry`,
);
return null;
}
const parsed = this.parseJalaliBirthday(driverBirthday);
if (!parsed) {
this.logger.warn(
`resolveDriverFanavaranId: could not parse driverBirthday "${driverBirthday}" for nationalCode=${nationalCode}`,
);
return null;
}
const targetRoleId = driverIsInsurer ? 161 : 166;
try {
const response = (await this.fanavaranLookupService.inquiryByUniqueIdentifier(
clientKey,
{
nationalCode,
birthYear: parsed.year,
birthMonth: parsed.month,
birthDay: parsed.day,
},
)) as Array<{
Id: number;
RoleId: number;
NationalCode: string;
Name?: string;
LastName?: string;
}>;
if (!Array.isArray(response) || response.length === 0) {
this.logger.warn(
`resolveDriverFanavaranId: empty response for nationalCode=${nationalCode}`,
);
return null;
}
const match = response.find((entry) => entry.RoleId === targetRoleId);
if (match) {
this.logger.log(
`resolveDriverFanavaranId: foundRoleId=${targetRoleId} Id=${match.Id} for nationalCode=${nationalCode} (${match.Name} ${match.LastName})`,
);
return match.Id;
}
this.logger.warn(
`resolveDriverFanavaranId: no person with RoleId=${targetRoleId} (driverIsInsurer=${driverIsInsurer}) for nationalCode=${nationalCode}. ` +
`Available RoleIds: ${response.map((e) => e.RoleId).join(", ")}. ` +
`Person is not defined in Fanavaran system for this role.`,
);
return null;
} catch (error) {
this.logger.error(
`resolveDriverFanavaranId: failed to call inquiry-by-unique-identifier for nationalCode=${nationalCode}: ${error instanceof Error ? error.message : error}`,
);
return null;
}
}
private async buildFanavaranDamageCasePayload(input: {
claimCase: any; claimCase: any;
blameCase?: any; blameCase?: any;
selectedParts: unknown[]; selectedParts: unknown[];
clientKey: FanavaranClientKey;
defaults: { defaults: {
AccidentVehicleUsedId: number; AccidentVehicleUsedId: number;
CulpritLicenceTypeId: number; CulpritLicenceTypeId: number;
@@ -3607,7 +3752,7 @@ export class ClaimRequestManagementService {
DriverIsOwner: number; DriverIsOwner: number;
FaultPercent: number; FaultPercent: number;
}; };
}): Record<string, unknown> { }): Promise<Record<string, unknown>> {
const plate = this.resolveOwnershipPlateForClaim( const plate = this.resolveOwnershipPlateForClaim(
input.claimCase, input.claimCase,
input.blameCase, input.blameCase,
@@ -3625,15 +3770,46 @@ export class ClaimRequestManagementService {
const inquiryMapped = vehicle?.inquiry?.mapped ?? {}; const inquiryMapped = vehicle?.inquiry?.mapped ?? {};
const inquiryRaw = vehicle?.inquiry?.raw ?? {}; const inquiryRaw = vehicle?.inquiry?.raw ?? {};
const guiltyUserId =
input.blameCase?.expertSubmitReplyFinal?.guiltyUserId ??
input.blameCase?.expertSubmitReply?.guiltyUserId;
const blamedParty =
guiltyUserId && Array.isArray(input.blameCase?.parties)
? input.blameCase.parties.find(
(party: any) =>
String(party?.person?.userId ?? "") === String(guiltyUserId),
)
: null;
const blamedThirdPolicyCode =
blamedParty?.vehicle?.inquiry?.mapped?.ThirdPolicyCode ?? null;
const carType = input.claimCase?.vehicle?.carType as string | undefined;
const vehicleKindId = await this.resolveVehicleKindId(
input.clientKey,
carType,
);
const driverFanavaranId = await this.resolveDriverFanavaranId(
input.clientKey,
person.nationalCodeOfDriver,
person.driverBirthday,
person.driverIsInsurer,
);
return { return {
BeginDate: insurance.startDate ?? null, BeginDate: insurance.startDate ?? null,
BuiltYear: BuiltYear:
Number(inquiryMapped.ModelField ?? inquiryMapped.ModelCii) || null, Number(inquiryMapped.ModelField ?? inquiryMapped.ModelCii) || null,
ChassisNo: inquiryMapped.ChassisNo ?? inquiryRaw.ChassisNo ?? null, ChassisNo:
inquiryMapped.ChassisNumberField ??
inquiryMapped.ShsNum ??
inquiryRaw.ChassisNumberField ??
inquiryRaw.ShsNum ??
null,
DmgHistoryStatus: input.defaults.DmgHistoryStatus, DmgHistoryStatus: input.defaults.DmgHistoryStatus,
Desc: this.formatFanavaranSelectedPartsDesc(input.selectedParts), Desc: this.formatFanavaranSelectedPartsDesc(input.selectedParts),
DmgCaseTypeId: input.defaults.DmgCaseTypeId, DmgCaseTypeId: input.defaults.DmgCaseTypeId,
DriverId: null, DriverId: driverFanavaranId ?? null,
EndDate: insurance.endDate ?? null, EndDate: insurance.endDate ?? null,
EstimateAmount: FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT, EstimateAmount: FANAVARAN_PROVISIONAL_ESTIMATE_AMOUNT,
FaultPercent: input.defaults.FaultPercent, FaultPercent: input.defaults.FaultPercent,
@@ -3645,7 +3821,12 @@ export class ClaimRequestManagementService {
LicenceIssuDate: person.driverBirthday ?? "1394/10/13", LicenceIssuDate: person.driverBirthday ?? "1394/10/13",
LicenceNo: person.driverLicense ?? "1124242", LicenceNo: person.driverLicense ?? "1124242",
LicenceTypeId: input.defaults.CulpritLicenceTypeId, LicenceTypeId: input.defaults.CulpritLicenceTypeId,
MotorNo: inquiryMapped.MotorNo ?? inquiryRaw.MotorNo ?? null, MotorNo:
inquiryMapped.MtrNum ??
inquiryMapped.EngineNumberField ??
inquiryRaw.MtrNum ??
inquiryRaw.EngineNumberField ??
null,
OwnerId: null, OwnerId: null,
PlaqueCityId: null, PlaqueCityId: null,
PlaqueKindId: plate ? input.defaults.PlaqueKindId : null, PlaqueKindId: plate ? input.defaults.PlaqueKindId : null,
@@ -3659,10 +3840,10 @@ export class ClaimRequestManagementService {
PlaqueSerial: plate ? String(plate.ir) : null, PlaqueSerial: plate ? String(plate.ir) : null,
PolicyNo: insurance.policyNumber ?? null, PolicyNo: insurance.policyNumber ?? null,
PreviousPolicyEndDate: insurance.endDate ?? "", PreviousPolicyEndDate: insurance.endDate ?? "",
VehicleKindId: null, VehicleKindId: vehicleKindId,
VIN: inquiryMapped.VIN ?? inquiryRaw.VIN ?? null, VIN: inquiryMapped.VIN ?? inquiryRaw.VIN ?? null,
AccidentVehicleUsedId: input.defaults.AccidentVehicleUsedId, AccidentVehicleUsedId: input.defaults.AccidentVehicleUsedId,
PolicyCINumber: null, PolicyCINumber: blamedThirdPolicyCode,
}; };
} }
@@ -4454,9 +4635,10 @@ export class ClaimRequestManagementService {
async submitFanavaranV2( async submitFanavaranV2(
claimCaseId: string, claimCaseId: string,
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
bodyOverride?: Record<string, unknown>,
): Promise<any> { ): Promise<any> {
try { try {
return await this.executeFanavaranV2Submit(claimCaseId, clientKey); return await this.executeFanavaranV2Submit(claimCaseId, clientKey, bodyOverride);
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
`[Fanavaran ${clientKey} V2] Error submitting to Fanavaran`, `[Fanavaran ${clientKey} V2] Error submitting to Fanavaran`,
@@ -4495,10 +4677,11 @@ export class ClaimRequestManagementService {
); );
} }
const payload = this.buildFanavaranDamageCasePayload({ const payload = await this.buildFanavaranDamageCasePayload({
claimCase, claimCase,
blameCase, blameCase,
selectedParts: claimCase.damage?.selectedParts ?? [], selectedParts: claimCase.damage?.selectedParts ?? [],
clientKey,
defaults: profile.defaults, defaults: profile.defaults,
}); });
@@ -4520,6 +4703,7 @@ export class ClaimRequestManagementService {
async submitFanavaranDamageCaseV2( async submitFanavaranDamageCaseV2(
claimCaseId: string, claimCaseId: string,
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
bodyOverride?: Record<string, unknown>,
): Promise<any> { ): Promise<any> {
try { try {
return await this.executeFanavaranDamageCaseSubmit( return await this.executeFanavaranDamageCaseSubmit(
@@ -4527,6 +4711,7 @@ export class ClaimRequestManagementService {
clientKey, clientKey,
undefined, undefined,
FanavaranAuditSource.SUBMIT, FanavaranAuditSource.SUBMIT,
bodyOverride,
); );
} catch (error) { } catch (error) {
this.logger.error( this.logger.error(
@@ -5112,15 +5297,22 @@ export class ClaimRequestManagementService {
async submitFanavaranExpertiseV2( async submitFanavaranExpertiseV2(
claimCaseId: string, claimCaseId: string,
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
bodyOverride?: Record<string, unknown>,
): Promise<any> { ): Promise<any> {
try { try {
const claimCase = await this.claimCaseDbService.findById(claimCaseId); const claimCase = await this.claimCaseDbService.findById(claimCaseId);
if (!claimCase) throw new NotFoundException("Claim case not found"); if (!claimCase) throw new NotFoundException("Claim case not found");
const { payload, warnings } = await this.buildFanavaranExpertisePayload({ let payload: Record<string, unknown>;
claimCase, if (bodyOverride) {
clientKey, payload = bodyOverride;
}); } else {
this.assertFanavaranExpertisePayloadReady(payload, warnings); const built = await this.buildFanavaranExpertisePayload({
claimCase,
clientKey,
});
payload = built.payload;
this.assertFanavaranExpertisePayloadReady(payload, built.warnings);
}
return await this.executeFanavaranExpertiseSubmit( return await this.executeFanavaranExpertiseSubmit(
claimCaseId, claimCaseId,
clientKey, clientKey,
@@ -5625,6 +5817,7 @@ export class ClaimRequestManagementService {
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
selectedParts?: unknown[], selectedParts?: unknown[],
auditSource: FanavaranAuditSource = FanavaranAuditSource.AUTO_SUBMIT, auditSource: FanavaranAuditSource = FanavaranAuditSource.AUTO_SUBMIT,
bodyOverride?: Record<string, unknown>,
): Promise<any> { ): Promise<any> {
const profile = getFanavaranClientProfile(clientKey); const profile = getFanavaranClientProfile(clientKey);
const claimCase = await this.claimCaseDbService.findById(claimCaseId); const claimCase = await this.claimCaseDbService.findById(claimCaseId);
@@ -5652,10 +5845,11 @@ export class ClaimRequestManagementService {
); );
} }
const payload = this.buildFanavaranDamageCasePayload({ const payload = bodyOverride ?? await this.buildFanavaranDamageCasePayload({
claimCase, claimCase,
blameCase, blameCase,
selectedParts: selectedParts ?? claimCase.damage?.selectedParts ?? [], selectedParts: selectedParts ?? claimCase.damage?.selectedParts ?? [],
clientKey,
defaults: profile.defaults, defaults: profile.defaults,
}); });
const url = `${this.FANAVARAN_SUBMIT_URL}/${claimCase.claimId}/dmg-cases`; const url = `${this.FANAVARAN_SUBMIT_URL}/${claimCase.claimId}/dmg-cases`;
@@ -6059,6 +6253,7 @@ export class ClaimRequestManagementService {
private async executeFanavaranV2Submit( private async executeFanavaranV2Submit(
claimCaseId: string, claimCaseId: string,
clientKey: FanavaranClientKey, clientKey: FanavaranClientKey,
bodyOverride?: Record<string, unknown>,
): Promise<any> { ): Promise<any> {
const profile = getFanavaranClientProfile(clientKey); const profile = getFanavaranClientProfile(clientKey);
const logPrefix = `[Fanavaran ${clientKey} V2]`; const logPrefix = `[Fanavaran ${clientKey} V2]`;
@@ -6066,7 +6261,7 @@ export class ClaimRequestManagementService {
this.logger.log( this.logger.log(
`${logPrefix} Starting submission for claimCaseId: ${claimCaseId}`, `${logPrefix} Starting submission for claimCaseId: ${claimCaseId}`,
); );
const fanavaranData = await this.previewFanavaranSubmitV2( const fanavaranData = bodyOverride ?? await this.previewFanavaranSubmitV2(
claimCaseId, claimCaseId,
clientKey, clientKey,
); );

View File

@@ -66,6 +66,16 @@ export const FANAVARAN_REMOTE_LOOKUPS: FanavaranRemoteLookupDefinition[] = [
url: `${FANAVARAN_LOOKUP_BASE_URL}/car/code-list/expert-status`, url: `${FANAVARAN_LOOKUP_BASE_URL}/car/code-list/expert-status`,
cacheFile: "expert-status.json", cacheFile: "expert-status.json",
}, },
{
name: "vehicle-kinds",
url: `${FANAVARAN_LOOKUP_BASE_URL}/car/base-info/vehicle-kinds`,
cacheFile: "vehicle-kinds.json",
},
{
name: "person-role",
url: `${FANAVARAN_LOOKUP_BASE_URL}/common/code-list/person-role`,
cacheFile: "person-role.json",
},
]; ];
export const TEJARAT_STATIC_ACCIDENT_FILES = { export const TEJARAT_STATIC_ACCIDENT_FILES = {

View File

@@ -14,6 +14,7 @@ import {
type FanavaranClientKey, type FanavaranClientKey,
} from "src/core/config/fanavaran-client.config"; } from "src/core/config/fanavaran-client.config";
import { import {
FANAVARAN_LOOKUP_BASE_URL,
fanavaranLookupCacheDir, fanavaranLookupCacheDir,
tejaratStaticAccidentFilePath, tejaratStaticAccidentFilePath,
} from "./fanavaran-lookup.config"; } from "./fanavaran-lookup.config";
@@ -246,6 +247,32 @@ export class FanavaranLookupService {
} }
} }
async inquiryByVin(
clientKey: FanavaranClientKey,
vin: string,
): Promise<unknown> {
const url = `${FANAVARAN_LOOKUP_BASE_URL}/car/vehicles/inquiry-by-vin?vin=${encodeURIComponent(vin)}`;
return this.fetchFromFanavaran(clientKey, url);
}
async inquiryByUniqueIdentifier(
clientKey: FanavaranClientKey,
params: {
nationalCode: string;
birthYear: number;
birthMonth: number;
birthDay: number;
},
): Promise<unknown> {
const url =
`${FANAVARAN_LOOKUP_BASE_URL}/common/parties/inquiry-by-unique-identifier` +
`?NationalCode=${encodeURIComponent(params.nationalCode)}` +
`&BirthYear=${params.birthYear}` +
`&BirthMonth=${params.birthMonth}` +
`&BirthDay=${params.birthDay}`;
return this.fetchFromFanavaran(clientKey, url);
}
mapFanavaranAccidentCausesToReasonOptions( mapFanavaranAccidentCausesToReasonOptions(
causes: unknown, causes: unknown,
): { id: number; label: string; fanavaran: number }[] { ): { id: number; label: string; fanavaran: number }[] {

View File

@@ -1,5 +1,6 @@
import { import {
BadRequestException, BadRequestException,
Body,
Controller, Controller,
Get, Get,
Param, Param,
@@ -105,11 +106,13 @@ export class FanavaranController {
async submit( async submit(
@Param("client") client: string, @Param("client") client: string,
@Param("claimCaseId") claimCaseId: string, @Param("claimCaseId") claimCaseId: string,
@Body() body?: Record<string, unknown>,
) { ) {
const clientKey = this.parseClientParam(client); const clientKey = this.parseClientParam(client);
return await this.claimRequestManagementService.submitFanavaranV2( return await this.claimRequestManagementService.submitFanavaranV2(
claimCaseId, claimCaseId,
clientKey, clientKey,
body && Object.keys(body).length > 0 ? body : undefined,
); );
} }
@@ -157,11 +160,13 @@ export class FanavaranController {
async submitDamageCase( async submitDamageCase(
@Param("client") client: string, @Param("client") client: string,
@Param("claimCaseId") claimCaseId: string, @Param("claimCaseId") claimCaseId: string,
@Body() body?: Record<string, unknown>,
) { ) {
const clientKey = this.parseClientParam(client); const clientKey = this.parseClientParam(client);
return await this.claimRequestManagementService.submitFanavaranDamageCaseV2( return await this.claimRequestManagementService.submitFanavaranDamageCaseV2(
claimCaseId, claimCaseId,
clientKey, clientKey,
body && Object.keys(body).length > 0 ? body : undefined,
); );
} }
@@ -261,11 +266,13 @@ export class FanavaranController {
async submitExpertise( async submitExpertise(
@Param("client") client: string, @Param("client") client: string,
@Param("claimCaseId") claimCaseId: string, @Param("claimCaseId") claimCaseId: string,
@Body() body?: Record<string, unknown>,
) { ) {
const clientKey = this.parseClientParam(client); const clientKey = this.parseClientParam(client);
return await this.claimRequestManagementService.submitFanavaranExpertiseV2( return await this.claimRequestManagementService.submitFanavaranExpertiseV2(
claimCaseId, claimCaseId,
clientKey, clientKey,
body && Object.keys(body).length > 0 ? body : undefined,
); );
} }

View File

@@ -1,8 +1,9 @@
import { Controller, Get, Param } from "@nestjs/common"; import { Controller, Get, Param, Query } from "@nestjs/common";
import { import {
ApiOkResponse, ApiOkResponse,
ApiOperation, ApiOperation,
ApiParam, ApiParam,
ApiQuery,
ApiTags, ApiTags,
} from "@nestjs/swagger"; } from "@nestjs/swagger";
import { LookupsService } from "./lookups.service"; import { LookupsService } from "./lookups.service";
@@ -171,6 +172,63 @@ export class LookupsController {
return await this.lookupsService.getExpertStatus(); return await this.lookupsService.getExpertStatus();
} }
@Get("vehicle-kinds")
@ApiOperation({
summary: "Fanavaran GEN.12 vehicle kind lookup",
description:
"Returns values for damage case payload field VehicleKindId from car/base-info/vehicle-kinds.",
})
@ApiOkResponse({
description: "Returns Fanavaran vehicle kinds lookup data",
schema: { type: "array", items: { type: "object" } },
})
async getVehicleKinds() {
return await this.lookupsService.getVehicleKinds();
}
@Get("person-role")
@ApiOperation({
summary: "Fanavaran person role lookup",
description:
"Returns person role codes from common/code-list/person-role.",
})
@ApiOkResponse({
description: "Returns Fanavaran person role lookup data",
schema: {
type: "array",
items: {
type: "object",
properties: {
Caption: { type: "string" },
Id: { type: "number" },
IsActive: { type: "number" },
},
},
},
})
async getPersonRole() {
return await this.lookupsService.getPersonRole();
}
@Get("inquiry-by-vin")
@ApiOperation({
summary: "Fanavaran vehicle inquiry by VIN",
description:
"Returns vehicle details from Fanavaran for the given VIN number via car/vehicles/inquiry-by-vin.",
})
@ApiQuery({
name: "vin",
description: "Vehicle Identification Number (VIN)",
example: "IRNKAEK4150012345",
})
@ApiOkResponse({
description: "Returns Fanavaran vehicle inquiry data for the VIN",
schema: { type: "object" },
})
async inquiryByVin(@Query("vin") vin: string) {
return await this.lookupsService.inquiryByVin(vin);
}
@Get("fanavaran") @Get("fanavaran")
@ApiOperation({ @ApiOperation({
summary: "List configured Fanavaran remote lookups", summary: "List configured Fanavaran remote lookups",

View File

@@ -115,6 +115,19 @@ export class LookupsService {
return await this.getClientRemoteLookup("expert-status"); 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 inquiryByVin(vin: string): Promise<unknown> {
const clientKey = this.activeClientKey();
return this.fanavaranLookupService.inquiryByVin(clientKey, vin);
}
async getAccidentWay(): Promise<{ id: number; label: string }[]> { async getAccidentWay(): Promise<{ id: number; label: string }[]> {
const clientKey = this.activeClientKey(); const clientKey = this.activeClientKey();
const fileName = TEJARAT_STATIC_ACCIDENT_FILES.accidentWay; const fileName = TEJARAT_STATIC_ACCIDENT_FILES.accidentWay;