@bytebrand/export-cars 1.22.20 → 1.22.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/formats/google-xml.builder.js +5 -5
- package/dist/formats/google-xml.builder.js.map +1 -1
- package/dist/interfaces/export-item.interface.d.ts +9 -4
- package/dist/transformers/google.transformer.d.ts +8 -1
- package/dist/transformers/google.transformer.js +74 -23
- package/dist/transformers/google.transformer.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/formats/google-xml.builder.ts +7 -7
- package/src/interfaces/export-item.interface.ts +9 -4
- package/src/transformers/google.transformer.ts +86 -25
package/package.json
CHANGED
|
@@ -49,17 +49,17 @@ export class GoogleXmlBuilder extends XMLBuilderBase {
|
|
|
49
49
|
</g:${rootTag}>`;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
private getCertificationElement(rootTag: string, data: {
|
|
52
|
+
private getCertificationElement(rootTag: string, data: Array<{
|
|
53
53
|
certification_authority: string;
|
|
54
54
|
certification_name: string;
|
|
55
55
|
certification_code?: string;
|
|
56
56
|
certification_value?: string;
|
|
57
|
-
}): string {
|
|
58
|
-
return `<g:${rootTag}>
|
|
59
|
-
<g:certification_authority>${
|
|
60
|
-
<g:certification_name>${
|
|
61
|
-
<g:certification_value>${
|
|
62
|
-
</g:${rootTag}
|
|
57
|
+
}>): string {
|
|
58
|
+
return data.map(certification => `<g:${rootTag}>
|
|
59
|
+
<g:certification_authority>${certification.certification_authority}</g:certification_authority>
|
|
60
|
+
<g:certification_name>${certification.certification_name}</g:certification_name>
|
|
61
|
+
<g:certification_value>${certification.certification_value}</g:certification_value>
|
|
62
|
+
</g:${rootTag}>`).join('');
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
private getInstallmentElement(rootTag: string, data: { paybackPeriod: string; monthlyInstallment: string; apr?: string }): string {
|
|
@@ -173,27 +173,32 @@ export interface GoogleXmlItem {
|
|
|
173
173
|
availability?: string;
|
|
174
174
|
energy_efficiency_class?: string;
|
|
175
175
|
installment?: { paybackPeriod: any; monthlyInstallment: any; apr: string };
|
|
176
|
+
vehicle_msrp?: string;
|
|
176
177
|
|
|
177
178
|
vehicle_fulfillment: {
|
|
178
179
|
option: string;
|
|
179
180
|
store_code: string;
|
|
180
181
|
};
|
|
181
|
-
certification?: {
|
|
182
|
+
certification?: Array<{
|
|
182
183
|
certification_authority: string;
|
|
183
184
|
certification_name: string;
|
|
184
185
|
certification_code?: string;
|
|
185
186
|
certification_value?: string;
|
|
186
|
-
}
|
|
187
|
+
}>;
|
|
187
188
|
link_template: string;
|
|
188
189
|
additional_image_link: string[];
|
|
189
190
|
model: string;
|
|
190
|
-
VIN
|
|
191
|
+
VIN?: string;
|
|
191
192
|
trim: string;
|
|
192
193
|
year: number;
|
|
193
194
|
mileage: string;
|
|
194
195
|
vehicle_option: string[];
|
|
195
|
-
body_style
|
|
196
|
+
body_style?: string,
|
|
196
197
|
engine: string,
|
|
198
|
+
transmission?: string;
|
|
199
|
+
drive?: string;
|
|
200
|
+
doors?: number;
|
|
201
|
+
capacity?: number;
|
|
197
202
|
date_first_registered: string,
|
|
198
203
|
fuel_consumption: string,
|
|
199
204
|
energy_consumption?: string,
|
|
@@ -7,6 +7,7 @@ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
|
|
|
7
7
|
import { Injectable } from '@nestjs/common';
|
|
8
8
|
import { ConfigService, ImagesService, TransformerService, UserService } from '../services';
|
|
9
9
|
import { GoogleXmlItem } from '../interfaces';
|
|
10
|
+
import { isValidVin } from '../utils';
|
|
10
11
|
import moment from 'moment';
|
|
11
12
|
|
|
12
13
|
const GOOGLE_MAX_TRIM_LENGTH = 50;
|
|
@@ -59,7 +60,7 @@ export class GoogleTransformer {
|
|
|
59
60
|
certification: this.getCertification(car),
|
|
60
61
|
title: this.getTitle(car),
|
|
61
62
|
product_type: this.getCategory(car),
|
|
62
|
-
VIN: this.
|
|
63
|
+
VIN: this.getVin(car),
|
|
63
64
|
id: carId,
|
|
64
65
|
image_link: allImages[0],
|
|
65
66
|
additional_image_link: allImages.slice(1, 10),
|
|
@@ -68,6 +69,7 @@ export class GoogleTransformer {
|
|
|
68
69
|
link_template: `${this.getLink(car)}?store={store_code}`,
|
|
69
70
|
condition: this.mapState(car),
|
|
70
71
|
price: this.getPrice(car),
|
|
72
|
+
vehicle_msrp: this.getVehicleMsrp(car),
|
|
71
73
|
// certified_pre-owned: '',
|
|
72
74
|
brand: this.transformService.make(car),
|
|
73
75
|
model: this.transformService.model(car),
|
|
@@ -78,6 +80,10 @@ export class GoogleTransformer {
|
|
|
78
80
|
vehicle_option: this.getExtrasField(car),
|
|
79
81
|
body_style: this.mapBodyStyle(car),
|
|
80
82
|
engine: this.mapFuel(car),
|
|
83
|
+
transmission: this.mapTransmission(car),
|
|
84
|
+
drive: this.mapDrive(car),
|
|
85
|
+
doors: this.getDoors(car),
|
|
86
|
+
capacity: this.getCapacity(car),
|
|
81
87
|
date_first_registered: this.getDateFirstRegistered(car),
|
|
82
88
|
fuel_consumption: `${this.transformService.fuelConsumption(car)}l/100km`,
|
|
83
89
|
energy_consumption: this.getEnergyConsumption(car),
|
|
@@ -85,7 +91,7 @@ export class GoogleTransformer {
|
|
|
85
91
|
fuel_consumption_discharged_battery: this.getFuelConsumptionDischargedBattery(car),
|
|
86
92
|
co2_emissions: `${this.transformService.cO2Emission(car)}g/km`,
|
|
87
93
|
description: this.processText((await this.getDescription(car))),
|
|
88
|
-
identifier_exists: '
|
|
94
|
+
identifier_exists: 'yes',
|
|
89
95
|
availability: 'in_stock',
|
|
90
96
|
// custom_label_0: '',
|
|
91
97
|
// custom_label_1: '',
|
|
@@ -110,6 +116,12 @@ export class GoogleTransformer {
|
|
|
110
116
|
'electric_range',
|
|
111
117
|
'fuel_consumption_discharged_battery',
|
|
112
118
|
'installment',
|
|
119
|
+
'body_style',
|
|
120
|
+
'vehicle_msrp',
|
|
121
|
+
'transmission',
|
|
122
|
+
'drive',
|
|
123
|
+
'doors',
|
|
124
|
+
'capacity',
|
|
113
125
|
];
|
|
114
126
|
for (const key of optionalKeys) {
|
|
115
127
|
if (!item[key]) {
|
|
@@ -124,12 +136,14 @@ export class GoogleTransformer {
|
|
|
124
136
|
if (images.length === 0)
|
|
125
137
|
return false
|
|
126
138
|
|
|
127
|
-
if (!this.mapBodyStyle(car))
|
|
128
|
-
return false
|
|
129
|
-
|
|
130
139
|
return true
|
|
131
140
|
}
|
|
132
141
|
|
|
142
|
+
private getVin(car: DataSchemes.Car): string {
|
|
143
|
+
const vin = get(car, 'metaData.vin', '');
|
|
144
|
+
return isValidVin(vin) ? vin : get(car, 'marketing.fakeVIN', '');
|
|
145
|
+
}
|
|
146
|
+
|
|
133
147
|
private getTitle(car: DataSchemes.Car): string {
|
|
134
148
|
const model = toString(get(car, 'mainData.model', ''));
|
|
135
149
|
const brand = trim(this.getBrand(car));
|
|
@@ -200,12 +214,13 @@ export class GoogleTransformer {
|
|
|
200
214
|
}
|
|
201
215
|
}
|
|
202
216
|
|
|
203
|
-
private
|
|
204
|
-
const retailPrice = get(car, 'recommendedRetailPrice'
|
|
205
|
-
|
|
206
|
-
|
|
217
|
+
private getVehicleMsrp(car: DataSchemes.Car): string | undefined {
|
|
218
|
+
const retailPrice = get(car, 'recommendedRetailPrice');
|
|
219
|
+
const salesPrice = get(car, 'price.currentSalesPrice', 0);
|
|
220
|
+
if (!retailPrice || round(retailPrice, 2) === round(salesPrice, 2)) {
|
|
221
|
+
return undefined;
|
|
207
222
|
}
|
|
208
|
-
return
|
|
223
|
+
return `${round(retailPrice, 2)} EUR`;
|
|
209
224
|
}
|
|
210
225
|
|
|
211
226
|
private getPrice(car: DataSchemes.Car): string {
|
|
@@ -241,7 +256,7 @@ export class GoogleTransformer {
|
|
|
241
256
|
return get(available, availability);
|
|
242
257
|
}
|
|
243
258
|
|
|
244
|
-
private
|
|
259
|
+
private mapEnergyClass(selector: string): string {
|
|
245
260
|
const available = {
|
|
246
261
|
selector_energyEfficiencyClass_a: 'A',
|
|
247
262
|
selector_energyEfficiencyClass_ap: 'A+',
|
|
@@ -255,21 +270,42 @@ export class GoogleTransformer {
|
|
|
255
270
|
selector_energyEfficiencyClass_g: 'G',
|
|
256
271
|
selector_unknown: 'default',
|
|
257
272
|
};
|
|
258
|
-
const
|
|
259
|
-
const value = get(available, energyClass);
|
|
273
|
+
const value = get(available, selector);
|
|
260
274
|
return value ? value.replace(/\+/g, '') : '';
|
|
261
275
|
}
|
|
262
276
|
|
|
277
|
+
private getEnergyClass(car: DataSchemes.Car): string {
|
|
278
|
+
return this.mapEnergyClass(get(car, 'environmentEmissions.energyEfficiencyClass', 'selector_unknown'));
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private getDischargedEnergyClass(car: DataSchemes.Car): string {
|
|
282
|
+
return this.mapEnergyClass(get(car, 'environmentEmissions.wltpDischargedEnergyEfficiencyClass', 'selector_unknown'));
|
|
283
|
+
}
|
|
284
|
+
|
|
263
285
|
private getCertification(car: DataSchemes.Car) {
|
|
264
|
-
const
|
|
265
|
-
|
|
266
|
-
|
|
286
|
+
const certifications: Array<{ certification_authority: string; certification_name: string; certification_value: string }> = [];
|
|
287
|
+
|
|
288
|
+
const co2Class = this.getEnergyClass(car);
|
|
289
|
+
if (co2Class && co2Class !== 'default') {
|
|
290
|
+
certifications.push({
|
|
291
|
+
certification_authority: 'BMWK',
|
|
292
|
+
certification_name: 'Vehicle_CO2_Class',
|
|
293
|
+
certification_value: co2Class,
|
|
294
|
+
});
|
|
267
295
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
296
|
+
|
|
297
|
+
if (get(car, 'engineData.hybridPlugin')) {
|
|
298
|
+
const dischargedClass = this.getDischargedEnergyClass(car);
|
|
299
|
+
if (dischargedClass && dischargedClass !== 'default') {
|
|
300
|
+
certifications.push({
|
|
301
|
+
certification_authority: 'BMWK',
|
|
302
|
+
certification_name: 'Vehicle_CO2_Class_Discharged_Battery',
|
|
303
|
+
certification_value: dischargedClass,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return certifications.length ? certifications : undefined;
|
|
273
309
|
}
|
|
274
310
|
|
|
275
311
|
private getEnergyConsumption(car: DataSchemes.Car): string | undefined {
|
|
@@ -366,6 +402,32 @@ export class GoogleTransformer {
|
|
|
366
402
|
return get(available, category);
|
|
367
403
|
}
|
|
368
404
|
|
|
405
|
+
private mapTransmission(car: DataSchemes.Car): string | undefined {
|
|
406
|
+
const available = {
|
|
407
|
+
selector_gearbox_manualShift: 'MANUAL',
|
|
408
|
+
selector_gearbox_semiAutomatic: 'AUTOMATIC',
|
|
409
|
+
selector_gearbox_automatic: 'AUTOMATIC',
|
|
410
|
+
};
|
|
411
|
+
return get(available, get(car, 'driveSuspension.gearbox'));
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
private mapDrive(car: DataSchemes.Car): string | undefined {
|
|
415
|
+
const available = {
|
|
416
|
+
selector_driveType_frontWheelDrive: 'FWD',
|
|
417
|
+
selector_driveType_rearWheelDrive: 'RWD',
|
|
418
|
+
selector_driveType_allWheelDrive: 'AWD',
|
|
419
|
+
};
|
|
420
|
+
return get(available, get(car, 'driveSuspension.driveType'));
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
private getDoors(car: DataSchemes.Car): number | undefined {
|
|
424
|
+
return toSafeInteger(get(car, 'mainData.doors')) || undefined;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
private getCapacity(car: DataSchemes.Car): number | undefined {
|
|
428
|
+
return toSafeInteger(get(car, 'engineData.cubicCapacity')) || undefined;
|
|
429
|
+
}
|
|
430
|
+
|
|
369
431
|
private getExtrasField(car: DataSchemes.Car): string[] {
|
|
370
432
|
const booleanFields: string[] = [
|
|
371
433
|
'engineData.startStopSystem',
|
|
@@ -479,10 +541,9 @@ export class GoogleTransformer {
|
|
|
479
541
|
}
|
|
480
542
|
|
|
481
543
|
private getYear(car: DataSchemes.Car) {
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
const firstModelsProductionYear = date.getFullYear();
|
|
544
|
+
// mainData.firstModelsProductionDate is already a 4-digit year (mobile.de "vintage"),
|
|
545
|
+
// not a timestamp — do not run it through `new Date(...)`.
|
|
546
|
+
const firstModelsProductionYear = toSafeInteger(get(car, 'mainData.firstModelsProductionDate', 0));
|
|
486
547
|
|
|
487
548
|
return firstModelsProductionYear > TIMESTAMP_FIRST_YEAR ? firstModelsProductionYear : null
|
|
488
549
|
}
|