forked from Yara724/api
Added insurer capabilities for super-admin
This commit is contained in:
@@ -1,18 +1,25 @@
|
|||||||
import {
|
import {
|
||||||
|
BadRequestException,
|
||||||
Body,
|
Body,
|
||||||
Controller,
|
Controller,
|
||||||
Get,
|
Get,
|
||||||
|
Param,
|
||||||
Patch,
|
Patch,
|
||||||
Post,
|
Post,
|
||||||
|
Put,
|
||||||
|
Query,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
} from "@nestjs/common";
|
} from "@nestjs/common";
|
||||||
import {
|
import {
|
||||||
ApiBearerAuth,
|
ApiBearerAuth,
|
||||||
ApiBody,
|
ApiBody,
|
||||||
ApiOperation,
|
ApiOperation,
|
||||||
|
ApiParam,
|
||||||
|
ApiQuery,
|
||||||
ApiResponse,
|
ApiResponse,
|
||||||
ApiTags,
|
ApiTags,
|
||||||
} from "@nestjs/swagger";
|
} from "@nestjs/swagger";
|
||||||
|
import { Types } from "mongoose";
|
||||||
import { SuperAdminGuard } from "./guards/super-admin.guard";
|
import { SuperAdminGuard } from "./guards/super-admin.guard";
|
||||||
import { SuperAdminService } from "./super-admin.service";
|
import { SuperAdminService } from "./super-admin.service";
|
||||||
import {
|
import {
|
||||||
@@ -32,6 +39,20 @@ import {
|
|||||||
UpdateSystemSettingsDto,
|
UpdateSystemSettingsDto,
|
||||||
} from "src/system-settings/dto/system-settings.dto";
|
} from "src/system-settings/dto/system-settings.dto";
|
||||||
import { SetExternalInquiriesLiveDto } from "src/client/dto/external-inquiries-live.dto";
|
import { SetExternalInquiriesLiveDto } from "src/client/dto/external-inquiries-live.dto";
|
||||||
|
import { ExpertInsurerService } from "src/expert-insurer/expert-insurer.service";
|
||||||
|
import { ListQueryV2Dto } from "src/common/dto/list-query-v2.dto";
|
||||||
|
import {
|
||||||
|
UnifiedFileStatusReportDto,
|
||||||
|
UnifiedFileStatusReportQueryDto,
|
||||||
|
} from "src/common/dto/unified-file-status-report.dto";
|
||||||
|
import { CreateBranchDto } from "src/client/dto/create-branch.dto";
|
||||||
|
import { FileRating } from "src/request-management/entities/schema/request-management.schema";
|
||||||
|
import {
|
||||||
|
CreateBlameExpertByInsurerDto,
|
||||||
|
CreateClaimExpertByInsurerDto,
|
||||||
|
CreateFileMakerByInsurerDto,
|
||||||
|
CreateFileReviewerByInsurerDto,
|
||||||
|
} from "src/expert-insurer/dto/create-insurer-expert.dto";
|
||||||
|
|
||||||
@ApiTags("super-admin")
|
@ApiTags("super-admin")
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@@ -41,6 +62,7 @@ export class SuperAdminController {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly superAdminService: SuperAdminService,
|
private readonly superAdminService: SuperAdminService,
|
||||||
private readonly systemSettingsService: SystemSettingsService,
|
private readonly systemSettingsService: SystemSettingsService,
|
||||||
|
private readonly expertInsurerService: ExpertInsurerService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
// ── Super-admin account management ───────────────────────────────────────
|
// ── Super-admin account management ───────────────────────────────────────
|
||||||
@@ -159,4 +181,313 @@ export class SuperAdminController {
|
|||||||
externalApis: { sandHubUseLiveApi: body?.enabled === true },
|
externalApis: { sandHubUseLiveApi: body?.enabled === true },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Insurer panel (super-admin proxy) ────────────────────────────────────
|
||||||
|
|
||||||
|
@Get("insurer/branches")
|
||||||
|
@ApiOperation({ summary: "List branches for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
@ApiQuery({ name: "search", required: false, type: String })
|
||||||
|
@ApiQuery({ name: "from", required: false, description: "Optional start datetime (ISO string)" })
|
||||||
|
@ApiQuery({ name: "to", required: false, description: "Optional end datetime (ISO string)" })
|
||||||
|
@ApiQuery({ name: "isActive", required: false, description: "Filter active state (true/false)" })
|
||||||
|
getInsuranceBranches(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Query("search") search?: string,
|
||||||
|
@Query("from") from?: string,
|
||||||
|
@Query("to") to?: string,
|
||||||
|
@Query("isActive") isActive?: string,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.retrieveInsuranceBranches(
|
||||||
|
clientId,
|
||||||
|
{ search, from, to, isActive },
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("insurer/branches")
|
||||||
|
@ApiOperation({ summary: "Add a branch for a given client" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
allOf: [
|
||||||
|
{ $ref: "#/components/schemas/CreateBranchDto" },
|
||||||
|
{
|
||||||
|
type: "object",
|
||||||
|
required: ["clientId"],
|
||||||
|
properties: { clientId: { type: "string", description: "Client ObjectId" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addBranch(
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body() createBranchDto: CreateBranchDto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.addBranch(clientId, createBranchDto);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Put("insurer/branches/:branchId/status")
|
||||||
|
@ApiOperation({ summary: "Set branch active/inactive for a given client" })
|
||||||
|
@ApiParam({ name: "branchId" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
clientId: { type: "string", description: "Client ObjectId" },
|
||||||
|
isActive: { type: "boolean" },
|
||||||
|
},
|
||||||
|
required: ["clientId", "isActive"],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setBranchStatus(
|
||||||
|
@Param("branchId") branchId: string,
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body("isActive") isActive: unknown,
|
||||||
|
) {
|
||||||
|
let active: boolean;
|
||||||
|
if (typeof isActive === "boolean") {
|
||||||
|
active = isActive;
|
||||||
|
} else {
|
||||||
|
const normalized = String(isActive ?? "").trim().toLowerCase();
|
||||||
|
if (!["true", "false", "1", "0", "yes", "no"].includes(normalized)) {
|
||||||
|
throw new BadRequestException("isActive must be a boolean");
|
||||||
|
}
|
||||||
|
active = ["true", "1", "yes"].includes(normalized);
|
||||||
|
}
|
||||||
|
return this.expertInsurerService.setBranchActive(clientId, branchId, active);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("insurer/experts/blame")
|
||||||
|
@ApiOperation({ summary: "Create a blame expert under a given client" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
allOf: [
|
||||||
|
{ $ref: "#/components/schemas/CreateBlameExpertByInsurerDto" },
|
||||||
|
{
|
||||||
|
type: "object",
|
||||||
|
required: ["clientId"],
|
||||||
|
properties: { clientId: { type: "string", description: "Client ObjectId" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addBlameExpert(
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body() body: CreateBlameExpertByInsurerDto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.addBlameExpert(clientId, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("insurer/experts/claim")
|
||||||
|
@ApiOperation({ summary: "Create a claim expert under a given client" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
allOf: [
|
||||||
|
{ $ref: "#/components/schemas/CreateClaimExpertByInsurerDto" },
|
||||||
|
{
|
||||||
|
type: "object",
|
||||||
|
required: ["clientId"],
|
||||||
|
properties: { clientId: { type: "string", description: "Client ObjectId" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addClaimExpert(
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body() body: CreateClaimExpertByInsurerDto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.addClaimExpert(clientId, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("insurer/experts/file-maker")
|
||||||
|
@ApiOperation({ summary: "Create a FileMaker account under a given client" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
allOf: [
|
||||||
|
{ $ref: "#/components/schemas/CreateFileMakerByInsurerDto" },
|
||||||
|
{
|
||||||
|
type: "object",
|
||||||
|
required: ["clientId"],
|
||||||
|
properties: { clientId: { type: "string", description: "Client ObjectId" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addFileMaker(
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body() body: CreateFileMakerByInsurerDto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.addFileMaker(clientId, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post("insurer/experts/file-reviewer")
|
||||||
|
@ApiOperation({ summary: "Create a FileReviewer account under a given client" })
|
||||||
|
@ApiBody({
|
||||||
|
schema: {
|
||||||
|
allOf: [
|
||||||
|
{ $ref: "#/components/schemas/CreateFileReviewerByInsurerDto" },
|
||||||
|
{
|
||||||
|
type: "object",
|
||||||
|
required: ["clientId"],
|
||||||
|
properties: { clientId: { type: "string", description: "Client ObjectId" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addFileReviewer(
|
||||||
|
@Body("clientId") clientId: string,
|
||||||
|
@Body() body: CreateFileReviewerByInsurerDto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.addFileReviewer(clientId, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/experts/list")
|
||||||
|
@ApiOperation({ summary: "List all experts of a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
@ApiQuery({ name: "page", type: Number })
|
||||||
|
@ApiQuery({ name: "response_count", type: Number })
|
||||||
|
getAllExperts(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Query("page") page: number,
|
||||||
|
@Query("response_count") count: number,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.retrieveAllExpertsOfClient(
|
||||||
|
{ clientKey: clientId },
|
||||||
|
page,
|
||||||
|
count,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/experts/top")
|
||||||
|
@ApiOperation({ summary: "Top blame vs claim experts for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getTopExperts(@Query("clientId") clientId: string) {
|
||||||
|
return this.expertInsurerService.getTopExpertsForClient({ clientKey: clientId });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/files")
|
||||||
|
@ApiOperation({ summary: "List files (blame + claim merged) for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getAllFiles(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Query() query: ListQueryV2Dto,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.retrieveAllFilesOfClient(clientId, query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/report/unified-file-statuses")
|
||||||
|
@ApiOperation({ summary: "Unified file status catalog + counts for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
@ApiResponse({ status: 200, type: UnifiedFileStatusReportDto })
|
||||||
|
getUnifiedFileStatusReport(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Query() query: UnifiedFileStatusReportQueryDto,
|
||||||
|
): Promise<UnifiedFileStatusReportDto> {
|
||||||
|
return this.expertInsurerService.getInsurerUnifiedFileStatusReport(
|
||||||
|
{ clientKey: clientId },
|
||||||
|
query,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/report/status-counts")
|
||||||
|
@ApiOperation({
|
||||||
|
summary: "Legacy status counts for a given client",
|
||||||
|
deprecated: true,
|
||||||
|
description: "Prefer GET insurer/report/unified-file-statuses.",
|
||||||
|
})
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
@ApiQuery({ name: "from", required: false, description: "Optional start datetime (ISO string)" })
|
||||||
|
@ApiQuery({ name: "to", required: false, description: "Optional end datetime (ISO string)" })
|
||||||
|
getInsurerStatusReport(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Query("from") from?: string,
|
||||||
|
@Query("to") to?: string,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.getInsurerFileStatusCounts(
|
||||||
|
{ clientKey: clientId },
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/files/:publicId/timeline")
|
||||||
|
@ApiOperation({ summary: "Activity timeline for a case of a given client" })
|
||||||
|
@ApiParam({ name: "publicId" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getFileTimeline(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Param("publicId") publicId: string,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.getFileTimeline(clientId, publicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/files/:publicId")
|
||||||
|
@ApiOperation({ summary: "File details by publicId for a given client" })
|
||||||
|
@ApiParam({ name: "publicId" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getFileDetailsByPublicId(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Param("publicId") publicId: string,
|
||||||
|
) {
|
||||||
|
return this.expertInsurerService.retrieveFileDetailsByPublicId(clientId, publicId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @Put("insurer/files/:publicId/rating")
|
||||||
|
// @ApiOperation({ summary: "Rate experts by publicId for a given client" })
|
||||||
|
// @ApiParam({ name: "publicId" })
|
||||||
|
// @ApiBody({
|
||||||
|
// schema: {
|
||||||
|
// type: "object",
|
||||||
|
// required: [
|
||||||
|
// "clientId",
|
||||||
|
// "collisionMethodAccuracy",
|
||||||
|
// "evaluationTimeliness",
|
||||||
|
// "accidentCauseAccuracy",
|
||||||
|
// "guiltyVehicleIdentification",
|
||||||
|
// "botRating",
|
||||||
|
// ],
|
||||||
|
// properties: {
|
||||||
|
// clientId: { type: "string", description: "Client ObjectId" },
|
||||||
|
// collisionMethodAccuracy: { type: "number", minimum: 0, maximum: 5 },
|
||||||
|
// evaluationTimeliness: { type: "number", minimum: 0, maximum: 5 },
|
||||||
|
// accidentCauseAccuracy: { type: "number", minimum: 0, maximum: 5 },
|
||||||
|
// guiltyVehicleIdentification: { type: "number", minimum: 0, maximum: 5 },
|
||||||
|
// botRating: { type: "number", minimum: 0, maximum: 5 },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
// rateExpertsByPublicId(
|
||||||
|
// @Param("publicId") publicId: string,
|
||||||
|
// @Body() body: FileRating & { clientId: string },
|
||||||
|
// ) {
|
||||||
|
// const { clientId, ...rating } = body;
|
||||||
|
// return this.expertInsurerService.rateExpertByPublicId(publicId, rating as FileRating, clientId);
|
||||||
|
// }
|
||||||
|
|
||||||
|
@Get("insurer/top-files")
|
||||||
|
@ApiOperation({ summary: "Top-rated files for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getTopFiles(@Query("clientId") clientId: string) {
|
||||||
|
return this.expertInsurerService.getTopFilesForClient(clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/statistics")
|
||||||
|
@ApiOperation({ summary: "Expert statistics report for a given client" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getExpertStatistics(@Query("clientId") clientId: string) {
|
||||||
|
return this.expertInsurerService.getExpertStatisticsReport({ clientKey: clientId });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get("insurer/:expertId")
|
||||||
|
@ApiOperation({ summary: "Files handled by one roster expert for a given client" })
|
||||||
|
@ApiParam({ name: "expertId" })
|
||||||
|
@ApiQuery({ name: "clientId", required: true, type: String })
|
||||||
|
getExpertFiles(
|
||||||
|
@Query("clientId") clientId: string,
|
||||||
|
@Param("expertId") expertId: string,
|
||||||
|
) {
|
||||||
|
if (!Types.ObjectId.isValid(expertId)) {
|
||||||
|
throw new BadRequestException("Invalid expert ID");
|
||||||
|
}
|
||||||
|
return this.expertInsurerService.getAllFilesForInsurerExpert(expertId, clientId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import { ClientModule } from "src/client/client.module";
|
|||||||
import { SystemSettingsModule } from "src/system-settings/system-settings.module";
|
import { SystemSettingsModule } from "src/system-settings/system-settings.module";
|
||||||
import { HashModule } from "src/utils/hash/hash.module";
|
import { HashModule } from "src/utils/hash/hash.module";
|
||||||
import { UsersModule } from "src/users/users.module";
|
import { UsersModule } from "src/users/users.module";
|
||||||
|
import { ExpertInsurerModule } from "src/expert-insurer/expert-insurer.module";
|
||||||
import { SuperAdminController } from "./super-admin.controller";
|
import { SuperAdminController } from "./super-admin.controller";
|
||||||
import { SuperAdminService } from "./super-admin.service";
|
import { SuperAdminService } from "./super-admin.service";
|
||||||
import { SuperAdminGuard } from "./guards/super-admin.guard";
|
import { SuperAdminGuard } from "./guards/super-admin.guard";
|
||||||
@@ -26,6 +27,7 @@ import { SuperAdminGuard } from "./guards/super-admin.guard";
|
|||||||
SystemSettingsModule,
|
SystemSettingsModule,
|
||||||
HashModule,
|
HashModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
ExpertInsurerModule,
|
||||||
],
|
],
|
||||||
controllers: [SuperAdminController],
|
controllers: [SuperAdminController],
|
||||||
providers: [SuperAdminService, SuperAdminGuard],
|
providers: [SuperAdminService, SuperAdminGuard],
|
||||||
|
|||||||
Reference in New Issue
Block a user