YARA-1078

This commit is contained in:
SepehrYahyaee
2026-08-16 12:35:18 +03:30
parent 875b52d761
commit 01f8a5b12c
6 changed files with 548 additions and 295 deletions

View File

@@ -0,0 +1,186 @@
import { ApiProperty, ApiPropertyOptional } from "@nestjs/swagger";
// ---------------------------------------------------------------------------
// Query helpers
// ---------------------------------------------------------------------------
export type ExpertKindFilter = "all" | "expert" | "damage_expert";
export class InsurerReportQueryDto {
@ApiPropertyOptional({ description: "Start of date range (ISO string)" })
from?: string;
@ApiPropertyOptional({ description: "End of date range (ISO string)" })
to?: string;
@ApiPropertyOptional({
enum: ["all", "expert", "damage_expert"],
description:
"Filter by expert kind. `expert` = blame-panel expert; `damage_expert` = claim damage expert; `all` (default) = both.",
})
expertKind?: ExpertKindFilter;
}
export class InsurerWorkLogQueryDto extends InsurerReportQueryDto {
@ApiPropertyOptional({ type: Number, description: "Page number (1-based)" })
page?: number;
@ApiPropertyOptional({ type: Number, description: "Items per page" })
limit?: number;
}
// ---------------------------------------------------------------------------
// Statistics
// ---------------------------------------------------------------------------
export class InsurerStatisticsBreakdownDto {
@ApiProperty({ description: "Files that have an insurer rating" })
filesWithInsurerRating: number;
@ApiProperty({ description: "Files that have a bot rating" })
filesWithBotRating: number;
@ApiProperty({ description: "Files that have any user rating" })
filesWithUserRating: number;
@ApiProperty({ description: "Files that have an objection" })
filesWithObjection: number;
@ApiProperty({ description: "Average insurer rating (0–5)" })
averageInsurerRating: number;
@ApiProperty({ description: "Average bot rating (0–5)" })
averageBotRating: number;
}
export class InsurerStatisticsDto {
@ApiProperty({
description:
"تعداد کل پرونده‌های بررسی‌شده — distinct tenant claim files with at least one expert CHECKED activity.",
})
totalFilesReviewed: number;
@ApiProperty({
description:
"رضایت کاربران از روند پرونده — average of progressSpeed + registrationEase + overallEvaluation across rated claim files, normalised to 0–100. Formula: (avg of three dimensions across all rated files / 5) * 100.",
})
averageUserRatingPercentage: number;
@ApiProperty({
description:
"پرونده‌های همراه — blame files where expertInitiated === true AND creationMethod === IN_PERSON.",
})
inPersonAccompaniedCount: number;
@ApiProperty({ description: "Claim files created in the current calendar month." })
filesCreatedThisMonth: number;
@ApiProperty({ description: "Total claim files scoped to this insurer." })
totalFiles: number;
@ApiProperty({
description:
"Percentage of total claim files that have any user rating recorded. (NOT a satisfaction metric — do not render as رضایت کاربران.)",
deprecated: true,
})
filesWithUserRatingPercentage: number;
@ApiProperty({ description: "Percentage of files with an objection." })
objectionPercentage: number;
@ApiProperty({ description: "Insurer-to-bot rating ratio (0–100)." })
insurerToBotRatingPercentage: number;
@ApiProperty({ type: InsurerStatisticsBreakdownDto })
breakdown: InsurerStatisticsBreakdownDto;
}
// ---------------------------------------------------------------------------
// Top files
// ---------------------------------------------------------------------------
export class TopFileUserRatingDto {
@ApiPropertyOptional({ description: "User's free-text comment" })
comment?: string | null;
@ApiPropertyOptional({ description: "User's overall evaluation score (0–5)" })
overallEvaluation?: number | null;
}
export class InsurerTopFileDto {
@ApiProperty({ description: "Public file ID — use for front-end link مشاهده پرونده" })
publicId: string;
@ApiProperty({ description: "ISO creation datetime" })
createdAt: string;
@ApiProperty({ description: "Combined insurer + user rating blend (0–5)" })
combinedScore: number;
@ApiProperty({ type: TopFileUserRatingDto })
userRating: TopFileUserRatingDto;
}
// ---------------------------------------------------------------------------
// Top experts
// ---------------------------------------------------------------------------
export class InsurerTopExpertDto {
@ApiProperty()
_id: string;
@ApiProperty()
fullName: string;
@ApiProperty({ enum: ["blame", "claim"] })
expertKind: "blame" | "claim";
@ApiPropertyOptional({ description: "Overall average combined rating (0–5)" })
overallAverageRating: number | null;
@ApiProperty({ description: "Activity stats from expertFileActivity log" })
requestStats: { totalHandled: number; totalChecked: number };
}
export class InsurerTopExpertsDto {
@ApiProperty({ type: [InsurerTopExpertDto], description: "Top blame-panel experts" })
blameExperts: InsurerTopExpertDto[];
@ApiProperty({ type: [InsurerTopExpertDto], description: "Top damage experts (claim)" })
claimExperts: InsurerTopExpertDto[];
}
// ---------------------------------------------------------------------------
// Work-log (mirrors reports.dto.ts shapes; exposed from this module for swagger)
// ---------------------------------------------------------------------------
export class InsurerWorkLogEntryDto {
@ApiProperty()
expertId: string;
@ApiProperty()
fullName: string;
@ApiProperty({ enum: ["expert", "damage_expert"] })
expertKind: "expert" | "damage_expert";
@ApiProperty({ description: "Distinct files in HANDLED state up to cutoff" })
totalHandled: number;
@ApiProperty({ description: "Distinct files currently CHECKED but not yet HANDLED" })
currentlyChecking: number;
@ApiProperty({
description:
"Distinct files with at least one CHECKED event in the reporting window (all-time when no date range given; restricted to from–to otherwise).",
})
distinctFilesCheckedInPeriod: number;
}
export class InsurerWorkLogResponseDto {
@ApiProperty({ type: [InsurerWorkLogEntryDto] })
experts: InsurerWorkLogEntryDto[];
@ApiProperty({ description: "Total experts in roster" })
total: number;
}