diff --git a/src/reports/reports.module.ts b/src/reports/reports.module.ts index 4f4b5db..0fb42c3 100644 --- a/src/reports/reports.module.ts +++ b/src/reports/reports.module.ts @@ -1,11 +1,16 @@ import { Module } from "@nestjs/common"; import { ClaimRequestManagementModule } from "src/claim-request-management/claim-request-management.module"; import { RequestManagementModule } from "src/request-management/request-management.module"; +import { ClientModule } from "src/client/client.module"; import { ReportsController } from "./reports.controller"; import { ReportsService } from "./reports.service"; @Module({ - imports: [RequestManagementModule, ClaimRequestManagementModule], + imports: [ + RequestManagementModule, + ClaimRequestManagementModule, + ClientModule, + ], controllers: [ReportsController], providers: [ReportsService], }) diff --git a/src/reports/reports.service.ts b/src/reports/reports.service.ts index decfbb2..131559b 100644 --- a/src/reports/reports.service.ts +++ b/src/reports/reports.service.ts @@ -1,9 +1,11 @@ -import { Injectable } from "@nestjs/common"; +import { Injectable, Logger } from "@nestjs/common"; import { Types } from "mongoose"; import { ClaimRequestManagementDbService } from "src/claim-request-management/entites/db-service/claim-request-management.db.service"; import { RequestManagementDbService } from "src/request-management/entities/db-service/request-management.db.service"; +import { ClientDbService } from "src/client/entities/db-service/client.db.service"; import { ReqBlameStatus } from "src/Types&Enums/blame-request-management/status.enum"; import { ReqClaimStatus } from "src/Types&Enums/claim-request-management/status.enum"; +import { UserType } from "src/Types&Enums/userType.enum"; import { CompanyAllRequestsCountReportDtoRs, DamageExpertAllRequestsCountReportDtoRs, @@ -12,9 +14,12 @@ import { @Injectable() export class ReportsService { + private readonly logger = new Logger(ReportsService.name); + constructor( private readonly requestManagementDbService: RequestManagementDbService, private readonly claimRequestManagementDbService: ClaimRequestManagementDbService, + private readonly clientDbService: ClientDbService, ) {} async getAllCheckedRequestsCountFn(role: string, client: string) { @@ -81,7 +86,91 @@ export class ReportsService { return data; } - async getAllRequestsCountByRole(role: string, client: string) { + private isVisibleToClientType(client: any, actor: any): boolean { + if (actor.userType === UserType.GENUINE) { + return true; + } + if ( + actor.userType === UserType.LEGAL && + String(client._id) === actor.clientKey + ) { + return true; + } + return false; + } + + private wasHandledByActor(request: any, actorSub: string): boolean { + type ActorCheckerEntry = { CheckedRequest?: { actorId: string } }; + const actorChecker = request.actorsChecker as ActorCheckerEntry[]; + + if (!Array.isArray(actorChecker)) { + return false; + } + + const matchingEntry = actorChecker.find( + (entry) => String(entry?.CheckedRequest?.actorId) === actorSub, + ); + + return !!matchingEntry; + } + + /** + * Filters claim requests using the same logic as expert-claim service + * to ensure consistency between endpoints + */ + private async filterClaimRequestsForExpert( + requests: any[], + actor: any, + ): Promise { + const filteredRequests = []; + + for (const r of requests) { + // For expert-initiated blame files, only show to the initiating expert + if (r.blameFile?.expertInitiated && r.blameFile?.initiatedBy) { + if (String(r.blameFile.initiatedBy) !== actor.sub) { + continue; // Skip if not the initiating expert + } + // Expert-initiated claim files are always visible to the initiating expert + filteredRequests.push(r); + continue; + } + + const client = await this.clientDbService.findOne({ + _id: r.userClientKey, + }); + + if (!client) { + this.logger.warn( + `Client not found for claim request with ID: ${r._id}. Skipping.`, + ); + continue; + } + + const specialHandlingStatuses = [ + ReqClaimStatus.CheckAgain, + ReqClaimStatus.ReviewRequest, + ReqClaimStatus.PendingFactorValidation, + ]; + + const requiresSpecificActorCheck = specialHandlingStatuses.includes( + r.claimStatus, + ); + + if (requiresSpecificActorCheck) { + if (this.wasHandledByActor(r, actor.sub)) { + filteredRequests.push(r); + } + } else { + if (this.isVisibleToClientType(client, actor)) { + filteredRequests.push(r); + } + } + } + + return filteredRequests; + } + + async getAllRequestsCountByRole(role: string, client: string, actor?: any) { if (role === "expert") { const statuses = Object.values(ReqBlameStatus); const data: Record = { all: 0 }; @@ -115,16 +204,51 @@ export class ReportsService { const statuses = Object.values(ReqClaimStatus); const data: Record = { all: 0 }; - for (const status of statuses) { - const filter = { - claimStatus: status, - userClientKey: new Types.ObjectId(client), - }; + // For damage_expert, we need to apply the same filtering as expert-claim service + if (actor) { + // Fetch all requests with the statuses that expert-claim service shows + // This matches the statuses in getClaimRequestsListForExpert + const relevantStatuses = [ + ReqClaimStatus.UnChecked, + ReqClaimStatus.ReviewRequest, + ReqClaimStatus.CheckAgain, + ReqClaimStatus.CloseRequest, + ReqClaimStatus.InPersonVisit, + ReqClaimStatus.CheckedRequest, + ReqClaimStatus.PendingFactorValidation, + ]; - const count = - await this.claimRequestManagementDbService.countByFilter(filter); - data[status] = count; - data.all += count; + // Fetch all requests with relevant statuses (matching expert-claim query) + const allRequests = + await this.claimRequestManagementDbService.findAllByStatus({ + claimStatus: { $in: relevantStatuses }, + }); + + // Filter requests using the same logic as expert-claim service + const filteredRequests = + await this.filterClaimRequestsForExpert(allRequests, actor); + + // Count by status from filtered results + for (const status of statuses) { + const count = filteredRequests.filter( + (r) => r.claimStatus === status, + ).length; + data[status] = count; + data.all += count; + } + } else { + // Fallback to simple count if actor not provided (shouldn't happen for damage_expert) + for (const status of statuses) { + const filter = { + claimStatus: status, + userClientKey: new Types.ObjectId(client), + }; + + const count = + await this.claimRequestManagementDbService.countByFilter(filter); + data[status] = count; + data.all += count; + } } return data; @@ -174,7 +298,12 @@ export class ReportsService { async getAllRequestsReportCount(actor, client) { if (actor.role === "damage_expert") { - const data = await this.getAllRequestsCountByRole(actor.role, client); + // Pass actor to apply filtering logic for damage_expert + const data = await this.getAllRequestsCountByRole( + actor.role, + client, + actor, + ); return new DamageExpertAllRequestsCountReportDtoRs(data); } else if (actor.role === "expert") { const data = await this.getAllRequestsCountByRole(actor.role, client);