Implemented CAR_BODY fanavaran inquiry

This commit is contained in:
SepehrYahyaee
2026-09-06 14:11:32 +03:30
parent 4d2501d90c
commit ef9768795d
8 changed files with 470 additions and 64 deletions

View File

@@ -79,14 +79,44 @@ export class Insurance {
@Prop({ type: [String] })
coverages?: string[];
/** CAR_BODY only: mocked car-body insurance inquiry result */
/** CAR_BODY inquiry result; raw provider data is retained in vehicle.inquiry.carBody.raw. */
@Prop({ type: MongooseSchema.Types.Mixed })
carBodyInsurance?: {
policyNumber?: string;
policyId?: number;
contractId?: number;
startDate?: string;
endDate?: string;
insurerCompany?: string;
coverages?: string[];
companyId?: number | string;
companyName?: string;
insurerName?: string;
insurerNationalCode?: string;
ownerNationalCode?: string;
ownerName?: string;
customerName?: string;
customerLastName?: string;
customerFatherName?: string;
customerMobile?: string;
customerAddress?: string;
customerPostalCode?: string;
chassisNumber?: string;
vin?: string;
motorNumber?: string;
vehicleGroup?: string;
vehicleSystem?: string;
vehicleKind?: string;
builtYear?: number;
cylinderCount?: number;
passengerCount?: number;
usage?: string;
issueDate?: string;
vehicleValue?: number;
totalPremium?: number;
noLossYearsCount?: number;
lossDocuments?: unknown[];
hasEndorsement?: boolean;
};
}
export const InsuranceSchema = SchemaFactory.createForClass(Insurance);
@@ -183,4 +213,4 @@ export class Party {
@Prop({ type: PartyConfirmationSchema })
confirmation?: PartyConfirmation;
}
export const PartySchema = SchemaFactory.createForClass(Party);
export const PartySchema = SchemaFactory.createForClass(Party);

View File

