1
0
forked from Yara724/api

Rework the reports and insurer part

This commit is contained in:
2026-04-11 00:12:10 +03:30
parent 7ef057dc1f
commit 9afb079786
10 changed files with 564 additions and 1052 deletions

View File

@@ -7,6 +7,11 @@ import {
Logger,
NotFoundException,
} from "@nestjs/common";
import {
assertBlameCaseForExpertTenant,
blameCaseAccessibleToExpert,
requireActorClientKey,
} from "src/helpers/tenant-scope";
import { RequestManagementDbService } from "src/request-management/entities/db-service/request-management.db.service";
import { BlameRequestDbService } from "src/request-management/entities/db-service/blame-request.db.service";
import {
@@ -185,21 +190,21 @@ export class ExpertBlameService {
*/
async findAllV2(actor: any): Promise<AllRequestDtoRsV2> {
try {
requireActorClientKey(actor);
const expertId = actor.sub;
// Fetch all DISAGREEMENT cases
const allCases = await this.blameRequestDbService.find(
{
blameStatus: BlameStatus.DISAGREEMENT,
},
{ lean: true },
);
const allCases = await this.blameRequestDbService.find({}, { lean: true });
// Filter to show only:
// 1. Fresh requests (WAITING_FOR_EXPERT and no decision)
// 2. Requests decided by current expert
// 3. Expert-initiated: only the initiating field expert sees them
// 1. Same insurance tenant (party clientId or expert-initiated by this actor)
// 2. Fresh requests (WAITING_FOR_EXPERT and no decision)
// 3. Requests decided by current expert
// 4. Expert-initiated: only the initiating field expert sees them
const visibleCases = (allCases as Record<string, unknown>[]).filter((doc) => {
if (!blameCaseAccessibleToExpert(doc, actor)) {
return false;
}
const expertInitiated = doc.expertInitiated === true;
const initiatedByFieldExpertId = doc.initiatedByFieldExpertId;
@@ -520,12 +525,15 @@ export class ExpertBlameService {
* Excludes history. Returns only nonCAR_BODY types. Builds file links for all evidence.
* Access control: Only allows viewing fresh requests or requests decided by current expert.
*/
async findOneV2(requestId: string, actorId: string): Promise<Record<string, unknown>> {
async findOneV2(requestId: string, actor: any): Promise<Record<string, unknown>> {
try {
requireActorClientKey(actor);
const actorId = actor.sub;
const doc = await this.blameRequestDbService.findByIdWithoutHistory(requestId);
if (!doc) {
throw new NotFoundException("Request not found");
}
assertBlameCaseForExpertTenant(doc, actor);
const type = doc.type as string;
if (type === BlameRequestType.CAR_BODY) {
throw new ForbiddenException(
@@ -668,6 +676,8 @@ export class ExpertBlameService {
throw new NotFoundException("Request not found");
}
assertBlameCaseForExpertTenant(request, actorDetail);
// Validate request is available for expert review
if (
request.status !== CaseStatus.WAITING_FOR_EXPERT ||
@@ -696,7 +706,9 @@ export class ExpertBlameService {
const lockExpiryTime = new Date(lockedAt).getTime() + 15 * 60 * 1000;
if (Date.now() < lockExpiryTime) {
// Lock is still valid
const lockedByActorId = String(request.workflow.lockedBy?.actorId);
const lockedByActorId = String(
request.workflow.lockedBy?.actorId ?? "",
);
if (lockedByActorId === actorDetail.sub) {
throw new BadRequestException(
"You have already locked this request",
@@ -755,15 +767,19 @@ export class ExpertBlameService {
async resendRequestV2(
requestId: string,
resendDto: ResendRequestDto,
actorId: string,
actor: any,
): Promise<{ requestId: string; status: string }> {
try {
requireActorClientKey(actor);
const actorId = actor.sub;
const request = await this.blameRequestDbService.findById(requestId);
if (!request) {
throw new NotFoundException("Request not found");
}
assertBlameCaseForExpertTenant(request, actor);
// Validate request is locked by current expert
if (!request.workflow?.locked) {
throw new ForbiddenException(
@@ -872,15 +888,19 @@ export class ExpertBlameService {
async replyRequestV2(
requestId: string,
reply: SubmitReplyDto,
actorId: string,
actor: any,
): Promise<{ requestId: string; status: string }> {
try {
requireActorClientKey(actor);
const actorId = actor.sub;
const request = await this.blameRequestDbService.findById(requestId);
if (!request) {
throw new NotFoundException("Request not found");
}
assertBlameCaseForExpertTenant(request, actor);
// Validate no decision exists yet
if (request.expert?.decision) {
throw new ForbiddenException(

View File

@@ -42,7 +42,7 @@ export class ExpertBlameV2Controller {
@ApiParam({ name: "id", description: "Blame case request id" })
async findOne(@Param("id") id: string, @CurrentUser() actor: any) {
try {
return await this.expertBlameService.findOneV2(id, actor.sub);
return await this.expertBlameService.findOneV2(id, actor);
} catch (error) {
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(
@@ -73,7 +73,7 @@ export class ExpertBlameV2Controller {
@CurrentUser() actor: any,
) {
try {
return await this.expertBlameService.resendRequestV2(id, body, actor.sub);
return await this.expertBlameService.resendRequestV2(id, body, actor);
} catch (error) {
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(
@@ -93,7 +93,7 @@ export class ExpertBlameV2Controller {
@CurrentUser() actor: any,
) {
try {
return await this.expertBlameService.replyRequestV2(id, body, actor.sub);
return await this.expertBlameService.replyRequestV2(id, body, actor);
} catch (error) {
if (error instanceof HttpException) throw error;
throw new InternalServerErrorException(