Fixed Participants

This commit is contained in:
SepehrYahyaee
2026-09-14 14:27:23 +03:30
parent 51166a8d0d
commit 9930e9ff5b
13 changed files with 518 additions and 199 deletions

View File

@@ -130,6 +130,7 @@ import {
normalizeInquirySubmission,
resolveInquirySubjects,
runPlateInquiryWithFallback,
sanitizeStoredInquiryParticipants,
} from "./inquiry-participant-resolver";
/**
@@ -311,12 +312,8 @@ export class RequestManagementService {
private normalizeInquiryInput<T extends Record<string, any>>(
type: BlameRequestType,
input: T,
partyRole?: PartyRole,
): NormalizedInquirySubmission<T> {
return normalizeInquirySubmission(type, input, {
allowUnknownThirdPartyPolicyholder:
type === BlameRequestType.THIRD_PARTY && partyRole === PartyRole.SECOND,
});
return normalizeInquirySubmission(type, input);
}
private applyInquiryParticipantsToParty(
@@ -334,6 +331,8 @@ export class RequestManagementService {
party.vehicle.previousPlateId = submission.vehicle.previousPlate
? this.plateToPlateIdString(submission.vehicle.previousPlate)
: undefined;
party.vehicle.previousPolicyholderNationalCode =
submission.vehicle.previousPolicyholderNationalCode;
if (submission.vehicle.vin) party.vehicle.vin = submission.vehicle.vin;
}
}
@@ -354,24 +353,18 @@ export class RequestManagementService {
submission: NormalizedInquirySubmission<Record<string, any>>,
options?: Record<string, any>,
): Promise<any> {
if (submission.thirdPartyPolicyholder.unknown) {
return {
raw: null,
mapped: {},
skipped: true,
plateKind: "CURRENT",
attempts: [],
};
}
const subjects = resolveInquirySubjects(submission);
const result = await runPlateInquiryWithFallback({
vehicle: submission.vehicle,
fallbackCurrentPlate: submission.dto.plate,
query: (plate) =>
query: (plate, plateKind) =>
this.sandHubService.getTejaratBlockInquiry(
{
plate: plate as any,
nationalCodeOfInsurer: subjects.thirdPartyPolicyNationalCode,
nationalCodeOfInsurer:
plateKind === "PREVIOUS"
? submission.vehicle!.previousPolicyholderNationalCode!
: subjects.thirdPartyPolicyNationalCode,
},
options,
),
@@ -401,9 +394,12 @@ export class RequestManagementService {
const result = await runPlateInquiryWithFallback({
vehicle: submission.vehicle,
fallbackCurrentPlate: submission.dto.plate,
query: (plate) =>
query: (plate, plateKind) =>
this.sandHubService.getCarBodyInquiry({
nationalCodeOfInsurer: policyholderNationalCode,
nationalCodeOfInsurer:
plateKind === "PREVIOUS"
? submission.vehicle!.previousPolicyholderNationalCode!
: policyholderNationalCode,
plate: plate as any,
}),
isUsable: (value) =>
@@ -435,9 +431,6 @@ export class RequestManagementService {
"vehicle.vin is required for a VIN/chassis inquiry.",
);
}
if (submission.thirdPartyPolicyholder.unknown) {
return { raw: null, mapped: {}, skipped: true };
}
const subjects = resolveInquirySubjects(submission);
const result = await this.sandHubService.getPolicyByChassisInquiry(
{
@@ -446,7 +439,7 @@ export class RequestManagementService {
},
options,
);
return { ...result, skipped: false };
return result;
}
private async runParticipantPersonalInquiries(
@@ -457,9 +450,7 @@ export class RequestManagementService {
): Promise<void> {
const participants = submission.participants.legacy
? [submission.thirdPartyPolicyholder]
: submission.participants.participants.filter(
(participant) => !participant.unknown,
);
: submission.participants.participants;
const results: Record<string, unknown> = {};
for (const participant of participants) {
@@ -598,7 +589,6 @@ export class RequestManagementService {
const personal: Record<string, unknown> = {};
for (const participant of submission.participants.participants) {
if (participant.unknown) continue;
personal[participant.participantId] =
await this.sandHubService.getPersonalInquiry(
participant.nationalCode,
@@ -664,6 +654,8 @@ export class RequestManagementService {
[`${prefix}.previousPlateId`]: submission.vehicle?.previousPlate
? this.plateToPlateIdString(submission.vehicle.previousPlate)
: undefined,
[`${prefix}.previousPolicyholderNationalCode`]:
submission.vehicle?.previousPolicyholderNationalCode,
[`${prefix}.vehicleVin`]: submission.vehicle?.vin,
[`${prefix}.policyInquiry`]: audit,
},
@@ -1732,12 +1724,9 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
body,
role,
);
body = inquirySubmission.dto as unknown as AddPlateDto;
this.applyInquiryParticipantsToParty(party, inquirySubmission);
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
// Validation: driver/insurer sameness rules
if (body.driverIsInsurer === false) {
@@ -1801,19 +1790,13 @@ export class RequestManagementService {
req,
"thirdParty",
role,
!inquiry.skipped,
true,
{
source: inquirySource,
plateKind: inquiry.plateKind,
attempts: inquiry.attempts,
raw: inquiryRaw,
mapped: inquiryMapped,
...(inquiry.skipped
? {
skipped: true,
reason: "Third-party policyholder is unknown",
}
: {}),
},
);
if (inquiry.offline?.fanavaranDriverId != null) {
@@ -1882,7 +1865,7 @@ export class RequestManagementService {
// Find client by company code
const clientName = inquiryMapped?.CompanyName;
if (!clientName && !policyholderUnknown) {
if (!clientName) {
const error = new BadRequestException(
`CompanyName missing from inquiry response`,
);
@@ -2183,13 +2166,10 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
body,
role,
);
body = inquirySubmission.dto as unknown as InitialFormVinDto;
const subjects = resolveInquirySubjects(inquirySubmission);
this.applyInquiryParticipantsToParty(party, inquirySubmission);
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
// Validation: driver/insurer sameness rules (identical to plate path)
if (body.driverIsInsurer === false) {
@@ -2246,17 +2226,11 @@ export class RequestManagementService {
req,
"thirdParty",
role,
!inquiry.skipped,
true,
{
source: "ESG_VIN_INQUIRY",
raw: inquiryRaw,
mapped: inquiryMapped,
...(inquiry.skipped
? {
skipped: true,
reason: "Third-party policyholder is unknown",
}
: {}),
},
);
} catch (err: any) {
@@ -2319,7 +2293,7 @@ export class RequestManagementService {
// Resolve insurer client from inquiry response
const clientName = inquiryMapped?.CompanyName;
if (!clientName && !policyholderUnknown) {
if (!clientName) {
const error = new BadRequestException(
"CompanyName missing from VIN inquiry response",
);
@@ -3482,8 +3456,6 @@ export class RequestManagementService {
const clientName = sandHubReport?.CompanyName;
const companyCode = sandHubReport?.CompanyCode;
const policyholderUnknown =
inquirySubmission?.thirdPartyPolicyholder.unknown === true;
const client = clientName
? await this.clientService.findOrCreateClientByCompanyCode(
companyCode,
@@ -3491,7 +3463,7 @@ export class RequestManagementService {
)
: null;
if (!client && !policyholderUnknown) {
if (!client) {
throw new HttpException("Client not found", HttpStatus.CONFLICT);
}
@@ -3529,13 +3501,11 @@ export class RequestManagementService {
plate: body.plate,
nationalCode: body.nationalCodeOfInsurer,
};
const sandHubDoc = policyInquiry?.skipped
? null
: await this.sandHubService.sandHubDocumentCreator(
user.sub,
request["_doc"]._id,
sandHubDocData,
);
const sandHubDoc = await this.sandHubService.sandHubDocumentCreator(
user.sub,
request["_doc"]._id,
sandHubDocData,
);
if (partyType === "firstParty" && sandHubDoc) {
await this.requestManagementDbService.findAndUpdate(
@@ -3592,6 +3562,8 @@ export class RequestManagementService {
?.previousPlate
? this.plateToPlateIdString(inquirySubmission.vehicle.previousPlate)
: undefined;
setFields[`${partyDetails}.previousPolicyholderNationalCode`] =
inquirySubmission.vehicle?.previousPolicyholderNationalCode;
setFields[`${partyDetails}.vehicleVin`] =
inquirySubmission.vehicle?.vin;
}
@@ -3704,7 +3676,6 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
request.type as BlameRequestType,
body,
partyRole,
);
body = inquirySubmission.dto as unknown as AddPlateDto;
@@ -6641,7 +6612,6 @@ export class RequestManagementService {
participantId: participant.participantId,
fullName: participant.fullName,
hasDrivingLicense: participant.hasDrivingLicense,
unknown: participant.unknown,
}))
: undefined;
const evidenceRaw = party.evidence as Record<string, unknown> | undefined;
@@ -6951,7 +6921,6 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
formData.firstPartyPlate,
PartyRole.FIRST,
);
this.recordInquiryParticipantContext(
req,
@@ -7139,6 +7108,8 @@ export class RequestManagementService {
previousPlateId: inquirySubmission.vehicle?.previousPlate
? this.plateToPlateIdString(inquirySubmission.vehicle.previousPlate)
: undefined,
previousPolicyholderNationalCode:
inquirySubmission.vehicle?.previousPolicyholderNationalCode,
vin: inquirySubmission.vehicle?.vin,
inquiry: {
...sandHubReport,
@@ -7279,7 +7250,6 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
plateDto,
role,
);
this.recordInquiryParticipantContext(req, role, inquirySubmission);
const existingPartyIndex = this.getPartyIndex(req, role);
@@ -7290,8 +7260,6 @@ export class RequestManagementService {
);
}
plateDto = inquirySubmission.dto;
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
let inquiry: any;
try {
if (inquirySubmission.participants.legacy) {
@@ -7332,19 +7300,13 @@ export class RequestManagementService {
req,
"thirdParty",
role,
!inquiry.skipped,
true,
{
source: inquiry.offline?.source ?? "TEJARAT_BLOCK_INQUIRY",
plateKind: inquiry.plateKind,
attempts: inquiry.attempts,
raw: inquiry.raw,
mapped: inquiry.mapped,
...(inquiry.skipped
? {
skipped: true,
reason: "Third-party policyholder is unknown",
}
: {}),
},
);
const clientName =
@@ -7358,7 +7320,7 @@ export class RequestManagementService {
)
: await this.clientService.findOne({ clientName })
: null;
if (!client && !policyholderUnknown) {
if (!client) {
const error = new NotFoundException(
`Client not found for company: ${clientName}`,
);
@@ -7434,6 +7396,8 @@ export class RequestManagementService {
previousPlateId: inquirySubmission.vehicle?.previousPlate
? this.plateToPlateIdString(inquirySubmission.vehicle.previousPlate)
: undefined,
previousPolicyholderNationalCode:
inquirySubmission.vehicle?.previousPolicyholderNationalCode,
vin: inquirySubmission.vehicle?.vin,
inquiry: sandHubReport,
},
@@ -8071,7 +8035,6 @@ export class RequestManagementService {
const firstInquirySubmission = this.normalizeInquiryInput(
BlameRequestType.THIRD_PARTY,
formData.firstPartyPlate,
PartyRole.FIRST,
);
const firstPartyPlate = firstInquirySubmission.dto;
let firstPolicyInquiry: any;
@@ -8179,6 +8142,8 @@ export class RequestManagementService {
firstInquirySubmission.vehicle.previousPlate,
)
: undefined;
firstPartyDetails.previousPolicyholderNationalCode =
firstInquirySubmission.vehicle?.previousPolicyholderNationalCode;
firstPartyDetails.vehicleVin = firstInquirySubmission.vehicle?.vin;
}
@@ -8209,7 +8174,6 @@ export class RequestManagementService {
const secondInquirySubmission = this.normalizeInquiryInput(
BlameRequestType.THIRD_PARTY,
formData.secondParty.plate,
PartyRole.SECOND,
);
let secondPolicyInquiry: any;
try {
@@ -8243,8 +8207,6 @@ export class RequestManagementService {
const companyCode = sandHubReport?.CompanyCode;
// Try to find client by company code first (more reliable)
const policyholderUnknown =
secondInquirySubmission.thirdPartyPolicyholder.unknown === true;
const client = clientName
? companyCode
? await this.clientService.findOrCreateClientByCompanyCode(
@@ -8254,7 +8216,7 @@ export class RequestManagementService {
: await this.clientService.findOne({ clientName: clientName })
: null;
if (!client && !policyholderUnknown) {
if (!client) {
const error = new NotFoundException(
`Client not found for company: ${clientName}${companyCode ? ` (code: ${companyCode})` : ""}`,
);
@@ -8319,6 +8281,8 @@ export class RequestManagementService {
secondInquirySubmission.vehicle.previousPlate,
)
: undefined;
secondPartyDetails.previousPolicyholderNationalCode =
secondInquirySubmission.vehicle?.previousPolicyholderNationalCode;
secondPartyDetails.vehicleVin = secondInquirySubmission.vehicle?.vin;
}
@@ -8554,7 +8518,6 @@ export class RequestManagementService {
const firstInquirySubmission = this.normalizeInquiryInput(
BlameRequestType.CAR_BODY,
formData.firstPartyPlate,
PartyRole.FIRST,
);
const firstPartyPlate = firstInquirySubmission.dto;
let thirdPartyPolicyInquiry: any;
@@ -8687,6 +8650,8 @@ export class RequestManagementService {
firstInquirySubmission.vehicle.previousPlate,
)
: undefined;
firstPartyDetails.previousPolicyholderNationalCode =
firstInquirySubmission.vehicle?.previousPolicyholderNationalCode;
firstPartyDetails.vehicleVin = firstInquirySubmission.vehicle?.vin;
}
firstPartyDetails.firstPartyClient.clientId =
@@ -9805,13 +9770,10 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
partyData,
partyRole,
);
partyData = inquirySubmission.dto as RunInquiriesV3Dto;
const subjects = resolveInquirySubjects(inquirySubmission);
this.applyInquiryParticipantsToParty(party, inquirySubmission);
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND";
let clientId: string | undefined;
const inquiryOptions = (cid?: string) =>
@@ -9838,19 +9800,13 @@ export class RequestManagementService {
req,
"thirdParty",
partyRole,
!inquiry.skipped,
true,
{
source: inquirySource,
plateKind: inquiry.plateKind,
attempts: inquiry.attempts,
raw: inquiryRaw,
mapped: inquiryMapped,
...(inquiry.skipped
? {
skipped: true,
reason: "Third-party policyholder is unknown",
}
: {}),
},
);
if (inquiry.offline?.fanavaranDriverId != null) {
@@ -9900,7 +9856,7 @@ export class RequestManagementService {
const clientName = inquiryMapped?.CompanyName;
const companyCode = inquiryMapped?.CompanyCode;
if (!clientName && !policyholderUnknown) {
if (!clientName) {
const error = new BadRequestException(
`CompanyName missing from ${roleLabel} party inquiry response`,
);
@@ -10162,10 +10118,14 @@ export class RequestManagementService {
vehicleOwnerNationalCode: string,
clientId?: string,
): Promise<void> {
if (!sheba) return;
if (!String(sheba ?? "").trim()) {
throw new BadRequestException(
"sheba is required for the damaged party.",
);
}
await this.sandHubService.getShebaValidation(
vehicleOwnerNationalCode,
sheba,
sheba!.trim(),
clientId ? { clientId } : undefined,
);
}
@@ -10738,13 +10698,10 @@ export class RequestManagementService {
const inquirySubmission = this.normalizeInquiryInput(
req.type,
partyData,
partyRole,
);
partyData = inquirySubmission.dto as RunInquiriesVinV3Dto;
const subjects = resolveInquirySubjects(inquirySubmission);
this.applyInquiryParticipantsToParty(party, inquirySubmission);
const policyholderUnknown =
inquirySubmission.thirdPartyPolicyholder.unknown === true;
const roleLabel = partyRole === PartyRole.FIRST ? "FIRST" : "SECOND";
let clientId: string | undefined;
const inquiryOptions = (cid?: string) =>
@@ -10763,17 +10720,11 @@ export class RequestManagementService {
req,
"thirdParty",
partyRole,
!inquiry.skipped,
true,
{
source: "ESG_VIN_INQUIRY",
raw: inquiryRaw,
mapped: inquiryMapped,
...(inquiry.skipped
? {
skipped: true,
reason: "Third-party policyholder is unknown",
}
: {}),
},
);
} catch (err: any) {
@@ -10817,7 +10768,7 @@ export class RequestManagementService {
const clientName = inquiryMapped?.CompanyName;
const companyCode = inquiryMapped?.CompanyCode;
if (!clientName && !policyholderUnknown) {
if (!clientName) {
const error = new BadRequestException(
`CompanyName missing from ${roleLabel} party VIN inquiry response`,
);
@@ -12320,12 +12271,16 @@ export class RequestManagementService {
message:
"استعلام طرف مقصر با موفقیت انجام شد. اکنون می‌توانید لینک تقصیر را برای کاربر ارسال کنید.",
guiltyParty: {
participants: firstPartyAfter?.participants,
participants: sanitizeStoredInquiryParticipants(
firstPartyAfter?.participants,
),
participantRoles: firstPartyAfter?.participantRoles,
vehicle: firstPartyAfter?.vehicle
? {
plateId: firstPartyAfter.vehicle.plateId,
previousPlateId: firstPartyAfter.vehicle.previousPlateId,
previousPolicyholderNationalCode:
firstPartyAfter.vehicle.previousPolicyholderNationalCode,
registrationState: firstPartyAfter.vehicle.registrationState,
vin: firstPartyAfter.vehicle.vin,
name: firstPartyAfter.vehicle.name,
@@ -12435,13 +12390,17 @@ export class RequestManagementService {
message:
"استعلام VIN طرف مقصر با موفقیت انجام شد. اکنون می‌توانید لینک تقصیر را برای کاربر ارسال کنید.",
guiltyParty: {
participants: firstPartyAfter?.participants,
participants: sanitizeStoredInquiryParticipants(
firstPartyAfter?.participants,
),
participantRoles: firstPartyAfter?.participantRoles,
vehicle: firstPartyAfter?.vehicle
? {
vin: firstPartyAfter.vehicle.vin,
plateId: firstPartyAfter.vehicle.plateId,
previousPlateId: firstPartyAfter.vehicle.previousPlateId,
previousPolicyholderNationalCode:
firstPartyAfter.vehicle.previousPolicyholderNationalCode,
registrationState: firstPartyAfter.vehicle.registrationState,
name: firstPartyAfter.vehicle.name,
type: firstPartyAfter.vehicle.type,
@@ -12684,7 +12643,7 @@ export class RequestManagementService {
skipInitialFormStep: (req as any).skipInitialFormStep,
parties: ((req as any).parties ?? []).map((p: any) => ({
role: p.role,
participants: p.participants,
participants: sanitizeStoredInquiryParticipants(p.participants),
participantRoles: p.participantRoles,
person: {
phoneNumber: p.person?.phoneNumber,
@@ -12709,6 +12668,8 @@ export class RequestManagementService {
? {
plateId: p.vehicle.plateId,
previousPlateId: p.vehicle.previousPlateId,
previousPolicyholderNationalCode:
p.vehicle.previousPolicyholderNationalCode,
registrationState: p.vehicle.registrationState,
vin: p.vehicle.vin,
name: p.vehicle.name,
@@ -12844,7 +12805,7 @@ export class RequestManagementService {
requiresFileMakerApproval: plain.requiresFileMakerApproval,
parties: (plain.parties ?? []).map((p: any) => ({
role: p.role,
participants: p.participants,
participants: sanitizeStoredInquiryParticipants(p.participants),
participantRoles: p.participantRoles,
person: {
fullName: p.person?.fullName,
@@ -12873,6 +12834,8 @@ export class RequestManagementService {
? {
plateId: p.vehicle.plateId,
previousPlateId: p.vehicle.previousPlateId,
previousPolicyholderNationalCode:
p.vehicle.previousPolicyholderNationalCode,
registrationState: p.vehicle.registrationState,
vin: p.vehicle.vin,
name: p.vehicle.name,
@@ -13027,7 +12990,7 @@ export class RequestManagementService {
: null,
parties: (plain.parties ?? []).map((p: any) => ({
role: p.role,
participants: p.participants,
participants: sanitizeStoredInquiryParticipants(p.participants),
participantRoles: p.participantRoles,
person: {
fullName: p.person?.fullName,
@@ -13056,6 +13019,8 @@ export class RequestManagementService {
? {
plateId: p.vehicle.plateId,
previousPlateId: p.vehicle.previousPlateId,
previousPolicyholderNationalCode:
p.vehicle.previousPolicyholderNationalCode,
registrationState: p.vehicle.registrationState,
vin: p.vehicle.vin,
name: p.vehicle.name,