@bytebrand/export-cars 1.10.0 → 1.10.2

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 (33) hide show
  1. package/dist/configs/config.d.ts +3 -13
  2. package/dist/configs/config.js +3 -15
  3. package/dist/configs/config.js.map +1 -1
  4. package/dist/configs/criteo.config.js +1 -0
  5. package/dist/configs/criteo.config.js.map +1 -1
  6. package/dist/configs/facebook-shop.config.js +1 -0
  7. package/dist/configs/facebook-shop.config.js.map +1 -1
  8. package/dist/configs/fb.config.js +1 -0
  9. package/dist/configs/fb.config.js.map +1 -1
  10. package/dist/export.command.d.ts +2 -3
  11. package/dist/export.command.js +2 -5
  12. package/dist/export.command.js.map +1 -1
  13. package/dist/services/images.service.d.ts +3 -5
  14. package/dist/services/images.service.js +7 -23
  15. package/dist/services/images.service.js.map +1 -1
  16. package/dist/services/user.service.d.ts +1 -1
  17. package/dist/services/user.service.js.map +1 -1
  18. package/dist/transformers/by-owner.transformer.js +3 -14
  19. package/dist/transformers/by-owner.transformer.js.map +1 -1
  20. package/dist/transformers/fb.transformer.d.ts +4 -2
  21. package/dist/transformers/fb.transformer.js +25 -10
  22. package/dist/transformers/fb.transformer.js.map +1 -1
  23. package/dist/tsconfig.build.tsbuildinfo +1 -1
  24. package/package.json +3 -9
  25. package/src/configs/config.ts +3 -15
  26. package/src/configs/criteo.config.ts +1 -0
  27. package/src/configs/facebook-shop.config.ts +1 -0
  28. package/src/configs/fb.config.ts +1 -0
  29. package/src/export.command.ts +1 -2
  30. package/src/services/images.service.ts +14 -28
  31. package/src/services/user.service.ts +4 -2
  32. package/src/transformers/by-owner.transformer.ts +3 -16
  33. package/src/transformers/fb.transformer.ts +29 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/export-cars",
3
- "version": "1.10.0",
3
+ "version": "1.10.2",
4
4
  "description": "",
5
5
  "author": "bytebrand",
6
6
  "license": "UNLICENSED",
@@ -21,12 +21,10 @@
21
21
  "@bytebrand/car-schema": "^3.12.24",
22
22
  "@bytebrand/chunkable": "^5.13.2",
23
23
  "@bytebrand/cronicle-helper": "^1.15.1",
24
- "@bytebrand/fe-financing": "^5.4.3",
25
24
  "@bytebrand/i18n-dictionaries": "^1.4.2",
26
25
  "@bytebrand/import-helper": "^0.35.1",
27
26
  "@bytebrand/schema-tools": "^3.13.24",
28
27
  "@bytebrand/zipper": "^2.1.1",
29
- "@nestjs/axios": "^0.1.0",
30
28
  "@nestjs/common": "^9.0.0",
31
29
  "@nestjs/core": "^9.0.0",
32
30
  "bottleneck": "^2.19.5",
@@ -36,12 +34,8 @@
36
34
  "lodash": "^4.17.21",
37
35
  "moment": "^2.29.4",
38
36
  "nest-commander": "^3.1.0",
39
- "nest-winston": "^1.8.0",
40
37
  "reflect-metadata": "^0.1.13",
41
- "rimraf": "^3.0.2",
42
- "rxjs": "^7.2.0",
43
- "vin-generator": "^1.0.1",
44
- "winston": "^3.8.2"
38
+ "vin-generator": "^1.0.1"
45
39
  },
46
40
  "devDependencies": {
47
41
  "@nestjs/cli": "^9.0.0",
@@ -66,5 +60,5 @@
66
60
  "engines": {
67
61
  "node": ">=14.0.0"
68
62
  },
69
- "gitHead": "37593dea01bef934aa28dee2dfc50c29fad9aeef"
63
+ "gitHead": "4fd5ec3e85f39f7932eead7b1dbd60dc780d39f0"
70
64
  }
