@bytebrand/export-cars 1.21.7 → 1.21.8

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.
Files changed (156) hide show
  1. package/.editorconfig +8 -8
  2. package/.eslintignore +1 -1
  3. package/.eslintrc.js +24 -24
  4. package/.prettierrc.js +7 -7
  5. package/README.md +65 -65
  6. package/dist/configs/index.d.ts +1 -0
  7. package/dist/configs/index.js +1 -0
  8. package/dist/configs/index.js.map +1 -1
  9. package/dist/configs/santander.config.d.ts +5 -0
  10. package/dist/configs/santander.config.js +18 -0
  11. package/dist/configs/santander.config.js.map +1 -0
  12. package/dist/enums/export-type.enum.d.ts +1 -0
  13. package/dist/enums/export-type.enum.js +1 -0
  14. package/dist/enums/export-type.enum.js.map +1 -1
  15. package/dist/export.command.js +1 -1
  16. package/dist/export.command.js.map +1 -1
  17. package/dist/export.schema.d.ts +6 -2
  18. package/dist/export.schema.js +4 -0
  19. package/dist/export.schema.js.map +1 -1
  20. package/dist/exporters/index.d.ts +1 -0
  21. package/dist/exporters/index.js +1 -0
  22. package/dist/exporters/index.js.map +1 -1
  23. package/dist/exporters/santander.exporter.d.ts +12 -0
  24. package/dist/exporters/santander.exporter.js +63 -0
  25. package/dist/exporters/santander.exporter.js.map +1 -0
  26. package/dist/formats/auto24-xml.builder.js +2 -2
  27. package/dist/formats/google-xml.builder.js +3 -3
  28. package/dist/formats/modix-xml.builder.js +2 -2
  29. package/dist/formats/ooyyo-xml.builder.js +1 -1
  30. package/dist/formats/santander-csv.builder.d.ts +6 -0
  31. package/dist/formats/santander-csv.builder.js +17 -0
  32. package/dist/formats/santander-csv.builder.js.map +1 -0
  33. package/dist/tsconfig.build.tsbuildinfo +1 -1
  34. package/nest-cli.json +5 -5
  35. package/package.json +61 -61
  36. package/src/app.module.ts +38 -38
  37. package/src/configs/alleskralle.config.ts +15 -15
  38. package/src/configs/as24.config.ts +13 -13
  39. package/src/configs/auto24.config.ts +15 -15
  40. package/src/configs/autoboerse.config.ts +16 -16
  41. package/src/configs/autouncle.config.ts +14 -14
  42. package/src/configs/awin.config.ts +15 -15
  43. package/src/configs/by-owner.config.ts +14 -14
  44. package/src/configs/config.ts +83 -83
  45. package/src/configs/criteo.config.ts +17 -17
  46. package/src/configs/dasparking.config.ts +15 -15
  47. package/src/configs/eauto.config.ts +15 -15
  48. package/src/configs/evium.config.ts +18 -18
  49. package/src/configs/facebook-shop.config.ts +16 -16
  50. package/src/configs/fb.config.ts +16 -16
  51. package/src/configs/google.config.ts +14 -14
  52. package/src/configs/index.ts +22 -21
  53. package/src/configs/kleinanzeigeFocus.config.ts +14 -14
  54. package/src/configs/marktde.config.ts +18 -18
  55. package/src/configs/meinstadt.config.ts +15 -15
  56. package/src/configs/mitula.config.ts +14 -14
  57. package/src/configs/ooyyo.config.ts +15 -15
  58. package/src/configs/santander.config.ts +15 -0
  59. package/src/configs/trovit.config.ts +14 -14
  60. package/src/configs/yescar.config.ts +17 -17
  61. package/src/constants/autouncle.contants.ts +4 -4
  62. package/src/constants/fb.constants.ts +7 -7
  63. package/src/constants/index.ts +1 -1
  64. package/src/constants/modix/body-color-name.constant.ts +20 -20
  65. package/src/constants/modix/category.constant.ts +14 -14
  66. package/src/constants/modix/fuel.constant.ts +14 -14
  67. package/src/constants/modix/index.ts +7 -7
  68. package/src/constants/modix/manufacturers.constant.ts +7498 -7498
  69. package/src/constants/modix/transmission.constant.ts +8 -8
  70. package/src/constants/modix/usage-type.constant.ts +13 -13
  71. package/src/constants/modix/vehicle-class.constant.ts +17 -17
  72. package/src/enums/environment.enum.ts +5 -5
  73. package/src/enums/export-type.enum.ts +33 -32
  74. package/src/enums/file-types.enum.ts +8 -8
  75. package/src/enums/image-type.enum.ts +4 -4
  76. package/src/enums/index.ts +4 -4
  77. package/src/export.command.ts +37 -37
  78. package/src/export.schema.ts +134 -128
  79. package/src/exporters/as24.exporter.ts +69 -69
  80. package/src/exporters/auto24.exporter.ts +48 -48
  81. package/src/exporters/autouncle.exporter.ts +60 -60
  82. package/src/exporters/awin.exporter.ts +47 -47
  83. package/src/exporters/by-owner.exporter.ts +44 -44
  84. package/src/exporters/facebook-shop.exporter.ts +51 -51
  85. package/src/exporters/fb.exporter.ts +52 -52
  86. package/src/exporters/google.exporter.ts +45 -45
  87. package/src/exporters/index.ts +15 -14
  88. package/src/exporters/meinstadt.exporter.ts +55 -55
  89. package/src/exporters/mobile.exporter.ts +64 -64
  90. package/src/exporters/modix.exporter.ts +56 -56
  91. package/src/exporters/ooyyo.exporter.ts +48 -48
  92. package/src/exporters/rubrikk.exporter.ts +53 -53
  93. package/src/exporters/santander.exporter.ts +50 -0
  94. package/src/exporters/trovit.exporter.ts +51 -51
  95. package/src/formats/auto24-xml.builder.ts +54 -54
  96. package/src/formats/autouncle-json.builder.ts +20 -20
  97. package/src/formats/awin-csv.builder.ts +16 -16
  98. package/src/formats/facebook-shop.builder.ts +69 -69
  99. package/src/formats/fb-xml.builder.ts +71 -71
  100. package/src/formats/google-xml.builder.ts +35 -35
  101. package/src/formats/index.ts +5 -5
  102. package/src/formats/meinstadt-json.builder.ts +19 -19
  103. package/src/formats/modix-xml.builder.ts +180 -180
  104. package/src/formats/ooyyo-xml.builder.ts +48 -48
  105. package/src/formats/rubrikk-xml.builder.ts +27 -27
  106. package/src/formats/santander-csv.builder.ts +15 -0
  107. package/src/formats/trovit-xml.builder.ts +44 -44
  108. package/src/interfaces/atributes-wrap-item.intreface.ts +6 -6
  109. package/src/interfaces/dealers-mapping.interface.ts +7 -7
  110. package/src/interfaces/description.interface.ts +24 -24
  111. package/src/interfaces/export-item.interface.ts +366 -366
  112. package/src/interfaces/exporter.interface.ts +3 -3
  113. package/src/interfaces/index.ts +3 -3
  114. package/src/interfaces/input.interface.ts +6 -6
  115. package/src/interfaces/mapping-rules.interface.ts +11 -11
  116. package/src/interfaces/modix/index.ts +1 -1
  117. package/src/interfaces/modix/modix-item-list.interface.ts +5 -5
  118. package/src/interfaces/params.interface.ts +13 -13
  119. package/src/interfaces/rule-parser.interface.ts +3 -3
  120. package/src/main.ts +14 -14
  121. package/src/rules/abstract.rule.ts +37 -37
  122. package/src/rules/date.rule.ts +19 -19
  123. package/src/rules/number.rule.ts +15 -15
  124. package/src/rules/string.rule.ts +8 -8
  125. package/src/services/car.service.ts +49 -49
  126. package/src/services/config.service.ts +15 -15
  127. package/src/services/images.service.ts +207 -207
  128. package/src/services/index.ts +9 -9
  129. package/src/services/loader.service.ts +29 -29
  130. package/src/services/mapping.service.ts +91 -91
  131. package/src/services/request.service.ts +44 -44
  132. package/src/services/rules.service.ts +61 -61
  133. package/src/services/transformer.service.ts +129 -129
  134. package/src/services/user.service.ts +57 -57
  135. package/src/transformers/as24.transformer.ts +253 -253
  136. package/src/transformers/auto24.transfomer.ts +155 -155
  137. package/src/transformers/autouncle.transformer.ts +236 -236
  138. package/src/transformers/awin.transformer.ts +193 -193
  139. package/src/transformers/by-owner.transformer.ts +354 -354
  140. package/src/transformers/facebook-shop.transformer.ts +93 -93
  141. package/src/transformers/fb-description.transformer.ts +316 -316
  142. package/src/transformers/fb-equipment.transformer.ts +161 -161
  143. package/src/transformers/fb.transformer.ts +655 -655
  144. package/src/transformers/google.transformer.ts +169 -169
  145. package/src/transformers/index.ts +5 -5
  146. package/src/transformers/meinstadt.transformer.ts +92 -92
  147. package/src/transformers/mobile.transformer.ts +482 -482
  148. package/src/transformers/modix.transformer.ts +227 -227
  149. package/src/transformers/ooyyo.transformer.ts +109 -109
  150. package/src/transformers/rubrikk.transformer.ts +200 -200
  151. package/src/transformers/trovit.transformer.ts +63 -63
  152. package/src/utils/converter.utils.ts +15 -15
  153. package/src/utils/index.ts +2 -2
  154. package/src/utils/validator.utils.ts +7 -7
  155. package/tsconfig.build.json +4 -4
  156. package/tsconfig.json +29 -29
