pim-import 5.0.1 → 5.0.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.
- package/dist/algolia/clean.js +0 -1
- package/dist/algolia/config.js +0 -1
- package/dist/algolia/downloads.js +0 -1
- package/dist/algolia/families.js +0 -1
- package/dist/algolia/inspirations.js +0 -1
- package/dist/algolia/models.js +0 -1
- package/dist/algolia/news.js +0 -1
- package/dist/algolia/pressRelease.js +0 -1
- package/dist/algolia/pressReview.js +0 -1
- package/dist/algolia/products.js +0 -1
- package/dist/algolia/projects.js +0 -1
- package/dist/algolia/stories.js +0 -1
- package/dist/algolia/subFamilies.js +0 -1
- package/dist/algolia/subModels.js +0 -1
- package/dist/browser.js +0 -1
- package/dist/downloads/classes/manageEntry.js +0 -1
- package/dist/downloads/import.js +0 -1
- package/dist/index.js +0 -1
- package/dist/libs/contentful-cda.js +0 -1
- package/dist/libs/contentful.js +0 -1
- package/dist/libs/imgix.js +0 -1
- package/dist/libs/logs.js +0 -1
- package/dist/libs/netlify.js +0 -1
- package/dist/libs/notifications.js +0 -1
- package/dist/libs/pdf.js +0 -1
- package/dist/libs/s3.js +0 -1
- package/dist/libs/sentry.js +0 -1
- package/dist/pim/config.js +0 -1
- package/dist/pim/endpoints.js +0 -1
- package/dist/pim/methods/bulkPublish.js +0 -1
- package/dist/pim/methods/catalogs.js +0 -1
- package/dist/pim/methods/checkTopicDraftAndPagePublished.js +0 -1
- package/dist/pim/methods/designers.js +0 -1
- package/dist/pim/methods/dictionary.js +0 -1
- package/dist/pim/methods/families.js +0 -1
- package/dist/pim/methods/latestProducts.js +0 -1
- package/dist/pim/methods/migrateEntryFields.js +0 -1
- package/dist/pim/methods/models.js +0 -1
- package/dist/pim/methods/pages/catalogs.js +0 -1
- package/dist/pim/methods/pages/families.js +0 -1
- package/dist/pim/methods/pages/subfamilies.js +0 -1
- package/dist/pim/methods/products.js +0 -1
- package/dist/pim/methods/subfamilies.js +0 -1
- package/dist/pim/methods/submodels.js +0 -1
- package/dist/pim/request.js +0 -1
- package/dist/resources/AllProducts.js +0 -1
- package/dist/resources/Audit.js +0 -1
- package/dist/resources/CatalogDetails.js +0 -1
- package/dist/resources/CollectionModels.js +0 -1
- package/dist/resources/CollectionSubFamilies.js +0 -1
- package/dist/resources/CollectionSubModels.js +0 -1
- package/dist/resources/DProductSubLine.js +0 -1
- package/dist/resources/FamilyDetails.js +0 -1
- package/dist/resources/ProductDetails.js +0 -1
- package/dist/resources/ProductRelation.js +0 -1
- package/dist/resources/cfFields.js +0 -1
- package/dist/types.js +0 -1
- package/dist/utils.js +0 -1
- package/package.json +7 -2
- package/.env.example +0 -45
- package/.nvmrc +0 -1
- package/.vscode/settings.json +0 -21
- package/dist/algolia/clean.js.map +0 -1
- package/dist/algolia/config.js.map +0 -1
- package/dist/algolia/downloads.js.map +0 -1
- package/dist/algolia/families.js.map +0 -1
- package/dist/algolia/inspirations.js.map +0 -1
- package/dist/algolia/models.js.map +0 -1
- package/dist/algolia/news.js.map +0 -1
- package/dist/algolia/pressRelease.js.map +0 -1
- package/dist/algolia/pressReview.js.map +0 -1
- package/dist/algolia/products.js.map +0 -1
- package/dist/algolia/projects.js.map +0 -1
- package/dist/algolia/stories.js.map +0 -1
- package/dist/algolia/subFamilies.js.map +0 -1
- package/dist/algolia/subModels.js.map +0 -1
- package/dist/browser.js.map +0 -1
- package/dist/downloads/classes/manageEntry.js.map +0 -1
- package/dist/downloads/import.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/libs/contentful-cda.js.map +0 -1
- package/dist/libs/contentful.js.map +0 -1
- package/dist/libs/imgix.js.map +0 -1
- package/dist/libs/logs.js.map +0 -1
- package/dist/libs/netlify.js.map +0 -1
- package/dist/libs/notifications.js.map +0 -1
- package/dist/libs/pdf.js.map +0 -1
- package/dist/libs/s3.js.map +0 -1
- package/dist/libs/sentry.js.map +0 -1
- package/dist/pim/config.js.map +0 -1
- package/dist/pim/endpoints.js.map +0 -1
- package/dist/pim/methods/bulkPublish.js.map +0 -1
- package/dist/pim/methods/catalogs.js.map +0 -1
- package/dist/pim/methods/checkTopicDraftAndPagePublished.js.map +0 -1
- package/dist/pim/methods/designers.js.map +0 -1
- package/dist/pim/methods/dictionary.js.map +0 -1
- package/dist/pim/methods/families.js.map +0 -1
- package/dist/pim/methods/latestProducts.js.map +0 -1
- package/dist/pim/methods/migrateEntryFields.js.map +0 -1
- package/dist/pim/methods/models.js.map +0 -1
- package/dist/pim/methods/pages/catalogs.js.map +0 -1
- package/dist/pim/methods/pages/families.js.map +0 -1
- package/dist/pim/methods/pages/subfamilies.js.map +0 -1
- package/dist/pim/methods/products.js.map +0 -1
- package/dist/pim/methods/subfamilies.js.map +0 -1
- package/dist/pim/methods/submodels.js.map +0 -1
- package/dist/pim/request.js.map +0 -1
- package/dist/resources/AllProducts.js.map +0 -1
- package/dist/resources/Audit.js.map +0 -1
- package/dist/resources/CatalogDetails.js.map +0 -1
- package/dist/resources/CollectionModels.js.map +0 -1
- package/dist/resources/CollectionSubFamilies.js.map +0 -1
- package/dist/resources/CollectionSubModels.js.map +0 -1
- package/dist/resources/DProductSubLine.js.map +0 -1
- package/dist/resources/FamilyDetails.js.map +0 -1
- package/dist/resources/ProductDetails.js.map +0 -1
- package/dist/resources/ProductRelation.js.map +0 -1
- package/dist/resources/cfFields.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils.js.map +0 -1
- package/docs/import-data-from-the-dictionary.md +0 -83
- package/docs/import-products.md +0 -61
- package/docs/import-taxonomies-from-the-catalog.md +0 -60
- package/docs/settings.md +0 -47
- package/jest.config.js +0 -16
- package/local-fn/reindex.js +0 -182
- package/src/algolia/clean.ts +0 -164
- package/src/algolia/config.ts +0 -390
- package/src/algolia/downloads.ts +0 -346
- package/src/algolia/families.ts +0 -652
- package/src/algolia/inspirations.ts +0 -315
- package/src/algolia/models.ts +0 -589
- package/src/algolia/news.ts +0 -258
- package/src/algolia/pressRelease.ts +0 -255
- package/src/algolia/pressReview.ts +0 -247
- package/src/algolia/products.ts +0 -731
- package/src/algolia/projects.ts +0 -339
- package/src/algolia/stories.ts +0 -347
- package/src/algolia/subFamilies.ts +0 -709
- package/src/algolia/subModels.ts +0 -359
- package/src/browser.ts +0 -122
- package/src/downloads/classes/manageEntry.ts +0 -99
- package/src/downloads/csv/legal.csv +0 -5
- package/src/downloads/csv/products.csv +0 -373
- package/src/downloads/import.ts +0 -381
- package/src/index.ts +0 -140
- package/src/libs/contentful-cda.ts +0 -543
- package/src/libs/contentful.ts +0 -1453
- package/src/libs/imgix.ts +0 -297
- package/src/libs/logs.ts +0 -121
- package/src/libs/netlify.ts +0 -37
- package/src/libs/notifications.ts +0 -104
- package/src/libs/pdf.ts +0 -107
- package/src/libs/s3.ts +0 -305
- package/src/libs/sentry.ts +0 -33
- package/src/pim/config.ts +0 -84
- package/src/pim/data/productFields.json +0 -1178
- package/src/pim/endpoints.ts +0 -364
- package/src/pim/methods/bulkPublish.ts +0 -266
- package/src/pim/methods/catalogs.ts +0 -586
- package/src/pim/methods/checkTopicDraftAndPagePublished.ts +0 -70
- package/src/pim/methods/designers.ts +0 -128
- package/src/pim/methods/dictionary.ts +0 -611
- package/src/pim/methods/families.ts +0 -345
- package/src/pim/methods/latestProducts.ts +0 -70
- package/src/pim/methods/migrateEntryFields.ts +0 -99
- package/src/pim/methods/models.ts +0 -349
- package/src/pim/methods/pages/catalogs.ts +0 -28
- package/src/pim/methods/pages/families.ts +0 -50
- package/src/pim/methods/pages/subfamilies.ts +0 -98
- package/src/pim/methods/products.ts +0 -3297
- package/src/pim/methods/subfamilies.ts +0 -706
- package/src/pim/methods/submodels.ts +0 -262
- package/src/pim/request.ts +0 -61
- package/src/resources/AllProducts.ts +0 -41
- package/src/resources/Audit.ts +0 -24
- package/src/resources/CatalogDetails.ts +0 -51
- package/src/resources/CollectionModels.ts +0 -42
- package/src/resources/CollectionSubFamilies.ts +0 -45
- package/src/resources/CollectionSubModels.ts +0 -36
- package/src/resources/DProductSubLine.ts +0 -34
- package/src/resources/FamilyDetails.ts +0 -31
- package/src/resources/ProductDetails.ts +0 -352
- package/src/resources/ProductRelation.ts +0 -24
- package/src/resources/cfFields.ts +0 -8
- package/src/types.ts +0 -268
- package/src/utils.ts +0 -553
- package/tsconfig.json +0 -93
- package/tslint.json +0 -22
- package/types/libs/puppeteer.d.ts +0 -17
- package/types/pim/methods/checkIp.d.ts +0 -1
- /package/{types → dist}/algolia/clean.d.ts +0 -0
- /package/{types → dist}/algolia/config.d.ts +0 -0
- /package/{types → dist}/algolia/downloads.d.ts +0 -0
- /package/{types → dist}/algolia/families.d.ts +0 -0
- /package/{types → dist}/algolia/inspirations.d.ts +0 -0
- /package/{types → dist}/algolia/models.d.ts +0 -0
- /package/{types → dist}/algolia/news.d.ts +0 -0
- /package/{types → dist}/algolia/pressRelease.d.ts +0 -0
- /package/{types → dist}/algolia/pressReview.d.ts +0 -0
- /package/{types → dist}/algolia/products.d.ts +0 -0
- /package/{types → dist}/algolia/projects.d.ts +0 -0
- /package/{types → dist}/algolia/stories.d.ts +0 -0
- /package/{types → dist}/algolia/subFamilies.d.ts +0 -0
- /package/{types → dist}/algolia/subModels.d.ts +0 -0
- /package/{types → dist}/browser.d.ts +0 -0
- /package/{types → dist}/downloads/classes/manageEntry.d.ts +0 -0
- /package/{types → dist}/downloads/import.d.ts +0 -0
- /package/{types → dist}/index.d.ts +0 -0
- /package/{types → dist}/libs/contentful-cda.d.ts +0 -0
- /package/{types → dist}/libs/contentful.d.ts +0 -0
- /package/{types → dist}/libs/imgix.d.ts +0 -0
- /package/{types → dist}/libs/logs.d.ts +0 -0
- /package/{types → dist}/libs/netlify.d.ts +0 -0
- /package/{types → dist}/libs/notifications.d.ts +0 -0
- /package/{types → dist}/libs/pdf.d.ts +0 -0
- /package/{types → dist}/libs/s3.d.ts +0 -0
- /package/{types → dist}/libs/sentry.d.ts +0 -0
- /package/{types → dist}/pim/config.d.ts +0 -0
- /package/{types → dist}/pim/endpoints.d.ts +0 -0
- /package/{types → dist}/pim/methods/bulkPublish.d.ts +0 -0
- /package/{types → dist}/pim/methods/catalogs.d.ts +0 -0
- /package/{types → dist}/pim/methods/checkTopicDraftAndPagePublished.d.ts +0 -0
- /package/{types → dist}/pim/methods/designers.d.ts +0 -0
- /package/{types → dist}/pim/methods/dictionary.d.ts +0 -0
- /package/{types → dist}/pim/methods/families.d.ts +0 -0
- /package/{types → dist}/pim/methods/latestProducts.d.ts +0 -0
- /package/{types → dist}/pim/methods/migrateEntryFields.d.ts +0 -0
- /package/{types → dist}/pim/methods/models.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/catalogs.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/families.d.ts +0 -0
- /package/{types → dist}/pim/methods/pages/subfamilies.d.ts +0 -0
- /package/{types → dist}/pim/methods/products.d.ts +0 -0
- /package/{types → dist}/pim/methods/subfamilies.d.ts +0 -0
- /package/{types → dist}/pim/methods/submodels.d.ts +0 -0
- /package/{types → dist}/pim/request.d.ts +0 -0
- /package/{types → dist}/resources/AllProducts.d.ts +0 -0
- /package/{types → dist}/resources/Audit.d.ts +0 -0
- /package/{types → dist}/resources/CatalogDetails.d.ts +0 -0
- /package/{types → dist}/resources/CollectionModels.d.ts +0 -0
- /package/{types → dist}/resources/CollectionSubFamilies.d.ts +0 -0
- /package/{types → dist}/resources/CollectionSubModels.d.ts +0 -0
- /package/{types → dist}/resources/DProductSubLine.d.ts +0 -0
- /package/{types → dist}/resources/FamilyDetails.d.ts +0 -0
- /package/{types → dist}/resources/ProductDetails.d.ts +0 -0
- /package/{types → dist}/resources/ProductRelation.d.ts +0 -0
- /package/{types → dist}/resources/cfFields.d.ts +0 -0
- /package/{types → dist}/types.d.ts +0 -0
- /package/{types → dist}/utils.d.ts +0 -0
|
@@ -1,3297 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ProductDetails,
|
|
3
|
-
AssetsEntity,
|
|
4
|
-
ColourVariant,
|
|
5
|
-
} from "../../resources/ProductDetails";
|
|
6
|
-
import { AllProductsEntry } from "../../resources/AllProducts";
|
|
7
|
-
import { ProductRelation } from "../../resources/ProductRelation";
|
|
8
|
-
import { FieldItem } from "../../resources/cfFields";
|
|
9
|
-
import { Audit } from "../../resources/Audit";
|
|
10
|
-
import {
|
|
11
|
-
AvailableCatalogs,
|
|
12
|
-
CfLocalizedEntryField,
|
|
13
|
-
WrapperImageFields,
|
|
14
|
-
CfSys,
|
|
15
|
-
} from "../../types";
|
|
16
|
-
import { log, serverUtils } from "../../libs/logs";
|
|
17
|
-
import {
|
|
18
|
-
getEntryByCode,
|
|
19
|
-
getAllEntriesByCodes,
|
|
20
|
-
getEnvironmentDefaultLocaleCode,
|
|
21
|
-
createEntryWithId,
|
|
22
|
-
cfLocales,
|
|
23
|
-
getEntryByID,
|
|
24
|
-
updateEntry,
|
|
25
|
-
getEnvironment,
|
|
26
|
-
addFieldValue,
|
|
27
|
-
addToRelationFields,
|
|
28
|
-
removeFromRelationFields,
|
|
29
|
-
removeFromFieldObject,
|
|
30
|
-
createWrapperImgix,
|
|
31
|
-
getDictionaryLocaleValue,
|
|
32
|
-
getDictionaryJson,
|
|
33
|
-
getAllEntries,
|
|
34
|
-
archiveEntry,
|
|
35
|
-
} from "../../libs/contentful";
|
|
36
|
-
import type {
|
|
37
|
-
Entry,
|
|
38
|
-
CreateEntryProps,
|
|
39
|
-
} from "contentful-management/dist/typings/entities/entry";
|
|
40
|
-
import { KeyValueMap } from "contentful-management/dist/typings/common-types";
|
|
41
|
-
import {
|
|
42
|
-
stringToSlug,
|
|
43
|
-
secondBetweenTwoDate,
|
|
44
|
-
sleep,
|
|
45
|
-
getLocalISOTime,
|
|
46
|
-
capitalizeFirstLetter,
|
|
47
|
-
sanitizeValue,
|
|
48
|
-
getPimTranslations,
|
|
49
|
-
basename,
|
|
50
|
-
} from "../../utils";
|
|
51
|
-
import {
|
|
52
|
-
saveAllProductsToS3,
|
|
53
|
-
getFileFromS3,
|
|
54
|
-
saveJsonToS3,
|
|
55
|
-
upload as uploadToS3,
|
|
56
|
-
} from "../../libs/s3";
|
|
57
|
-
import { getAudit, getProductDetails } from "../endpoints";
|
|
58
|
-
import { getCategoryTopicCode } from "./catalogs";
|
|
59
|
-
import productFieldsRequiredData from "../data/productFields.json";
|
|
60
|
-
import {
|
|
61
|
-
getDefaultWrapperImgixAttributesByPimUrl,
|
|
62
|
-
getImgixPimUrlByOriginPath,
|
|
63
|
-
getOriginPathByPimUrl,
|
|
64
|
-
purgeImageCacheByUrl,
|
|
65
|
-
} from "../../libs/imgix";
|
|
66
|
-
import { generatePDFByUrl } from "../../libs/pdf";
|
|
67
|
-
import { reindexProduct } from "../../algolia/products";
|
|
68
|
-
import { addDesignerData } from "./designers";
|
|
69
|
-
import { notify } from "../../libs/notifications";
|
|
70
|
-
|
|
71
|
-
export type AvailableProductStatus =
|
|
72
|
-
| "To be review"
|
|
73
|
-
| "Published"
|
|
74
|
-
| "Unpublished";
|
|
75
|
-
|
|
76
|
-
export type AvailableRelationFieldKeys =
|
|
77
|
-
| "accessories"
|
|
78
|
-
| "accessoryOf"
|
|
79
|
-
| "bulbOf"
|
|
80
|
-
| "sparepartOf"
|
|
81
|
-
| "bulbs"
|
|
82
|
-
| "spareparts";
|
|
83
|
-
|
|
84
|
-
const PIM_DUPLICATE_SEPARATOR: string = "~";
|
|
85
|
-
const S3_PIM_PAYLOAD_PATH = `pim/payload/`;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Check if the sku passed belongs to a product which should not be imported
|
|
89
|
-
* but which needs to be used to create product associations -> additional taxonomy terms.
|
|
90
|
-
*
|
|
91
|
-
* It returns false only if it is an product that needs to be imported or the the updated productEntry
|
|
92
|
-
*
|
|
93
|
-
* @param productDetails
|
|
94
|
-
* @returns peoductEntry or boolean
|
|
95
|
-
*/
|
|
96
|
-
const isTermsToAdd = async (
|
|
97
|
-
productDetails: ProductDetails,
|
|
98
|
-
catalog: AvailableCatalogs
|
|
99
|
-
): Promise<Entry | boolean> => {
|
|
100
|
-
if (!productDetails.code.includes(PIM_DUPLICATE_SEPARATOR)) {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
log(
|
|
104
|
-
`Product used to create associations between product and additional taxonomy terms: ${productDetails.code}`
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
const realCode = productDetails.code.substring(
|
|
108
|
-
0,
|
|
109
|
-
productDetails.code.indexOf(PIM_DUPLICATE_SEPARATOR)
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
let productEntry: Entry = await getEntryByCode(realCode, "topicProduct");
|
|
113
|
-
if (!productEntry) {
|
|
114
|
-
log(
|
|
115
|
-
`The product ${realCode} does not exist, it is not possible to save the additional association with the ${productDetails?.currentCatalog?.subFamilyCode} family and the ${productDetails?.currentCatalog?.categoryCode} category`
|
|
116
|
-
);
|
|
117
|
-
return true;
|
|
118
|
-
} else if (productEntry.isArchived()) {
|
|
119
|
-
log(
|
|
120
|
-
`The product ${realCode} is archived, it is not possible to save the additional association with the ${productDetails?.currentCatalog?.subFamilyCode} family and the ${productDetails?.currentCatalog?.categoryCode} category`
|
|
121
|
-
);
|
|
122
|
-
return true;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
// product -> catalog relation
|
|
126
|
-
const catalogFieldKey = "catalogs";
|
|
127
|
-
if (productDetails.currentCatalog?.catalogCode) {
|
|
128
|
-
const catalogEntry: Entry = await getEntryByCode(
|
|
129
|
-
productDetails.currentCatalog.catalogCode,
|
|
130
|
-
"topicCatalog",
|
|
131
|
-
"sys"
|
|
132
|
-
);
|
|
133
|
-
if (catalogEntry) {
|
|
134
|
-
log(
|
|
135
|
-
`Start the association of the ${realCode} with the ${productDetails.currentCatalog.catalogCode} catalog`
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
productEntry.fields = await addToRelationFields(
|
|
139
|
-
productEntry,
|
|
140
|
-
catalogFieldKey,
|
|
141
|
-
catalogEntry.sys.id,
|
|
142
|
-
true
|
|
143
|
-
);
|
|
144
|
-
} else {
|
|
145
|
-
log(
|
|
146
|
-
`The ${productDetails.currentCatalog.catalogCode} catalog does not exist`
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
} else {
|
|
150
|
-
log(`No catalog code found`, "WARN");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// product -> category relation
|
|
154
|
-
const categoriesFieldKey = "categories" + capitalizeFirstLetter(catalog);
|
|
155
|
-
if (productDetails.currentCatalog?.categoryCode) {
|
|
156
|
-
const categoryTopicCode = getCategoryTopicCode(
|
|
157
|
-
productDetails.currentCatalog.categoryCode,
|
|
158
|
-
catalog
|
|
159
|
-
);
|
|
160
|
-
const categoryEntry: Entry = await getEntryByCode(
|
|
161
|
-
categoryTopicCode,
|
|
162
|
-
"topicCategory",
|
|
163
|
-
"sys"
|
|
164
|
-
);
|
|
165
|
-
if (categoryEntry) {
|
|
166
|
-
log(
|
|
167
|
-
`Start the association of the ${realCode} with the ${categoryTopicCode} category`
|
|
168
|
-
);
|
|
169
|
-
productEntry.fields = await addToRelationFields(
|
|
170
|
-
productEntry,
|
|
171
|
-
categoriesFieldKey,
|
|
172
|
-
categoryEntry.sys.id,
|
|
173
|
-
true
|
|
174
|
-
);
|
|
175
|
-
} else {
|
|
176
|
-
log(`The ${categoryTopicCode} category does not exist`);
|
|
177
|
-
}
|
|
178
|
-
} else {
|
|
179
|
-
log(`No category code found`, "WARN");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// product -> family relation
|
|
183
|
-
const familiesFieldKey = "families";
|
|
184
|
-
if (productDetails.currentCatalog?.familyCode) {
|
|
185
|
-
const familyEntry: Entry = await getEntryByCode(
|
|
186
|
-
productDetails.currentCatalog.familyCode,
|
|
187
|
-
"topicFamily",
|
|
188
|
-
"sys"
|
|
189
|
-
);
|
|
190
|
-
if (familyEntry) {
|
|
191
|
-
log(
|
|
192
|
-
`Start the association of the ${realCode} with the ${productDetails.currentCatalog.familyCode} family`
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
productEntry.fields = await addToRelationFields(
|
|
196
|
-
productEntry,
|
|
197
|
-
familiesFieldKey,
|
|
198
|
-
familyEntry.sys.id,
|
|
199
|
-
true
|
|
200
|
-
);
|
|
201
|
-
} else {
|
|
202
|
-
log(
|
|
203
|
-
`The ${productDetails.currentCatalog.familyCode} family does not exist`
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
} else {
|
|
207
|
-
log(`No family code found`, "WARN");
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// product -> subFamily relation
|
|
211
|
-
const subFamiliesFieldKey = "subFamilies" + capitalizeFirstLetter(catalog);
|
|
212
|
-
if (productDetails.currentCatalog?.subFamilyCode) {
|
|
213
|
-
const subFamilyEntry: Entry = await getEntryByCode(
|
|
214
|
-
productDetails.currentCatalog.subFamilyCode,
|
|
215
|
-
"topicSubFamily",
|
|
216
|
-
"sys"
|
|
217
|
-
);
|
|
218
|
-
if (subFamilyEntry) {
|
|
219
|
-
log(
|
|
220
|
-
`Start the association of the ${realCode} with the ${productDetails?.currentCatalog?.subFamilyCode} subFamily`
|
|
221
|
-
);
|
|
222
|
-
|
|
223
|
-
productEntry.fields = await addToRelationFields(
|
|
224
|
-
productEntry,
|
|
225
|
-
subFamiliesFieldKey,
|
|
226
|
-
subFamilyEntry.sys.id,
|
|
227
|
-
true
|
|
228
|
-
);
|
|
229
|
-
} else {
|
|
230
|
-
log(
|
|
231
|
-
`The ${productDetails.currentCatalog.subFamilyCode} subFamily does not exist`
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
} else {
|
|
235
|
-
log(`No subFamily code found`, "WARN");
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
// product -> model relations
|
|
239
|
-
const modelsFieldKey = "models" + capitalizeFirstLetter(catalog);
|
|
240
|
-
if (productDetails.models) {
|
|
241
|
-
for (const model of productDetails.models) {
|
|
242
|
-
const modelCode = model.data.code;
|
|
243
|
-
if (modelCode) {
|
|
244
|
-
log(`Get model entry with id ${modelCode}`);
|
|
245
|
-
const modelEntry = await getEntryByID(modelCode, "topicModel", "sys");
|
|
246
|
-
if (modelEntry) {
|
|
247
|
-
log(
|
|
248
|
-
`Start the association of the ${realCode} with the ${modelCode} model`
|
|
249
|
-
);
|
|
250
|
-
productEntry.fields = await addToRelationFields(
|
|
251
|
-
productEntry,
|
|
252
|
-
modelsFieldKey,
|
|
253
|
-
modelEntry.sys.id,
|
|
254
|
-
true
|
|
255
|
-
);
|
|
256
|
-
} else {
|
|
257
|
-
log(`The ${modelCode} model does not exist`);
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
log(`No model code found`, "WARN");
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
} else {
|
|
264
|
-
log(`No models found`);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
// product -> submodel relations
|
|
268
|
-
const subModelsFieldKey = "subModels" + capitalizeFirstLetter(catalog);
|
|
269
|
-
if (productDetails.submodels) {
|
|
270
|
-
for (const submodel of productDetails.submodels) {
|
|
271
|
-
const subModelCode = submodel.data.code;
|
|
272
|
-
if (subModelCode) {
|
|
273
|
-
log(`Get subModel entry with id ${subModelCode}`);
|
|
274
|
-
const subModelEntry = await getEntryByID(
|
|
275
|
-
subModelCode,
|
|
276
|
-
"topicSubModel",
|
|
277
|
-
"sys"
|
|
278
|
-
);
|
|
279
|
-
if (subModelEntry) {
|
|
280
|
-
log(
|
|
281
|
-
`Start the association of the ${realCode} with the ${subModelCode} subModel`
|
|
282
|
-
);
|
|
283
|
-
productEntry.fields = await addToRelationFields(
|
|
284
|
-
productEntry,
|
|
285
|
-
subModelsFieldKey,
|
|
286
|
-
subModelEntry.sys.id,
|
|
287
|
-
true
|
|
288
|
-
);
|
|
289
|
-
} else {
|
|
290
|
-
log(`The ${subModelCode} subModel does not exist`);
|
|
291
|
-
}
|
|
292
|
-
} else {
|
|
293
|
-
log(`No subModel code found`, "WARN");
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
} else {
|
|
297
|
-
log(`No subModel found`);
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
productEntry = await productEntry.update();
|
|
301
|
-
if (productEntry.isPublished()) {
|
|
302
|
-
try {
|
|
303
|
-
productEntry = await productEntry.publish();
|
|
304
|
-
} catch (err: any) {
|
|
305
|
-
log(`Cannot publish entry.`);
|
|
306
|
-
log(err);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
return productEntry;
|
|
311
|
-
};
|
|
312
|
-
|
|
313
|
-
const notVisibleToWebProduct = async (code: string): Promise<void> => {
|
|
314
|
-
// topicProduct
|
|
315
|
-
let productEntry: Entry = await getEntryByCode(code, "topicProduct");
|
|
316
|
-
if (productEntry) {
|
|
317
|
-
const pageId = getProductPageIdByCode(productEntry.sys.id);
|
|
318
|
-
|
|
319
|
-
log("The product exists, I proceed to archive it");
|
|
320
|
-
productEntry = await archiveEntry(productEntry, true);
|
|
321
|
-
// page
|
|
322
|
-
let pageEntry = await getEntryByID(pageId, "page");
|
|
323
|
-
if (pageEntry) {
|
|
324
|
-
pageEntry = await archiveEntry(pageEntry);
|
|
325
|
-
}
|
|
326
|
-
} else {
|
|
327
|
-
log("The product has never been imported", "WARN");
|
|
328
|
-
}
|
|
329
|
-
};
|
|
330
|
-
|
|
331
|
-
export const setHideInRegionField = async (
|
|
332
|
-
destinations: string[],
|
|
333
|
-
pageData: CreateEntryProps
|
|
334
|
-
) => {
|
|
335
|
-
const env = await getEnvironment();
|
|
336
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
337
|
-
|
|
338
|
-
let productRegions = destinations
|
|
339
|
-
?.filter(
|
|
340
|
-
(item: any) =>
|
|
341
|
-
item?.code?.includes("PROFESSIONAL_") ||
|
|
342
|
-
(typeof item === "string" && item?.includes("PROFESSIONAL_"))
|
|
343
|
-
)
|
|
344
|
-
.map((item: any) => {
|
|
345
|
-
const region =
|
|
346
|
-
item?.code?.replace("PROFESSIONAL_", "")?.toLowerCase() ||
|
|
347
|
-
item?.replace("PROFESSIONAL_", "")?.toLowerCase();
|
|
348
|
-
return region === "china" ? "cn" : region;
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
/*
|
|
352
|
-
Aggiunto per risolvere il problema sul sito Cina:
|
|
353
|
-
|
|
354
|
-
se sono nascoste in global => lascio hide in regions CN
|
|
355
|
-
se non sono nascoste in global => tolgo hide in regions CN
|
|
356
|
-
*/
|
|
357
|
-
if (productRegions.includes("global") && !productRegions.includes("cn")) {
|
|
358
|
-
productRegions.push("cn");
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (pageData.fields.hideInRegions?.[defEnvLocaleCode]) {
|
|
362
|
-
pageData.fields.hideInRegions[defEnvLocaleCode] = [];
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
if (productRegions?.length) {
|
|
366
|
-
log(`Hide from other regions other than: ${productRegions.join(", ")}`);
|
|
367
|
-
const { items } = await env.getEntries({
|
|
368
|
-
content_type: "topicRegion",
|
|
369
|
-
limit: 100,
|
|
370
|
-
skip: 0,
|
|
371
|
-
locale: defEnvLocaleCode,
|
|
372
|
-
include: 0,
|
|
373
|
-
select: "sys,fields",
|
|
374
|
-
});
|
|
375
|
-
let count = 0;
|
|
376
|
-
for (const item of items) {
|
|
377
|
-
const region = item?.fields?.region?.[defEnvLocaleCode];
|
|
378
|
-
|
|
379
|
-
if (!productRegions.includes(region)) {
|
|
380
|
-
log(`Hide in region: ${region}`);
|
|
381
|
-
pageData.fields = await addToRelationFields(
|
|
382
|
-
pageData,
|
|
383
|
-
"hideInRegions",
|
|
384
|
-
item.sys.id,
|
|
385
|
-
true,
|
|
386
|
-
count++ === 0
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
} else if (pageData.fields?.hideInRegions?.[defEnvLocaleCode]) {
|
|
391
|
-
log(`No region found remove old hideInRegions relations.`);
|
|
392
|
-
} else {
|
|
393
|
-
log(`No region found.`, "WARN");
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
return pageData.fields;
|
|
397
|
-
};
|
|
398
|
-
|
|
399
|
-
const getProductPageData = async (
|
|
400
|
-
names: CfLocalizedEntryField,
|
|
401
|
-
slugs: CfLocalizedEntryField,
|
|
402
|
-
pageId: string,
|
|
403
|
-
productEntry: Entry,
|
|
404
|
-
productPageEntry: Entry
|
|
405
|
-
): Promise<CreateEntryProps> => {
|
|
406
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
407
|
-
const pageData: CreateEntryProps = {
|
|
408
|
-
fields: productPageEntry?.fields || {},
|
|
409
|
-
};
|
|
410
|
-
|
|
411
|
-
pageData.fields.title = names;
|
|
412
|
-
pageData.fields.slug = slugs;
|
|
413
|
-
|
|
414
|
-
pageData.fields = await addFieldValue(pageData, "internalName", pageId);
|
|
415
|
-
pageData.fields = await addFieldValue(pageData, "type", "CatalogProduct");
|
|
416
|
-
|
|
417
|
-
// Topic
|
|
418
|
-
pageData.fields = await addToRelationFields(
|
|
419
|
-
pageData,
|
|
420
|
-
"topic",
|
|
421
|
-
productEntry.sys.id
|
|
422
|
-
);
|
|
423
|
-
|
|
424
|
-
// hideInRegions
|
|
425
|
-
const destinations =
|
|
426
|
-
productEntry?.fields?.productFields?.[defEnvLocaleCode]?.destinations;
|
|
427
|
-
pageData.fields = await setHideInRegionField(destinations, pageData);
|
|
428
|
-
return pageData;
|
|
429
|
-
};
|
|
430
|
-
|
|
431
|
-
const createOrUpdateProductPage = async (
|
|
432
|
-
productEntry: Entry,
|
|
433
|
-
unpublish: boolean
|
|
434
|
-
): Promise<Entry> => {
|
|
435
|
-
const pageId = getProductPageIdByCode(productEntry.sys.id);
|
|
436
|
-
const names: CfLocalizedEntryField = productEntry.fields.name;
|
|
437
|
-
const slugs: any = {};
|
|
438
|
-
const code = productEntry.fields.code["en"];
|
|
439
|
-
|
|
440
|
-
for (const name of Object.entries(productEntry.fields.name)) {
|
|
441
|
-
slugs[name[0]] = stringToSlug(`${name[1]}-${code}`, true).toLowerCase();
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
// PAGE
|
|
445
|
-
let productPageEntry: Entry = await getEntryByID(pageId, "page");
|
|
446
|
-
const pageData: CreateEntryProps = await getProductPageData(
|
|
447
|
-
names,
|
|
448
|
-
slugs,
|
|
449
|
-
pageId,
|
|
450
|
-
productEntry,
|
|
451
|
-
productPageEntry
|
|
452
|
-
);
|
|
453
|
-
if (productPageEntry) {
|
|
454
|
-
if (productPageEntry.isArchived()) {
|
|
455
|
-
log(`Unarchive product page with id ${pageId}`);
|
|
456
|
-
productPageEntry = await productPageEntry.unarchive();
|
|
457
|
-
}
|
|
458
|
-
log(`Product page ${pageId} already exists. Updating...`);
|
|
459
|
-
productPageEntry = await updateEntry(
|
|
460
|
-
productPageEntry,
|
|
461
|
-
pageData,
|
|
462
|
-
productPageEntry.isPublished() && !unpublish
|
|
463
|
-
);
|
|
464
|
-
} else {
|
|
465
|
-
log(`Product page ${pageId} not exists. Create new entry with data`);
|
|
466
|
-
productPageEntry = await createEntryWithId("page", pageId, pageData);
|
|
467
|
-
}
|
|
468
|
-
|
|
469
|
-
return productPageEntry;
|
|
470
|
-
};
|
|
471
|
-
|
|
472
|
-
export const certificationFields = ["certification", "marking"];
|
|
473
|
-
export const excludeCertificationFieldsKeys = [
|
|
474
|
-
"designAwards",
|
|
475
|
-
"energyLabel",
|
|
476
|
-
"lightObjMinDist",
|
|
477
|
-
"ilcos",
|
|
478
|
-
"dynamicLoad",
|
|
479
|
-
"staticLoad",
|
|
480
|
-
"casambi",
|
|
481
|
-
"fMarking",
|
|
482
|
-
];
|
|
483
|
-
|
|
484
|
-
const getProductFields = async (pimDetails: any) => {
|
|
485
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
486
|
-
const productFields: any = {};
|
|
487
|
-
productFieldsRequiredData.forEach((fieldData) => {
|
|
488
|
-
if (fieldData.parent) {
|
|
489
|
-
if (
|
|
490
|
-
pimDetails?.[fieldData.parent]?.[fieldData.key] ||
|
|
491
|
-
pimDetails?.[fieldData.parent]?.[fieldData.key] === false
|
|
492
|
-
) {
|
|
493
|
-
if (Array.isArray(pimDetails[fieldData.parent][fieldData.key])) {
|
|
494
|
-
pimDetails[fieldData.parent][fieldData.key].forEach((item: any) => {
|
|
495
|
-
if (
|
|
496
|
-
item.code &&
|
|
497
|
-
sanitizeValue(item.code) &&
|
|
498
|
-
sanitizeValue(item[`value_${defaultEnvironmentLocaleCode}`])
|
|
499
|
-
) {
|
|
500
|
-
if (!productFields?.[fieldData.parent]?.[fieldData.key]) {
|
|
501
|
-
if (!productFields?.[fieldData.parent]) {
|
|
502
|
-
productFields[fieldData.parent] = {};
|
|
503
|
-
}
|
|
504
|
-
productFields[fieldData.parent][fieldData.key] = [];
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
productFields[fieldData.parent][fieldData.key].push({
|
|
508
|
-
code: item.code,
|
|
509
|
-
parentName: item?.parentName || "",
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
} else {
|
|
514
|
-
let value: any = "";
|
|
515
|
-
if (
|
|
516
|
-
pimDetails?.[fieldData.parent]?.[fieldData.key]?.code &&
|
|
517
|
-
sanitizeValue(pimDetails[fieldData.parent][fieldData.key].code) &&
|
|
518
|
-
sanitizeValue(
|
|
519
|
-
pimDetails[fieldData.parent][fieldData.key][
|
|
520
|
-
`value_${defaultEnvironmentLocaleCode}`
|
|
521
|
-
]
|
|
522
|
-
)
|
|
523
|
-
) {
|
|
524
|
-
value = {
|
|
525
|
-
code:
|
|
526
|
-
pimDetails[fieldData.parent][fieldData.key]?.code ||
|
|
527
|
-
pimDetails[fieldData.parent][fieldData.key] ||
|
|
528
|
-
"",
|
|
529
|
-
parentName:
|
|
530
|
-
pimDetails[fieldData.parent][fieldData.key]?.parentName || "",
|
|
531
|
-
};
|
|
532
|
-
} else if (
|
|
533
|
-
(pimDetails?.[fieldData.parent]?.[fieldData.key]?.state &&
|
|
534
|
-
sanitizeValue(
|
|
535
|
-
pimDetails[fieldData.parent][fieldData.key].state
|
|
536
|
-
)) ||
|
|
537
|
-
pimDetails[fieldData.parent][fieldData.key].state === false
|
|
538
|
-
) {
|
|
539
|
-
value = {
|
|
540
|
-
state: !!pimDetails[fieldData.parent][fieldData.key].state,
|
|
541
|
-
label:
|
|
542
|
-
pimDetails[fieldData.parent][fieldData.key]?.label?.[
|
|
543
|
-
`value_${defaultEnvironmentLocaleCode}`
|
|
544
|
-
] || "",
|
|
545
|
-
};
|
|
546
|
-
} else if (
|
|
547
|
-
typeof pimDetails[fieldData.parent][fieldData.key] !== "object" &&
|
|
548
|
-
(sanitizeValue(pimDetails[fieldData.parent][fieldData.key]) ||
|
|
549
|
-
pimDetails[fieldData.parent][fieldData.key] === false)
|
|
550
|
-
) {
|
|
551
|
-
value = pimDetails[fieldData.parent][fieldData.key];
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
if (value || value === false) {
|
|
555
|
-
if (!productFields[fieldData.parent]) {
|
|
556
|
-
productFields[fieldData.parent] = {};
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
productFields[fieldData.parent][fieldData.key] = value;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
} else {
|
|
563
|
-
log(
|
|
564
|
-
`${fieldData.parent}.${fieldData.key} product field not found on the pim or null`
|
|
565
|
-
);
|
|
566
|
-
}
|
|
567
|
-
} else {
|
|
568
|
-
if (pimDetails.hasOwnProperty(fieldData.key)) {
|
|
569
|
-
if (Array.isArray(pimDetails[fieldData.key])) {
|
|
570
|
-
pimDetails[fieldData.key].forEach((item: any) => {
|
|
571
|
-
if (
|
|
572
|
-
item.code &&
|
|
573
|
-
sanitizeValue(item.code) &&
|
|
574
|
-
sanitizeValue(item[`value_${defaultEnvironmentLocaleCode}`])
|
|
575
|
-
) {
|
|
576
|
-
if (!productFields?.[fieldData.key]) {
|
|
577
|
-
productFields[fieldData.key] = [];
|
|
578
|
-
}
|
|
579
|
-
productFields[fieldData.key].push({
|
|
580
|
-
code: item.code,
|
|
581
|
-
parentName: item?.parentName || "",
|
|
582
|
-
});
|
|
583
|
-
}
|
|
584
|
-
});
|
|
585
|
-
} else {
|
|
586
|
-
let value: any = "";
|
|
587
|
-
if (
|
|
588
|
-
pimDetails[fieldData.key]?.code &&
|
|
589
|
-
sanitizeValue(pimDetails[fieldData.key].code) &&
|
|
590
|
-
sanitizeValue(
|
|
591
|
-
pimDetails[fieldData.key][`value_${defaultEnvironmentLocaleCode}`]
|
|
592
|
-
)
|
|
593
|
-
) {
|
|
594
|
-
value = {
|
|
595
|
-
code:
|
|
596
|
-
pimDetails[fieldData.key]?.code ||
|
|
597
|
-
pimDetails[fieldData.key] ||
|
|
598
|
-
"",
|
|
599
|
-
parentName: pimDetails[fieldData.key]?.parentName || "",
|
|
600
|
-
};
|
|
601
|
-
} else if (
|
|
602
|
-
typeof pimDetails[fieldData.key] !== "object" &&
|
|
603
|
-
(sanitizeValue(pimDetails[fieldData.key]) ||
|
|
604
|
-
pimDetails[fieldData.key] === false)
|
|
605
|
-
) {
|
|
606
|
-
value = pimDetails[fieldData.key];
|
|
607
|
-
}
|
|
608
|
-
if (value || value === false) {
|
|
609
|
-
productFields[fieldData.key] = value;
|
|
610
|
-
}
|
|
611
|
-
}
|
|
612
|
-
} else {
|
|
613
|
-
log(`${fieldData.key} product field not found on the pim`);
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
});
|
|
617
|
-
|
|
618
|
-
productFields.certifications = [];
|
|
619
|
-
for (const certificationField of certificationFields) {
|
|
620
|
-
if (productFields?.[certificationField]) {
|
|
621
|
-
log(`Manage certifications field: ${certificationField}`);
|
|
622
|
-
for (const [key, values] of Object.entries(
|
|
623
|
-
productFields[certificationField]
|
|
624
|
-
)) {
|
|
625
|
-
if (!excludeCertificationFieldsKeys.includes(key)) {
|
|
626
|
-
log(`Add ${key} values to productFields.certifications`);
|
|
627
|
-
productFields.certifications =
|
|
628
|
-
productFields.certifications.concat(values);
|
|
629
|
-
}
|
|
630
|
-
}
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
if (productFields.certifications.length) {
|
|
634
|
-
log(`Remove unwanted values to productFields.certifications`);
|
|
635
|
-
productFields.certifications = productFields.certifications.filter(
|
|
636
|
-
(value: any) => {
|
|
637
|
-
return sanitizeValue(value?.code);
|
|
638
|
-
}
|
|
639
|
-
);
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
return productFields;
|
|
643
|
-
};
|
|
644
|
-
|
|
645
|
-
const getTopicProductIdByCode = (productCode: string) => {
|
|
646
|
-
return productCode;
|
|
647
|
-
};
|
|
648
|
-
|
|
649
|
-
export const getProductPageIdByCode = (productCode: string) => {
|
|
650
|
-
return `${productCode}_PAGE`;
|
|
651
|
-
};
|
|
652
|
-
|
|
653
|
-
const getProductPayloadS3Details = (topicProductId: string) => {
|
|
654
|
-
return { path: S3_PIM_PAYLOAD_PATH, fileName: `${topicProductId}.json` };
|
|
655
|
-
};
|
|
656
|
-
|
|
657
|
-
const getProductAssets = async (
|
|
658
|
-
pimAssets: AssetsEntity[],
|
|
659
|
-
productCode: string
|
|
660
|
-
) => {
|
|
661
|
-
const assets: any = {};
|
|
662
|
-
for (const pimAsset of pimAssets) {
|
|
663
|
-
if (pimAsset?.url && pimAsset?.assetType?.code) {
|
|
664
|
-
const assetCode = pimAsset?.assetType?.code;
|
|
665
|
-
const md5 = pimAsset?.md5;
|
|
666
|
-
|
|
667
|
-
if (!assetCode || !md5) {
|
|
668
|
-
log(
|
|
669
|
-
`No assetCode or md5 found for product: ${productCode} assetURL: ${pimAsset.url}`,
|
|
670
|
-
"WARN"
|
|
671
|
-
);
|
|
672
|
-
continue;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
if (!assets?.[assetCode]) {
|
|
676
|
-
assets[assetCode] = [];
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
let assetUrl: string = "";
|
|
680
|
-
const pimDomain = "dam.flos.net";
|
|
681
|
-
const fileExtension = pimAsset.url.split(".")?.pop()?.toLowerCase() || "";
|
|
682
|
-
if (
|
|
683
|
-
process.env.FPI_IMGIX_PIM_IMAGE_DOMAIN &&
|
|
684
|
-
pimAsset.url.indexOf(pimDomain) !== -1 &&
|
|
685
|
-
["jpg", "png", "gif"].includes(fileExtension)
|
|
686
|
-
) {
|
|
687
|
-
assetUrl = pimAsset.url.replace(
|
|
688
|
-
pimDomain,
|
|
689
|
-
process.env.FPI_IMGIX_PIM_IMAGE_DOMAIN
|
|
690
|
-
);
|
|
691
|
-
} else if (["svg"].includes(fileExtension)) {
|
|
692
|
-
assetUrl = pimAsset.url;
|
|
693
|
-
} else {
|
|
694
|
-
const path = `product-assets/${md5}`;
|
|
695
|
-
const fileName = basename(pimAsset.url);
|
|
696
|
-
|
|
697
|
-
// FIXME: Trovare un modo per rintracciare i file già esistenti, l'unico parametro utilizzabile è l'MD5
|
|
698
|
-
// Se esistono file con lo stesso filename ma diverso MD5 questi verranno caricati più volte
|
|
699
|
-
const assetAlreadyExists = await getFileFromS3(
|
|
700
|
-
`${path}/${fileName}`,
|
|
701
|
-
true
|
|
702
|
-
);
|
|
703
|
-
if (assetAlreadyExists) {
|
|
704
|
-
log(`Asset aleady exists: ${assetAlreadyExists}`);
|
|
705
|
-
assetUrl = assetAlreadyExists;
|
|
706
|
-
} else {
|
|
707
|
-
log(`Asset not exists, importing it to S3 path: ${path}/${fileName}`);
|
|
708
|
-
try {
|
|
709
|
-
const res = await uploadToS3(pimAsset.url, fileName, path);
|
|
710
|
-
assetUrl = res.Location;
|
|
711
|
-
} catch (err: any) {
|
|
712
|
-
log(
|
|
713
|
-
`Unable to upload file: ${err.response.status} - ${err.response.statusText}`,
|
|
714
|
-
"WARN"
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
if (assetUrl) {
|
|
721
|
-
assets[assetCode].push(assetUrl);
|
|
722
|
-
}
|
|
723
|
-
} else {
|
|
724
|
-
log(
|
|
725
|
-
`The asset ${pimAsset?.assetType} cannot be imported because the url or assetType.code parameters are empty`,
|
|
726
|
-
"WARN"
|
|
727
|
-
);
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
|
|
731
|
-
return assets;
|
|
732
|
-
};
|
|
733
|
-
|
|
734
|
-
const getProductData = async (
|
|
735
|
-
productEntry: Entry,
|
|
736
|
-
productDetails: ProductDetails
|
|
737
|
-
) => {
|
|
738
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
739
|
-
|
|
740
|
-
const data: CreateEntryProps = {
|
|
741
|
-
fields: productEntry?.fields || {},
|
|
742
|
-
};
|
|
743
|
-
|
|
744
|
-
data.fields.name = getPimTranslations(
|
|
745
|
-
productDetails,
|
|
746
|
-
"webNaming",
|
|
747
|
-
productDetails.name,
|
|
748
|
-
255
|
|
749
|
-
);
|
|
750
|
-
data.fields = await addFieldValue(data, "code", productDetails.code);
|
|
751
|
-
|
|
752
|
-
data.fields.description = getPimTranslations(productDetails, "description1");
|
|
753
|
-
data.fields.excerpt = getPimTranslations(productDetails, "description2");
|
|
754
|
-
data.fields.note = getPimTranslations(productDetails, "note");
|
|
755
|
-
|
|
756
|
-
const { currentCatalog, ...pimDetails } = productDetails;
|
|
757
|
-
|
|
758
|
-
log(`Set productFields`);
|
|
759
|
-
const productFields = await getProductFields(pimDetails);
|
|
760
|
-
data.fields = await addFieldValue(data, "productFields", productFields);
|
|
761
|
-
|
|
762
|
-
// catalogs
|
|
763
|
-
const catalog = productDetails?.currentCatalog?.catalogCode || "";
|
|
764
|
-
if (catalog) {
|
|
765
|
-
const catalogEntry: Entry = await getEntryByCode(
|
|
766
|
-
catalog,
|
|
767
|
-
"topicCatalog",
|
|
768
|
-
"sys"
|
|
769
|
-
);
|
|
770
|
-
log(`Set catalog relation: ${catalog}`);
|
|
771
|
-
data.fields = await addToRelationFields(
|
|
772
|
-
data,
|
|
773
|
-
"catalogs",
|
|
774
|
-
catalogEntry.sys.id,
|
|
775
|
-
true
|
|
776
|
-
);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
// categories - for catalg
|
|
780
|
-
const categoriesFieldKey = "categories" + capitalizeFirstLetter(catalog);
|
|
781
|
-
if (catalog && productDetails?.currentCatalog?.categoryCode) {
|
|
782
|
-
const categoryTopicCode = getCategoryTopicCode(
|
|
783
|
-
productDetails.currentCatalog.categoryCode,
|
|
784
|
-
catalog
|
|
785
|
-
);
|
|
786
|
-
const categoryEntry: Entry = await getEntryByCode(
|
|
787
|
-
categoryTopicCode,
|
|
788
|
-
"topicCategory",
|
|
789
|
-
"sys"
|
|
790
|
-
);
|
|
791
|
-
if (!categoryEntry) {
|
|
792
|
-
log(`The topicCategory with code ${categoryTopicCode} not found`, "WARN");
|
|
793
|
-
} else {
|
|
794
|
-
log(
|
|
795
|
-
`Set category relation: ${categoryTopicCode} in the field ${categoriesFieldKey}`
|
|
796
|
-
);
|
|
797
|
-
data.fields = await addToRelationFields(
|
|
798
|
-
data,
|
|
799
|
-
categoriesFieldKey,
|
|
800
|
-
categoryEntry.sys.id,
|
|
801
|
-
true
|
|
802
|
-
);
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
// families
|
|
807
|
-
if (productDetails?.currentCatalog?.familyCode) {
|
|
808
|
-
const familyEntry: Entry = await getEntryByCode(
|
|
809
|
-
productDetails.currentCatalog.familyCode,
|
|
810
|
-
"topicFamily",
|
|
811
|
-
"sys"
|
|
812
|
-
);
|
|
813
|
-
if (!familyEntry) {
|
|
814
|
-
log(
|
|
815
|
-
`The topicFamily with code ${productDetails.currentCatalog.familyCode} not found`,
|
|
816
|
-
"WARN"
|
|
817
|
-
);
|
|
818
|
-
} else {
|
|
819
|
-
log(`Set family relation: ${productDetails.currentCatalog.familyCode}`);
|
|
820
|
-
data.fields = await addToRelationFields(
|
|
821
|
-
data,
|
|
822
|
-
"families",
|
|
823
|
-
familyEntry.sys.id,
|
|
824
|
-
true
|
|
825
|
-
);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
|
|
829
|
-
// subFamilies - for catalg
|
|
830
|
-
const subFamiliesFieldKey = "subFamilies" + capitalizeFirstLetter(catalog);
|
|
831
|
-
if (productDetails?.currentCatalog?.subFamilyCode) {
|
|
832
|
-
const subFamilyEntry: Entry = await getEntryByCode(
|
|
833
|
-
productDetails.currentCatalog.subFamilyCode,
|
|
834
|
-
"topicSubFamily",
|
|
835
|
-
"sys"
|
|
836
|
-
);
|
|
837
|
-
|
|
838
|
-
if (!subFamilyEntry) {
|
|
839
|
-
log(
|
|
840
|
-
`The topicSubFamily with code ${productDetails.currentCatalog.subFamilyCode} not found`,
|
|
841
|
-
"WARN"
|
|
842
|
-
);
|
|
843
|
-
} else {
|
|
844
|
-
log(
|
|
845
|
-
`Set subFamily relation: ${productDetails.currentCatalog.subFamilyCode} in the field ${subFamiliesFieldKey}`
|
|
846
|
-
);
|
|
847
|
-
data.fields = await addToRelationFields(
|
|
848
|
-
data,
|
|
849
|
-
subFamiliesFieldKey,
|
|
850
|
-
subFamilyEntry.sys.id,
|
|
851
|
-
true
|
|
852
|
-
);
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// productLine
|
|
857
|
-
if (productDetails?.productLine) {
|
|
858
|
-
const productLineEntry: Entry = await getEntryByCode(
|
|
859
|
-
productDetails.productLine.code,
|
|
860
|
-
"topicProductLine",
|
|
861
|
-
"sys"
|
|
862
|
-
);
|
|
863
|
-
if (!productLineEntry) {
|
|
864
|
-
log(
|
|
865
|
-
`The topicProductLine with code ${productDetails.productLine.code} not found`,
|
|
866
|
-
"WARN"
|
|
867
|
-
);
|
|
868
|
-
} else {
|
|
869
|
-
log(`Set productLine relation: ${productDetails.productLine.code}`);
|
|
870
|
-
data.fields = await addToRelationFields(
|
|
871
|
-
data,
|
|
872
|
-
"productLine",
|
|
873
|
-
productLineEntry.sys.id
|
|
874
|
-
);
|
|
875
|
-
}
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
// productSubLine
|
|
879
|
-
if (productDetails?.productLineDetail) {
|
|
880
|
-
const productSubLineEntry: Entry = await getEntryByCode(
|
|
881
|
-
productDetails.productLineDetail.code,
|
|
882
|
-
"topicProductSubLine",
|
|
883
|
-
"sys"
|
|
884
|
-
);
|
|
885
|
-
if (!productSubLineEntry) {
|
|
886
|
-
log(
|
|
887
|
-
`The topicProductSubLine with code ${productDetails.productLineDetail.code} not found`,
|
|
888
|
-
"WARN"
|
|
889
|
-
);
|
|
890
|
-
} else {
|
|
891
|
-
log(
|
|
892
|
-
`Set productSubLine relation: ${productDetails.productLineDetail.code}`
|
|
893
|
-
);
|
|
894
|
-
data.fields = await addToRelationFields(
|
|
895
|
-
data,
|
|
896
|
-
"productSubLine",
|
|
897
|
-
productSubLineEntry.sys.id
|
|
898
|
-
);
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
// models - for catalg
|
|
903
|
-
const modelsFieldKey = "models" + capitalizeFirstLetter(catalog);
|
|
904
|
-
if (productDetails?.models) {
|
|
905
|
-
log(`Set ${productDetails.models.length} model relations`);
|
|
906
|
-
const modelCodes = productDetails.models.map((model) => {
|
|
907
|
-
return model.data.code;
|
|
908
|
-
});
|
|
909
|
-
|
|
910
|
-
const topicModelEntries = await getAllEntriesByCodes(
|
|
911
|
-
modelCodes,
|
|
912
|
-
"topicModel",
|
|
913
|
-
"sys,fields.catalog"
|
|
914
|
-
);
|
|
915
|
-
|
|
916
|
-
if (topicModelEntries.length) {
|
|
917
|
-
for (const topicModelEntry of topicModelEntries) {
|
|
918
|
-
if (
|
|
919
|
-
topicModelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys
|
|
920
|
-
?.id !== catalog
|
|
921
|
-
) {
|
|
922
|
-
log(
|
|
923
|
-
`The model ${topicModelEntry.sys.id} belongs to the catalog ${topicModelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys?.id} and will not be imported`
|
|
924
|
-
);
|
|
925
|
-
continue;
|
|
926
|
-
} else {
|
|
927
|
-
log(
|
|
928
|
-
`Set relation with model ${topicModelEntry.sys.id} in the field ${modelsFieldKey}`
|
|
929
|
-
);
|
|
930
|
-
data.fields = await addToRelationFields(
|
|
931
|
-
data,
|
|
932
|
-
modelsFieldKey,
|
|
933
|
-
topicModelEntry.sys.id,
|
|
934
|
-
true
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
} else {
|
|
939
|
-
log(
|
|
940
|
-
`No topicModel found for product ${
|
|
941
|
-
productDetails.code
|
|
942
|
-
}: ${modelCodes.join(",")}`,
|
|
943
|
-
"WARN"
|
|
944
|
-
);
|
|
945
|
-
}
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
// subModels for catalog
|
|
949
|
-
const subModelsFieldKey = "subModels" + capitalizeFirstLetter(catalog);
|
|
950
|
-
if (productDetails?.submodels) {
|
|
951
|
-
log(`Set ${productDetails.submodels.length} subModels relations`);
|
|
952
|
-
const subModelsCodes = productDetails.submodels.map((subModel) => {
|
|
953
|
-
return subModel.data.code;
|
|
954
|
-
});
|
|
955
|
-
|
|
956
|
-
const topicSubModelEntries = await getAllEntriesByCodes(
|
|
957
|
-
subModelsCodes,
|
|
958
|
-
"topicSubModel",
|
|
959
|
-
"sys,fields.catalog"
|
|
960
|
-
);
|
|
961
|
-
|
|
962
|
-
if (topicSubModelEntries.length) {
|
|
963
|
-
for (const topicSubModelEntry of topicSubModelEntries) {
|
|
964
|
-
if (
|
|
965
|
-
topicSubModelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]
|
|
966
|
-
?.sys?.id !== catalog
|
|
967
|
-
) {
|
|
968
|
-
log(
|
|
969
|
-
`The subModel ${topicSubModelEntry.sys.id} belongs to the catalog ${topicSubModelEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode]?.sys?.id} and will not be imported`
|
|
970
|
-
);
|
|
971
|
-
continue;
|
|
972
|
-
} else {
|
|
973
|
-
log(
|
|
974
|
-
`Set relation with subModel ${topicSubModelEntry.sys.id} in the field ${subModelsFieldKey}`
|
|
975
|
-
);
|
|
976
|
-
data.fields = await addToRelationFields(
|
|
977
|
-
data,
|
|
978
|
-
subModelsFieldKey,
|
|
979
|
-
topicSubModelEntry.sys.id,
|
|
980
|
-
true
|
|
981
|
-
);
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
} else {
|
|
985
|
-
log(
|
|
986
|
-
`No topicSubModel found for product ${
|
|
987
|
-
productDetails.code
|
|
988
|
-
}: ${subModelsCodes.join(",")}`,
|
|
989
|
-
"WARN"
|
|
990
|
-
);
|
|
991
|
-
}
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
// assets
|
|
995
|
-
if (productDetails?.assets) {
|
|
996
|
-
const pimAssetThumb = productDetails.assets.find(
|
|
997
|
-
(asset) => asset?.assetType.code === "THUMB"
|
|
998
|
-
);
|
|
999
|
-
|
|
1000
|
-
// THUMB
|
|
1001
|
-
if (pimAssetThumb?.url && pimAssetThumb?.md5) {
|
|
1002
|
-
log(`Set THUMB`);
|
|
1003
|
-
// THUMB WRAPPER IMGIX
|
|
1004
|
-
const wrapperImgixID = pimAssetThumb.md5;
|
|
1005
|
-
let wrapperImgix = await getEntryByID(
|
|
1006
|
-
wrapperImgixID,
|
|
1007
|
-
"wrapperImgix",
|
|
1008
|
-
"sys,fields"
|
|
1009
|
-
);
|
|
1010
|
-
if (wrapperImgix) {
|
|
1011
|
-
log(`wrapperImgix with id ${wrapperImgixID} already exists`);
|
|
1012
|
-
const imgixBasename = basename(
|
|
1013
|
-
wrapperImgix.fields.imgixData[defaultEnvironmentLocaleCode].url
|
|
1014
|
-
);
|
|
1015
|
-
const pimBasename = basename(pimAssetThumb.url);
|
|
1016
|
-
if (imgixBasename !== pimBasename) {
|
|
1017
|
-
log(`Update img url from ${imgixBasename} to ${pimBasename}`);
|
|
1018
|
-
const newImgixUrl = getImgixPimUrlByOriginPath(
|
|
1019
|
-
getOriginPathByPimUrl(pimAssetThumb.url)
|
|
1020
|
-
);
|
|
1021
|
-
wrapperImgix.fields.imgixData[defaultEnvironmentLocaleCode].url =
|
|
1022
|
-
newImgixUrl;
|
|
1023
|
-
wrapperImgix = await wrapperImgix.update();
|
|
1024
|
-
if (wrapperImgix.isPublished()) {
|
|
1025
|
-
wrapperImgix = await wrapperImgix.publish();
|
|
1026
|
-
}
|
|
1027
|
-
|
|
1028
|
-
log(`The new imgix url is: ${newImgixUrl}`);
|
|
1029
|
-
} else {
|
|
1030
|
-
log(`wrapperImgix basename matched`);
|
|
1031
|
-
}
|
|
1032
|
-
} else {
|
|
1033
|
-
log(
|
|
1034
|
-
`Add thumbnail imgix wrapper with id ${wrapperImgixID} to Contentful`
|
|
1035
|
-
);
|
|
1036
|
-
const altText: any = getPimTranslations(pimAssetThumb, "title");
|
|
1037
|
-
if (altText[defaultEnvironmentLocaleCode] === null) {
|
|
1038
|
-
altText[defaultEnvironmentLocaleCode] = "Thumbnail";
|
|
1039
|
-
}
|
|
1040
|
-
const wrapperImgixAttributes = getDefaultWrapperImgixAttributesByPimUrl(
|
|
1041
|
-
pimAssetThumb.url
|
|
1042
|
-
);
|
|
1043
|
-
if (wrapperImgixAttributes) {
|
|
1044
|
-
const wrapperImgixFields: WrapperImageFields = {
|
|
1045
|
-
internalName: `${pimAssetThumb?.assetType?.code}_${pimAssetThumb.md5}`,
|
|
1046
|
-
imgixData: wrapperImgixAttributes,
|
|
1047
|
-
altText,
|
|
1048
|
-
};
|
|
1049
|
-
wrapperImgix = await createWrapperImgix(
|
|
1050
|
-
wrapperImgixID,
|
|
1051
|
-
wrapperImgixFields
|
|
1052
|
-
);
|
|
1053
|
-
} else {
|
|
1054
|
-
log(
|
|
1055
|
-
`Unable to create wrapperimagix because the image was not found on imgix. Image URL: ${pimAssetThumb.url}`,
|
|
1056
|
-
"WARN"
|
|
1057
|
-
);
|
|
1058
|
-
}
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
if (wrapperImgix?.sys?.id) {
|
|
1062
|
-
data.fields = await addToRelationFields(
|
|
1063
|
-
data,
|
|
1064
|
-
"thumbnailImgix",
|
|
1065
|
-
wrapperImgix.sys.id
|
|
1066
|
-
);
|
|
1067
|
-
}
|
|
1068
|
-
} else {
|
|
1069
|
-
log(`No thumbnail found or md5 is null`, "WARN");
|
|
1070
|
-
}
|
|
1071
|
-
|
|
1072
|
-
// OTHER ASSETS
|
|
1073
|
-
const pimOtherAssets = productDetails.assets.filter(
|
|
1074
|
-
(asset) => asset?.assetType.code !== "THUMB"
|
|
1075
|
-
);
|
|
1076
|
-
if (pimOtherAssets.length) {
|
|
1077
|
-
log(`Uploading ${pimOtherAssets.length} assets to S3`);
|
|
1078
|
-
const assets = await getProductAssets(
|
|
1079
|
-
pimOtherAssets as AssetsEntity[],
|
|
1080
|
-
productDetails.code
|
|
1081
|
-
);
|
|
1082
|
-
if (assets) {
|
|
1083
|
-
data.fields = await addFieldValue(data, "assets", assets);
|
|
1084
|
-
}
|
|
1085
|
-
} else {
|
|
1086
|
-
log(`No other assets found`, "WARN");
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
|
|
1090
|
-
// lastPimSyncDate
|
|
1091
|
-
data.fields = await addFieldValue(data, "lastPimSyncDate", getLocalISOTime());
|
|
1092
|
-
|
|
1093
|
-
// designers
|
|
1094
|
-
if (productDetails.designers) {
|
|
1095
|
-
for (const designer of productDetails.designers) {
|
|
1096
|
-
data.fields = await addDesignerData(data, designer, true);
|
|
1097
|
-
}
|
|
1098
|
-
} else {
|
|
1099
|
-
log(`No designers found`, "WARN");
|
|
1100
|
-
if (data.fields.designers?.[defaultEnvironmentLocaleCode]) {
|
|
1101
|
-
log(`remove old designers relation`);
|
|
1102
|
-
data.fields.designers = [];
|
|
1103
|
-
}
|
|
1104
|
-
}
|
|
1105
|
-
|
|
1106
|
-
// autodescription
|
|
1107
|
-
data.fields.autoDescription = await getTopicProductAutodescription(
|
|
1108
|
-
data.fields
|
|
1109
|
-
);
|
|
1110
|
-
|
|
1111
|
-
// Destinations
|
|
1112
|
-
if (productDetails?.destinations?.length) {
|
|
1113
|
-
log(`set destinations`);
|
|
1114
|
-
data.fields = await addFieldValue(
|
|
1115
|
-
data,
|
|
1116
|
-
"destinations",
|
|
1117
|
-
productDetails.destinations.map((item) => item.code)
|
|
1118
|
-
);
|
|
1119
|
-
} else {
|
|
1120
|
-
log(`destinations not found`, "WARN");
|
|
1121
|
-
}
|
|
1122
|
-
|
|
1123
|
-
// endpoint payload - used into setProductRelationships
|
|
1124
|
-
const productEntryId = getTopicProductIdByCode(productDetails.code);
|
|
1125
|
-
const { path, fileName } = getProductPayloadS3Details(productEntryId);
|
|
1126
|
-
log(`Uploading "${fileName}" to S3 path "${path}"`);
|
|
1127
|
-
const { Location } = await saveJsonToS3(pimDetails, fileName, path);
|
|
1128
|
-
data.fields = await addFieldValue(data, "endpointPayload", Location);
|
|
1129
|
-
log(`"${fileName}" uploaded to ${Location}`);
|
|
1130
|
-
|
|
1131
|
-
return data;
|
|
1132
|
-
};
|
|
1133
|
-
|
|
1134
|
-
const getProductColourVariantsData = async (
|
|
1135
|
-
topicProductColourVariantsCode: string,
|
|
1136
|
-
productEntryId: string,
|
|
1137
|
-
topicProductColourVariants: Entry | null
|
|
1138
|
-
) => {
|
|
1139
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
1140
|
-
const data: CreateEntryProps = {
|
|
1141
|
-
fields: {
|
|
1142
|
-
code: {},
|
|
1143
|
-
lastPimSyncDate: {},
|
|
1144
|
-
},
|
|
1145
|
-
};
|
|
1146
|
-
|
|
1147
|
-
if (topicProductColourVariants?.fields) {
|
|
1148
|
-
data.fields = topicProductColourVariants.fields;
|
|
1149
|
-
}
|
|
1150
|
-
|
|
1151
|
-
// code
|
|
1152
|
-
data.fields.code[defaultEnvironmentLocaleCode] =
|
|
1153
|
-
topicProductColourVariantsCode;
|
|
1154
|
-
|
|
1155
|
-
// products
|
|
1156
|
-
data.fields = await addToRelationFields(
|
|
1157
|
-
data,
|
|
1158
|
-
"products",
|
|
1159
|
-
productEntryId,
|
|
1160
|
-
true
|
|
1161
|
-
);
|
|
1162
|
-
|
|
1163
|
-
// lastPimSyncDate
|
|
1164
|
-
data.fields.lastPimSyncDate[defaultEnvironmentLocaleCode] = getLocalISOTime();
|
|
1165
|
-
|
|
1166
|
-
return data;
|
|
1167
|
-
};
|
|
1168
|
-
|
|
1169
|
-
const addProductColourVariants = async (
|
|
1170
|
-
colourVariants: ColourVariant[],
|
|
1171
|
-
productEntryId: string
|
|
1172
|
-
) => {
|
|
1173
|
-
for (const colourVariant of colourVariants) {
|
|
1174
|
-
const topicId = `PCV_${colourVariant.code}`;
|
|
1175
|
-
let topicProductColourVariants: Entry = await getEntryByID(
|
|
1176
|
-
topicId,
|
|
1177
|
-
"topicProductColourVariants"
|
|
1178
|
-
);
|
|
1179
|
-
const data = await getProductColourVariantsData(
|
|
1180
|
-
colourVariant.code,
|
|
1181
|
-
productEntryId,
|
|
1182
|
-
topicProductColourVariants
|
|
1183
|
-
);
|
|
1184
|
-
if (!topicProductColourVariants) {
|
|
1185
|
-
log(`Create topicProductColourVariants with code ${topicId}`);
|
|
1186
|
-
// Create new topicProductColourVariants
|
|
1187
|
-
topicProductColourVariants = await createEntryWithId(
|
|
1188
|
-
"topicProductColourVariants",
|
|
1189
|
-
topicId,
|
|
1190
|
-
data,
|
|
1191
|
-
true
|
|
1192
|
-
);
|
|
1193
|
-
} else {
|
|
1194
|
-
log(`Update topicProductColourVariants with code ${topicId}`);
|
|
1195
|
-
// Update existing topicProductColourVariants
|
|
1196
|
-
topicProductColourVariants = await updateEntry(
|
|
1197
|
-
topicProductColourVariants,
|
|
1198
|
-
data,
|
|
1199
|
-
topicProductColourVariants.isPublished()
|
|
1200
|
-
);
|
|
1201
|
-
}
|
|
1202
|
-
}
|
|
1203
|
-
};
|
|
1204
|
-
|
|
1205
|
-
/**
|
|
1206
|
-
* Import product
|
|
1207
|
-
* - name
|
|
1208
|
-
* - code
|
|
1209
|
-
* - status
|
|
1210
|
-
* - categories
|
|
1211
|
-
* - families
|
|
1212
|
-
* - subfamilies
|
|
1213
|
-
* - models
|
|
1214
|
-
* - submodels
|
|
1215
|
-
* - productLine
|
|
1216
|
-
* - accessories
|
|
1217
|
-
* - accessoryOf
|
|
1218
|
-
* - bulbOf
|
|
1219
|
-
* - sparepartOf
|
|
1220
|
-
* - bulbs
|
|
1221
|
-
* - spareparts
|
|
1222
|
-
* - pimDetails
|
|
1223
|
-
* - lastPimSyncDate
|
|
1224
|
-
*/
|
|
1225
|
-
const addProduct = async (
|
|
1226
|
-
productDetails: ProductDetails
|
|
1227
|
-
): Promise<Entry | boolean> => {
|
|
1228
|
-
// Check that the title is set
|
|
1229
|
-
const title = productDetails.webNaming || productDetails.name;
|
|
1230
|
-
if (!title) {
|
|
1231
|
-
log(
|
|
1232
|
-
`Can't possible to import the product ${productDetails.code}, name and webNaming not found`
|
|
1233
|
-
);
|
|
1234
|
-
return false;
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
log(`If exists get entry with code: ${productDetails.code}`);
|
|
1238
|
-
|
|
1239
|
-
let productEntry: Entry = await getEntryByCode(
|
|
1240
|
-
productDetails.code,
|
|
1241
|
-
"topicProduct"
|
|
1242
|
-
);
|
|
1243
|
-
|
|
1244
|
-
const productData = await getProductData(productEntry, productDetails);
|
|
1245
|
-
|
|
1246
|
-
let publishEntry = false;
|
|
1247
|
-
|
|
1248
|
-
if (!productEntry) {
|
|
1249
|
-
const productEntryId = getTopicProductIdByCode(productDetails.code);
|
|
1250
|
-
log(`Create product with code ${productEntryId}`);
|
|
1251
|
-
// Create new topicProduct
|
|
1252
|
-
productEntry = await createEntryWithId(
|
|
1253
|
-
"topicProduct",
|
|
1254
|
-
productEntryId,
|
|
1255
|
-
productData,
|
|
1256
|
-
false
|
|
1257
|
-
);
|
|
1258
|
-
} else {
|
|
1259
|
-
if (productEntry.isArchived()) {
|
|
1260
|
-
log(`Unarchive product with code ${productDetails.code}`);
|
|
1261
|
-
productEntry = await productEntry.unarchive();
|
|
1262
|
-
}
|
|
1263
|
-
log(`Update product with code ${productDetails.code}`);
|
|
1264
|
-
productEntry = await updateEntry(
|
|
1265
|
-
productEntry,
|
|
1266
|
-
productData,
|
|
1267
|
-
productEntry.isPublished()
|
|
1268
|
-
);
|
|
1269
|
-
publishEntry = productEntry?.isPublished();
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
log(`Publish entry: ${publishEntry}`);
|
|
1273
|
-
|
|
1274
|
-
// Create or update pageContent and page of the current topicProduct
|
|
1275
|
-
await createOrUpdateProductPage(productEntry, !publishEntry);
|
|
1276
|
-
|
|
1277
|
-
if (productDetails?.colourVariants) {
|
|
1278
|
-
await addProductColourVariants(
|
|
1279
|
-
productDetails.colourVariants,
|
|
1280
|
-
productEntry.sys.id
|
|
1281
|
-
);
|
|
1282
|
-
}
|
|
1283
|
-
|
|
1284
|
-
return productEntry;
|
|
1285
|
-
};
|
|
1286
|
-
|
|
1287
|
-
const validateImportProduct = (
|
|
1288
|
-
productDetails: ProductDetails,
|
|
1289
|
-
catalog: AvailableCatalogs,
|
|
1290
|
-
familyCodeIn?: string[],
|
|
1291
|
-
subFamilyCodeIn?: string[]
|
|
1292
|
-
) => {
|
|
1293
|
-
// Validate catalog
|
|
1294
|
-
if (!productDetails.currentCatalog?.catalogCode) {
|
|
1295
|
-
log(
|
|
1296
|
-
`The product ${productDetails.code} does not belong to the ${catalog} catalog or the catalog is not specified. Catalog code: ${productDetails.currentCatalog?.catalogCode}`,
|
|
1297
|
-
"WARN"
|
|
1298
|
-
);
|
|
1299
|
-
return false;
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
// Validate family
|
|
1303
|
-
if (
|
|
1304
|
-
familyCodeIn?.length &&
|
|
1305
|
-
!familyCodeIn.includes(productDetails.currentCatalog?.familyCode as string)
|
|
1306
|
-
) {
|
|
1307
|
-
log(
|
|
1308
|
-
`The product ${
|
|
1309
|
-
productDetails.code
|
|
1310
|
-
} does not belong to any of the ${familyCodeIn.join(
|
|
1311
|
-
","
|
|
1312
|
-
)} families or the family is not specified. Family code: ${
|
|
1313
|
-
productDetails.currentCatalog?.familyCode
|
|
1314
|
-
}`,
|
|
1315
|
-
"WARN"
|
|
1316
|
-
);
|
|
1317
|
-
return false;
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
// Validate subfamily
|
|
1321
|
-
if (
|
|
1322
|
-
subFamilyCodeIn?.length &&
|
|
1323
|
-
!subFamilyCodeIn.includes(
|
|
1324
|
-
productDetails.currentCatalog?.subFamilyCode as string
|
|
1325
|
-
)
|
|
1326
|
-
) {
|
|
1327
|
-
log(
|
|
1328
|
-
`The product ${
|
|
1329
|
-
productDetails.code
|
|
1330
|
-
} does not belong to any of the ${subFamilyCodeIn.join(
|
|
1331
|
-
","
|
|
1332
|
-
)} subFamilies or the subFamily is not specified. SubFamily code: ${
|
|
1333
|
-
productDetails.currentCatalog?.subFamilyCode
|
|
1334
|
-
}`,
|
|
1335
|
-
"WARN"
|
|
1336
|
-
);
|
|
1337
|
-
return false;
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
return true;
|
|
1341
|
-
};
|
|
1342
|
-
|
|
1343
|
-
/**
|
|
1344
|
-
* Import product
|
|
1345
|
-
*
|
|
1346
|
-
* create/update topicProduct
|
|
1347
|
-
* - name
|
|
1348
|
-
* - code
|
|
1349
|
-
* - pimDetails
|
|
1350
|
-
* - status
|
|
1351
|
-
* - catalogs
|
|
1352
|
-
* - categories
|
|
1353
|
-
* - subFamilies
|
|
1354
|
-
* - productLine
|
|
1355
|
-
* - lastPimSyncDate
|
|
1356
|
-
*
|
|
1357
|
-
* @param productDetails
|
|
1358
|
-
* @param catalog
|
|
1359
|
-
* @returns
|
|
1360
|
-
*/
|
|
1361
|
-
export const importProduct = async (
|
|
1362
|
-
productDetails: ProductDetails,
|
|
1363
|
-
catalog: AvailableCatalogs,
|
|
1364
|
-
familyCodeIn?: string[],
|
|
1365
|
-
subFamilyCodeIn?: string[]
|
|
1366
|
-
): Promise<boolean> => {
|
|
1367
|
-
productDetails.currentCatalog = productDetails.catalogs?.find(
|
|
1368
|
-
(itemCatalog) => itemCatalog.catalogCode === catalog
|
|
1369
|
-
);
|
|
1370
|
-
|
|
1371
|
-
if (
|
|
1372
|
-
!validateImportProduct(
|
|
1373
|
-
productDetails,
|
|
1374
|
-
catalog,
|
|
1375
|
-
familyCodeIn,
|
|
1376
|
-
subFamilyCodeIn
|
|
1377
|
-
)
|
|
1378
|
-
) {
|
|
1379
|
-
return false;
|
|
1380
|
-
}
|
|
1381
|
-
|
|
1382
|
-
log(`Import product ${productDetails.code}`, "INFO");
|
|
1383
|
-
|
|
1384
|
-
const isTermsToAddCode = await isTermsToAdd(productDetails, catalog);
|
|
1385
|
-
if (isTermsToAddCode) {
|
|
1386
|
-
return false;
|
|
1387
|
-
}
|
|
1388
|
-
|
|
1389
|
-
if (
|
|
1390
|
-
(productDetails.visibleToWeb === true ||
|
|
1391
|
-
productDetails.code === "0000000-TEST") &&
|
|
1392
|
-
productDetails.destinations?.filter((item) =>
|
|
1393
|
-
item.code.includes("PROFESSIONAL_")
|
|
1394
|
-
).length
|
|
1395
|
-
) {
|
|
1396
|
-
await addProduct(productDetails);
|
|
1397
|
-
return true;
|
|
1398
|
-
} else {
|
|
1399
|
-
await notVisibleToWebProduct(productDetails.code);
|
|
1400
|
-
const destinations = productDetails.destinations
|
|
1401
|
-
?.map((item) => item.code)
|
|
1402
|
-
.join(", ");
|
|
1403
|
-
|
|
1404
|
-
log(
|
|
1405
|
-
`Product not to be imported: ${productDetails.code} - visibleToWeb = ${productDetails.visibleToWeb} - destinations = [${destinations}]`
|
|
1406
|
-
);
|
|
1407
|
-
return false;
|
|
1408
|
-
}
|
|
1409
|
-
};
|
|
1410
|
-
|
|
1411
|
-
export const setProductRelationships = async (
|
|
1412
|
-
code: string,
|
|
1413
|
-
fieldKey: AvailableRelationFieldKeys | null = null
|
|
1414
|
-
) => {
|
|
1415
|
-
log(`setProductRelationships - code: ${code} fieldKey: ${fieldKey}`, "INFO");
|
|
1416
|
-
|
|
1417
|
-
const fieldKeys: AvailableRelationFieldKeys[] = [
|
|
1418
|
-
"accessories",
|
|
1419
|
-
"accessoryOf",
|
|
1420
|
-
"bulbOf",
|
|
1421
|
-
"sparepartOf",
|
|
1422
|
-
"bulbs",
|
|
1423
|
-
"spareparts",
|
|
1424
|
-
];
|
|
1425
|
-
|
|
1426
|
-
if (!fieldKey) {
|
|
1427
|
-
log(
|
|
1428
|
-
`The fieldKey parameter is empty so all fields will be imported: ${fieldKeys.join(
|
|
1429
|
-
","
|
|
1430
|
-
)} `
|
|
1431
|
-
);
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
const currentFieldKeys = fieldKey ? [fieldKey] : fieldKeys;
|
|
1435
|
-
let productEntry = await getEntryByCode(code, "topicProduct");
|
|
1436
|
-
if (!productEntry) {
|
|
1437
|
-
log(`Product with code ${code} not found`, "WARN");
|
|
1438
|
-
} else if (productEntry.isArchived()) {
|
|
1439
|
-
log(`Product with code ${code} is archived`, "WARN");
|
|
1440
|
-
} else if (!productEntry.isArchived()) {
|
|
1441
|
-
const { path, fileName } = getProductPayloadS3Details(productEntry.sys.id);
|
|
1442
|
-
log(`Get payload from ${path}${fileName} S3 path`);
|
|
1443
|
-
const productDetails = await getFileFromS3(`${path}${fileName}`);
|
|
1444
|
-
if (productDetails) {
|
|
1445
|
-
const defaultEnvironmentLocaleCode =
|
|
1446
|
-
await getEnvironmentDefaultLocaleCode();
|
|
1447
|
-
let update = false;
|
|
1448
|
-
let fieldKeysCount = 0;
|
|
1449
|
-
for (const currentFieldKey of currentFieldKeys) {
|
|
1450
|
-
log(`Set ${currentFieldKey} relations to product with code ${code}`);
|
|
1451
|
-
const fieldValues: ProductRelation[] = productDetails[currentFieldKey];
|
|
1452
|
-
|
|
1453
|
-
if (fieldValues) {
|
|
1454
|
-
const relationships = [];
|
|
1455
|
-
const producRelationCodes = fieldValues.map((fieldValue) => {
|
|
1456
|
-
return fieldValue.code;
|
|
1457
|
-
});
|
|
1458
|
-
|
|
1459
|
-
const entries = await getAllEntriesByCodes(
|
|
1460
|
-
producRelationCodes,
|
|
1461
|
-
"topicProduct",
|
|
1462
|
-
"sys,fields.code"
|
|
1463
|
-
);
|
|
1464
|
-
|
|
1465
|
-
for (const fieldValue of fieldValues) {
|
|
1466
|
-
const entry = entries.find(
|
|
1467
|
-
(currentEntry) =>
|
|
1468
|
-
currentEntry.fields.code[defaultEnvironmentLocaleCode] ===
|
|
1469
|
-
fieldValue.code
|
|
1470
|
-
);
|
|
1471
|
-
if (entry) {
|
|
1472
|
-
relationships.push({
|
|
1473
|
-
quantity: fieldValue.quantity || "",
|
|
1474
|
-
typeCode: fieldValue.typeCode || "",
|
|
1475
|
-
typeLabel: fieldValue.typeLabel || "",
|
|
1476
|
-
entryId: entry.sys.id,
|
|
1477
|
-
});
|
|
1478
|
-
} else {
|
|
1479
|
-
log(
|
|
1480
|
-
`The product with ${fieldValue.code} code was not found, it cannot be associated with the ${currentFieldKey} field of product ${code}`
|
|
1481
|
-
);
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
const prevItemsCount =
|
|
1485
|
-
productEntry?.fields[currentFieldKey]?.length || 0;
|
|
1486
|
-
if (relationships.length || prevItemsCount > 0) {
|
|
1487
|
-
if (!relationships.length && prevItemsCount > 0) {
|
|
1488
|
-
log(
|
|
1489
|
-
`No product relationships found of the field ${currentFieldKey} for the product ${code}, i remove ${prevItemsCount} pre-existing relationships`
|
|
1490
|
-
);
|
|
1491
|
-
} else {
|
|
1492
|
-
log(
|
|
1493
|
-
`Founded ${relationships.length} relationships of ${producRelationCodes.length} PIM relationships for the field ${currentFieldKey} of product ${code}`
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
productEntry.fields[currentFieldKey] = {};
|
|
1497
|
-
productEntry.fields[currentFieldKey][defaultEnvironmentLocaleCode] =
|
|
1498
|
-
relationships;
|
|
1499
|
-
update = true;
|
|
1500
|
-
} else {
|
|
1501
|
-
log(
|
|
1502
|
-
`No product relationships found of the field ${currentFieldKey} for the product ${code}`
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1505
|
-
|
|
1506
|
-
if (++fieldKeysCount % 7 === 0) {
|
|
1507
|
-
await sleep(2000, true);
|
|
1508
|
-
}
|
|
1509
|
-
} else {
|
|
1510
|
-
log(`No field ${currentFieldKey} found for the product ${code}`);
|
|
1511
|
-
}
|
|
1512
|
-
}
|
|
1513
|
-
|
|
1514
|
-
if (update) {
|
|
1515
|
-
try {
|
|
1516
|
-
productEntry = await productEntry.update();
|
|
1517
|
-
log(`Updated ${code} product changes`);
|
|
1518
|
-
if (productEntry.isPublished()) {
|
|
1519
|
-
try {
|
|
1520
|
-
productEntry = await productEntry.publish();
|
|
1521
|
-
log(`Published ${code} product`);
|
|
1522
|
-
} catch (err: any) {
|
|
1523
|
-
const message = `setProductRelationships - Cannot publish entry. ${code}`;
|
|
1524
|
-
await notify(message, false);
|
|
1525
|
-
log(message);
|
|
1526
|
-
log(err);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
} catch (err: any) {
|
|
1530
|
-
const message = `setProductRelationships - Cannot update entry. ${code}`;
|
|
1531
|
-
await notify(message, false);
|
|
1532
|
-
log(message);
|
|
1533
|
-
log(err);
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
} else {
|
|
1537
|
-
log(
|
|
1538
|
-
`${productEntry.sys.id} product payload was not found on S3. Relationships cannot be set.`,
|
|
1539
|
-
"WARN"
|
|
1540
|
-
);
|
|
1541
|
-
}
|
|
1542
|
-
}
|
|
1543
|
-
};
|
|
1544
|
-
|
|
1545
|
-
/**
|
|
1546
|
-
* Set the product relationships
|
|
1547
|
-
*
|
|
1548
|
-
* TODO: È uno dei punti critici dell'import, in quanto dovento interrogare
|
|
1549
|
-
* l'endpoint /products?catalog&lastModified dobbiamo obbligatoriamente scorrere
|
|
1550
|
-
* tutti i prodotti restituiti anche se non interessano.
|
|
1551
|
-
* Potremmo passare la data in cui l'import inizia e ottenere a questo punto
|
|
1552
|
-
* tutti i topicProduct, del catalogo in questione, che hanno il campo lastPimSyncDate >= a quello di inizio import
|
|
1553
|
-
* di contro, facendo così aumenteremmo le chiamate fatte a contentful
|
|
1554
|
-
*
|
|
1555
|
-
* @param catalog
|
|
1556
|
-
* @param lastModified 20210527T00:00:01
|
|
1557
|
-
* @param offset
|
|
1558
|
-
* @param limit
|
|
1559
|
-
* @param s3FilePath pim/2021-05-27/all-products/all-products-ARCHITECTURAL-20200101T00:00:01.json
|
|
1560
|
-
* @returns
|
|
1561
|
-
*/
|
|
1562
|
-
export const setProductsRelationships = async (
|
|
1563
|
-
catalog: AvailableCatalogs,
|
|
1564
|
-
lastModified: string,
|
|
1565
|
-
fieldKey: AvailableRelationFieldKeys | null,
|
|
1566
|
-
offset: number = 0,
|
|
1567
|
-
limit: number = 150,
|
|
1568
|
-
s3FilePath: string = ""
|
|
1569
|
-
) => {
|
|
1570
|
-
const timeStart = new Date();
|
|
1571
|
-
log(
|
|
1572
|
-
`setProductsRelationships - catalog: ${catalog} lastModified: ${lastModified} fieldKey: ${fieldKey} offset: ${offset} limit: ${limit} s3FilePath: ${s3FilePath}`,
|
|
1573
|
-
"INFO"
|
|
1574
|
-
);
|
|
1575
|
-
|
|
1576
|
-
if (!s3FilePath) {
|
|
1577
|
-
const s3Path: string = await saveAllProductsToS3(catalog, lastModified);
|
|
1578
|
-
|
|
1579
|
-
const tEnd = new Date();
|
|
1580
|
-
const secs = secondBetweenTwoDate(timeStart, tEnd);
|
|
1581
|
-
log(`Request time: ${secs} seconds`);
|
|
1582
|
-
|
|
1583
|
-
return {
|
|
1584
|
-
offset: Number(offset),
|
|
1585
|
-
limit: Number(limit),
|
|
1586
|
-
completed: false,
|
|
1587
|
-
s3FilePath: s3Path,
|
|
1588
|
-
};
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
const JSONData: AllProductsEntry[] = await getFileFromS3(s3FilePath);
|
|
1592
|
-
const total: number = JSONData.length;
|
|
1593
|
-
|
|
1594
|
-
log(`${total} products founded`);
|
|
1595
|
-
|
|
1596
|
-
let count: number = 0;
|
|
1597
|
-
let updated: number = 0;
|
|
1598
|
-
let current: number = 0;
|
|
1599
|
-
for (const product of JSONData) {
|
|
1600
|
-
if (offset <= count || limit === -1) {
|
|
1601
|
-
log(`${count + 1} of ${JSONData.length}`);
|
|
1602
|
-
await setProductRelationships(product.code, fieldKey);
|
|
1603
|
-
updated++;
|
|
1604
|
-
|
|
1605
|
-
if (serverUtils) {
|
|
1606
|
-
serverUtils.log(product.code);
|
|
1607
|
-
const currentTotal =
|
|
1608
|
-
JSONData.length > limit && limit !== -1 ? limit : JSONData.length;
|
|
1609
|
-
const progress = Math.floor((++current / currentTotal) * 100);
|
|
1610
|
-
serverUtils.updateProgress(progress);
|
|
1611
|
-
}
|
|
1612
|
-
|
|
1613
|
-
if (updated % 7 === 0) {
|
|
1614
|
-
await sleep(500);
|
|
1615
|
-
}
|
|
1616
|
-
|
|
1617
|
-
if (limit !== -1 && count + 1 - offset >= limit) {
|
|
1618
|
-
break;
|
|
1619
|
-
}
|
|
1620
|
-
}
|
|
1621
|
-
count++;
|
|
1622
|
-
}
|
|
1623
|
-
|
|
1624
|
-
const timeEnd = new Date();
|
|
1625
|
-
const seconds = secondBetweenTwoDate(timeStart, timeEnd);
|
|
1626
|
-
log(`Request time: ${seconds} seconds`);
|
|
1627
|
-
|
|
1628
|
-
if (serverUtils) {
|
|
1629
|
-
serverUtils.updateProgress(100);
|
|
1630
|
-
}
|
|
1631
|
-
|
|
1632
|
-
return {
|
|
1633
|
-
offset: Number(offset) + Number(limit),
|
|
1634
|
-
limit: Number(limit),
|
|
1635
|
-
completed: limit === -1 || limit > updated,
|
|
1636
|
-
s3FilePath,
|
|
1637
|
-
total: JSONData.length,
|
|
1638
|
-
};
|
|
1639
|
-
};
|
|
1640
|
-
|
|
1641
|
-
const removeProductFromAllOfRelationFields = async (
|
|
1642
|
-
productCode: string,
|
|
1643
|
-
fieldKey: string,
|
|
1644
|
-
codes: string[]
|
|
1645
|
-
) => {
|
|
1646
|
-
const fieldKeysOf = {
|
|
1647
|
-
accessories: "accessoryOf",
|
|
1648
|
-
spareparts: "sparepartOf",
|
|
1649
|
-
bulb: "bulbOf",
|
|
1650
|
-
};
|
|
1651
|
-
const fieldKeyOf =
|
|
1652
|
-
fieldKey in fieldKeysOf
|
|
1653
|
-
? fieldKeysOf[fieldKey as keyof typeof fieldKeysOf]
|
|
1654
|
-
: "";
|
|
1655
|
-
|
|
1656
|
-
if (!fieldKeyOf) {
|
|
1657
|
-
log(`The fieldKey ${fieldKey} is not valid`, "WARN");
|
|
1658
|
-
return;
|
|
1659
|
-
}
|
|
1660
|
-
const productEntries = await getAllEntriesByCodes(
|
|
1661
|
-
codes,
|
|
1662
|
-
"topicProduct",
|
|
1663
|
-
"sys,fields",
|
|
1664
|
-
"fields.code"
|
|
1665
|
-
);
|
|
1666
|
-
|
|
1667
|
-
log(
|
|
1668
|
-
`Remove ${fieldKeyOf} relation from ${productEntries.length} topicProduct`
|
|
1669
|
-
);
|
|
1670
|
-
for (let productEntry of productEntries) {
|
|
1671
|
-
if (productEntry.isArchived()) {
|
|
1672
|
-
log(
|
|
1673
|
-
`Can't remove the ${fieldKeyOf} from ${productEntry.sys.id} because it is archived.`,
|
|
1674
|
-
"WARN"
|
|
1675
|
-
);
|
|
1676
|
-
} else {
|
|
1677
|
-
log(
|
|
1678
|
-
`Removing ${productCode} from the ${fieldKeyOf} of the product ${productEntry.sys.id}...`
|
|
1679
|
-
);
|
|
1680
|
-
productEntry.fields = await removeFromFieldObject(
|
|
1681
|
-
productEntry,
|
|
1682
|
-
fieldKeyOf,
|
|
1683
|
-
productCode
|
|
1684
|
-
);
|
|
1685
|
-
try {
|
|
1686
|
-
log(`update ${productEntry.sys.id}`);
|
|
1687
|
-
productEntry = await productEntry.update();
|
|
1688
|
-
if (productEntry.isPublished()) {
|
|
1689
|
-
try {
|
|
1690
|
-
productEntry = await productEntry.publish();
|
|
1691
|
-
} catch (err: any) {
|
|
1692
|
-
log(`Cannot publish entry ${productEntry.sys.id}.`);
|
|
1693
|
-
log(err);
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
} catch (err: any) {
|
|
1697
|
-
log(`Cannot update entry ${productEntry.sys.id}.`);
|
|
1698
|
-
log(err);
|
|
1699
|
-
}
|
|
1700
|
-
}
|
|
1701
|
-
}
|
|
1702
|
-
};
|
|
1703
|
-
|
|
1704
|
-
/**
|
|
1705
|
-
* Get all product entries of a specific catalog
|
|
1706
|
-
*
|
|
1707
|
-
* @param catalog
|
|
1708
|
-
* @returns
|
|
1709
|
-
*/
|
|
1710
|
-
export const getAllProductEntriesByCatalog = async (
|
|
1711
|
-
catalog: AvailableCatalogs,
|
|
1712
|
-
limit: number = 100,
|
|
1713
|
-
select: string = ""
|
|
1714
|
-
): Promise<Entry[]> => {
|
|
1715
|
-
log(`getAllProductEntriesByCatalog - catalog: ${catalog}`, "INFO");
|
|
1716
|
-
const env = await getEnvironment();
|
|
1717
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
1718
|
-
let allItems: Entry[] = [];
|
|
1719
|
-
let othersPagesToFetch = false;
|
|
1720
|
-
let skip = 0;
|
|
1721
|
-
let count = 0;
|
|
1722
|
-
do {
|
|
1723
|
-
const { items, total } = await env.getEntries({
|
|
1724
|
-
content_type: "topicProduct",
|
|
1725
|
-
"fields.catalogs.sys.id": catalog,
|
|
1726
|
-
limit,
|
|
1727
|
-
skip,
|
|
1728
|
-
locale: defEnvLocaleCode,
|
|
1729
|
-
include: 0,
|
|
1730
|
-
select,
|
|
1731
|
-
});
|
|
1732
|
-
|
|
1733
|
-
allItems = [...allItems, ...(items || [])];
|
|
1734
|
-
|
|
1735
|
-
log(`${allItems.length} topicProduct founded of ${total}`);
|
|
1736
|
-
|
|
1737
|
-
if (total && allItems.length < total) {
|
|
1738
|
-
othersPagesToFetch = true;
|
|
1739
|
-
skip += limit;
|
|
1740
|
-
if (++count % 7 === 0) {
|
|
1741
|
-
await sleep(200);
|
|
1742
|
-
}
|
|
1743
|
-
} else {
|
|
1744
|
-
othersPagesToFetch = false;
|
|
1745
|
-
}
|
|
1746
|
-
} while (othersPagesToFetch);
|
|
1747
|
-
|
|
1748
|
-
log(`${allItems.length} topicProduct founded`);
|
|
1749
|
-
|
|
1750
|
-
return allItems;
|
|
1751
|
-
};
|
|
1752
|
-
|
|
1753
|
-
const productAudit = async (
|
|
1754
|
-
audit: Audit,
|
|
1755
|
-
productEntries: Entry[],
|
|
1756
|
-
catalog: AvailableCatalogs,
|
|
1757
|
-
defaultEnvironmentLocaleCode: string,
|
|
1758
|
-
current: number,
|
|
1759
|
-
allAudit: Audit[],
|
|
1760
|
-
productPageEntries: Entry[]
|
|
1761
|
-
) => {
|
|
1762
|
-
log(`Search product entry with id ${audit.product}...`);
|
|
1763
|
-
let productEntry = productEntries.find(
|
|
1764
|
-
(currentEntry) =>
|
|
1765
|
-
currentEntry?.fields?.code?.[defaultEnvironmentLocaleCode] ===
|
|
1766
|
-
audit.product
|
|
1767
|
-
);
|
|
1768
|
-
|
|
1769
|
-
if (!productEntry) {
|
|
1770
|
-
let logMessage = "";
|
|
1771
|
-
if (catalog) {
|
|
1772
|
-
logMessage = `The ${audit.product} product was not found in the CMS with catalog ${catalog}`;
|
|
1773
|
-
} else {
|
|
1774
|
-
logMessage = `The ${audit.product} product was not found in the CMS`;
|
|
1775
|
-
}
|
|
1776
|
-
log(logMessage, "WARN");
|
|
1777
|
-
|
|
1778
|
-
if (serverUtils) {
|
|
1779
|
-
serverUtils.log(logMessage);
|
|
1780
|
-
const progress = Math.floor((++current / allAudit.length) * 100);
|
|
1781
|
-
serverUtils.updateProgress(progress);
|
|
1782
|
-
}
|
|
1783
|
-
return { current, continue: true };
|
|
1784
|
-
}
|
|
1785
|
-
|
|
1786
|
-
log(`Founded product with id ${productEntry.sys.id}`);
|
|
1787
|
-
|
|
1788
|
-
const pageEntryFromId = getProductPageIdByCode(audit.product);
|
|
1789
|
-
log(`Search product page entry with id ${pageEntryFromId}...`);
|
|
1790
|
-
let pageEntryFrom = productPageEntries.find(
|
|
1791
|
-
(currentEntry) => currentEntry.sys.id === pageEntryFromId
|
|
1792
|
-
);
|
|
1793
|
-
|
|
1794
|
-
if (pageEntryFrom) {
|
|
1795
|
-
log(`Founded product page with id ${pageEntryFrom.sys.id}`);
|
|
1796
|
-
} else {
|
|
1797
|
-
log(`Product page with id ${pageEntryFromId} not found`, "WARN");
|
|
1798
|
-
}
|
|
1799
|
-
|
|
1800
|
-
log(`Get product catalogs...`);
|
|
1801
|
-
const productCatalogs: AvailableCatalogs[] = productEntry?.fields?.catalogs?.[
|
|
1802
|
-
defaultEnvironmentLocaleCode
|
|
1803
|
-
].map((entryCatalog: FieldItem) => {
|
|
1804
|
-
return entryCatalog.sys.id;
|
|
1805
|
-
});
|
|
1806
|
-
|
|
1807
|
-
if (catalog && !productCatalogs.includes(catalog)) {
|
|
1808
|
-
log(`Product ${audit.product} does not belong to the ${catalog} catalog`);
|
|
1809
|
-
} else if (["PRODUCT_UNPUBLISH", "PRODUCT_WEBOFF"].includes(audit.what)) {
|
|
1810
|
-
log(`Set the product status as archive...`);
|
|
1811
|
-
// Set the product status as archive
|
|
1812
|
-
productEntry = await archiveEntry(productEntry, true);
|
|
1813
|
-
if (!pageEntryFrom) {
|
|
1814
|
-
log(`${pageEntryFromId} page from not found`);
|
|
1815
|
-
} else if (pageEntryFrom.isArchived()) {
|
|
1816
|
-
log(
|
|
1817
|
-
`Can't create redirect ${audit.product} to ${audit.upgradeProduct} because the page ${pageEntryFrom.sys.id} is archived.`,
|
|
1818
|
-
"WARN"
|
|
1819
|
-
);
|
|
1820
|
-
} else if (pageEntryFrom?.fields) {
|
|
1821
|
-
if (audit.upgradeProduct && audit.upgradeProduct !== "0") {
|
|
1822
|
-
log(
|
|
1823
|
-
`Creating redirect from ${audit.product} to ${audit.upgradeProduct}`
|
|
1824
|
-
);
|
|
1825
|
-
const pageEntryToId = getProductPageIdByCode(audit.upgradeProduct);
|
|
1826
|
-
const pageEntryTo = await getEntryByID(pageEntryToId, "page", "sys.id");
|
|
1827
|
-
|
|
1828
|
-
if (pageEntryTo) {
|
|
1829
|
-
// Save redirect
|
|
1830
|
-
pageEntryFrom.fields = await addToRelationFields(
|
|
1831
|
-
pageEntryFrom,
|
|
1832
|
-
"redirectTo",
|
|
1833
|
-
pageEntryTo.sys.id
|
|
1834
|
-
);
|
|
1835
|
-
pageEntryFrom = await pageEntryFrom.update();
|
|
1836
|
-
} else {
|
|
1837
|
-
log(
|
|
1838
|
-
`Can't create redirect ${audit.product} to ${audit.upgradeProduct} because the page ${pageEntryToId} not found.`,
|
|
1839
|
-
"WARN"
|
|
1840
|
-
);
|
|
1841
|
-
}
|
|
1842
|
-
}
|
|
1843
|
-
|
|
1844
|
-
pageEntryFrom = await archiveEntry(pageEntryFrom);
|
|
1845
|
-
}
|
|
1846
|
-
} else if (
|
|
1847
|
-
audit.what === "REMOVE_PRODUCT_RELATIONS" &&
|
|
1848
|
-
!productEntry.isArchived()
|
|
1849
|
-
) {
|
|
1850
|
-
log(`Remove product relations...`);
|
|
1851
|
-
if (productEntry.isUpdated()) {
|
|
1852
|
-
try {
|
|
1853
|
-
log(`Publish existing changes of entry ${productEntry.sys.id}.`);
|
|
1854
|
-
productEntry = await productEntry.publish();
|
|
1855
|
-
} catch (err: any) {
|
|
1856
|
-
log(`Cannot publish changes of entry ${productEntry.sys.id}.`);
|
|
1857
|
-
log(err);
|
|
1858
|
-
}
|
|
1859
|
-
}
|
|
1860
|
-
if (audit?.catalogs) {
|
|
1861
|
-
for (const item of audit?.catalogs) {
|
|
1862
|
-
if (!item?.where) {
|
|
1863
|
-
log(
|
|
1864
|
-
`catalogs.where field not exists. Product: ${audit.product} `,
|
|
1865
|
-
"WARN"
|
|
1866
|
-
);
|
|
1867
|
-
} else {
|
|
1868
|
-
let edit = false;
|
|
1869
|
-
if (item?.catalogCode) {
|
|
1870
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1871
|
-
productEntry,
|
|
1872
|
-
"catalogs",
|
|
1873
|
-
item.catalogCode,
|
|
1874
|
-
true
|
|
1875
|
-
);
|
|
1876
|
-
log(`edit catalogs`);
|
|
1877
|
-
edit = true;
|
|
1878
|
-
}
|
|
1879
|
-
if (item?.categoryCode) {
|
|
1880
|
-
const categoriesFieldKey =
|
|
1881
|
-
"categories" + capitalizeFirstLetter(item.where);
|
|
1882
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1883
|
-
productEntry,
|
|
1884
|
-
categoriesFieldKey,
|
|
1885
|
-
item.categoryCode,
|
|
1886
|
-
true
|
|
1887
|
-
);
|
|
1888
|
-
log(`edit ${categoriesFieldKey}`);
|
|
1889
|
-
edit = true;
|
|
1890
|
-
}
|
|
1891
|
-
if (item?.subfamilyCode) {
|
|
1892
|
-
const subFamiliesFieldKey =
|
|
1893
|
-
"subFamilies" + capitalizeFirstLetter(item.where);
|
|
1894
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1895
|
-
productEntry,
|
|
1896
|
-
subFamiliesFieldKey,
|
|
1897
|
-
item.subfamilyCode,
|
|
1898
|
-
true
|
|
1899
|
-
);
|
|
1900
|
-
log(`edit ${subFamiliesFieldKey}`);
|
|
1901
|
-
edit = true;
|
|
1902
|
-
}
|
|
1903
|
-
if (item?.models) {
|
|
1904
|
-
const modelsFieldKey = "models" + capitalizeFirstLetter(item.where);
|
|
1905
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1906
|
-
productEntry,
|
|
1907
|
-
modelsFieldKey,
|
|
1908
|
-
item.models,
|
|
1909
|
-
true
|
|
1910
|
-
);
|
|
1911
|
-
log(`edit ${modelsFieldKey}`);
|
|
1912
|
-
edit = true;
|
|
1913
|
-
}
|
|
1914
|
-
if (item?.subModels) {
|
|
1915
|
-
const subModelsFieldKey =
|
|
1916
|
-
"subModels" + capitalizeFirstLetter(item.where);
|
|
1917
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1918
|
-
productEntry,
|
|
1919
|
-
subModelsFieldKey,
|
|
1920
|
-
item.subModels,
|
|
1921
|
-
true
|
|
1922
|
-
);
|
|
1923
|
-
log(`edit ${subModelsFieldKey}`);
|
|
1924
|
-
edit = true;
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
const objectFieldsRelations: any = {
|
|
1928
|
-
ACCESSORIES: "accessories",
|
|
1929
|
-
SPARE_PARTS: "spareparts",
|
|
1930
|
-
BULBS: "bulbs",
|
|
1931
|
-
};
|
|
1932
|
-
|
|
1933
|
-
for (const objectFieldsRelationKey of Object.keys(
|
|
1934
|
-
objectFieldsRelations
|
|
1935
|
-
)) {
|
|
1936
|
-
if (item.where === objectFieldsRelationKey) {
|
|
1937
|
-
log(`Remove ${objectFieldsRelationKey} relations`);
|
|
1938
|
-
const codes = item.codes?.split(",") ?? [];
|
|
1939
|
-
if (codes.length) {
|
|
1940
|
-
const fieldKey = objectFieldsRelations[objectFieldsRelationKey];
|
|
1941
|
-
const lengthBefore =
|
|
1942
|
-
productEntry.fields?.[fieldKey]?.[
|
|
1943
|
-
defaultEnvironmentLocaleCode
|
|
1944
|
-
].length;
|
|
1945
|
-
|
|
1946
|
-
// Remove from the main product field
|
|
1947
|
-
productEntry.fields = await removeFromFieldObject(
|
|
1948
|
-
productEntry,
|
|
1949
|
-
fieldKey,
|
|
1950
|
-
codes
|
|
1951
|
-
);
|
|
1952
|
-
// Remove from the codes of field
|
|
1953
|
-
await removeProductFromAllOfRelationFields(
|
|
1954
|
-
productEntry.sys.id,
|
|
1955
|
-
fieldKey,
|
|
1956
|
-
codes
|
|
1957
|
-
);
|
|
1958
|
-
|
|
1959
|
-
const lengthAfter =
|
|
1960
|
-
productEntry.fields?.[fieldKey]?.[
|
|
1961
|
-
defaultEnvironmentLocaleCode
|
|
1962
|
-
].length;
|
|
1963
|
-
if (lengthBefore !== lengthAfter) {
|
|
1964
|
-
log(
|
|
1965
|
-
`edit field ${fieldKey} lengthBefore: ${lengthBefore} lengthAfter: ${lengthAfter}`
|
|
1966
|
-
);
|
|
1967
|
-
edit = true;
|
|
1968
|
-
} else {
|
|
1969
|
-
log(`No valid ${objectFieldsRelationKey} to remove found`);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
}
|
|
1973
|
-
}
|
|
1974
|
-
|
|
1975
|
-
if (item.where === "DESIGNERS" && item?.codes) {
|
|
1976
|
-
const lengthBefore =
|
|
1977
|
-
productEntry.fields?.designer?.[defaultEnvironmentLocaleCode]
|
|
1978
|
-
.length;
|
|
1979
|
-
const designers = item.codes.split(",");
|
|
1980
|
-
for (const designer of designers) {
|
|
1981
|
-
log(
|
|
1982
|
-
`Remove ${designer} designer to ${productEntry.sys.id} product if exists`
|
|
1983
|
-
);
|
|
1984
|
-
productEntry.fields = await removeFromRelationFields(
|
|
1985
|
-
productEntry,
|
|
1986
|
-
"designer",
|
|
1987
|
-
designer,
|
|
1988
|
-
false
|
|
1989
|
-
);
|
|
1990
|
-
}
|
|
1991
|
-
|
|
1992
|
-
if (
|
|
1993
|
-
lengthBefore !==
|
|
1994
|
-
productEntry.fields?.designer?.[defaultEnvironmentLocaleCode]
|
|
1995
|
-
.length
|
|
1996
|
-
) {
|
|
1997
|
-
log(`edit designer`);
|
|
1998
|
-
edit = true;
|
|
1999
|
-
} else {
|
|
2000
|
-
log(`No valid designer to remove found`);
|
|
2001
|
-
}
|
|
2002
|
-
}
|
|
2003
|
-
|
|
2004
|
-
if (edit) {
|
|
2005
|
-
// lastPimSyncDate
|
|
2006
|
-
productEntry.fields = await addFieldValue(
|
|
2007
|
-
productEntry,
|
|
2008
|
-
"lastPimSyncDate",
|
|
2009
|
-
getLocalISOTime()
|
|
2010
|
-
);
|
|
2011
|
-
try {
|
|
2012
|
-
log(`update ${productEntry.sys.id}`);
|
|
2013
|
-
productEntry = await productEntry.update();
|
|
2014
|
-
if (productEntry.isPublished()) {
|
|
2015
|
-
try {
|
|
2016
|
-
productEntry = await productEntry.publish();
|
|
2017
|
-
} catch (err: any) {
|
|
2018
|
-
log(`Cannot publish entry ${productEntry.sys.id}.`);
|
|
2019
|
-
log(err);
|
|
2020
|
-
}
|
|
2021
|
-
}
|
|
2022
|
-
} catch (err: any) {
|
|
2023
|
-
log(`Cannot update entry ${productEntry.sys.id}.`);
|
|
2024
|
-
log(err);
|
|
2025
|
-
}
|
|
2026
|
-
} else {
|
|
2027
|
-
log(`No valid editable criteria found`);
|
|
2028
|
-
console.log(productEntry.sys.id, "audit", audit);
|
|
2029
|
-
}
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
|
-
} else {
|
|
2033
|
-
log(
|
|
2034
|
-
`No catalogs field found in the audit ${audit.product} product`,
|
|
2035
|
-
"WARN"
|
|
2036
|
-
);
|
|
2037
|
-
}
|
|
2038
|
-
} else {
|
|
2039
|
-
log(`It has not yet been defined how to process the state ${audit.what}`);
|
|
2040
|
-
}
|
|
2041
|
-
|
|
2042
|
-
return { current, continue: false };
|
|
2043
|
-
};
|
|
2044
|
-
|
|
2045
|
-
const familyAudit = async (
|
|
2046
|
-
audit: Audit,
|
|
2047
|
-
familyEntries: Entry[],
|
|
2048
|
-
catalog: AvailableCatalogs,
|
|
2049
|
-
defaultEnvironmentLocaleCode: string,
|
|
2050
|
-
current: number,
|
|
2051
|
-
allAudit: Audit[]
|
|
2052
|
-
) => {
|
|
2053
|
-
log(`Search family entry with id ${audit.product}...`);
|
|
2054
|
-
let familyEntry = familyEntries.find(
|
|
2055
|
-
(currentEntry) =>
|
|
2056
|
-
currentEntry?.fields?.code?.[defaultEnvironmentLocaleCode] ===
|
|
2057
|
-
audit.product
|
|
2058
|
-
);
|
|
2059
|
-
|
|
2060
|
-
if (!familyEntry) {
|
|
2061
|
-
let logMessage = "";
|
|
2062
|
-
if (catalog) {
|
|
2063
|
-
logMessage = `The ${audit.product} family was not found in the CMS with catalog ${catalog}`;
|
|
2064
|
-
} else {
|
|
2065
|
-
logMessage = `The ${audit.product} family was not found in the CMS`;
|
|
2066
|
-
}
|
|
2067
|
-
log(logMessage, "WARN");
|
|
2068
|
-
|
|
2069
|
-
if (serverUtils) {
|
|
2070
|
-
serverUtils.log(logMessage);
|
|
2071
|
-
const progress = Math.floor((++current / allAudit.length) * 100);
|
|
2072
|
-
serverUtils.updateProgress(progress);
|
|
2073
|
-
}
|
|
2074
|
-
return { current, continue: true };
|
|
2075
|
-
}
|
|
2076
|
-
|
|
2077
|
-
log(`Founded family with id ${familyEntry.sys.id}`);
|
|
2078
|
-
|
|
2079
|
-
log(`Get family catalogs...`);
|
|
2080
|
-
const familyCatalogs: AvailableCatalogs[] = familyEntry?.fields?.catalogs?.[
|
|
2081
|
-
defaultEnvironmentLocaleCode
|
|
2082
|
-
].map((entryCatalog: FieldItem) => {
|
|
2083
|
-
return entryCatalog.sys.id;
|
|
2084
|
-
});
|
|
2085
|
-
|
|
2086
|
-
if (catalog && !familyCatalogs.includes(catalog)) {
|
|
2087
|
-
log(`Family ${audit.product} does not belong to the ${catalog} catalog`);
|
|
2088
|
-
} else if (audit.what === "REMOVE_FAMILY_RELATIONS") {
|
|
2089
|
-
for (const item of audit?.catalogs) {
|
|
2090
|
-
if (!item?.where) {
|
|
2091
|
-
log(
|
|
2092
|
-
`catalogs.where field not exists. Family: ${audit.product} `,
|
|
2093
|
-
"WARN"
|
|
2094
|
-
);
|
|
2095
|
-
} else {
|
|
2096
|
-
if (item.where === "DESIGNERS" && item?.codes) {
|
|
2097
|
-
const designers = item.codes.split(",");
|
|
2098
|
-
for (const designer of designers) {
|
|
2099
|
-
log(
|
|
2100
|
-
`Remove ${designer} designer to ${familyEntry.sys.id} family if exists`
|
|
2101
|
-
);
|
|
2102
|
-
familyEntry.fields = await removeFromRelationFields(
|
|
2103
|
-
familyEntry,
|
|
2104
|
-
"designer",
|
|
2105
|
-
designer,
|
|
2106
|
-
false
|
|
2107
|
-
);
|
|
2108
|
-
}
|
|
2109
|
-
familyEntry = await familyEntry.update();
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
} else {
|
|
2114
|
-
log(`It has not yet been defined how to process the state ${audit.what}`);
|
|
2115
|
-
}
|
|
2116
|
-
|
|
2117
|
-
return { current, continue: false };
|
|
2118
|
-
};
|
|
2119
|
-
|
|
2120
|
-
const subFamilyAudit = async (
|
|
2121
|
-
audit: Audit,
|
|
2122
|
-
subfamilyEntries: Entry[],
|
|
2123
|
-
catalog: AvailableCatalogs,
|
|
2124
|
-
defaultEnvironmentLocaleCode: string,
|
|
2125
|
-
current: number,
|
|
2126
|
-
allAudit: Audit[]
|
|
2127
|
-
) => {
|
|
2128
|
-
log(`Search subFamily entry with id ${audit.product}...`);
|
|
2129
|
-
let subFamilyEntry = subfamilyEntries.find(
|
|
2130
|
-
(currentEntry) =>
|
|
2131
|
-
currentEntry?.fields?.code?.[defaultEnvironmentLocaleCode] ===
|
|
2132
|
-
audit.product
|
|
2133
|
-
);
|
|
2134
|
-
|
|
2135
|
-
if (!subFamilyEntry) {
|
|
2136
|
-
let logMessage = "";
|
|
2137
|
-
if (catalog) {
|
|
2138
|
-
logMessage = `The ${audit.product} subFamily was not found in the CMS with catalog ${catalog}`;
|
|
2139
|
-
} else {
|
|
2140
|
-
logMessage = `The ${audit.product} subFamily was not found in the CMS`;
|
|
2141
|
-
}
|
|
2142
|
-
log(logMessage, "WARN");
|
|
2143
|
-
|
|
2144
|
-
if (serverUtils) {
|
|
2145
|
-
serverUtils.log(logMessage);
|
|
2146
|
-
const progress = Math.floor((++current / allAudit.length) * 100);
|
|
2147
|
-
serverUtils.updateProgress(progress);
|
|
2148
|
-
}
|
|
2149
|
-
return { current, continue: true };
|
|
2150
|
-
}
|
|
2151
|
-
|
|
2152
|
-
log(`Founded subFamily with id ${subFamilyEntry.sys.id}`);
|
|
2153
|
-
|
|
2154
|
-
log(`Get subFamily catalogs...`);
|
|
2155
|
-
const subFamilyCatalog: AvailableCatalogs =
|
|
2156
|
-
subFamilyEntry?.fields?.catalog?.[defaultEnvironmentLocaleCode].sys.id;
|
|
2157
|
-
|
|
2158
|
-
if (catalog && subFamilyCatalog !== catalog) {
|
|
2159
|
-
log(`SubFamily ${audit.product} does not belong to the ${catalog} catalog`);
|
|
2160
|
-
} else if (audit.what === "REMOVE_SUBFAMILY_RELATIONS") {
|
|
2161
|
-
for (const item of audit?.catalogs) {
|
|
2162
|
-
if (!item?.where) {
|
|
2163
|
-
log(
|
|
2164
|
-
`catalogs.where field not exists. SubFamily: ${audit.product} `,
|
|
2165
|
-
"WARN"
|
|
2166
|
-
);
|
|
2167
|
-
} else {
|
|
2168
|
-
if (item.where === "DESIGNERS" && item?.codes) {
|
|
2169
|
-
const designers = item.codes.split(",");
|
|
2170
|
-
for (const designer of designers) {
|
|
2171
|
-
log(
|
|
2172
|
-
`Remove ${designer} designer to ${subFamilyEntry.sys.id} subFamily if exists`
|
|
2173
|
-
);
|
|
2174
|
-
subFamilyEntry.fields = await removeFromRelationFields(
|
|
2175
|
-
subFamilyEntry,
|
|
2176
|
-
"designer",
|
|
2177
|
-
designer,
|
|
2178
|
-
false
|
|
2179
|
-
);
|
|
2180
|
-
}
|
|
2181
|
-
subFamilyEntry = await subFamilyEntry.update();
|
|
2182
|
-
}
|
|
2183
|
-
}
|
|
2184
|
-
}
|
|
2185
|
-
} else {
|
|
2186
|
-
log(`It has not yet been defined how to process the state ${audit.what}`);
|
|
2187
|
-
}
|
|
2188
|
-
|
|
2189
|
-
return { current, continue: false };
|
|
2190
|
-
};
|
|
2191
|
-
|
|
2192
|
-
/**
|
|
2193
|
-
*
|
|
2194
|
-
* Audit - Checks if there are products to publish or unpublish
|
|
2195
|
-
*
|
|
2196
|
-
* @param {string} lastModified The last modified data. Format: 20200426T07:50:00 - yearmonthdayThour:minute:second
|
|
2197
|
-
* @param {string} catalog
|
|
2198
|
-
*/
|
|
2199
|
-
export const audit = async (
|
|
2200
|
-
lastModified: string,
|
|
2201
|
-
catalog: AvailableCatalogs,
|
|
2202
|
-
offset: number = 0,
|
|
2203
|
-
limit: number = 150,
|
|
2204
|
-
s3FilePath: string = ""
|
|
2205
|
-
) => {
|
|
2206
|
-
offset = Number(offset);
|
|
2207
|
-
limit = Number(limit);
|
|
2208
|
-
const timeStart = new Date();
|
|
2209
|
-
log(`audit - lastModified: ${lastModified} catalog: ${catalog}`, "INFO");
|
|
2210
|
-
|
|
2211
|
-
// if not exists save data to s3
|
|
2212
|
-
if (!s3FilePath) {
|
|
2213
|
-
const allAudit = await getAudit(lastModified);
|
|
2214
|
-
if (!allAudit) {
|
|
2215
|
-
log(`No audits were found to process for the date ${lastModified}`);
|
|
2216
|
-
return {
|
|
2217
|
-
offset,
|
|
2218
|
-
limit,
|
|
2219
|
-
completed: true,
|
|
2220
|
-
s3FilePath: "",
|
|
2221
|
-
total: 0,
|
|
2222
|
-
processedEntries: 0,
|
|
2223
|
-
};
|
|
2224
|
-
}
|
|
2225
|
-
|
|
2226
|
-
const filename = `${lastModified}-all-audit.json`;
|
|
2227
|
-
const path = `audit`;
|
|
2228
|
-
await saveJsonToS3(allAudit, filename, path);
|
|
2229
|
-
const s3Path = `${path}/${filename}`;
|
|
2230
|
-
|
|
2231
|
-
if (serverUtils) {
|
|
2232
|
-
serverUtils.log(`Saved s3FilePath: ${s3Path}`);
|
|
2233
|
-
serverUtils.updateProgress(100);
|
|
2234
|
-
}
|
|
2235
|
-
|
|
2236
|
-
return {
|
|
2237
|
-
offset: Number(offset),
|
|
2238
|
-
limit: Number(limit),
|
|
2239
|
-
completed: false,
|
|
2240
|
-
s3FilePath: s3Path,
|
|
2241
|
-
total: allAudit.length,
|
|
2242
|
-
processedEntries: 0,
|
|
2243
|
-
};
|
|
2244
|
-
}
|
|
2245
|
-
|
|
2246
|
-
// get data from s3
|
|
2247
|
-
log(`Get audit details from ${s3FilePath}`);
|
|
2248
|
-
let allAudit: Audit[] = await getFileFromS3(s3FilePath);
|
|
2249
|
-
const total: number = allAudit.length;
|
|
2250
|
-
allAudit = allAudit.slice(offset, offset + limit);
|
|
2251
|
-
log(`Founded ${allAudit.length} items`);
|
|
2252
|
-
|
|
2253
|
-
if (allAudit) {
|
|
2254
|
-
const defaultEnvironmentLocaleCode =
|
|
2255
|
-
await getEnvironmentDefaultLocaleCode();
|
|
2256
|
-
|
|
2257
|
-
const productAuditWhat = [
|
|
2258
|
-
"PRODUCT_UNPUBLISH",
|
|
2259
|
-
"PRODUCT_WEBOFF",
|
|
2260
|
-
"REMOVE_PRODUCT_RELATIONS",
|
|
2261
|
-
];
|
|
2262
|
-
const productCodes = allAudit
|
|
2263
|
-
.filter((item) => productAuditWhat.includes(item.what))
|
|
2264
|
-
.map((audit) => audit.product);
|
|
2265
|
-
const familyCodes = allAudit
|
|
2266
|
-
.filter((item) => item.what === "REMOVE_FAMILY_RELATIONS")
|
|
2267
|
-
.map((audit) => audit.product);
|
|
2268
|
-
const subFamilyCodes = allAudit
|
|
2269
|
-
.filter((item) => item.what === "REMOVE_SUBFAMILY_RELATIONS")
|
|
2270
|
-
.map((audit) => audit.product);
|
|
2271
|
-
const otherFilters = [];
|
|
2272
|
-
if (catalog) {
|
|
2273
|
-
otherFilters.push({ key: "fields.catalogs.sys.id[in]", value: catalog });
|
|
2274
|
-
}
|
|
2275
|
-
log(`Get ${productCodes.length} product entry from Contentful`);
|
|
2276
|
-
const productEntries = await getAllEntriesByCodes(
|
|
2277
|
-
productCodes,
|
|
2278
|
-
"topicProduct",
|
|
2279
|
-
"sys,fields",
|
|
2280
|
-
"fields.code",
|
|
2281
|
-
otherFilters
|
|
2282
|
-
);
|
|
2283
|
-
log(`Founded ${productEntries.length} topicProduct`);
|
|
2284
|
-
|
|
2285
|
-
let familyEntries: Entry[] = [];
|
|
2286
|
-
if (familyCodes.length) {
|
|
2287
|
-
familyEntries = await getAllEntriesByCodes(
|
|
2288
|
-
familyCodes,
|
|
2289
|
-
"topicFamily",
|
|
2290
|
-
"sys,fields",
|
|
2291
|
-
"fields.code",
|
|
2292
|
-
otherFilters
|
|
2293
|
-
);
|
|
2294
|
-
}
|
|
2295
|
-
log(`Founded ${familyEntries.length} topicFamily`);
|
|
2296
|
-
|
|
2297
|
-
let subFamilyEntries: Entry[] = [];
|
|
2298
|
-
if (subFamilyCodes.length) {
|
|
2299
|
-
subFamilyEntries = await getAllEntriesByCodes(
|
|
2300
|
-
subFamilyCodes,
|
|
2301
|
-
"topicSubFamily",
|
|
2302
|
-
"sys,fields",
|
|
2303
|
-
"fields.code",
|
|
2304
|
-
otherFilters
|
|
2305
|
-
);
|
|
2306
|
-
}
|
|
2307
|
-
log(`Founded ${subFamilyEntries.length} topicSubFamily`);
|
|
2308
|
-
|
|
2309
|
-
if (
|
|
2310
|
-
!productEntries.length &&
|
|
2311
|
-
!familyEntries.length &&
|
|
2312
|
-
!subFamilyEntries.length
|
|
2313
|
-
) {
|
|
2314
|
-
log(
|
|
2315
|
-
`No items found between offset: ${offset} and limit: ${limit}. Total: ${total}`
|
|
2316
|
-
);
|
|
2317
|
-
const nextOffset = offset + limit;
|
|
2318
|
-
const completed = limit === -1 || offset >= total;
|
|
2319
|
-
if (completed) {
|
|
2320
|
-
log(`Audit completed`);
|
|
2321
|
-
}
|
|
2322
|
-
|
|
2323
|
-
const tEnd = new Date();
|
|
2324
|
-
const secs = secondBetweenTwoDate(timeStart, tEnd);
|
|
2325
|
-
log(`Execution time: ${secs} seconds`);
|
|
2326
|
-
|
|
2327
|
-
if (serverUtils) {
|
|
2328
|
-
serverUtils.log(`Audit completed`);
|
|
2329
|
-
serverUtils.updateProgress(100);
|
|
2330
|
-
}
|
|
2331
|
-
|
|
2332
|
-
return {
|
|
2333
|
-
offset: nextOffset,
|
|
2334
|
-
limit: limit,
|
|
2335
|
-
completed,
|
|
2336
|
-
s3FilePath,
|
|
2337
|
-
total,
|
|
2338
|
-
processedEntries: 0,
|
|
2339
|
-
};
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
|
-
const pageCodes = productEntries.map((entry: Entry) =>
|
|
2343
|
-
getProductPageIdByCode(entry.fields.code[defaultEnvironmentLocaleCode])
|
|
2344
|
-
);
|
|
2345
|
-
|
|
2346
|
-
log(`Get ${pageCodes.length} product page entry from Contentful`);
|
|
2347
|
-
const productPageEntries = await getAllEntriesByCodes(
|
|
2348
|
-
pageCodes,
|
|
2349
|
-
"page",
|
|
2350
|
-
"sys,fields",
|
|
2351
|
-
"sys.id"
|
|
2352
|
-
);
|
|
2353
|
-
log(`Founded ${productPageEntries.length} topicProduct pages`);
|
|
2354
|
-
|
|
2355
|
-
let count: number = offset;
|
|
2356
|
-
let current: number = 0;
|
|
2357
|
-
for (const audit of allAudit) {
|
|
2358
|
-
log(`${++count} of ${total}`);
|
|
2359
|
-
log(`I process the item ${audit.product} with status ${audit.what}`);
|
|
2360
|
-
|
|
2361
|
-
if (productAuditWhat.includes(audit.what)) {
|
|
2362
|
-
const result = await productAudit(
|
|
2363
|
-
audit,
|
|
2364
|
-
productEntries,
|
|
2365
|
-
catalog,
|
|
2366
|
-
defaultEnvironmentLocaleCode,
|
|
2367
|
-
current,
|
|
2368
|
-
allAudit,
|
|
2369
|
-
productPageEntries
|
|
2370
|
-
);
|
|
2371
|
-
current = result.current;
|
|
2372
|
-
if (result.continue) {
|
|
2373
|
-
continue;
|
|
2374
|
-
}
|
|
2375
|
-
} else if (audit.what === "REMOVE_FAMILY_RELATIONS") {
|
|
2376
|
-
const result = await familyAudit(
|
|
2377
|
-
audit,
|
|
2378
|
-
familyEntries,
|
|
2379
|
-
catalog,
|
|
2380
|
-
defaultEnvironmentLocaleCode,
|
|
2381
|
-
current,
|
|
2382
|
-
allAudit
|
|
2383
|
-
);
|
|
2384
|
-
current = result.current;
|
|
2385
|
-
if (result.continue) {
|
|
2386
|
-
continue;
|
|
2387
|
-
}
|
|
2388
|
-
} else if (audit.what === "REMOVE_SUBFAMILY_RELATIONS") {
|
|
2389
|
-
const result = await subFamilyAudit(
|
|
2390
|
-
audit,
|
|
2391
|
-
subFamilyEntries,
|
|
2392
|
-
catalog,
|
|
2393
|
-
defaultEnvironmentLocaleCode,
|
|
2394
|
-
current,
|
|
2395
|
-
allAudit
|
|
2396
|
-
);
|
|
2397
|
-
current = result.current;
|
|
2398
|
-
if (result.continue) {
|
|
2399
|
-
continue;
|
|
2400
|
-
}
|
|
2401
|
-
}
|
|
2402
|
-
|
|
2403
|
-
if (serverUtils) {
|
|
2404
|
-
serverUtils.log(audit.product);
|
|
2405
|
-
const progress = Math.floor((++current / allAudit.length) * 100);
|
|
2406
|
-
serverUtils.updateProgress(progress);
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
const nextOffset = offset + limit;
|
|
2411
|
-
const tEnd = new Date();
|
|
2412
|
-
const secs = secondBetweenTwoDate(timeStart, tEnd);
|
|
2413
|
-
log(`Execution time: ${secs} seconds`);
|
|
2414
|
-
|
|
2415
|
-
return {
|
|
2416
|
-
offset: nextOffset,
|
|
2417
|
-
limit,
|
|
2418
|
-
completed: limit === -1 || count >= total,
|
|
2419
|
-
s3FilePath,
|
|
2420
|
-
total,
|
|
2421
|
-
processedEntries:
|
|
2422
|
-
productEntries.length + familyEntries.length + subFamilyEntries.length,
|
|
2423
|
-
};
|
|
2424
|
-
} else {
|
|
2425
|
-
log(`Execution completed`);
|
|
2426
|
-
if (serverUtils) {
|
|
2427
|
-
serverUtils.log(`Execution completed`);
|
|
2428
|
-
serverUtils.updateProgress(100);
|
|
2429
|
-
}
|
|
2430
|
-
}
|
|
2431
|
-
const tEnd = new Date();
|
|
2432
|
-
const secs = secondBetweenTwoDate(timeStart, tEnd);
|
|
2433
|
-
log(`Request time: ${secs} seconds`);
|
|
2434
|
-
|
|
2435
|
-
return {
|
|
2436
|
-
offset: offset,
|
|
2437
|
-
limit: limit,
|
|
2438
|
-
completed: true,
|
|
2439
|
-
s3FilePath,
|
|
2440
|
-
processedEntries: 0,
|
|
2441
|
-
};
|
|
2442
|
-
};
|
|
2443
|
-
|
|
2444
|
-
export const importProductByCode = async (
|
|
2445
|
-
code: string,
|
|
2446
|
-
catalog: AvailableCatalogs
|
|
2447
|
-
) => {
|
|
2448
|
-
const timeStart = new Date();
|
|
2449
|
-
log(`importProductByCode - code: ${code} catalog: ${catalog}`, "INFO");
|
|
2450
|
-
const productDetails = await getProductDetails(code);
|
|
2451
|
-
|
|
2452
|
-
if (productDetails) {
|
|
2453
|
-
await importProduct(productDetails, catalog);
|
|
2454
|
-
}
|
|
2455
|
-
|
|
2456
|
-
const tEnd = new Date();
|
|
2457
|
-
const secs = secondBetweenTwoDate(timeStart, tEnd);
|
|
2458
|
-
log(`Request time: ${secs} seconds`);
|
|
2459
|
-
};
|
|
2460
|
-
|
|
2461
|
-
/**
|
|
2462
|
-
* Generate Tech Spec PDF by topicProducId
|
|
2463
|
-
*
|
|
2464
|
-
* @param topicProductId
|
|
2465
|
-
* @returns
|
|
2466
|
-
*/
|
|
2467
|
-
export const generateTechSpecPdf = async (
|
|
2468
|
-
topicProductId: string,
|
|
2469
|
-
country: string = "global",
|
|
2470
|
-
locale: string = "en"
|
|
2471
|
-
) => {
|
|
2472
|
-
log(`generateTechSpecPdf - topicProductId: ${topicProductId}`);
|
|
2473
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
2474
|
-
let topicProduct = await getEntryByID(
|
|
2475
|
-
topicProductId,
|
|
2476
|
-
"topicProduct",
|
|
2477
|
-
"",
|
|
2478
|
-
locale
|
|
2479
|
-
);
|
|
2480
|
-
if (!topicProduct) {
|
|
2481
|
-
throw new Error(`topicProduct with id ${topicProductId} not found`);
|
|
2482
|
-
} else if (topicProduct.isArchived()) {
|
|
2483
|
-
throw new Error(`topicProduct with id ${topicProductId} is archived`);
|
|
2484
|
-
}
|
|
2485
|
-
if (serverUtils) {
|
|
2486
|
-
serverUtils.updateProgress(10);
|
|
2487
|
-
}
|
|
2488
|
-
|
|
2489
|
-
const topicProductPageId = getProductPageIdByCode(topicProduct.sys.id);
|
|
2490
|
-
const topicProductPage = await getEntryByID(
|
|
2491
|
-
topicProductPageId,
|
|
2492
|
-
"page",
|
|
2493
|
-
"",
|
|
2494
|
-
locale
|
|
2495
|
-
);
|
|
2496
|
-
if (!topicProductPage) {
|
|
2497
|
-
throw new Error(`topicProductPage with id ${topicProductPageId} not found`);
|
|
2498
|
-
} else if (topicProductPage.isArchived()) {
|
|
2499
|
-
throw new Error(
|
|
2500
|
-
`topicProductPage with id ${topicProductPageId} is archived`
|
|
2501
|
-
);
|
|
2502
|
-
}
|
|
2503
|
-
|
|
2504
|
-
if (serverUtils) {
|
|
2505
|
-
serverUtils.updateProgress(20);
|
|
2506
|
-
}
|
|
2507
|
-
|
|
2508
|
-
const topicCatalogIds = topicProduct?.fields?.catalogs?.[
|
|
2509
|
-
defaultEnvironmentLocaleCode
|
|
2510
|
-
]?.map((catalog: any) => catalog.sys.id);
|
|
2511
|
-
const pageSlug =
|
|
2512
|
-
topicProductPage?.fields?.slug?.[locale] ??
|
|
2513
|
-
topicProductPage?.fields?.slug?.[defaultEnvironmentLocaleCode];
|
|
2514
|
-
const version = topicProduct?.sys?.version;
|
|
2515
|
-
const fileName =
|
|
2516
|
-
(pageSlug.length >= 170
|
|
2517
|
-
? `tech-spec-${topicProductId}`
|
|
2518
|
-
: `tech-spec-${pageSlug}`) + `_${country}-${locale}`; // 57 caratteri è il resto dell'url di S3
|
|
2519
|
-
let baseUrl = process.env.FPI_TECH_SPEC_BASE_URL ?? "";
|
|
2520
|
-
if (!baseUrl) {
|
|
2521
|
-
log(`FPI_TECH_SPEC_BASE_URL process env not found`, "ERROR");
|
|
2522
|
-
}
|
|
2523
|
-
baseUrl = baseUrl.replace(/\/?(\?|#|$)/, "/$1");
|
|
2524
|
-
let footerBaseUrl =
|
|
2525
|
-
process.env.FPI_TECH_SPEC_FOOTER_BASE_URL ??
|
|
2526
|
-
process.env.FPI_TECH_SPEC_BASE_URL ??
|
|
2527
|
-
"";
|
|
2528
|
-
if (!footerBaseUrl) {
|
|
2529
|
-
log(`FPI_TECH_SPEC_FOOTER_BASE_URL process env not found`, "ERROR");
|
|
2530
|
-
}
|
|
2531
|
-
footerBaseUrl = footerBaseUrl.replace(/\/?(\?|#|$)/, "/$1");
|
|
2532
|
-
|
|
2533
|
-
const layoutUrl = `${baseUrl}${locale}/${country}/tech-spec/${pageSlug}/v-${version}/`;
|
|
2534
|
-
const pdpSiteUrl =
|
|
2535
|
-
`${footerBaseUrl}${locale}/${country}/product/${pageSlug}`.replace(
|
|
2536
|
-
/\/?(\?|#|$)/,
|
|
2537
|
-
"/$1"
|
|
2538
|
-
);
|
|
2539
|
-
log(`pdpSiteUrl: ${pdpSiteUrl}`);
|
|
2540
|
-
const contents = {
|
|
2541
|
-
// header: {
|
|
2542
|
-
// right: "Technical Specifications",
|
|
2543
|
-
// },
|
|
2544
|
-
footer: {
|
|
2545
|
-
topLeft: `<a style="text-decoration: none; color:#000" href="${pdpSiteUrl}">${pdpSiteUrl}</a>`,
|
|
2546
|
-
topRight: topicProductId,
|
|
2547
|
-
bottomLeft: ``,
|
|
2548
|
-
bottomRight: ``,
|
|
2549
|
-
mail: topicCatalogIds.includes("OUTDOOR")
|
|
2550
|
-
? "flos.outdoor@flos.com"
|
|
2551
|
-
: "info@flos.com",
|
|
2552
|
-
},
|
|
2553
|
-
};
|
|
2554
|
-
|
|
2555
|
-
if (serverUtils) {
|
|
2556
|
-
serverUtils.updateProgress(35);
|
|
2557
|
-
}
|
|
2558
|
-
|
|
2559
|
-
const s3Url = await generatePDFByUrl(layoutUrl, fileName, contents);
|
|
2560
|
-
if (s3Url) {
|
|
2561
|
-
if (serverUtils) {
|
|
2562
|
-
serverUtils.log("PDF saved to S3!");
|
|
2563
|
-
serverUtils.log(`Update techSpec field...`);
|
|
2564
|
-
serverUtils.updateProgress(75);
|
|
2565
|
-
}
|
|
2566
|
-
|
|
2567
|
-
log(`Update techSpec field...`);
|
|
2568
|
-
topicProduct.fields = await addFieldValue(
|
|
2569
|
-
topicProduct,
|
|
2570
|
-
"techSpec",
|
|
2571
|
-
s3Url,
|
|
2572
|
-
false,
|
|
2573
|
-
locale
|
|
2574
|
-
);
|
|
2575
|
-
|
|
2576
|
-
topicProduct = await topicProduct.update();
|
|
2577
|
-
if (topicProduct.isPublished()) {
|
|
2578
|
-
try {
|
|
2579
|
-
topicProduct = await topicProduct.publish();
|
|
2580
|
-
} catch (err: any) {
|
|
2581
|
-
log(`Cannot publish entry.`);
|
|
2582
|
-
log(err);
|
|
2583
|
-
}
|
|
2584
|
-
}
|
|
2585
|
-
|
|
2586
|
-
if (serverUtils) {
|
|
2587
|
-
serverUtils.log("Updated!");
|
|
2588
|
-
serverUtils.updateProgress(100);
|
|
2589
|
-
}
|
|
2590
|
-
|
|
2591
|
-
log(`${topicProductId} techSpec field updated!`);
|
|
2592
|
-
return s3Url;
|
|
2593
|
-
} else {
|
|
2594
|
-
throw new Error(
|
|
2595
|
-
`TechSpec PDF generation failed for product: ${topicProductId}!`
|
|
2596
|
-
);
|
|
2597
|
-
}
|
|
2598
|
-
};
|
|
2599
|
-
|
|
2600
|
-
const getLightModuleAutoDescriptionByProductFields = async (
|
|
2601
|
-
productFileds: any
|
|
2602
|
-
) => {
|
|
2603
|
-
const autoDescription: any = {};
|
|
2604
|
-
const dictionaryJson = await getDictionaryJson();
|
|
2605
|
-
for (const locale of cfLocales) {
|
|
2606
|
-
if (!autoDescription?.[locale]) {
|
|
2607
|
-
autoDescription[locale] = "";
|
|
2608
|
-
}
|
|
2609
|
-
let addSeparator = false;
|
|
2610
|
-
if (productFileds?.electrical?.lampCategories) {
|
|
2611
|
-
const lampCategoriesLocalizedValues = [];
|
|
2612
|
-
for (const lampCategory of productFileds.electrical.lampCategories) {
|
|
2613
|
-
const lampCategoryLocalizedValue = await getDictionaryLocaleValue(
|
|
2614
|
-
locale,
|
|
2615
|
-
"lampCategories",
|
|
2616
|
-
lampCategory.code,
|
|
2617
|
-
"electrical",
|
|
2618
|
-
dictionaryJson
|
|
2619
|
-
);
|
|
2620
|
-
if (lampCategoryLocalizedValue) {
|
|
2621
|
-
lampCategoriesLocalizedValues.push(lampCategoryLocalizedValue);
|
|
2622
|
-
}
|
|
2623
|
-
}
|
|
2624
|
-
|
|
2625
|
-
if (lampCategoriesLocalizedValues.length) {
|
|
2626
|
-
if (addSeparator) {
|
|
2627
|
-
autoDescription[locale] += " - ";
|
|
2628
|
-
} else {
|
|
2629
|
-
addSeparator = true;
|
|
2630
|
-
}
|
|
2631
|
-
autoDescription[locale] += lampCategoriesLocalizedValues.join(", ");
|
|
2632
|
-
if (
|
|
2633
|
-
productFileds.electrical.lampCategories.find(
|
|
2634
|
-
(item: any) => item.code === "LAMPCAT4"
|
|
2635
|
-
) &&
|
|
2636
|
-
productFileds?.photometric?.ledTypes?.length
|
|
2637
|
-
) {
|
|
2638
|
-
const ledTypeLocalizedValues = [];
|
|
2639
|
-
for (const ledType of productFileds?.photometric?.ledTypes) {
|
|
2640
|
-
const ledTypeLocalizedValue = await getDictionaryLocaleValue(
|
|
2641
|
-
locale,
|
|
2642
|
-
"ledTypes",
|
|
2643
|
-
ledType.code,
|
|
2644
|
-
"photometric",
|
|
2645
|
-
dictionaryJson
|
|
2646
|
-
);
|
|
2647
|
-
if (ledTypeLocalizedValue) {
|
|
2648
|
-
ledTypeLocalizedValues.push(ledTypeLocalizedValue);
|
|
2649
|
-
}
|
|
2650
|
-
}
|
|
2651
|
-
|
|
2652
|
-
if (ledTypeLocalizedValues.length) {
|
|
2653
|
-
if (addSeparator) {
|
|
2654
|
-
autoDescription[locale] += " - ";
|
|
2655
|
-
} else {
|
|
2656
|
-
addSeparator = true;
|
|
2657
|
-
}
|
|
2658
|
-
autoDescription[locale] += ledTypeLocalizedValues.join(", ");
|
|
2659
|
-
}
|
|
2660
|
-
}
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
|
-
|
|
2664
|
-
if (productFileds?.electrical?.wPower) {
|
|
2665
|
-
if (addSeparator) {
|
|
2666
|
-
autoDescription[locale] += " - ";
|
|
2667
|
-
} else {
|
|
2668
|
-
addSeparator = true;
|
|
2669
|
-
}
|
|
2670
|
-
if (productFileds?.optical?.numberOfHeads >= 2) {
|
|
2671
|
-
autoDescription[locale] += `${productFileds.optical.numberOfHeads} x `;
|
|
2672
|
-
}
|
|
2673
|
-
autoDescription[locale] += `${productFileds.electrical.wPower}W`;
|
|
2674
|
-
}
|
|
2675
|
-
if (productFileds?.photometric?.realNetFlow) {
|
|
2676
|
-
if (addSeparator) {
|
|
2677
|
-
autoDescription[locale] += " - ";
|
|
2678
|
-
} else {
|
|
2679
|
-
addSeparator = true;
|
|
2680
|
-
}
|
|
2681
|
-
if (productFileds?.optical?.numberOfHeads >= 2) {
|
|
2682
|
-
autoDescription[locale] += `${productFileds.optical.numberOfHeads} x `;
|
|
2683
|
-
}
|
|
2684
|
-
autoDescription[locale] += `${productFileds.photometric.realNetFlow}lm`;
|
|
2685
|
-
}
|
|
2686
|
-
|
|
2687
|
-
if (productFileds?.photometric?.temperatureColor?.code) {
|
|
2688
|
-
const temperatireColorLocalizedValue = await getDictionaryLocaleValue(
|
|
2689
|
-
locale,
|
|
2690
|
-
"temperatureColor",
|
|
2691
|
-
productFileds.photometric.temperatureColor.code,
|
|
2692
|
-
"photometric",
|
|
2693
|
-
dictionaryJson
|
|
2694
|
-
);
|
|
2695
|
-
if (temperatireColorLocalizedValue) {
|
|
2696
|
-
if (addSeparator) {
|
|
2697
|
-
autoDescription[locale] += " - ";
|
|
2698
|
-
} else {
|
|
2699
|
-
addSeparator = true;
|
|
2700
|
-
}
|
|
2701
|
-
autoDescription[locale] += temperatireColorLocalizedValue + "K";
|
|
2702
|
-
}
|
|
2703
|
-
}
|
|
2704
|
-
|
|
2705
|
-
if (productFileds?.photometric?.cri?.code) {
|
|
2706
|
-
const CriLocalizedValue = await getDictionaryLocaleValue(
|
|
2707
|
-
locale,
|
|
2708
|
-
"cri",
|
|
2709
|
-
productFileds.photometric.cri.code,
|
|
2710
|
-
"photometric",
|
|
2711
|
-
dictionaryJson
|
|
2712
|
-
);
|
|
2713
|
-
if (CriLocalizedValue) {
|
|
2714
|
-
if (addSeparator) {
|
|
2715
|
-
autoDescription[locale] += " - ";
|
|
2716
|
-
} else {
|
|
2717
|
-
addSeparator = true;
|
|
2718
|
-
}
|
|
2719
|
-
autoDescription[locale] += "CRI> " + CriLocalizedValue;
|
|
2720
|
-
}
|
|
2721
|
-
}
|
|
2722
|
-
|
|
2723
|
-
if (productFileds?.photometric?.beam0_180) {
|
|
2724
|
-
if (addSeparator) {
|
|
2725
|
-
autoDescription[locale] += " - ";
|
|
2726
|
-
} else {
|
|
2727
|
-
addSeparator = true;
|
|
2728
|
-
}
|
|
2729
|
-
autoDescription[locale] += "Beam° " + productFileds.photometric.beam0_180;
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
|
|
2733
|
-
return autoDescription;
|
|
2734
|
-
};
|
|
2735
|
-
|
|
2736
|
-
const getOtherAutoDescriptionByProductFields = async (productFileds: any) => {
|
|
2737
|
-
const autoDescription: any = {};
|
|
2738
|
-
const dictionaryJson = await getDictionaryJson();
|
|
2739
|
-
for (const locale of cfLocales) {
|
|
2740
|
-
if (!autoDescription?.[locale]) {
|
|
2741
|
-
autoDescription[locale] = "";
|
|
2742
|
-
}
|
|
2743
|
-
let addSeparator = false;
|
|
2744
|
-
// Profile and others
|
|
2745
|
-
if (productFileds?.physical?.length_us && locale === "en-US") {
|
|
2746
|
-
autoDescription[locale] += "Length: " + productFileds.physical.length_us;
|
|
2747
|
-
addSeparator = true;
|
|
2748
|
-
} else if (productFileds?.physical?.length && locale !== "en-US") {
|
|
2749
|
-
autoDescription[locale] += "Length: " + productFileds.physical.length;
|
|
2750
|
-
addSeparator = true;
|
|
2751
|
-
}
|
|
2752
|
-
|
|
2753
|
-
if (productFileds?.mountings) {
|
|
2754
|
-
const mountingsLocalizedValues = [];
|
|
2755
|
-
for (const mounting of productFileds.mountings) {
|
|
2756
|
-
const mountingLocalizedValue = await getDictionaryLocaleValue(
|
|
2757
|
-
locale,
|
|
2758
|
-
"mountings",
|
|
2759
|
-
mounting.code,
|
|
2760
|
-
"",
|
|
2761
|
-
dictionaryJson
|
|
2762
|
-
);
|
|
2763
|
-
if (mountingLocalizedValue) {
|
|
2764
|
-
mountingsLocalizedValues.push(mountingLocalizedValue);
|
|
2765
|
-
}
|
|
2766
|
-
}
|
|
2767
|
-
|
|
2768
|
-
if (addSeparator) {
|
|
2769
|
-
autoDescription[locale] += " - ";
|
|
2770
|
-
} else {
|
|
2771
|
-
addSeparator = true;
|
|
2772
|
-
}
|
|
2773
|
-
autoDescription[locale] += mountingsLocalizedValues.join(", ");
|
|
2774
|
-
}
|
|
2775
|
-
}
|
|
2776
|
-
|
|
2777
|
-
return autoDescription;
|
|
2778
|
-
};
|
|
2779
|
-
|
|
2780
|
-
/**
|
|
2781
|
-
* Get topicProduct autoDescription
|
|
2782
|
-
*
|
|
2783
|
-
* @param topicProduct
|
|
2784
|
-
* @returns
|
|
2785
|
-
*/
|
|
2786
|
-
const getTopicProductAutodescription = async (
|
|
2787
|
-
topicProductFields: KeyValueMap
|
|
2788
|
-
) => {
|
|
2789
|
-
const defaultEnvironmentLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
2790
|
-
const productLineCode =
|
|
2791
|
-
topicProductFields?.productLine?.[defaultEnvironmentLocaleCode]?.sys?.id;
|
|
2792
|
-
const productFileds =
|
|
2793
|
-
topicProductFields?.productFields?.[defaultEnvironmentLocaleCode];
|
|
2794
|
-
|
|
2795
|
-
let autoDescription: any = {};
|
|
2796
|
-
switch (productLineCode) {
|
|
2797
|
-
case "PLINE6": // Soft Plate
|
|
2798
|
-
case "PLINE5": // Light Bulb
|
|
2799
|
-
case "PLINE3": // Driver
|
|
2800
|
-
case "PLINE2": // Accessory
|
|
2801
|
-
// post_content
|
|
2802
|
-
autoDescription = topicProductFields?.description;
|
|
2803
|
-
break;
|
|
2804
|
-
case "PLINE1": // Light Module
|
|
2805
|
-
autoDescription = await getLightModuleAutoDescriptionByProductFields(
|
|
2806
|
-
productFileds
|
|
2807
|
-
);
|
|
2808
|
-
|
|
2809
|
-
break;
|
|
2810
|
-
default:
|
|
2811
|
-
autoDescription = await getOtherAutoDescriptionByProductFields(
|
|
2812
|
-
productFileds
|
|
2813
|
-
);
|
|
2814
|
-
|
|
2815
|
-
break;
|
|
2816
|
-
}
|
|
2817
|
-
|
|
2818
|
-
return autoDescription;
|
|
2819
|
-
};
|
|
2820
|
-
|
|
2821
|
-
const setProductAutodescription = async (topicProduct: Entry) => {
|
|
2822
|
-
log(`Set audtodescription of the topic ${topicProduct.sys.id}`);
|
|
2823
|
-
const autoDescription = await getTopicProductAutodescription(
|
|
2824
|
-
topicProduct.fields
|
|
2825
|
-
);
|
|
2826
|
-
topicProduct.fields.autoDescription = autoDescription;
|
|
2827
|
-
if (!topicProduct.isArchived()) {
|
|
2828
|
-
topicProduct = await topicProduct.update();
|
|
2829
|
-
if (topicProduct.isPublished()) {
|
|
2830
|
-
topicProduct = await topicProduct.publish();
|
|
2831
|
-
}
|
|
2832
|
-
} else {
|
|
2833
|
-
log(
|
|
2834
|
-
`Product ${topicProduct.sys.id} is archived, it is not possible to update the autodescription`,
|
|
2835
|
-
"WARN"
|
|
2836
|
-
);
|
|
2837
|
-
}
|
|
2838
|
-
|
|
2839
|
-
return autoDescription;
|
|
2840
|
-
};
|
|
2841
|
-
|
|
2842
|
-
export const setProductsAutodescription = async (
|
|
2843
|
-
catalog: AvailableCatalogs,
|
|
2844
|
-
offset: number = 0,
|
|
2845
|
-
limit: number = 100
|
|
2846
|
-
) => {
|
|
2847
|
-
log(
|
|
2848
|
-
`setProductAutodescription - catalog: ${catalog}, offset: ${offset}, limit: ${limit}`,
|
|
2849
|
-
"INFO"
|
|
2850
|
-
);
|
|
2851
|
-
const env = await getEnvironment();
|
|
2852
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
2853
|
-
|
|
2854
|
-
const { items, total } = await env.getEntries({
|
|
2855
|
-
content_type: "topicProduct",
|
|
2856
|
-
"fields.catalogs.sys.id": catalog,
|
|
2857
|
-
limit,
|
|
2858
|
-
skip: offset,
|
|
2859
|
-
locale: defEnvLocaleCode,
|
|
2860
|
-
include: 0,
|
|
2861
|
-
select: "sys,fields",
|
|
2862
|
-
"sys.archivedAt[exists]": false,
|
|
2863
|
-
});
|
|
2864
|
-
|
|
2865
|
-
let count = 0;
|
|
2866
|
-
for (const item of items) {
|
|
2867
|
-
setProductAutodescription(item);
|
|
2868
|
-
|
|
2869
|
-
if (++count % 5 === 0) {
|
|
2870
|
-
log(
|
|
2871
|
-
`current: ${count} of ${limit} - global: ${offset + count} of ${total}`
|
|
2872
|
-
);
|
|
2873
|
-
await sleep(3000, true);
|
|
2874
|
-
}
|
|
2875
|
-
}
|
|
2876
|
-
|
|
2877
|
-
return {
|
|
2878
|
-
catalog,
|
|
2879
|
-
offset: Number(offset) + Number(limit),
|
|
2880
|
-
limit: Number(limit),
|
|
2881
|
-
completed: Number(offset) + Number(limit) >= total,
|
|
2882
|
-
total,
|
|
2883
|
-
};
|
|
2884
|
-
};
|
|
2885
|
-
|
|
2886
|
-
export const setProductAutodescriptionByTopicId = async (
|
|
2887
|
-
topicProductId: string
|
|
2888
|
-
) => {
|
|
2889
|
-
const topicProduct = await getEntryByID(topicProductId, "topicProduct");
|
|
2890
|
-
|
|
2891
|
-
return await setProductAutodescription(topicProduct);
|
|
2892
|
-
};
|
|
2893
|
-
|
|
2894
|
-
export const getProductAutodescription = async (topicProductId: string) => {
|
|
2895
|
-
const topicProduct = await getEntryByID(topicProductId, "topicProduct");
|
|
2896
|
-
|
|
2897
|
-
return await getTopicProductAutodescription(topicProduct.fields);
|
|
2898
|
-
};
|
|
2899
|
-
|
|
2900
|
-
export const removeProductFromColorVariantsByProductLine = async (
|
|
2901
|
-
productLineCode: string
|
|
2902
|
-
) => {
|
|
2903
|
-
log(`Serch topicProduct with productLine ${productLineCode}`);
|
|
2904
|
-
const topicProducts = await getAllEntries(
|
|
2905
|
-
"topicProduct",
|
|
2906
|
-
"sys",
|
|
2907
|
-
"fields.productLine.sys.id",
|
|
2908
|
-
productLineCode
|
|
2909
|
-
);
|
|
2910
|
-
const topicProductCodes = topicProducts.map(
|
|
2911
|
-
(topicProduct) => topicProduct.sys.id
|
|
2912
|
-
);
|
|
2913
|
-
|
|
2914
|
-
log(`Founded ${topicProductCodes.length} topicProducts`);
|
|
2915
|
-
|
|
2916
|
-
let count = 0;
|
|
2917
|
-
for (const topicProductCode of topicProductCodes) {
|
|
2918
|
-
log(`${++count} of ${topicProductCodes.length}`);
|
|
2919
|
-
log(
|
|
2920
|
-
`Serch topicProductColourVariants of the ${topicProductCode} topicProduct`
|
|
2921
|
-
);
|
|
2922
|
-
const topicProductColourVariants = await getAllEntries(
|
|
2923
|
-
"topicProductColourVariants",
|
|
2924
|
-
"sys,fields",
|
|
2925
|
-
"fields.products.sys.id[in]",
|
|
2926
|
-
topicProductCode
|
|
2927
|
-
);
|
|
2928
|
-
|
|
2929
|
-
if (topicProductColourVariants.length) {
|
|
2930
|
-
const defaultEnvironmentLocaleCode =
|
|
2931
|
-
await getEnvironmentDefaultLocaleCode();
|
|
2932
|
-
log(
|
|
2933
|
-
`${topicProductColourVariants.length} topicProductColourVariants founded`
|
|
2934
|
-
);
|
|
2935
|
-
for (let topicProductColourVariant of topicProductColourVariants) {
|
|
2936
|
-
log(
|
|
2937
|
-
`Remove the ${topicProductCode} topicProduct from the ${topicProductColourVariant.sys.id} topicProductColourVariants`
|
|
2938
|
-
);
|
|
2939
|
-
|
|
2940
|
-
topicProductColourVariant.fields.products[
|
|
2941
|
-
defaultEnvironmentLocaleCode
|
|
2942
|
-
] = topicProductColourVariant.fields.products[
|
|
2943
|
-
defaultEnvironmentLocaleCode
|
|
2944
|
-
].filter((item: CfSys) => item.sys.id !== topicProductCode);
|
|
2945
|
-
|
|
2946
|
-
if (
|
|
2947
|
-
topicProductColourVariant.fields.products[
|
|
2948
|
-
defaultEnvironmentLocaleCode
|
|
2949
|
-
].length
|
|
2950
|
-
) {
|
|
2951
|
-
log(
|
|
2952
|
-
`Update the ${topicProductColourVariant.sys.id} topicProductColourVariants`
|
|
2953
|
-
);
|
|
2954
|
-
topicProductColourVariant = await topicProductColourVariant.update();
|
|
2955
|
-
if (topicProductColourVariant.isPublished()) {
|
|
2956
|
-
topicProductColourVariant =
|
|
2957
|
-
await topicProductColourVariant.publish();
|
|
2958
|
-
}
|
|
2959
|
-
} else {
|
|
2960
|
-
log(
|
|
2961
|
-
`Remove the ${topicProductColourVariant.sys.id} topicProductColourVariants because don't have more topicProducts`
|
|
2962
|
-
);
|
|
2963
|
-
if (topicProductColourVariant.isPublished()) {
|
|
2964
|
-
topicProductColourVariant =
|
|
2965
|
-
await topicProductColourVariant.unpublish();
|
|
2966
|
-
}
|
|
2967
|
-
await topicProductColourVariant.delete();
|
|
2968
|
-
}
|
|
2969
|
-
}
|
|
2970
|
-
} else {
|
|
2971
|
-
log(
|
|
2972
|
-
`No topicProductColourVariants found for the ${topicProductCode} topicProduct`
|
|
2973
|
-
);
|
|
2974
|
-
}
|
|
2975
|
-
}
|
|
2976
|
-
};
|
|
2977
|
-
|
|
2978
|
-
/**
|
|
2979
|
-
* Remove a specific model from all product model relations
|
|
2980
|
-
* NOTE: require the reindex of all product updated
|
|
2981
|
-
*
|
|
2982
|
-
* @param modelCode
|
|
2983
|
-
*/
|
|
2984
|
-
export const removeAllProductModelProductRelations = async (
|
|
2985
|
-
modelCode: string
|
|
2986
|
-
) => {
|
|
2987
|
-
log(`removeAllProductModelProductRelations - modelCode: ${modelCode}`);
|
|
2988
|
-
const env = await getEnvironment();
|
|
2989
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
2990
|
-
const { items } = await env.getEntries({
|
|
2991
|
-
content_type: "topicProduct",
|
|
2992
|
-
locale: defEnvLocaleCode,
|
|
2993
|
-
include: 2,
|
|
2994
|
-
links_to_entry: modelCode,
|
|
2995
|
-
limit: 1000,
|
|
2996
|
-
});
|
|
2997
|
-
|
|
2998
|
-
log(`Founded ${items.length} products`);
|
|
2999
|
-
|
|
3000
|
-
const allProductModelFields = [
|
|
3001
|
-
"modelsArchitectural",
|
|
3002
|
-
"modelsOutdoor",
|
|
3003
|
-
"modelsDecorative",
|
|
3004
|
-
];
|
|
3005
|
-
for (let item of items) {
|
|
3006
|
-
for (const modelFieldKey of allProductModelFields) {
|
|
3007
|
-
if (
|
|
3008
|
-
item.fields?.[modelFieldKey]?.[defEnvLocaleCode].find(
|
|
3009
|
-
(model: CfSys) => model.sys.id === modelCode
|
|
3010
|
-
)
|
|
3011
|
-
) {
|
|
3012
|
-
item.fields[modelFieldKey][defEnvLocaleCode] = item.fields[
|
|
3013
|
-
modelFieldKey
|
|
3014
|
-
][defEnvLocaleCode].filter(
|
|
3015
|
-
(model: CfSys) => model.sys.id !== modelCode
|
|
3016
|
-
);
|
|
3017
|
-
}
|
|
3018
|
-
}
|
|
3019
|
-
|
|
3020
|
-
const productCode = item.fields.code[defEnvLocaleCode];
|
|
3021
|
-
if (item.isArchived()) {
|
|
3022
|
-
log(`Product with code ${productCode} is archived`, "WARN");
|
|
3023
|
-
} else {
|
|
3024
|
-
item = await item.update();
|
|
3025
|
-
log(`Updated product ${productCode}`);
|
|
3026
|
-
// log(`"${productCode}",`);
|
|
3027
|
-
}
|
|
3028
|
-
if (item.isPublished()) {
|
|
3029
|
-
item = await item.publish();
|
|
3030
|
-
}
|
|
3031
|
-
}
|
|
3032
|
-
};
|
|
3033
|
-
|
|
3034
|
-
/**
|
|
3035
|
-
*
|
|
3036
|
-
* Reimport audit products
|
|
3037
|
-
*
|
|
3038
|
-
* @param {string} lastModified The last modified data. Format: 20200426T07:50:00 - yearmonthdayThour:minute:second
|
|
3039
|
-
* @param {string} catalog
|
|
3040
|
-
*/
|
|
3041
|
-
export const reimportAuditProducts = async (
|
|
3042
|
-
lastModified: string,
|
|
3043
|
-
catalog: AvailableCatalogs,
|
|
3044
|
-
offset: number = 0,
|
|
3045
|
-
limit: number = 150,
|
|
3046
|
-
s3FilePath: string = ""
|
|
3047
|
-
) => {
|
|
3048
|
-
// if not exists save data to s3
|
|
3049
|
-
if (!s3FilePath) {
|
|
3050
|
-
const allAudit = await getAudit(lastModified);
|
|
3051
|
-
const allFilteredAudit = allAudit.filter((audit) =>
|
|
3052
|
-
["PRODUCT_WEBOFF", "PRODUCT_UNPUBLISH"].includes(audit.what)
|
|
3053
|
-
);
|
|
3054
|
-
if (!allFilteredAudit) {
|
|
3055
|
-
log(`No audits were found to process for the date ${lastModified}`);
|
|
3056
|
-
return {
|
|
3057
|
-
offset,
|
|
3058
|
-
limit,
|
|
3059
|
-
completed: true,
|
|
3060
|
-
s3FilePath: "",
|
|
3061
|
-
total: 0,
|
|
3062
|
-
processedEntries: 0,
|
|
3063
|
-
};
|
|
3064
|
-
}
|
|
3065
|
-
|
|
3066
|
-
const filename = `${lastModified}-all-audit-web-off.json`;
|
|
3067
|
-
const path = `audit/reimport`;
|
|
3068
|
-
await saveJsonToS3(allFilteredAudit, filename, path);
|
|
3069
|
-
const s3Path = `${path}/${filename}`;
|
|
3070
|
-
|
|
3071
|
-
return {
|
|
3072
|
-
offset: Number(offset),
|
|
3073
|
-
limit: Number(limit),
|
|
3074
|
-
completed: false,
|
|
3075
|
-
s3FilePath: s3Path,
|
|
3076
|
-
total: allAudit.length,
|
|
3077
|
-
processedEntries: 0,
|
|
3078
|
-
};
|
|
3079
|
-
}
|
|
3080
|
-
|
|
3081
|
-
// get data from s3
|
|
3082
|
-
log(`Get audit details from ${s3FilePath}`);
|
|
3083
|
-
let allAudit: Audit[] = await getFileFromS3(s3FilePath);
|
|
3084
|
-
const total: number = allAudit.length;
|
|
3085
|
-
allAudit = allAudit.slice(offset, offset + limit);
|
|
3086
|
-
log(`Founded ${allAudit.length} items`);
|
|
3087
|
-
|
|
3088
|
-
if (allAudit) {
|
|
3089
|
-
const defaultEnvironmentLocaleCode =
|
|
3090
|
-
await getEnvironmentDefaultLocaleCode();
|
|
3091
|
-
|
|
3092
|
-
const productCodes = allAudit.map((audit) => audit.product);
|
|
3093
|
-
const otherFilters = [];
|
|
3094
|
-
if (catalog) {
|
|
3095
|
-
otherFilters.push({ key: "fields.catalogs.sys.id[in]", value: catalog });
|
|
3096
|
-
}
|
|
3097
|
-
log(`Get ${productCodes.length} product entry from Contentful`);
|
|
3098
|
-
const entries = await getAllEntriesByCodes(
|
|
3099
|
-
productCodes,
|
|
3100
|
-
"topicProduct",
|
|
3101
|
-
"sys,fields",
|
|
3102
|
-
"fields.code",
|
|
3103
|
-
otherFilters
|
|
3104
|
-
);
|
|
3105
|
-
log(`Founded ${entries.length} topicProduct`);
|
|
3106
|
-
|
|
3107
|
-
if (!entries.length) {
|
|
3108
|
-
log(
|
|
3109
|
-
`No products found between offset: ${offset} and limit: ${limit}. Total: ${total}`
|
|
3110
|
-
);
|
|
3111
|
-
const nextOffset = offset + limit;
|
|
3112
|
-
const completed = limit === -1 || offset >= total;
|
|
3113
|
-
if (completed) {
|
|
3114
|
-
log(`Audit completed`);
|
|
3115
|
-
}
|
|
3116
|
-
|
|
3117
|
-
return {
|
|
3118
|
-
offset: nextOffset,
|
|
3119
|
-
limit: limit,
|
|
3120
|
-
completed,
|
|
3121
|
-
s3FilePath,
|
|
3122
|
-
total,
|
|
3123
|
-
processedEntries: 0,
|
|
3124
|
-
};
|
|
3125
|
-
}
|
|
3126
|
-
|
|
3127
|
-
const pageCodes = entries.map((entry: Entry) =>
|
|
3128
|
-
getProductPageIdByCode(entry.fields.code[defaultEnvironmentLocaleCode])
|
|
3129
|
-
);
|
|
3130
|
-
|
|
3131
|
-
log(`Get ${pageCodes.length} product page entry from Contentful`);
|
|
3132
|
-
const entriesPage = await getAllEntriesByCodes(
|
|
3133
|
-
pageCodes,
|
|
3134
|
-
"page",
|
|
3135
|
-
"sys,fields",
|
|
3136
|
-
"sys.id"
|
|
3137
|
-
);
|
|
3138
|
-
log(`Founded ${entriesPage.length} topicProduct pages`);
|
|
3139
|
-
let count: number = offset;
|
|
3140
|
-
for (const audit of allAudit) {
|
|
3141
|
-
log(`${++count} of ${total}`);
|
|
3142
|
-
log(`I process the product ${audit.product} with status ${audit.what}`);
|
|
3143
|
-
|
|
3144
|
-
log(`Search product entry with id ${audit.product}...`);
|
|
3145
|
-
const productEntry = entries.find(
|
|
3146
|
-
(currentEntry) =>
|
|
3147
|
-
currentEntry?.fields?.code?.[defaultEnvironmentLocaleCode] ===
|
|
3148
|
-
audit.product
|
|
3149
|
-
);
|
|
3150
|
-
|
|
3151
|
-
if (!productEntry) {
|
|
3152
|
-
let logMessage = "";
|
|
3153
|
-
if (catalog) {
|
|
3154
|
-
logMessage = `The ${audit.product} product was not found in the CMS with catalog ${catalog}`;
|
|
3155
|
-
} else {
|
|
3156
|
-
logMessage = `The ${audit.product} product was not found in the CMS`;
|
|
3157
|
-
}
|
|
3158
|
-
log(logMessage, "WARN");
|
|
3159
|
-
|
|
3160
|
-
continue;
|
|
3161
|
-
}
|
|
3162
|
-
|
|
3163
|
-
log(`Founded product with id ${productEntry.sys.id}`);
|
|
3164
|
-
|
|
3165
|
-
log(`Get product catalogs...`);
|
|
3166
|
-
const productCatalogs: AvailableCatalogs[] =
|
|
3167
|
-
productEntry?.fields?.catalogs?.[defaultEnvironmentLocaleCode].map(
|
|
3168
|
-
(entryCatalog: FieldItem) => {
|
|
3169
|
-
return entryCatalog.sys.id;
|
|
3170
|
-
}
|
|
3171
|
-
);
|
|
3172
|
-
|
|
3173
|
-
if (catalog && !productCatalogs.includes(catalog)) {
|
|
3174
|
-
log(
|
|
3175
|
-
`Product ${audit.product} does not belong to the ${catalog} catalog`
|
|
3176
|
-
);
|
|
3177
|
-
} else {
|
|
3178
|
-
log(`Import product...`);
|
|
3179
|
-
await importProductByCode(audit.product, catalog);
|
|
3180
|
-
await reindexProduct(audit.product, true);
|
|
3181
|
-
}
|
|
3182
|
-
}
|
|
3183
|
-
|
|
3184
|
-
const nextOffset = offset + limit;
|
|
3185
|
-
|
|
3186
|
-
return {
|
|
3187
|
-
offset: nextOffset,
|
|
3188
|
-
limit,
|
|
3189
|
-
completed: limit === -1 || count >= total,
|
|
3190
|
-
s3FilePath,
|
|
3191
|
-
total,
|
|
3192
|
-
processedEntries: entries.length,
|
|
3193
|
-
};
|
|
3194
|
-
} else {
|
|
3195
|
-
log(`Execution completed`);
|
|
3196
|
-
}
|
|
3197
|
-
|
|
3198
|
-
return {
|
|
3199
|
-
offset: offset,
|
|
3200
|
-
limit: limit,
|
|
3201
|
-
completed: true,
|
|
3202
|
-
s3FilePath,
|
|
3203
|
-
processedEntries: 0,
|
|
3204
|
-
};
|
|
3205
|
-
};
|
|
3206
|
-
|
|
3207
|
-
export const populateDestinations = async (offset: number, limit: number) => {
|
|
3208
|
-
const env = await getEnvironment();
|
|
3209
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
3210
|
-
|
|
3211
|
-
const opts = {
|
|
3212
|
-
content_type: "topicProduct",
|
|
3213
|
-
skip: offset,
|
|
3214
|
-
limit,
|
|
3215
|
-
locale: defEnvLocaleCode,
|
|
3216
|
-
// select: 'sys.id,fields',
|
|
3217
|
-
"sys.archivedAt[exists]": false,
|
|
3218
|
-
// "fields.destinations[exists]": false,
|
|
3219
|
-
};
|
|
3220
|
-
|
|
3221
|
-
const { items, total } = await env.getEntries(opts);
|
|
3222
|
-
|
|
3223
|
-
let count: number = offset;
|
|
3224
|
-
for (let productEntry of items) {
|
|
3225
|
-
log(`${++count} of ${total}`);
|
|
3226
|
-
log(`Product: ${productEntry.sys.id}`);
|
|
3227
|
-
const destinations =
|
|
3228
|
-
productEntry.fields.productFields[defEnvLocaleCode]?.destinations?.map(
|
|
3229
|
-
(destination: any) => destination.code
|
|
3230
|
-
) || [];
|
|
3231
|
-
|
|
3232
|
-
if (destinations.length) {
|
|
3233
|
-
log(`Set destinations: ${destinations.join(", ")}`);
|
|
3234
|
-
productEntry.fields = await addFieldValue(
|
|
3235
|
-
productEntry,
|
|
3236
|
-
"destinations",
|
|
3237
|
-
destinations
|
|
3238
|
-
);
|
|
3239
|
-
productEntry = await productEntry.update();
|
|
3240
|
-
} else {
|
|
3241
|
-
log(`No destinations found.`, "WARN");
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3244
|
-
if (productEntry.isPublished()) {
|
|
3245
|
-
try {
|
|
3246
|
-
productEntry = await productEntry.publish();
|
|
3247
|
-
} catch (err: any) {
|
|
3248
|
-
log(`Cannot publish entry.`);
|
|
3249
|
-
log(err);
|
|
3250
|
-
}
|
|
3251
|
-
}
|
|
3252
|
-
}
|
|
3253
|
-
|
|
3254
|
-
return { completed: !total || total === count + offset, offset, limit };
|
|
3255
|
-
};
|
|
3256
|
-
|
|
3257
|
-
export const purgeProductThumbCacheByProductCodes = async (
|
|
3258
|
-
productCodes: string[]
|
|
3259
|
-
) => {
|
|
3260
|
-
const defEnvLocaleCode = await getEnvironmentDefaultLocaleCode();
|
|
3261
|
-
|
|
3262
|
-
const productEntries = await getAllEntriesByCodes(
|
|
3263
|
-
productCodes,
|
|
3264
|
-
"topicProduct",
|
|
3265
|
-
"sys,fields.thumbnailImgix"
|
|
3266
|
-
);
|
|
3267
|
-
|
|
3268
|
-
let count: number = 0;
|
|
3269
|
-
const total: number = productEntries.length;
|
|
3270
|
-
for (const productEntry of productEntries) {
|
|
3271
|
-
log(`${++count} of ${total}`);
|
|
3272
|
-
const thumbEntryId =
|
|
3273
|
-
productEntry.fields?.thumbnailImgix?.[defEnvLocaleCode]?.sys?.id;
|
|
3274
|
-
|
|
3275
|
-
if (thumbEntryId) {
|
|
3276
|
-
let wrapperImgix = await getEntryByID(
|
|
3277
|
-
thumbEntryId,
|
|
3278
|
-
"wrapperImgix",
|
|
3279
|
-
"sys,fields"
|
|
3280
|
-
);
|
|
3281
|
-
if (wrapperImgix) {
|
|
3282
|
-
const imgixUrl =
|
|
3283
|
-
wrapperImgix.fields?.imgixData?.[defEnvLocaleCode]?.url;
|
|
3284
|
-
if (imgixUrl) {
|
|
3285
|
-
log(`Cleaning cache for ${imgixUrl}`);
|
|
3286
|
-
await purgeImageCacheByUrl(imgixUrl);
|
|
3287
|
-
} else {
|
|
3288
|
-
log(`No imgixUrl found in ${thumbEntryId} id`, "WARN");
|
|
3289
|
-
}
|
|
3290
|
-
} else {
|
|
3291
|
-
log(`No wrapperImgix found with ${thumbEntryId} id`, "WARN");
|
|
3292
|
-
}
|
|
3293
|
-
} else {
|
|
3294
|
-
log(`No thumbEntryId found in ${productEntry.sys.id}`, "WARN");
|
|
3295
|
-
}
|
|
3296
|
-
}
|
|
3297
|
-
};
|