forked from Yara724/api
Merge pull request 'Fix addClient bug' (#109) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#109
This commit is contained in:
@@ -99,19 +99,34 @@ export class ClientService {
|
||||
try {
|
||||
const newClient = await this.clientDbService.create({
|
||||
clientCode: client.clientCode,
|
||||
|
||||
clientName: {
|
||||
persian: client.clientName.persian,
|
||||
english: client.clientName.english || null,
|
||||
persian:
|
||||
typeof client.clientName === "string"
|
||||
? client.clientName
|
||||
: client.clientName?.persian,
|
||||
|
||||
english:
|
||||
typeof client.clientName === "string"
|
||||
? null
|
||||
: (client.clientName?.english ?? null),
|
||||
},
|
||||
|
||||
property: {
|
||||
smsApiKey: client.property.smsApiKey || null,
|
||||
smsApiKey: client.property?.smsApiKey ?? null,
|
||||
},
|
||||
useExpertMode: client.useExpertMode || null,
|
||||
|
||||
useExpertMode: client.useExpertMode ?? null,
|
||||
});
|
||||
if (newClient) return new ClientDtoRs(newClient);
|
||||
else throw new GoneException("database not connected");
|
||||
|
||||
if (!newClient) {
|
||||
throw new GoneException("database not connected");
|
||||
}
|
||||
|
||||
return new ClientDtoRs(newClient);
|
||||
} catch (er) {
|
||||
throw new BadGatewayException(er.errors);
|
||||
console.error("ADD CLIENT ERROR:", er);
|
||||
throw er;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { ApiProperty } from "@nestjs/swagger";
|
||||
import { IsIn, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator";
|
||||
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
|
||||
import {
|
||||
IsIn,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsOptional,
|
||||
IsString,
|
||||
ValidateNested,
|
||||
} from "class-validator";
|
||||
import { Type } from "class-transformer";
|
||||
import { Types } from "mongoose";
|
||||
|
||||
@@ -15,9 +22,8 @@ class ClientName {
|
||||
english: string;
|
||||
}
|
||||
class Property {
|
||||
@ApiProperty({})
|
||||
@ApiPropertyOptional({})
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
smsApiKey: string;
|
||||
}
|
||||
|
||||
|
||||
@@ -945,354 +945,375 @@ export class RequestManagementService {
|
||||
}
|
||||
|
||||
async initialFormV2(requestId: string, body: AddPlateDto, user: any) {
|
||||
const req = await this.blameRequestDbService.findById(requestId);
|
||||
if (!req) {
|
||||
throw new NotFoundException("Request not found");
|
||||
}
|
||||
try {
|
||||
const req = await this.blameRequestDbService.findById(requestId);
|
||||
if (!req) {
|
||||
throw new NotFoundException("Request not found");
|
||||
}
|
||||
|
||||
if (!req.workflow?.currentStep) {
|
||||
throw new BadRequestException("Request workflow is not initialized");
|
||||
}
|
||||
if (!req.workflow?.currentStep) {
|
||||
throw new BadRequestException("Request workflow is not initialized");
|
||||
}
|
||||
|
||||
const stepKey = req.workflow.currentStep as WorkflowStep;
|
||||
if (
|
||||
stepKey !== WorkflowStep.FIRST_INITIAL_FORM &&
|
||||
stepKey !== WorkflowStep.SECOND_INITIAL_FORM
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
`Invalid step. Expected FIRST_INITIAL_FORM or SECOND_INITIAL_FORM but got ${stepKey}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Detect which party from step
|
||||
const role = this.stepKeyToPartyRole(stepKey);
|
||||
const idx = this.getPartyIndex(req, role);
|
||||
if (idx === -1) {
|
||||
throw new BadRequestException(`${role} party not found on request`);
|
||||
}
|
||||
|
||||
const party = req.parties[idx];
|
||||
this.assertPartyOwner(
|
||||
party,
|
||||
user,
|
||||
`Only ${role} party can submit this step`,
|
||||
);
|
||||
|
||||
// Set userId for party if not already set (important for second party)
|
||||
if (!party.person) party.person = {} as any;
|
||||
if (!party.person.userId && user?.sub) {
|
||||
party.person.userId = Types.ObjectId.isValid(user.sub)
|
||||
? new Types.ObjectId(user.sub)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
// Validation: driver/insurer sameness rules
|
||||
if (body.driverIsInsurer === false) {
|
||||
const stepKey = req.workflow.currentStep as WorkflowStep;
|
||||
if (
|
||||
body.nationalCodeOfInsurer === body.nationalCodeOfDriver ||
|
||||
body.insurerLicense === body.driverLicense
|
||||
stepKey !== WorkflowStep.FIRST_INITIAL_FORM &&
|
||||
stepKey !== WorkflowStep.SECOND_INITIAL_FORM
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"Insurer and Driver should be two different persons in this mode.",
|
||||
`Invalid step. Expected FIRST_INITIAL_FORM or SECOND_INITIAL_FORM but got ${stepKey}`,
|
||||
);
|
||||
}
|
||||
} else if (body.driverIsInsurer === true) {
|
||||
const sameNat = body.nationalCodeOfInsurer === body.nationalCodeOfDriver;
|
||||
const sameLic = body.insurerLicense === body.driverLicense;
|
||||
const sameBirthday =
|
||||
body.driverBirthday == null ||
|
||||
String(body.driverBirthday) === String(body.insurerBirthday);
|
||||
if (!sameNat || !sameLic || !sameBirthday) {
|
||||
throw new BadRequestException(
|
||||
"When driverIsInsurer is true, insurer and driver data must be the same.",
|
||||
);
|
||||
|
||||
// Detect which party from step
|
||||
const role = this.stepKeyToPartyRole(stepKey);
|
||||
const idx = this.getPartyIndex(req, role);
|
||||
if (idx === -1) {
|
||||
throw new BadRequestException(`${role} party not found on request`);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- External inquiry 1: Tejarat block inquiry ----
|
||||
let inquiryRaw: any;
|
||||
let inquiryMapped: any;
|
||||
try {
|
||||
const inquiry = await this.sandHubService.getTejaratBlockInquiry({
|
||||
plate: body.plate,
|
||||
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
|
||||
});
|
||||
inquiryRaw = inquiry.raw;
|
||||
inquiryMapped = inquiry.mapped;
|
||||
this.logger.log(
|
||||
`[TEJARAT] block inquiry raw for request=${req._id}: ${JSON.stringify(inquiryRaw)}`,
|
||||
const party = req.parties[idx];
|
||||
this.assertPartyOwner(
|
||||
party,
|
||||
user,
|
||||
`Only ${role} party can submit this step`,
|
||||
);
|
||||
this.logger.log(
|
||||
`[TEJARAT] block inquiry mapped for request=${req._id}: ${JSON.stringify(inquiryMapped)}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, true, {
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
});
|
||||
} catch (err: any) {
|
||||
this.logger.error(
|
||||
`[TEJARAT] block inquiry failed for request=${req._id}: ${err?.message || err}`,
|
||||
);
|
||||
if (err?.response) {
|
||||
this.logger.error(
|
||||
`[TEJARAT] block inquiry response for request=${req._id}: status=${
|
||||
err.response.status
|
||||
}, data=${JSON.stringify(err.response.data)}`,
|
||||
);
|
||||
|
||||
// Set userId for party if not already set (important for second party)
|
||||
if (!party.person) party.person = {} as any;
|
||||
if (!party.person.userId && user?.sub) {
|
||||
party.person.userId = Types.ObjectId.isValid(user.sub)
|
||||
? new Types.ObjectId(user.sub)
|
||||
: undefined;
|
||||
}
|
||||
this.recordPartyCaseInquiryStatus(
|
||||
req,
|
||||
"thirdParty",
|
||||
role,
|
||||
false,
|
||||
{},
|
||||
err,
|
||||
);
|
||||
await (req as any).save();
|
||||
throw new HttpException("Inquiry failed", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (inquiryMapped?.Error) {
|
||||
this.logger.warn(
|
||||
`[TEJARAT] block inquiry error for request=${req._id}: ${JSON.stringify(
|
||||
inquiryMapped.Error,
|
||||
)}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, false, {
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
});
|
||||
await (req as any).save();
|
||||
throw new HttpException(
|
||||
inquiryMapped.Error.Message || "Inquiry returned error",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
// Validation: driver/insurer sameness rules
|
||||
if (body.driverIsInsurer === false) {
|
||||
if (
|
||||
body.nationalCodeOfInsurer === body.nationalCodeOfDriver ||
|
||||
body.insurerLicense === body.driverLicense
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"Insurer and Driver should be two different persons in this mode.",
|
||||
);
|
||||
}
|
||||
} else if (body.driverIsInsurer === true) {
|
||||
const sameNat =
|
||||
body.nationalCodeOfInsurer === body.nationalCodeOfDriver;
|
||||
const sameLic = body.insurerLicense === body.driverLicense;
|
||||
const sameBirthday =
|
||||
body.driverBirthday == null ||
|
||||
String(body.driverBirthday) === String(body.insurerBirthday);
|
||||
if (!sameNat || !sameLic || !sameBirthday) {
|
||||
throw new BadRequestException(
|
||||
"When driverIsInsurer is true, insurer and driver data must be the same.",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- External inquiry 2: personal identity check (insurer/driver nationalCode + birthDate) ----
|
||||
// The form sends the birthday as a Jalali date in any of these shapes:
|
||||
// - number 13770624 (packed YYYYMMDD)
|
||||
// - string "1377-06-24" / "1377/06/24" / "13770624"
|
||||
// We forward it as-is; sandHubService.getPersonalInquiry() handles the
|
||||
// Jalali → Gregorian conversion required by the external API.
|
||||
const personalNationalCode =
|
||||
body.nationalCodeOfInsurer || body.nationalCodeOfDriver;
|
||||
const personalBirthDate: number | string | null = (body.insurerBirthday ??
|
||||
body.driverBirthday ??
|
||||
null) as number | string | null;
|
||||
if (
|
||||
!personalNationalCode ||
|
||||
personalBirthDate === null ||
|
||||
personalBirthDate === undefined ||
|
||||
String(personalBirthDate).trim() === ""
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"Valid nationalCode and birthDate are required for personal inquiry.",
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const personalInquiry = await this.sandHubService.getPersonalInquiry(
|
||||
personalNationalCode,
|
||||
personalBirthDate,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(
|
||||
req,
|
||||
"person",
|
||||
role,
|
||||
true,
|
||||
personalInquiry,
|
||||
);
|
||||
this.logger.log(
|
||||
`[SANDHUB] personal inquiry success request=${req._id} nationalCode=${personalNationalCode}: ${JSON.stringify(
|
||||
personalInquiry,
|
||||
)}`,
|
||||
);
|
||||
} catch (err: any) {
|
||||
this.logger.error(
|
||||
`[SANDHUB] personal inquiry failed request=${req._id} nationalCode=${personalNationalCode}: ${err?.message || err}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "person", role, false, {}, err);
|
||||
await (req as any).save();
|
||||
throw new HttpException(
|
||||
"Personal identity inquiry failed",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// ---- External inquiry 3: driving license check (insurerLicense + nationalCode) ----
|
||||
// const licenseNationalCode = body.nationalCodeOfInsurer || body.nationalCodeOfDriver;
|
||||
// const licenseNumber = body.insurerLicense;
|
||||
// if (!licenseNationalCode || !licenseNumber) {
|
||||
// throw new BadRequestException(
|
||||
// "nationalCode and insurerLicense are required for driving license inquiry.",
|
||||
// );
|
||||
// }
|
||||
// try {
|
||||
// const licenseInquiry = await this.sandHubService.getDrivingLicenseInfo(
|
||||
// licenseNationalCode,
|
||||
// licenseNumber,
|
||||
// );
|
||||
// this.logger.log(
|
||||
// `[SANDHUB] license inquiry success request=${req._id} nationalCode=${licenseNationalCode}: ${JSON.stringify(
|
||||
// licenseInquiry,
|
||||
// )}`,
|
||||
// );
|
||||
// } catch (err: any) {
|
||||
// this.logger.error(
|
||||
// `[SANDHUB] license inquiry failed request=${req._id} nationalCode=${licenseNationalCode}: ${err?.message || err}`,
|
||||
// );
|
||||
// throw new HttpException(
|
||||
// "Driving license inquiry failed",
|
||||
// HttpStatus.BAD_REQUEST,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Find client by company code
|
||||
const clientName = inquiryMapped?.CompanyName;
|
||||
const companyCode = inquiryMapped?.CompanyCode;
|
||||
const client =
|
||||
await this.clientService.findClientWithCompanyCode(+companyCode);
|
||||
|
||||
if (!client) {
|
||||
await this.clientService.addClient({
|
||||
clientName,
|
||||
clientCode: companyCode,
|
||||
useExpertMode: "legal",
|
||||
});
|
||||
}
|
||||
|
||||
// if (!client) {
|
||||
// throw new HttpException("Client not found", HttpStatus.CONFLICT);
|
||||
// }
|
||||
|
||||
// Persist inquiry/body data into new model
|
||||
if (!party.person) party.person = {} as any;
|
||||
const resolvedClientId = (client as any)?._id ?? (client as any)?._doc?._id;
|
||||
party.person.clientId = resolvedClientId;
|
||||
party.person.nationalCodeOfInsurer = body.nationalCodeOfInsurer;
|
||||
party.person.nationalCodeOfDriver = body.nationalCodeOfDriver;
|
||||
party.person.insurerLicense = body.insurerLicense;
|
||||
party.person.driverLicense = body.driverLicense;
|
||||
party.person.driverIsInsurer = body.driverIsInsurer;
|
||||
party.person.isNewCar = body.isNewCar;
|
||||
party.person.userNoCertificate = body.userNoCertificate;
|
||||
party.person.insurerBirthday = body.insurerBirthday;
|
||||
party.person.driverBirthday =
|
||||
body.driverBirthday ??
|
||||
(body.driverIsInsurer ? String(body.insurerBirthday) : null);
|
||||
|
||||
if (!party.vehicle) party.vehicle = {} as any;
|
||||
party.vehicle.isNew = body.isNewCar;
|
||||
party.vehicle.plateId =
|
||||
typeof body.plateId === "string"
|
||||
? body.plateId
|
||||
: this.plateToPlateIdString(body.plate);
|
||||
party.vehicle.name = inquiryMapped?.MapTypNam;
|
||||
party.vehicle.type = `${inquiryMapped?.UsageField} / ${inquiryMapped?.MapUsageName || "-"}`;
|
||||
party.vehicle.inquiry = {
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
};
|
||||
|
||||
if (!party.insurance) party.insurance = {} as any;
|
||||
party.insurance.policyNumber = inquiryMapped?.LastCompanyDocumentNumber;
|
||||
party.insurance.company = clientName;
|
||||
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
|
||||
party.insurance.startDate = inquiryMapped?.IssueDate;
|
||||
party.insurance.endDate = inquiryMapped?.EndDate;
|
||||
|
||||
// CAR BODY EXTERNAL API INQUIRY
|
||||
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
|
||||
let carBodyInfo: any;
|
||||
// ---- External inquiry 1: Tejarat block inquiry ----
|
||||
let inquiryRaw: any;
|
||||
let inquiryMapped: any;
|
||||
try {
|
||||
carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry({
|
||||
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
|
||||
const inquiry = await this.sandHubService.getTejaratBlockInquiry({
|
||||
plate: body.plate,
|
||||
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
|
||||
});
|
||||
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, {
|
||||
source: "TEJARAT_CAR_BODY_INQUIRY",
|
||||
raw: carBodyInfo.raw,
|
||||
mapped: carBodyInfo.mapped,
|
||||
inquiryRaw = inquiry.raw;
|
||||
inquiryMapped = inquiry.mapped;
|
||||
this.logger.log(
|
||||
`[TEJARAT] block inquiry raw for request=${req._id}: ${JSON.stringify(inquiryRaw)}`,
|
||||
);
|
||||
this.logger.log(
|
||||
`[TEJARAT] block inquiry mapped for request=${req._id}: ${JSON.stringify(inquiryMapped)}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, true, {
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
});
|
||||
} catch (err: any) {
|
||||
this.logger.error(
|
||||
`[TEJARAT] car body inquiry failed for request=${req._id}: ${err?.message || err}`,
|
||||
`[TEJARAT] block inquiry failed for request=${req._id}: ${err?.message || err}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "carBody", role, false, {}, err);
|
||||
if (err?.response) {
|
||||
this.logger.error(
|
||||
`[TEJARAT] block inquiry response for request=${req._id}: status=${
|
||||
err.response.status
|
||||
}, data=${JSON.stringify(err.response.data)}`,
|
||||
);
|
||||
}
|
||||
this.recordPartyCaseInquiryStatus(
|
||||
req,
|
||||
"thirdParty",
|
||||
role,
|
||||
false,
|
||||
{},
|
||||
err,
|
||||
);
|
||||
await (req as any).save();
|
||||
throw new HttpException("Inquiry failed", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
|
||||
if (inquiryMapped?.Error) {
|
||||
this.logger.warn(
|
||||
`[TEJARAT] block inquiry error for request=${req._id}: ${JSON.stringify(
|
||||
inquiryMapped.Error,
|
||||
)}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, false, {
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
});
|
||||
await (req as any).save();
|
||||
throw new HttpException(
|
||||
"Car body inquiry failed",
|
||||
inquiryMapped.Error.Message || "Inquiry returned error",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// Raw + mapped stored under vehicle (same pattern as third-party inquiry)
|
||||
// ---- External inquiry 2: personal identity check (insurer/driver nationalCode + birthDate) ----
|
||||
// The form sends the birthday as a Jalali date in any of these shapes:
|
||||
// - number 13770624 (packed YYYYMMDD)
|
||||
// - string "1377-06-24" / "1377/06/24" / "13770624"
|
||||
// We forward it as-is; sandHubService.getPersonalInquiry() handles the
|
||||
// Jalali → Gregorian conversion required by the external API.
|
||||
const personalNationalCode =
|
||||
body.nationalCodeOfInsurer || body.nationalCodeOfDriver;
|
||||
const personalBirthDate: number | string | null = (body.insurerBirthday ??
|
||||
body.driverBirthday ??
|
||||
null) as number | string | null;
|
||||
if (
|
||||
!personalNationalCode ||
|
||||
personalBirthDate === null ||
|
||||
personalBirthDate === undefined ||
|
||||
String(personalBirthDate).trim() === ""
|
||||
) {
|
||||
throw new BadRequestException(
|
||||
"Valid nationalCode and birthDate are required for personal inquiry.",
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const personalInquiry = await this.sandHubService.getPersonalInquiry(
|
||||
personalNationalCode,
|
||||
personalBirthDate,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(
|
||||
req,
|
||||
"person",
|
||||
role,
|
||||
true,
|
||||
personalInquiry,
|
||||
);
|
||||
this.logger.log(
|
||||
`[SANDHUB] personal inquiry success request=${req._id} nationalCode=${personalNationalCode}: ${JSON.stringify(
|
||||
personalInquiry,
|
||||
)}`,
|
||||
);
|
||||
} catch (err: any) {
|
||||
this.logger.error(
|
||||
`[SANDHUB] personal inquiry failed request=${req._id} nationalCode=${personalNationalCode}: ${err?.message || err}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(req, "person", role, false, {}, err);
|
||||
await (req as any).save();
|
||||
throw new HttpException(
|
||||
"Personal identity inquiry failed",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// ---- External inquiry 3: driving license check (insurerLicense + nationalCode) ----
|
||||
// const licenseNationalCode = body.nationalCodeOfInsurer || body.nationalCodeOfDriver;
|
||||
// const licenseNumber = body.insurerLicense;
|
||||
// if (!licenseNationalCode || !licenseNumber) {
|
||||
// throw new BadRequestException(
|
||||
// "nationalCode and insurerLicense are required for driving license inquiry.",
|
||||
// );
|
||||
// }
|
||||
// try {
|
||||
// const licenseInquiry = await this.sandHubService.getDrivingLicenseInfo(
|
||||
// licenseNationalCode,
|
||||
// licenseNumber,
|
||||
// );
|
||||
// this.logger.log(
|
||||
// `[SANDHUB] license inquiry success request=${req._id} nationalCode=${licenseNationalCode}: ${JSON.stringify(
|
||||
// licenseInquiry,
|
||||
// )}`,
|
||||
// );
|
||||
// } catch (err: any) {
|
||||
// this.logger.error(
|
||||
// `[SANDHUB] license inquiry failed request=${req._id} nationalCode=${licenseNationalCode}: ${err?.message || err}`,
|
||||
// );
|
||||
// throw new HttpException(
|
||||
// "Driving license inquiry failed",
|
||||
// HttpStatus.BAD_REQUEST,
|
||||
// );
|
||||
// }
|
||||
|
||||
// Find client by company code
|
||||
const clientName = inquiryMapped?.CompanyName;
|
||||
if (!clientName) {
|
||||
throw new BadRequestException(
|
||||
`CompanyName missing from inquiry response`,
|
||||
);
|
||||
}
|
||||
const companyCode = inquiryMapped?.CompanyCode;
|
||||
let client =
|
||||
await this.clientService.findClientWithCompanyCode(+companyCode);
|
||||
|
||||
if (!client) {
|
||||
await this.clientService.addClient({
|
||||
clientName: {
|
||||
persian: clientName,
|
||||
english: null,
|
||||
},
|
||||
clientCode: Number(companyCode),
|
||||
useExpertMode: "legal",
|
||||
});
|
||||
}
|
||||
|
||||
// if (!client) {
|
||||
// throw new HttpException("Client not found", HttpStatus.CONFLICT);
|
||||
// }
|
||||
|
||||
// Persist inquiry/body data into new model
|
||||
if (!party.person) party.person = {} as any;
|
||||
const resolvedClientId =
|
||||
(client as any)?._id ?? (client as any)?._doc?._id;
|
||||
party.person.clientId = resolvedClientId;
|
||||
party.person.nationalCodeOfInsurer = body.nationalCodeOfInsurer;
|
||||
party.person.nationalCodeOfDriver = body.nationalCodeOfDriver;
|
||||
party.person.insurerLicense = body.insurerLicense;
|
||||
party.person.driverLicense = body.driverLicense;
|
||||
party.person.driverIsInsurer = body.driverIsInsurer;
|
||||
party.person.isNewCar = body.isNewCar;
|
||||
party.person.userNoCertificate = body.userNoCertificate;
|
||||
party.person.insurerBirthday = body.insurerBirthday;
|
||||
party.person.driverBirthday =
|
||||
body.driverBirthday ??
|
||||
(body.driverIsInsurer ? String(body.insurerBirthday) : null);
|
||||
|
||||
if (!party.vehicle) party.vehicle = {} as any;
|
||||
party.vehicle.isNew = body.isNewCar;
|
||||
party.vehicle.plateId =
|
||||
typeof body.plateId === "string"
|
||||
? body.plateId
|
||||
: this.plateToPlateIdString(body.plate);
|
||||
party.vehicle.name = inquiryMapped?.MapTypNam;
|
||||
party.vehicle.type = `${inquiryMapped?.UsageField} / ${inquiryMapped?.MapUsageName || "-"}`;
|
||||
party.vehicle.inquiry = {
|
||||
...party.vehicle.inquiry, // preserve existing third-party inquiry if present
|
||||
carBody: {
|
||||
source: "TEJARAT_CAR_BODY_INQUIRY",
|
||||
raw: carBodyInfo.raw,
|
||||
mapped: carBodyInfo.mapped,
|
||||
source: "TEJARAT_BLOCK_INQUIRY",
|
||||
raw: inquiryRaw,
|
||||
mapped: inquiryMapped,
|
||||
};
|
||||
|
||||
if (!party.insurance) party.insurance = {} as any;
|
||||
party.insurance.policyNumber = inquiryMapped?.LastCompanyDocumentNumber;
|
||||
party.insurance.company = clientName;
|
||||
party.insurance.financialCeiling = inquiryMapped?.FinancialCvrCptl;
|
||||
party.insurance.startDate = inquiryMapped?.IssueDate;
|
||||
party.insurance.endDate = inquiryMapped?.EndDate;
|
||||
|
||||
// CAR BODY EXTERNAL API INQUIRY
|
||||
if (req.type === BlameRequestType.CAR_BODY && role === PartyRole.FIRST) {
|
||||
let carBodyInfo: any;
|
||||
try {
|
||||
carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry({
|
||||
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
|
||||
plate: body.plate,
|
||||
});
|
||||
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, {
|
||||
source: "TEJARAT_CAR_BODY_INQUIRY",
|
||||
raw: carBodyInfo.raw,
|
||||
mapped: carBodyInfo.mapped,
|
||||
});
|
||||
} catch (err: any) {
|
||||
this.logger.error(
|
||||
`[TEJARAT] car body inquiry failed for request=${req._id}: ${err?.message || err}`,
|
||||
);
|
||||
this.recordPartyCaseInquiryStatus(
|
||||
req,
|
||||
"carBody",
|
||||
role,
|
||||
false,
|
||||
{},
|
||||
err,
|
||||
);
|
||||
await (req as any).save();
|
||||
throw new HttpException(
|
||||
"Car body inquiry failed",
|
||||
HttpStatus.BAD_REQUEST,
|
||||
);
|
||||
}
|
||||
|
||||
// Raw + mapped stored under vehicle (same pattern as third-party inquiry)
|
||||
party.vehicle.inquiry = {
|
||||
...party.vehicle.inquiry, // preserve existing third-party inquiry if present
|
||||
carBody: {
|
||||
source: "TEJARAT_CAR_BODY_INQUIRY",
|
||||
raw: carBodyInfo.raw,
|
||||
mapped: carBodyInfo.mapped,
|
||||
},
|
||||
};
|
||||
|
||||
// Flat key fields extracted alongside third-party insurance fields
|
||||
const m = carBodyInfo.mapped;
|
||||
(party.insurance as any).carBodyInsurance = {
|
||||
policyNumber: m.policyNumber ?? null,
|
||||
companyId: m.companyId ?? null,
|
||||
companyName: m.CompanyName ?? null,
|
||||
insurerName: m.insurerName ?? null,
|
||||
insurerNationalCode: m.insurerNationalCode ?? null,
|
||||
ownerNationalCode: m.ownerNationalCode ?? null,
|
||||
chassisNumber: m.ChassisNumberField ?? null,
|
||||
vin: m.VinNumberField ?? null,
|
||||
motorNumber: m.EngineNumberField ?? null,
|
||||
vehicleGroup: m.vehicleGroupTitle ?? null,
|
||||
vehicleSystem: m.vehicleSystemTitle ?? null,
|
||||
startDate: m.StartDate ?? null,
|
||||
endDate: m.EndDate ?? null,
|
||||
issueDate: m.IssueDate ?? null,
|
||||
noLossYearsCount: m.noLossYearsCount ?? null,
|
||||
lossDocuments: m.lossDocuments ?? [],
|
||||
hasEndorsement: m.hasEndorsement ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
// Advance workflow
|
||||
await this.advanceWorkflowToNext(req, stepKey);
|
||||
|
||||
// History
|
||||
if (!Array.isArray(req.history)) req.history = [];
|
||||
req.history.push({
|
||||
type: `${stepKey}_SUBMITTED`,
|
||||
actor: {
|
||||
actorId: Types.ObjectId.isValid(user?.sub)
|
||||
? new Types.ObjectId(user.sub)
|
||||
: undefined,
|
||||
actorName: user?.fullName,
|
||||
actorType: "user",
|
||||
},
|
||||
};
|
||||
metadata: {
|
||||
role,
|
||||
companyCode,
|
||||
companyName: clientName,
|
||||
},
|
||||
} as any);
|
||||
|
||||
// Flat key fields extracted alongside third-party insurance fields
|
||||
const m = carBodyInfo.mapped;
|
||||
(party.insurance as any).carBodyInsurance = {
|
||||
policyNumber: m.policyNumber ?? null,
|
||||
companyId: m.companyId ?? null,
|
||||
companyName: m.CompanyName ?? null,
|
||||
insurerName: m.insurerName ?? null,
|
||||
insurerNationalCode: m.insurerNationalCode ?? null,
|
||||
ownerNationalCode: m.ownerNationalCode ?? null,
|
||||
chassisNumber: m.ChassisNumberField ?? null,
|
||||
vin: m.VinNumberField ?? null,
|
||||
motorNumber: m.EngineNumberField ?? null,
|
||||
vehicleGroup: m.vehicleGroupTitle ?? null,
|
||||
vehicleSystem: m.vehicleSystemTitle ?? null,
|
||||
startDate: m.StartDate ?? null,
|
||||
endDate: m.EndDate ?? null,
|
||||
issueDate: m.IssueDate ?? null,
|
||||
noLossYearsCount: m.noLossYearsCount ?? null,
|
||||
lossDocuments: m.lossDocuments ?? [],
|
||||
hasEndorsement: m.hasEndorsement ?? null,
|
||||
await (req as any).save();
|
||||
|
||||
return {
|
||||
requestId: req._id,
|
||||
publicId: req.publicId,
|
||||
workflow: req.workflow,
|
||||
blameStatus: req.blameStatus,
|
||||
status: req.status,
|
||||
};
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
// Advance workflow
|
||||
await this.advanceWorkflowToNext(req, stepKey);
|
||||
|
||||
// History
|
||||
if (!Array.isArray(req.history)) req.history = [];
|
||||
req.history.push({
|
||||
type: `${stepKey}_SUBMITTED`,
|
||||
actor: {
|
||||
actorId: Types.ObjectId.isValid(user?.sub)
|
||||
? new Types.ObjectId(user.sub)
|
||||
: undefined,
|
||||
actorName: user?.fullName,
|
||||
actorType: "user",
|
||||
},
|
||||
metadata: {
|
||||
role,
|
||||
companyCode,
|
||||
companyName: clientName,
|
||||
},
|
||||
} as any);
|
||||
|
||||
await (req as any).save();
|
||||
|
||||
return {
|
||||
requestId: req._id,
|
||||
publicId: req.publicId,
|
||||
workflow: req.workflow,
|
||||
blameStatus: req.blameStatus,
|
||||
status: req.status,
|
||||
};
|
||||
}
|
||||
|
||||
async addDetailLocationV2(requestId: string, body: LocationDto, user: any) {
|
||||
|
||||
Reference in New Issue
Block a user