forked from Yara724/api
FIXED FILE REVIEWER GET ALL
This commit is contained in:
@@ -58,6 +58,7 @@ import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||
import {
|
||||
assertClaimCaseForTenant,
|
||||
assertClaimCaseForExpertActor,
|
||||
blameCaseTouchesClient,
|
||||
claimCaseInitiatedByFieldExpert,
|
||||
claimCaseTouchesClient,
|
||||
requireActorClientKey,
|
||||
@@ -3618,6 +3619,9 @@ export class ExpertClaimService {
|
||||
if (actor.role === RoleEnum.FIELD_EXPERT) {
|
||||
return this.getFieldExpertClaimListV2(actor, query);
|
||||
}
|
||||
if (actor.role === RoleEnum.FILE_REVIEWER) {
|
||||
return this.getFileReviewerClaimListV2(actor, query);
|
||||
}
|
||||
requireActorClientKey(actor);
|
||||
const actorId = actor.sub;
|
||||
const clientKey = actor.clientKey as string;
|
||||
@@ -3885,6 +3889,96 @@ export class ExpertClaimService {
|
||||
return this.paginateClaimListV2(list, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Claim list for FILE_REVIEWER — returns claims linked to sealed expert-initiated
|
||||
* IN_PERSON blame files (WAITING_FOR_FILE_REVIEWER, WAITING_FOR_EXPERT, COMPLETED)
|
||||
* that belong to this reviewer's insurance company.
|
||||
*/
|
||||
private async getFileReviewerClaimListV2(
|
||||
actor: any,
|
||||
query: ListQueryV2Dto = {},
|
||||
): Promise<GetClaimListV2ResponseDto> {
|
||||
const clientKey = requireActorClientKey(actor);
|
||||
|
||||
// Find all sealed blame files (across statuses the reviewer cares about)
|
||||
const sealedBlames = (await this.blameRequestDbService.find(
|
||||
{
|
||||
expertInitiated: true,
|
||||
creationMethod: "IN_PERSON",
|
||||
status: {
|
||||
$in: [
|
||||
"WAITING_FOR_FILE_REVIEWER",
|
||||
"WAITING_FOR_EXPERT",
|
||||
"COMPLETED",
|
||||
],
|
||||
},
|
||||
},
|
||||
{ lean: true, select: "_id type parties blameStatus status expert.decision" },
|
||||
)) as any[];
|
||||
|
||||
if (sealedBlames.length === 0) {
|
||||
return this.paginateClaimListV2([], query);
|
||||
}
|
||||
|
||||
// Scope to this reviewer's insurer via blame party clientId
|
||||
const scopedBlameIds = sealedBlames
|
||||
.filter((b) => blameCaseTouchesClient(b, clientKey))
|
||||
.map((b) => b._id);
|
||||
|
||||
if (scopedBlameIds.length === 0) {
|
||||
return this.paginateClaimListV2([], query);
|
||||
}
|
||||
|
||||
const claims = (await this.claimCaseDbService.find({
|
||||
blameRequestId: { $in: scopedBlameIds },
|
||||
})) as any[];
|
||||
|
||||
const blameById = new Map<string, any>(
|
||||
sealedBlames.map((b) => [String(b._id), b]),
|
||||
);
|
||||
|
||||
const list = claims.map((c) => {
|
||||
const blame = c.blameRequestId
|
||||
? blameById.get(c.blameRequestId.toString())
|
||||
: undefined;
|
||||
const v = this.vehicleForExpertFromClaimAndBlameMap(c, blameById);
|
||||
const fileCtx = blame ? this.blameFileContextForExpert(blame) : {};
|
||||
const lockActive = !!(
|
||||
c.workflow?.locked && this.isClaimV2WorkflowLockCurrentlyEnforced(c)
|
||||
);
|
||||
return {
|
||||
claimRequestId: c._id.toString(),
|
||||
publicId: c.publicId,
|
||||
status: c.status,
|
||||
unifiedFileStatus: resolveUnifiedFileStatus({
|
||||
blameStatus: blame?.status,
|
||||
claimStatus: c.status,
|
||||
}),
|
||||
currentStep: c.workflow?.currentStep || "",
|
||||
locked: lockActive,
|
||||
lockedBy:
|
||||
lockActive && c.workflow?.lockedBy
|
||||
? {
|
||||
actorId: c.workflow.lockedBy.actorId?.toString(),
|
||||
actorName: c.workflow.lockedBy.actorName,
|
||||
lockedAt: (c.workflow as any).lockedAt?.toISOString?.(),
|
||||
expiredAt: (c.workflow as any).expiredAt?.toISOString?.(),
|
||||
}
|
||||
: undefined,
|
||||
vehicle: v
|
||||
? { carName: v.carName, carModel: v.carModel, carType: v.carType }
|
||||
: undefined,
|
||||
...fileCtx,
|
||||
createdAt: c.createdAt,
|
||||
awaitingFactorValidation: claimIsAwaitingExpertFactorValidationV2(c),
|
||||
needsFileReviewerCompletion:
|
||||
String(blame?.status ?? "") === "WAITING_FOR_FILE_REVIEWER",
|
||||
};
|
||||
}) as ClaimListItemV2Dto[];
|
||||
|
||||
return this.paginateClaimListV2(list, query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load linked blame case for damage-expert claim detail (same enrichment as expert-blame `findOneV2`:
|
||||
* party evidence `videoUrl` / `voiceUrls`, Jalali date strings).
|
||||
@@ -4062,7 +4156,10 @@ export class ExpertClaimService {
|
||||
clientKey?: string;
|
||||
role?: string;
|
||||
}): Promise<void> {
|
||||
if ((actor as any).role === RoleEnum.FIELD_EXPERT) return;
|
||||
if (
|
||||
(actor as any).role === RoleEnum.FIELD_EXPERT ||
|
||||
(actor as any).role === RoleEnum.FILE_REVIEWER
|
||||
) return;
|
||||
const clientKey = requireActorClientKey(actor);
|
||||
const lockTtlMs = EXPERT_WORKFLOW_LOCK_TTL_MS;
|
||||
const now = new Date();
|
||||
@@ -4242,10 +4339,28 @@ export class ExpertClaimService {
|
||||
const isFactorValidationPending =
|
||||
claimIsAwaitingExpertFactorValidationV2(claim);
|
||||
|
||||
// Field experts can always view their own initiated claims regardless of status
|
||||
if (actor.role === RoleEnum.FIELD_EXPERT) {
|
||||
// Field experts and FileReviewers can always view IN_PERSON expert-initiated
|
||||
// claims regardless of claim status (they work across multiple non-standard steps).
|
||||
if (
|
||||
actor.role === RoleEnum.FIELD_EXPERT ||
|
||||
actor.role === RoleEnum.FILE_REVIEWER
|
||||
) {
|
||||
if (!claimCaseInitiatedByFieldExpert(claim, actor, linkedBlame)) {
|
||||
throw new ForbiddenException("This claim was not initiated by you.");
|
||||
// For FILE_REVIEWER: also accept if the linked blame is sealed for them
|
||||
const isFileReviewerEligible =
|
||||
actor.role === RoleEnum.FILE_REVIEWER &&
|
||||
linkedBlame?.expertInitiated &&
|
||||
linkedBlame?.creationMethod === "IN_PERSON" &&
|
||||
[
|
||||
"WAITING_FOR_FILE_REVIEWER",
|
||||
"WAITING_FOR_EXPERT",
|
||||
"COMPLETED",
|
||||
].includes(String(linkedBlame?.status ?? ""));
|
||||
if (!isFileReviewerEligible) {
|
||||
throw new ForbiddenException(
|
||||
"This claim is not accessible to you.",
|
||||
);
|
||||
}
|
||||
}
|
||||
// Fall through to the detail build below (skip the damage-expert gate)
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user