forked from Yara724/api
fix: align inquiry errors and expert review rules
This commit is contained in:
@@ -156,7 +156,7 @@ import {
|
||||
ExpertFileKind,
|
||||
} from "src/users/entities/schema/expert-file-activity.schema";
|
||||
|
||||
/** Maximum sum of line `totalPayment` across the claim (Toman; priced parts + factor lines after validation). */
|
||||
/** Configured V1 maximum sum of line `totalPayment` across the claim (Rial). */
|
||||
import { getClaimV2TotalPaymentCapToman } from "src/constants/repair-amount-limits";
|
||||
import { ListQueryV2Dto } from "src/common/dto/list-query-v2.dto";
|
||||
import {
|
||||
@@ -180,6 +180,7 @@ import {
|
||||
normalizeMoneyAmountString,
|
||||
parseMoneyAmountToman,
|
||||
} from "src/utils/unicode-digits";
|
||||
import { claimPriceCapAppliesToBlame } from "src/helpers/claim-price-cap";
|
||||
|
||||
@Injectable()
|
||||
export class ExpertClaimService {
|
||||
@@ -1694,8 +1695,13 @@ export class ExpertClaimService {
|
||||
throw new BadRequestException(pricingValidationError);
|
||||
}
|
||||
|
||||
// Validate total price cap (priced lines sum), when enabled.
|
||||
const priceCap = getClaimV2TotalPaymentCapToman();
|
||||
// The total cap is a V1-only rule. Legacy claims embed their blame file.
|
||||
const configuredPriceCap = getClaimV2TotalPaymentCapToman();
|
||||
const priceCap =
|
||||
configuredPriceCap !== null &&
|
||||
claimPriceCapAppliesToBlame(request.blameFile)
|
||||
? configuredPriceCap
|
||||
: null;
|
||||
if (priceCap !== null && reply.parts && reply.parts.length > 0) {
|
||||
let totalPrice = 0;
|
||||
|
||||
@@ -1727,7 +1733,7 @@ export class ExpertClaimService {
|
||||
|
||||
if (totalPrice > priceCap) {
|
||||
throw new BadRequestException({
|
||||
message: `You have reached the maximum acceptable total price (Toman). The sum of priced parts and factor lines (${totalPrice.toLocaleString()}) exceeds the limit (${priceCap.toLocaleString()}).`,
|
||||
message: `You have reached the maximum acceptable total price (Rial). The sum of priced parts and factor lines (${totalPrice.toLocaleString()}) exceeds the limit (${priceCap.toLocaleString()}).`,
|
||||
error: "PRICE_CAP_ERROR",
|
||||
code: "PRICE_CAP_ERROR",
|
||||
totalPrice: totalPrice,
|
||||
@@ -2293,7 +2299,8 @@ export class ExpertClaimService {
|
||||
* Preconditions: all `factorNeeded` parts have `factorLink`; case is UNDER_REVIEW at EXPERT_COST_EVALUATION.
|
||||
* — All approved → COMPLETED + APPROVED (expert-entered line totals; no extra owner signature).
|
||||
* — Any rejected (repriced) → COMPLETED + APPROVED (auto-close for now; owner sign may be added later).
|
||||
* When enabled by env, total of all repair lines must be ≤ the claim v2 total payment cap.
|
||||
* For V1 user-created files, when enabled by env, the total of all repair
|
||||
* lines must be no greater than the configured total-payment cap.
|
||||
* Response: `claimStatus` = `ClaimStatus`; `caseStatus` = `ClaimCaseStatus`.
|
||||
*/
|
||||
async validateClaimFactorsV2(
|
||||
@@ -2433,7 +2440,12 @@ export class ExpertClaimService {
|
||||
};
|
||||
}
|
||||
|
||||
const priceCap = getClaimV2TotalPaymentCapToman();
|
||||
const configuredPriceCap = getClaimV2TotalPaymentCapToman();
|
||||
const priceCap =
|
||||
configuredPriceCap !== null &&
|
||||
claimPriceCapAppliesToBlame(await this.loadBlameForClaim(claim))
|
||||
? configuredPriceCap
|
||||
: null;
|
||||
if (priceCap !== null) {
|
||||
let totalPrice = 0;
|
||||
for (const part of updatedReply.parts || []) {
|
||||
@@ -2448,7 +2460,7 @@ export class ExpertClaimService {
|
||||
}
|
||||
if (totalPrice > priceCap) {
|
||||
throw new BadRequestException({
|
||||
message: `You have reached the maximum acceptable total price (Toman). The sum of priced parts and factor lines (${totalPrice.toLocaleString()}) exceeds the limit (${priceCap.toLocaleString()}).`,
|
||||
message: `You have reached the maximum acceptable total price (Rial). The sum of priced parts and factor lines (${totalPrice.toLocaleString()}) exceeds the limit (${priceCap.toLocaleString()}).`,
|
||||
error: "PRICE_CAP_ERROR",
|
||||
totalPrice,
|
||||
priceCap,
|
||||
@@ -3259,7 +3271,7 @@ export class ExpertClaimService {
|
||||
* - Claim must exist
|
||||
* - Must be locked by this expert (workflow.lockedBy.actorId === actor.sub)
|
||||
* - Must be in EXPERT_REVIEWING status
|
||||
* - Total payment across all parts must not exceed 53,000,000 (same cap as factor validation totals)
|
||||
* - V1 only: total payment across all parts must not exceed the configured cap
|
||||
* - Each part must include `daghi` (option + conditional price) like V1
|
||||
*
|
||||
* On success:
|
||||
@@ -3364,8 +3376,12 @@ export class ExpertClaimService {
|
||||
throw new BadRequestException(pricingValidationError);
|
||||
}
|
||||
|
||||
// Price cap validation, when enabled.
|
||||
const priceCap = getClaimV2TotalPaymentCapToman();
|
||||
// The configured total cap is enforced only for V1 user-created files.
|
||||
const configuredPriceCap = getClaimV2TotalPaymentCapToman();
|
||||
const priceCap =
|
||||
configuredPriceCap !== null && claimPriceCapAppliesToBlame(blame)
|
||||
? configuredPriceCap
|
||||
: null;
|
||||
if (priceCap !== null) {
|
||||
let totalPrice = 0;
|
||||
for (const part of reply.parts || []) {
|
||||
@@ -3376,7 +3392,7 @@ export class ExpertClaimService {
|
||||
}
|
||||
if (totalPrice > priceCap) {
|
||||
throw new BadRequestException({
|
||||
message: `مجموع مبلغ قطعات (${totalPrice.toLocaleString("fa-IR")}) از سقف مجاز (${priceCap.toLocaleString("fa-IR")}) تومان بیشتر است.`,
|
||||
message: `مجموع مبلغ قطعات (${totalPrice.toLocaleString("fa-IR")}) از سقف مجاز (${priceCap.toLocaleString("fa-IR")}) ریال بیشتر است.`,
|
||||
error: "PRICE_CAP_ERROR",
|
||||
code: "PRICE_CAP_ERROR",
|
||||
totalPrice,
|
||||
@@ -5125,7 +5141,11 @@ export class ExpertClaimService {
|
||||
claim.blameRequestId
|
||||
? this.blameRequestDbService.find(
|
||||
{ _id: new Types.ObjectId(claim.blameRequestId.toString()) },
|
||||
{ lean: true, select: "type parties expert.decision" },
|
||||
{
|
||||
lean: true,
|
||||
select:
|
||||
"type parties expert.decision creationMethod expertInitiated registrarInitiated callCenterInitiated initiatedByFieldExpertId initiatedByRegistrarId initiatedByCallCenterId",
|
||||
},
|
||||
)
|
||||
: Promise.resolve([]),
|
||||
]);
|
||||
@@ -5160,6 +5180,11 @@ export class ExpertClaimService {
|
||||
const blameFileContext = blameLean
|
||||
? this.blameFileContextForExpert(blameLean)
|
||||
: {};
|
||||
const configuredPriceCap = getClaimV2TotalPaymentCapToman();
|
||||
const priceCap =
|
||||
configuredPriceCap !== null && claimPriceCapAppliesToBlame(linkedBlame)
|
||||
? configuredPriceCap
|
||||
: null;
|
||||
|
||||
let videoCapture: ClaimDetailV2ResponseDto["videoCapture"] = undefined;
|
||||
if (videoCaptureRow) {
|
||||
@@ -5269,6 +5294,7 @@ export class ExpertClaimService {
|
||||
? this.sanitizeVehicleInquiryForApi(vehiclePayload)
|
||||
: undefined,
|
||||
...blameFileContext,
|
||||
priceCap,
|
||||
blameRequestId: claim.blameRequestId?.toString(),
|
||||
blameRequestNo: claim.blameRequestNo,
|
||||
money: moneyPayload,
|
||||
|
||||
Reference in New Issue
Block a user