fix(pl24): wire Fiat as P5-modern /p5fiat (was dead LEGACY_FIAT /fca)

Fiat (fiatp_parts/fiatt_parts) was misconfigured as LEGACY_FIAT basePath /fca,
which 404s on every request — PL24 Fiat decode was dead. Live discovery
(de-708171) shows Fiat is a standard P5 Modern catalog at /p5fiat: directAccess
+ maingroups/subgroups/parts/images all match the existing P5 flow. Only the
vinfoBasic record shape differs ({key,description} vs {values:{description,value}}).

- types: fiatp_parts/fiatt_parts -> P5_MODERN, apiPath/basePath /p5fiat
- parseVehicleResponse: parse the p5fiat vinfoBasic shape; friendly model from
  "Model bilgisi"; year from MY / production date

Covers European (ZFA) Fiats + some commercial Tofas (fiatt). Turkish Tofas
passenger VINs (NM4, incl. Egea) are not in this catalog. de account separation
(resolveAccount Rule 1) unchanged; de auth handshake proxied, catalog data not.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-04 16:58:03 +03:00
parent 45953f6dd5
commit 4a115db885
2 changed files with 51 additions and 14 deletions

View File

@@ -997,16 +997,36 @@ export class PL24Service {
serviceName: string,
): Omit<PL24DecodedVehicle, "categories"> {
const segments =
(data.segments as Record<string, { records?: Array<{ values: Record<string, string> }> }>) ||
{};
(data.segments as Record<
string,
{
records?: Array<{
values?: Record<string, string>;
key?: string;
description?: string;
code?: string;
}>;
}
>) || {};
const vinfoRecords = segments.vinfoBasic?.records || [];
const vehicleData: Record<string, string> = {};
for (const record of vinfoRecords) {
// Two record shapes across P5 backends:
// p5vwag etc.: { values: { description: <label>, value: <value> } }
// p5fiat: { key: <label>, description: <value>, code?: <code> }
let label = "";
let value = "";
if (record.values) {
const key = record.values.description?.toLowerCase().replace(/[\s\/]+/g, "_") || "";
vehicleData[key] = record.values.value?.replace(/\r?\n/g, " ").trim() || "";
label = record.values.description || "";
value = record.values.value || "";
} else if (record.key) {
label = record.key;
value = record.description || "";
}
if (!label) continue;
const key = label.toLowerCase().replace(/[\s\/]+/g, "_");
if (!(key in vehicleData)) vehicleData[key] = value.replace(/\r?\n/g, " ").trim();
}
// Helper: look up by multiple possible keys (EN + TR)
@@ -1063,8 +1083,22 @@ export class PL24Service {
return {
brand: SERVICE_TO_BRAND[serviceName] || serviceName.replace("_parts", ""),
model: lookup("model")?.trim() || (data.description as string)?.split(" - ")[0]?.trim() || "",
year: Number.parseInt(lookup("model_yili", "year") || "", 10) || extractModelYear(vin) || 0,
// p5fiat carries the friendly model in "Model bilgisi" ("Panda POP 1.2 8V 69CV 5M E6");
// its plain "Model" is a numeric code. Other P5 backends only have "model".
model:
lookup("model_bilgisi", "model")?.trim() ||
(data.description as string)?.split(" - ")[0]?.trim() ||
"",
// p5fiat has no plain model-year field; derive it from "MY" ("… = 2014 YILI") or the
// production date ("05/09/2014"). Other P5 backends use a plain model_yili/year number.
year:
Number.parseInt(lookup("model_yili", "year") || "", 10) ||
Number.parseInt(
(lookup("my", "üretim_tarihi", "uretim_tarihi") || "").match(/(19|20)\d{2}/)?.[0] || "",
10,
) ||
extractModelYear(vin) ||
0,
series: lookup("satis_tipi", "sales_type"),
bodyType,
engineCode: engineCode || (engineDesc ? engineDesc.split("/")[0]?.trim() : null),

View File

@@ -362,17 +362,20 @@ export const PL24_SERVICE_CATALOGS: Record<string, PL24CatalogConfig> = {
architecture: "LEGACY_VOLVO",
},
// Fiat Group (FCA/Stellantis) — P4 Legacy, requires de-708171 account
// NOTE: basePath/apiPath require Playwright verification with de account
// Fiat Group (FCA) — P5 Modern catalog at /p5fiat, requires de-708171 account.
// Verified live 2026-06-04: launchCatalog.do → /pl24-app (P5 SPA), backend /p5fiat;
// directAccess + maingroups/subgroups/parts/images are standard P5. Covers European
// (ZFA) Fiats + some commercial Tofaş (fiatt); Turkish Tofaş passenger (NM4, incl. Egea)
// is NOT in this catalog. de auth handshake is proxied; catalog data needs no proxy.
fiatp_parts: {
basePath: "/fca",
apiPath: "/fca",
architecture: "LEGACY_FIAT",
basePath: "/p5fiat",
apiPath: "/p5fiat",
architecture: "P5_MODERN",
},
fiatt_parts: {
basePath: "/fca",
apiPath: "/fca",
architecture: "LEGACY_FIAT",
basePath: "/p5fiat",
apiPath: "/p5fiat",
architecture: "P5_MODERN",
},
};