forked from Yara724/api
131 lines
5.1 KiB
TypeScript
131 lines
5.1 KiB
TypeScript
import { ClaimCaseStatus } from "src/Types&Enums/claim-request-management/claim-case-status.enum";
|
|
import { ClaimStatus } from "src/Types&Enums/claim-request-management/claimStatus.enum";
|
|
import { ClaimWorkflowStep } from "src/Types&Enums/claim-request-management/claim-workflow-steps.enum";
|
|
|
|
export interface ClaimPricingPartLite {
|
|
factorNeeded?: boolean;
|
|
/** Numeric catalog id (legacy string values may still exist in old documents). */
|
|
partId?: number | string;
|
|
}
|
|
|
|
export function getActiveV2ExpertReply(claim: { evaluation?: Record<string, unknown> }): {
|
|
replyKey: "damageExpertReplyFinal" | "damageExpertReply";
|
|
reply: Record<string, unknown>;
|
|
parts: ClaimPricingPartLite[];
|
|
} | null {
|
|
const fin = claim.evaluation?.damageExpertReplyFinal as
|
|
| { parts?: ClaimPricingPartLite[]; submittedAt?: Date }
|
|
| undefined;
|
|
const ini = claim.evaluation?.damageExpertReply as
|
|
| { parts?: ClaimPricingPartLite[]; submittedAt?: Date }
|
|
| undefined;
|
|
if (fin?.submittedAt && fin?.parts?.length) {
|
|
return { replyKey: "damageExpertReplyFinal", reply: fin as Record<string, unknown>, parts: fin.parts };
|
|
}
|
|
if (ini?.submittedAt && ini?.parts?.length) {
|
|
return { replyKey: "damageExpertReply", reply: ini as Record<string, unknown>, parts: ini.parts };
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export function classifyV2ExpertPricingParts(parts: ClaimPricingPartLite[]) {
|
|
const factorNeeded = parts.filter((p) => p.factorNeeded === true);
|
|
const priced = parts.filter((p) => p.factorNeeded !== true);
|
|
return {
|
|
pricedPartsCount: priced.length,
|
|
factorNeededPartsCount: factorNeeded.length,
|
|
mixedFactorAndPrice:
|
|
factorNeeded.length > 0 && priced.length > 0,
|
|
allFactorLines: factorNeeded.length > 0 && priced.length === 0,
|
|
noFactors: factorNeeded.length === 0,
|
|
};
|
|
}
|
|
|
|
const OWNER_POST_EXPERT_INSURER_SIGNATURE_STATUSES: ReadonlySet<string> = new Set([
|
|
ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL,
|
|
ClaimCaseStatus.INSURER_REVIEW_AWAITING_OWNER_SIGN,
|
|
ClaimCaseStatus.INSURER_REVIEW_MIXED_FACTORS_PENDING,
|
|
]);
|
|
|
|
const OWNER_FACTOR_UPLOAD_PHASE_STATUSES: ReadonlySet<string> = new Set([
|
|
ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL,
|
|
ClaimCaseStatus.OWNER_REPAIR_FACTOR_UPLOAD_PENDING,
|
|
ClaimCaseStatus.INSURER_REVIEW_MIXED_FACTORS_PENDING,
|
|
]);
|
|
|
|
const V2_POST_EXPERT_OWNER_PIPELINE_STATUSES: ReadonlySet<string> = new Set([
|
|
ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL,
|
|
ClaimCaseStatus.INSURER_REVIEW_AWAITING_OWNER_SIGN,
|
|
ClaimCaseStatus.INSURER_REVIEW_MIXED_FACTORS_PENDING,
|
|
ClaimCaseStatus.OWNER_REPAIR_FACTOR_UPLOAD_PENDING,
|
|
ClaimCaseStatus.EXPERT_VALIDATING_REPAIR_FACTORS,
|
|
]);
|
|
|
|
/** Owner multipart sign at `INSURER_REVIEW` (priced-line gate or final acceptance). */
|
|
export function claimCaseStatusAllowsOwnerInsurerSignStep(
|
|
status: ClaimCaseStatus | string | undefined,
|
|
): boolean {
|
|
return OWNER_POST_EXPERT_INSURER_SIGNATURE_STATUSES.has(String(status ?? ""));
|
|
}
|
|
|
|
/** Repair-factor upload during `NEEDS_REVISION` @ `OWNER_UPLOAD_FACTOR_DOCUMENTS`. */
|
|
export function claimCaseStatusAllowsOwnerFactorUploadDuringRevision(
|
|
status: ClaimCaseStatus | string | undefined,
|
|
): boolean {
|
|
return OWNER_FACTOR_UPLOAD_PHASE_STATUSES.has(String(status ?? ""));
|
|
}
|
|
|
|
/** Owner-facing post-expert flow: signatures, factor uploads, or waiting on expert factor validation. */
|
|
export function claimCaseStatusIsV2OwnerPostExpertPipeline(
|
|
status: ClaimCaseStatus | string | undefined,
|
|
): boolean {
|
|
return V2_POST_EXPERT_OWNER_PIPELINE_STATUSES.has(String(status ?? ""));
|
|
}
|
|
|
|
export function claimIsAwaitingExpertFactorValidationV2(claim: {
|
|
status?: ClaimCaseStatus | string;
|
|
claimStatus?: ClaimStatus;
|
|
workflow?: { currentStep?: string };
|
|
}): boolean {
|
|
return (
|
|
claim.claimStatus === ClaimStatus.UNDER_REVIEW &&
|
|
claim.workflow?.currentStep === ClaimWorkflowStep.EXPERT_COST_EVALUATION &&
|
|
(claim.status === ClaimCaseStatus.EXPERT_VALIDATING_REPAIR_FACTORS ||
|
|
claim.status === ClaimCaseStatus.WAITING_FOR_INSURER_APPROVAL)
|
|
);
|
|
}
|
|
|
|
export function claimCaseStatusAfterExpertReplyV2(parts: ClaimPricingPartLite[]): ClaimCaseStatus {
|
|
const { mixedFactorAndPrice } = classifyV2ExpertPricingParts(parts);
|
|
const needsFactorUpload = parts.some((p) => p.factorNeeded === true);
|
|
if (!needsFactorUpload) {
|
|
return ClaimCaseStatus.INSURER_REVIEW_AWAITING_OWNER_SIGN;
|
|
}
|
|
if (mixedFactorAndPrice) {
|
|
return ClaimCaseStatus.INSURER_REVIEW_MIXED_FACTORS_PENDING;
|
|
}
|
|
return ClaimCaseStatus.OWNER_REPAIR_FACTOR_UPLOAD_PENDING;
|
|
}
|
|
|
|
export function claimIsV2ExpertFactorUploadStep(claim: { workflow?: { currentStep?: string } }) {
|
|
return claim.workflow?.currentStep === ClaimWorkflowStep.OWNER_UPLOAD_FACTOR_DOCUMENTS;
|
|
}
|
|
|
|
export function claimIsV2PendingFactorExpertValidation(claim: {
|
|
status?: ClaimCaseStatus;
|
|
claimStatus?: ClaimStatus;
|
|
workflow?: { currentStep?: string };
|
|
}) {
|
|
return claimIsAwaitingExpertFactorValidationV2(claim);
|
|
}
|
|
|
|
export function objectionDisallowedDueToOutstandingFactorWorkflow(claim: {
|
|
workflow?: { currentStep?: string };
|
|
}) {
|
|
const step = claim.workflow?.currentStep;
|
|
return (
|
|
step === ClaimWorkflowStep.OWNER_UPLOAD_FACTOR_DOCUMENTS ||
|
|
step === ClaimWorkflowStep.EXPERT_COST_EVALUATION
|
|
);
|
|
}
|