1
0
forked from Yara724/api
Files
yara724-api/src/claim-request-management/entites/schema/claim-cases.schema.ts

279 lines
7.6 KiB
TypeScript

import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { HydratedDocument, Schema as MongooseSchema, Types } from "mongoose";
import { ClaimRequiredDocumentType } from "src/Types&Enums/claim-request-management/required-document-type.enum";
import { ClaimStatus } from "src/Types&Enums/claim-request-management/claimStatus.enum";
import { ClaimCaseStatus } from "src/Types&Enums/claim-request-management/claim-case-status.enum";
import {
HistoryEvent,
HistoryEventSchema,
} from "src/request-management/entities/schema/historyEvent.type";
import {
ClaimDamageSelection,
ClaimDamageSelectionSchema,
} from "./claim-case.damage.schema";
import {
ClaimMoney,
ClaimMoneySchema,
ClaimOwner,
ClaimOwnerSchema,
ClaimVehicleSnapshot,
ClaimVehicleSnapshotSchema,
} from "./claim-case.identity.schema";
import { ClaimMedia, ClaimMediaSchema } from "./claim-case.media.schema";
import {
ClaimEvaluation,
ClaimEvaluationSchema,
} from "./claim-case.evaluation.schema";
import {
ClaimCaseSnapshot,
ClaimCaseSnapshotSchema,
} from "./claim-case.snapshot.schema";
import {
ClaimWorkflow,
ClaimWorkflowSchema,
} from "./claim-case.workflow.schema";
import { UserClaimRating } from "./claim-request-management.schema";
import {
CaseInquiries,
CaseInquiriesSchema,
} from "src/common/schema/case-inquiries.schema";
@Schema({ _id: false })
export class RequiredDocumentRef {
@Prop({ type: Types.ObjectId })
fileId?: Types.ObjectId;
@Prop({ type: String })
filePath?: string;
@Prop({ type: String })
fileName?: string;
@Prop({ type: Boolean, default: true })
uploaded?: boolean;
@Prop({ type: Date })
uploadedAt?: Date;
}
export const RequiredDocumentRefSchema =
SchemaFactory.createForClass(RequiredDocumentRef);
@Schema({ _id: false })
export class FanavaranSyncStage {
@Prop({ type: String })
status?: "pending" | "success" | "failed" | "skipped";
@Prop({ type: Date })
lastTriedAt?: Date;
@Prop({ type: String })
lastError?: string;
@Prop({ type: Number })
claimId?: number;
@Prop({ type: Number })
claimNo?: number;
@Prop({ type: Number })
dmgCaseId?: number;
@Prop({ type: Number })
expertiseId?: number;
@Prop({ type: [MongooseSchema.Types.Mixed], default: [] })
files?: unknown[];
@Prop({ type: MongooseSchema.Types.Mixed })
response?: unknown;
@Prop({ type: Number, default: 0 })
retryCount?: number;
@Prop({ type: Number, default: 2 })
maxRetries?: number;
@Prop({ type: Date })
nextRetryAt?: Date;
}
export const FanavaranSyncStageSchema =
SchemaFactory.createForClass(FanavaranSyncStage);
@Schema({ _id: false })
export class FanavaranSyncState {
@Prop({ type: FanavaranSyncStageSchema })
baseClaim?: FanavaranSyncStage;
@Prop({ type: FanavaranSyncStageSchema })
damageCase?: FanavaranSyncStage;
@Prop({ type: FanavaranSyncStageSchema })
attachments?: FanavaranSyncStage;
@Prop({ type: FanavaranSyncStageSchema })
expertise?: FanavaranSyncStage;
}
export const FanavaranSyncStateSchema =
SchemaFactory.createForClass(FanavaranSyncState);
@Schema({
collection: "claimCases",
timestamps: true,
id: true,
versionKey: false,
})
export class ClaimCase {
@Prop({ required: true, unique: true, index: true, trim: true })
requestNo: string;
/**
* Human-friendly shared id across blame+claim (e.g. A14235).
* Generated once on blame creation and copied into claim.
*/
@Prop({ required: true, unique: true, index: true, trim: true })
publicId: string;
/**
* Overall case status (user flow + expert flow progression)
*/
@Prop({
required: true,
type: String,
enum: ClaimCaseStatus,
default: ClaimCaseStatus.CREATED,
})
status: ClaimCaseStatus;
/**
* Claim damage determination status (expert assessment)
*/
@Prop({ type: String, enum: ClaimStatus, default: ClaimStatus.PENDING })
claimStatus: ClaimStatus;
/**
* Set while the linked blame file is in WAITING_FOR_DOCUMENT_RESEND so the claim flow can block or message the user.
*/
@Prop({ default: false })
blameDocumentResendPending?: boolean;
/**
* Link to the blame case that originated this claim.
* IMPORTANT: this is intentionally ONLY an id reference (no embedded blame file).
*/
@Prop({ type: Types.ObjectId, index: true })
blameRequestId?: Types.ObjectId;
@Prop({ type: String, index: true })
blameRequestNo?: string;
/**
* Set when this claim was created by a field expert on behalf of the damaged
* party (expert-initiated IN_PERSON flow). Used to scope the expert's panel
* access to only their own initiated files.
*/
@Prop({ type: Types.ObjectId, index: true })
initiatedByFieldExpertId?: Types.ObjectId;
/**
* The damaged party's userId, resolved from the blame at claim-creation time.
* Stored here so view/list access does not require an extra blame lookup.
* For CAR_BODY this is the FIRST party; for THIRD_PARTY it is the non-guilty party.
*/
@Prop({ type: Types.ObjectId, index: true })
damagedPartyUserId?: Types.ObjectId;
@Prop({ type: ClaimWorkflowSchema, default: () => ({}) })
workflow?: ClaimWorkflow;
@Prop({ type: ClaimOwnerSchema, default: () => ({}) })
owner?: ClaimOwner;
@Prop({ type: ClaimVehicleSnapshotSchema, default: () => ({}) })
vehicle?: ClaimVehicleSnapshot;
@Prop({ type: ClaimMoneySchema })
money?: ClaimMoney;
@Prop({ type: Number })
claimNo?: number;
@Prop({ type: Number })
claimId?: number;
@Prop({ type: Number })
dmgCaseId?: number;
@Prop({ type: Number })
expertiseId?: number;
@Prop({ type: FanavaranSyncStateSchema, default: () => ({}) })
fanavaranSync?: FanavaranSyncState;
@Prop({ type: ClaimDamageSelectionSchema, default: () => ({}) })
damage?: ClaimDamageSelection;
@Prop({ type: ClaimMediaSchema, default: () => ({}) })
media?: ClaimMedia;
@Prop({ type: ClaimEvaluationSchema, default: () => ({}) })
evaluation?: ClaimEvaluation;
@Prop({ type: CaseInquiriesSchema, default: () => ({}) })
inquiries?: CaseInquiries;
/**
* Optional “read-optimized” copy of fields from blame/request side.
* Source of truth remains `blameRequestId`.
*/
@Prop({ type: ClaimCaseSnapshotSchema })
snapshot?: ClaimCaseSnapshot;
/**
* For quick “has user uploaded X?” checks. Values point to docs in the
* `claim-required-documents` collection.
*/
@Prop({
type: Map,
of: RequiredDocumentRefSchema,
default: () => ({}),
})
requiredDocuments?: Map<string, RequiredDocumentRef>;
@Prop({ type: [HistoryEventSchema], default: [] })
history?: HistoryEvent[];
/**
* User satisfaction rating (damaged party), after the case is completed.
*/
@Prop({ type: UserClaimRating, required: false })
userRating?: UserClaimRating;
@Prop({ type: Types.ObjectId, index: true })
createdByRegistrarId?: Types.ObjectId;
/**
* V5 split flow: when true, the claim must be approved by the FileMaker
* who created the file before fanavaran submission is allowed.
*/
@Prop({ type: Boolean, default: false })
requiresFileMakerApproval?: boolean;
/**
* V5 split flow: ObjectId of the FileMaker who must approve this claim.
* Set when the FileReviewer uploads the blame accident video in the V5 flow.
*/
@Prop({ type: Types.ObjectId, index: true })
fileMakerApprovalActorId?: Types.ObjectId;
/**
* Legacy fields kept optional to simplify progressive migration.
* If you choose to migrate later, we can remove these.
*/
@Prop({ type: MongooseSchema.Types.Mixed })
legacy?: any;
}
export type ClaimCaseDocument = HydratedDocument<ClaimCase>;
export const ClaimCaseSchema = SchemaFactory.createForClass(ClaimCase);
ClaimCaseSchema.index({ status: 1, "workflow.locked": 1 });