forked from Yara724/api
merge upstream
This commit is contained in:
@@ -64,6 +64,9 @@ import { resendRequestHasPayload } from "src/helpers/claim-expert-resend";
|
|||||||
export class ExpertClaimService {
|
export class ExpertClaimService {
|
||||||
private readonly logger = new Logger(ExpertClaimService.name);
|
private readonly logger = new Logger(ExpertClaimService.name);
|
||||||
|
|
||||||
|
/** Matches blame v2 `workflow` lock TTL: locker may re-enter until expired, then others may open. */
|
||||||
|
private readonly claimV2WorkflowLockTtlMs = 15 * 60 * 1000;
|
||||||
|
|
||||||
private readonly priceDropPart = {
|
private readonly priceDropPart = {
|
||||||
backFender: {
|
backFender: {
|
||||||
Minor: 2,
|
Minor: 2,
|
||||||
@@ -2551,13 +2554,28 @@ export class ExpertClaimService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True when another expert still holds an active (non-expired) workflow lock.
|
||||||
|
* Missing `lockedAt` on old documents: treat lock as still enforced until cleared.
|
||||||
|
*/
|
||||||
|
private isClaimV2WorkflowLockCurrentlyEnforced(claim: any): boolean {
|
||||||
|
if (!claim?.workflow?.locked) return false;
|
||||||
|
const la = claim.workflow?.lockedAt as Date | string | undefined;
|
||||||
|
if (!la) return true;
|
||||||
|
return (
|
||||||
|
Date.now() <
|
||||||
|
new Date(la).getTime() + this.claimV2WorkflowLockTtlMs
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* V2: Get claim detail for damage expert
|
* V2: Get claim detail for damage expert
|
||||||
*
|
*
|
||||||
* Validations:
|
* Validations:
|
||||||
* - Claim must exist and belong to the actor's insurer (`assertClaimCaseForTenant`)
|
* - Claim must exist and belong to the actor's insurer (`assertClaimCaseForTenant`)
|
||||||
* - Allowed when picking up/reviewing: WAITING_FOR_DAMAGE_EXPERT (if locked, only the locking expert)
|
* - Allowed when: WAITING_FOR_DAMAGE_EXPERT (queue), or EXPERT_REVIEWING (after lock — same expert must be able to reopen detail),
|
||||||
* - Or when validating factors: WAITING_FOR_INSURER_APPROVAL + UNDER_REVIEW at EXPERT_COST_EVALUATION
|
* or factor-validation queue (WAITING_FOR_INSURER_APPROVAL + UNDER_REVIEW + EXPERT_COST_EVALUATION)
|
||||||
|
* - If an active workflow lock exists (15 min from lockedAt): only the locking expert; after expiry, any expert (tenant) may view
|
||||||
*/
|
*/
|
||||||
async getClaimDetailV2(
|
async getClaimDetailV2(
|
||||||
claimRequestId: string,
|
claimRequestId: string,
|
||||||
@@ -2572,29 +2590,29 @@ export class ExpertClaimService {
|
|||||||
|
|
||||||
assertClaimCaseForTenant(claim, actor);
|
assertClaimCaseForTenant(claim, actor);
|
||||||
|
|
||||||
const isPickupReview =
|
const isDamageExpertPhase =
|
||||||
claim.status === ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT;
|
claim.status === ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT ||
|
||||||
|
claim.status === ClaimCaseStatus.EXPERT_REVIEWING;
|
||||||
const isFactorValidationPending =
|
const isFactorValidationPending =
|
||||||
claim.status === ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL &&
|
claim.status === ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL &&
|
||||||
claim.claimStatus === ClaimStatus.UNDER_REVIEW &&
|
claim.claimStatus === ClaimStatus.UNDER_REVIEW &&
|
||||||
claim.workflow?.currentStep === ClaimWorkflowStep.EXPERT_COST_EVALUATION;
|
claim.workflow?.currentStep === ClaimWorkflowStep.EXPERT_COST_EVALUATION;
|
||||||
|
|
||||||
if (!isPickupReview && !isFactorValidationPending) {
|
if (!isDamageExpertPhase && !isFactorValidationPending) {
|
||||||
throw new ForbiddenException(
|
throw new ForbiddenException(
|
||||||
`This claim is not available for expert review. Current status: ${claim.status}`,
|
`This claim is not available for expert review. Current status: ${claim.status}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If locked by someone else, deny access (initial pickup / assessment only)
|
const lockBlocksOthers = this.isClaimV2WorkflowLockCurrentlyEnforced(claim);
|
||||||
if (
|
if (lockBlocksOthers) {
|
||||||
isPickupReview &&
|
const lockerId = claim.workflow?.lockedBy?.actorId?.toString();
|
||||||
claim.workflow?.locked &&
|
if (lockerId && lockerId !== actorId) {
|
||||||
claim.workflow.lockedBy?.actorId?.toString() !== actorId
|
|
||||||
) {
|
|
||||||
throw new ForbiddenException(
|
throw new ForbiddenException(
|
||||||
`This claim is locked by another expert: ${claim.workflow.lockedBy?.actorName}`,
|
`This claim is locked by another expert: ${claim.workflow.lockedBy?.actorName}`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const hasCapture = (data: any, key: string) =>
|
const hasCapture = (data: any, key: string) =>
|
||||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||||
|
|||||||
Reference in New Issue
Block a user