@@ -1,109 +1,109 @@
1
- import { Translator } from '@bytebrand/schema-tools';
2
- import { de } from '@bytebrand/i18n-dictionaries';
3
- import { get, toString, isEmpty, trim, join } from 'lodash';
4
- import * as moment from 'moment';
5
- import { DataSchemes } from '@bytebrand/car-schema';
6
- import { OoyyoXmlItem } from '../interfaces';
7
- import { ImboImageResponseInterface } from '@bytebrand/chunkable';
8
- import { ConfigService, ImagesService } from '../services';
9
- import { Injectable } from '@nestjs/common';
10
-
11
- @Injectable()
12
- export class OoyyoTransformer {
13
- private translator: Translator;
14
-
15
- constructor(private configService: ConfigService, private imageService: ImagesService) {
16
- this.translator = new Translator(de);
17
- }
18
-
19
- async transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<OoyyoXmlItem> {
20
- const carId = toString(get(car, '_id', ''));
21
- const creationDate = get(car, 'metaData.creationDate') as number;
22
- const constructionYear = get(car, 'mainData.constructionYear') as number;
23
- const firstRegistration = get(car, 'mainData.firstRegistration') as number;
24
- const isNew = get(car, 'mainData.condition') === 'selector_condition_new';
25
- let year = firstRegistration ? moment(firstRegistration * 1000).format('YYYY') : constructionYear;
26
-
27
- if (!year && isNew) {
28
- year = moment().subtract(2, 'months').format('YYYY');
29
- }
30
-
31
- return {
32
- url: `https://www.${this.configService.config.domain}/search/vehicle/${carId}?source=classifieds&medium=listing&campaign=ooyyo`,
33
- title: this.getTitle(car),
34
- content: trim(toString(get(car, 'offer.offerDescription', ''))),
35
- price: toString(get(car, 'price.currentSalesPrice', '')),
36
- make: toString(get(car, 'mainData.make', '')),
37
- model: toString(get(car, 'mainData.model', '')),
38
- engine_size: toString(get(car, 'engineData.cubicCapacity', '')),
39
- trim: toString(get(car, 'mainData.subModel', '')),
40
- body_type: this.translateSelector(get(car, 'mainData.category', '')),
41
- color: this.translateSelector(get(car, 'exterior.exteriorColor', '')).replace('Außenfarbe ', ''),
42
- year: toString(year),
43
- mileage: toString(get(car, 'mainData.mileage', '')),
44
- fuel_type: this.translateSelector(get(car, 'consumption.fuel', '')),
45
- transmission: this.translateSelector(get(car, 'driveSuspension.gearbox', '')),
46
- euronorm: this.getEmissionClass(car),
47
- power: toString(get(car, 'engineData.powerKW', '')),
48
- doors: toString(get(car, 'mainData.doors', '')),
49
- seats: toString(get(car, 'mainData.seats', '')),
50
- gears: toString(get(car, 'driveSuspension.gears', '')),
51
- pictures: await this.imageService.getImages(car, imboImages, this.configService.config.imageType, false),
52
- location: {
53
- city: toString(get(car, 'location.city', '')),
54
- postcode: toString(get(car, 'location.zipCode', '')),
55
- region: toString(get(car, 'location.countryCode', '')),
56
- },
57
- vin: toString(get(car, 'metaData.vin', '')),
58
- is_new: this.getCondition(car),
59
- date: this.formatTimestamp(creationDate),
60
- time: this.formatTimestamp(creationDate, true),
61
- };
62
- }
63
-
64
- private getTitle(car: DataSchemes.Car): string {
65
- const year = toString(get(car, 'mainData.constructionYear', ''));
66
- const make = toString(get(car, 'mainData.make', ''));
67
- const model = toString(get(car, 'mainData.model', ''));
68
- const subModel = toString(get(car, 'mainData.subModel', ''));
69
- return trim(join([year, make, model, subModel], ' '));
70
- }
71
-
72
- private getCondition(car: DataSchemes.Car): string {
73
- const conditionSelector = get(car, 'mainData.condition', '');
74
- return conditionSelector === 'selector_condition_new' ? '1' : '0';
75
- }
76
-
77
- private translateSelector(selector: string): string {
78
- if (isEmpty(selector) || selector === 'selector_unknown') {
79
- return '';
80
- }
81
- return this.translator.translateVal(selector);
82
- }
83
-
84
- private getEmissionClass(car: DataSchemes.Car): string {
85
- const available = {
86
- selector_emissionClass_euro1: '1',
87
- selector_emissionClass_euro2: '2',
88
- selector_emissionClass_euro3: '3',
89
- selector_emissionClass_euro4: '4',
90
- selector_emissionClass_euro5: '5',
91
- selector_emissionClass_euro6: '6',
92
- selector_emissionClass_euro6b: '6b',
93
- selector_emissionClass_euro6c: '6c',
94
- selector_emissionClass_euro6d: '6d',
95
- selector_emissionClass_euro6d_temp: '6d-TEMP',
96
- selector_unknown: 'default',
97
- };
98
- const emissionClass = get(car, 'environmentEmissions.emissionClass', 'selector_unknown');
99
- return get(available, emissionClass);
100
- }
101
-
102
- private formatTimestamp(timestamp: number, onlyTime = false): string {
103
- if (!timestamp) {
104
- return '';
105
- }
106
- const format = onlyTime ? 'hh:mm:ss' : 'DD/MM/YYYY';
107
- return moment(timestamp * 1000).format(format);
108
- }
109
- }
1
+ import { Translator } from '@bytebrand/schema-tools';
2
+ import { de } from '@bytebrand/i18n-dictionaries';
3
+ import { get, toString, isEmpty, trim, join } from 'lodash';
4
+ import * as moment from 'moment';
5
+ import { DataSchemes } from '@bytebrand/car-schema';
6
+ import { OoyyoXmlItem } from '../interfaces';
7
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
8
+ import { ConfigService, ImagesService } from '../services';
9
+ import { Injectable } from '@nestjs/common';
10
+
11
+ @Injectable()
12
+ export class OoyyoTransformer {
13
+ private translator: Translator;
14
+
15
+ constructor(private configService: ConfigService, private imageService: ImagesService) {
16
+ this.translator = new Translator(de);
17
+ }
18
+
19
+ async transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<OoyyoXmlItem> {
20
+ const carId = toString(get(car, '_id', ''));
21
+ const creationDate = get(car, 'metaData.creationDate') as number;
22
+ const constructionYear = get(car, 'mainData.constructionYear') as number;
23
+ const firstRegistration = get(car, 'mainData.firstRegistration') as number;
24
+ const isNew = get(car, 'mainData.condition') === 'selector_condition_new';
25
+ let year = firstRegistration ? moment(firstRegistration * 1000).format('YYYY') : constructionYear;
26
+
27
+ if (!year && isNew) {
28
+ year = moment().subtract(2, 'months').format('YYYY');
29
+ }
30
+
31
+ return {
32
+ url: `https://www.${this.configService.config.domain}/search/vehicle/${carId}?source=classifieds&medium=listing&campaign=ooyyo`,
33
+ title: this.getTitle(car),
34
+ content: trim(toString(get(car, 'offer.offerDescription', ''))),
35
+ price: toString(get(car, 'price.currentSalesPrice', '')),
36
+ make: toString(get(car, 'mainData.make', '')),
37
+ model: toString(get(car, 'mainData.model', '')),
38
+ engine_size: toString(get(car, 'engineData.cubicCapacity', '')),
39
+ trim: toString(get(car, 'mainData.subModel', '')),
40
+ body_type: this.translateSelector(get(car, 'mainData.category', '')),
41
+ color: this.translateSelector(get(car, 'exterior.exteriorColor', '')).replace('Außenfarbe ', ''),
42
+ year: toString(year),
43
+ mileage: toString(get(car, 'mainData.mileage', '')),
44
+ fuel_type: this.translateSelector(get(car, 'consumption.fuel', '')),
45
+ transmission: this.translateSelector(get(car, 'driveSuspension.gearbox', '')),
46
+ euronorm: this.getEmissionClass(car),
47
+ power: toString(get(car, 'engineData.powerKW', '')),
48
+ doors: toString(get(car, 'mainData.doors', '')),
49
+ seats: toString(get(car, 'mainData.seats', '')),
50
+ gears: toString(get(car, 'driveSuspension.gears', '')),
51
+ pictures: await this.imageService.getImages(car, imboImages, this.configService.config.imageType, false),
52
+ location: {
53
+ city: toString(get(car, 'location.city', '')),
54
+ postcode: toString(get(car, 'location.zipCode', '')),
55
+ region: toString(get(car, 'location.countryCode', '')),
56
+ },
57
+ vin: toString(get(car, 'metaData.vin', '')),
58
+ is_new: this.getCondition(car),
59
+ date: this.formatTimestamp(creationDate),
60
+ time: this.formatTimestamp(creationDate, true),
61
+ };
62
+ }
63
+
64
+ private getTitle(car: DataSchemes.Car): string {
65
+ const year = toString(get(car, 'mainData.constructionYear', ''));
66
+ const make = toString(get(car, 'mainData.make', ''));
67
+ const model = toString(get(car, 'mainData.model', ''));
68
+ const subModel = toString(get(car, 'mainData.subModel', ''));
69
+ return trim(join([year, make, model, subModel], ' '));
70
+ }
71
+
72
+ private getCondition(car: DataSchemes.Car): string {
73
+ const conditionSelector = get(car, 'mainData.condition', '');
74
+ return conditionSelector === 'selector_condition_new' ? '1' : '0';
75
+ }
76
+
77
+ private translateSelector(selector: string): string {
78
+ if (isEmpty(selector) || selector === 'selector_unknown') {
79
+ return '';
80
+ }
81
+ return this.translator.translateVal(selector);
82
+ }
83
+
84
+ private getEmissionClass(car: DataSchemes.Car): string {
85
+ const available = {
86
+ selector_emissionClass_euro1: '1',
87
+ selector_emissionClass_euro2: '2',
88
+ selector_emissionClass_euro3: '3',
89
+ selector_emissionClass_euro4: '4',
90
+ selector_emissionClass_euro5: '5',
91
+ selector_emissionClass_euro6: '6',
92
+ selector_emissionClass_euro6b: '6b',
93
+ selector_emissionClass_euro6c: '6c',
94
+ selector_emissionClass_euro6d: '6d',
95
+ selector_emissionClass_euro6d_temp: '6d-TEMP',
96
+ selector_unknown: 'default',
97
+ };
98
+ const emissionClass = get(car, 'environmentEmissions.emissionClass', 'selector_unknown');
99
+ return get(available, emissionClass);
100
+ }
101
+
102
+ private formatTimestamp(timestamp: number, onlyTime = false): string {
103
+ if (!timestamp) {
104
+ return '';
105
+ }
106
+ const format = onlyTime ? 'hh:mm:ss' : 'DD/MM/YYYY';
107
+ return moment(timestamp * 1000).format(format);
108
+ }
109
+ }
@@ -1,200 +1,200 @@
1
- import { escape, get, isEmpty, isNumber, join, toNumber, toSafeInteger, toString, trim } from 'lodash';
2
- import { Injectable } from '@nestjs/common';
3
- import * as moment from 'moment/moment';
4
-
5
- import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
6
- import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
7
- import { ImboImageResponseInterface } from '@bytebrand/chunkable';
8
- import { TranslatorExtended } from '@bytebrand/schema-tools';
9
- import { DataSchemes } from '@bytebrand/car-schema';
10
-
11
- import { ConfigService, ImagesService, UserService } from '../services';
12
- import { RubrikkXmlItem } from '../interfaces';
13
-
14
- @Injectable()
15
- export class RubrikkTransformer {
16
- private translator: TranslatorExtended;
17
-
18
- constructor(
19
- private readonly configService: ConfigService,
20
- private readonly imageService: ImagesService,
21
- private readonly userService: UserService,
22
- ) {
23
- const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
24
- this.translator = new TranslatorExtended(dict);
25
- }
26
-
27
- async transform({
28
- car,
29
- images,
30
- }: {
31
- car: DataSchemes.Car;
32
- images: ImboImageResponseInterface[];
33
- }): Promise<RubrikkXmlItem> {
34
- return {
35
- //Common Fields
36
- ad__all_imageurls: await this.imageService.getImages(car, images, this.configService.config.imageType, false),
37
- ad__condition_new_used_etc: this.getCondition(car),
38
- ad__description: await this.getDescription(car),
39
- ad__headline: this.getTitle(car),
40
- ad__imageurl: this.getImageLink(car),
41
- ad__price: toNumber(get(car, 'price.currentSalesPrice', null)),
42
- ad__price_currency: toString(get(car, 'price.currency', 'EUR')),
43
- product__type: this.getCategory(car),
44
- ad__url: this.getCarLink(car),
45
- efficiency_class: this.getEnergyClass(car),
46
- ad__number_ad__number_reference_id: toString(get(car, 'metaData.vehicleId', '')),
47
-
48
- //Categorization
49
- category_original: 'Autos',
50
- maincategory_original: 'Fahrzeuge',
51
-
52
- //Advertiser Info
53
- advertiser__company_homepage_url: 'https://www.auto.de',
54
- advertiser__company_logo_url:
55
- 'https://autode-static.de/wp-content/themes/autode/front/img/header/b_logo_autode.svg',
56
- advertiser__email: 'auto@auto.de',
57
- advertiser__name_company_name: 'Auto.de',
58
- advertiser__phone: '+498004030182',
59
-
60
- // Geography Info
61
- location__country: 'Deutschland',
62
- location__municipality_city: get(car, 'location.city', ''),
63
- location__zip_postal_code: toString(get(car, 'location.zipCode', '')),
64
-
65
- // Motoring Fields
66
- motoring__body_type: this.translateSelector(get(car, 'mainData.category', '')),
67
- motoring__color: this.getColor(car),
68
- motoring__drivetrain: this.getDriveType(car),
69
- motoring__emission_class: this.translateSelector(get(car, 'environmentEmissions.emissionClass', '')),
70
- motoring__emission_co2: get(car, 'environmentEmissions.co2', null),
71
- motoring__emission_co2_unit: 'g/km',
72
- motoring__emission_sticker: this.translateSelector(get(car, 'environmentEmissions.emissionSticker', '')),
73
- motoring__engine_displacement_cubic_centimeters: toNumber(get(car, 'engineData.cubicCapacity', null)),
74
- motoring__fuel_consumption_combined: get(car, 'consumption.consumptionCombined', null),
75
- motoring__fuel_consumption_combined_unit: this.getUrbanUnit(car),
76
- motoring__fuel_consumption_extra_urban: get(car, 'consumption.consumptionOuter', null),
77
- motoring__fuel_consumption_extra_urban_unit: this.getUrbanUnit(car),
78
- motoring__fuel_consumption_urban: get(car, 'consumption.consumptionInner', null),
79
- motoring__fuel_consumption_urban_unit: this.getUrbanUnit(car),
80
- motoring__fuel_type: this.translateSelector(get(car, 'consumption.fuel', '')),
81
- motoring__make: toString(get(car, 'mainData.make', '')),
82
- motoring__mileage_kilometers: get(car, 'mainData.mileage', null),
83
- motoring__model: toString(get(car, 'mainData.model', '')),
84
- motoring__model_year: this.getYear(car),
85
- motoring__number_of_doors: get(car, 'mainData.doors', null),
86
- motoring__number_of_seats: get(car, 'mainData.seats', null),
87
- motoring__power_kw: get(car, 'engineData.powerKW', null),
88
- motoring__power_hp: get(car, 'engineData.powerPS', null),
89
- motoring__transmission: this.getDrivetrain(car),
90
- };
91
- }
92
-
93
- private getUrbanUnit(car: DataSchemes.Car) {
94
- const fuel_type = this.translateSelector(get(car, 'consumption.fuel', ''));
95
- return fuel_type === 'Elektro' ? 'kWt/100km' : 'l/100km';
96
- }
97
-
98
- private translateSelector(selector: string): string {
99
- if (isEmpty(selector) || selector === 'selector_unknown') {
100
- return '';
101
- }
102
- return this.translator.translateVal(selector);
103
- }
104
-
105
- private getTitle(car: DataSchemes.Car): string {
106
- const make = toString(get(car, 'mainData.make', ''));
107
- const model = toString(get(car, 'mainData.model', ''));
108
- const subModel = toString(get(car, 'mainData.subModel', ''));
109
- return trim(escape(join([make, model, subModel], ' ')));
110
- }
111
-
112
- private getCondition(car: DataSchemes.Car): string {
113
- const available = {
114
- selector_condition_new: 'Neu',
115
- selector_condition_used: 'Gebraucht',
116
- selector_unknown: 'Gebraucht',
117
- };
118
- const condition = get(car, 'mainData.condition', 'selector_unknown');
119
- return get(available, condition);
120
- }
121
-
122
- private getCategory(car: DataSchemes.Car): string {
123
- return this.translator.translateVal(get(car, 'mainData.category', ''));
124
- }
125
-
126
- private getCarLink(car: DataSchemes.Car): string {
127
- return `https://${this.configService.config.domain}/search/vehicle/${car._id}?source=classifieds&medium=listing&campaign=focus`;
128
- }
129
-
130
- private getImageLink(car: DataSchemes.Car): string {
131
- const mainImageId = get(car, 'metaData.mainImageId', '');
132
- return mainImageId
133
- ? `${this.configService.config.baseImageUrl}/carimage/${car._id}/${mainImageId}/large-cached.webp`
134
- : `${this.configService.config.baseImageUrl}/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg`;
135
- }
136
-
137
- private getEnergyClass(car: DataSchemes.Car): string {
138
- const available = {
139
- selector_energyEfficiencyClass_a: 'A',
140
- selector_energyEfficiencyClass_ap: 'A+',
141
- selector_energyEfficiencyClass_app: 'A++',
142
- selector_energyEfficiencyClass_appp: 'A+++',
143
- selector_energyEfficiencyClass_b: 'B',
144
- selector_energyEfficiencyClass_c: 'C',
145
- selector_energyEfficiencyClass_d: 'D',
146
- selector_energyEfficiencyClass_e: 'E',
147
- selector_energyEfficiencyClass_f: 'F',
148
- selector_energyEfficiencyClass_g: 'G',
149
- selector_unknown: 'default',
150
- };
151
- const energyClass = get(car, 'environmentEmissions.energyEfficiencyClass', 'selector_unknown');
152
- return get(available, energyClass);
153
- }
154
-
155
- private getColor(car: DataSchemes.Car): string {
156
- let colorSelection = get(car, 'exterior.exteriorColor', 'selector_unknown');
157
- if (!colorSelection || colorSelection === 'selector_unknown') {
158
- colorSelection = 'selector_unknown';
159
- }
160
- return this.translator.translateVal(colorSelection);
161
- }
162
-
163
- private getDrivetrain(car: DataSchemes.Car): string {
164
- const available = {
165
- selector_gearbox_manualShift: 'Manual',
166
- selector_gearbox_semiAutomatic: 'Automatic',
167
- selector_gearbox_automatic: 'Automatic',
168
- selector_unknown: 'N/A',
169
- };
170
- const transmission = get(car, 'driveSuspension.gearbox', 'selector_unknown');
171
- return get(available, transmission);
172
- }
173
-
174
- private getYear(car: DataSchemes.Car): string {
175
- const firstRegistration = get(car, 'mainData.firstRegistration') as number;
176
- if (isNumber(firstRegistration)) {
177
- return moment(firstRegistration * 1000).format('YYYY');
178
- }
179
- return moment().format('YYYY');
180
- }
181
-
182
- private getDriveType(car: DataSchemes.Car): string {
183
- const available = {
184
- selector_unknown: 'N/A',
185
- selector_driveType_frontWheelDrive: 'FWD',
186
- selector_driveType_rearWheelDrive: 'RWD',
187
- selector_driveType_allWheelDrive: 'AWD',
188
- };
189
-
190
- const driveType = get(car, 'driveSuspension.driveType', 'selector_unknown');
191
- return get(available, driveType) || 'N/A';
192
- }
193
-
194
- private async getDescription(car: DataSchemes.Car): Promise<string> {
195
- const dealerId = get(car, 'metaData.ownerId');
196
- const descriptionSchema = await this.userService.getDefaultSummaryByDealerId(dealerId);
197
- const descriptionBuilder = CarDescriptionFactory.create(DescriptionTypeEnum.Mobile, car);
198
- return descriptionBuilder.transform(descriptionSchema);
199
- }
200
- }
1
+ import { escape, get, isEmpty, isNumber, join, toNumber, toSafeInteger, toString, trim } from 'lodash';
2
+ import { Injectable } from '@nestjs/common';
3
+ import * as moment from 'moment/moment';
4
+
5
+ import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
6
+ import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
7
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
8
+ import { TranslatorExtended } from '@bytebrand/schema-tools';
9
+ import { DataSchemes } from '@bytebrand/car-schema';
10
+
11
+ import { ConfigService, ImagesService, UserService } from '../services';
12
+ import { RubrikkXmlItem } from '../interfaces';
13
+
14
+ @Injectable()
15
+ export class RubrikkTransformer {
16
+ private translator: TranslatorExtended;
17
+
18
+ constructor(
19
+ private readonly configService: ConfigService,
20
+ private readonly imageService: ImagesService,
21
+ private readonly userService: UserService,
22
+ ) {
23
+ const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
24
+ this.translator = new TranslatorExtended(dict);
25
+ }
26
+
27
+ async transform({
28
+ car,
29
+ images,
30
+ }: {
31
+ car: DataSchemes.Car;
32
+ images: ImboImageResponseInterface[];
33
+ }): Promise<RubrikkXmlItem> {
34
+ return {
35
+ //Common Fields
36
+ ad__all_imageurls: await this.imageService.getImages(car, images, this.configService.config.imageType, false),
37
+ ad__condition_new_used_etc: this.getCondition(car),
38
+ ad__description: await this.getDescription(car),
39
+ ad__headline: this.getTitle(car),
40
+ ad__imageurl: this.getImageLink(car),
41
+ ad__price: toNumber(get(car, 'price.currentSalesPrice', null)),
42
+ ad__price_currency: toString(get(car, 'price.currency', 'EUR')),
43
+ product__type: this.getCategory(car),
44
+ ad__url: this.getCarLink(car),
45
+ efficiency_class: this.getEnergyClass(car),
46
+ ad__number_ad__number_reference_id: toString(get(car, 'metaData.vehicleId', '')),
47
+
48
+ //Categorization
49
+ category_original: 'Autos',
50
+ maincategory_original: 'Fahrzeuge',
51
+
52
+ //Advertiser Info
53
+ advertiser__company_homepage_url: 'https://www.auto.de',
54
+ advertiser__company_logo_url:
55
+ 'https://autode-static.de/wp-content/themes/autode/front/img/header/b_logo_autode.svg',
56
+ advertiser__email: 'auto@auto.de',
57
+ advertiser__name_company_name: 'Auto.de',
58
+ advertiser__phone: '+498004030182',
59
+
60
+ // Geography Info
61
+ location__country: 'Deutschland',
62
+ location__municipality_city: get(car, 'location.city', ''),
63
+ location__zip_postal_code: toString(get(car, 'location.zipCode', '')),
64
+
65
+ // Motoring Fields
66
+ motoring__body_type: this.translateSelector(get(car, 'mainData.category', '')),
67
+ motoring__color: this.getColor(car),
68
+ motoring__drivetrain: this.getDriveType(car),
69
+ motoring__emission_class: this.translateSelector(get(car, 'environmentEmissions.emissionClass', '')),
70
+ motoring__emission_co2: get(car, 'environmentEmissions.co2', null),
71
+ motoring__emission_co2_unit: 'g/km',
72
+ motoring__emission_sticker: this.translateSelector(get(car, 'environmentEmissions.emissionSticker', '')),
73
+ motoring__engine_displacement_cubic_centimeters: toNumber(get(car, 'engineData.cubicCapacity', null)),
74
+ motoring__fuel_consumption_combined: get(car, 'consumption.consumptionCombined', null),
75
+ motoring__fuel_consumption_combined_unit: this.getUrbanUnit(car),
76
+ motoring__fuel_consumption_extra_urban: get(car, 'consumption.consumptionOuter', null),
77
+ motoring__fuel_consumption_extra_urban_unit: this.getUrbanUnit(car),
78
+ motoring__fuel_consumption_urban: get(car, 'consumption.consumptionInner', null),
79
+ motoring__fuel_consumption_urban_unit: this.getUrbanUnit(car),
80
+ motoring__fuel_type: this.translateSelector(get(car, 'consumption.fuel', '')),
81
+ motoring__make: toString(get(car, 'mainData.make', '')),
82
+ motoring__mileage_kilometers: get(car, 'mainData.mileage', null),
83
+ motoring__model: toString(get(car, 'mainData.model', '')),
84
+ motoring__model_year: this.getYear(car),
85
+ motoring__number_of_doors: get(car, 'mainData.doors', null),
86
+ motoring__number_of_seats: get(car, 'mainData.seats', null),
87
+ motoring__power_kw: get(car, 'engineData.powerKW', null),
88
+ motoring__power_hp: get(car, 'engineData.powerPS', null),
89
+ motoring__transmission: this.getDrivetrain(car),
90
+ };
91
+ }
92
+
93
+ private getUrbanUnit(car: DataSchemes.Car) {
94
+ const fuel_type = this.translateSelector(get(car, 'consumption.fuel', ''));
95
+ return fuel_type === 'Elektro' ? 'kWt/100km' : 'l/100km';
96
+ }
97
+
98
+ private translateSelector(selector: string): string {
99
+ if (isEmpty(selector) || selector === 'selector_unknown') {
100
+ return '';
101
+ }
102
+ return this.translator.translateVal(selector);
103
+ }
104
+
105
+ private getTitle(car: DataSchemes.Car): string {
106
+ const make = toString(get(car, 'mainData.make', ''));
107
+ const model = toString(get(car, 'mainData.model', ''));
108
+ const subModel = toString(get(car, 'mainData.subModel', ''));
109
+ return trim(escape(join([make, model, subModel], ' ')));
110
+ }
111
+
112
+ private getCondition(car: DataSchemes.Car): string {
113
+ const available = {
114
+ selector_condition_new: 'Neu',
115
+ selector_condition_used: 'Gebraucht',
116
+ selector_unknown: 'Gebraucht',
117
+ };
118
+ const condition = get(car, 'mainData.condition', 'selector_unknown');
119
+ return get(available, condition);
120
+ }
121
+
122
+ private getCategory(car: DataSchemes.Car): string {
123
+ return this.translator.translateVal(get(car, 'mainData.category', ''));
124
+ }
125
+
126
+ private getCarLink(car: DataSchemes.Car): string {
127
+ return `https://${this.configService.config.domain}/search/vehicle/${car._id}?source=classifieds&medium=listing&campaign=focus`;
128
+ }
129
+
130
+ private getImageLink(car: DataSchemes.Car): string {
131
+ const mainImageId = get(car, 'metaData.mainImageId', '');
132
+ return mainImageId
133
+ ? `${this.configService.config.baseImageUrl}/carimage/${car._id}/${mainImageId}/large-cached.webp`
134
+ : `${this.configService.config.baseImageUrl}/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg`;
135
+ }
136
+
137
+ private getEnergyClass(car: DataSchemes.Car): string {
138
+ const available = {
139
+ selector_energyEfficiencyClass_a: 'A',
140
+ selector_energyEfficiencyClass_ap: 'A+',
141
+ selector_energyEfficiencyClass_app: 'A++',
142
+ selector_energyEfficiencyClass_appp: 'A+++',
143
+ selector_energyEfficiencyClass_b: 'B',
144
+ selector_energyEfficiencyClass_c: 'C',
145
+ selector_energyEfficiencyClass_d: 'D',
146
+ selector_energyEfficiencyClass_e: 'E',
147
+ selector_energyEfficiencyClass_f: 'F',
148
+ selector_energyEfficiencyClass_g: 'G',
149
+ selector_unknown: 'default',
150
+ };
151
+ const energyClass = get(car, 'environmentEmissions.energyEfficiencyClass', 'selector_unknown');
152
+ return get(available, energyClass);
153
+ }
154
+
155
+ private getColor(car: DataSchemes.Car): string {
156
+ let colorSelection = get(car, 'exterior.exteriorColor', 'selector_unknown');
157
+ if (!colorSelection || colorSelection === 'selector_unknown') {
158
+ colorSelection = 'selector_unknown';
159
+ }
160
+ return this.translator.translateVal(colorSelection);
161
+ }
162
+
163
+ private getDrivetrain(car: DataSchemes.Car): string {
164
+ const available = {
165
+ selector_gearbox_manualShift: 'Manual',
166
+ selector_gearbox_semiAutomatic: 'Automatic',
167
+ selector_gearbox_automatic: 'Automatic',
168
+ selector_unknown: 'N/A',
169
+ };
170
+ const transmission = get(car, 'driveSuspension.gearbox', 'selector_unknown');
171
+ return get(available, transmission);
172
+ }
173
+
174
+ private getYear(car: DataSchemes.Car): string {
175
+ const firstRegistration = get(car, 'mainData.firstRegistration') as number;
176
+ if (isNumber(firstRegistration)) {
177
+ return moment(firstRegistration * 1000).format('YYYY');
178
+ }
179
+ return moment().format('YYYY');
180
+ }
181
+
182
+ private getDriveType(car: DataSchemes.Car): string {
183
+ const available = {
184
+ selector_unknown: 'N/A',
185
+ selector_driveType_frontWheelDrive: 'FWD',
186
+ selector_driveType_rearWheelDrive: 'RWD',
187
+ selector_driveType_allWheelDrive: 'AWD',
188
+ };
189
+
190
+ const driveType = get(car, 'driveSuspension.driveType', 'selector_unknown');
191
+ return get(available, driveType) || 'N/A';
192
+ }
193
+
194
+ private async getDescription(car: DataSchemes.Car): Promise<string> {
195
+ const dealerId = get(car, 'metaData.ownerId');
196
+ const descriptionSchema = await this.userService.getDefaultSummaryByDealerId(dealerId);
197
+ const descriptionBuilder = CarDescriptionFactory.create(DescriptionTypeEnum.Mobile, car);
198
+ return descriptionBuilder.transform(descriptionSchema);
199
+ }
200
+ }