forked from Yara724/api
Fixed daqi being enforced on REPAIR
This commit is contained in:
@@ -43,4 +43,22 @@ describe("SubmitExpertReplyV2Dto", () => {
|
||||
|
||||
expect(await validate(dto)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("accepts a repair part without daghi", async () => {
|
||||
const dto = plainToInstance(SubmitExpertReplyV2Dto, {
|
||||
description: "Damage assessment",
|
||||
parts: [
|
||||
{
|
||||
partId: 201,
|
||||
typeOfDamage: TypeOfDamage.Repair,
|
||||
price: "10000",
|
||||
salary: "0",
|
||||
totalPayment: "10000",
|
||||
factorNeeded: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(await validate(dto)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -94,11 +94,17 @@ export class PartPricingV2Dto {
|
||||
@IsRepairLineAmountToman({ allowZero: true })
|
||||
totalPayment: string;
|
||||
|
||||
@ApiProperty({ type: DaghiDetailsV2Dto })
|
||||
@ApiPropertyOptional({
|
||||
type: DaghiDetailsV2Dto,
|
||||
description: "Required for change lines; omit for repair lines.",
|
||||
})
|
||||
@ValidateIf(
|
||||
(part: PartPricingV2Dto) => part.typeOfDamage === TypeOfDamage.Change,
|
||||
)
|
||||
@IsNotEmpty()
|
||||
@ValidateNested()
|
||||
@Type(() => DaghiDetailsV2Dto)
|
||||
daghi: DaghiDetailsV2Dto;
|
||||
daghi?: DaghiDetailsV2Dto;
|
||||
|
||||
@ApiProperty({
|
||||
example: false,
|
||||
|
||||
@@ -27,6 +27,31 @@ function createService() {
|
||||
}
|
||||
|
||||
describe("ExpertClaimService expert-reply pricing", () => {
|
||||
it("allows a repair line without daghi and removes a stray daghi payload", () => {
|
||||
const service = createService() as any;
|
||||
|
||||
expect(
|
||||
service.validateAndNormalizeDaghiForExpertReplyV2([
|
||||
{
|
||||
partId: 201,
|
||||
typeOfDamage: TypeOfDamage.Repair,
|
||||
price: "10000",
|
||||
salary: "0",
|
||||
totalPayment: "10000",
|
||||
daghi: { option: DaghiOption.NO_VALUE },
|
||||
},
|
||||
]),
|
||||
).toEqual([
|
||||
{
|
||||
partId: 201,
|
||||
typeOfDamage: TypeOfDamage.Repair,
|
||||
price: "10000",
|
||||
salary: "0",
|
||||
totalPayment: "10000",
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("rejects a blank pricing line on the legacy submit endpoint before changing status", async () => {
|
||||
const service = createService() as any;
|
||||
const findAndUpdate = jest.fn();
|
||||
|
||||
@@ -102,6 +102,7 @@ import { ClaimFactorsImageDbService } from "src/claim-request-management/entites
|
||||
import { ClaimRequiredDocumentDbService } from "src/claim-request-management/entites/db-service/claim-required-document.db.service";
|
||||
import { FactorStatus } from "src/Types&Enums/claim-request-management/factor-status.enum";
|
||||
import { DaghiOption } from "src/Types&Enums/claim-request-management/daghi-option.enum";
|
||||
import { TypeOfDamage } from "src/Types&Enums/claim-request-management/type-of-damage.enum";
|
||||
import { BranchDbService } from "src/client/entities/db-service/branch.db.service";
|
||||
import { ClaimSubmitResendV2Dto } from "./dto/expert-claim-v2.dto";
|
||||
import { BlameRequestDbService } from "src/request-management/entities/db-service/blame-request.db.service";
|
||||
@@ -947,6 +948,7 @@ export class ExpertClaimService {
|
||||
parts: import("./dto/expert-claim-v2.dto").PartPricingV2Dto[],
|
||||
) {
|
||||
for (const part of parts) {
|
||||
if (part.typeOfDamage === TypeOfDamage.Repair) continue;
|
||||
if (!part.daghi || !part.daghi.option) {
|
||||
throw new BadRequestException(
|
||||
`Daghi option is required for part ${part.partId}`,
|
||||
@@ -972,16 +974,23 @@ export class ExpertClaimService {
|
||||
}
|
||||
}
|
||||
|
||||
return parts.map((part) => ({
|
||||
return parts.map((part) => {
|
||||
if (part.typeOfDamage === TypeOfDamage.Repair) {
|
||||
const { daghi: _daghi, ...repairPart } = part;
|
||||
return repairPart;
|
||||
}
|
||||
return {
|
||||
...part,
|
||||
daghi: {
|
||||
option: part.daghi.option,
|
||||
...(part.daghi.price && { price: part.daghi.price }),
|
||||
...(part.daghi.branchId && Types.ObjectId.isValid(part.daghi.branchId) && {
|
||||
branchId: new Types.ObjectId(part.daghi.branchId),
|
||||
option: part.daghi!.option,
|
||||
...(part.daghi!.price && { price: part.daghi!.price }),
|
||||
...(part.daghi!.branchId &&
|
||||
Types.ObjectId.isValid(part.daghi!.branchId) && {
|
||||
branchId: new Types.ObjectId(part.daghi!.branchId),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
private findClosestCar(input: string, cars: { carName: string }[]) {
|
||||
@@ -1711,6 +1720,7 @@ export class ExpertClaimService {
|
||||
// Validate daghi fields
|
||||
if (reply.parts && reply.parts.length > 0) {
|
||||
for (const part of reply.parts) {
|
||||
if (part.typeOfDamage === TypeOfDamage.Repair) continue;
|
||||
if (!part.daghi || !part.daghi.option) {
|
||||
throw new BadRequestException(
|
||||
`Daghi option is required for part ${part.partId}`,
|
||||
@@ -1758,16 +1768,22 @@ export class ExpertClaimService {
|
||||
: ClaimStepsEnum.WaitingForUserToReact;
|
||||
|
||||
// Process parts: convert branchId string to ObjectId if present
|
||||
const processedParts = reply.parts.map((part) => ({
|
||||
const processedParts = reply.parts.map((part) => {
|
||||
if (part.typeOfDamage === TypeOfDamage.Repair) {
|
||||
const { daghi: _daghi, ...repairPart } = part;
|
||||
return repairPart;
|
||||
}
|
||||
return {
|
||||
...part,
|
||||
daghi: {
|
||||
option: part.daghi.option,
|
||||
...(part.daghi.price && { price: part.daghi.price }),
|
||||
...(part.daghi.branchId && {
|
||||
branchId: new Types.ObjectId(part.daghi.branchId),
|
||||
option: part.daghi!.option,
|
||||
...(part.daghi!.price && { price: part.daghi!.price }),
|
||||
...(part.daghi!.branchId && {
|
||||
branchId: new Types.ObjectId(part.daghi!.branchId),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
};
|
||||
});
|
||||
|
||||
const expertProfileSnapshot = await this.snapshotDamageExpert(userId.sub);
|
||||
|
||||
|
||||
@@ -33,6 +33,20 @@ describe("getExpertReplyPricingValidationError", () => {
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("accepts a repair line without daghi", () => {
|
||||
expect(
|
||||
getExpertReplyPricingValidationError([
|
||||
{
|
||||
partId: 201,
|
||||
typeOfDamage: TypeOfDamage.Repair,
|
||||
price: "10000",
|
||||
salary: "0",
|
||||
totalPayment: "10000",
|
||||
},
|
||||
]),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it("rejects a repair line without a price", () => {
|
||||
expect(
|
||||
getExpertReplyPricingValidationError([
|
||||
|
||||
@@ -42,9 +42,11 @@ export function getExpertReplyPricingValidationError(
|
||||
return `${label} requires typeOfDamage to be either '${TypeOfDamage.Repair}' or '${TypeOfDamage.Change}'.`;
|
||||
}
|
||||
|
||||
const daghi = part.daghi;
|
||||
if (
|
||||
!part.daghi ||
|
||||
!Object.values(DaghiOption).includes(part.daghi.option as DaghiOption)
|
||||
part.typeOfDamage === TypeOfDamage.Change &&
|
||||
(!daghi ||
|
||||
!Object.values(DaghiOption).includes(daghi.option as DaghiOption))
|
||||
) {
|
||||
return `${label} requires a valid daghi option.`;
|
||||
}
|
||||
@@ -52,7 +54,7 @@ export function getExpertReplyPricingValidationError(
|
||||
const price = parseMoneyAmountToman(part.price);
|
||||
const salary = parseMoneyAmountToman(part.salary);
|
||||
const totalPayment = parseMoneyAmountToman(part.totalPayment);
|
||||
const daghiPrice = parseMoneyAmountToman(part.daghi.price);
|
||||
const daghiPrice = parseMoneyAmountToman(daghi?.price);
|
||||
const hasPrice =
|
||||
part.price != null &&
|
||||
(typeof part.price !== "string" || part.price.trim() !== "");
|
||||
@@ -80,7 +82,7 @@ export function getExpertReplyPricingValidationError(
|
||||
}
|
||||
|
||||
if (
|
||||
part.daghi.option === DaghiOption.RECYCLED_PARTS_VALUE &&
|
||||
daghi?.option === DaghiOption.RECYCLED_PARTS_VALUE &&
|
||||
(daghiPrice === null ||
|
||||
daghiPrice < REPAIR_LINE_AMOUNT_TOMAN.MIN ||
|
||||
daghiPrice > REPAIR_LINE_AMOUNT_TOMAN.MAX)
|
||||
|
||||
Reference in New Issue
Block a user