@bytebrand/export-cars 1.7.1 → 1.9.0

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 (146) hide show
  1. package/dist/app.module.js +7 -5
  2. package/dist/app.module.js.map +1 -1
  3. package/dist/configs/alleskralle.config.js +3 -1
  4. package/dist/configs/alleskralle.config.js.map +1 -1
  5. package/dist/configs/as24.config.js.map +1 -1
  6. package/dist/configs/autoboerse.config.js +1 -1
  7. package/dist/configs/autouncle.config.js +1 -1
  8. package/dist/configs/config.d.ts +3 -1
  9. package/dist/configs/config.js +6 -4
  10. package/dist/configs/config.js.map +1 -1
  11. package/dist/configs/criteo.config.js +2 -1
  12. package/dist/configs/criteo.config.js.map +1 -1
  13. package/dist/configs/dasparking.config.js +1 -1
  14. package/dist/configs/facebook-shop.config.d.ts +5 -0
  15. package/dist/configs/facebook-shop.config.js +17 -0
  16. package/dist/configs/facebook-shop.config.js.map +1 -0
  17. package/dist/configs/index.d.ts +1 -0
  18. package/dist/configs/index.js +1 -0
  19. package/dist/configs/index.js.map +1 -1
  20. package/dist/configs/kleinanzeigefocus.config.js +2 -2
  21. package/dist/configs/kleinanzeigefocus.config.js.map +1 -1
  22. package/dist/configs/meinstadt.config.js +0 -1
  23. package/dist/configs/meinstadt.config.js.map +1 -1
  24. package/dist/configs/ooyyo.config.js +1 -0
  25. package/dist/configs/ooyyo.config.js.map +1 -1
  26. package/dist/constants/modix/index.d.ts +1 -0
  27. package/dist/constants/modix/index.js +1 -0
  28. package/dist/constants/modix/index.js.map +1 -1
  29. package/dist/enums/export-type.enum.d.ts +2 -1
  30. package/dist/enums/export-type.enum.js +1 -0
  31. package/dist/enums/export-type.enum.js.map +1 -1
  32. package/dist/enums/file-types.enum.js +0 -1
  33. package/dist/enums/file-types.enum.js.map +1 -1
  34. package/dist/enums/image-type.enum.d.ts +4 -0
  35. package/dist/enums/image-type.enum.js +9 -0
  36. package/dist/enums/image-type.enum.js.map +1 -0
  37. package/dist/enums/index.d.ts +2 -0
  38. package/dist/enums/index.js +2 -0
  39. package/dist/enums/index.js.map +1 -1
  40. package/dist/export.schema.d.ts +6 -2
  41. package/dist/export.schema.js +4 -0
  42. package/dist/export.schema.js.map +1 -1
  43. package/dist/exporters/auto24.exporter.js +1 -1
  44. package/dist/exporters/auto24.exporter.js.map +1 -1
  45. package/dist/exporters/facebook-shop.exporter.d.ts +12 -0
  46. package/dist/exporters/facebook-shop.exporter.js +63 -0
  47. package/dist/exporters/facebook-shop.exporter.js.map +1 -0
  48. package/dist/exporters/fb.exporter.js +1 -3
  49. package/dist/exporters/fb.exporter.js.map +1 -1
  50. package/dist/exporters/index.d.ts +1 -0
  51. package/dist/exporters/index.js +1 -0
  52. package/dist/exporters/index.js.map +1 -1
  53. package/dist/exporters/modix.exporter.js.map +1 -1
  54. package/dist/exporters/ooyyo.exporter.js +1 -1
  55. package/dist/exporters/ooyyo.exporter.js.map +1 -1
  56. package/dist/formats/facebook-shop.builder.d.ts +10 -0
  57. package/dist/formats/facebook-shop.builder.js +62 -0
  58. package/dist/formats/facebook-shop.builder.js.map +1 -0
  59. package/dist/formats/index.d.ts +1 -0
  60. package/dist/formats/index.js +1 -0
  61. package/dist/formats/index.js.map +1 -1
  62. package/dist/interfaces/export-item.interface.d.ts +26 -0
  63. package/dist/interfaces/params.interface.d.ts +1 -7
  64. package/dist/services/{marketing-images.service.d.ts → images.service.d.ts} +9 -5
  65. package/dist/services/images.service.js +151 -0
  66. package/dist/services/images.service.js.map +1 -0
  67. package/dist/services/index.d.ts +1 -1
  68. package/dist/services/index.js +1 -1
  69. package/dist/services/index.js.map +1 -1
  70. package/dist/transformers/auto24.transfomer.d.ts +4 -6
  71. package/dist/transformers/auto24.transfomer.js +10 -27
  72. package/dist/transformers/auto24.transfomer.js.map +1 -1
  73. package/dist/transformers/autouncle.transformer.d.ts +5 -5
  74. package/dist/transformers/autouncle.transformer.js +10 -34
  75. package/dist/transformers/autouncle.transformer.js.map +1 -1
  76. package/dist/transformers/facebook-shop.transformer.d.ts +18 -0
  77. package/dist/transformers/facebook-shop.transformer.js +96 -0
  78. package/dist/transformers/facebook-shop.transformer.js.map +1 -0
  79. package/dist/transformers/fb.transformer.d.ts +2 -3
  80. package/dist/transformers/fb.transformer.js +8 -26
  81. package/dist/transformers/fb.transformer.js.map +1 -1
  82. package/dist/transformers/google.transformer.d.ts +5 -5
  83. package/dist/transformers/google.transformer.js +10 -26
  84. package/dist/transformers/google.transformer.js.map +1 -1
  85. package/dist/transformers/index.d.ts +1 -0
  86. package/dist/transformers/index.js +1 -0
  87. package/dist/transformers/index.js.map +1 -1
  88. package/dist/transformers/meinstadt.transformer.d.ts +1 -1
  89. package/dist/transformers/meinstadt.transformer.js +3 -4
  90. package/dist/transformers/meinstadt.transformer.js.map +1 -1
  91. package/dist/transformers/modix.transformer.d.ts +1 -1
  92. package/dist/transformers/modix.transformer.js +3 -4
  93. package/dist/transformers/modix.transformer.js.map +1 -1
  94. package/dist/transformers/ooyyo.transformer.d.ts +4 -5
  95. package/dist/transformers/ooyyo.transformer.js +7 -17
  96. package/dist/transformers/ooyyo.transformer.js.map +1 -1
  97. package/dist/transformers/rubrikk.transformer.d.ts +4 -4
  98. package/dist/transformers/rubrikk.transformer.js +5 -13
  99. package/dist/transformers/rubrikk.transformer.js.map +1 -1
  100. package/dist/tsconfig.build.tsbuildinfo +1 -1
  101. package/package.json +2 -2
  102. package/src/app.module.ts +6 -12
  103. package/src/configs/alleskralle.config.ts +3 -1
  104. package/src/configs/as24.config.ts +1 -1
  105. package/src/configs/auto24.config.ts +1 -1
  106. package/src/configs/autoboerse.config.ts +2 -2
  107. package/src/configs/autouncle.config.ts +1 -1
  108. package/src/configs/config.ts +3 -2
  109. package/src/configs/criteo.config.ts +3 -2
  110. package/src/configs/dasparking.config.ts +1 -1
  111. package/src/configs/{kleinanzeigefocus.config.ts → facebook-shop.config.ts} +3 -3
  112. package/src/configs/index.ts +1 -0
  113. package/src/configs/kleinanzeigeFocus.config.ts +14 -0
  114. package/src/configs/meinstadt.config.ts +1 -1
  115. package/src/configs/ooyyo.config.ts +2 -1
  116. package/src/constants/modix/index.ts +1 -0
  117. package/src/enums/export-type.enum.ts +7 -6
  118. package/src/enums/file-types.enum.ts +1 -1
  119. package/src/enums/image-type.enum.ts +4 -0
  120. package/src/enums/index.ts +2 -0
  121. package/src/export.schema.ts +8 -3
  122. package/src/exporters/auto24.exporter.ts +2 -4
  123. package/src/exporters/facebook-shop.exporter.ts +51 -0
  124. package/src/exporters/fb.exporter.ts +6 -6
  125. package/src/exporters/index.ts +1 -0
  126. package/src/exporters/modix.exporter.ts +6 -5
  127. package/src/exporters/ooyyo.exporter.ts +3 -4
  128. package/src/formats/facebook-shop.builder.ts +69 -0
  129. package/src/formats/index.ts +1 -0
  130. package/src/interfaces/export-item.interface.ts +26 -0
  131. package/src/interfaces/params.interface.ts +1 -7
  132. package/src/services/images.service.ts +161 -0
  133. package/src/services/index.ts +1 -2
  134. package/src/transformers/auto24.transfomer.ts +8 -31
  135. package/src/transformers/autouncle.transformer.ts +9 -35
  136. package/src/transformers/facebook-shop.transformer.ts +94 -0
  137. package/src/transformers/fb.transformer.ts +16 -44
  138. package/src/transformers/google.transformer.ts +10 -28
  139. package/src/transformers/index.ts +1 -0
  140. package/src/transformers/meinstadt.transformer.ts +2 -3
  141. package/src/transformers/modix.transformer.ts +19 -10
  142. package/src/transformers/ooyyo.transformer.ts +4 -18
  143. package/src/transformers/rubrikk.transformer.ts +5 -16
  144. package/dist/services/marketing-images.service.js +0 -58
  145. package/dist/services/marketing-images.service.js.map +0 -1
  146. package/src/services/marketing-images.service.ts +0 -70