@@ -5,7 +5,7 @@ export class Config {
5
5
  apikey: string;
6
6
  campaign: string;
7
7
  userActionsUrl: string;
8
- marketingImageId: number;
8
+ marketingImageConfigId: number;
9
9
  upaUrl: string;
10
10
  imboUrl: string;
11
11
  imageUrl: string;
@@ -13,7 +13,6 @@ export class Config {
13
13
  imageType: ImageType;
14
14
  isNewCar: boolean;
15
15
  isCriteo: boolean;
16
- criteoMarketingImagesConfigId: number;
17
16
  exportType: ExportType;
18
17
  domain: string;
19
18
  input: {
@@ -34,32 +33,23 @@ export class Config {
34
33
  dealersSpreadsheetTitle: string;
35
34
 
36
35
  protected environmentConfig = {
37
- [Environment.LOCAL]: {
38
- domain: 'autode-dev.de',
39
- criteoMarketingImagesConfigId: 12,
40
- localConvertedDirectory: 'resources/csv_dev',
41
- remoteDirectory: 'import_dev',
42
- imageUrl: 'https://images.autode-dev.de/cache_test',
43
- baseImageUrl: 'https://images.autode-dev.de',
44
- marketingImageId: 8,
45
- },
46
36
  [Environment.DEVELOP]: {
47
37
  domain: 'autode-dev.de',
38
+ fbMarketingImageId: 8,
48
39
  criteoMarketingImagesConfigId: 12,
49
40
  localConvertedDirectory: 'resources/csv_dev',
50
41
  remoteDirectory: 'import_dev',
51
42
  imageUrl: 'https://images.autode-dev.de/cache_test',
52
43
  baseImageUrl: 'https://images.autode-dev.de',
53
- marketingImageId: 8,
54
44
  },
55
45
  [Environment.PRODUCTION]: {
56
46
  domain: 'auto.de',
47
+ fbMarketingImageId: 1,
57
48
  criteoMarketingImagesConfigId: 3,
58
49
  localConvertedDirectory: 'resources/csv_prod',
59
50
  remoteDirectory: 'import',
60
51
  imageUrl: 'https://images.auto.de/generated_images',
61
52
  baseImageUrl: 'https://images.auto.de',
62
- marketingImageId: 1,
63
53
  },
64
54
  };
65
55
 
@@ -67,9 +57,7 @@ export class Config {
67
57
  this.apikey = params.apikey;
68
58
  this.exportType = params.exportType;
69
59
  this.cpc = params.cpc;
70
- this.criteoMarketingImagesConfigId = this.environmentConfig[params.environment].criteoMarketingImagesConfigId;
71
60
  this.domain = this.environmentConfig[params.environment].domain;
72
- this.marketingImageId = this.environmentConfig[params.environment].marketingImageId;
73
61
  this.baseImageUrl = this.environmentConfig[params.environment].baseImageUrl;
74
62
  this.mappingSpreadsheetId = '147qz9sTgs1wi13ua8YKa0IgfxAn1X_qH6LkGnAnzeyY';
75
63
  this.dealersSpreadsheetId = '1gWrcA-uRTpna1h66Mbe2Y7NA0tIhlUaQXBcS4a_UzOw';
@@ -8,6 +8,7 @@ export class CriteoConfig extends Config {
8
8
  this.campaign = ExportType.CRITEO;
9
9
  this.pathesConfig.localConvertedDirectory = `resources/${ExportType.CRITEO}-export`;
10
10
  this.imageType = ImageType.marketing;
11
+ this.marketingImageConfigId = this.environmentConfig[params.environment].criteoMarketingImagesConfigId;
11
12
  this.outputFiles = [
12
13
  `${this.pathesConfig.localConvertedDirectory}/api_export_cars_${ExportType.CRITEO}.${FileType.XML}`,
13
14
  ];
@@ -8,6 +8,7 @@ export class FacebookShopConfig extends Config {
8
8
  this.pathesConfig.localConvertedDirectory = `resources/${ExportType.FACEBOOK_SHOP}-export`;
9
9
  this.imageUrl = this.environmentConfig[params.environment].baseImageUrl;
10
10
  this.imageType = ImageType.marketing;
11
+ this.marketingImageConfigId = this.environmentConfig[params.environment].fbMarketingImageId;
11
12
  this.outputFiles = [
12
13
  `${this.pathesConfig.localConvertedDirectory}/api_export_cars_${ExportType.FACEBOOK_SHOP}.${FileType.XML}`,
13
14
  ];
@@ -8,6 +8,7 @@ export class FbConfig extends Config {
8
8
  this.pathesConfig.localConvertedDirectory = `resources/${ExportType.FB}-export`;
9
9
  this.imageUrl = this.environmentConfig[params.environment].imageUrl;
10
10
  this.imageType = ImageType.marketing;
11
+ this.marketingImageConfigId = this.environmentConfig[params.environment].fbMarketingImageId;
11
12
  this.outputFiles = [
12
13
  `${this.pathesConfig.localConvertedDirectory}/api_export_cars_${ExportType.FB}.${FileType.XML}`,
13
14
  ];
@@ -1,5 +1,5 @@
1
1
  import { createInterface } from 'readline';
2
- import { Command, CommandRunner, InquirerService } from 'nest-commander';
2
+ import { Command, CommandRunner } from 'nest-commander';
3
3
  import { ConfigService } from './services';
4
4
  import { Input } from './interfaces/input.interface';
5
5
  import { exportSchema } from './export.schema';
@@ -13,7 +13,6 @@ import { LoggerService } from '@bytebrand/cronicle-helper';
13
13
  })
14
14
  export class ExportRunner extends CommandRunner {
15
15
  constructor(
16
- private readonly inquirer: InquirerService,
17
16
  private configService: ConfigService,
18
17
  private moduleRef: ModuleRef,
19
18
  ) {
@@ -1,17 +1,20 @@
1
+ import { get, toString } from 'lodash';
2
+
1
3
  import { Injectable } from '@nestjs/common';
2
- import { DataSchemes } from '@bytebrand/car-schema';
4
+
5
+ import { MarketingImageConfigsInterface } from '@bytebrand/autode-request';
3
6
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
4
- import { get, toString } from 'lodash';
7
+ import { DataSchemes } from '@bytebrand/car-schema';
8
+
9
+ import { FB_MAX_IMAGE_COUNT_FOR_DEAFULT } from '../constants/fb.constants';
5
10
  import { isNotEmptyArray } from '../utils/validator.utils';
6
11
  import { ConfigService } from './config.service';
7
- import { ImageType } from '../enums';
8
- import { MarketingImageConfigInterface, MarketingImageConfigsInterface } from '@bytebrand/autode-request';
9
12
  import { UserService } from './user.service';
10
- import { FB_MAX_IMAGE_COUNT_FOR_DEAFULT } from '../constants/fb.constants';
13
+ import { ImageType } from '../enums';
11
14
 
12
15
  @Injectable()
13
16
  export class ImagesService {
14
- constructor(private readonly configService: ConfigService, private readonly userService: UserService) {}
17
+ constructor(private readonly configService: ConfigService, private readonly userService: UserService) { }
15
18
 
16
19
  async getImages(
17
20
  car: DataSchemes.Car,
@@ -74,7 +77,7 @@ export class ImagesService {
74
77
 
75
78
  const carId = toString(get(car, '_id', ''));
76
79
 
77
- const transformedImages = this.generateImageLinks(images, carId);
80
+ const transformedImages = this.generateImageLinks(images.filter(i => i), carId);
78
81
  if (transformedImages.length < 17) {
79
82
  transformedImages.push(...defaultImages);
80
83
  }
@@ -90,10 +93,9 @@ export class ImagesService {
90
93
  async getMarketingImages(images: any, carId: string): Promise<string[]> {
91
94
  const imageUrl = this.configService.config.imageUrl;
92
95
  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);
96
+
97
+ const config = await this.userService.getMarketingImageConfig(this.configService.config.marketingImageConfigId);
98
+ const marketingImageConfigs = config.marketingImages.map(i => ({ marketingImageCodes: i.imageCodes }));
97
99
 
98
100
  const defImages = [
99
101
  'https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg',
@@ -110,7 +112,7 @@ export class ImagesService {
110
112
  const imageCode = marketingImage.marketingImageCodes[i];
111
113
  const imageId = transformedImages[imageCode];
112
114
  if (imageId) {
113
- imageUrls.push(this.getImagePathWithExtenstion(imageUrl, carId, imageId, configs));
115
+ imageUrls.push(this.getImagePathWithExtenstion(imageUrl, carId, imageId, config));
114
116
  break;
115
117
  }
116
118
  }
@@ -121,14 +123,6 @@ export class ImagesService {
121
123
  return imageUrls;
122
124
  }
123
125
 
124
- async getMarketingImageConfigs(): Promise<MarketingImageConfigsInterface> {
125
- const configs = await this.userService.getMarketingImageConfigs();
126
- const responseData = configs.find(config => config.channelCode.includes(this.configService.config.exportType));
127
- let id;
128
- !responseData?.id ? (id = this.configService.config.marketingImageId) : (id = responseData.id);
129
- return this.userService.getMarketingImageConfig(id);
130
- }
131
-
132
126
  private transformImagesArrayIntoObject(images: { [imageCode: string]: string }[]) {
133
127
  const result: { [imageCode: string]: string } = {};
134
128
  images.forEach(image => {
@@ -138,14 +132,6 @@ export class ImagesService {
138
132
  return result;
139
133
  }
140
134
 
141
- private transform(config: MarketingImageConfigInterface): { marketingImageCodes: string[] }[] {
142
- return config.marketingImages.map(marketingImage => {
143
- return {
144
- marketingImageCodes: marketingImage.imageCodes,
145
- };
146
- });
147
- }
148
-
149
135
  protected getChannelPath(imageUrl: string, carId: string): string {
150
136
  return `${imageUrl}/${[carId[0], carId[1], carId[2], carId].join('/')}`;
151
137
  }
@@ -1,9 +1,11 @@
1
1
  import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
2
+
3
+ import { MarketingImageConfigInterface, MarketingImageConfigsInterface } from '@bytebrand/autode-request';
4
+
2
5
  import { RequestService } from './request.service';
3
6
  import { Cache } from 'cache-manager';
4
7
  import { get } from 'lodash';
5
- import { MarketingImageConfigInterface, MarketingImageConfigsInterface } from '@bytebrand/autode-request';
6
- import { ExportType, FileType } from '../enums';
8
+
7
9
 
8
10
  @Injectable()
9
11
  export class UserService {
@@ -3,7 +3,6 @@ import { Translator, TranslatorExtended } from '@bytebrand/schema-tools';
3
3
  import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
4
4
  import { DataSchemes } from '@bytebrand/car-schema';
5
5
  import { Injectable } from '@nestjs/common';
6
- import { normalizeRateObject, getMonthlyInstallment, getComputedFinancing } from '@bytebrand/fe-financing';
7
6
  import * as moment from 'moment';
8
7
 
9
8
  type transformFn = (car: DataSchemes.Car, translator: TranslatorExtended) => string;
@@ -24,23 +23,11 @@ export class ByOwnerTransformer {
24
23
 
25
24
  price: 'price.currentSalesPrice',
26
25
  '(old price) strike price': 'price.wasPrice',
27
- rate: (car: DataSchemes.Car) => {
28
- const { rate } = normalizeRateObject({ ...car });
29
- return getMonthlyInstallment(rate);
30
- },
26
+ rate: (car: DataSchemes.Car) => car.rate.monthlyInstallment,
31
27
  'discount in %': this.mapToNumber('price.historyPriceDifferencePerCent', 1, 0),
32
28
  'discount in €': this.mapToNumber('price.historyPriceDifference', 1, 0),
33
- 'first_installment in €': (car: DataSchemes.Car) => {
34
- const { rate } = normalizeRateObject({ ...car });
35
- const price = getComputedFinancing(rate) as ReturnType<typeof getComputedFinancing> & {
36
- firstInstallment: number;
37
- };
38
- return price.firstInstallment;
39
- },
40
- 'amount of month': (car: DataSchemes.Car) => {
41
- const { rate } = normalizeRateObject({ ...car });
42
- return rate.paybackPeriod;
43
- },
29
+ 'first_installment in €': (car: DataSchemes.Car) => car.rate.firstInstallment,
30
+ 'amount of month': (car: DataSchemes.Car) => car.rate.paybackPeriod,
44
31
 
45
32
  Name: (car: DataSchemes.Car): string => {
46
33
  const make = toString(get(car, 'mainData.make', ''));
@@ -1,5 +1,5 @@
1
- import { TranslatorExtended } from '@bytebrand/schema-tools';
2
- import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
1
+ import { Cache } from 'cache-manager';
2
+ import * as moment from 'moment';
3
3
  import {
4
4
  escape,
5
5
  findIndex,
@@ -15,17 +15,23 @@ import {
15
15
  trim,
16
16
  truncate,
17
17
  } from 'lodash';
18
- import * as moment from 'moment';
19
- import { DataSchemes } from '@bytebrand/car-schema';
20
- import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
18
+
19
+ import { CACHE_MANAGER, Inject, Injectable } from '@nestjs/common';
20
+
21
21
  import { DePostalCodesEntryInterface } from '@bytebrand/car-basic-data-scope/dist/interfaces/DePostalCodesInterface';
22
- import { ConfigService, ImagesService } from '../services';
22
+ import { de, deVehicleDetailsPage, deVehicleProps } from '@bytebrand/i18n-dictionaries';
23
+ import { DePostalCodesService } from '@bytebrand/car-basic-data-scope';
23
24
  import { ImboImageResponseInterface } from '@bytebrand/chunkable';
24
- import { isValidVin } from '../utils/validator.utils';
25
- import { Injectable } from '@nestjs/common';
26
- import { FbDescription } from './fb-description.transformer';
25
+ import { TranslatorExtended } from '@bytebrand/schema-tools';
26
+ import { DataSchemes } from '@bytebrand/car-schema';
27
+
27
28
  import { Description } from '../interfaces/description.interface';
29
+ import { FbDescription } from './fb-description.transformer';
30
+ import { ConfigService, ImagesService } from '../services';
28
31
  import { FbEquipment } from './fb-equipment.transformer';
32
+ import { isValidVin } from '../utils/validator.utils';
33
+ import { UserService } from 'src/services';
34
+ import { ImageType } from '../enums';
29
35
  import {
30
36
  DEFAULT_ADDR1,
31
37
  DEFAULT_CITY,
@@ -34,8 +40,7 @@ import {
34
40
  FB_MIN_MILEAGES,
35
41
  TIMESTAMP_FIRST_YEAR,
36
42
  } from '../constants/fb.constants';
37
- import { UserService } from 'src/services';
38
- import { ImageType } from '../enums';
43
+
39
44
 
40
45
  @Injectable()
41
46
  export class FbTransformer {
@@ -43,7 +48,11 @@ export class FbTransformer {
43
48
  private postalCodesService: DePostalCodesService;
44
49
  private imagesService: ImagesService;
45
50
 
46
- constructor(private readonly configService: ConfigService, private readonly userService: UserService) {
51
+ constructor(
52
+ @Inject(CACHE_MANAGER) private cacheManager: Cache,
53
+ private readonly configService: ConfigService,
54
+ private readonly userService: UserService
55
+ ) {
47
56
  this.imagesService = new ImagesService(configService, userService);
48
57
  const dict = { ...de, ...deVehicleProps, ...deVehicleDetailsPage };
49
58
  this.translator = new TranslatorExtended(dict);
@@ -317,10 +326,17 @@ export class FbTransformer {
317
326
  }
318
327
 
319
328
  private async getLocationByInfo(info: { zip: number; city: string }): Promise<DePostalCodesEntryInterface> {
320
- let entry: DePostalCodesEntryInterface = await this.postalCodesService.getLocationByPostalCode(info.zip);
329
+ const cacheKey = `${info.city}_${info.zip}`;
330
+
331
+ let entry: DePostalCodesEntryInterface = await this.cacheManager.get(cacheKey);
332
+ if (entry) { return entry };
333
+
334
+ entry = await this.postalCodesService.getLocationByPostalCode(info.zip);
335
+ await this.cacheManager.set(cacheKey, entry);
321
336
 
322
337
  if (!entry) {
323
338
  entry = await this.postalCodesService.getLocationByCity(info.city);
339
+ await this.cacheManager.set(cacheKey, entry);
324
340
  }
325
341
  return entry;
326
342
  }