forked from Yara724/api
Compare commits
4 Commits
fca88bc151
...
af1a07743e
| Author | SHA1 | Date | |
|---|---|---|---|
| af1a07743e | |||
| 277f2d4d66 | |||
|
|
514018beb1 | ||
| 374b15933d |
@@ -64,6 +64,9 @@ import { resendRequestHasPayload } from "src/helpers/claim-expert-resend";
|
||||
export class ExpertClaimService {
|
||||
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 = {
|
||||
backFender: {
|
||||
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
|
||||
*
|
||||
* Validations:
|
||||
* - 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)
|
||||
* - Or when validating factors: WAITING_FOR_INSURER_APPROVAL + UNDER_REVIEW at EXPERT_COST_EVALUATION
|
||||
* - Allowed when: WAITING_FOR_DAMAGE_EXPERT (queue), or EXPERT_REVIEWING (after lock — same expert must be able to reopen detail),
|
||||
* 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(
|
||||
claimRequestId: string,
|
||||
@@ -2572,29 +2590,29 @@ export class ExpertClaimService {
|
||||
|
||||
assertClaimCaseForTenant(claim, actor);
|
||||
|
||||
const isPickupReview =
|
||||
claim.status === ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT;
|
||||
const isDamageExpertPhase =
|
||||
claim.status === ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT ||
|
||||
claim.status === ClaimCaseStatus.EXPERT_REVIEWING;
|
||||
const isFactorValidationPending =
|
||||
claim.status === ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL &&
|
||||
claim.claimStatus === ClaimStatus.UNDER_REVIEW &&
|
||||
claim.workflow?.currentStep === ClaimWorkflowStep.EXPERT_COST_EVALUATION;
|
||||
|
||||
if (!isPickupReview && !isFactorValidationPending) {
|
||||
if (!isDamageExpertPhase && !isFactorValidationPending) {
|
||||
throw new ForbiddenException(
|
||||
`This claim is not available for expert review. Current status: ${claim.status}`,
|
||||
);
|
||||
}
|
||||
|
||||
// If locked by someone else, deny access (initial pickup / assessment only)
|
||||
if (
|
||||
isPickupReview &&
|
||||
claim.workflow?.locked &&
|
||||
claim.workflow.lockedBy?.actorId?.toString() !== actorId
|
||||
) {
|
||||
const lockBlocksOthers = this.isClaimV2WorkflowLockCurrentlyEnforced(claim);
|
||||
if (lockBlocksOthers) {
|
||||
const lockerId = claim.workflow?.lockedBy?.actorId?.toString();
|
||||
if (lockerId && lockerId !== actorId) {
|
||||
throw new ForbiddenException(
|
||||
`This claim is locked by another expert: ${claim.workflow.lockedBy?.actorName}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const hasCapture = (data: any, key: string) =>
|
||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||
|
||||
Reference in New Issue
Block a user