forked from Yara724/api
YARA-868
This commit is contained in:
@@ -2805,6 +2805,27 @@ export class ClaimRequestManagementService {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Branch ids referenced on expert-priced parts (`daghi` object with `branchId`). */
|
||||||
|
private collectBranchIdsFromClaimExpertReply(reply: {
|
||||||
|
parts?: unknown[];
|
||||||
|
}): Set<string> {
|
||||||
|
const ids = new Set<string>();
|
||||||
|
const parts = reply?.parts;
|
||||||
|
if (!Array.isArray(parts)) {
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
for (const p of parts) {
|
||||||
|
const d = (p as { daghi?: unknown })?.daghi;
|
||||||
|
if (d && typeof d === "object" && d !== null && "branchId" in d) {
|
||||||
|
const bid = (d as { branchId?: unknown }).branchId;
|
||||||
|
if (bid != null && Types.ObjectId.isValid(String(bid))) {
|
||||||
|
ids.add(String(bid));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fanavaran Submit - Map data from claim-request-management and request-management to third-party-car-financial-claims format
|
* Fanavaran Submit - Map data from claim-request-management and request-management to third-party-car-financial-claims format
|
||||||
*/
|
*/
|
||||||
@@ -5139,6 +5160,7 @@ export class ClaimRequestManagementService {
|
|||||||
async submitOwnerInsurerApprovalSignV2(
|
async submitOwnerInsurerApprovalSignV2(
|
||||||
claimRequestId: string,
|
claimRequestId: string,
|
||||||
agree: boolean,
|
agree: boolean,
|
||||||
|
branchId: string,
|
||||||
signFile: Express.Multer.File,
|
signFile: Express.Multer.File,
|
||||||
currentUserId: string,
|
currentUserId: string,
|
||||||
actor?: { sub: string; role?: string; fullName?: string },
|
actor?: { sub: string; role?: string; fullName?: string },
|
||||||
@@ -5200,6 +5222,34 @@ export class ClaimRequestManagementService {
|
|||||||
throw new BadRequestException("No expert reply is available to sign off on yet.");
|
throw new BadRequestException("No expert reply is available to sign off on yet.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const rawBranchId = (branchId ?? "").trim();
|
||||||
|
if (!rawBranchId || !Types.ObjectId.isValid(rawBranchId)) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
"branchId is required and must be a valid MongoDB ObjectId.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const branchDoc = await this.branchDbService.findById(rawBranchId);
|
||||||
|
if (!branchDoc) {
|
||||||
|
throw new NotFoundException(`Branch with ID ${rawBranchId} not found.`);
|
||||||
|
}
|
||||||
|
const ownerClientId = claimCase.owner?.clientId;
|
||||||
|
if (!ownerClientId || String(branchDoc.clientKey) !== String(ownerClientId)) {
|
||||||
|
throw new ForbiddenException(
|
||||||
|
"This branch does not belong to the insurer for this claim.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
const branchIdsOnPricing = this.collectBranchIdsFromClaimExpertReply(
|
||||||
|
activeReply as { parts?: unknown[] },
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
branchIdsOnPricing.size > 0 &&
|
||||||
|
!branchIdsOnPricing.has(String(rawBranchId))
|
||||||
|
) {
|
||||||
|
throw new BadRequestException(
|
||||||
|
"branchId must match a branch used in the expert pricing for this claim.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const signDoc = await this.claimSignDbService.create({
|
const signDoc = await this.claimSignDbService.create({
|
||||||
fileName: signFile.filename,
|
fileName: signFile.filename,
|
||||||
userId: effectiveUserId,
|
userId: effectiveUserId,
|
||||||
@@ -5210,6 +5260,7 @@ export class ClaimRequestManagementService {
|
|||||||
const signedAt = new Date();
|
const signedAt = new Date();
|
||||||
const approvalPayload = {
|
const approvalPayload = {
|
||||||
agree,
|
agree,
|
||||||
|
branchId: new Types.ObjectId(rawBranchId),
|
||||||
signDetailId: signId,
|
signDetailId: signId,
|
||||||
signedAt,
|
signedAt,
|
||||||
};
|
};
|
||||||
@@ -5233,7 +5284,7 @@ export class ClaimRequestManagementService {
|
|||||||
type: "OWNER_REJECTED_INSURER_APPROVAL_PRICING",
|
type: "OWNER_REJECTED_INSURER_APPROVAL_PRICING",
|
||||||
actor: historyActor,
|
actor: historyActor,
|
||||||
timestamp: signedAt,
|
timestamp: signedAt,
|
||||||
metadata: {},
|
metadata: { branchId: rawBranchId },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -5262,7 +5313,7 @@ export class ClaimRequestManagementService {
|
|||||||
type: "OWNER_SIGNED_INSURER_APPROVAL",
|
type: "OWNER_SIGNED_INSURER_APPROVAL",
|
||||||
actor: historyActor,
|
actor: historyActor,
|
||||||
timestamp: signedAt,
|
timestamp: signedAt,
|
||||||
metadata: {},
|
metadata: { branchId: rawBranchId },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -245,21 +245,27 @@ export class ClaimRequestManagementV2Controller {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Sign final claim pricing (owner)",
|
summary: "Sign final claim pricing (owner)",
|
||||||
description:
|
description:
|
||||||
"Multipart: `sign` (signature image) and `agree` (boolean). Allowed only when `status` is WAITING_FOR_INSURER_APPROVAL, " +
|
"Multipart: `sign` (signature image), `agree` (boolean), and `branchId` (Mongo ObjectId of the insurer branch the file is reviewed under). " +
|
||||||
|
"Allowed only when `status` is WAITING_FOR_INSURER_APPROVAL, " +
|
||||||
"`workflow.currentStep` is INSURER_REVIEW (not EXPERT_COST_EVALUATION), and `claimStatus` is APPROVED. " +
|
"`workflow.currentStep` is INSURER_REVIEW (not EXPERT_COST_EVALUATION), and `claimStatus` is APPROVED. " +
|
||||||
"If `agree` is true, the case moves to COMPLETED; if false, to REJECTED.",
|
"If `agree` is true, the case moves to COMPLETED; if false, to REJECTED.",
|
||||||
})
|
})
|
||||||
@ApiBody({
|
@ApiBody({
|
||||||
description: "Signature file and agreement",
|
description: "Signature file, agreement, and branch",
|
||||||
schema: {
|
schema: {
|
||||||
type: "object",
|
type: "object",
|
||||||
required: ["sign", "agree"],
|
required: ["sign", "agree", "branchId"],
|
||||||
properties: {
|
properties: {
|
||||||
sign: { type: "string", format: "binary", description: "Signature image" },
|
sign: { type: "string", format: "binary", description: "Signature image" },
|
||||||
agree: {
|
agree: {
|
||||||
type: "boolean",
|
type: "boolean",
|
||||||
description: "true to accept expert pricing and complete the claim",
|
description: "true to accept expert pricing and complete the claim",
|
||||||
},
|
},
|
||||||
|
branchId: {
|
||||||
|
type: "string",
|
||||||
|
description: "Insurer branch id (must belong to the claim owner's insurer; if pricing lists branch options, must match one of them)",
|
||||||
|
example: "507f1f77bcf86cd799439011",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -285,6 +291,7 @@ export class ClaimRequestManagementV2Controller {
|
|||||||
async submitOwnerInsurerApprovalSignV2(
|
async submitOwnerInsurerApprovalSignV2(
|
||||||
@Param("claimRequestId") claimRequestId: string,
|
@Param("claimRequestId") claimRequestId: string,
|
||||||
@Body("agree") agree: string | boolean,
|
@Body("agree") agree: string | boolean,
|
||||||
|
@Body("branchId") branchId: string,
|
||||||
@CurrentUser() user: any,
|
@CurrentUser() user: any,
|
||||||
@UploadedFile() sign: Express.Multer.File,
|
@UploadedFile() sign: Express.Multer.File,
|
||||||
) {
|
) {
|
||||||
@@ -297,6 +304,7 @@ export class ClaimRequestManagementV2Controller {
|
|||||||
return await this.claimRequestManagementService.submitOwnerInsurerApprovalSignV2(
|
return await this.claimRequestManagementService.submitOwnerInsurerApprovalSignV2(
|
||||||
claimRequestId,
|
claimRequestId,
|
||||||
agreed,
|
agreed,
|
||||||
|
typeof branchId === "string" ? branchId : "",
|
||||||
sign,
|
sign,
|
||||||
user.sub,
|
user.sub,
|
||||||
user,
|
user,
|
||||||
|
|||||||
@@ -82,6 +82,10 @@ export class ClaimOwnerInsurerApproval {
|
|||||||
@Prop({ type: Boolean, required: true })
|
@Prop({ type: Boolean, required: true })
|
||||||
agree: boolean;
|
agree: boolean;
|
||||||
|
|
||||||
|
/** Branch the owner is signing for (must belong to their insurer; aligned with expert daghi options when present). */
|
||||||
|
@Prop({ type: Types.ObjectId })
|
||||||
|
branchId?: Types.ObjectId;
|
||||||
|
|
||||||
@Prop({ type: Types.ObjectId })
|
@Prop({ type: Types.ObjectId })
|
||||||
signDetailId?: Types.ObjectId;
|
signDetailId?: Types.ObjectId;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user