pim-import 2.22.0 → 2.24.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 (36) hide show
  1. package/dist/algolia/config.js +22 -2
  2. package/dist/algolia/config.js.map +1 -1
  3. package/dist/algolia/{collections.js → families.js} +12 -12
  4. package/dist/algolia/families.js.map +1 -0
  5. package/dist/algolia/models.js +1 -0
  6. package/dist/algolia/models.js.map +1 -1
  7. package/dist/algolia/subFamilies.js +242 -0
  8. package/dist/algolia/subFamilies.js.map +1 -0
  9. package/dist/algolia/subModels.js +1 -0
  10. package/dist/algolia/subModels.js.map +1 -1
  11. package/dist/index.js +13 -9
  12. package/dist/index.js.map +1 -1
  13. package/dist/libs/contentful.js +8 -1
  14. package/dist/libs/contentful.js.map +1 -1
  15. package/dist/pim/endpoints.js +2 -0
  16. package/dist/pim/endpoints.js.map +1 -1
  17. package/dist/pim/methods/families.js +0 -31
  18. package/dist/pim/methods/families.js.map +1 -1
  19. package/dist/pim/methods/products.js +1 -1
  20. package/dist/pim/methods/products.js.map +1 -1
  21. package/dist/pim/methods/subfamilies.js +2 -1
  22. package/dist/pim/methods/subfamilies.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/algolia/config.ts +24 -3
  25. package/src/algolia/{collections.ts → families.ts} +8 -10
  26. package/src/algolia/models.ts +2 -0
  27. package/src/algolia/subFamilies.ts +429 -0
  28. package/src/algolia/subModels.ts +2 -0
  29. package/src/index.ts +9 -4
  30. package/src/libs/contentful.ts +8 -1
  31. package/src/pim/endpoints.ts +2 -0
  32. package/src/pim/methods/families.ts +86 -86
  33. package/src/pim/methods/products.ts +6 -1
  34. package/src/pim/methods/subfamilies.ts +2 -2
  35. package/src/resources/ProductDetails.ts +0 -1
  36. package/dist/algolia/collections.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Collection index
2
+ * Families index
3
3
  */