@@ -1,5 +1,5 @@
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Types } from "mongoose";
import { Schema as MongooseSchema, Types } from "mongoose";
import {
ResendFirstPartyDto,
ResendSecondPartyDto,
@@ -79,6 +79,13 @@ export class CarBodyInsuranceDetail {
@Prop({ type: [String] })
coverages?: string[];
/** Complete provider payload, retained for audit and future field mapping. */
@Prop({ type: MongooseSchema.Types.Mixed })
raw?: unknown;
@Prop()
source?: string;
}
export class SecondPartyFile {

View File

@@ -1513,7 +1513,7 @@ export class RequestManagementService {
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
let carBodyInfo: any;
try {
carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry(
carBodyInfo = await this.sandHubService.getCarBodyInquiry(
{
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate,
@@ -1523,13 +1523,13 @@ export class RequestManagementService {
: inquiryOptions,
);
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, {
source: "TEJARAT_CAR_BODY_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
});
} catch (err: any) {
this.logger.error(
`[TEJARAT] car body inquiry failed for request=${req._id}: ${err?.message || err}`,
`[CAR_BODY] inquiry failed for request=${req._id}: ${err?.message || err}`,
);
this.recordPartyCaseInquiryStatus(
req,
@@ -1552,7 +1552,7 @@ export class RequestManagementService {
party.vehicle.inquiry = {
...party.vehicle.inquiry,
carBody: {
source: "TEJARAT_CAR_BODY_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
},
@@ -1562,19 +1562,35 @@ export class RequestManagementService {
const m = carBodyInfo.mapped;
(party.insurance as any).carBodyInsurance = {
policyNumber: m.policyNumber ?? null,
policyId: m.policyId ?? null,
contractId: m.contractId ?? null,
companyId: m.companyId ?? null,
companyName: m.CompanyName ?? null,
insurerName: m.insurerName ?? null,
insurerNationalCode: m.insurerNationalCode ?? null,
ownerNationalCode: m.ownerNationalCode ?? null,
ownerName: m.ownerName ?? null,
customerName: m.customerName ?? null,
customerLastName: m.customerLastName ?? null,
customerFatherName: m.customerFatherName ?? null,
customerMobile: m.customerMobile ?? null,
customerAddress: m.customerAddress ?? null,
customerPostalCode: m.customerPostalCode ?? null,
chassisNumber: m.ChassisNumberField ?? null,
vin: m.VinNumberField ?? null,
motorNumber: m.EngineNumberField ?? null,
vehicleGroup: m.vehicleGroupTitle ?? null,
vehicleSystem: m.vehicleSystemTitle ?? null,
vehicleKind: m.vehicleKind ?? null,
builtYear: m.builtYear ?? null,
cylinderCount: m.cylinderCount ?? null,
passengerCount: m.passengerCount ?? null,
usage: m.usage ?? null,
startDate: m.StartDate ?? null,
endDate: m.EndDate ?? null,
issueDate: m.IssueDate ?? null,
vehicleValue: m.vehicleValue ?? null,
totalPremium: m.totalPremium ?? null,
noLossYearsCount: m.noLossYearsCount ?? null,
lossDocuments: m.lossDocuments ?? [],
hasEndorsement: m.hasEndorsement ?? null,
@@ -3006,13 +3022,15 @@ export class RequestManagementService {
sandHubReport.EndDate,
};
// For CAR_BODY type, also fetch and persist mocked car body insurance info
// For CAR_BODY type, persist the provider response and its mapped fields.
if (request.type === "CAR_BODY" && partyType === "firstParty") {
const carBodyInfo = await this.mockCarBodyInsuranceInquiry(
request._id,
body.plate,
body.nationalCodeOfInsurer,
const carBodyInquiry = await this.sandHubService.getCarBodyInquiry(
{
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate,
} as any,
);
const carBodyInfo = carBodyInquiry.mapped as any;
this.logger.log(
`[CAR_BODY] Saving car body insurance data to blame file ${request._id}:`,
@@ -3035,6 +3053,12 @@ export class RequestManagementService {
setFields[
"firstPartyDetails.firstPartyCarBodyInsuranceDetail.coverages"
] = carBodyInfo.coverages;
setFields[
"firstPartyDetails.firstPartyCarBodyInsuranceDetail.raw"
] = carBodyInquiry.raw;
setFields[
"firstPartyDetails.firstPartyCarBodyInsuranceDetail.source"
] = carBodyInquiry.source;
}
// Build final update payload with proper MongoDB operators
@@ -4423,40 +4447,6 @@ export class RequestManagementService {
return { message: "Update saved successfully." };
}
// Mocked CAR_BODY insurance inquiry – replace with real external API later
private async mockCarBodyInsuranceInquiry(
requestId: string,
plate: any,
nationalCodeOfInsurer: string,
): Promise<{
policyNumber: string;
startDate: string;
endDate: string;
insurerCompany: string;
coverages: string[];
}> {
this.logger.log(
`[CAR_BODY] Mocking car body insurance inquiry for request ${requestId} (plate=${JSON.stringify(
plate,
)}, nationalCodeOfInsurer=${nationalCodeOfInsurer})`,
);
const today = new Date();
const oneYearLater = new Date(
today.getFullYear() + 1,
today.getMonth(),
today.getDate(),
);
return {
policyNumber: "CB-MOCK-123456",
startDate: today.toISOString().slice(0, 10),
endDate: oneYearLater.toISOString().slice(0, 10),
insurerCompany: "Mock Car Body Insurance Co.",
coverages: ["آتش‌سوزی", "سرقت", "بدنه کامل"],
};
}
private async processResendUploads(
files: { [key: string]: Express.Multer.File[] },
requestId: string,
@@ -6325,17 +6315,21 @@ export class RequestManagementService {
});
}
const carBodyInfo = await this.mockCarBodyInsuranceInquiry(
requestId,
firstPartyPlate.plate,
firstPartyPlate.nationalCodeOfInsurer,
);
const carBodyInquiry = await this.sandHubService.getCarBodyInquiry({
nationalCodeOfInsurer: firstPartyPlate.nationalCodeOfInsurer,
plate: firstPartyPlate.plate,
} as any);
const carBodyInfo = carBodyInquiry.mapped as any;
this.recordPartyCaseInquiryStatus(
req,
"carBody",
PartyRole.FIRST,
true,
carBodyInfo,
{
source: carBodyInquiry.source,
raw: carBodyInquiry.raw,
mapped: carBodyInfo,
},
);
const firstParty: any = {
@@ -6364,7 +6358,14 @@ export class RequestManagementService {
model: sandHubReport?.MapTypNam,
type: `${sandHubReport?.UsageField || ""} / ${sandHubReport?.MapUsageName || "-"}`,
isNew: firstPartyPlate.isNewCar,
inquiry: sandHubReport,
inquiry: {
...sandHubReport,
carBody: {
source: carBodyInquiry.source,
raw: carBodyInquiry.raw,
mapped: carBodyInfo,
},
},
},
insurance: {
policyNumber:
@@ -6381,6 +6382,8 @@ export class RequestManagementService {
endDate: carBodyInfo.endDate,
insurerCompany: carBodyInfo.insurerCompany,
coverages: carBodyInfo.coverages,
raw: carBodyInquiry.raw,
source: carBodyInquiry.source,
},
},
statement: {
@@ -7585,11 +7588,11 @@ export class RequestManagementService {
};
// CAR_BODY specific insurance info
const carBodyInfo = await this.mockCarBodyInsuranceInquiry(
request._id.toString(),
firstPartyPlate.plate,
firstPartyPlate.nationalCodeOfInsurer,
);
const carBodyInquiry = await this.sandHubService.getCarBodyInquiry({
nationalCodeOfInsurer: firstPartyPlate.nationalCodeOfInsurer,
plate: firstPartyPlate.plate,
} as any);
const carBodyInfo = carBodyInquiry.mapped as any;
firstPartyDetails.firstPartyCarBodyInsuranceDetail = {
policyNumber: carBodyInfo.policyNumber,
@@ -7597,6 +7600,8 @@ export class RequestManagementService {
endDate: carBodyInfo.endDate,
insurerCompany: carBodyInfo.insurerCompany,
coverages: carBodyInfo.coverages,
raw: carBodyInquiry.raw,
source: carBodyInquiry.source,
};
// Update the firstPartyDetails in the payload with all plate data
@@ -8808,7 +8813,7 @@ export class RequestManagementService {
partyRole === PartyRole.FIRST
) {
try {
const carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry(
const carBodyInfo = await this.sandHubService.getCarBodyInquiry(
{
nationalCodeOfInsurer: partyData.nationalCodeOfInsurer,
plate: partyData.plate as any,
@@ -8816,14 +8821,14 @@ export class RequestManagementService {
clientId ? { clientId } : undefined,
);
this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, {
source: "TEJARAT_CAR_BODY_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
});
party.vehicle.inquiry = {
...party.vehicle.inquiry,
carBody: {
source: "TEJARAT_CAR_BODY_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
},
@@ -8831,8 +8836,38 @@ export class RequestManagementService {
const m = carBodyInfo.mapped;
(party.insurance as any).carBodyInsurance = {
policyNumber: m.policyNumber ?? null,
policyId: m.policyId ?? null,
contractId: m.contractId ?? null,
companyId: m.companyId ?? null,
companyName: m.CompanyName ?? null,
insurerName: m.insurerName ?? null,
insurerNationalCode: m.insurerNationalCode ?? null,
ownerNationalCode: m.ownerNationalCode ?? null,
ownerName: m.ownerName ?? null,
customerName: m.customerName ?? null,
customerLastName: m.customerLastName ?? null,
customerFatherName: m.customerFatherName ?? null,
customerMobile: m.customerMobile ?? null,
customerAddress: m.customerAddress ?? null,
customerPostalCode: m.customerPostalCode ?? null,
chassisNumber: m.ChassisNumberField ?? null,
vin: m.VinNumberField ?? null,
motorNumber: m.EngineNumberField ?? null,
vehicleGroup: m.vehicleGroupTitle ?? null,
vehicleSystem: m.vehicleSystemTitle ?? null,
vehicleKind: m.vehicleKind ?? null,
builtYear: m.builtYear ?? null,
cylinderCount: m.cylinderCount ?? null,
passengerCount: m.passengerCount ?? null,
usage: m.usage ?? null,
startDate: m.StartDate ?? null,
endDate: m.EndDate ?? null,
issueDate: m.IssueDate ?? null,
vehicleValue: m.vehicleValue ?? null,
totalPremium: m.totalPremium ?? null,
noLossYearsCount: m.noLossYearsCount ?? null,
lossDocuments: m.lossDocuments ?? [],
hasEndorsement: m.hasEndorsement ?? null,
};
const cbCompanyCode = m.companyId ?? m.CompanyCode;
const cbCompanyName = m.CompanyName ?? m.companyPersianName;
@@ -9633,7 +9668,7 @@ export class RequestManagementService {
partyRole === PartyRole.FIRST
) {
try {
const carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry(
const carBodyInfo = await this.sandHubService.getCarBodyInquiry(
{
nationalCodeOfInsurer: partyData.nationalCodeOfInsurer,
plate: partyData.vin as any, // VIN used as identifier for CAR_BODY
@@ -9641,14 +9676,14 @@ export class RequestManagementService {
clientId ? { clientId } : undefined,
);
this.recordPartyCaseInquiryStatus(req, "carBody", partyRole, true, {
source: "TEJARAT_CAR_BODY_VIN_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
});
party.vehicle.inquiry = {
...party.vehicle.inquiry,
carBody: {
source: "TEJARAT_CAR_BODY_VIN_INQUIRY",
source: carBodyInfo.source,
raw: carBodyInfo.raw,
mapped: carBodyInfo.mapped,
},
@@ -9656,8 +9691,38 @@ export class RequestManagementService {
const m = carBodyInfo.mapped;
(party.insurance as any).carBodyInsurance = {
policyNumber: m.policyNumber ?? null,
policyId: m.policyId ?? null,
contractId: m.contractId ?? null,
companyId: m.companyId ?? null,
companyName: m.CompanyName ?? null,
insurerName: m.insurerName ?? null,
insurerNationalCode: m.insurerNationalCode ?? null,
ownerNationalCode: m.ownerNationalCode ?? null,
ownerName: m.ownerName ?? null,
customerName: m.customerName ?? null,
customerLastName: m.customerLastName ?? null,
customerFatherName: m.customerFatherName ?? null,
customerMobile: m.customerMobile ?? null,
customerAddress: m.customerAddress ?? null,
customerPostalCode: m.customerPostalCode ?? null,
chassisNumber: m.ChassisNumberField ?? null,
vin: m.VinNumberField ?? null,
motorNumber: m.EngineNumberField ?? null,
vehicleGroup: m.vehicleGroupTitle ?? null,
vehicleSystem: m.vehicleSystemTitle ?? null,
vehicleKind: m.vehicleKind ?? null,
builtYear: m.builtYear ?? null,
cylinderCount: m.cylinderCount ?? null,
passengerCount: m.passengerCount ?? null,
usage: m.usage ?? null,
startDate: m.StartDate ?? null,
endDate: m.EndDate ?? null,
issueDate: m.IssueDate ?? null,
vehicleValue: m.vehicleValue ?? null,
totalPremium: m.totalPremium ?? null,
noLossYearsCount: m.noLossYearsCount ?? null,
lossDocuments: m.lossDocuments ?? [],
hasEndorsement: m.hasEndorsement ?? null,
};
const cbCompanyCode = m.companyId ?? m.CompanyCode;
const cbCompanyName = m.CompanyName ?? m.companyPersianName;