Implement role-complete inquiry participants

This commit is contained in:
SepehrYahyaee
2026-09-13 10:59:00 +03:30
parent 401ad6a143
commit c64f23091a
12 changed files with 2179 additions and 690 deletions

View File

@@ -4,213 +4,253 @@ import { Schema as MongooseSchema, Types } from "mongoose";
import { Location, LocationSchema } from "./accidentInformation.type";
export enum PartyRole {
FIRST = "FIRST",
SECOND = "SECOND",
}
FIRST = "FIRST",
SECOND = "SECOND",
}
@Schema({ _id: false })
export class Person {
@Prop({ type: Types.ObjectId })
userId?: Types.ObjectId;
@Prop({ type: Types.ObjectId })
userId?: Types.ObjectId;
@Prop() fullName?: string;
@Prop() phoneNumber?: string;
@Prop({ type: Types.ObjectId }) clientId?: Types.ObjectId;
@Prop() birthday?: string;
@Prop() fullName?: string;
@Prop() phoneNumber?: string;
@Prop({ type: Types.ObjectId }) clientId?: Types.ObjectId;
@Prop() birthday?: string;
// ---- FIRST_INITIAL_FORM (step-manager driven) ----
@Prop() nationalCodeOfInsurer?: string;
@Prop() nationalCodeOfDriver?: string;
@Prop() insurerLicense?: string;
@Prop() driverLicense?: string;
/** Driving licence type code from the Fanavaran lookup (GET /lookups/driving-licence-types). */
@Prop() licenseType?: string;
// ---- FIRST_INITIAL_FORM (step-manager driven) ----
@Prop() nationalCodeOfInsurer?: string;
@Prop() nationalCodeOfDriver?: string;
@Prop() insurerLicense?: string;
@Prop() driverLicense?: string;
/** Driving licence type code from the Fanavaran lookup (GET /lookups/driving-licence-types). */
@Prop() licenseType?: string;
@Prop({ type: Boolean })
driverIsInsurer?: boolean;
@Prop({ type: Boolean })
driverIsInsurer?: boolean;
@Prop({ type: Boolean })
isNewCar?: boolean;
@Prop({ type: Boolean })
isNewCar?: boolean;
/**
* Mirrors existing DTO `userNoCertificate` (true means user has NO certificate).
*/
@Prop({ type: Boolean })
userNoCertificate?: boolean;
/**
* Mirrors existing DTO `userNoCertificate` (true means user has NO certificate).
*/
@Prop({ type: Boolean })
userNoCertificate?: boolean;
@Prop({ type: Number })
insurerBirthday?: number;
@Prop({ type: Number })
insurerBirthday?: number;
@Prop({ type: String })
driverBirthday?: string | null;
@Prop({ type: String })
driverBirthday?: string | null;
/** Cached Fanavaran party ID resolved from nationalCodeOfDriver + driverBirthday + driverIsInsurer */
@Prop({ type: Number })
fanavaranDriverId?: number;
/** Cached Fanavaran party ID resolved from nationalCodeOfDriver + driverBirthday + driverIsInsurer */
@Prop({ type: Number })
fanavaranDriverId?: number;
}
export const PersonSchema = SchemaFactory.createForClass(Person);
@Schema({ _id: false })
export class Vehicle {
@Prop() plateId?: string;
/** VIN / chassis number — populated only when the inquiry was performed via VIN lookup. */
@Prop() vin?: string;
@Prop() name?: string;
@Prop() model?: string;
@Prop() type?: string;
@Prop() isNew?: boolean;
export class InquiryParticipant {
@Prop({ required: true })
participantId: string;
/**
* Full external inquiry payload (Tejarat/SandHub) stored as-is
* so we never lose fields that are not mapped yet.
*/
@Prop({ type: MongooseSchema.Types.Mixed })
inquiry?: any;
@Prop()
nationalCode: string;
@Prop()
birthday: string;
@Prop() fullName?: string;
@Prop() phoneNumber?: string;
@Prop({ type: Boolean }) hasDrivingLicense?: boolean;
@Prop() licenseNumber?: string;
@Prop() licenseType?: string;
}
export const InquiryParticipantSchema =
SchemaFactory.createForClass(InquiryParticipant);
@Schema({ _id: false })
export class InquiryParticipantRoles {
@Prop() driver?: string;
@Prop() vehicleOwner?: string;
@Prop() thirdPartyPolicyholder?: string;
@Prop() carBodyPolicyholder?: string;
}
export const InquiryParticipantRolesSchema = SchemaFactory.createForClass(
InquiryParticipantRoles,
);
@Schema({ _id: false })
export class Vehicle {
@Prop() plateId?: string;
/** VIN / chassis number — populated only when the inquiry was performed via VIN lookup. */
@Prop() vin?: string;
@Prop() name?: string;
@Prop() model?: string;
@Prop() type?: string;
@Prop() isNew?: boolean;
@Prop({ enum: ["CURRENT", "RECENTLY_TRANSFERRED"] })
registrationState?: "CURRENT" | "RECENTLY_TRANSFERRED";
@Prop() previousPlateId?: string;
/**
* Full external inquiry payload (Tejarat/SandHub) stored as-is
* so we never lose fields that are not mapped yet.
*/
@Prop({ type: MongooseSchema.Types.Mixed })
inquiry?: any;
}
export const VehicleSchema = SchemaFactory.createForClass(Vehicle);
@Schema({ _id: false })
export class Insurance {
@Prop() policyNumber?: string;
@Prop() company?: string;
@Prop() startDate?: string;
@Prop() endDate?: string;
@Prop() financialCeiling?: string;
@Prop({ type: [String] })
coverages?: string[];
@Prop() policyNumber?: string;
@Prop() company?: string;
@Prop() startDate?: string;
@Prop() endDate?: string;
@Prop() financialCeiling?: string;
@Prop({ type: [String] })
coverages?: string[];
/** CAR_BODY inquiry result; raw provider data is retained in vehicle.inquiry.carBody.raw. */
@Prop({ type: MongooseSchema.Types.Mixed })
carBodyInsurance?: {
policyNumber?: string;
policyId?: number;
contractId?: number;
startDate?: string;
endDate?: string;
insurerCompany?: string;
coverages?: string[];
companyId?: number | string;
companyName?: string;
insurerName?: string;
insurerNationalCode?: string;
ownerNationalCode?: string;
ownerName?: string;
customerName?: string;
customerLastName?: string;
customerFatherName?: string;
customerMobile?: string;
customerAddress?: string;
customerPostalCode?: string;
chassisNumber?: string;
vin?: string;
motorNumber?: string;
vehicleGroup?: string;
vehicleSystem?: string;
vehicleKind?: string;
builtYear?: number;
cylinderCount?: number;
passengerCount?: number;
usage?: string;
issueDate?: string;
vehicleValue?: number;
totalPremium?: number;
noLossYearsCount?: number;
lossDocuments?: unknown[];
hasEndorsement?: boolean;
};
/** CAR_BODY inquiry result; raw provider data is retained in vehicle.inquiry.carBody.raw. */
@Prop({ type: MongooseSchema.Types.Mixed })
carBodyInsurance?: {
policyNumber?: string;
policyId?: number;
contractId?: number;
startDate?: string;
endDate?: string;
insurerCompany?: string;
coverages?: string[];
companyId?: number | string;
companyName?: string;
insurerName?: string;
insurerNationalCode?: string;
ownerNationalCode?: string;
ownerName?: string;
customerName?: string;
customerLastName?: string;
customerFatherName?: string;
customerMobile?: string;
customerAddress?: string;
customerPostalCode?: string;
chassisNumber?: string;
vin?: string;
motorNumber?: string;
vehicleGroup?: string;
vehicleSystem?: string;
vehicleKind?: string;
builtYear?: number;
cylinderCount?: number;
passengerCount?: number;
usage?: string;
issueDate?: string;
vehicleValue?: number;
totalPremium?: number;
noLossYearsCount?: number;
lossDocuments?: unknown[];
hasEndorsement?: boolean;
};
}
export const InsuranceSchema = SchemaFactory.createForClass(Insurance);
@Schema({ _id: false })
export class PartyStatement {
@Prop({ default: false })
acceptsExpertOpinion?: boolean;
@Prop({ default: false })
acceptsExpertOpinion?: boolean;
@Prop({ default: false })
claimsDamage?: boolean;
@Prop({ default: false })
admitsGuilt?: boolean;
@Prop({ type: String })
description?: string;
@Prop({ default: false })
claimsDamage?: boolean;
/** CAR_BODY: accident conditions from description step */
@Prop() accidentDate?: Date;
@Prop() accidentTime?: string;
@Prop() weatherCondition?: string;
@Prop() roadCondition?: string;
@Prop() lightCondition?: string;
@Prop({ default: false })
admitsGuilt?: boolean;
@Prop({ type: String })
description?: string;
/** CAR_BODY: accident conditions from description step */
@Prop() accidentDate?: Date;
@Prop() accidentTime?: string;
@Prop() weatherCondition?: string;
@Prop() roadCondition?: string;
@Prop() lightCondition?: string;
}
export const PartyStatementSchema = SchemaFactory.createForClass(PartyStatement);
export const PartyStatementSchema =
SchemaFactory.createForClass(PartyStatement);
@Schema({ _id: false })
export class EvidenceBundle {
@Prop({ type: [String] })
images?: string[];
@Prop({ type: [String] })
images?: string[];
@Prop({ type: [String] })
voices?: string[];
@Prop() videoId?: string;
@Prop({ type: [String] })
voices?: string[];
@Prop() videoId?: string;
}
export const EvidenceBundleSchema = SchemaFactory.createForClass(EvidenceBundle);
export const EvidenceBundleSchema =
SchemaFactory.createForClass(EvidenceBundle);
@Schema({ _id: false })
export class Signature {
@Prop() fileId: string;
@Prop() fileName: string;
@Prop() fileUrl: string;
@Prop() fileId: string;
@Prop() fileName: string;
@Prop() fileUrl: string;
}
export const SignatureSchema = SchemaFactory.createForClass(Signature);
@Schema({ _id: false })
export class PartyConfirmation {
@Prop() partyRole: PartyRole;
@Prop() accepted: boolean;
@Prop({ type: SignatureSchema })
signature?: Signature;
@Prop() partyRole: PartyRole;
@Prop() accepted: boolean;
@Prop({ type: SignatureSchema })
signature?: Signature;
}
export const PartyConfirmationSchema =
SchemaFactory.createForClass(PartyConfirmation);
@Schema({ _id: false })
export class Party {
@Prop({ enum: PartyRole })
role: PartyRole;
@Prop({ enum: PartyRole })
role: PartyRole;
@Prop({ type: PersonSchema })
person: Person;
@Prop({ type: PersonSchema })
person: Person;
/**
* CAR_BODY only: first form – accident with car vs object.
* Second form (guilty/damaged) may be added later as carBodySecondForm.
*/
@Prop({ type: MongooseSchema.Types.Mixed })
carBodyFirstForm?: { car?: boolean; object?: boolean };
/** Distinct people involved with this vehicle; roles below reference participantId. */
@Prop({ type: [InquiryParticipantSchema], default: undefined })
participants?: InquiryParticipant[];
/**
* Party-submitted location (step-driven: FIRST_LOCATION / SECOND_LOCATION).
*/
@Prop({ type: LocationSchema })
location?: Location;
@Prop({ type: VehicleSchema })
vehicle?: Vehicle;
@Prop({ type: InsuranceSchema })
insurance?: Insurance;
@Prop({ type: PartyStatementSchema })
statement?: PartyStatement;
@Prop({ type: EvidenceBundleSchema })
evidence?: EvidenceBundle;
@Prop({ type: PartyConfirmationSchema })
confirmation?: PartyConfirmation;
@Prop({ type: InquiryParticipantRolesSchema })
participantRoles?: InquiryParticipantRoles;
/**
* CAR_BODY only: first form – accident with car vs object.
* Second form (guilty/damaged) may be added later as carBodySecondForm.
*/
@Prop({ type: MongooseSchema.Types.Mixed })
carBodyFirstForm?: { car?: boolean; object?: boolean };
/**
* Party-submitted location (step-driven: FIRST_LOCATION / SECOND_LOCATION).
*/
@Prop({ type: LocationSchema })
location?: Location;
@Prop({ type: VehicleSchema })
vehicle?: Vehicle;
@Prop({ type: InsuranceSchema })
insurance?: Insurance;
@Prop({ type: PartyStatementSchema })
statement?: PartyStatement;
@Prop({ type: EvidenceBundleSchema })
evidence?: EvidenceBundle;
@Prop({ type: PartyConfirmationSchema })
confirmation?: PartyConfirmation;
}
export const PartySchema = SchemaFactory.createForClass(Party);