pim-import 2.47.1 → 2.48.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.
@@ -1,21 +1,16 @@
1
1
  /**
2
2
  * Product index
3
3
  */
4
- import { cfLocales } from "../libs/contentful";
5
4
  import {
6
5
  getClient,
7
6
  getEnvironmentDefaultLocaleCode,
8
7
  getEntryByID,
9
8
  getTopicDetails,
10
- getDictionaryJson,
11
- getDictionaryLocaleValue,
12
9
  } from "../libs/contentful-cda";
13
10
  import {
14
11
  CfLocalizedEntryField,
15
12
  TopicDetailsResponse,
16
- AvailableCatalogs,
17
13
  AlgoliaPaginateRecords,
18
- CfSys,
19
14
  WrapperImageFields,
20
15
  } from "../types";
21
16
  import type { Entry } from "contentful-management/dist/typings/entities/entry";
@@ -62,216 +57,6 @@ const indexKey: AvailableIndicesKey = "products";
62
57
  const topicProductSelect =
63
58
  "sys,fields.name,fields.code,fields.catalogs,fields.categoriesArchitectural,fields.categoriesOutdoor,fields.categoriesDecorative,fields.families,fields.subFamiliesArchitectural,fields.subFamiliesOutdoor,fields.subFamiliesDecorative,fields.modelsArchitectural,fields.modelsOutdoor,fields.modelsDecorative,fields.subModelsArchitectural,fields.subModelsOutdoor,fields.subModelsDecorative,fields.productLine,fields.productSubLine,fields.productFields,fields.thumbnailImgix";
64
59
 
