add blame in claim details plus auto expert decision bug fixed

This commit is contained in:
2026-04-19 11:57:18 +03:30
parent c5b2d7b520
commit 08a4d754c1
5 changed files with 393 additions and 8 deletions

View File

@@ -0,0 +1,149 @@
import { Types } from "mongoose";
import { BlameRequestType } from "src/Types&Enums/blame-request-management/blameRequestType.enum";
import { BlameStatus } from "src/Types&Enums/blame-request-management/blameStatus.enum";
import { PartyRole } from "src/request-management/entities/schema/partyRole.enum";
/** Default accident taxonomy when guilt is established by mutual party agreement (no field-expert decision). */
export const MUTUAL_AGREEMENT_EXPERT_DECISION_FIELDS = {
accidentWay: { id: 8, label: "جلو به عقب" },
accidentReason: {
id: 1,
fanavaran: 1,
label:
"عدم رعايت فاصله مناسب با وسيله نقليه و يا عدم توجه به جلو",
},
accidentType: {
id: 1,
label: "برخورد یک وسیله نقلیه با یک وسیله نقلیه",
},
} as const;
export type MutualAgreementDecisionPayload = {
guiltyPartyId: Types.ObjectId;
description: string;
decidedAt: Date;
decidedByExpertId?: Types.ObjectId;
fields: typeof MUTUAL_AGREEMENT_EXPERT_DECISION_FIELDS;
};
function partyPhone(p: { person?: { phoneNumber?: string } } | undefined): string {
return (p?.person?.phoneNumber || "").trim();
}
function partyUserId(
p: { person?: { userId?: Types.ObjectId } } | undefined,
): Types.ObjectId | null {
const id = p?.person?.userId;
if (!id) return null;
return id instanceof Types.ObjectId ? id : new Types.ObjectId(String(id));
}
/**
* When the first party chose AGREED (guilty or damaged) and the second party exists,
* derive the guilty party and build the synthetic expert.decision payload.
* Does not set decidedByExpertId — this is not a field-expert adjudication.
*/
export function buildMutualAgreementExpertDecision(
doc: Record<string, unknown>,
): MutualAgreementDecisionPayload | null {
if (doc.type !== BlameRequestType.THIRD_PARTY) return null;
if (doc.blameStatus !== BlameStatus.AGREED) return null;
const parties = (doc.parties ?? []) as Array<{
role?: string;
person?: { userId?: Types.ObjectId; phoneNumber?: string };
statement?: {
admitsGuilt?: boolean;
claimsDamage?: boolean;
acceptsExpertOpinion?: boolean;
};
}>;
const first = parties.find((p) => p.role === PartyRole.FIRST);
const second = parties.find((p) => p.role === PartyRole.SECOND);
if (!first || !second) return null;
const st = first.statement;
if (!st) return null;
if (st.acceptsExpertOpinion) return null;
const admits = !!st.admitsGuilt;
const claims = !!st.claimsDamage;
if (admits === claims) return null;
let guiltyParty: typeof first;
let damagedParty: typeof first;
if (admits) {
guiltyParty = first;
damagedParty = second;
} else {
guiltyParty = second;
damagedParty = first;
}
const guiltyId = partyUserId(guiltyParty);
if (!guiltyId) return null;
const gPhone = partyPhone(guiltyParty);
const dPhone = partyPhone(damagedParty);
if (!gPhone || !dPhone) return null;
const description = `با توافق طرفین مقصر و زیان دیده مشخص شد. کاربر ${gPhone} مقصر و کاربر ${dPhone} زیان دیده می باشد.`;
return {
guiltyPartyId: guiltyId,
description,
decidedAt: new Date(),
fields: MUTUAL_AGREEMENT_EXPERT_DECISION_FIELDS,
};
}
/**
* Merge complementary statement flags onto the second party for expert/claim UIs when
* only the first party submitted a formal confession (V2 remote flow).
*/
export function enrichBlamePartiesForAgreementView(
doc: Record<string, unknown>,
): Array<Record<string, unknown>> {
const parties = (doc.parties ?? []) as Array<Record<string, unknown>>;
if (!Array.isArray(parties) || parties.length === 0) return parties;
const first = parties.find((p) => p.role === PartyRole.FIRST) as
| {
statement?: Record<string, unknown>;
}
| undefined;
const secondIdx = parties.findIndex((p) => p.role === PartyRole.SECOND);
if (!first?.statement || secondIdx === -1) return parties;
if (doc.blameStatus !== BlameStatus.AGREED) return parties;
const st = first.statement as {
admitsGuilt?: boolean;
claimsDamage?: boolean;
acceptsExpertOpinion?: boolean;
};
if (st.acceptsExpertOpinion) return parties;
const admits = !!st.admitsGuilt;
const claims = !!st.claimsDamage;
if (admits === claims) return parties;
const second = parties[secondIdx] as {
statement?: Record<string, unknown>;
};
const prev = (second.statement ?? {}) as Record<string, unknown>;
const mergedStatement = {
...prev,
admitsGuilt: admits ? false : true,
claimsDamage: admits ? true : false,
acceptsExpertOpinion: false,
};
const next = [...parties];
next[secondIdx] = {
...second,
statement: mergedStatement,
};
return next;
}