forked from Yara724/api
Merge pull request 'YARA-1177' (#235) from s.yahyaee/yara724-api:main into main
Reviewed-on: Yara724/api#235
This commit is contained in:
@@ -38,6 +38,7 @@ import { ClaimCaseDbService } from "./entites/db-service/claim-case.db.service";
|
|||||||
import { BlameRequestDbService } from "src/request-management/entities/db-service/blame-request.db.service";
|
import { BlameRequestDbService } from "src/request-management/entities/db-service/blame-request.db.service";
|
||||||
import { CreateClaimFromBlameResponseDto } from "./dto/create-claim-v2.dto";
|
import { CreateClaimFromBlameResponseDto } from "./dto/create-claim-v2.dto";
|
||||||
import {
|
import {
|
||||||
|
OuterPartCatalogItemDto,
|
||||||
SelectOuterPartsV2Dto,
|
SelectOuterPartsV2Dto,
|
||||||
SelectOuterPartsV2ResponseDto,
|
SelectOuterPartsV2ResponseDto,
|
||||||
} from "./dto/select-outer-parts-v2.dto";
|
} from "./dto/select-outer-parts-v2.dto";
|
||||||
@@ -140,7 +141,7 @@ import {
|
|||||||
} from "src/helpers/claim-car-angle-media";
|
} from "src/helpers/claim-car-angle-media";
|
||||||
import {
|
import {
|
||||||
ClaimVehicleTypeV2,
|
ClaimVehicleTypeV2,
|
||||||
OUTER_PARTS_BY_CAR_TYPE,
|
FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
OuterPartCatalogItem,
|
OuterPartCatalogItem,
|
||||||
} from "src/static/outer-car-parts-catalog";
|
} from "src/static/outer-car-parts-catalog";
|
||||||
import {
|
import {
|
||||||
@@ -563,67 +564,53 @@ export class ClaimRequestManagementService {
|
|||||||
/**
|
/**
|
||||||
* Outer-parts catalog returned to clients (user app + expert panel).
|
* Outer-parts catalog returned to clients (user app + expert panel).
|
||||||
*
|
*
|
||||||
* The shape intentionally mirrors how items are persisted under
|
* Fetches the live `car/base-info/car-components` lookup from Fanavaran so
|
||||||
* `damage.selectedParts` so the front-end can match catalog rows to the
|
* the list always matches what Fanavaran accepts in DmgSections[].DmgSectionId.
|
||||||
* stored selection by `id` / `catalogKey` without renaming fields:
|
* The lookup service handles caching to disk; `carType` is ignored because
|
||||||
*
|
* Fanavaran uses a single flat catalog across all vehicle types.
|
||||||
* { id, name, side, label_fa, catalogKey, carType }
|
|
||||||
*
|
|
||||||
* - `name` is side-agnostic (`backWheel`, not `left_backWheel`).
|
|
||||||
* - `label_fa` is disambiguated with the side in parentheses when multiple
|
|
||||||
* catalog rows share the same Farsi title (e.g. `چرخ عقب (چپ)`).
|
|
||||||
* - `catalogKey` keeps the original full key (`left_backWheel`) for clients
|
|
||||||
* that already address parts by it.
|
|
||||||
*/
|
*/
|
||||||
getOuterPartsCatalogV2(
|
async getOuterPartsCatalogV2(): Promise<OuterPartCatalogItemDto[]> {
|
||||||
carType?: ClaimVehicleTypeV2,
|
const clientKey = resolveFanavaranClientKey();
|
||||||
): (DamageSelectedPartV2 & { carType: ClaimVehicleTypeV2 })[] {
|
const rows = await this.getFanavaranLookupRows(clientKey, "car-components");
|
||||||
const buildForType = (
|
return rows
|
||||||
type: ClaimVehicleTypeV2,
|
.filter(
|
||||||
items: OuterPartCatalogItem[],
|
(r): r is { Id: number; Caption: string } =>
|
||||||
): (DamageSelectedPartV2 & { carType: ClaimVehicleTypeV2 })[] =>
|
!!r &&
|
||||||
items.map((p) => ({
|
typeof r === "object" &&
|
||||||
...catalogItemToSelectedPart(p, items),
|
typeof (r as any).Id === "number" &&
|
||||||
carType: type,
|
typeof (r as any).Caption === "string",
|
||||||
}));
|
)
|
||||||
|
.map((r) => ({ id: r.Id, label_fa: r.Caption }));
|
||||||
if (carType) {
|
|
||||||
const items = OUTER_PARTS_BY_CAR_TYPE[carType] || [];
|
|
||||||
return buildForType(carType, items);
|
|
||||||
}
|
|
||||||
|
|
||||||
const out: (DamageSelectedPartV2 & { carType: ClaimVehicleTypeV2 })[] = [];
|
|
||||||
for (const [type, items] of Object.entries(OUTER_PARTS_BY_CAR_TYPE)) {
|
|
||||||
out.push(...buildForType(type as ClaimVehicleTypeV2, items));
|
|
||||||
}
|
|
||||||
return out.sort((a, b) => {
|
|
||||||
if (a.carType === b.carType) return (a.id ?? 0) - (b.id ?? 0);
|
|
||||||
return String(a.carType).localeCompare(String(b.carType));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal raw catalog (kept in the original `OuterPartCatalogItem` shape so
|
* Resolve the live Fanavaran car-components catalog as `OuterPartCatalogItem`
|
||||||
* existing internal code that indexes by `key`/`titleFa` keeps working).
|
* rows for internal use (e.g. validating selectedPartIds).
|
||||||
* Public API consumers should use `getOuterPartsCatalogV2` instead.
|
* Falls back to the static snapshot when the remote lookup is unavailable.
|
||||||
*/
|
*/
|
||||||
private getOuterPartsRawCatalog(
|
private async getLiveFanavaranCatalogItems(): Promise<OuterPartCatalogItem[]> {
|
||||||
carType?: ClaimVehicleTypeV2,
|
const clientKey = resolveFanavaranClientKey();
|
||||||
): OuterPartCatalogItem[] {
|
const rows = await this.getFanavaranLookupRows(clientKey, "car-components");
|
||||||
if (carType) {
|
if (!rows.length) {
|
||||||
return (OUTER_PARTS_BY_CAR_TYPE[carType] || []).map((p) => ({
|
this.logger.warn(
|
||||||
...p,
|
"getLiveFanavaranCatalogItems: remote lookup returned empty, falling back to snapshot",
|
||||||
carType,
|
);
|
||||||
|
return FANAVARAN_CAR_PARTS_CATALOG;
|
||||||
|
}
|
||||||
|
return rows
|
||||||
|
.filter(
|
||||||
|
(r): r is { Id: number; Caption: string } =>
|
||||||
|
!!r &&
|
||||||
|
typeof r === "object" &&
|
||||||
|
typeof (r as any).Id === "number" &&
|
||||||
|
typeof (r as any).Caption === "string",
|
||||||
|
)
|
||||||
|
.map((r): OuterPartCatalogItem => ({
|
||||||
|
id: r.Id,
|
||||||
|
key: String(r.Id),
|
||||||
|
titleFa: r.Caption,
|
||||||
|
side: "",
|
||||||
}));
|
}));
|
||||||
}
|
|
||||||
const out: OuterPartCatalogItem[] = [];
|
|
||||||
for (const [type, items] of Object.entries(OUTER_PARTS_BY_CAR_TYPE)) {
|
|
||||||
const t = type as ClaimVehicleTypeV2;
|
|
||||||
for (const p of items) {
|
|
||||||
out.push({ ...p, carType: t });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private userDamageDetail(blRequest: RequestManagementModel) {
|
private userDamageDetail(blRequest: RequestManagementModel) {
|
||||||
@@ -7628,22 +7615,14 @@ export class ClaimRequestManagementService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. Validate by selected car type and resolve selected parts by ids/keys
|
// 5. Fetch the live Fanavaran catalog and resolve selected parts by ids
|
||||||
const selectedCarType = (body as any)?.carType as
|
const selectedCarType = (body as any)?.carType as
|
||||||
| ClaimVehicleTypeV2
|
| ClaimVehicleTypeV2
|
||||||
| undefined;
|
| undefined;
|
||||||
if (!selectedCarType || !OUTER_PARTS_BY_CAR_TYPE[selectedCarType]) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
"Vehicle type is required before selecting outer parts.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const catalog = OUTER_PARTS_BY_CAR_TYPE[selectedCarType];
|
const liveCatalog = await this.getLiveFanavaranCatalogItems();
|
||||||
const byId = new Map<number, OuterPartCatalogItem>(
|
const byId = new Map<number, OuterPartCatalogItem>(
|
||||||
catalog.map((p) => [p.id, p]),
|
liveCatalog.map((p) => [p.id, p]),
|
||||||
);
|
|
||||||
const byKey = new Map<string, OuterPartCatalogItem>(
|
|
||||||
catalog.map((p) => [p.key, p]),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const selectedFromIds: OuterPartCatalogItem[] = [];
|
const selectedFromIds: OuterPartCatalogItem[] = [];
|
||||||
@@ -7655,43 +7634,20 @@ export class ClaimRequestManagementService {
|
|||||||
const item = byId.get(id);
|
const item = byId.get(id);
|
||||||
if (!item) {
|
if (!item) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
`Invalid outer part id for ${selectedCarType}: ${id}`,
|
`Invalid outer part id: ${id}. Use GET outer-parts-catalog to see valid IDs.`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
selectedFromIds.push(item);
|
selectedFromIds.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backward compatibility with selectedParts + legacy carPartDamage
|
if (selectedFromIds.length === 0) {
|
||||||
let selectedParts = Array.isArray((body as any)?.selectedParts)
|
throw new BadRequestException(
|
||||||
? ((body as any).selectedParts as string[])
|
"selectedPartIds is required and must contain at least one valid Fanavaran part ID",
|
||||||
: [];
|
|
||||||
if (selectedParts.length === 0 && (body as any)?.carPartDamage) {
|
|
||||||
this.assertCarPartDamageAtMostTwoOfFourSides(
|
|
||||||
(body as any).carPartDamage as CarDamagePartDto,
|
|
||||||
);
|
);
|
||||||
selectedParts = this.carDamagePartDtoToOuterPartSlugs(
|
|
||||||
(body as any).carPartDamage as CarDamagePartDto,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const selectedFromKeys: OuterPartCatalogItem[] = [];
|
|
||||||
for (const key of selectedParts) {
|
|
||||||
const item = byKey.get(key);
|
|
||||||
if (!item) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
`Invalid outer part key for ${selectedCarType}: ${key}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
selectedFromKeys.push(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const selectedItems =
|
const selectedItems = selectedFromIds;
|
||||||
selectedFromIds.length > 0 ? selectedFromIds : selectedFromKeys;
|
|
||||||
if (selectedItems.length === 0) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
"selectedPartIds or selectedParts is required and must contain at least one item",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DISABLED: At most two non-top sides allowed
|
// DISABLED: At most two non-top sides allowed
|
||||||
// const sideSet = new Set(
|
// const sideSet = new Set(
|
||||||
@@ -7706,7 +7662,7 @@ export class ClaimRequestManagementService {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
const selectedPartDocs = selectedItems.map((p) =>
|
const selectedPartDocs = selectedItems.map((p) =>
|
||||||
catalogItemToSelectedPart(p, catalog),
|
catalogItemToSelectedPart(p, liveCatalog),
|
||||||
);
|
);
|
||||||
const damagedPartsInitial = selectedPartDocs.map((p) => ({
|
const damagedPartsInitial = selectedPartDocs.map((p) => ({
|
||||||
id: p.id ?? undefined,
|
id: p.id ?? undefined,
|
||||||
@@ -8061,18 +8017,12 @@ export class ClaimRequestManagementService {
|
|||||||
"Only the claim owner can view capture requirements",
|
"Only the claim owner can view capture requirements",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Build car-type aware outer-parts lookup (complete source: static catalog).
|
// Build outer-parts lookup for resolving stored DB parts.
|
||||||
// Uses the raw catalog shape (`{id, key, titleFa, side, ...}`) because the
|
// Uses the static snapshot (FANAVARAN_CAR_PARTS_CATALOG) which is keyed
|
||||||
// map below is keyed on the full `key` (e.g. `left_backfender`).
|
// by numeric id (key === String(id)). This is only needed for legacy
|
||||||
const selectedCarType = claimCase.vehicle?.carType as
|
// migration of parts stored before the Fanavaran catalog change.
|
||||||
| ClaimVehicleTypeV2
|
|
||||||
| undefined;
|
|
||||||
const catalogForType =
|
|
||||||
selectedCarType && OUTER_PARTS_BY_CAR_TYPE[selectedCarType]
|
|
||||||
? OUTER_PARTS_BY_CAR_TYPE[selectedCarType]
|
|
||||||
: this.getOuterPartsRawCatalog();
|
|
||||||
const catalogByKey = new Map<string, OuterPartCatalogItem>();
|
const catalogByKey = new Map<string, OuterPartCatalogItem>();
|
||||||
for (const item of catalogForType) {
|
for (const item of FANAVARAN_CAR_PARTS_CATALOG) {
|
||||||
if (!catalogByKey.has(item.key)) catalogByKey.set(item.key, item);
|
if (!catalogByKey.has(item.key)) catalogByKey.set(item.key, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ import { ListQueryV2Dto } from "src/common/dto/list-query-v2.dto";
|
|||||||
import { ClaimDetailsV2ResponseDto } from "./dto/claim-details-v2.dto";
|
import { ClaimDetailsV2ResponseDto } from "./dto/claim-details-v2.dto";
|
||||||
import { UserObjectionV2Dto } from "./dto/user-objection-v2.dto";
|
import { UserObjectionV2Dto } from "./dto/user-objection-v2.dto";
|
||||||
import { UserRatingDto } from "./dto/user-rating.dto";
|
import { UserRatingDto } from "./dto/user-rating.dto";
|
||||||
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
|
||||||
|
|
||||||
@ApiTags("claim-request-management (v2)")
|
@ApiTags("claim-request-management (v2)")
|
||||||
@Controller("v2/claim-request-management")
|
@Controller("v2/claim-request-management")
|
||||||
@@ -452,17 +451,15 @@ export class ClaimRequestManagementV2Controller {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Get outer parts catalog (V2)",
|
summary: "Get outer parts catalog (V2)",
|
||||||
description:
|
description:
|
||||||
"Returns outer-damage parts with id/key/side. Optional `carType` filter returns only that type catalog.",
|
"Returns the Fanavaran car-components list. All vehicle types share the same catalog.",
|
||||||
})
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: "Outer parts catalog",
|
description: "Outer parts catalog",
|
||||||
type: [OuterPartCatalogItemDto],
|
type: [OuterPartCatalogItemDto],
|
||||||
})
|
})
|
||||||
async getOuterPartsCatalog(
|
async getOuterPartsCatalog(): Promise<OuterPartCatalogItemDto[]> {
|
||||||
@Query("carType") carType?: ClaimVehicleTypeV2,
|
return await this.claimRequestManagementService.getOuterPartsCatalogV2();
|
||||||
): Promise<OuterPartCatalogItemDto[]> {
|
|
||||||
return this.claimRequestManagementService.getOuterPartsCatalogV2(carType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("branches/:insuranceId")
|
@Get("branches/:insuranceId")
|
||||||
|
|||||||
@@ -8,69 +8,20 @@ import {
|
|||||||
IsOptional,
|
IsOptional,
|
||||||
IsInt,
|
IsInt,
|
||||||
} from "class-validator";
|
} from "class-validator";
|
||||||
import {
|
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
||||||
ClaimVehicleTypeV2,
|
|
||||||
OuterPartSideV2,
|
|
||||||
} from "src/static/outer-car-parts-catalog";
|
|
||||||
import { DamageSelectedPartV2BodyDto } from "./damage-selected-part-v2.dto";
|
import { DamageSelectedPartV2BodyDto } from "./damage-selected-part-v2.dto";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enum for valid outer car parts that can be damaged
|
* V2 DTO for selecting damaged outer car parts.
|
||||||
* Follows the naming convention from workflow step definition
|
* Submit `selectedPartIds` with IDs from the `GET outer-parts-catalog` response.
|
||||||
*/
|
|
||||||
export enum OuterCarPart {
|
|
||||||
// Hood
|
|
||||||
HOOD = "hood",
|
|
||||||
|
|
||||||
// Doors
|
|
||||||
FRONT_RIGHT_DOOR = "front_right_door",
|
|
||||||
FRONT_LEFT_DOOR = "front_left_door",
|
|
||||||
REAR_RIGHT_DOOR = "rear_right_door",
|
|
||||||
REAR_LEFT_DOOR = "rear_left_door",
|
|
||||||
|
|
||||||
// Bumpers
|
|
||||||
FRONT_BUMPER = "front_bumper",
|
|
||||||
REAR_BUMPER = "rear_bumper",
|
|
||||||
|
|
||||||
// Fenders
|
|
||||||
FRONT_RIGHT_FENDER = "front_right_fender",
|
|
||||||
FRONT_LEFT_FENDER = "front_left_fender",
|
|
||||||
REAR_RIGHT_FENDER = "rear_right_fender",
|
|
||||||
REAR_LEFT_FENDER = "rear_left_fender",
|
|
||||||
|
|
||||||
// Trunk & Roof
|
|
||||||
TRUNK = "trunk",
|
|
||||||
ROOF = "roof",
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* V2 DTO for selecting damaged outer car parts
|
|
||||||
* Much cleaner than the nested boolean structure
|
|
||||||
*/
|
*/
|
||||||
export class SelectOuterPartsV2Dto {
|
export class SelectOuterPartsV2Dto {
|
||||||
@ApiProperty({
|
@ApiPropertyOptional({
|
||||||
description: "Array of selected damaged outer car parts",
|
description:
|
||||||
example: ["hood", "front_right_door", "rear_bumper", "roof"],
|
"Selected outer part IDs from the Fanavaran car-components catalog. " +
|
||||||
enum: OuterCarPart,
|
"IDs must match values returned by GET outer-parts-catalog.",
|
||||||
isArray: true,
|
example: [9, 10, 30],
|
||||||
minItems: 1,
|
|
||||||
maxItems: 13,
|
|
||||||
})
|
|
||||||
@IsOptional()
|
|
||||||
@IsArray({ message: "selectedParts must be an array" })
|
|
||||||
@ArrayMinSize(1, { message: "At least one damaged part must be selected" })
|
|
||||||
@ArrayUnique({ message: "Duplicate parts are not allowed" })
|
|
||||||
@IsEnum(OuterCarPart, {
|
|
||||||
each: true,
|
|
||||||
message: "Invalid part name. Must be one of the valid outer car parts",
|
|
||||||
})
|
|
||||||
selectedParts?: OuterCarPart[];
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: "Selected outer part IDs from catalog",
|
|
||||||
example: [9, 10, 4],
|
|
||||||
type: [Number],
|
type: [Number],
|
||||||
required: false,
|
|
||||||
})
|
})
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsArray({ message: "selectedPartIds must be an array" })
|
@IsArray({ message: "selectedPartIds must be an array" })
|
||||||
@@ -79,12 +30,13 @@ export class SelectOuterPartsV2Dto {
|
|||||||
@IsInt({ each: true, message: "Each selected part ID must be an integer" })
|
@IsInt({ each: true, message: "Each selected part ID must be an integer" })
|
||||||
selectedPartIds?: number[];
|
selectedPartIds?: number[];
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiPropertyOptional({
|
||||||
description: "Vehicle type for validating available outer parts",
|
description:
|
||||||
|
"Vehicle type (sedan, suv, hatchback, pickup, van). Optional — stored for context only; " +
|
||||||
|
"all vehicle types share the same Fanavaran parts catalog.",
|
||||||
enum: ClaimVehicleTypeV2,
|
enum: ClaimVehicleTypeV2,
|
||||||
required: true,
|
|
||||||
})
|
})
|
||||||
@IsNotEmpty()
|
@IsOptional()
|
||||||
@IsEnum(ClaimVehicleTypeV2)
|
@IsEnum(ClaimVehicleTypeV2)
|
||||||
carType?: ClaimVehicleTypeV2;
|
carType?: ClaimVehicleTypeV2;
|
||||||
}
|
}
|
||||||
@@ -156,53 +108,21 @@ export class SetClaimVehicleTypeV2Dto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shape returned by `GET .../outer-parts-catalog` (both user and expert
|
* Shape returned by `GET .../outer-parts-catalog`.
|
||||||
* controllers). It mirrors how items are persisted under
|
* Sourced live from the Fanavaran `car/base-info/car-components` lookup so that
|
||||||
* `damage.selectedParts` (see `DamageSelectedPartV2BodyDto`) so the front-end
|
* the list always matches what Fanavaran accepts in `DmgSections[].DmgSectionId`.
|
||||||
* can match catalog rows to stored selections without any field renaming:
|
|
||||||
* `name` is side-agnostic, `label_fa` is disambiguated with the side in
|
|
||||||
* parentheses, and the original full catalog key (`left_backfender`) is
|
|
||||||
* exposed as `catalogKey`.
|
|
||||||
*/
|
*/
|
||||||
export class OuterPartCatalogItemDto {
|
export class OuterPartCatalogItemDto {
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: "Static catalog id (unique across all car types)",
|
description:
|
||||||
example: 102,
|
"Fanavaran DmgSectionId — use this value when submitting selectedPartIds",
|
||||||
|
example: 30,
|
||||||
})
|
})
|
||||||
id: number;
|
id: number;
|
||||||
|
|
||||||
@ApiProperty({
|
@ApiProperty({
|
||||||
description: "Side-agnostic part name (matches stored part `name`)",
|
description: "Display label in Farsi (Caption from Fanavaran)",
|
||||||
example: "backWheel",
|
example: "درب جلو سمت راننده",
|
||||||
})
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: "Vehicle side / region",
|
|
||||||
enum: OuterPartSideV2,
|
|
||||||
example: "left",
|
|
||||||
})
|
|
||||||
side: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description:
|
|
||||||
"Display label in Farsi, with side disambiguator in parentheses when needed",
|
|
||||||
example: "چرخ عقب (چپ)",
|
|
||||||
})
|
})
|
||||||
label_fa: string;
|
label_fa: string;
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: "Original full catalog key (matches stored `catalogKey`)",
|
|
||||||
example: "left_backWheel",
|
|
||||||
required: false,
|
|
||||||
})
|
|
||||||
catalogKey?: string;
|
|
||||||
|
|
||||||
@ApiProperty({
|
|
||||||
description: "Vehicle type this catalog row belongs to",
|
|
||||||
enum: ClaimVehicleTypeV2,
|
|
||||||
required: false,
|
|
||||||
example: "suv",
|
|
||||||
})
|
|
||||||
carType?: ClaimVehicleTypeV2;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import {
|
|||||||
Patch,
|
Patch,
|
||||||
Post,
|
Post,
|
||||||
Put,
|
Put,
|
||||||
Query,
|
|
||||||
UploadedFile,
|
UploadedFile,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
@@ -33,7 +32,6 @@ import { CurrentUser } from "src/decorators/user.decorator";
|
|||||||
import { MediaPolicyService } from "src/media-policy/media-policy.service";
|
import { MediaPolicyService } from "src/media-policy/media-policy.service";
|
||||||
import { DEFAULT_MEDIA_MAX_BYTES } from "src/client/client.service";
|
import { DEFAULT_MEDIA_MAX_BYTES } from "src/client/client.service";
|
||||||
import { RoleEnum } from "src/Types&Enums/role.enum";
|
import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||||
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
|
||||||
import { ClaimRequestManagementService } from "./claim-request-management.service";
|
import { ClaimRequestManagementService } from "./claim-request-management.service";
|
||||||
import {
|
import {
|
||||||
OuterPartCatalogItemDto,
|
OuterPartCatalogItemDto,
|
||||||
@@ -101,15 +99,15 @@ export class ExpertInitiatedClaimMirrorController {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Get outer parts catalog (V2)",
|
summary: "Get outer parts catalog (V2)",
|
||||||
description:
|
description:
|
||||||
"Returns outer-damage parts with id/key/side. Optional `carType` filter returns only that type catalog.",
|
"Returns the Fanavaran car-components list. All vehicle types share the same catalog.",
|
||||||
})
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: "Outer parts catalog",
|
description: "Outer parts catalog",
|
||||||
type: [OuterPartCatalogItemDto],
|
type: [OuterPartCatalogItemDto],
|
||||||
})
|
})
|
||||||
async getOuterPartsCatalog(@Query("carType") carType?: ClaimVehicleTypeV2) {
|
async getOuterPartsCatalog() {
|
||||||
return this.claimRequestManagementService.getOuterPartsCatalogV2(carType);
|
return await this.claimRequestManagementService.getOuterPartsCatalogV2();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("car-other-part")
|
@Get("car-other-part")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import {
|
|||||||
Param,
|
Param,
|
||||||
Patch,
|
Patch,
|
||||||
Post,
|
Post,
|
||||||
Query,
|
|
||||||
UploadedFile,
|
UploadedFile,
|
||||||
UseGuards,
|
UseGuards,
|
||||||
UseInterceptors,
|
UseInterceptors,
|
||||||
@@ -30,7 +29,6 @@ import { CurrentUser } from "src/decorators/user.decorator";
|
|||||||
import { MediaPolicyService } from "src/media-policy/media-policy.service";
|
import { MediaPolicyService } from "src/media-policy/media-policy.service";
|
||||||
import { DEFAULT_MEDIA_MAX_BYTES } from "src/client/client.service";
|
import { DEFAULT_MEDIA_MAX_BYTES } from "src/client/client.service";
|
||||||
import { RoleEnum } from "src/Types&Enums/role.enum";
|
import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||||
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
|
||||||
import { ClaimRequestManagementService } from "./claim-request-management.service";
|
import { ClaimRequestManagementService } from "./claim-request-management.service";
|
||||||
import {
|
import {
|
||||||
OuterPartCatalogItemDto,
|
OuterPartCatalogItemDto,
|
||||||
@@ -96,15 +94,15 @@ export class RegistrarClaimMirrorController {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Get outer parts catalog (V2)",
|
summary: "Get outer parts catalog (V2)",
|
||||||
description:
|
description:
|
||||||
"Returns outer-damage parts with id/key/side. Optional `carType` filter returns only that type catalog.",
|
"Returns the Fanavaran car-components list. All vehicle types share the same catalog.",
|
||||||
})
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: "Outer parts catalog",
|
description: "Outer parts catalog",
|
||||||
type: [OuterPartCatalogItemDto],
|
type: [OuterPartCatalogItemDto],
|
||||||
})
|
})
|
||||||
async getOuterPartsCatalog(@Query("carType") carType?: ClaimVehicleTypeV2) {
|
async getOuterPartsCatalog() {
|
||||||
return this.claimRequestManagementService.getOuterPartsCatalogV2(carType);
|
return await this.claimRequestManagementService.getOuterPartsCatalogV2();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("car-other-part")
|
@Get("car-other-part")
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ import {
|
|||||||
import { FactorValidationV2Dto } from "./dto/factor-validation.dto";
|
import { FactorValidationV2Dto } from "./dto/factor-validation.dto";
|
||||||
import { ClaimRequestManagementService } from "src/claim-request-management/claim-request-management.service";
|
import { ClaimRequestManagementService } from "src/claim-request-management/claim-request-management.service";
|
||||||
import { OuterPartCatalogItemDto } from "src/claim-request-management/dto/select-outer-parts-v2.dto";
|
import { OuterPartCatalogItemDto } from "src/claim-request-management/dto/select-outer-parts-v2.dto";
|
||||||
import { ClaimVehicleTypeV2 } from "src/static/outer-car-parts-catalog";
|
|
||||||
|
|
||||||
class InPersonVisitV2Dto {
|
class InPersonVisitV2Dto {
|
||||||
@ApiPropertyOptional({ example: "Paint damage requires physical inspection" })
|
@ApiPropertyOptional({ example: "Paint damage requires physical inspection" })
|
||||||
@@ -105,17 +104,15 @@ export class ExpertClaimV2Controller {
|
|||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: "Get outer parts catalog (V2)",
|
summary: "Get outer parts catalog (V2)",
|
||||||
description:
|
description:
|
||||||
"Returns outer-damage parts with id/key/side. Optional `carType` filter returns only that type catalog.",
|
"Returns the Fanavaran car-components list. All vehicle types share the same catalog.",
|
||||||
})
|
})
|
||||||
@ApiResponse({
|
@ApiResponse({
|
||||||
status: 200,
|
status: 200,
|
||||||
description: "Outer parts catalog",
|
description: "Outer parts catalog",
|
||||||
type: [OuterPartCatalogItemDto],
|
type: [OuterPartCatalogItemDto],
|
||||||
})
|
})
|
||||||
async getOuterPartsCatalog(
|
async getOuterPartsCatalog(): Promise<OuterPartCatalogItemDto[]> {
|
||||||
@Query("carType") carType?: ClaimVehicleTypeV2,
|
return await this.claimRequestManagementService.getOuterPartsCatalogV2();
|
||||||
): Promise<OuterPartCatalogItemDto[]> {
|
|
||||||
return this.claimRequestManagementService.getOuterPartsCatalogV2(carType);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get("inner-parts-catalog")
|
@Get("inner-parts-catalog")
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import {
|
import {
|
||||||
ClaimVehicleTypeV2,
|
ClaimVehicleTypeV2,
|
||||||
|
FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
OUTER_PARTS_BY_CAR_TYPE,
|
OUTER_PARTS_BY_CAR_TYPE,
|
||||||
OuterPartCatalogItem,
|
OuterPartCatalogItem,
|
||||||
OuterPartSideV2,
|
OuterPartSideV2,
|
||||||
@@ -93,12 +94,14 @@ export function sameCatalogPartId(
|
|||||||
return na != null && nb != null && na === nb;
|
return na != null && nb != null && na === nb;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** API part id: numeric catalog id only (`null` for internal / non-catalog lines). */
|
/** API part id: numeric catalog id only (`null` for free-text / non-catalog lines). */
|
||||||
export function catalogPartIdFromSelectedPart(
|
export function catalogPartIdFromSelectedPart(
|
||||||
sp: DamageSelectedPartV2,
|
sp: DamageSelectedPartV2,
|
||||||
): number | null {
|
): number | null {
|
||||||
if (isInternalDamageSide(sp.side)) return null;
|
// Parts from the Fanavaran catalog always carry a numeric id regardless of side.
|
||||||
if (sp.id != null && Number.isFinite(sp.id)) return sp.id;
|
if (sp.id != null && Number.isFinite(sp.id)) return sp.id;
|
||||||
|
// Legacy parts without an id and with an internal/unknown side are free-text only.
|
||||||
|
if (isInternalDamageSide(sp.side)) return null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,12 +156,13 @@ export function disambiguateOuterPartLabelFa(
|
|||||||
return `${t} (${sideFa})`;
|
return `${t} (${sideFa})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CATALOG_ITEM_BY_ID = new Map<number, OuterPartCatalogItem>();
|
/**
|
||||||
for (const list of Object.values(OUTER_PARTS_BY_CAR_TYPE)) {
|
* Static id → item map for legacy DB part resolution.
|
||||||
for (const it of list) {
|
* Built from the Fanavaran snapshot; unique because all car types share the same list.
|
||||||
CATALOG_ITEM_BY_ID.set(it.id, it);
|
*/
|
||||||
}
|
const CATALOG_ITEM_BY_ID = new Map<number, OuterPartCatalogItem>(
|
||||||
}
|
FANAVARAN_CAR_PARTS_CATALOG.map((it) => [it.id, it]),
|
||||||
|
);
|
||||||
|
|
||||||
function findCatalogItemByKey(key: string): OuterPartCatalogItem | undefined {
|
function findCatalogItemByKey(key: string): OuterPartCatalogItem | undefined {
|
||||||
for (const list of Object.values(OUTER_PARTS_BY_CAR_TYPE)) {
|
for (const list of Object.values(OUTER_PARTS_BY_CAR_TYPE)) {
|
||||||
@@ -681,7 +685,7 @@ export function normalizeCarPartDamageForExpertReply(
|
|||||||
? o.side.trim().toLowerCase()
|
? o.side.trim().toLowerCase()
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
if (name && sideIn) {
|
if (name) {
|
||||||
const id = toNum(o.id);
|
const id = toNum(o.id);
|
||||||
const ck =
|
const ck =
|
||||||
typeof o.catalogKey === "string" && o.catalogKey.trim()
|
typeof o.catalogKey === "string" && o.catalogKey.trim()
|
||||||
@@ -689,36 +693,28 @@ export function normalizeCarPartDamageForExpertReply(
|
|||||||
: undefined;
|
: undefined;
|
||||||
const catalog = carType ? OUTER_PARTS_BY_CAR_TYPE[carType] : undefined;
|
const catalog = carType ? OUTER_PARTS_BY_CAR_TYPE[carType] : undefined;
|
||||||
let catItem: OuterPartCatalogItem | undefined;
|
let catItem: OuterPartCatalogItem | undefined;
|
||||||
if (catalog) {
|
// Try id-based lookup first (works for Fanavaran parts which have no side)
|
||||||
|
if (id != null) {
|
||||||
|
catItem = catalog?.find((c) => c.id === id) ?? CATALOG_ITEM_BY_ID.get(id) ?? undefined;
|
||||||
|
}
|
||||||
|
if (!catItem && catalog) {
|
||||||
const byKey = new Map(catalog.map((c) => [c.key, c]));
|
const byKey = new Map(catalog.map((c) => [c.key, c]));
|
||||||
if (ck) catItem = byKey.get(ck);
|
if (ck) catItem = byKey.get(ck);
|
||||||
if (!catItem && id != null) catItem = catalog.find((c) => c.id === id);
|
if (!catItem && sideIn) {
|
||||||
if (!catItem) {
|
|
||||||
catItem = byKey.get(catalogLikeKeyFromPart({ side: sideIn, name }));
|
catItem = byKey.get(catalogLikeKeyFromPart({ side: sideIn, name }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!catItem && id != null) {
|
if (!catItem && ck) catItem = findCatalogItemByKey(ck);
|
||||||
catItem = CATALOG_ITEM_BY_ID.get(id!) ?? undefined;
|
if (catItem) {
|
||||||
}
|
|
||||||
const list = catalog?.length
|
|
||||||
? catalog
|
|
||||||
: catItem
|
|
||||||
? outerCatalogListForItem(catItem)
|
|
||||||
: [];
|
|
||||||
if (catItem && list.length) {
|
|
||||||
return selectedPartToStoredRecord(
|
return selectedPartToStoredRecord(
|
||||||
catalogItemToSelectedPart(catItem, list),
|
catalogItemToSelectedPart(catItem, outerCatalogListForItem(catItem)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const label_fa =
|
const label_fa =
|
||||||
typeof o.label_fa === "string" && o.label_fa.trim()
|
typeof o.label_fa === "string" && o.label_fa.trim()
|
||||||
? o.label_fa.trim()
|
? o.label_fa.trim()
|
||||||
: name;
|
: name;
|
||||||
const out: Record<string, unknown> = {
|
const out: Record<string, unknown> = { name, side: sideIn, label_fa };
|
||||||
name,
|
|
||||||
side: sideIn,
|
|
||||||
label_fa,
|
|
||||||
};
|
|
||||||
if (id != null) out.id = id;
|
if (id != null) out.id = id;
|
||||||
if (ck) out.catalogKey = ck;
|
if (ck) out.catalogKey = ck;
|
||||||
return out;
|
return out;
|
||||||
@@ -731,9 +727,8 @@ export function normalizeCarPartDamageForExpertReply(
|
|||||||
carType,
|
carType,
|
||||||
);
|
);
|
||||||
if (catItem) {
|
if (catItem) {
|
||||||
const list = outerCatalogListForItem(catItem);
|
|
||||||
return selectedPartToStoredRecord(
|
return selectedPartToStoredRecord(
|
||||||
catalogItemToSelectedPart(catItem, list),
|
catalogItemToSelectedPart(catItem, outerCatalogListForItem(catItem)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const sideFa = SIDE_LABEL_FA[legacySide] || legacySide;
|
const sideFa = SIDE_LABEL_FA[legacySide] || legacySide;
|
||||||
@@ -744,7 +739,7 @@ export function normalizeCarPartDamageForExpertReply(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error("carPartDamage must include side and (name or part)");
|
throw new Error("carPartDamage must include a name or part field");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Best-effort migration for API output; never throws. */
|
/** Best-effort migration for API output; never throws. */
|
||||||
|
|||||||
857
src/static/fanavaran-car-components.snapshot.json
Normal file
857
src/static/fanavaran-car-components.snapshot.json
Normal file
@@ -0,0 +1,857 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"Caption": "جلو کامل",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 1,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 2,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 3,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "عقب کامل",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 4,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 5,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 6,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "بدنه راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 7,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "بدنه چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 8,
|
||||||
|
"ToDate": "1379/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سپر جلو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 9,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سپر عقب",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 10,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "آينه سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 93,
|
||||||
|
"Id": 11,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "آينه سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 93,
|
||||||
|
"Id": 12,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "چراغ جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 13,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "چراغ جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 14,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "چراغ عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 15,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "چراغ عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 16,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لاستيک جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 17,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لاستيک جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 18,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لاستيک عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 19,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لاستيک عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 20,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لاستيک زاپاس",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 21,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رينگ جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 22,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رينگ جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 23,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رينگ عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 24,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رينگ عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 90,
|
||||||
|
"Id": 25,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "راهنماي جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 26,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "راهنماي جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 27,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "راهنماي عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 28,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "راهنماي عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 29,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب جلو سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 30,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب جلو سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 31,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب عقب سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 32,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب عقب سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 33,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "گلگير جلو سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 34,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "گلگير جلو سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 35,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "گلگير عقب سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 36,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "گلگير عقب سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 37,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون جلو چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 38,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون جلو راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 39,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون وسط چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 40,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون وسط راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 41,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون عقب چپ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 42,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ستون عقب راست",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 43,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه جلو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 44,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه عقب",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 45,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سيني جلو (زير موتور)",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 46,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب موتور جلو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 47,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درب صندوق عقب",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 48,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "جلو پنجره",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 49,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سقف خودرو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 50,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سانروف",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 51,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سيني کف صندوق",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 52,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "متعلقات جلوبندي",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 53,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "متعلقات داخل خودرو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 54,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "اگزوز و متعلقات",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 55,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "بلوکه سيلندر",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 56,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "موتور و متعلقات ( به غير از سيلندر)",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 57,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شاسي جلو",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 58,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شاسي عقب",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 59,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ايربگ",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 60,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه پنجره درب جلو سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 61,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه پنجره درب جلو سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 62,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه پنجره درب عقب سمت راننده",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 63,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه پنجره درب عقب سمت سرنشين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": 95,
|
||||||
|
"Id": 64,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "بادگير شيشه ها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 65,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "برف پاک کن",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 66,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رکاب ها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 67,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "درپوش باک بنزين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 68,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سامانه برق رساني (به جزء باتري)",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 69,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "باتري",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 70,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5450
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سيستم تهويه مطبوع (به جزء کولر)",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 71,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "کولر",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 72,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "خسارتهاي پنهان",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 73,
|
||||||
|
"ToDate": "1405/03/03",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "کلاف",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 74,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "کف اتاق",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 75,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سيني عقب",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 76,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "حسگرها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 77,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "قفل در",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 78,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "لوازم تزيني",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 79,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "دستگيره ها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 80,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "زه ها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 81,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ديفيوژر",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 82,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رادياتور",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 83,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "فلاپ ها",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 84,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "دوربين",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1380/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 85,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "اتاق",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1404/03/04",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 86,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "موتور",
|
||||||
|
"DmgBusinessLineId": 5454,
|
||||||
|
"FromDate": "1404/03/04",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 87,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5449
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "سيستم صوتي و تصويري",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 88,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5451
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ساير وسايل صوتي",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": 88,
|
||||||
|
"Id": 89,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5450
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "رينگ و لاستيك",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 90,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5448
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "ساير (بجز لوازم صوتي و تصويري )",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 91,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5450
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "كليه قطعات فابريك",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 92,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5448
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "آينه بغل",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 93,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5448
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "راديو پخش",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": 88,
|
||||||
|
"Id": 94,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5450
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Caption": "شيشه",
|
||||||
|
"DmgBusinessLineId": 5453,
|
||||||
|
"FromDate": "1300/01/01",
|
||||||
|
"GroupId": null,
|
||||||
|
"Id": 95,
|
||||||
|
"ToDate": "1999/12/29",
|
||||||
|
"UsedPlaceId": 5448
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -1,3 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Outer car parts catalog — shaped around the Fanavaran `car/base-info/car-components`
|
||||||
|
* API response.
|
||||||
|
*
|
||||||
|
* The *live* catalog is fetched at runtime through `FanavaranLookupService` so
|
||||||
|
* any changes Fanavaran makes to their part list are picked up automatically.
|
||||||
|
* `FANAVARAN_CAR_PARTS_CATALOG` below is a **static fallback snapshot** used
|
||||||
|
* only for legacy in-DB part resolution (i.e. parts that were stored before
|
||||||
|
* this change). It must not be used as the source for API responses.
|
||||||
|
*/
|
||||||
|
|
||||||
export enum ClaimVehicleTypeV2 {
|
export enum ClaimVehicleTypeV2 {
|
||||||
SEDAN = "sedan",
|
SEDAN = "sedan",
|
||||||
SUV = "suv",
|
SUV = "suv",
|
||||||
@@ -16,58 +27,132 @@ export enum OuterPartSideV2 {
|
|||||||
|
|
||||||
export type OuterPartCatalogItem = {
|
export type OuterPartCatalogItem = {
|
||||||
id: number;
|
id: number;
|
||||||
|
/** String key — equals `String(id)` for Fanavaran-sourced items. */
|
||||||
key: string;
|
key: string;
|
||||||
titleFa: string;
|
titleFa: string;
|
||||||
side: OuterPartSideV2;
|
/** Side is encoded in the Farsi caption for Fanavaran items; empty string for those. */
|
||||||
|
side: OuterPartSideV2 | "";
|
||||||
carType?: ClaimVehicleTypeV2;
|
carType?: ClaimVehicleTypeV2;
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseFor = (offset: number): OuterPartCatalogItem[] => [
|
/**
|
||||||
// left
|
* Snapshot of the Fanavaran `car/base-info/car-components` lookup.
|
||||||
{ id: offset + 1, key: "left_backfender", titleFa: "گلگیر عقب", side: OuterPartSideV2.LEFT },
|
* Used ONLY as a static fallback when resolving legacy part IDs already stored
|
||||||
{ id: offset + 2, key: "left_backWheel", titleFa: "چرخ عقب", side: OuterPartSideV2.LEFT },
|
* in the database. All live API endpoints must call `FanavaranLookupService`
|
||||||
{ id: offset + 3, key: "left_backDoor", titleFa: "در عقب", side: OuterPartSideV2.LEFT },
|
* instead.
|
||||||
{ id: offset + 4, key: "left_frontDoor", titleFa: "در جلو", side: OuterPartSideV2.LEFT },
|
*/
|
||||||
{ id: offset + 5, key: "left_mirror", titleFa: "آیینه", side: OuterPartSideV2.LEFT },
|
export const FANAVARAN_CAR_PARTS_CATALOG: OuterPartCatalogItem[] = [
|
||||||
{ id: offset + 6, key: "left_frontWheel", titleFa: "چرخ جلو", side: OuterPartSideV2.LEFT },
|
{ id: 1, key: "1", titleFa: "جلو کامل", side: "" },
|
||||||
{ id: offset + 7, key: "left_frontFender", titleFa: "گلگیر جلو", side: OuterPartSideV2.LEFT },
|
{ id: 2, key: "2", titleFa: "جلو چپ", side: "" },
|
||||||
{ id: offset + 8, key: "left_backWindow", titleFa: "شیشه عقب", side: OuterPartSideV2.LEFT },
|
{ id: 3, key: "3", titleFa: "جلو راست", side: "" },
|
||||||
{ id: offset + 9, key: "left_frontWindow", titleFa: "شیشه جلو", side: OuterPartSideV2.LEFT },
|
{ id: 4, key: "4", titleFa: "عقب کامل", side: "" },
|
||||||
// right
|
{ id: 5, key: "5", titleFa: "عقب چپ", side: "" },
|
||||||
{ id: offset + 10, key: "right_backfender", titleFa: "گلگیر عقب", side: OuterPartSideV2.RIGHT },
|
{ id: 6, key: "6", titleFa: "عقب راست", side: "" },
|
||||||
{ id: offset + 11, key: "right_backWheel", titleFa: "چرخ عقب", side: OuterPartSideV2.RIGHT },
|
{ id: 7, key: "7", titleFa: "بدنه راست", side: "" },
|
||||||
{ id: offset + 12, key: "right_backDoor", titleFa: "در عقب", side: OuterPartSideV2.RIGHT },
|
{ id: 8, key: "8", titleFa: "بدنه چپ", side: "" },
|
||||||
{ id: offset + 13, key: "right_frontDoor", titleFa: "در جلو", side: OuterPartSideV2.RIGHT },
|
{ id: 9, key: "9", titleFa: "سپر جلو", side: "" },
|
||||||
{ id: offset + 14, key: "right_mirror", titleFa: "آیینه", side: OuterPartSideV2.RIGHT },
|
{ id: 10, key: "10", titleFa: "سپر عقب", side: "" },
|
||||||
{ id: offset + 15, key: "right_frontWheel", titleFa: "چرخ جلو", side: OuterPartSideV2.RIGHT },
|
{ id: 11, key: "11", titleFa: "آينه سمت راننده", side: "" },
|
||||||
{ id: offset + 16, key: "right_frontFender", titleFa: "گلگیر جلو", side: OuterPartSideV2.RIGHT },
|
{ id: 12, key: "12", titleFa: "آينه سمت سرنشين", side: "" },
|
||||||
{ id: offset + 17, key: "right_backWindow", titleFa: "شیشه عقب", side: OuterPartSideV2.RIGHT },
|
{ id: 13, key: "13", titleFa: "چراغ جلو چپ", side: "" },
|
||||||
{ id: offset + 18, key: "right_frontWindow", titleFa: "شیشه جلو", side: OuterPartSideV2.RIGHT },
|
{ id: 14, key: "14", titleFa: "چراغ جلو راست", side: "" },
|
||||||
// front
|
{ id: 15, key: "15", titleFa: "چراغ عقب چپ", side: "" },
|
||||||
{ id: offset + 19, key: "front_frontBumper", titleFa: "سپر جلو", side: OuterPartSideV2.FRONT },
|
{ id: 16, key: "16", titleFa: "چراغ عقب راست", side: "" },
|
||||||
{ id: offset + 20, key: "front_frontCarWindshield", titleFa: "شیشه جلو", side: OuterPartSideV2.FRONT },
|
{ id: 17, key: "17", titleFa: "لاستيک جلو چپ", side: "" },
|
||||||
{ id: offset + 21, key: "front_carHood", titleFa: "کاپوت", side: OuterPartSideV2.FRONT },
|
{ id: 18, key: "18", titleFa: "لاستيک جلو راست", side: "" },
|
||||||
{ id: offset + 22, key: "front_leftLight", titleFa: "چراغ چپ", side: OuterPartSideV2.FRONT },
|
{ id: 19, key: "19", titleFa: "لاستيک عقب چپ", side: "" },
|
||||||
{ id: offset + 23, key: "front_rightLight", titleFa: "چراغ راست", side: OuterPartSideV2.FRONT },
|
{ id: 20, key: "20", titleFa: "لاستيک عقب راست", side: "" },
|
||||||
{ id: offset + 24, key: "front_frontGrille", titleFa: "جلو پنجره", side: OuterPartSideV2.FRONT },
|
{ id: 21, key: "21", titleFa: "لاستيک زاپاس", side: "" },
|
||||||
// back
|
{ id: 22, key: "22", titleFa: "رينگ جلو چپ", side: "" },
|
||||||
{ id: offset + 25, key: "back_backBumper", titleFa: "سپر عقب", side: OuterPartSideV2.BACK },
|
{ id: 23, key: "23", titleFa: "رينگ جلو راست", side: "" },
|
||||||
{ id: offset + 26, key: "back_carTrunk", titleFa: "صندوق عقب", side: OuterPartSideV2.BACK },
|
{ id: 24, key: "24", titleFa: "رينگ عقب چپ", side: "" },
|
||||||
{ id: offset + 27, key: "back_backCarWindshield", titleFa: "شیشه عقب", side: OuterPartSideV2.BACK },
|
{ id: 25, key: "25", titleFa: "رينگ عقب راست", side: "" },
|
||||||
{ id: offset + 28, key: "back_leftLight", titleFa: "چراغ چپ", side: OuterPartSideV2.BACK },
|
{ id: 26, key: "26", titleFa: "راهنماي جلو چپ", side: "" },
|
||||||
{ id: offset + 29, key: "back_rightLight", titleFa: "چراغ راست", side: OuterPartSideV2.BACK },
|
{ id: 27, key: "27", titleFa: "راهنماي جلو راست", side: "" },
|
||||||
// top
|
{ id: 28, key: "28", titleFa: "راهنماي عقب چپ", side: "" },
|
||||||
{ id: offset + 30, key: "top_roof", titleFa: "سقف", side: OuterPartSideV2.TOP },
|
{ id: 29, key: "29", titleFa: "راهنماي عقب راست", side: "" },
|
||||||
|
{ id: 30, key: "30", titleFa: "درب جلو سمت راننده", side: "" },
|
||||||
|
{ id: 31, key: "31", titleFa: "درب جلو سمت سرنشين", side: "" },
|
||||||
|
{ id: 32, key: "32", titleFa: "درب عقب سمت راننده", side: "" },
|
||||||
|
{ id: 33, key: "33", titleFa: "درب عقب سمت سرنشين", side: "" },
|
||||||
|
{ id: 34, key: "34", titleFa: "گلگير جلو سمت راننده", side: "" },
|
||||||
|
{ id: 35, key: "35", titleFa: "گلگير جلو سمت سرنشين", side: "" },
|
||||||
|
{ id: 36, key: "36", titleFa: "گلگير عقب سمت راننده", side: "" },
|
||||||
|
{ id: 37, key: "37", titleFa: "گلگير عقب سمت سرنشين", side: "" },
|
||||||
|
{ id: 38, key: "38", titleFa: "ستون جلو چپ", side: "" },
|
||||||
|
{ id: 39, key: "39", titleFa: "ستون جلو راست", side: "" },
|
||||||
|
{ id: 40, key: "40", titleFa: "ستون وسط چپ", side: "" },
|
||||||
|
{ id: 41, key: "41", titleFa: "ستون وسط راست", side: "" },
|
||||||
|
{ id: 42, key: "42", titleFa: "ستون عقب چپ", side: "" },
|
||||||
|
{ id: 43, key: "43", titleFa: "ستون عقب راست", side: "" },
|
||||||
|
{ id: 44, key: "44", titleFa: "شيشه جلو", side: "" },
|
||||||
|
{ id: 45, key: "45", titleFa: "شيشه عقب", side: "" },
|
||||||
|
{ id: 46, key: "46", titleFa: "سيني جلو (زير موتور)", side: "" },
|
||||||
|
{ id: 47, key: "47", titleFa: "درب موتور جلو", side: "" },
|
||||||
|
{ id: 48, key: "48", titleFa: "درب صندوق عقب", side: "" },
|
||||||
|
{ id: 49, key: "49", titleFa: "جلو پنجره", side: "" },
|
||||||
|
{ id: 50, key: "50", titleFa: "سقف خودرو", side: "" },
|
||||||
|
{ id: 51, key: "51", titleFa: "سانروف", side: "" },
|
||||||
|
{ id: 52, key: "52", titleFa: "سيني کف صندوق", side: "" },
|
||||||
|
{ id: 53, key: "53", titleFa: "متعلقات جلوبندي", side: "" },
|
||||||
|
{ id: 54, key: "54", titleFa: "متعلقات داخل خودرو", side: "" },
|
||||||
|
{ id: 55, key: "55", titleFa: "اگزوز و متعلقات", side: "" },
|
||||||
|
{ id: 56, key: "56", titleFa: "بلوکه سيلندر", side: "" },
|
||||||
|
{ id: 57, key: "57", titleFa: "موتور و متعلقات ( به غير از سيلندر)", side: "" },
|
||||||
|
{ id: 58, key: "58", titleFa: "شاسي جلو", side: "" },
|
||||||
|
{ id: 59, key: "59", titleFa: "شاسي عقب", side: "" },
|
||||||
|
{ id: 60, key: "60", titleFa: "ايربگ", side: "" },
|
||||||
|
{ id: 61, key: "61", titleFa: "شيشه پنجره درب جلو سمت راننده", side: "" },
|
||||||
|
{ id: 62, key: "62", titleFa: "شيشه پنجره درب جلو سمت سرنشين", side: "" },
|
||||||
|
{ id: 63, key: "63", titleFa: "شيشه پنجره درب عقب سمت راننده", side: "" },
|
||||||
|
{ id: 64, key: "64", titleFa: "شيشه پنجره درب عقب سمت سرنشين", side: "" },
|
||||||
|
{ id: 65, key: "65", titleFa: "بادگير شيشه ها", side: "" },
|
||||||
|
{ id: 66, key: "66", titleFa: "برف پاک کن", side: "" },
|
||||||
|
{ id: 67, key: "67", titleFa: "رکاب ها", side: "" },
|
||||||
|
{ id: 68, key: "68", titleFa: "درپوش باک بنزين", side: "" },
|
||||||
|
{ id: 69, key: "69", titleFa: "سامانه برق رساني (به جزء باتري)", side: "" },
|
||||||
|
{ id: 70, key: "70", titleFa: "باتري", side: "" },
|
||||||
|
{ id: 71, key: "71", titleFa: "سيستم تهويه مطبوع (به جزء کولر)", side: "" },
|
||||||
|
{ id: 72, key: "72", titleFa: "کولر", side: "" },
|
||||||
|
{ id: 73, key: "73", titleFa: "خسارتهاي پنهان", side: "" },
|
||||||
|
{ id: 74, key: "74", titleFa: "کلاف", side: "" },
|
||||||
|
{ id: 75, key: "75", titleFa: "کف اتاق", side: "" },
|
||||||
|
{ id: 76, key: "76", titleFa: "سيني عقب", side: "" },
|
||||||
|
{ id: 77, key: "77", titleFa: "حسگرها", side: "" },
|
||||||
|
{ id: 78, key: "78", titleFa: "قفل در", side: "" },
|
||||||
|
{ id: 79, key: "79", titleFa: "لوازم تزيني", side: "" },
|
||||||
|
{ id: 80, key: "80", titleFa: "دستگيره ها", side: "" },
|
||||||
|
{ id: 81, key: "81", titleFa: "زه ها", side: "" },
|
||||||
|
{ id: 82, key: "82", titleFa: "ديفيوژر", side: "" },
|
||||||
|
{ id: 83, key: "83", titleFa: "رادياتور", side: "" },
|
||||||
|
{ id: 84, key: "84", titleFa: "فلاپ ها", side: "" },
|
||||||
|
{ id: 85, key: "85", titleFa: "دوربين", side: "" },
|
||||||
|
{ id: 86, key: "86", titleFa: "اتاق", side: "" },
|
||||||
|
{ id: 87, key: "87", titleFa: "موتور", side: "" },
|
||||||
|
{ id: 88, key: "88", titleFa: "سيستم صوتي و تصويري", side: "" },
|
||||||
|
{ id: 89, key: "89", titleFa: "ساير وسايل صوتي", side: "" },
|
||||||
|
{ id: 90, key: "90", titleFa: "رينگ و لاستيك", side: "" },
|
||||||
|
{ id: 91, key: "91", titleFa: "ساير (بجز لوازم صوتي و تصويري )", side: "" },
|
||||||
|
{ id: 92, key: "92", titleFa: "كليه قطعات فابريك", side: "" },
|
||||||
|
{ id: 93, key: "93", titleFa: "آينه بغل", side: "" },
|
||||||
|
{ id: 94, key: "94", titleFa: "راديو پخش", side: "" },
|
||||||
|
{ id: 95, key: "95", titleFa: "شيشه", side: "" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Backward-compatible alias used by `outer-damage-parts.ts` for legacy DB part
|
||||||
|
* resolution. All vehicle types share the same flat Fanavaran catalog because
|
||||||
|
* Fanavaran does not differentiate parts by car type.
|
||||||
|
*
|
||||||
|
* Do NOT use this for serving API responses — use `FanavaranLookupService` instead.
|
||||||
|
*/
|
||||||
export const OUTER_PARTS_BY_CAR_TYPE: Record<
|
export const OUTER_PARTS_BY_CAR_TYPE: Record<
|
||||||
ClaimVehicleTypeV2,
|
ClaimVehicleTypeV2,
|
||||||
OuterPartCatalogItem[]
|
OuterPartCatalogItem[]
|
||||||
> = {
|
> = {
|
||||||
[ClaimVehicleTypeV2.SEDAN]: baseFor(0),
|
[ClaimVehicleTypeV2.SEDAN]: FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
[ClaimVehicleTypeV2.SUV]: baseFor(100),
|
[ClaimVehicleTypeV2.SUV]: FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
[ClaimVehicleTypeV2.HATCHBACK]: baseFor(200),
|
[ClaimVehicleTypeV2.HATCHBACK]: FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
[ClaimVehicleTypeV2.PICKUP]: baseFor(300),
|
[ClaimVehicleTypeV2.PICKUP]: FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
[ClaimVehicleTypeV2.VAN]: baseFor(400),
|
[ClaimVehicleTypeV2.VAN]: FANAVARAN_CAR_PARTS_CATALOG,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user