65
- const getLightModuleAutoDescriptionByProductFields = async (
66
- productFileds: any,
67
- catalogs: AvailableCatalogs[]
68
- ) => {
69
- const autoDescription: any = {};
70
- const dictionaryJson = await getDictionaryJson();
71
- for (const locale of cfLocales) {
72
- if (!autoDescription?.[locale]) {
73
- autoDescription[locale] = "";
74
- }
75
- let addSeparator = false;
76
- if (productFileds?.electrical?.lampCategories) {
77
- const lampCategoriesLocalizedValues = [];
78
- for (const lampCategory of productFileds.electrical.lampCategories) {
79
- const lampCategoryLocalizedValue = await getDictionaryLocaleValue(
80
- locale,
81
- "lampCategories",
82
- lampCategory.code,
83
- "electrical",
84
- dictionaryJson
85
- );
86
- if (lampCategoryLocalizedValue) {
87
- lampCategoriesLocalizedValues.push(lampCategoryLocalizedValue);
88
- }
89
- }
90
-
91
- if (lampCategoriesLocalizedValues.length) {
92
- if (addSeparator) {
93
- autoDescription[locale] += " - ";
94
- } else {
95
- addSeparator = true;
96
- }
97
- autoDescription[locale] += lampCategoriesLocalizedValues.join(", ");
98
- }
99
- }
100
-
101
- if (
102
- productFileds?.electrical?.wPower &&
103
- catalogs.indexOf("ARCHITECTURAL") !== -1
104
- ) {
105
- if (addSeparator) {
106
- autoDescription[locale] += " - ";
107
- } else {
108
- addSeparator = true;
109
- }
110
- autoDescription[locale] += productFileds.electrical.wPower;
111
- }
112
-
113
- if (
114
- productFileds?.optical?.numberOfHeads &&
115
- productFileds?.optical?.numberOfHeads > 1 &&
116
- productFileds?.photometric?.realNetFlow &&
117
- catalogs.indexOf("ARCHITECTURAL") !== -1
118
- ) {
119
- if (addSeparator) {
120
- autoDescription[locale] += " - ";
121
- } else {
122
- addSeparator = true;
123
- }
124
- autoDescription[locale] +=
125
- productFileds.optical.numberOfHeads +
126
- " x " +
127
- productFileds.photometric.realNetFlow;
128
- } else if (
129
- productFileds?.photometric?.realNetFlow &&
130
- catalogs.indexOf("ARCHITECTURAL") !== -1
131
- ) {
132
- if (addSeparator) {
133
- autoDescription[locale] += " - ";
134
- } else {
135
- addSeparator = true;
136
- }
137
- autoDescription[locale] += productFileds.photometric.realNetFlow;
138
- }
139
-
140
- if (productFileds?.photometric?.temperatureColor?.code) {
141
- const temperatireColorLocalizedValue = await getDictionaryLocaleValue(
142
- locale,
143
- "temperatureColor",
144
- productFileds.photometric.temperatureColor.code,
145
- "photometric",
146
- dictionaryJson
147
- );
148
- if (temperatireColorLocalizedValue) {
149
- if (addSeparator) {
150
- autoDescription[locale] += " - ";
151
- } else {
152
- addSeparator = true;
153
- }
154
- autoDescription[locale] += temperatireColorLocalizedValue;
155
- }
156
- }
157
-
158
- if (productFileds?.photometric?.cri?.code) {
159
- const CriLocalizedValue = await getDictionaryLocaleValue(
160
- locale,
161
- "cri",
162
- productFileds.photometric.cri.code,
163
- "photometric",
164
- dictionaryJson
165
- );
166
- if (CriLocalizedValue) {
167
- if (addSeparator) {
168
- autoDescription[locale] += " - ";
169
- } else {
170
- addSeparator = true;
171
- }
172
- autoDescription[locale] += "CRI " + CriLocalizedValue;
173
- }
174
- }
175
-
176
- if (
177
- productFileds?.photometric?.beam0_180 &&
178
- catalogs.indexOf("OUTDOOR") !== -1
179
- ) {
180
- if (addSeparator) {
181
- autoDescription[locale] += " - ";
182
- } else {
183
- addSeparator = true;
184
- }
185
- autoDescription[locale] += "BEAM " + productFileds.photometric.beam0_180;
186
- }
187
- }
188
-
189
- return autoDescription;
190
- };
191
-
192
- const getOtherAutoDescriptionByProductFields = async (productFileds: any) => {
193
- const autoDescription: any = {};
194
- const dictionaryJson = await getDictionaryJson();
195
- for (const locale of cfLocales) {
196
- if (!autoDescription?.[locale]) {
197
- autoDescription[locale] = "";
198
- }
199
- let addSeparator = false;
200
- // Profile and others
201
- if (productFileds?.physical?.length) {
202
- autoDescription[locale] += "Length: " + productFileds.physical.length;
203
- addSeparator = true;
204
- }
205
-
206
- if (productFileds?.mountings) {
207
- const mountingsLocalizedValues = [];
208
- for (const mounting of productFileds.mountings) {
209
- const mountingLocalizedValue = await getDictionaryLocaleValue(
210
- locale,
211
- "mountings",
212
- mounting.code,
213
- "",
214
- dictionaryJson
215
- );
216
- if (mountingLocalizedValue) {
217
- mountingsLocalizedValues.push(mountingLocalizedValue);
218
- }
219
- }
220
-
221
- if (addSeparator) {
222
- autoDescription[locale] += " - ";
223
- } else {
224
- addSeparator = true;
225
- }
226
- autoDescription[locale] += mountingsLocalizedValues.join(", ");
227
- }
228
- }
229
- };
230
-
231
- /**
232
- * Get topicProduct autoDescription
233
- *
234
- * @param topicProduct
235
- * @returns
236
- */
237
- const getTopicProductAutodescription = async (topicProduct: Entry) => {
238
- const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
239
- let catalogs = topicProduct?.fields?.catalogs?.[defaultEnvironmentLocaleCode];
240
- if (catalogs) {
241
- catalogs = catalogs.map((catalog: CfSys) => catalog.sys.id);
242
- }
243
- const productLineCode =
244
- topicProduct?.fields?.productLine?.[defaultEnvironmentLocaleCode]?.sys?.id;
245
- const productFileds =
246
- topicProduct?.fields?.productFields?.[defaultEnvironmentLocaleCode];
247
-
248
- let autoDescription: any = {};
249
- switch (productLineCode) {
250
- case "PLINE6": // Soft Plate
251
- case "PLINE5": // Light Bulb
252
- case "PLINE3": // Driver
253
- case "PLINE2": // Accessory
254
- // post_content
255
- autoDescription = topicProduct?.fields?.description;
256
- break;
257
- case "PLINE1": // Light Module
258
- autoDescription = await getLightModuleAutoDescriptionByProductFields(
259
- productFileds,
260
- catalogs
261
- );
262
-
263
- break;
264
- default:
265
- autoDescription = await getOtherAutoDescriptionByProductFields(
266
- productFileds
267
- );
268
-
269
- break;
270
- }
271
-
272
- return autoDescription;
273
- };
274
-
275
60
  const pipedreamPDFGenerator = async (topicProductId: string) => {
276
61
  if (process.env.FPI_PIPEDREAM_TECH_SPEC_PDF) {
277
62
  const res = await axios.get(process.env.FPI_PIPEDREAM_TECH_SPEC_PDF, {
@@ -369,7 +154,6 @@ const getObject = async (
369
154
  topicProductWithFields,
370
155
  "subFamiliesArchitectural",
371
156
  "topicSubFamily",
372
- true,
373
157
  true
374
158
  );
375
159
 
@@ -378,7 +162,6 @@ const getObject = async (
378
162
  topicProductWithFields,
379
163
  "subFamiliesOutdoor",
380
164
  "topicSubFamily",
381
- true,
382
165
  true
383
166
  );
384
167
 
@@ -387,7 +170,6 @@ const getObject = async (
387
170
  topicProductWithFields,
388
171
  "subFamiliesDecorative",
389
172
  "topicSubFamily",
390
- true,
391
173
  true
392
174
  );
393
175
 
@@ -456,9 +238,7 @@ const getObject = async (
456
238
  );
457
239
 
458
240
  log(`Get autoDescription...`);
459
- const autoDescription = await getTopicProductAutodescription(
460
- topicProductWithFields
461
- );
241
+ const autoDescription = topicProductWithFields?.fields?.autoDescription ?? {};
462
242
 
463
243
  log(`Get thumbnail imgix details...`);
464
244
  let thumbnailImgix = {};
@@ -0,0 +1,187 @@
1
+ import { log } from "../libs/logs";
2
+ import {
3
+ getClient,
4
+ getEnvironmentDefaultLocaleCode,
5
+ getEntryByID,
6
+ getTopicPage,
7
+ } from "../libs/contentful-cda";
8
+ import { getIndex, AvailableIndicesKey, removeIndexObject } from "./config";
9
+ import { getLocalISOTime, secondBetweenTwoDate } from "../utils";
10
+ import type { Entry } from "contentful-management/dist/typings/entities/entry";
11
+ import { CfLocalizedEntryField, AlgoliaPaginateRecords } from "../types";
12
+
13
+ const indexKey: AvailableIndicesKey = "stories";
14
+
15
+ export type AlgoliaStoryRecord = {
16
+ objectID: string;
17
+ name?: CfLocalizedEntryField;
18
+ excerpt?: CfLocalizedEntryField;
19
+ description?: CfLocalizedEntryField;
20
+ slugs?: {};
21
+ lastSyncDate?: string;
22
+ };
23
+
24
+ const getObject = async (topicStory: Entry): Promise<AlgoliaStoryRecord> => {
25
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
26
+ log(`Sync the ${topicStory.sys.id} topicStory...`);
27
+ let topicStoryWithFields: Entry = topicStory;
28
+
29
+ const emptyLocalizedField: CfLocalizedEntryField = {
30
+ [defaultEnvironmentLocaleCode]: "",
31
+ };
32
+
33
+ if (!topicStoryWithFields?.fields) {
34
+ log(`Get the ${topicStory.sys.id} topicStory details...`);
35
+ topicStoryWithFields = await getEntryByID(topicStory.sys.id, "topicStory");
36
+ }
37
+
38
+ if (!topicStoryWithFields) {
39
+ log(`The topicStory ${topicStory.sys.id} not found`, "WARN");
40
+
41
+ const recordFail: AlgoliaStoryRecord = {
42
+ objectID: topicStory?.sys?.id,
43
+ };
44
+
45
+ return recordFail; // return objectID to delete the record if it exists
46
+ }
47
+
48
+ log(`Get page details...`);
49
+ const page = await getTopicPage(topicStory.sys.id, "fields.slug");
50
+ const slugs = page?.fields.slug || {};
51
+
52
+ // Single record
53
+ const record: AlgoliaStoryRecord = {
54
+ objectID: topicStoryWithFields.sys.id,
55
+ name: topicStoryWithFields?.fields?.title || emptyLocalizedField,
56
+ excerpt: topicStoryWithFields?.fields?.excerpt || emptyLocalizedField,
57
+ description:
58
+ topicStoryWithFields?.fields?.description || emptyLocalizedField,
59
+ slugs,
60
+ lastSyncDate: getLocalISOTime(),
61
+ };
62
+
63
+ return record;
64
+ };
65
+
66
+ export const reindexStory = async (topicStoryId: string) => {
67
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
68
+ const timeStart = new Date();
69
+
70
+ log(`reindexStory - entryId: ${topicStoryId} `);
71
+
72
+ const topicStory = await getEntryByID(topicStoryId, "topicStory");
73
+
74
+ if (!topicStory) {
75
+ log(`No topicStoryId found with id ${topicStoryId}`, "WARN");
76
+ return false;
77
+ }
78
+
79
+ const object = await getObject(topicStory);
80
+
81
+ // Save record to Algolia
82
+ const index = getIndex(indexKey);
83
+ let record = null;
84
+ const slugs: any = object?.slugs;
85
+ if (slugs?.[defaultEnvironmentLocaleCode]) {
86
+ log(`Save object`);
87
+ record = await index.saveObject(object);
88
+ } else {
89
+ log(`Delete object`);
90
+ record = await index.deleteObject(object.objectID);
91
+ }
92
+ const timeEnd = new Date();
93
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
94
+ log(`Execution time: ${seconds} seconds`);
95
+
96
+ return { ...record, ...object };
97
+ };
98
+
99
+ /**
100
+ * Get Objects
101
+ *
102
+ * @param offset
103
+ * @param limit
104
+ * @param filterKey
105
+ * @param filterValue
106
+ * @returns
107
+ */
108
+ const getObjects = async (
109
+ offset: number,
110
+ limit: number,
111
+ filterKey?: string,
112
+ filterValue?: string
113
+ ): Promise<AlgoliaPaginateRecords> => {
114
+ const client = await getClient();
115
+
116
+ const opts: any = {
117
+ content_type: "topicStory",
118
+ limit,
119
+ skip: offset,
120
+ locale: "*",
121
+ // select: "",
122
+ };
123
+ if (filterKey && filterValue) {
124
+ opts[filterKey] = filterValue;
125
+ }
126
+ const { items, total } = await client.getEntries(opts);
127
+
128
+ const objects: AlgoliaStoryRecord[] = [];
129
+ let count: number = Number(offset);
130
+ for (const topicStory of items) {
131
+ log(`${++count} of ${total}`, "INFO");
132
+ const timeStart = new Date();
133
+ const record = await getObject(topicStory);
134
+ const timeEnd = new Date();
135
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
136
+ log(`Execution time: ${seconds} seconds`);
137
+ objects.push(record);
138
+ }
139
+
140
+ return {
141
+ objects,
142
+ offset: Number(offset) + Number(limit),
143
+ limit: Number(limit),
144
+ completed: count >= total, // if is true the import is completed
145
+ total,
146
+ };
147
+ };
148
+
149
+ export const reindexStories = async (
150
+ offset: number = 0,
151
+ limit: number = 50,
152
+ filterKey: string = "",
153
+ filterValue: string = ""
154
+ ) => {
155
+ const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
156
+ const timeStart = new Date();
157
+ log(
158
+ `reindexStories - filterKey: ${filterKey} filterValue: ${filterValue} offset: ${offset} limit: ${limit} `
159
+ );
160
+
161
+ const records = await getObjects(offset, limit, filterKey, filterValue);
162
+ const objectsToSave = records.objects.filter(
163
+ (object) => object?.slugs?.[defaultEnvironmentLocaleCode]
164
+ );
165
+ const objectIdsToDelete = records.objects
166
+ .filter((object) => !object?.slugs?.[defaultEnvironmentLocaleCode])
167
+ .map((object) => object.objectID);
168
+
169
+ // Save records to Algolia
170
+ const index = getIndex(indexKey);
171
+ log(`Save ${objectsToSave.length} objects to ${index.indexName} index`);
172
+ const savedObjectIDs = await index.saveObjects(objectsToSave);
173
+ log(
174
+ `Delete ${objectIdsToDelete.length} objects from ${index.indexName} index`
175
+ );
176
+ const deletedObjectIDs = await index.deleteObjects(objectIdsToDelete);
177
+
178
+ const timeEnd = new Date();
179
+ const seconds = secondBetweenTwoDate(timeStart, timeEnd);
180
+ log(`Execution time: ${seconds} seconds`);
181
+
182
+ return { ...records, ...savedObjectIDs, ...deletedObjectIDs };
183
+ };
184
+
185
+ export const removeStoryObject = async (objectId: string) => {
186
+ return removeIndexObject(objectId, indexKey);
187
+ };
@@ -39,7 +39,7 @@ const getSubFamilyPage = async (
39
39
  return {
40
40
  slugs: {},
41
41
  type: "",
42
- details: {},
42
+ // details: {},
43
43
  };
44
44
  }
45
45
 
@@ -67,26 +67,26 @@ const getSubFamilyPage = async (
67
67
  "fields.slug,fields.type"
68
68
  );
69
69
 
70
- const catalogEntryId =
71
- modelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys?.id;
72
- const modelCatalogPage: any = catalogEntryId
73
- ? await getEntryByID(`${catalogEntryId}_PAGE`, "page", "fields.slug")
74
- : {};
75
- const subFamilyEntryId =
76
- modelEntry?.fields?.subFamily?.[defaultEnvironmentLocaleCode]?.sys?.id;
77
- const modelCatalogSubFamilyPage: any = subFamilyEntryId
78
- ? await getEntryByID(`${subFamilyEntryId}_PAGE`, "page", "fields.slug")
79
- : {};
70
+ // const catalogEntryId =
71
+ // modelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys?.id;
72
+ // const modelCatalogPage: any = catalogEntryId
73
+ // ? await getEntryByID(`${catalogEntryId}_PAGE`, "page", "fields.slug")
74
+ // : {};
75
+ // const subFamilyEntryId =
76
+ // modelEntry?.fields?.subFamily?.[defaultEnvironmentLocaleCode]?.sys?.id;
77
+ // const modelCatalogSubFamilyPage: any = subFamilyEntryId
78
+ // ? await getEntryByID(`${subFamilyEntryId}_PAGE`, "page", "fields.slug")
79
+ // : {};
80
80
  if (modelPage) {
81
81
  return {
82
82
  slugs: modelPage?.fields?.slug,
83
83
  type: modelPage?.fields?.type?.[defaultEnvironmentLocaleCode],
84
- details: {
85
- catalogPageSlugs:
86
- keysToLowerCase(modelCatalogPage?.fields?.slug) || {},
87
- subFamilyPageSlugs:
88
- keysToLowerCase(modelCatalogSubFamilyPage?.fields?.slug) || {},
89
- },
84
+ // details: {
85
+ // catalogPageSlugs:
86
+ // keysToLowerCase(modelCatalogPage?.fields?.slug) || {},
87
+ // subFamilyPageSlugs:
88
+ // keysToLowerCase(modelCatalogSubFamilyPage?.fields?.slug) || {},
89
+ // },
90
90
  };
91
91
  } else {
92
92
  log(`The modelPage with id "${modelPageId}" not found`, "WARN");
@@ -314,7 +314,7 @@ const getObject = async (
314
314
  fullScreenImageImgix,
315
315
  slugs: keysToLowerCase(page?.slugs) || {},
316
316
  slugType: page?.type || "",
317
- slugDetails: page?.details || {},
317
+ // slugDetails: page?.details || {},
318
318
  catalogs,
319
319
  categories,
320
320
  productFields,
package/src/index.ts CHANGED
@@ -36,6 +36,7 @@ export {
36
36
  getAllProductEntriesByCatalog,
37
37
  audit,
38
38
  generateTechSpecPdf,
39
+ setProductAutodescription,
39
40
  } from "./pim/methods/products";
40
41
  // export {
41
42
  // createOrUpdateCatalogPages,
@@ -86,6 +87,11 @@ export {
86
87
  reindexProjects,
87
88
  removeProjectObject,
88
89
  } from "./algolia/projects";
90
+ export {
91
+ reindexStory,
92
+ reindexStories,
93
+ removeStoryObject,
94
+ } from "./algolia/stories";
89
95
  export { importDownloads } from "./downloads/import";
90
96
  export { getLocalISOTime } from "./utils";
91
97
  export { getStaticDailyProducts } from "./pim/endpoints";
@@ -427,7 +427,7 @@
427
427
  "type": "array"
428
428
  },
429
429
  {
430
- "key": "precabled",
430
+ "key": "preCabled",
431
431
  "parent": "physical",
432
432
  "icon": false,
433
433
  "dictionary": "",