From 642139de9c14797a38a04c57048f51dd6ec35e78 Mon Sep 17 00:00:00 2001 From: Semih Yesilyurt Date: Tue, 2 Jun 2026 20:20:30 +0300 Subject: [PATCH] =?UTF-8?q?fix(pl24):=20detect=20"bak=C4=B1n=C4=B1z=20tabl?= =?UTF-8?q?o,=20konum:"=20reference=20phrasing=20too?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PL24 translates "see table" two ways — "bk. tablo:" and "bakınız tablo, konum:". Detection only matched the first, so the latter rows (e.g. evaporator housing → 820-020) stayed dead. Broaden the name regex to match either, and strip both phrasings from the displayed label. The code-in-remark gate still prevents flagging real parts that merely mention "tablo". Co-Authored-By: Claude Opus 4.8 (1M context) --- apps/api/src/categories/categories.service.ts | 21 ++++++++++++------- .../web/src/components/schema/parts-panel.tsx | 9 ++++---- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/apps/api/src/categories/categories.service.ts b/apps/api/src/categories/categories.service.ts index 4b883e0..b0cf100 100644 --- a/apps/api/src/categories/categories.service.ts +++ b/apps/api/src/categories/categories.service.ts @@ -1471,15 +1471,20 @@ export class CategoriesService { }; } - // PL24 BOM "bk. tablo:NNN-NNN" rows are cross-references to another - // illustration, not real parts (oem_code "N/A", target code in `remark`). - // Upstream gives us NO navigable link for them — only the text code — so we - // resolve it ourselves: every illustration's code lives in its category name - // as `{NNN-NNN}`, so we build a code→categoryId index for this vehicle and - // attach it. Codes whose target branch hasn't been lazily seeded yet resolve - // to null; the UI then falls back to a pre-filled catalog search. + // PL24 BOM cross-reference rows point to another illustration, not a real part + // (oem_code "N/A", target code in `remark`). Upstream gives us NO navigable + // link — only the text code — so we resolve it ourselves: every illustration's + // code lives in its category name as `{NNN-NNN}`, so we build a code→categoryId + // index for this vehicle and attach it. Codes whose target branch hasn't been + // lazily seeded yet resolve to null; the UI then drills on demand / falls back + // to a pre-filled catalog search. + // + // The "see table" phrasing varies by PL24's own translation: "bk. tablo:" and + // "bakınız tablo, konum:" both occur — match either (the code-in-remark gate + // below keeps this from flagging real parts that merely mention "tablo"). private static readonly REF_CODE_RE = /\d{3}-\d{3}/g; private static readonly REF_CODE_IN_NAME_RE = /\{(\d{3}-\d{3})\}/g; + private static readonly REF_NAME_RE = /b(?:k\.?|akınız)\s+tablo/i; // Build a code→categoryId index for a vehicle from the `{NNN-NNN}` illustration // codes embedded in category names. Reflects only what's been seeded so far. @@ -1502,7 +1507,7 @@ export class CategoriesService { rows: T[], vehicleId: string | null, ): Promise<(T & { references?: Array<{ code: string; categoryId: string | null }> })[]> { - const isRef = (p: T) => p.name?.includes("bk. tablo"); + const isRef = (p: T) => CategoriesService.REF_NAME_RE.test(p.name ?? ""); if (!vehicleId || !rows.some(isRef)) return rows; const index = await this.buildReferenceIndex(vehicleId); diff --git a/apps/web/src/components/schema/parts-panel.tsx b/apps/web/src/components/schema/parts-panel.tsx index c7e2927..ae50723 100644 --- a/apps/web/src/components/schema/parts-panel.tsx +++ b/apps/web/src/components/schema/parts-panel.tsx @@ -202,13 +202,14 @@ export function PartsPanel({ parts, vehicleId, categoryId, isLoading }: PartsPan const isSelected = group != null && selectedGroup === group; const isUnavailable = part.unavailable === true; - // PL24 "bk. tablo:" cross-reference row — not a real part, but a - // jump to another illustration. Render the target table code(s) - // as navigable links instead of a dead "N/A" OEM cell. + // PL24 cross-reference row ("bk. tablo:" / "bakınız tablo, konum:") + // — not a real part, but a jump to another illustration. Render + // the target table code(s) as navigable links instead of a dead + // "N/A" OEM cell, dropping the "see table" tail from the label. const refs = part.references; if (refs && refs.length > 0) { const label = part.name - .replace(/bk\.\s*tablo:?/i, "") + .replace(/b(?:k\.?|akınız)\s+tablo.*$/is, "") .replace(/\s*\/\s*$/, "") .trim(); return (