fixed many bugs and step issues

This commit is contained in:
SepehrYahyaee
2026-04-18 17:04:19 +03:30
parent 7f5b64f2a6
commit 0086b8db4d
14 changed files with 443 additions and 89 deletions

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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,