refactor(emex): rewrite EMEX integration, add category fallback

Replace browser-based Puppeteer scraper with standalone scraper wrapper.
Add EMEX as fallback source for categories when PL24 is unavailable.
Update vehicle decoding to use new synchronous EMEX API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Sase Dev
2026-02-12 19:48:03 +00:00
parent 8b106cbb1f
commit a8eb8f4bdc
20 changed files with 1494 additions and 1209 deletions

View File

@@ -82,17 +82,18 @@ export class VehiclesService {
}
// 5. Fallback to EMEX if PL24 not available
let emexVehicle = null;
let emexVehicle: import('../integrations/emex/emex.types').DecodedVehicle | null = null;
if (!pl24Vehicle) {
this.logger.log(`PL24 returned no data for ${vin}, trying EMEX fallback`);
try {
emexVehicle = await this.emexService.getScrapedVehicle(vin);
if (!emexVehicle) {
await this.emexService.decodeVin(vin, userId);
this.logger.log(`EMEX scrape job queued for ${vin}`);
if (this.emexService.isSupported(vin)) {
const emexResult = await this.emexService.decodeVin(vin);
if (emexResult && emexResult.brand !== 'UNKNOWN') {
emexVehicle = emexResult;
}
}
} catch (emexError) {
this.logger.warn(`EMEX fallback failed for ${vin}`, emexError);
this.logger.warn(`EMEX fallback failed for ${vin}: ${(emexError as Error).message}`);
}
}
@@ -113,13 +114,13 @@ export class VehiclesService {
vin,
brandId,
brandName: corgiResult.brandName,
model: pl24Vehicle?.model || emexVehicle?.modelCode || vinApiData?.model || null,
year: pl24Vehicle?.year || emexVehicle?.yearFrom || corgiResult.modelYear || (vinApiData ? parseInt(vinApiData.modelYear) : null),
engine: pl24Vehicle?.engineType || pl24Vehicle?.engineCode || emexVehicle?.engine || vinApiData?.engineModel || null,
transmission: pl24Vehicle?.transmission || vinApiData?.transmissionStyle || null,
bodyType: pl24Vehicle?.bodyType || vinApiData?.bodyClass || null,
model: pl24Vehicle?.model || emexVehicle?.model || vinApiData?.model || null,
year: pl24Vehicle?.year || emexVehicle?.year || corgiResult.modelYear || (vinApiData ? parseInt(vinApiData.modelYear) : null),
engine: pl24Vehicle?.engineType || pl24Vehicle?.engineCode || emexVehicle?.engineCode || emexVehicle?.engineType || vinApiData?.engineModel || null,
transmission: pl24Vehicle?.transmission || emexVehicle?.transmission || vinApiData?.transmissionStyle || null,
bodyType: pl24Vehicle?.bodyType || emexVehicle?.bodyType || vinApiData?.bodyClass || null,
market: null as string | null,
rawData: pl24Vehicle || emexVehicle?.rawData || vinApiData || null,
rawData: pl24Vehicle || emexVehicle?.raw || vinApiData || null,
source,
updatedAt: new Date(),
};