1
0
forked from Yara724/api
This commit is contained in:
2026-05-01 11:37:24 +03:30
parent 6f120b0066
commit 6429cb0f2b

View File

@@ -245,6 +245,24 @@ export class ExpertClaimService {
return String(actor.clientKey ?? ""); return String(actor.clientKey ?? "");
} }
/**
* `preLockQueueSnapshot` must only store {@link ClaimWorkflowStep} values.
* Legacy / mistaken data sometimes put {@link ClaimCaseStatus} (e.g. WAITING_FOR_DAMAGE_EXPERT)
* in `workflow.currentStep`, which would fail Mongoose enum validation when snapshotted.
*/
private normalizeClaimWorkflowStepForSnapshot(
value: unknown,
fallback: ClaimWorkflowStep,
): ClaimWorkflowStep {
if (
typeof value === "string" &&
(Object.values(ClaimWorkflowStep) as string[]).includes(value)
) {
return value as ClaimWorkflowStep;
}
return fallback;
}
/** Owner mobile: linked blame party phone when available, else `users.mobile`. */ /** Owner mobile: linked blame party phone when available, else `users.mobile`. */
private async resolveClaimOwnerPhone(claim: any): Promise<string | undefined> { private async resolveClaimOwnerPhone(claim: any): Promise<string | undefined> {
if (!claim?.owner?.userId) return undefined; if (!claim?.owner?.userId) return undefined;
@@ -2226,20 +2244,30 @@ export class ExpertClaimService {
}, },
'workflow.preLockQueueSnapshot': { 'workflow.preLockQueueSnapshot': {
claimStatus: claim.claimStatus, claimStatus: claim.claimStatus,
currentStep: currentStep: this.normalizeClaimWorkflowStepForSnapshot(
claim.workflow?.currentStep ?? ClaimWorkflowStep.USER_SUBMISSION_COMPLETE, claim.workflow?.currentStep,
ClaimWorkflowStep.USER_SUBMISSION_COMPLETE,
),
...(claim.workflow?.nextStep != null ...(claim.workflow?.nextStep != null
? { nextStep: claim.workflow.nextStep } ? {
nextStep: this.normalizeClaimWorkflowStepForSnapshot(
claim.workflow.nextStep,
ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT,
),
}
: {}), : {}),
}, },
'workflow.currentStep': ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT, 'workflow.currentStep': ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT,
$push: { $push: {
history: { history: {
event: 'CLAIM_LOCKED', type: "CLAIM_LOCKED",
performedBy: actor.sub, actor: {
performedByName: actor.fullName, actorId: new Types.ObjectId(actor.sub),
performedAt: new Date(), actorName: actor.fullName,
note: `Claim locked by damage expert ${actor.fullName}`, actorType: "damage_expert",
},
timestamp: new Date(),
metadata: { note: `Claim locked by damage expert ${actor.fullName}` },
}, },
}, },
}); });
@@ -2657,11 +2685,16 @@ export class ExpertClaimService {
}), }),
$push: { $push: {
history: { history: {
event: 'IN_PERSON_VISIT_REQUESTED', type: "IN_PERSON_VISIT_REQUESTED",
performedBy: actor.sub, actor: {
performedByName: actor.fullName, actorId: new Types.ObjectId(actor.sub),
performedAt: new Date(), actorName: actor.fullName,
note: note || 'Expert requested in-person visit', actorType: "damage_expert",
},
timestamp: new Date(),
metadata: {
note: note || "Expert requested in-person visit",
},
}, },
}, },
}); });
@@ -2678,7 +2711,7 @@ export class ExpertClaimService {
claimRequestId, claimRequestId,
status: claim.status, status: claim.status,
claimStatus: ClaimStatus.NEEDS_REVISION, claimStatus: ClaimStatus.NEEDS_REVISION,
message: 'In-person visit requested. User will be notified.', message: "In-person visit requested. User will be notified.",
}; };
} }
@@ -3106,11 +3139,16 @@ export class ExpertClaimService {
| undefined; | undefined;
const restoreClaimStatus = snap?.claimStatus ?? ClaimStatus.PENDING; const restoreClaimStatus = snap?.claimStatus ?? ClaimStatus.PENDING;
const restoreCurrent = const restoreCurrent = this.normalizeClaimWorkflowStepForSnapshot(
snap?.currentStep ?? ClaimWorkflowStep.USER_SUBMISSION_COMPLETE; snap?.currentStep,
ClaimWorkflowStep.USER_SUBMISSION_COMPLETE,
);
const restoreNext = const restoreNext =
snap?.nextStep != null snap?.nextStep != null
? snap.nextStep ? this.normalizeClaimWorkflowStepForSnapshot(
snap.nextStep,
ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT,
)
: ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT; : ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT;
const lockFieldsUnset = { const lockFieldsUnset = {
@@ -3455,31 +3493,41 @@ export class ExpertClaimService {
: []; : [];
const selectedParts = body.selectedParts as string[]; const selectedParts = body.selectedParts as string[];
if (!(claim as any).damage) (claim as any).damage = {}; const $set: Record<string, unknown> = {
(claim as any).damage.selectedParts = selectedParts; "damage.selectedParts": selectedParts,
};
// Keep damaged-parts captures consistent with updated selection.
const damagedPartsMedia = (claim as any).media?.damagedParts; const damagedPartsMedia = (claim as any).media?.damagedParts;
if (damagedPartsMedia) { if (damagedPartsMedia) {
const selectedSet = new Set(selectedParts); const selectedSet = new Set(selectedParts);
if (damagedPartsMedia instanceof Map) { if (damagedPartsMedia instanceof Map) {
for (const key of Array.from(damagedPartsMedia.keys())) { const m = new Map(damagedPartsMedia as Map<string, unknown>);
if (!selectedSet.has(key)) damagedPartsMedia.delete(key); for (const key of Array.from(m.keys())) {
if (!selectedSet.has(key)) m.delete(key);
} }
$set["media.damagedParts"] = Object.fromEntries(m.entries());
} else { } else {
for (const key of Object.keys(damagedPartsMedia)) { const o = {
if (!selectedSet.has(key)) delete damagedPartsMedia[key]; ...(damagedPartsMedia as Record<string, unknown>),
};
for (const key of Object.keys(o)) {
if (!selectedSet.has(key)) delete o[key];
} }
$set["media.damagedParts"] = o;
} }
} }
if (!Array.isArray((claim as any).history)) (claim as any).history = []; await this.claimCaseDbService.findByIdAndUpdate(claimRequestId, {
(claim as any).history.push({ $set,
event: "EXPERT_DAMAGED_PARTS_UPDATED", $push: {
performedBy: actor.sub, history: {
performedByName: actor.fullName, type: "EXPERT_DAMAGED_PARTS_UPDATED",
performedAt: new Date(), actor: {
note: "Damage expert edited selected damaged parts", actorId: new Types.ObjectId(actor.sub),
actorName: actor.fullName,
actorType: "damage_expert",
},
timestamp: new Date(),
metadata: { metadata: {
previousSelectedParts: previous, previousSelectedParts: previous,
selectedParts, selectedParts,
@@ -3487,10 +3535,10 @@ export class ExpertClaimService {
expertProfileSnapshot: damagedPartsEditSnapshot, expertProfileSnapshot: damagedPartsEditSnapshot,
}), }),
}, },
},
},
}); });
await (claim as any).save();
return { return {
claimRequestId: claim._id.toString(), claimRequestId: claim._id.toString(),
selectedParts, selectedParts,