forked from Yara724/api
fixed many bugs and step issues
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { BlameRequestType } from 'src/Types&Enums/blame-request-management/blameRequestType.enum';
|
||||
|
||||
export class ClaimDetailV2ResponseDto {
|
||||
@ApiProperty()
|
||||
@@ -43,6 +44,19 @@ export class ClaimDetailV2ResponseDto {
|
||||
plate?: any;
|
||||
};
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Blame file type from linked blame case',
|
||||
enum: BlameRequestType,
|
||||
})
|
||||
blameRequestType?: BlameRequestType;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
'CAR_BODY only: first-step flags — another car (`car`) and/or object (`object`)',
|
||||
example: { car: true, object: false },
|
||||
})
|
||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||
|
||||
@ApiPropertyOptional({ description: 'Blame request ID', example: '507f...' })
|
||||
blameRequestId?: string;
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
|
||||
import { BlameRequestType } from 'src/Types&Enums/blame-request-management/blameRequestType.enum';
|
||||
|
||||
export class ClaimListItemV2Dto {
|
||||
@ApiProperty({ description: 'Claim case ID' })
|
||||
@@ -29,6 +30,20 @@ export class ClaimListItemV2Dto {
|
||||
carType?: string;
|
||||
};
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description: 'Blame file type from linked blame case',
|
||||
enum: BlameRequestType,
|
||||
example: BlameRequestType.THIRD_PARTY,
|
||||
})
|
||||
blameRequestType?: BlameRequestType;
|
||||
|
||||
@ApiPropertyOptional({
|
||||
description:
|
||||
'CAR_BODY only: first-step flags — accident involved another car (`car`) and/or fixed object (`object`)',
|
||||
example: { car: true, object: false },
|
||||
})
|
||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||
|
||||
@ApiProperty({ description: 'Submission date', example: '2026-02-22T10:00:00.000Z' })
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import {
|
||||
requireActorClientKey,
|
||||
} from "src/helpers/tenant-scope";
|
||||
import { ClaimWorkflowStep } from "src/Types&Enums/claim-request-management/claim-workflow-steps.enum";
|
||||
import { BlameRequestType } from "src/Types&Enums/blame-request-management/blameRequestType.enum";
|
||||
import { PartyRole } from "src/request-management/entities/schema/partyRole.enum";
|
||||
import { GetClaimListV2ResponseDto, ClaimListItemV2Dto } from "./dto/claim-list-v2.dto";
|
||||
import { ClaimDetailV2ResponseDto } from "./dto/claim-detail-v2.dto";
|
||||
import { ClaimSubmitReplyDto, ClaimSubmitResendDto } from "./dto/reply.dto";
|
||||
@@ -47,6 +49,7 @@ import { ClaimRequiredDocumentDbService } from "src/claim-request-management/ent
|
||||
import { FactorStatus } from "src/Types&Enums/claim-request-management/factor-status.enum";
|
||||
import { DaghiOption } from "src/Types&Enums/claim-request-management/daghi-option.enum";
|
||||
import { BranchDbService } from "src/client/entities/db-service/branch.db.service";
|
||||
import { BlameRequestDbService } from "src/request-management/entities/db-service/blame-request.db.service";
|
||||
|
||||
@Injectable()
|
||||
export class ExpertClaimService {
|
||||
@@ -165,8 +168,120 @@ export class ExpertClaimService {
|
||||
private readonly claimFactorsImageDbService: ClaimFactorsImageDbService,
|
||||
private readonly claimRequiredDocumentDbService: ClaimRequiredDocumentDbService,
|
||||
private readonly branchDbService: BranchDbService,
|
||||
private readonly blameRequestDbService: BlameRequestDbService,
|
||||
) {}
|
||||
|
||||
/** Map blame party `Vehicle` (name/model/type) to expert panel shape. */
|
||||
private expertVehicleFromPartyVehicle(v: any): {
|
||||
carName?: string;
|
||||
carModel?: string;
|
||||
carType?: string;
|
||||
plate?: { plateId?: string };
|
||||
} | undefined {
|
||||
if (!v || typeof v !== "object") return undefined;
|
||||
const carName = v.name ?? v.carName;
|
||||
const carModel = v.model ?? v.carModel;
|
||||
const carType = v.type ?? v.carType;
|
||||
const plateId = v.plateId;
|
||||
const plate =
|
||||
plateId != null && String(plateId).length > 0
|
||||
? { plateId: String(plateId) }
|
||||
: undefined;
|
||||
if (!carName && !carModel && !carType && !plate) return undefined;
|
||||
return { carName, carModel, carType, ...(plate ? { plate } : {}) };
|
||||
}
|
||||
|
||||
/** Damaged party vehicle on blame (matches claim owner, or non-guilty party for THIRD_PARTY). */
|
||||
private damagedPartyVehicleFromBlame(
|
||||
blame: any,
|
||||
claim: any,
|
||||
):
|
||||
| {
|
||||
carName?: string;
|
||||
carModel?: string;
|
||||
carType?: string;
|
||||
plate?: { plateId?: string };
|
||||
}
|
||||
| undefined {
|
||||
const parties = blame?.parties;
|
||||
if (!Array.isArray(parties) || parties.length === 0) return undefined;
|
||||
|
||||
const ownerId = claim?.owner?.userId ? String(claim.owner.userId) : "";
|
||||
let party = ownerId
|
||||
? parties.find(
|
||||
(p: any) =>
|
||||
p?.person?.userId && String(p.person.userId) === ownerId,
|
||||
)
|
||||
: undefined;
|
||||
|
||||
if (!party && blame?.expert?.decision?.guiltyPartyId) {
|
||||
const guilty = String(blame.expert.decision.guiltyPartyId);
|
||||
party = parties.find(
|
||||
(p: any) =>
|
||||
p?.person?.userId && String(p.person.userId) !== guilty,
|
||||
);
|
||||
}
|
||||
|
||||
if (!party && parties.length === 1) party = parties[0];
|
||||
|
||||
return this.expertVehicleFromPartyVehicle(party?.vehicle);
|
||||
}
|
||||
|
||||
private vehicleForExpertFromClaimAndBlameMap(
|
||||
claim: any,
|
||||
blameById: Map<string, any>,
|
||||
):
|
||||
| { carName?: string; carModel?: string; carType?: string; plate?: { plateId?: string } }
|
||||
| undefined {
|
||||
const cv = claim?.vehicle;
|
||||
if (
|
||||
cv &&
|
||||
(cv.carName || cv.carModel || cv.carType || (cv as any).plate)
|
||||
) {
|
||||
return {
|
||||
carName: cv.carName,
|
||||
carModel: cv.carModel,
|
||||
carType: cv.carType,
|
||||
...((cv as any).plate ? { plate: (cv as any).plate } : {}),
|
||||
};
|
||||
}
|
||||
const bid = claim?.blameRequestId?.toString();
|
||||
if (!bid) return undefined;
|
||||
const blame = blameById.get(bid);
|
||||
if (!blame) return undefined;
|
||||
return this.damagedPartyVehicleFromBlame(blame, claim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blame file kind for damage-expert UI: THIRD_PARTY vs CAR_BODY, and CAR_BODY first-step flags.
|
||||
*/
|
||||
private blameFileContextForExpert(blame: any): {
|
||||
blameRequestType?: BlameRequestType;
|
||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||
} {
|
||||
if (!blame?.type) return {};
|
||||
const blameRequestType = blame.type as BlameRequestType;
|
||||
const out: {
|
||||
blameRequestType?: BlameRequestType;
|
||||
carBodyFirstForm?: { car?: boolean; object?: boolean };
|
||||
} = { blameRequestType };
|
||||
if (blameRequestType !== BlameRequestType.CAR_BODY) return out;
|
||||
|
||||
const parties = blame.parties;
|
||||
if (!Array.isArray(parties) || parties.length === 0) return out;
|
||||
|
||||
const first =
|
||||
parties.find((p: any) => p?.role === PartyRole.FIRST) ?? parties[0];
|
||||
const cbf = first?.carBodyFirstForm;
|
||||
if (cbf && typeof cbf === "object") {
|
||||
out.carBodyFirstForm = {
|
||||
...(typeof cbf.car === "boolean" ? { car: cbf.car } : {}),
|
||||
...(typeof cbf.object === "boolean" ? { object: cbf.object } : {}),
|
||||
};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private isVisibleToClientType(client: any, actor: any): boolean {
|
||||
if (actor.userType === UserType.GENUINE) {
|
||||
return true;
|
||||
@@ -1858,29 +1973,57 @@ export class ExpertClaimService {
|
||||
],
|
||||
});
|
||||
|
||||
const list = (claims as any[])
|
||||
.filter((c) => claimCaseTouchesClient(c, clientKey))
|
||||
.map((c) => ({
|
||||
claimRequestId: c._id.toString(),
|
||||
publicId: c.publicId,
|
||||
status: c.status,
|
||||
currentStep: c.workflow?.currentStep || '',
|
||||
locked: c.workflow?.locked || false,
|
||||
lockedBy: c.workflow?.lockedBy
|
||||
? {
|
||||
actorId: c.workflow.lockedBy.actorId?.toString(),
|
||||
actorName: c.workflow.lockedBy.actorName,
|
||||
}
|
||||
: undefined,
|
||||
vehicle: c.vehicle
|
||||
? {
|
||||
carName: c.vehicle.carName,
|
||||
carModel: c.vehicle.carModel,
|
||||
carType: c.vehicle.carType,
|
||||
}
|
||||
: undefined,
|
||||
createdAt: c.createdAt,
|
||||
})) as ClaimListItemV2Dto[];
|
||||
const filtered = (claims as any[]).filter((c) =>
|
||||
claimCaseTouchesClient(c, clientKey),
|
||||
);
|
||||
|
||||
const blameIds = [
|
||||
...new Set(
|
||||
filtered
|
||||
.map((c) => c.blameRequestId?.toString())
|
||||
.filter((id): id is string => !!id),
|
||||
),
|
||||
];
|
||||
const blames =
|
||||
blameIds.length > 0
|
||||
? ((await this.blameRequestDbService.find(
|
||||
{ _id: { $in: blameIds.map((id) => new Types.ObjectId(id)) } },
|
||||
{ lean: true, select: "type parties expert.decision" },
|
||||
)) as any[])
|
||||
: [];
|
||||
const blameById = new Map<string, any>(
|
||||
blames.map((b) => [String(b._id), b]),
|
||||
);
|
||||
|
||||
const list = filtered.map((c) => {
|
||||
const v = this.vehicleForExpertFromClaimAndBlameMap(c, blameById);
|
||||
const blame = c.blameRequestId
|
||||
? blameById.get(c.blameRequestId.toString())
|
||||
: undefined;
|
||||
const fileCtx = blame ? this.blameFileContextForExpert(blame) : {};
|
||||
return {
|
||||
claimRequestId: c._id.toString(),
|
||||
publicId: c.publicId,
|
||||
status: c.status,
|
||||
currentStep: c.workflow?.currentStep || "",
|
||||
locked: c.workflow?.locked || false,
|
||||
lockedBy: c.workflow?.lockedBy
|
||||
? {
|
||||
actorId: c.workflow.lockedBy.actorId?.toString(),
|
||||
actorName: c.workflow.lockedBy.actorName,
|
||||
}
|
||||
: undefined,
|
||||
vehicle: v
|
||||
? {
|
||||
carName: v.carName,
|
||||
carModel: v.carModel,
|
||||
carType: v.carType,
|
||||
}
|
||||
: undefined,
|
||||
...fileCtx,
|
||||
createdAt: c.createdAt,
|
||||
};
|
||||
}) as ClaimListItemV2Dto[];
|
||||
|
||||
return { list, total: list.length };
|
||||
}
|
||||
@@ -1967,6 +2110,32 @@ export class ExpertClaimService {
|
||||
};
|
||||
}
|
||||
|
||||
let vehiclePayload = claim.vehicle as any;
|
||||
const hasClaimVehicle =
|
||||
vehiclePayload &&
|
||||
(vehiclePayload.carName ||
|
||||
vehiclePayload.carModel ||
|
||||
vehiclePayload.carType ||
|
||||
vehiclePayload.plate);
|
||||
|
||||
let blameLean: any = null;
|
||||
if (claim.blameRequestId) {
|
||||
const rows = (await this.blameRequestDbService.find(
|
||||
{ _id: new Types.ObjectId(claim.blameRequestId.toString()) },
|
||||
{ lean: true, select: "type parties expert.decision" },
|
||||
)) as any[];
|
||||
blameLean = rows[0] ?? null;
|
||||
}
|
||||
|
||||
if (!hasClaimVehicle && blameLean) {
|
||||
const fromBlame = this.damagedPartyVehicleFromBlame(blameLean, claim);
|
||||
if (fromBlame) vehiclePayload = fromBlame;
|
||||
}
|
||||
|
||||
const blameFileContext = blameLean
|
||||
? this.blameFileContextForExpert(blameLean)
|
||||
: {};
|
||||
|
||||
return {
|
||||
claimRequestId: claim._id.toString(),
|
||||
publicId: claim.publicId,
|
||||
@@ -1988,7 +2157,8 @@ export class ExpertClaimService {
|
||||
fullName: claim.owner.fullName,
|
||||
}
|
||||
: undefined,
|
||||
vehicle: claim.vehicle,
|
||||
vehicle: vehiclePayload,
|
||||
...blameFileContext,
|
||||
blameRequestId: claim.blameRequestId?.toString(),
|
||||
blameRequestNo: claim.blameRequestNo,
|
||||
selectedParts: claim.damage?.selectedParts,
|
||||
|
||||
Reference in New Issue
Block a user