forked from Yara724/api
YARA-867
This commit is contained in:
@@ -99,6 +99,16 @@ export class ClaimDetailV2ResponseDto {
|
||||
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({
|
||||
description:
|
||||
'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,
|
||||
'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
|
||||
{
|
||||
'workflow.locked': true,
|
||||
@@ -2919,6 +2924,34 @@ export class ExpertClaimService {
|
||||
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). */
|
||||
private serializeBlameExpertDecisionForClaimDetail(
|
||||
decision: unknown,
|
||||
@@ -3025,8 +3058,9 @@ export class ExpertClaimService {
|
||||
|
||||
/**
|
||||
* Persist unlock when claim V2 workflow lock TTL has passed.
|
||||
* If the expert never submitted a damage reply, restores queue fields from
|
||||
* `workflow.preLockQueueSnapshot` (or defaults) so the case shows as WAITING_FOR_DAMAGE_EXPERT again.
|
||||
* When the case was in {@link ClaimCaseStatus.EXPERT_REVIEWING}, restores queue fields from
|
||||
* `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(
|
||||
claimRequestId: string,
|
||||
@@ -3047,7 +3081,6 @@ export class ExpertClaimService {
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!expiredAt && !lockedAt) return false;
|
||||
|
||||
const lockedById = claim.workflow.lockedBy?.actorId;
|
||||
const filter: Record<string, unknown> = {
|
||||
@@ -3059,12 +3092,10 @@ export class ExpertClaimService {
|
||||
} else if (lockedAt) {
|
||||
filter["workflow.lockedAt"] = lockedAt;
|
||||
} else if (lockedById) {
|
||||
filter["workflow.lockedBy.actorId"] = lockedById;
|
||||
filter["workflow.lockedBy.actorId"] = new Types.ObjectId(String(lockedById));
|
||||
}
|
||||
|
||||
const needsQueueRestore =
|
||||
claim.status === ClaimCaseStatus.EXPERT_REVIEWING &&
|
||||
!this.claimHasDamageExpertReply(claim);
|
||||
const needsQueueRestore = claim.status === ClaimCaseStatus.EXPERT_REVIEWING;
|
||||
|
||||
const snap = claim.workflow?.preLockQueueSnapshot as
|
||||
| {
|
||||
@@ -3136,6 +3167,7 @@ export class ExpertClaimService {
|
||||
actor: any,
|
||||
): Promise<ClaimDetailV2ResponseDto> {
|
||||
const actorId = actor.sub;
|
||||
await this.reconcileStaleExpertReviewingClaimLocksForTenant(actor);
|
||||
await this.expireClaimWorkflowLockV2IfStale(claimRequestId);
|
||||
const claim = await this.claimCaseDbService.findById(claimRequestId);
|
||||
|
||||
@@ -3319,6 +3351,21 @@ export class ExpertClaimService {
|
||||
? ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT
|
||||
: 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 {
|
||||
claimRequestId: claim._id.toString(),
|
||||
publicId: claim.publicId,
|
||||
@@ -3341,7 +3388,9 @@ export class ExpertClaimService {
|
||||
fullName: claim.owner.fullName,
|
||||
}
|
||||
: undefined,
|
||||
vehicle: vehiclePayload,
|
||||
vehicle: vehiclePayload
|
||||
? this.sanitizeVehicleInquiryForApi(vehiclePayload)
|
||||
: undefined,
|
||||
...blameFileContext,
|
||||
blameRequestId: claim.blameRequestId?.toString(),
|
||||
blameRequestNo: claim.blameRequestNo,
|
||||
@@ -3361,8 +3410,9 @@ export class ExpertClaimService {
|
||||
damageExpertReplyFinal: (claim as any).evaluation?.damageExpertReplyFinal,
|
||||
}
|
||||
: undefined,
|
||||
objection,
|
||||
videoCapture,
|
||||
blameCase: blameCase ?? undefined,
|
||||
blameCase: blameCaseForApi,
|
||||
blameExpertDecision,
|
||||
createdAt: (claim as any).createdAt,
|
||||
updatedAt: (claim as any).updatedAt,
|
||||
|
||||
Reference in New Issue
Block a user