forked from Yara724/api
HOTFIX: not allowing empty price when expert tries to submit
This commit is contained in:
19
src/helpers/expert-reply-pricing.spec.ts
Normal file
19
src/helpers/expert-reply-pricing.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { getExpertReplyPricingValidationError } from "./expert-reply-pricing";
|
||||
|
||||
describe("getExpertReplyPricingValidationError", () => {
|
||||
it("rejects a blank pricing line", () => {
|
||||
expect(
|
||||
getExpertReplyPricingValidationError([
|
||||
{ partId: 201, price: "", salary: "", totalPayment: "" },
|
||||
]),
|
||||
).toMatch(/requires valid price, salary, and totalPayment/);
|
||||
});
|
||||
|
||||
it("accepts a fully priced line with a zero-valued split", () => {
|
||||
expect(
|
||||
getExpertReplyPricingValidationError([
|
||||
{ partId: 201, price: "0", salary: "10000", totalPayment: "10000" },
|
||||
]),
|
||||
).toBeNull();
|
||||
});
|
||||
});
|
||||
59
src/helpers/expert-reply-pricing.ts
Normal file
59
src/helpers/expert-reply-pricing.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { REPAIR_LINE_AMOUNT_TOMAN } from "src/constants/repair-amount-limits";
|
||||
import { parseMoneyAmountToman } from "src/utils/unicode-digits";
|
||||
|
||||
type ExpertReplyPricingPart = {
|
||||
partId?: unknown;
|
||||
price?: unknown;
|
||||
salary?: unknown;
|
||||
totalPayment?: unknown;
|
||||
};
|
||||
|
||||
/**
|
||||
* Validates the pricing that an expert must provide for every submitted
|
||||
* damaged-part line. This is deliberately independent of DTO validation:
|
||||
* legacy endpoints and deployments without a global ValidationPipe call the
|
||||
* service directly.
|
||||
*/
|
||||
export function getExpertReplyPricingValidationError(
|
||||
parts: unknown,
|
||||
): string | null {
|
||||
if (!Array.isArray(parts) || parts.length === 0) {
|
||||
return "At least one damaged part with pricing is required to submit an expert reply.";
|
||||
}
|
||||
|
||||
for (const [index, rawPart] of parts.entries()) {
|
||||
const part = rawPart as ExpertReplyPricingPart | null;
|
||||
const label =
|
||||
part && part.partId != null && String(part.partId).trim() !== ""
|
||||
? `Part ${String(part.partId)}`
|
||||
: `Damaged part ${index + 1}`;
|
||||
|
||||
if (!part || typeof part !== "object") {
|
||||
return `${label} must include price, salary, and totalPayment.`;
|
||||
}
|
||||
|
||||
const price = parseMoneyAmountToman(part.price);
|
||||
const salary = parseMoneyAmountToman(part.salary);
|
||||
const totalPayment = parseMoneyAmountToman(part.totalPayment);
|
||||
|
||||
const splitAmountIsValid = (amount: number | null) =>
|
||||
amount !== null &&
|
||||
(amount === 0 ||
|
||||
(amount >= REPAIR_LINE_AMOUNT_TOMAN.MIN &&
|
||||
amount <= REPAIR_LINE_AMOUNT_TOMAN.MAX));
|
||||
const totalIsValid =
|
||||
totalPayment !== null &&
|
||||
totalPayment >= REPAIR_LINE_AMOUNT_TOMAN.MIN &&
|
||||
totalPayment <= REPAIR_LINE_AMOUNT_TOMAN.MAX;
|
||||
|
||||
if (
|
||||
!splitAmountIsValid(price) ||
|
||||
!splitAmountIsValid(salary) ||
|
||||
!totalIsValid
|
||||
) {
|
||||
return `${label} requires valid price, salary, and totalPayment. Price and salary may be 0; totalPayment must be between ${REPAIR_LINE_AMOUNT_TOMAN.MIN.toLocaleString("en-US")} and ${REPAIR_LINE_AMOUNT_TOMAN.MAX.toLocaleString("en-US")} Toman.`;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user