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:
2026-06-03 14:01:44 +03:30
3 changed files with 370 additions and 328 deletions

View File

@@ -99,19 +99,34 @@ export class ClientService {
try { try {
const newClient = await this.clientDbService.create({ const newClient = await this.clientDbService.create({
clientCode: client.clientCode, clientCode: client.clientCode,
clientName: { clientName: {
persian: client.clientName.persian, persian:
english: client.clientName.english || null, typeof client.clientName === "string"
? client.clientName
: client.clientName?.persian,
english:
typeof client.clientName === "string"
? null
: (client.clientName?.english ?? null),
}, },
property: { 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) { } catch (er) {
throw new BadGatewayException(er.errors); console.error("ADD CLIENT ERROR:", er);
throw er;
} }
} }

View File

@@ -1,5 +1,12 @@
import { ApiProperty } from "@nestjs/swagger"; import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
import { IsIn, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested } from "class-validator"; import {
IsIn,
IsNotEmpty,
IsNumber,
IsOptional,
IsString,
ValidateNested,
} from "class-validator";
import { Type } from "class-transformer"; import { Type } from "class-transformer";
import { Types } from "mongoose"; import { Types } from "mongoose";
@@ -15,9 +22,8 @@ class ClientName {
english: string; english: string;
} }
class Property { class Property {
@ApiProperty({}) @ApiPropertyOptional({})
@IsString() @IsString()
@IsNotEmpty()
smsApiKey: string; smsApiKey: string;
} }

View File

@@ -945,354 +945,375 @@ export class RequestManagementService {
} }
async initialFormV2(requestId: string, body: AddPlateDto, user: any) { async initialFormV2(requestId: string, body: AddPlateDto, user: any) {
const req = await this.blameRequestDbService.findById(requestId); try {
if (!req) { const req = await this.blameRequestDbService.findById(requestId);
throw new NotFoundException("Request not found"); if (!req) {
} throw new NotFoundException("Request not found");
}
if (!req.workflow?.currentStep) { if (!req.workflow?.currentStep) {
throw new BadRequestException("Request workflow is not initialized"); throw new BadRequestException("Request workflow is not initialized");
} }
const stepKey = req.workflow.currentStep as WorkflowStep; 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) {
if ( if (
body.nationalCodeOfInsurer === body.nationalCodeOfDriver || stepKey !== WorkflowStep.FIRST_INITIAL_FORM &&
body.insurerLicense === body.driverLicense stepKey !== WorkflowStep.SECOND_INITIAL_FORM
) { ) {
throw new BadRequestException( 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; // Detect which party from step
const sameLic = body.insurerLicense === body.driverLicense; const role = this.stepKeyToPartyRole(stepKey);
const sameBirthday = const idx = this.getPartyIndex(req, role);
body.driverBirthday == null || if (idx === -1) {
String(body.driverBirthday) === String(body.insurerBirthday); throw new BadRequestException(`${role} party not found on request`);
if (!sameNat || !sameLic || !sameBirthday) {
throw new BadRequestException(
"When driverIsInsurer is true, insurer and driver data must be the same.",
);
} }
}
// ---- External inquiry 1: Tejarat block inquiry ---- const party = req.parties[idx];
let inquiryRaw: any; this.assertPartyOwner(
let inquiryMapped: any; party,
try { user,
const inquiry = await this.sandHubService.getTejaratBlockInquiry({ `Only ${role} party can submit this step`,
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)}`,
); );
this.logger.log(
`[TEJARAT] block inquiry mapped for request=${req._id}: ${JSON.stringify(inquiryMapped)}`, // Set userId for party if not already set (important for second party)
); if (!party.person) party.person = {} as any;
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, true, { if (!party.person.userId && user?.sub) {
source: "TEJARAT_BLOCK_INQUIRY", party.person.userId = Types.ObjectId.isValid(user.sub)
raw: inquiryRaw, ? new Types.ObjectId(user.sub)
mapped: inquiryMapped, : undefined;
});
} 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)}`,
);
} }
this.recordPartyCaseInquiryStatus(
req,
"thirdParty",
role,
false,
{},
err,
);
await (req as any).save();
throw new HttpException("Inquiry failed", HttpStatus.BAD_REQUEST);
}
if (inquiryMapped?.Error) { // Validation: driver/insurer sameness rules
this.logger.warn( if (body.driverIsInsurer === false) {
`[TEJARAT] block inquiry error for request=${req._id}: ${JSON.stringify( if (
inquiryMapped.Error, body.nationalCodeOfInsurer === body.nationalCodeOfDriver ||
)}`, body.insurerLicense === body.driverLicense
); ) {
this.recordPartyCaseInquiryStatus(req, "thirdParty", role, false, { throw new BadRequestException(
source: "TEJARAT_BLOCK_INQUIRY", "Insurer and Driver should be two different persons in this mode.",
raw: inquiryRaw, );
mapped: inquiryMapped, }
}); } else if (body.driverIsInsurer === true) {
await (req as any).save(); const sameNat =
throw new HttpException( body.nationalCodeOfInsurer === body.nationalCodeOfDriver;
inquiryMapped.Error.Message || "Inquiry returned error", const sameLic = body.insurerLicense === body.driverLicense;
HttpStatus.BAD_REQUEST, 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) ---- // ---- External inquiry 1: Tejarat block inquiry ----
// The form sends the birthday as a Jalali date in any of these shapes: let inquiryRaw: any;
// - number 13770624 (packed YYYYMMDD) let inquiryMapped: any;
// - 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;
try { try {
carBodyInfo = await this.sandHubService.getTejaratCarBodyInquiry({ const inquiry = await this.sandHubService.getTejaratBlockInquiry({
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
plate: body.plate, plate: body.plate,
nationalCodeOfInsurer: body.nationalCodeOfInsurer,
}); });
this.recordPartyCaseInquiryStatus(req, "carBody", role, true, { inquiryRaw = inquiry.raw;
source: "TEJARAT_CAR_BODY_INQUIRY", inquiryMapped = inquiry.mapped;
raw: carBodyInfo.raw, this.logger.log(
mapped: carBodyInfo.mapped, `[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) { } catch (err: any) {
this.logger.error( 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(); await (req as any).save();
throw new HttpException( throw new HttpException(
"Car body inquiry failed", inquiryMapped.Error.Message || "Inquiry returned error",
HttpStatus.BAD_REQUEST, 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 = {
...party.vehicle.inquiry, // preserve existing third-party inquiry if present source: "TEJARAT_BLOCK_INQUIRY",
carBody: { raw: inquiryRaw,
source: "TEJARAT_CAR_BODY_INQUIRY", mapped: inquiryMapped,
raw: carBodyInfo.raw, };
mapped: carBodyInfo.mapped,
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 await (req as any).save();
const m = carBodyInfo.mapped;
(party.insurance as any).carBodyInsurance = { return {
policyNumber: m.policyNumber ?? null, requestId: req._id,
companyId: m.companyId ?? null, publicId: req.publicId,
companyName: m.CompanyName ?? null, workflow: req.workflow,
insurerName: m.insurerName ?? null, blameStatus: req.blameStatus,
insurerNationalCode: m.insurerNationalCode ?? null, status: req.status,
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,
}; };
} 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) { async addDetailLocationV2(requestId: string, body: LocationDto, user: any) {