This commit is contained in:
SepehrYahyaee
2026-07-11 12:23:00 +03:30
parent da3f57870e
commit 7a3ddcc7be
3 changed files with 45 additions and 2 deletions

View File

@@ -0,0 +1,25 @@
import { HttpException, HttpStatus } from "@nestjs/common";
/**
* Thrown when a well-formed request violates a business rule that cannot be
* expressed as a generic validation error. Returns HTTP 422 with a structured
* body so the frontend can branch on `errorCode` without string-matching the
* human-readable `message`.
*
* Response body shape:
* ```json
* { "errorCode": "SOME_CODE", "message": "Human-readable explanation." }
* ```
*/
export class BusinessRuleException extends HttpException {
constructor(
public readonly errorCode: string,
message: string,
) {
super({ errorCode, message }, HttpStatus.UNPROCESSABLE_ENTITY);
}
}
export const BusinessErrorCode = {
DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED: "DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED",
} as const;

View File

@@ -12,6 +12,10 @@ import {
Logger,
NotFoundException,
} from "@nestjs/common";
import {
BusinessErrorCode,
BusinessRuleException,
} from "./exceptions/business-rule.exception";
import { distance as stringDistance } from "fastest-levenshtein"; // حتما نصب بشه
import { Types } from "mongoose";
import { lastValueFrom } from "rxjs";
@@ -3013,7 +3017,8 @@ export class ExpertClaimService {
}
if (existingResend?.fulfilledAt) {
throw new BadRequestException(
throw new BusinessRuleException(
BusinessErrorCode.DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED,
"The owner has already fulfilled a damage-expert resend for this claim. You cannot request another resend.",
);
}

View File

@@ -281,7 +281,20 @@ export class ExpertClaimV2Controller {
description:
"Claim must be locked by this expert (`EXPERT_REVIEWING`). Sets `WAITING_FOR_USER_RESEND`, `USER_EXPERT_RESEND`, `NEEDS_REVISION`, clears the lock, and stores `evaluation.damageExpertResend`. " +
"Owner completes via document/capture endpoints or `POST .../expert-resend/acknowledge` when only instructions were given.\n\n" +
"**One resend per claim lifecycle:** if the owner has already fulfilled a resend (`damageExpertResend.fulfilledAt`), this endpoint returns **400**—the expert may only submit a priced reply or request in-person visit afterward.",
"**One resend per claim lifecycle:** if the owner has already fulfilled a resend (`damageExpertResend.fulfilledAt`), this endpoint returns **422** with `errorCode: DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED`—the expert may only submit a priced reply or request in-person visit afterward.",
})
@ApiResponse({
status: 422,
description:
"Business rule violation: resend limit exceeded. " +
"`errorCode: DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED` — the owner has already fulfilled a prior resend request for this claim.",
schema: {
example: {
errorCode: "DAMAGE_EXPERT_RESEND_LIMIT_EXCEEDED",
message:
"The owner has already fulfilled a damage-expert resend for this claim. You cannot request another resend.",
},
},
})
@ApiParam({ name: "claimRequestId" })
@ApiBody({ type: ClaimSubmitResendV2Dto })