Initial commit after migration to gitea

This commit is contained in:
2026-01-18 11:27:43 +03:30
parent a21039410c
commit ea4b8eb543
196 changed files with 45567 additions and 9 deletions

View File

@@ -0,0 +1,465 @@
import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
import { Types } from "mongoose";
import {
ResendFirstPartyDto,
ResendSecondPartyDto,
} from "src/expert-blame/dto/reply.dto";
import { AddPlateDto } from "src/profile/dto/user/AddPlateDto";
import { ReqBlameStatus } from "src/Types&Enums/blame-request-management/status.enum";
import { StepsEnum } from "src/Types&Enums/blame-request-management/steps.enum";
export class InitialForm {
@Prop({ required: false, default: false })
expertOpinion?: boolean;
@Prop({ required: false, default: false })
imDamaged?: boolean;
@Prop({ required: false, default: false })
imGuilty?: boolean;
}
export class FirstPartyFile {
@Prop()
descriptions?: string[];
@Prop()
voices?: string[];
@Prop()
firstPartyVideoId?: string;
// CAR_BODY specific accident details
@Prop({ type: Date })
accidentDate?: Date;
@Prop()
accidentTime?: string;
@Prop()
weatherCondition?: string;
@Prop()
roadCondition?: string;
@Prop()
lightCondition?: string;
}
export class CarDetail {
carName?: string;
carModel?: string;
carType?: string;
isNewCar?: boolean;
insurerBirthday?: string;
driverBirthday?: string | null;
}
export class InsuranceDetail {
insuranceId?: string;
insuranceCompany?: string;
financialCommitmentCeiling?: string;
startDate?: string;
endDate?: string;
}
// CAR_BODY specific insurance details for the damaged party
export class CarBodyInsuranceDetail {
@Prop()
policyNumber?: string;
@Prop()
startDate?: string;
@Prop()
endDate?: string;
@Prop()
insurerCompany?: string;
@Prop({ type: [String] })
coverages?: string[];
}
export class SecondPartyFile {
@Prop()
descriptions?: string[];
@Prop()
voices?: string[];
@Prop()
secondPartyVideoId?: string;
}
export class FirstPartyClient {
clientName?: string;
clientId?: Types.ObjectId;
}
export class SecondPartyClient {
clientName?: string;
clientId?: Types.ObjectId;
}
export class FirstPartyDetail {
@Prop({ type: String })
firstPartyId?: Types.ObjectId;
@Prop({ type: String })
firstPartyPhoneNumber?: string;
@Prop({ type: String })
firstPartyClientId?: string;
@Prop({
type: AddPlateDto,
description: "first add plate and send plate id to this field",
})
firstPartyPlate?: AddPlateDto;
@Prop({ type: CarDetail })
firstPartyCarDetail?: CarDetail;
@Prop({ type: InsuranceDetail })
firstPartyInsuranceDetail?: InsuranceDetail;
// Only used for CAR_BODY type requests car body insurance info
@Prop({ type: CarBodyInsuranceDetail })
firstPartyCarBodyInsuranceDetail?: CarBodyInsuranceDetail;
@Prop({ type: FirstPartyFile })
firstPartyClient?: FirstPartyClient;
@Prop({ type: FirstPartyFile })
firstPartyFile?: FirstPartyFile;
@Prop({ type: FirstPartyFile })
firstPartyInitialForm?: InitialForm;
@Prop({ type: Boolean })
firstPartyCertificate: boolean | null;
}
export class SecondPartyDetail {
@Prop({ type: String })
secondPartyId?: Types.ObjectId;
@Prop({ type: String })
secondPartyPhoneNumber?: string;
@Prop({ type: SecondPartyClient })
secondPartyClient?: SecondPartyClient;
@Prop({
type: AddPlateDto,
description: "secondParty add plate and send plate id to this field",
})
secondPartyPlate?: AddPlateDto;
@Prop()
secondPartyCarDetail?: CarDetail;
@Prop({ type: InsuranceDetail })
secondPartyInsuranceDetail?: InsuranceDetail;
@Prop()
secondPartyPlateId?: string;
@Prop({ type: InitialForm })
secondPartyInitialForm: InitialForm;
@Prop({ type: SecondPartyFile })
secondPartyFiles?: SecondPartyFile;
}
export class LocationDto {
@Prop({ type: Number, required: true })
lat: number;
@Prop({ type: Number, required: true })
lon: number;
}
export class AccidentWayIF {
@Prop({ required: true })
id: string;
@Prop({ required: true })
label: string;
}
export class AccidentReasonIF {
@Prop({ required: true })
id: string;
@Prop({ required: true })
label: string;
@Prop({ required: true })
fanavaran: number;
}
export class FieldsInterface {
@Prop({ required: true, type: AccidentWayIF })
accidentWay: AccidentWayIF;
@Prop({ required: true, type: AccidentReasonIF })
accidentReason: AccidentReasonIF;
@Prop({ required: true, type: AccidentWayIF })
accidentType: AccidentWayIF;
}
export class SignDetail {
@Prop()
fileId: string;
@Prop()
fileName: string;
@Prop()
fileUrl: string;
}
export class PartiesComment {
@Prop({ required: true, type: Boolean })
isAccept?: boolean;
@Prop({ required: true })
signDetail?: SignDetail;
}
export class SubmitReply {
@Prop({ required: true })
description: string;
@Prop({ required: true, type: String })
guiltyUserId: Types.ObjectId;
@Prop({ required: true })
fields: FieldsInterface;
@Prop({ required: true, default: () => new Date() })
submitTime: Date;
@Prop({ type: PartiesComment })
firstPartyComment?: PartiesComment;
@Prop({ type: PartiesComment })
secondPartyComment?: PartiesComment;
@Prop()
systemResponse: string;
}
export class ExpertResendParties {
userId?: Types.ObjectId;
description?: string;
}
export class ExpertResendReply {
// TODO change DTOs to dynamic Exmple SubmitReply Parties comment
@Prop()
firstParty?: ResendFirstPartyDto;
@Prop()
secondParty?: ResendSecondPartyDto;
}
export class ActorLockDetails {
@Prop({ type: String })
fullName?: string;
@Prop({ type: Types.ObjectId })
actorId?: Types.ObjectId;
}
export enum CreationMethod {
NORMAL = "NORMAL",
LINK = "LINK",
IN_PERSON = "IN_PERSON",
}
export enum FilledBy {
CUSTOMER = "customer",
EXPERT = "expert",
}
export class ExpertLinkInfo {
@Prop({ type: String, required: true })
token: string;
@Prop({ type: Date, required: true })
expiresAt: Date;
@Prop({ type: Boolean, default: false })
isUsed: boolean;
@Prop({ type: Boolean, default: false })
isExpired: boolean;
@Prop({ type: Date })
generatedAt: Date;
@Prop({ type: String })
sentTo?: string; // Phone number or email
@Prop({ type: Number, default: 0 })
openCount: number;
@Prop({ type: Date })
lastOpenedAt?: Date;
@Prop({ type: Date })
usedAt?: Date;
}
export class FileHistoryEvent {
@Prop({ type: String, required: true })
eventType: string; // "LINK_SENT", "LINK_OPENED", "FILLED_BY_CUSTOMER", "FILLED_BY_EXPERT", "ASSIGNED_TO_EXPERT", "EVALUATION_STARTED", "EVALUATION_COMPLETED", "USER_ACCEPTED", "USER_REJECTED", "SENT_TO_FANAVARAN", "CODE_RECEIVED"
@Prop({ type: Types.ObjectId })
actorId?: Types.ObjectId;
@Prop({ type: String })
actorName?: string;
@Prop({ type: String })
actorType?: string; // "expert", "damage_expert", "customer"
@Prop({ type: Date, default: () => new Date() })
timestamp: Date;
@Prop({ type: Object })
metadata?: any; // Additional event-specific data
}
@Schema({ _id: false })
export class FileRating {
@Prop({ type: Number, min: 0, max: 5 })
collisionMethodAccuracy: number;
@Prop({ type: Number, min: 0, max: 5 })
evaluationTimeliness: number;
@Prop({ type: Number, min: 0, max: 5 })
accidentCauseAccuracy: number;
@Prop({ type: Number, min: 0, max: 5 })
guiltyVehicleIdentification: number;
}
// TODO clean all sub Object to other files
export type RequestManagementDocs = RequestManagementModel & Document;
@Schema({
collection: "requests-management",
versionKey: false,
timestamps: true,
autoIndex: true,
_id: true,
})
export class RequestManagementModel {
@Prop({ type: String, required: false })
type: string;
@Prop({ type: String, required: true, index: { unique: true } })
requestNumber: string;
@Prop()
blameStatus: ReqBlameStatus | StepsEnum;
@Prop()
steps?: StepsEnum[];
@Prop()
userComment?: string;
@Prop()
currentStep: StepsEnum;
@Prop()
nextStep?: StepsEnum;
@Prop({ description: "first step" })
initialForm?: InitialForm;
@Prop({ required: false })
firstPartyDetails?: FirstPartyDetail;
@Prop({ required: false, type: Types.ObjectId })
sanHubId?: Types.ObjectId;
@Prop({ required: false })
secondPartyDetails?: SecondPartyDetail;
@Prop({ required: false, description: "third step call" })
firstPartyLocation?: LocationDto;
@Prop({ required: false })
secondPartyLocation?: LocationDto;
@Prop({ type: Date, default: Date.now })
createdAt?: Date | string;
@Prop({ type: Date, default: Date.now })
updatedAt?: Date;
@Prop()
lockFile?: boolean;
@Prop({ type: Date })
lockTime?: Date | string | number;
@Prop({ type: Date })
unlockTime?: Date | number;
@Prop()
actorLocked?: ActorLockDetails;
@Prop()
actorsChecker?: [];
@Prop({ required: false })
expertSubmitReply?: SubmitReply | null;
@Prop()
expertResendReply?: ExpertResendReply;
@Prop()
expertSubmitReplyFinal?: ExpertResendReply;
@Prop({ type: FileRating, required: false })
rating?: FileRating;
@Prop({ type: Date, required: false })
autoCloseTriggerTime?: Date;
@Prop({ type: Boolean, default: false })
isHandledStatsUpdated?: boolean;
// Expert-initiated file tracking
@Prop({ type: Boolean, default: false })
expertInitiated?: boolean;
@Prop({ type: Types.ObjectId })
initiatedBy?: Types.ObjectId; // Expert who started the process
@Prop({ type: String, enum: FilledBy })
filledBy?: FilledBy; // Who filled the information
@Prop({ type: String, enum: CreationMethod, default: CreationMethod.NORMAL })
creationMethod?: CreationMethod; // How the file was created
@Prop({ type: ExpertLinkInfo })
expertLink?: ExpertLinkInfo; // Link information if created via link
@Prop({ type: [FileHistoryEvent], default: [] })
history?: FileHistoryEvent[]; // Timeline of events
@Prop({ type: Types.ObjectId })
assignedExpertId?: Types.ObjectId; // Expert assigned for evaluation (should be same as initiatedBy for expert-initiated files)
}
export const RequestManagementSchema = SchemaFactory.createForClass(
RequestManagementModel,
);