diff --git a/src/request-management/request-management.service.ts b/src/request-management/request-management.service.ts index 64821e8..e17b350 100644 --- a/src/request-management/request-management.service.ts +++ b/src/request-management/request-management.service.ts @@ -110,6 +110,7 @@ import { collectUserIdVariants, } from "src/helpers/party-access-queries"; import { resolveLinkedUserIdStrings } from "src/helpers/user-access-resolver"; +import { normalizePlateText } from "src/utils/plate-normalizer/plate-normalizer.service"; /** * Formats a compact Jalali date (number or string like 13780624) as YYYY/MM/DD. @@ -134,6 +135,34 @@ export class RequestManagementService { throw new BadRequestException(`Step ${stepKey} is not a party-scoped step`); } + /** + * Reverse map: Fanavaran/Tejarat numeric letter code → Persian plate letter. + * Tejarat inquiry stores Plk2 as a numeric code (e.g. 12 → "م", 5 → "د"). + * ESG VIN inquiry via parsePlkString already returns the actual letter string, + * but the mock and some Tejarat responses use the numeric code form. + */ + private static readonly PLATE_LETTER_CODE_TO_LETTER: Record = { + 1: "الف", 2: "ب", 3: "پ", 4: "ج", 5: "د", + 6: "س", 7: "ص", 8: "ط", 9: "ع", 10: "ق", + 11: "ل", 12: "م", 13: "ن", 14: "و", 15: "ه", + 16: "ی", 17: "ک", 18: "ژ", 19: "ت", 20: "ث", + 21: "ز", 22: "ش", 23: "ف", 24: "گ", + }; + + /** + * Resolve a plate center letter from whatever shape Plk2 arrives in: + * - already a Persian string → returned as-is (after normalization) + * - a numeric code (number or numeric string) → looked up in the reverse map + */ + private resolvePlk2Letter(plk2: any): string { + if (plk2 == null) return ""; + const code = Number(plk2); + if (Number.isFinite(code) && code > 0) { + return RequestManagementService.PLATE_LETTER_CODE_TO_LETTER[code] ?? ""; + } + return normalizePlateText(String(plk2).trim()); + } + /** Convert plate (string or { ir, leftDigits, centerAlphabet, centerDigits }) to string for vehicle.plateId */ private plateToPlateIdString(plate: any): string { if (plate == null) return ""; @@ -1842,12 +1871,16 @@ export class RequestManagementService { if (!party.vehicle) party.vehicle = {} as any; party.vehicle.isNew = body.isNewCar; - // Derive plateId from the plate parts returned by the VIN inquiry (plk → Plk1/Plk2/Plk3/PlkSrl). + // Derive plateId from the plate parts returned by the VIN inquiry. + // Plk2 may be a numeric letter code (e.g. 5 → "د") or already a Persian + // letter string — resolvePlk2Letter handles both forms. // Falls back to the submitted VIN so plateId is never empty. party.vehicle.plateId = this.plateToPlateIdString({ ir: inquiryMapped?.PlkSrl, leftDigits: inquiryMapped?.Plk1, - centerAlphabet: inquiryMapped?.Plk2 ?? inquiryMapped?.plateLetterid, + centerAlphabet: this.resolvePlk2Letter( + inquiryMapped?.Plk2 ?? inquiryMapped?.plateLetterid, + ), centerDigits: inquiryMapped?.Plk3, }) || body.vin; party.vehicle.name = inquiryMapped?.MapTypNam; @@ -9514,12 +9547,16 @@ export class RequestManagementService { (party.person as any).licenseType = (partyData as any).licenseType; if (!party.vehicle) party.vehicle = {} as any; - // Derive plateId from the plate parts returned by the VIN inquiry (plk → Plk1/Plk2/Plk3/PlkSrl). + // Derive plateId from the plate parts returned by the VIN inquiry. + // Plk2 may be a numeric letter code (e.g. 5 → "د") or already a Persian + // letter string — resolvePlk2Letter handles both forms. // Falls back to the submitted VIN so plateId is never empty. party.vehicle.plateId = this.plateToPlateIdString({ ir: inquiryMapped?.PlkSrl, leftDigits: inquiryMapped?.Plk1, - centerAlphabet: inquiryMapped?.Plk2 ?? inquiryMapped?.plateLetterid, + centerAlphabet: this.resolvePlk2Letter( + inquiryMapped?.Plk2 ?? inquiryMapped?.plateLetterid, + ), centerDigits: inquiryMapped?.Plk3, }) || partyData.vin; party.vehicle.name = inquiryMapped?.MapTypNam;