4
4
  import {
5
5
  getClient,
@@ -52,7 +52,7 @@ export type AlgoliaFamilyRecord = {
52
52
  lastSyncDate: string;
53
53
  };
54
54
 
55
- const indexKey: AvailableIndicesKey = "collections";
55
+ const indexKey: AvailableIndicesKey = "families";
56
56
 
57
57
  const getFamilyPage = async (topicFamily: Entry): Promise<pageResponse> => {
58
58
  const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
@@ -317,9 +317,7 @@ const getObject = async (topicFamily: Entry): Promise<AlgoliaFamilyRecord> => {
317
317
  log(`Get productFields details...`);
318
318
  const productFields = await getProductFields(topicFamily);
319
319
 
320
- const isNew: boolean = !!productFields?.upgrade?.find(
321
- (item: any) => item === "UP3"
322
- );
320
+ const isNew: boolean = topicFamilyWithFields?.fields?.isNew || false;
323
321
 
324
322
  log(`Get thumbnail imgix details...`);
325
323
  let thumbnailImgix = {};
@@ -409,12 +407,12 @@ const getObjects = async (
409
407
  };
410
408
  };
411
409
 
412
- export const reindexCollections = async (
410
+ export const reindexFamilies = async (
413
411
  offset: number = 0,
414
412
  limit: number = 50
415
413
  ) => {
416
414
  const timeStart = new Date();
417
- log(`reindexCollections - offset: ${offset} limit: ${limit} `);
415
+ log(`reindexFamilies - offset: ${offset} limit: ${limit} `);
418
416
 
419
417
  const records = await getObjects(offset, limit);
420
418
  const objectsToSave = records.objects.filter(
@@ -440,10 +438,10 @@ export const reindexCollections = async (
440
438
  return { ...records, ...savedObjectIDs, ...deletedObjectIDs };
441
439
  };
442
440
 
443
- export const reindexCollection = async (topicFamilyEntryId: string) => {
441
+ export const reindexFamily = async (topicFamilyEntryId: string) => {
444
442
  const timeStart = new Date();
445
443
 
446
- log(`reindexCollection - entryId: ${topicFamilyEntryId} `);
444
+ log(`reindexFamily - entryId: ${topicFamilyEntryId} `);
447
445
 
448
446
  // Get single object data
449
447
  const topicFamily = await getEntryByID(topicFamilyEntryId, "topicFamily");
@@ -466,6 +464,6 @@ export const reindexCollection = async (topicFamilyEntryId: string) => {
466
464
  return { ...record, ...object };
467
465
  };
468
466
 
469
- export const removeCollectionObject = async (objectId: string) => {
467
+ export const removeFamilyObject = async (objectId: string) => {
470
468
  return removeIndexObject(objectId, indexKey);
471
469
  };
@@ -56,6 +56,7 @@ type AlgoliaModelRecord = {
56
56
  productLine?: TopicDetailsResponse;
57
57
  catalog?: TopicDetailsResponse;
58
58
  subFamily?: TopicDetailsResponse;
59
+ isNew?: boolean;
59
60
  priority?: number;
60
61
  colors?: string[];
61
62
  lastSyncDate?: string;
@@ -251,6 +252,7 @@ const getObject = async (
251
252
  catalog,
252
253
  subFamily,
253
254
  colors,
255
+ isNew: topicModelWithFields?.fields?.isNew || false,
254
256
  priority:
255
257
  topicModelWithFields?.fields?.priority?.[defaultEnvironmentLocaleCode] ||
256
258
  0,
@@ -0,0 +1,429 @@
1
+ /**
2
+ * SubFamilies index
3
+ */
4
+ import {
5
+ getClient,
6
+ getEnvironmentDefaultLocaleCode,
7
+ getEntryByID,
8
+ getAllEntries,
9
+ getTopicDetails,
10
+ } from "../libs/contentful-cda";
11
+ import { AlgoliaPaginateRecords } from "../types";
12
+ import type { Entry } from "contentful-management/dist/typings/entities/entry";
13
+ import { log } from "../libs/logs";
14
+ import { getIndex, AvailableIndicesKey, removeIndexObject } from "./config";
15
+ import {
16
+ getLocalISOTime,
17
+ sanitizeValue,
18
+ secondBetweenTwoDate,
19
+ keysToLowerCase,
20
+ addProductFieldValueCodesByPimDetails,
21
+ capitalizeFirstLetter,
22
+ } from "../utils";
23
+ import { getWrapperImgixFields } from "../libs/imgix";
24
+ import { AlgoliaFamilyRecord, pageResponse } from "./families";
25
+
26
+ const indexKey: AvailableIndicesKey = "subFamilies";
27
+
28
+ const getSubFamilyPage = async (
29
+ topicSubFamily: Entry
30
+ ): Promise<pageResponse> => {
31
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
32
+ const subFamilyPage = await getEntryByID(
33
+ `${topicSubFamily.sys.id}_PAGE`,
34
+ "page"
35
+ );
36
+ if (!subFamilyPage) {
37
+ log(`${topicSubFamily.sys.id}_PAGE not found`, "WARN");
38
+ return {
39
+ slugs: {},
40
+ type: "",
41
+ details: {},
42
+ };
43
+ }
44
+
45
+ const subFamilyPageId = subFamilyPage.sys.id;
46
+
47
+ // check if subFamily has many relations with model
48
+ const client = await getClient();
49
+ const { items: modelEntries } = await client.getEntries({
50
+ content_type: "topicModel",
51
+ "fields.subFamily.sys.id": subFamilyPageId.replace("_PAGE", ""),
52
+ limit: 2,
53
+ locale: "*",
54
+ select: "sys,fields.catalog,fields.subFamily",
55
+ });
56
+
57
+ if (modelEntries?.length === 1) {
58
+ // Return model page slug
59
+ const modelEntry = modelEntries[0];
60
+ const modelPageId = `${modelEntry.sys.id}_PAGE`;
61
+ const modelPage = await getEntryByID(
62
+ modelPageId,
63
+ "page",
64
+ "fields.slug,fields.type"
65
+ );
66
+
67
+ const catalogEntryId =
68
+ modelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys?.id;
69
+ const modelCatalogPage: any = catalogEntryId
70
+ ? await getEntryByID(`${catalogEntryId}_PAGE`, "page", "fields.slug")
71
+ : {};
72
+ const subFamilyEntryId =
73
+ modelEntry?.fields?.subFamily?.[defaultEnvironmentLocaleCode]?.sys?.id;
74
+ const modelCatalogSubFamilyPage: any = subFamilyEntryId
75
+ ? await getEntryByID(`${subFamilyEntryId}_PAGE`, "page", "fields.slug")
76
+ : {};
77
+ if (modelPage) {
78
+ return {
79
+ slugs: modelPage?.fields?.slug,
80
+ type: modelPage?.fields?.type?.[defaultEnvironmentLocaleCode],
81
+ details: {
82
+ catalogPageSlugs:
83
+ keysToLowerCase(modelCatalogPage?.fields?.slug) || {},
84
+ subFamilyPageSlugs:
85
+ keysToLowerCase(modelCatalogSubFamilyPage?.fields?.slug) || {},
86
+ },
87
+ };
88
+ } else {
89
+ log(`The modelPage with id "${modelPageId}" not found`, "WARN");
90
+ }
91
+ }
92
+
93
+ // Return SubFamily page slug
94
+ if (subFamilyPage) {
95
+ return {
96
+ slugs: subFamilyPage?.fields?.slug,
97
+ type: subFamilyPage?.fields?.type?.[defaultEnvironmentLocaleCode],
98
+ details: {},
99
+ };
100
+ } else {
101
+ log(
102
+ `The subFamilyPage with id "${topicSubFamily.sys.id}_PAGE" not found`,
103
+ "WARN"
104
+ );
105
+ }
106
+
107
+ // if it doesn't find any slugs
108
+ return null;
109
+ };
110
+
111
+ const getProductFields = async (topicSubFamily: Entry): Promise<any> => {
112
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
113
+ const catalogName = capitalizeFirstLetter(
114
+ (
115
+ topicSubFamily.fields.catalog?.[defaultEnvironmentLocaleCode]?.sys.id ||
116
+ ""
117
+ ).toLowerCase()
118
+ );
119
+ if (!catalogName) {
120
+ console.log(topicSubFamily.fields.catalog);
121
+ log(`Cannot find catalog name`, "WARN");
122
+ return {};
123
+ }
124
+
125
+ const fieldName = `subFamilies${catalogName}`;
126
+
127
+ const topicProductEntries = await getAllEntries(
128
+ "topicProduct",
129
+ "sys,fields.productFields",
130
+ `fields.${fieldName}.sys.id[in]`,
131
+ `${topicSubFamily.sys.id}`,
132
+ 50
133
+ // [ TODO: Riabilitare il filtro una votla passati alla CDA
134
+ // {
135
+ // key: "fields.pimStatus",
136
+ // value: "Published",
137
+ // },
138
+ // ]
139
+ );
140
+ if (!topicProductEntries?.length) {
141
+ log(`No products founded for subFamily ${topicSubFamily.sys.id}`, "WARN");
142
+ return false;
143
+ } else {
144
+ log(`${topicProductEntries?.length} products founded`);
145
+ }
146
+
147
+ let productFields: any = {};
148
+
149
+ for (const topicProduct of topicProductEntries) {
150
+ if (topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode]) {
151
+ const pimDetails =
152
+ topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode];
153
+
154
+ if (!productFields?.certification) {
155
+ productFields.certification = [];
156
+ }
157
+
158
+ // CERTIFICATION - ENEC | PIM certification->enec
159
+ if (
160
+ pimDetails?.certification?.enec?.code &&
161
+ sanitizeValue(pimDetails.certification.enec.code) &&
162
+ productFields?.certification.indexOf("ENEC") === -1
163
+ ) {
164
+ productFields.certification.push("ENEC");
165
+ }
166
+ // CERTIFICATION - UL | PIM certification->ul
167
+ if (
168
+ pimDetails?.certification?.ul?.code &&
169
+ sanitizeValue(pimDetails.certification.ul.code) &&
170
+ productFields?.certification.indexOf("UL") === -1
171
+ ) {
172
+ productFields.certification.push("UL");
173
+ }
174
+
175
+ // MOUNTINGS [Has many]
176
+ productFields = addProductFieldValueCodesByPimDetails(
177
+ pimDetails,
178
+ productFields,
179
+ "mountings"
180
+ );
181
+
182
+ // ORINTATIONS [Has many]
183
+ productFields = addProductFieldValueCodesByPimDetails(
184
+ pimDetails,
185
+ productFields,
186
+ "orientations",
187
+ "physical"
188
+ );
189
+
190
+ // DRIVER TYPE | PIM powerSupplyType [Has many]
191
+ productFields = addProductFieldValueCodesByPimDetails(
192
+ pimDetails,
193
+ productFields,
194
+ "powerSupplyType",
195
+ "electrical"
196
+ );
197
+
198
+ // LIGHTING DISTRIBUTIONS | PIM powerSupplyType [Has many]
199
+ productFields = addProductFieldValueCodesByPimDetails(
200
+ pimDetails,
201
+ productFields,
202
+ "lightingDistributions",
203
+ "optical"
204
+ );
205
+
206
+ // OPTICAL TYPE [Only one]
207
+ productFields = addProductFieldValueCodesByPimDetails(
208
+ pimDetails,
209
+ productFields,
210
+ "opticalType",
211
+ "optical"
212
+ );
213
+
214
+ // MARKETS [Has many]
215
+ productFields = addProductFieldValueCodesByPimDetails(
216
+ pimDetails,
217
+ productFields,
218
+ "markets"
219
+ );
220
+
221
+ // UPGRADE
222
+ productFields = addProductFieldValueCodesByPimDetails(
223
+ pimDetails,
224
+ productFields,
225
+ "upgrade"
226
+ );
227
+
228
+ // CERTIFICATIONS
229
+ productFields = addProductFieldValueCodesByPimDetails(
230
+ pimDetails,
231
+ productFields,
232
+ "certifications"
233
+ );
234
+ }
235
+ }
236
+
237
+ return productFields;
238
+ };
239
+
240
+ const getObject = async (
241
+ topicSubFamily: Entry
242
+ ): Promise<AlgoliaFamilyRecord> => {
243
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
244
+ log(`Get details of the ${topicSubFamily.sys.id} topicSubFamily`);
245
+ const topicSubFamilyWithFields = await getEntryByID(
246
+ topicSubFamily.sys.id,
247
+ "topicSubFamily"
248
+ );
249
+
250
+ log(`Get page details...`);
251
+ const page = await getSubFamilyPage(topicSubFamilyWithFields);
252
+ log(`Slugs type: ${page?.type}`);
253
+
254
+ log(`Get catalogs details...`);
255
+ const catalogs = await getTopicDetails(
256
+ topicSubFamilyWithFields,
257
+ "catalog",
258
+ "topicCatalog",
259
+ true
260
+ );
261
+ log(`${catalogs?.length} catalogs founded`);
262
+
263
+ log(`Get categories details...`);
264
+ const categories = await getTopicDetails(
265
+ topicSubFamilyWithFields,
266
+ "category",
267
+ "topicCategory",
268
+ true
269
+ );
270
+ log(`${categories?.length} categories founded`);
271
+
272
+ log(`Get productFields details...`);
273
+ const productFields = await getProductFields(topicSubFamilyWithFields);
274
+
275
+ const isNew: boolean = topicSubFamilyWithFields?.fields?.isNew || false;
276
+
277
+ log(`Get thumbnail imgix details...`);
278
+ let thumbnailImgix = {};
279
+ const thumbnailImgixWrapperImgixID =
280
+ topicSubFamilyWithFields?.fields?.thumbnailImgix?.[
281
+ defaultEnvironmentLocaleCode
282
+ ]?.sys.id;
283
+ if (thumbnailImgixWrapperImgixID) {
284
+ thumbnailImgix = await getWrapperImgixFields(thumbnailImgixWrapperImgixID);
285
+ } else {
286
+ log(`No thumbnail imgix found`, "WARN");
287
+ }
288
+
289
+ log(`Get full screen imgix details...`);
290
+ let fullScreenImageImgix = {};
291
+ const fullScreenImageImgixWrapperImgixID =
292
+ topicSubFamilyWithFields?.fields?.fullScreenImageImgix?.[
293
+ defaultEnvironmentLocaleCode
294
+ ]?.sys.id;
295
+ if (fullScreenImageImgixWrapperImgixID) {
296
+ fullScreenImageImgix = await getWrapperImgixFields(
297
+ fullScreenImageImgixWrapperImgixID
298
+ );
299
+ } else {
300
+ log(`No full screen imgix found`, "WARN");
301
+ }
302
+
303
+ log(`Get priority details...`);
304
+ const priority =
305
+ topicSubFamilyWithFields?.fields?.priority?.[
306
+ defaultEnvironmentLocaleCode
307
+ ] || 0;
308
+
309
+ // Single record
310
+ const record: AlgoliaFamilyRecord = {
311
+ objectID: topicSubFamilyWithFields.sys.id,
312
+ names: keysToLowerCase(topicSubFamilyWithFields?.fields?.name) || {},
313
+ code:
314
+ topicSubFamilyWithFields?.fields?.code?.[defaultEnvironmentLocaleCode] ||
315
+ {},
316
+ thumbnailImgix,
317
+ fullScreenImageImgix,
318
+ slugs: keysToLowerCase(page?.slugs) || {},
319
+ slugType: page?.type || "",
320
+ slugDetails: page?.details || {},
321
+ catalogs,
322
+ categories,
323
+ productFields,
324
+ priority,
325
+ isNew,
326
+ lastSyncDate: getLocalISOTime(),
327
+ };
328
+
329
+ return record;
330
+ };
331
+
332
+ const getObjects = async (
333
+ offset: number,
334
+ limit: number
335
+ ): Promise<AlgoliaPaginateRecords> => {
336
+ const client = await getClient();
337
+
338
+ const opts: any = {
339
+ content_type: "topicSubFamily",
340
+ limit,
341
+ skip: offset,
342
+ locale: "*",
343
+ select: "sys",
344
+ };
345
+ const { items, total } = await client.getEntries(opts);
346
+
347
+ const objects: AlgoliaFamilyRecord[] = [];
348
+ let count: number = Number(offset);
349
+ for (const topicSubFamily of items) {
350
+ log(`${++count} of ${total}`, "INFO");
351
+ const timeStart = new Date();
352
+ const record = await getObject(topicSubFamily);
353
+ const timeEnd = new Date();
354
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
355
+ log(`Execution time: ${seconds} seconds`);
356
+ objects.push(record);
357
+ }
358
+
359
+ return {
360
+ objects,
361
+ offset: Number(offset) + Number(limit),
362
+ limit: Number(limit),
363
+ completed: count >= total, // if is true the import is completed
364
+ };
365
+ };
366
+
367
+ export const reindexSubFamilies = async (
368
+ offset: number = 0,
369
+ limit: number = 50
370
+ ) => {
371
+ const timeStart = new Date();
372
+ log(`reindexSubFamilies - offset: ${offset} limit: ${limit} `);
373
+
374
+ const records = await getObjects(offset, limit);
375
+ const objectsToSave = records.objects.filter(
376
+ (object) => object.productFields
377
+ );
378
+ const objectIdsToDelete = records.objects
379
+ .filter((object) => !object?.productFields)
380
+ .map((object) => object.objectID);
381
+
382
+ // Save records to Algolia
383
+ const index = getIndex(indexKey);
384
+ log(`Save ${objectsToSave.length} objects to ${index.indexName} index`);
385
+ const savedObjectIDs = await index.saveObjects(objectsToSave);
386
+ log(
387
+ `Delete ${objectIdsToDelete.length} objects from ${index.indexName} index`
388
+ );
389
+ const deletedObjectIDs = await index.deleteObjects(objectIdsToDelete);
390
+
391
+ const timeEnd = new Date();
392
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
393
+ log(`Execution time: ${seconds} seconds`);
394
+
395
+ return { ...records, ...savedObjectIDs, ...deletedObjectIDs };
396
+ };
397
+
398
+ export const reindexSubFamily = async (topicSubFamilyEntryId: string) => {
399
+ const timeStart = new Date();
400
+
401
+ log(`reindexSubFamily - entryId: ${topicSubFamilyEntryId} `);
402
+
403
+ // Get single object data
404
+ const topicSubFamily = await getEntryByID(
405
+ topicSubFamilyEntryId,
406
+ "topicSubFamily"
407
+ );
408
+ const object = await getObject(topicSubFamily);
409
+
410
+ // Save record to Algolia
411
+ const index = getIndex(indexKey);
412
+ let record = null;
413
+ if (object.productFields) {
414
+ log(`Save object`);
415
+ record = await index.saveObject(object);
416
+ } else {
417
+ log(`Delete object`);
418
+ record = await index.deleteObject(object.objectID);
419
+ }
420
+ const timeEnd = new Date();
421
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
422
+ log(`Execution time: ${seconds} seconds`);
423
+
424
+ return { ...record, ...object };
425
+ };
426
+
427
+ export const removeSubFamilyObject = async (objectId: string) => {
428
+ return removeIndexObject(objectId, indexKey);
429
+ };
@@ -44,6 +44,7 @@ type AlgoliaSubModelRecord = {
44
44
  catalog?: TopicDetailsResponse;
45
45
  subFamily?: TopicDetailsResponse;
46
46
  parentModel?: TopicDetailsResponse;
47
+ isNew?: boolean;
47
48
  priority?: number;
48
49
  productCounter?: number;
49
50
  lastSyncDate?: string;
@@ -226,6 +227,7 @@ const getObject = async (
226
227
  topicSubModelWithFields?.fields?.priority?.[
227
228
  defaultEnvironmentLocaleCode
228
229
  ] || 0,
230
+ isNew: topicSubModelWithFields?.fields?.isNew || false,
229
231
  productCounter: await getProductCounter(topicSubModelWithFields),
230
232
  lastSyncDate: getLocalISOTime(),
231
233
  };
package/src/index.ts CHANGED
@@ -38,10 +38,15 @@ export {
38
38
  } from "./pim/methods/pages/catalogs";
39
39
  export { resetIndexSettings } from "./algolia/config";
40
40
  export {
41
- reindexCollections,
42
- reindexCollection,
43
- removeCollectionObject,
44
- } from "./algolia/collections";
41
+ reindexFamilies,
42
+ reindexFamily,
43
+ removeFamilyObject,
44
+ } from "./algolia/families";
45
+ export {
46
+ reindexSubFamilies,
47
+ reindexSubFamily,
48
+ removeSubFamilyObject,
49
+ } from "./algolia/subFamilies";
45
50
  export {
46
51
  createOrUpdateSubFamilyPages,
47
52
  createOrUpdateSubFamilyPageByCode,
@@ -237,7 +237,14 @@ export const updateEntry = async (
237
237
  for (const [key, value] of Object.entries(data.fields)) {
238
238
  itemEntry.fields[key] = value;
239
239
  }
240
- const entry = await itemEntry.update();
240
+
241
+ let entry = itemEntry;
242
+ try {
243
+ entry = await itemEntry.update();
244
+ } catch (err) {
245
+ log(`Cannot update entry.`);
246
+ log(err);
247
+ }
241
248
 
242
249
  if (publish) {
243
250
  try {
@@ -240,6 +240,8 @@ export const getStaticDailyProducts = async (
240
240
  };
241
241
  checkConfig();
242
242
 
243
+ log(`Requesting daily update on ${config.baseURL}static-daily-products`);
244
+ log(`Params: ${JSON.stringify(opts)}`);
243
245
  const { data } = await axios.get(`${config.baseURL}static-daily-products`, {
244
246
  params: opts,
245
247
  responseType: "arraybuffer",