@@ -0,0 +1,161 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { DataSchemes } from '@bytebrand/car-schema';
3
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
4
+ import { get, toString } from 'lodash';
5
+ import { isNotEmptyArray } from '../utils/validator.utils';
6
+ import { ConfigService } from './config.service';
7
+ import { ImageType } from '../enums';
8
+ import { MarketingImageConfigInterface, MarketingImageConfigsInterface } from '@bytebrand/autode-request';
9
+ import { UserService } from './user.service';
10
+ import { FB_MAX_IMAGE_COUNT_FOR_DEAFULT } from '../constants/fb.constants';
11
+
12
+ @Injectable()
13
+ export class ImagesService {
14
+ constructor(private readonly configService: ConfigService, private readonly userService: UserService) {}
15
+
16
+ async getImages(
17
+ car: DataSchemes.Car,
18
+ images: ImboImageResponseInterface[],
19
+ imageType: ImageType,
20
+ ): Promise<Array<string>> {
21
+ if (imageType === ImageType.default) {
22
+ return this.getDefaultImages(car, images);
23
+ } else {
24
+ const carId = toString(get(car, '_id', ''));
25
+ return await this.getMarketingImages(images, carId);
26
+ }
27
+ }
28
+
29
+ getDefaultImages(car: DataSchemes.Car, images: ImboImageResponseInterface[]): Array<string> {
30
+ const defaultImages = [
31
+ 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
32
+ 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg',
33
+ 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg',
34
+ 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg',
35
+ ];
36
+
37
+ if (!isNotEmptyArray(images)) {
38
+ return defaultImages;
39
+ }
40
+
41
+ const firstImageId = get(car, 'metaData.mainImageId', null);
42
+ const secondImageId = get(car, 'metaData.secImageId', null);
43
+ const thirdImageId = get(car, 'metaData.thirdImageId', null);
44
+
45
+ if (firstImageId) {
46
+ images.forEach((image, index) => {
47
+ if (firstImageId === image.imageIdentifier) {
48
+ const tmp = images[index];
49
+ images[index] = images[0];
50
+ images[0] = tmp;
51
+ }
52
+ });
53
+ }
54
+
55
+ if (secondImageId) {
56
+ images.forEach((image, index) => {
57
+ if (secondImageId === image.imageIdentifier) {
58
+ const tmp = images[index];
59
+ images[index] = images[1];
60
+ images[1] = tmp;
61
+ }
62
+ });
63
+ }
64
+
65
+ if (thirdImageId) {
66
+ images.forEach((image, index) => {
67
+ if (thirdImageId === image.imageIdentifier) {
68
+ const tmp = images[index];
69
+ images[index] = images[2];
70
+ images[2] = tmp;
71
+ }
72
+ });
73
+ }
74
+
75
+ const carId = toString(get(car, '_id', ''));
76
+
77
+ const transformedImages = this.generateImageLinks(images, carId);
78
+ if (transformedImages.length < 17) {
79
+ transformedImages.push(...defaultImages);
80
+ }
81
+ return transformedImages;
82
+ }
83
+
84
+ generateImageLinks(images: ImboImageResponseInterface[], carId: string) {
85
+ return images.map((image: ImboImageResponseInterface) => {
86
+ return `${this.configService.config.baseImageUrl}/carimage/${carId}/${image.imageIdentifier}/large`;
87
+ });
88
+ }
89
+
90
+ async getMarketingImages(images: any, carId: string): Promise<string[]> {
91
+ const imageUrl = this.configService.config.imageUrl;
92
+ const transformedImages = this.transformImagesArrayIntoObject(images);
93
+ const configs = this.configService.config.isCriteo
94
+ ? await this.userService.getMarketingImageConfig(this.configService.config.criteoMarketingImagesConfigId)
95
+ : ((await this.getMarketingImageConfigs()) as any);
96
+ const marketingImageConfigs = this.transform(configs);
97
+
98
+ const defImages = [
99
+ { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
100
+ { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
101
+ { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
102
+ { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
103
+ ];
104
+
105
+ const imageUrls = [];
106
+
107
+ for (let i = 0; i < marketingImageConfigs.length; i++) {
108
+ const marketingImage = marketingImageConfigs[i];
109
+ for (let i = 0; i < marketingImage.marketingImageCodes.length; i++) {
110
+ const imageCode = marketingImage.marketingImageCodes[i];
111
+ const imageId = transformedImages[imageCode];
112
+ if (imageId) {
113
+ imageUrls.push(this.getImagePathWithExtenstion(imageUrl, carId, imageId, configs));
114
+ break;
115
+ }
116
+ }
117
+ }
118
+ if (imageUrls.length < FB_MAX_IMAGE_COUNT_FOR_DEAFULT) {
119
+ imageUrls.push(...defImages);
120
+ }
121
+ return imageUrls;
122
+ }
123
+
124
+ async getMarketingImageConfigs(): Promise<MarketingImageConfigsInterface> {
125
+ const configs = await this.userService.getMarketingImageConfigs();
126
+ const { id } = configs.find(config => config.channelCode.includes(this.configService.config.exportType));
127
+
128
+ return this.userService.getMarketingImageConfig(id);
129
+ }
130
+
131
+ private transformImagesArrayIntoObject(images: { [imageCode: string]: string }[]) {
132
+ const result: { [imageCode: string]: string } = {};
133
+ images.forEach(image => {
134
+ const imageCode = image.imageCodePredicted.split('-')[0];
135
+ result[imageCode] = image.imageIdentifier;
136
+ });
137
+ return result;
138
+ }
139
+
140
+ private transform(config: MarketingImageConfigInterface): { marketingImageCodes: string[] }[] {
141
+ return config.marketingImages.map(marketingImage => {
142
+ return {
143
+ marketingImageCodes: marketingImage.imageCodes,
144
+ };
145
+ });
146
+ }
147
+
148
+ protected getChannelPath(imageUrl: string, carId: string): string {
149
+ return `${imageUrl}/${[carId[0], carId[1], carId[2], carId].join('/')}`;
150
+ }
151
+
152
+ protected getImagePathWithExtenstion(
153
+ imageUrl: string,
154
+ carId: string,
155
+ imageId: string,
156
+ config: MarketingImageConfigsInterface,
157
+ ): string {
158
+ const { channelCode, imageExtension } = config;
159
+ return `${this.getChannelPath(imageUrl, carId)}/${channelCode.replace(/ /g, '-')}-${imageId}.${imageExtension}`;
160
+ }
161
+ }
@@ -5,5 +5,4 @@ export * from './loader.service';
5
5
  export * from './config.service';
6
6
  export * from './request.service';
7
7
  export * from './mapping.service';
8
- export * from './marketing-images.service';
9
-
8
+ export * from './images.service';
@@ -1,25 +1,26 @@
1
1
  import { Translator } from '@bytebrand/schema-tools';
2
2
  import { de } from '@bytebrand/i18n-dictionaries';
3
- import { get, toString, isNil, isEmpty, first } from 'lodash';
3
+ import { get, isEmpty, isNil, toString } from 'lodash';
4
4
  import * as moment from 'moment';
5
5
  import { DataSchemes } from '@bytebrand/car-schema';
6
6
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
7
7
  import { Auto24XmlItem } from '../interfaces';
8
8
  import { Injectable } from '@nestjs/common';
9
- import { ConfigService } from '../services/config.service';
9
+ import { ConfigService, ImagesService } from '../services';
10
10
  import { isNotEmptyArray } from '../utils/validator.utils';
11
+ import { ImageType } from '../enums';
11
12
 
12
13
  @Injectable()
13
14
  export class Auto24Transformer {
14
15
  private translator: Translator;
15
16
 
16
- constructor(private configService: ConfigService) {
17
+ constructor(private configService: ConfigService, private readonly imageService: ImagesService) {
17
18
  this.translator = new Translator(de);
18
19
  }
19
20
 
20
- transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Auto24XmlItem {
21
+ async transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<Auto24XmlItem> {
21
22
  const carId = toString(get(car, '_id', ''));
22
-
23
+ const transformedImages = await this.imageService.getImages(car, imboImages, ImageType.default);
23
24
  let userlink = `https://www.${this.configService.config.domain}/search/vehicle/${carId}`;
24
25
  if (this.configService.config.campaign) {
25
26
  userlink += `?source=classifieds&medium=listing&campaign=${this.configService.config.campaign}`;
@@ -37,9 +38,9 @@ export class Auto24Transformer {
37
38
  consumptionK: toString(get(car, 'consumption.consumptionCombined', '')),
38
39
  co2: toString(get(car, 'environmentEmissions.co2', '')),
39
40
  efficiencyclass: this.translateSelector(get(car, 'environmentEmissions.energyEfficiencyClass', '')),
40
- image: this.getImageField(carId, toString(get(car, 'metaData.mainImageId')), imboImages),
41
+ image: transformedImages[0],
41
42
  registration: this.getRegistrationField(get(car, 'mainData.firstRegistration') as number),
42
- images: this.getImagesField(carId, imboImages),
43
+ images: transformedImages,
43
44
  price: toString(get(car, 'price.currentSalesPrice', '')),
44
45
  power: toString(get(car, 'engineData.powerKW', '')),
45
46
  zip: toString(get(car, 'location.zipCode', '')),
@@ -132,28 +133,4 @@ export class Auto24Transformer {
132
133
  })
133
134
  .join(', ');
134
135
  }
135
-
136
- private getImagesField(carId: string, images: ImboImageResponseInterface[]): string[] {
137
- if (isNotEmptyArray(images)) {
138
- return images.map((image: ImboImageResponseInterface) => {
139
- return this.buildLargeImageUrl(carId, image.imageIdentifier);
140
- });
141
- }
142
- return [];
143
- }
144
-
145
- private getImageField(carId: string, mainImageId: string, images: ImboImageResponseInterface[]): string {
146
- if (isNil(mainImageId) || isEmpty(mainImageId)) {
147
- if (isNotEmptyArray(images)) {
148
- const firstImageId = first(images);
149
- return this.buildLargeImageUrl(carId, firstImageId.imageIdentifier);
150
- }
151
- return '';
152
- }
153
- return this.buildLargeImageUrl(carId, mainImageId);
154
- }
155
-
156
- private buildLargeImageUrl(carId: string, imageId: string): string {
157
- return `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`;
158
- }
159
136
  }
@@ -5,18 +5,18 @@ import * as moment from 'moment';
5
5
  import { DataSchemes } from '@bytebrand/car-schema';
6
6
  import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
7
7
  import { DePostalCodesEntryInterface } from '@bytebrand/car-basic-data-scope/dist/interfaces/DePostalCodesInterface';
8
- import { ConfigService } from '../services/config.service';
8
+ import { ConfigService, ImagesService } from '../services';
9
9
  import { Injectable } from '@nestjs/common';
10
10
  import { DEFAULT_ADDR1, DEFAULT_CITY, DEFAULT_ZIP, MIN_MILEAGES } from '../constants/autouncle.contants';
11
11
  import { AutouncleJsonItem } from '../interfaces';
12
- import { isNotEmptyArray } from '../utils/validator.utils';
12
+ import { ImboImageResponseInterface } from '@bytebrand/chunkable';
13
13
 
14
14
  @Injectable()
15
15
  export class AutouncleTransformer {
16
16
  private translator: TranslatorExtended;
17
17
  private postalCodesService: DePostalCodesService;
18
18
 
19
- constructor(private configService: ConfigService) {
19
+ constructor(private configService: ConfigService, private imageService: ImagesService) {
20
20
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
21
21
  this.translator = new TranslatorExtended(dict);
22
22
  this.postalCodesService = DePostalCodesService.getInstance();
@@ -28,7 +28,7 @@ export class AutouncleTransformer {
28
28
  owner,
29
29
  }: {
30
30
  car: DataSchemes.Car;
31
- images: unknown[];
31
+ images: ImboImageResponseInterface[];
32
32
  metadata?: unknown;
33
33
  owner: unknown;
34
34
  }): Promise<AutouncleJsonItem> {
@@ -61,7 +61,7 @@ export class AutouncleTransformer {
61
61
  seller_name: 'auto.de',
62
62
  seller_id: toString(get(car, 'metaData.ownerId', '')),
63
63
  description: toString(get(car, 'offer.offerDescription', '')),
64
- images: this.getImagesField(autodeId, get(car, 'metaData.mainImageId', null), images),
64
+ images: this.getImagesField(car, images),
65
65
  fuel_economy: toString(get(car, 'consumption.consumptionCombined', '')),
66
66
  co2_emission: toString(get(car, 'environmentEmissions.co2', '')),
67
67
  co2_effiency_class: toString(get(car, 'environmentEmissions.energyEfficiencyClass', '')),
@@ -230,35 +230,9 @@ export class AutouncleTransformer {
230
230
  return '';
231
231
  }
232
232
 
233
- private getImagesField(carId: string, mainImageId: string, images: unknown[]): { url: string }[] {
234
- const defImages = [
235
- { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
236
- { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
237
- { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
238
- { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
239
- ];
240
- if (isNotEmptyArray(images)) {
241
- const imageList = images.sort(this.setMainImageFirst(mainImageId)).map((image: any) => {
242
- return { url: this.buildLargeImageUrl(carId, image.imageIdentifier) };
243
- });
244
-
245
- if (imageList.length < 17) {
246
- imageList.push(...defImages);
247
- }
248
- return imageList;
249
- }
250
- return defImages;
251
- }
252
-
253
- private buildLargeImageUrl(carId: string, imageId: string): string {
254
- return `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`;
255
- }
256
-
257
- private setMainImageFirst(mainImageId: string): (current: any, next: any) => number {
258
- return (current: any, next: any): number => {
259
- if (current.imageIdentifier === mainImageId) return -1;
260
- if (next.imageIdentifier === mainImageId) return 1;
261
- return 0;
262
- };
233
+ private getImagesField(car: DataSchemes.Car, images: ImboImageResponseInterface[]): { url: string }[] {
234
+ return this.imageService.getDefaultImages(car, images).map(url => {
235
+ return { url };
236
+ });
263
237
  }
264
238
  }
@@ -0,0 +1,94 @@
1
+ import { Injectable } from '@nestjs/common';
2
+
3
+ import { escape, get, join, round, toString, trim } from 'lodash';
4
+
5
+ import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
6
+ import { TranslatorExtended } from '@bytebrand/schema-tools';
7
+ import { DataSchemes } from '@bytebrand/car-schema';
8
+
9
+ import { FacebookShopItem } from '../interfaces';
10
+ import { ConfigService } from '../services';
11
+ import { Description } from '../interfaces/description.interface';
12
+ import { FbDescription } from './fb-description.transformer';
13
+ import { FbEquipment } from './fb-equipment.transformer';
14
+
15
+ @Injectable()
16
+ export class FacebookShopTransformer {
17
+ private translator: TranslatorExtended;
18
+
19
+ constructor(private readonly configService: ConfigService) {
20
+ const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
21
+ this.translator = new TranslatorExtended(dict);
22
+ }
23
+
24
+ async transform({ car }: { car: DataSchemes.Car }): Promise<FacebookShopItem> {
25
+ return {
26
+ id: { value: get(car, 'metaData.vehicleId'), isGoogle: true },
27
+ title: { value: this.getTitle(car), isGoogle: true },
28
+ description: { value: this.getDescription(car), isGoogle: true },
29
+ availability: { value: 'in stock', isGoogle: true },
30
+ condition: { value: this.getCondition(car), isGoogle: true },
31
+ price: { value: this.getPrice(car), isGoogle: true },
32
+ link: { value: this.getCarLink(car), isGoogle: true },
33
+ image_link: { value: this.getImageLink(car), isGoogle: true },
34
+ brand: { value: get(car, 'mainData.make', ''), isGoogle: true },
35
+ additional_image_link: { value: this.getImageLink(car), isGoogle: false },
36
+ quantity_to_sell_on_facebook: { value: 1, isGoogle: true },
37
+ google_product_category: { value: '916', isGoogle: true },
38
+ sale_price: { value: this.getPrice(car), isGoogle: true },
39
+ status: { value: 'active', isGoogle: true },
40
+ color: { value: this.getColor(car), isGoogle: false },
41
+ product_type: {
42
+ value: 'Vehicles &amp; Parts > Vehicles > Motor Vehicles > Cars, Trucks &amp; Vans',
43
+ isGoogle: true,
44
+ },
45
+ };
46
+ }
47
+
48
+ private getTitle(car: DataSchemes.Car): string {
49
+ const year = toString(get(car, 'mainData.constructionYear', ''));
50
+ const make = toString(get(car, 'mainData.make', ''));
51
+ const model = toString(get(car, 'mainData.model', ''));
52
+ const subModel = toString(get(car, 'mainData.subModel', ''));
53
+ return trim(escape(join([year, make, model, subModel], ' ')));
54
+ }
55
+
56
+ private getCondition(car: DataSchemes.Car): string {
57
+ const available = {
58
+ selector_condition_new: 'New',
59
+ selector_condition_used: 'Used',
60
+ selector_unknown: 'New',
61
+ };
62
+ const condition = get(car, 'mainData.condition', 'selector_unknown');
63
+ return get(available, condition);
64
+ }
65
+
66
+ private getCarLink(car: DataSchemes.Car): string {
67
+ return `https://${this.configService.config.domain}/search/vehicle/${car._id}`;
68
+ }
69
+
70
+ private getPrice(car: DataSchemes.Car): string {
71
+ const price = get(car, 'price.currentSalesPrice', 0);
72
+ return `${round(price, 2)} EUR`;
73
+ }
74
+
75
+ private getColor(car: DataSchemes.Car): string {
76
+ let colorSelection = get(car, 'exterior.exteriorColor', 'selector_unknown');
77
+ if (!colorSelection || colorSelection === 'selector_unknown') {
78
+ colorSelection = 'selector_unknown';
79
+ }
80
+ return this.translator.translateVal(colorSelection);
81
+ }
82
+
83
+ private getDescription(car: DataSchemes.Car): Description[] {
84
+ return FbDescription.create(car, this.translator, new FbEquipment()).getDescriptionArray();
85
+ }
86
+
87
+ //todo: move to image service
88
+ private getImageLink(car: DataSchemes.Car): string {
89
+ const mainImageId = get(car, 'metaData.mainImageId', '');
90
+ return mainImageId
91
+ ? `${this.configService.config.baseImageUrl}/carimage/${car._id}/${mainImageId}/large-cached.webp`
92
+ : `${this.configService.config.baseImageUrl}/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg`;
93
+ }
94
+ }
@@ -1,28 +1,27 @@
1
1
  import { TranslatorExtended } from '@bytebrand/schema-tools';
2
2
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
3
3
  import {
4
+ escape,
5
+ findIndex,
4
6
  get,
5
- toString,
7
+ includes,
8
+ isArray,
9
+ isBoolean,
6
10
  isEmpty,
7
- trim,
11
+ isString,
8
12
  join,
9
- escape,
10
13
  toSafeInteger,
14
+ toString,
15
+ trim,
11
16
  truncate,
12
- isBoolean,
13
- isString,
14
- isArray,
15
- includes,
16
- findIndex,
17
17
  } from 'lodash';
18
18
  import * as moment from 'moment';
19
19
  import { DataSchemes } from '@bytebrand/car-schema';
20
20
  import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
21
21
  import { DePostalCodesEntryInterface } from '@bytebrand/car-basic-data-scope/dist/interfaces/DePostalCodesInterface';
22
- import { MarketingImagesService } from '../services/marketing-images.service';
23
- import { ConfigService } from '../services/config.service';
22
+ import { ConfigService, ImagesService } from '../services';
24
23
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
25
- import { isNotEmptyArray, isValidVin } from '../utils/validator.utils';
24
+ import { isValidVin } from '../utils/validator.utils';
26
25
  import { Injectable } from '@nestjs/common';
27
26
  import { FbDescription } from './fb-description.transformer';
28
27
  import { Description } from '../interfaces/description.interface';
@@ -31,24 +30,21 @@ import {
31
30
  DEFAULT_ADDR1,
32
31
  DEFAULT_CITY,
33
32
  DEFAULT_ZIP,
34
- FB_MAX_IMAGE_COUNT_FOR_DEAFULT,
35
33
  FB_MAX_TRIM_LENGTH,
36
34
  FB_MIN_MILEAGES,
37
35
  TIMESTAMP_FIRST_YEAR,
38
36
  } from '../constants/fb.constants';
39
37
  import { UserService } from 'src/services';
38
+ import { ImageType } from '../enums';
40
39
 
41
40
  @Injectable()
42
41
  export class FbTransformer {
43
42
  private translator: TranslatorExtended;
44
43
  private postalCodesService: DePostalCodesService;
45
- private marketingImages: MarketingImagesService;
44
+ private imagesService: ImagesService;
46
45
 
47
- constructor(
48
- private readonly configService: ConfigService,
49
- private readonly userService: UserService
50
- ) {
51
- this.marketingImages = new MarketingImagesService(configService, userService);
46
+ constructor(private readonly configService: ConfigService, private readonly userService: UserService) {
47
+ this.imagesService = new ImagesService(configService, userService);
52
48
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
53
49
  this.translator = new TranslatorExtended(dict);
54
50
  this.postalCodesService = DePostalCodesService.getInstance();
@@ -81,7 +77,7 @@ export class FbTransformer {
81
77
  make: toString(get(car, 'mainData.make', '')),
82
78
  model: toString(get(car, 'mainData.model', '')),
83
79
  trim: this.getTrim(car),
84
- image: await this.getImagesField(autodeId, get(car, 'metaData.mainImageId', null), images),
80
+ image: await this.imagesService.getImages(car, images, ImageType.marketing),
85
81
  year: toString(year),
86
82
  mileage: {
87
83
  value: this.getMileage(car),
@@ -152,15 +148,13 @@ export class FbTransformer {
152
148
  dealer_email: string;
153
149
  dealer_phone: string;
154
150
  } {
155
- const items = {
151
+ return {
156
152
  dealer_communication_channel: 'LEAD_FORM',
157
153
  dealer_id: get(car, 'metaData.ownerId'),
158
154
  dealer_privacy_policy_url: 'https://www.auto.de/einwilligungserklaerung-datenschutz-agb/',
159
155
  dealer_email: 'auto@auto.de',
160
156
  dealer_phone: '+498000008300',
161
157
  };
162
-
163
- return items;
164
158
  }
165
159
 
166
160
  private getTitle(car: DataSchemes.Car): string {
@@ -372,28 +366,6 @@ export class FbTransformer {
372
366
  return mileage <= FB_MIN_MILEAGES ? FB_MIN_MILEAGES + 1 : mileage;
373
367
  }
374
368
 
375
- private async getImagesField(
376
- carId: string,
377
- _mainImageId: string,
378
- images: ImboImageResponseInterface[],
379
- ): Promise<{ url: string }[]> {
380
- const defImages = [
381
- { url: 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg' },
382
- { url: 'https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg' },
383
- { url: 'https://images.auto.de/carimage/noimage/gY1zF8PXzH2W/large-cached.jpeg' },
384
- { url: 'https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg' },
385
- ];
386
- if (isNotEmptyArray(images)) {
387
- const imageList = await this.marketingImages.getImagesUrl(images, this.configService.config.imageUrl, carId);
388
-
389
- if (imageList.length < FB_MAX_IMAGE_COUNT_FOR_DEAFULT) {
390
- imageList.push(...defImages);
391
- }
392
- return imageList;
393
- }
394
- return defImages;
395
- }
396
-
397
369
  private getHighlights(car: DataSchemes.Car): { type: unknown; value: unknown }[] {
398
370
  const facebookFeatures = [
399
371
  { key: 'assistants.abs', type: 'abs_brakes', value: 'ABS' },
@@ -1,25 +1,28 @@
1
- import { get, toString, trim, join, escape, round } from 'lodash';
1
+ import { escape, get, join, round, toString, trim } from 'lodash';
2
2
  import { CarDescriptionFactory, DescriptionTypeEnum } from '@bytebrand/car-description';
3
3
  import { DataSchemes } from '@bytebrand/car-schema';
4
4
  import { TranslatorExtended } from '@bytebrand/schema-tools';
5
5
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
6
6
  import { Injectable } from '@nestjs/common';
7
- import { UserService } from '../services/user.service';
8
- import { ConfigService } from '../services/config.service';
7
+ import { ConfigService, ImagesService, UserService } from '../services';
9
8
  import { GoogleXmlItem } from '../interfaces';
9
+ import { ImageType } from '../enums';
10
10
 
11
11
  @Injectable()
12
12
  export class GoogleTransformer {
13
13
  private translator: TranslatorExtended;
14
14
 
15
- constructor(private userService: UserService, private configService: ConfigService) {
15
+ constructor(
16
+ private userService: UserService,
17
+ private configService: ConfigService,
18
+ private imageService: ImagesService,
19
+ ) {
16
20
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
17
21
  this.translator = new TranslatorExtended(dict);
18
22
  }
19
23
 
20
- async transform({ car }: { car: DataSchemes.Car }): Promise<GoogleXmlItem> {
24
+ async transform({ car, images }: { car: DataSchemes.Car; images: Array<any> }): Promise<GoogleXmlItem> {
21
25
  const carId = toString(get(car, '_id', ''));
22
- const mainImageId = get(car, 'metaData.mainImageId', '');
23
26
 
24
27
  return {
25
28
  id: carId,
@@ -28,7 +31,7 @@ export class GoogleTransformer {
28
31
  google_product_category: this.getBreadcrumbs(car),
29
32
  product_type: this.getCategory(car),
30
33
  link: this.getLink(car),
31
- image_link: await this.buildLargeImageUrl(carId, mainImageId),
34
+ image_link: await this.imageService.getImages(car, images, ImageType.marketing)[0],
32
35
  condition: this.mapState(car),
33
36
  availability: this.getAvailability(car),
34
37
  brand: get(car, 'mainData.make', ''),
@@ -98,27 +101,6 @@ export class GoogleTransformer {
98
101
  return this.translator.translateVal(colorSelection);
99
102
  }
100
103
 
101
- private async buildLargeImageUrl(carId: string, imageId: string): Promise<string> {
102
- if (this.configService.config.isCriteo) {
103
- try {
104
- const criteoConfig = await this.userService.getMarketingImageConfig(this.configService.config.criteoMarketingImagesConfigId);
105
- return imageId
106
- ? `${this.configService.config.imageUrl}/generated_images/${[carId[0], carId[1], carId[2], carId].join(
107
- '/',
108
- )}/criteo-${imageId}.${criteoConfig.imageExtension}`
109
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
110
- } catch (e) {
111
- console.log('Error: Failed to get criteoConfig');
112
- return imageId
113
- ? `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`
114
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
115
- }
116
- }
117
- return imageId
118
- ? `${this.configService.config.imageUrl}/carimage/${carId}/${imageId}/large`
119
- : 'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large';
120
- }
121
-
122
104
  private mapState(car: DataSchemes.Car): string {
123
105
  const available = {
124
106
  selector_condition_new: 'Neu',
@@ -1,2 +1,3 @@
1
1
  export * from './rubrikk.transformer';
2
2
  export * from './modix.transformer';
3
+ export * from './facebook-shop.transformer';
@@ -3,7 +3,7 @@ import { DataSchemes } from '@bytebrand/car-schema';
3
3
 
4
4
  import { de } from '@bytebrand/i18n-dictionaries';
5
5
  import { Injectable } from '@nestjs/common';
6
- import { ConfigService } from '../services/config.service';
6
+ import { ConfigService } from '../services';
7
7
  import { MeinstadtJsonItem } from '../interfaces';
8
8
 
9
9
  @Injectable()
@@ -73,8 +73,7 @@ export class MeinstadtTransformer {
73
73
  private getDescription(car: DataSchemes.Car): string {
74
74
  const usageType = get(car, 'offer.offerDescription', null);
75
75
  if (usageType) {
76
- const afterFromatting = usageType.replace(/\\/g, ',').replace(/\\/g, ',').replace(/,,/g, ',');
77
- return afterFromatting;
76
+ return usageType.replace(/\\/g, ',').replace(/\\/g, ',').replace(/,,/g, ',');
78
77
  } else return null;
79
78
  }
80
79
  }