forked from Yara724/api
YARA-867
This commit is contained in:
@@ -85,7 +85,7 @@ export class ClaimRequestManagementV2Controller {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Get Claim Details (V2)",
|
summary: "Get Claim Details (V2)",
|
||||||
description:
|
description:
|
||||||
"Get claim details for current actor. USER receives only minimal own-needed payload (no extra owner/security fields). FIELD_EXPERT keeps full view for expert workflows.",
|
"Get claim details for current actor. USER (claim owner) receives the same core claim payload including `owner` (userId, clientId, optional userClientKey). FIELD_EXPERT additionally receives unmasked money and userRating when present.",
|
||||||
})
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
|
|||||||
@@ -99,6 +99,16 @@ export class ClaimDetailV2ResponseDto {
|
|||||||
damageExpertReplyFinal?: unknown;
|
damageExpertReplyFinal?: unknown;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ApiPropertyOptional({
|
||||||
|
description:
|
||||||
|
'Owner objection to expert-priced parts (`evaluation.objection`): disputed lines + optional new parts + submission time.',
|
||||||
|
})
|
||||||
|
objection?: {
|
||||||
|
objectionParts?: Array<Record<string, unknown>>;
|
||||||
|
newParts?: Array<Record<string, unknown>>;
|
||||||
|
submittedAt?: Date | string;
|
||||||
|
};
|
||||||
|
|
||||||
@ApiPropertyOptional({
|
@ApiPropertyOptional({
|
||||||
description:
|
description:
|
||||||
'Car walk-around video from `claim-video-capture` (resolved from `media.videoCaptureId`).',
|
'Car walk-around video from `claim-video-capture` (resolved from `media.videoCaptureId`).',
|
||||||
|
|||||||
@@ -2723,6 +2723,11 @@ export class ExpertClaimService {
|
|||||||
status: ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT,
|
status: ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT,
|
||||||
'workflow.locked': { $ne: true },
|
'workflow.locked': { $ne: true },
|
||||||
},
|
},
|
||||||
|
// Expert reviewing but lock cleared (e.g. TTL expiry) — still list until status is reconciled
|
||||||
|
{
|
||||||
|
status: ClaimCaseStatus.EXPERT_REVIEWING,
|
||||||
|
'workflow.locked': { $ne: true },
|
||||||
|
},
|
||||||
// This expert's own locked/in-progress claims
|
// This expert's own locked/in-progress claims
|
||||||
{
|
{
|
||||||
'workflow.locked': true,
|
'workflow.locked': true,
|
||||||
@@ -2919,6 +2924,34 @@ export class ExpertClaimService {
|
|||||||
return docRec;
|
return docRec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Strip bulky insurer-inquiry payloads (`raw` / `mapped`) from vehicle.inquiry. */
|
||||||
|
private sanitizeVehicleInquiryForApi(vehicle: any) {
|
||||||
|
if (!vehicle || typeof vehicle !== "object") return vehicle;
|
||||||
|
const inquiry = vehicle.inquiry;
|
||||||
|
if (!inquiry || typeof inquiry !== "object") return vehicle;
|
||||||
|
const { raw, mapped, ...safeInquiry } = inquiry as Record<string, unknown>;
|
||||||
|
return {
|
||||||
|
...vehicle,
|
||||||
|
inquiry: safeInquiry,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Linked blame snapshot for damage-expert detail: keep API response lean. */
|
||||||
|
private sanitizeBlameCaseForClaimDetailApi(
|
||||||
|
blame: Record<string, unknown>,
|
||||||
|
): Record<string, unknown> {
|
||||||
|
const out = { ...blame };
|
||||||
|
const parties = out.parties;
|
||||||
|
if (Array.isArray(parties)) {
|
||||||
|
out.parties = parties.map((p: any) =>
|
||||||
|
p && typeof p === "object"
|
||||||
|
? { ...p, vehicle: this.sanitizeVehicleInquiryForApi(p.vehicle) }
|
||||||
|
: p,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
/** JSON-safe `expert.decision` for API responses (ObjectIds → string). */
|
/** JSON-safe `expert.decision` for API responses (ObjectIds → string). */
|
||||||
private serializeBlameExpertDecisionForClaimDetail(
|
private serializeBlameExpertDecisionForClaimDetail(
|
||||||
decision: unknown,
|
decision: unknown,
|
||||||
@@ -3025,8 +3058,9 @@ export class ExpertClaimService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Persist unlock when claim V2 workflow lock TTL has passed.
|
* Persist unlock when claim V2 workflow lock TTL has passed.
|
||||||
* If the expert never submitted a damage reply, restores queue fields from
|
* When the case was in {@link ClaimCaseStatus.EXPERT_REVIEWING}, restores queue fields from
|
||||||
* `workflow.preLockQueueSnapshot` (or defaults) so the case shows as WAITING_FOR_DAMAGE_EXPERT again.
|
* `workflow.preLockQueueSnapshot` (or defaults) and sets status back to WAITING_FOR_DAMAGE_EXPERT
|
||||||
|
* so the claim reappears in the open expert queue (same intent as blame list expiry + in-memory unlock).
|
||||||
*/
|
*/
|
||||||
private async expireClaimWorkflowLockV2IfStale(
|
private async expireClaimWorkflowLockV2IfStale(
|
||||||
claimRequestId: string,
|
claimRequestId: string,
|
||||||
@@ -3047,7 +3081,6 @@ export class ExpertClaimService {
|
|||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!expiredAt && !lockedAt) return false;
|
|
||||||
|
|
||||||
const lockedById = claim.workflow.lockedBy?.actorId;
|
const lockedById = claim.workflow.lockedBy?.actorId;
|
||||||
const filter: Record<string, unknown> = {
|
const filter: Record<string, unknown> = {
|
||||||
@@ -3059,12 +3092,10 @@ export class ExpertClaimService {
|
|||||||
} else if (lockedAt) {
|
} else if (lockedAt) {
|
||||||
filter["workflow.lockedAt"] = lockedAt;
|
filter["workflow.lockedAt"] = lockedAt;
|
||||||
} else if (lockedById) {
|
} else if (lockedById) {
|
||||||
filter["workflow.lockedBy.actorId"] = lockedById;
|
filter["workflow.lockedBy.actorId"] = new Types.ObjectId(String(lockedById));
|
||||||
}
|
}
|
||||||
|
|
||||||
const needsQueueRestore =
|
const needsQueueRestore = claim.status === ClaimCaseStatus.EXPERT_REVIEWING;
|
||||||
claim.status === ClaimCaseStatus.EXPERT_REVIEWING &&
|
|
||||||
!this.claimHasDamageExpertReply(claim);
|
|
||||||
|
|
||||||
const snap = claim.workflow?.preLockQueueSnapshot as
|
const snap = claim.workflow?.preLockQueueSnapshot as
|
||||||
| {
|
| {
|
||||||
@@ -3136,6 +3167,7 @@ export class ExpertClaimService {
|
|||||||
actor: any,
|
actor: any,
|
||||||
): Promise<ClaimDetailV2ResponseDto> {
|
): Promise<ClaimDetailV2ResponseDto> {
|
||||||
const actorId = actor.sub;
|
const actorId = actor.sub;
|
||||||
|
await this.reconcileStaleExpertReviewingClaimLocksForTenant(actor);
|
||||||
await this.expireClaimWorkflowLockV2IfStale(claimRequestId);
|
await this.expireClaimWorkflowLockV2IfStale(claimRequestId);
|
||||||
const claim = await this.claimCaseDbService.findById(claimRequestId);
|
const claim = await this.claimCaseDbService.findById(claimRequestId);
|
||||||
|
|
||||||
@@ -3319,6 +3351,21 @@ export class ExpertClaimService {
|
|||||||
? ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT
|
? ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT
|
||||||
: claim.status;
|
: claim.status;
|
||||||
|
|
||||||
|
const objection = (claim as any).evaluation?.objection
|
||||||
|
? {
|
||||||
|
objectionParts:
|
||||||
|
(claim as any).evaluation.objection.objectionParts ?? [],
|
||||||
|
newParts: (claim as any).evaluation.objection.newParts ?? [],
|
||||||
|
submittedAt: (claim as any).evaluation.objection.submittedAt,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const blameCaseForApi = blameCase
|
||||||
|
? this.sanitizeBlameCaseForClaimDetailApi(
|
||||||
|
blameCase as Record<string, unknown>,
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
claimRequestId: claim._id.toString(),
|
claimRequestId: claim._id.toString(),
|
||||||
publicId: claim.publicId,
|
publicId: claim.publicId,
|
||||||
@@ -3341,7 +3388,9 @@ export class ExpertClaimService {
|
|||||||
fullName: claim.owner.fullName,
|
fullName: claim.owner.fullName,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
vehicle: vehiclePayload,
|
vehicle: vehiclePayload
|
||||||
|
? this.sanitizeVehicleInquiryForApi(vehiclePayload)
|
||||||
|
: undefined,
|
||||||
...blameFileContext,
|
...blameFileContext,
|
||||||
blameRequestId: claim.blameRequestId?.toString(),
|
blameRequestId: claim.blameRequestId?.toString(),
|
||||||
blameRequestNo: claim.blameRequestNo,
|
blameRequestNo: claim.blameRequestNo,
|
||||||
@@ -3361,8 +3410,9 @@ export class ExpertClaimService {
|
|||||||
damageExpertReplyFinal: (claim as any).evaluation?.damageExpertReplyFinal,
|
damageExpertReplyFinal: (claim as any).evaluation?.damageExpertReplyFinal,
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
|
objection,
|
||||||
videoCapture,
|
videoCapture,
|
||||||
blameCase: blameCase ?? undefined,
|
blameCase: blameCaseForApi,
|
||||||
blameExpertDecision,
|
blameExpertDecision,
|
||||||
createdAt: (claim as any).createdAt,
|
createdAt: (claim as any).createdAt,
|
||||||
updatedAt: (claim as any).updatedAt,
|
updatedAt: (claim as any).updatedAt,
|
||||||
|
|||||||
Reference in New Issue
Block a user