forked from Yara724/api
Fixed insurer
This commit is contained in:
@@ -23,6 +23,7 @@ import { UsersModule } from "./users/users.module";
|
||||
import { applyIranFaTimestampPlugin } from "./helpers/mongoose-fa-timestamps.plugin";
|
||||
import { CronModule } from "./utils/cron/cron.module";
|
||||
import { WorkflowStepManagementModule } from "./workflow-step-management/workflow-step-management.module";
|
||||
import { ExpertInitiatedModule } from "./expert-initiated/expert-initiated.module";
|
||||
import * as Joi from "joi";
|
||||
|
||||
@Module({
|
||||
@@ -112,6 +113,7 @@ import * as Joi from "joi";
|
||||
ExpertInsurerModule,
|
||||
LookupsModule,
|
||||
WorkflowStepManagementModule,
|
||||
// ExpertInitiatedModule,
|
||||
],
|
||||
controllers: [],
|
||||
providers: [
|
||||
|
||||
@@ -117,6 +117,7 @@ export class UserAuthService {
|
||||
|
||||
if (!userExist) {
|
||||
await this.smsSender(otp, canonicalMobile);
|
||||
// console.log(`OTP for ${canonicalMobile}: ${otp}`);
|
||||
const newUser = await this.userDbService.createUser({
|
||||
mobile: canonicalMobile,
|
||||
username: canonicalMobile,
|
||||
@@ -144,6 +145,7 @@ export class UserAuthService {
|
||||
}
|
||||
|
||||
await this.smsSender(otp, canonicalMobile);
|
||||
// console.log(`OTP for ${canonicalMobile}: ${otp}`);
|
||||
await this.userDbService.findOneAndUpdate(
|
||||
buildUserLookupByPhone(canonicalMobile),
|
||||
{
|
||||
|
||||
@@ -5156,7 +5156,6 @@ export class ClaimRequestManagementService {
|
||||
): Promise<UploadRequiredDocumentV2ResponseDto> {
|
||||
try {
|
||||
const claimCase = await this.claimCaseDbService.findById(claimRequestId);
|
||||
|
||||
if (!claimCase) {
|
||||
throw new NotFoundException(
|
||||
`Claim case with ID ${claimRequestId} not found`,
|
||||
@@ -5214,6 +5213,7 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (isResendUpload) {
|
||||
if (claimCase.status !== ClaimCaseStatus.WAITING_FOR_USER_RESEND) {
|
||||
throw new BadRequestException(
|
||||
@@ -5262,7 +5262,6 @@ export class ClaimRequestManagementService {
|
||||
|
||||
const fileUrl = buildFileLink(file.path);
|
||||
|
||||
// Create document reference in claim-required-documents collection
|
||||
const docRef = await this.claimRequiredDocumentDbService.create({
|
||||
path: file.path,
|
||||
fileName: file.filename,
|
||||
@@ -5271,17 +5270,8 @@ export class ClaimRequestManagementService {
|
||||
uploadedAt: new Date(),
|
||||
});
|
||||
|
||||
// Update claim case
|
||||
const updateData: any = {
|
||||
[`requiredDocuments.${body.documentKey}`]: {
|
||||
fileId: docRef._id,
|
||||
filePath: file.path,
|
||||
fileName: file.filename,
|
||||
uploaded: true,
|
||||
uploadedAt: new Date(),
|
||||
},
|
||||
$push: {
|
||||
history: {
|
||||
// Base history entry for this upload
|
||||
const uploadHistoryEntry = {
|
||||
type: "DOCUMENT_UPLOADED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(currentUserId),
|
||||
@@ -5294,19 +5284,27 @@ export class ClaimRequestManagementService {
|
||||
fileName: file.filename,
|
||||
fileId: docRef._id.toString(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Base $set — always applied
|
||||
const $set: Record<string, unknown> = {
|
||||
[`requiredDocuments.${body.documentKey}`]: {
|
||||
fileId: docRef._id,
|
||||
filePath: file.path,
|
||||
fileName: file.filename,
|
||||
uploaded: true,
|
||||
uploadedAt: new Date(),
|
||||
},
|
||||
};
|
||||
|
||||
// History entries to push — always at least the upload entry
|
||||
const historyEntries: unknown[] = [uploadHistoryEntry];
|
||||
|
||||
// completedSteps entries to push
|
||||
const completedStepsEntries: string[] = [];
|
||||
|
||||
let allDocumentsUploaded = false;
|
||||
let remaining = 0;
|
||||
|
||||
// Will be true when this upload also completes capture-phase docs AND
|
||||
// every angle + every selected damaged part has already been captured.
|
||||
// In that case we advance the workflow exactly like `capturePartV2` does
|
||||
// when the user finishes the last capture — otherwise the user would be
|
||||
// stuck in CAPTURE_PART_DAMAGES with all captures done but no more
|
||||
// captures to upload to trigger the transition.
|
||||
let captureStepCompletedOnThisUpload = false;
|
||||
|
||||
if (!isResendUpload) {
|
||||
@@ -5317,7 +5315,6 @@ export class ClaimRequestManagementService {
|
||||
remaining = CAPTURE_PHASE_DAMAGED_PARTY_DOC_KEYS.filter(
|
||||
(k) => !afterThis(k),
|
||||
).length;
|
||||
allDocumentsUploaded = false;
|
||||
|
||||
if (remaining === 0) {
|
||||
const progressAfterDoc = getClaimCaptureProgress(claimCase, {
|
||||
@@ -5330,15 +5327,16 @@ export class ClaimRequestManagementService {
|
||||
progressAfterDoc.capturePhaseDocsComplete
|
||||
) {
|
||||
captureStepCompletedOnThisUpload = true;
|
||||
updateData["status"] =
|
||||
ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS;
|
||||
updateData["workflow.currentStep"] =
|
||||
$set["status"] = ClaimCaseStatus.UPLOADING_REQUIRED_DOCUMENTS;
|
||||
$set["workflow.currentStep"] =
|
||||
ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS;
|
||||
updateData["workflow.nextStep"] =
|
||||
$set["workflow.nextStep"] =
|
||||
ClaimWorkflowStep.USER_SUBMISSION_COMPLETE;
|
||||
updateData.$push.history = [
|
||||
updateData.$push.history,
|
||||
{
|
||||
|
||||
completedStepsEntries.push(
|
||||
ClaimWorkflowStep.CAPTURE_PART_DAMAGES,
|
||||
);
|
||||
historyEntries.push({
|
||||
type: "STEP_COMPLETED",
|
||||
actor: {
|
||||
actorId: new Types.ObjectId(currentUserId),
|
||||
@@ -5351,10 +5349,7 @@ export class ClaimRequestManagementService {
|
||||
description:
|
||||
"Angles, damaged parts, and capture-phase vehicle evidence (chassis, engine, metal plate) are complete. Please upload remaining required documents.",
|
||||
},
|
||||
},
|
||||
];
|
||||
updateData.$push["workflow.completedSteps"] =
|
||||
ClaimWorkflowStep.CAPTURE_PART_DAMAGES;
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -5370,14 +5365,17 @@ export class ClaimRequestManagementService {
|
||||
);
|
||||
|
||||
if (allDocumentsUploaded) {
|
||||
updateData["status"] = ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT;
|
||||
updateData["claimStatus"] = ClaimStatus.PENDING;
|
||||
updateData["workflow.currentStep"] =
|
||||
$set["status"] = ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT;
|
||||
$set["claimStatus"] = ClaimStatus.PENDING;
|
||||
$set["workflow.currentStep"] =
|
||||
ClaimWorkflowStep.USER_SUBMISSION_COMPLETE;
|
||||
updateData["workflow.nextStep"] =
|
||||
$set["workflow.nextStep"] =
|
||||
ClaimWorkflowStep.EXPERT_DAMAGE_ASSESSMENT;
|
||||
updateData.$push.history = [
|
||||
updateData.$push.history,
|
||||
|
||||
completedStepsEntries.push(
|
||||
ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS,
|
||||
);
|
||||
historyEntries.push(
|
||||
{
|
||||
type: "STEP_COMPLETED",
|
||||
actor: {
|
||||
@@ -5405,16 +5403,30 @@ export class ClaimRequestManagementService {
|
||||
"User submission complete. Claim ready for damage expert review.",
|
||||
},
|
||||
},
|
||||
];
|
||||
updateData.$push["workflow.completedSteps"] =
|
||||
ClaimWorkflowStep.UPLOAD_REQUIRED_DOCUMENTS;
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the final MongoDB update — all operators explicit and clean
|
||||
const updatePayload: Record<string, unknown> = { $set };
|
||||
|
||||
const $push: Record<string, unknown> = {
|
||||
history:
|
||||
historyEntries.length === 1
|
||||
? historyEntries[0]
|
||||
: { $each: historyEntries },
|
||||
};
|
||||
if (completedStepsEntries.length === 1) {
|
||||
$push["workflow.completedSteps"] = completedStepsEntries[0];
|
||||
} else if (completedStepsEntries.length > 1) {
|
||||
$push["workflow.completedSteps"] = { $each: completedStepsEntries };
|
||||
}
|
||||
updatePayload.$push = $push;
|
||||
|
||||
await this.claimCaseDbService.findByIdAndUpdate(
|
||||
claimRequestId,
|
||||
updateData,
|
||||
updatePayload,
|
||||
);
|
||||
|
||||
if (isResendUpload) {
|
||||
|
||||
@@ -92,7 +92,10 @@ import {
|
||||
buildMutualAgreementExpertDecision,
|
||||
enrichBlamePartiesForAgreementView,
|
||||
} from "src/helpers/blame-party-agreement-decision";
|
||||
import { resendRequestHasPayload } from "src/helpers/claim-expert-resend";
|
||||
import {
|
||||
normalizeResendDocumentKeys,
|
||||
resendRequestHasPayload,
|
||||
} from "src/helpers/claim-expert-resend";
|
||||
import {
|
||||
claimCaseStatusAfterExpertReplyV2,
|
||||
classifyV2ExpertPricingParts,
|
||||
@@ -133,6 +136,7 @@ import { CLAIM_V2_TOTAL_PAYMENT_CAP_TOMAN } from "src/constants/repair-amount-li
|
||||
import { ListQueryV2Dto } from "src/common/dto/list-query-v2.dto";
|
||||
import { applyListQueryV2 } from "src/helpers/list-query-v2";
|
||||
import { buildEnrichedDamagedParts } from "./dto/claim-damaged-part.enricher";
|
||||
import { canonicalizeResendDocumentKey } from "src/helpers/claim-resend-document-keys";
|
||||
|
||||
const CLAIM_V2_TOTAL_PAYMENT_CAP = CLAIM_V2_TOTAL_PAYMENT_CAP_TOMAN;
|
||||
|
||||
@@ -3842,29 +3846,29 @@ export class ExpertClaimService {
|
||||
const isResendPending =
|
||||
claim.status === ClaimCaseStatus.WAITING_FOR_USER_RESEND;
|
||||
|
||||
const assignedForReviewById = String(
|
||||
(claim.workflow as any)?.assignedForReviewBy?.actorId ?? "",
|
||||
);
|
||||
const lockEnforced = this.isClaimV2WorkflowLockCurrentlyEnforced(claim);
|
||||
const lockedById = String(claim.workflow?.lockedBy?.actorId ?? "");
|
||||
const isAssignedToMe =
|
||||
!!assignedForReviewById && assignedForReviewById === actorId;
|
||||
|
||||
// Gate: must satisfy at least one bucket
|
||||
if (
|
||||
!isDamageExpertPhase &&
|
||||
!isFactorValidationPending &&
|
||||
!isResendPending
|
||||
!isResendPending &&
|
||||
!isAssignedToMe
|
||||
) {
|
||||
throw new ForbiddenException(
|
||||
`This claim is not available for expert review. Current status: ${claim.status}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Ownership access control — same 4-bucket logic as list
|
||||
const assignedForReviewById = String(
|
||||
(claim.workflow as any)?.assignedForReviewBy?.actorId ?? "",
|
||||
);
|
||||
const lockEnforced = this.isClaimV2WorkflowLockCurrentlyEnforced(claim);
|
||||
const lockedById = String(claim.workflow?.lockedBy?.actorId ?? "");
|
||||
|
||||
const isAvailable =
|
||||
isDamageExpertPhase && !assignedForReviewById && !lockEnforced;
|
||||
const isAssignedToMe =
|
||||
!!assignedForReviewById && assignedForReviewById === actorId;
|
||||
const isLockedByMe = lockEnforced && lockedById === actorId;
|
||||
// Factor validation is open to all tenant experts (no individual ownership)
|
||||
const isFactorValidationOpen = isFactorValidationPending;
|
||||
|
||||
if (
|
||||
@@ -3888,12 +3892,19 @@ export class ExpertClaimService {
|
||||
);
|
||||
}
|
||||
|
||||
const hasCapture = (data: any, key: string) =>
|
||||
data && (data instanceof Map ? data.get(key) : data[key]);
|
||||
|
||||
// Build requiredDocuments map
|
||||
const requiredDocs = claim.requiredDocuments as any;
|
||||
const requiredDocumentsStatus: Record<string, any> = {};
|
||||
|
||||
// Resend documents requested by expert — normalize to canonical keys for comparison
|
||||
const resendDocumentKeys = new Set(
|
||||
normalizeResendDocumentKeys(
|
||||
(claim as any).evaluation?.damageExpertResend?.resendDocuments,
|
||||
),
|
||||
);
|
||||
const resendFulfilled = !!(claim as any).evaluation?.damageExpertResend
|
||||
?.fulfilledAt;
|
||||
|
||||
if (requiredDocs) {
|
||||
const keys =
|
||||
requiredDocs instanceof Map
|
||||
@@ -3902,11 +3913,18 @@ export class ExpertClaimService {
|
||||
for (const k of keys as string[]) {
|
||||
const doc =
|
||||
requiredDocs instanceof Map ? requiredDocs.get(k) : requiredDocs[k];
|
||||
const canonicalKey = canonicalizeResendDocumentKey(k) ?? k;
|
||||
const wasResendRequested = resendDocumentKeys.has(canonicalKey);
|
||||
|
||||
requiredDocumentsStatus[k] = {
|
||||
uploaded: !!doc?.uploaded,
|
||||
fileId: doc?.fileId?.toString(),
|
||||
fileName: doc?.fileName,
|
||||
filePath: doc?.filePath ? buildFileLink(doc.filePath) : undefined,
|
||||
resend: {
|
||||
wasRequested: wasResendRequested,
|
||||
isFulfilled: wasResendRequested && resendFulfilled,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3927,7 +3945,7 @@ export class ExpertClaimService {
|
||||
};
|
||||
}
|
||||
|
||||
// Build damaged parts list (aligned with normalized selected parts and enriched with evaluation context)
|
||||
// Build enriched damaged parts
|
||||
const carTypeExpert = claim.vehicle?.carType as
|
||||
| ClaimVehicleTypeV2
|
||||
| undefined;
|
||||
@@ -3938,18 +3956,10 @@ export class ExpertClaimService {
|
||||
);
|
||||
const damagedPartsDataExpert = claim.media?.damagedParts as any;
|
||||
|
||||
// Extract optimization lookups from the DB document safely
|
||||
const evaluationBlock = (claim as any).evaluation;
|
||||
const priceDropLines = evaluationBlock?.priceDrop?.partLines || [];
|
||||
const objectionParts = evaluationBlock?.objection?.objectionParts || [];
|
||||
const newObjectionParts = evaluationBlock?.objection?.newParts || [];
|
||||
|
||||
// Inside getClaimDetailV2, replace the damagedParts block:
|
||||
|
||||
const damagedParts = buildEnrichedDamagedParts({
|
||||
selectedParts: selectedNormExpert,
|
||||
damagedPartsData: damagedPartsDataExpert,
|
||||
evaluationBlock: (claim as any).evaluation, // damageExpertResend lives here already
|
||||
evaluationBlock: (claim as any).evaluation,
|
||||
expertAddedParts: (claim.damage as any)?.expertAddedParts ?? [],
|
||||
getDamagedPartCaptureBlob,
|
||||
hasDamagedPartCapture,
|
||||
@@ -3957,7 +3967,7 @@ export class ExpertClaimService {
|
||||
buildFileLink,
|
||||
});
|
||||
|
||||
// 1. Vehicle payload logic from "upstream"
|
||||
// Vehicle payload — fall back to blame inquiry if claim vehicle is sparse
|
||||
let vehiclePayload = claim.vehicle as any;
|
||||
const hasClaimVehicle =
|
||||
vehiclePayload &&
|
||||
@@ -3968,7 +3978,6 @@ export class ExpertClaimService {
|
||||
|
||||
let blameLean: any = null;
|
||||
|
||||
// 2. Video capture and blame case db queries from "stashed"
|
||||
const videoCaptureIdRaw = (claim.media as any)?.videoCaptureId;
|
||||
const blameRequestIdStr = claim.blameRequestId?.toString();
|
||||
|
||||
@@ -3991,18 +4000,15 @@ export class ExpertClaimService {
|
||||
blameLean = blameLeanRows[0] ?? null;
|
||||
}
|
||||
|
||||
// If claim vehicle not found and blameLean exists, replace vehiclePayload
|
||||
if (!hasClaimVehicle && blameLean) {
|
||||
const fromBlame = this.damagedPartyVehicleFromBlame(blameLean, claim);
|
||||
if (fromBlame) vehiclePayload = fromBlame;
|
||||
}
|
||||
|
||||
// 3. Blame file context logic from "upstream"
|
||||
const blameFileContext = blameLean
|
||||
? this.blameFileContextForExpert(blameLean)
|
||||
: {};
|
||||
|
||||
// 4. videoCapture logic from "stashed"
|
||||
let videoCapture: ClaimDetailV2ResponseDto["videoCapture"] = undefined;
|
||||
if (videoCaptureRow) {
|
||||
const vc = videoCaptureRow as any;
|
||||
@@ -4036,28 +4042,12 @@ export class ExpertClaimService {
|
||||
? ClaimCaseStatus.WAITING_FOR_DAMAGE_EXPERT
|
||||
: claim.status;
|
||||
|
||||
const objection = (claim as any).evaluation?.objection
|
||||
? {
|
||||
objectionParts:
|
||||
(claim as any).evaluation.objection.objectionParts ?? [],
|
||||
newParts: (claim as any).evaluation.objection.newParts ?? [],
|
||||
submittedAt: (claim as any).evaluation.objection.submittedAt,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
const blameCaseForApi = blameCase
|
||||
? this.sanitizeBlameCaseForClaimDetailApi(
|
||||
blameCase as Record<string, unknown>,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
// Enrich the full evaluation block with `signLink`s for every place a user
|
||||
// signature is referenced, then assemble the response slice.
|
||||
//
|
||||
// We always expose owner approval blocks (when present in the DB) because
|
||||
// the signature URL is needed across all phases of the claim. The expert
|
||||
// reply payloads are still gated on `isFactorValidationPending` to match
|
||||
// the historical contract of this endpoint.
|
||||
const claimEvaluationRaw = (claim as any).evaluation as
|
||||
| Record<string, unknown>
|
||||
| undefined;
|
||||
@@ -4122,7 +4112,6 @@ export class ExpertClaimService {
|
||||
blameRequestId: claim.blameRequestId?.toString(),
|
||||
blameRequestNo: claim.blameRequestNo,
|
||||
money: moneyPayload,
|
||||
// selectedParts: selectedNormExpert,
|
||||
otherParts: claim.damage?.otherParts,
|
||||
requiredDocuments:
|
||||
Object.keys(requiredDocumentsStatus).length > 0
|
||||
@@ -4131,10 +4120,9 @@ export class ExpertClaimService {
|
||||
carAngles,
|
||||
damagedParts,
|
||||
awaitingFactorValidation: isFactorValidationPending,
|
||||
evaluation: enrichedEvaluation as
|
||||
evaluation: evaluationForApi as
|
||||
| ClaimDetailV2ResponseDto["evaluation"]
|
||||
| undefined,
|
||||
// objection,
|
||||
videoCapture,
|
||||
blameCase: blameCaseForApi,
|
||||
blameExpertDecision,
|
||||
|
||||
@@ -1099,6 +1099,8 @@ export class ExpertInsurerService {
|
||||
|
||||
async retrieveAllFilesOfClient(insurerId: string) {
|
||||
const id = this.getClientId(insurerId);
|
||||
const idStr = String(id);
|
||||
|
||||
const [blameFiles, claimFiles] = await Promise.all([
|
||||
this.getClientBlameFiles(id),
|
||||
this.getClientClaimFiles(id),
|
||||
@@ -1112,11 +1114,7 @@ export class ExpertInsurerService {
|
||||
parties?: Array<{
|
||||
role?: string;
|
||||
fullName?: string;
|
||||
vehicle?: {
|
||||
carName?: string;
|
||||
carModel?: string;
|
||||
plate?: string;
|
||||
};
|
||||
vehicle?: { carName?: string; carModel?: string; plate?: string };
|
||||
}>;
|
||||
blame?: {
|
||||
requestId?: string;
|
||||
@@ -1125,11 +1123,7 @@ export class ExpertInsurerService {
|
||||
parties?: Array<{
|
||||
role?: string;
|
||||
fullName?: string;
|
||||
vehicle?: {
|
||||
carName?: string;
|
||||
carModel?: string;
|
||||
plate?: string;
|
||||
};
|
||||
vehicle?: { carName?: string; carModel?: string; plate?: string };
|
||||
}>;
|
||||
expertNames?: string[];
|
||||
createdAt?: Date | string;
|
||||
@@ -1150,6 +1144,7 @@ export class ExpertInsurerService {
|
||||
}
|
||||
>();
|
||||
|
||||
// Index blame files first
|
||||
for (const b of blameFiles) {
|
||||
const key = String((b as any).publicId || (b as any)._id || "");
|
||||
if (!key) continue;
|
||||
@@ -1163,7 +1158,7 @@ export class ExpertInsurerService {
|
||||
(b as any).requestNo || String((b as any).requestNumber || ""),
|
||||
status: (b as any).status,
|
||||
parties: partiesPreview,
|
||||
expertNames: extractExpertNamesFromBlame(b), // ← add
|
||||
expertNames: extractExpertNamesFromBlame(b),
|
||||
createdAt: (b as any).createdAt,
|
||||
updatedAt: (b as any).updatedAt,
|
||||
};
|
||||
@@ -1173,10 +1168,61 @@ export class ExpertInsurerService {
|
||||
byPublicId.set(key, prev);
|
||||
}
|
||||
|
||||
// For claim files whose blame wasn't in blameFiles (different insurer's blame),
|
||||
// fetch the linked blame directly so we can get vehicle + parties data
|
||||
const claimOnlyBlameIds = claimFiles
|
||||
.filter((c) => {
|
||||
const key = String((c as any).publicId || (c as any)._id || "");
|
||||
return key && !byPublicId.has(key) && (c as any).blameRequestId;
|
||||
})
|
||||
.map((c) => String((c as any).blameRequestId));
|
||||
|
||||
const uniqueBlameIds = [...new Set(claimOnlyBlameIds)].filter(Boolean);
|
||||
|
||||
const linkedBlames =
|
||||
uniqueBlameIds.length > 0
|
||||
? ((await this.blameRequestDbService.find(
|
||||
{
|
||||
_id: {
|
||||
$in: uniqueBlameIds.map((id) => new Types.ObjectId(id)),
|
||||
},
|
||||
},
|
||||
{ lean: true },
|
||||
)) as any[])
|
||||
: [];
|
||||
|
||||
const linkedBlameByPublicId = new Map<string, any>(
|
||||
linkedBlames.map((b) => [String(b.publicId), b]),
|
||||
);
|
||||
|
||||
// Index claim files
|
||||
for (const c of claimFiles) {
|
||||
const key = String((c as any).publicId || (c as any)._id || "");
|
||||
if (!key) continue;
|
||||
const prev = byPublicId.get(key) ?? { publicId: key };
|
||||
|
||||
// If no blame entry yet, use the linked blame for parties/vehicle/fileType
|
||||
if (!prev.blame) {
|
||||
const linkedBlame = linkedBlameByPublicId.get(key);
|
||||
if (linkedBlame) {
|
||||
const partiesFromBlame = this.buildPartiesPreview(
|
||||
linkedBlame.parties,
|
||||
);
|
||||
prev.fileType = prev.fileType ?? linkedBlame.type;
|
||||
prev.blame = {
|
||||
requestId: String(linkedBlame._id),
|
||||
requestNo: linkedBlame.requestNo || "",
|
||||
status: linkedBlame.status,
|
||||
parties: partiesFromBlame,
|
||||
expertNames: extractExpertNamesFromBlame(linkedBlame),
|
||||
createdAt: linkedBlame.createdAt,
|
||||
updatedAt: linkedBlame.updatedAt,
|
||||
};
|
||||
prev.parties = prev.parties ?? partiesFromBlame;
|
||||
prev.createdAt = prev.createdAt ?? linkedBlame.createdAt;
|
||||
}
|
||||
}
|
||||
|
||||
const claimPartiesPreview = this.buildPartiesPreview(
|
||||
(c as any)?.snapshot?.parties,
|
||||
);
|
||||
@@ -1189,7 +1235,7 @@ export class ExpertInsurerService {
|
||||
status: (c as any).status,
|
||||
claimStatus: (c as any).claimStatus,
|
||||
currentStep: (c as any).currentStep,
|
||||
expertNames: extractExpertNamesFromClaim(c), // ← add
|
||||
expertNames: extractExpertNamesFromClaim(c),
|
||||
createdAt: (c as any).createdAt,
|
||||
updatedAt: (c as any).updatedAt,
|
||||
};
|
||||
|
||||
@@ -260,6 +260,19 @@ export function canFinalizeExpertResend(claim: any): boolean {
|
||||
claim?.damage?.selectedParts,
|
||||
);
|
||||
|
||||
console.log("[canFinalizeExpertResend]", {
|
||||
docKeys,
|
||||
partKeys,
|
||||
docResults: docKeys.map((k) => ({
|
||||
k,
|
||||
uploaded: isRequiredDocumentUploaded(claim, k),
|
||||
})),
|
||||
partResults: partKeys.map((k) => ({
|
||||
k,
|
||||
captured: hasDamagedPartCapture(claim, k),
|
||||
})),
|
||||
});
|
||||
|
||||
if (docKeys.length === 0 && partKeys.length === 0) {
|
||||
return String(r.resendDescription || "").trim() !== "";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user