@softwear/latestcollectioncore 1.0.63 → 1.0.65
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/buildPropertyMappingFn.js +12 -30
- package/dist/types.d.ts +6 -1
- package/package.json +1 -1
- package/src/buildPropertyMappingFn.ts +19 -28
- package/src/types.ts +7 -1
- package/test/applyPropertyMapping.spec.js +46 -0
|
@@ -14,7 +14,7 @@ const mappingPairs = [
|
|
|
14
14
|
{ category: 'CustomSize', from: 'sizeSupplier', to: '_customsize' },
|
|
15
15
|
{ category: 'Size', from: 'sizeSupplier', to: 'size' },
|
|
16
16
|
{ category: 'Gender', from: 'articleGroupSupplier', to: '_gender', mustMatch: true },
|
|
17
|
-
{ category: 'ERM', from: ['_gender', 'articleGroup'], to: '_erm-code', mustMatch: true },
|
|
17
|
+
{ category: 'ERM', from: ['_gender', 'articleGroup'], to: '_erm-code', mustMatch: true, defaultMappingSource: 'ermmapping' },
|
|
18
18
|
];
|
|
19
19
|
const evaluateFromExpr = function (sku, from) {
|
|
20
20
|
if (typeof from == 'string')
|
|
@@ -22,34 +22,16 @@ const evaluateFromExpr = function (sku, from) {
|
|
|
22
22
|
return from.map((field) => sku[field] || '').join('.');
|
|
23
23
|
};
|
|
24
24
|
function default_1(brands, strategy) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}, {});
|
|
34
|
-
};
|
|
35
|
-
// Helper function to convert all mapping rules to an indexed object
|
|
36
|
-
const indexFn = function (propertyMapping) {
|
|
37
|
-
if (!propertyMapping)
|
|
38
|
-
return {};
|
|
39
|
-
const maps = {};
|
|
40
|
-
index_1.MAPPING_CATEGORIES.forEach((category) => {
|
|
41
|
-
const map = indexedMapping(propertyMapping, category);
|
|
42
|
-
if (map !== undefined)
|
|
43
|
-
maps[category] = map;
|
|
25
|
+
const indexedByBrandPropertyMapping = {};
|
|
26
|
+
brands.forEach(({ id, propertyMapping }) => {
|
|
27
|
+
if (!indexedByBrandPropertyMapping[id])
|
|
28
|
+
indexedByBrandPropertyMapping[id] = {};
|
|
29
|
+
propertyMapping === null || propertyMapping === void 0 ? void 0 : propertyMapping.forEach((mapping) => {
|
|
30
|
+
if (!indexedByBrandPropertyMapping[id][mapping.category])
|
|
31
|
+
indexedByBrandPropertyMapping[id][mapping.category] = {};
|
|
32
|
+
indexedByBrandPropertyMapping[id][mapping.category][mapping.from] = mapping.to;
|
|
44
33
|
});
|
|
45
|
-
|
|
46
|
-
};
|
|
47
|
-
const indexedByBrandPropertyMapping = brands.reduce((acc, item) => {
|
|
48
|
-
if (!acc[item.id])
|
|
49
|
-
acc[item.id] = {};
|
|
50
|
-
Object.assign(acc[item.id], indexFn(item.propertyMapping));
|
|
51
|
-
return acc;
|
|
52
|
-
}, {});
|
|
34
|
+
});
|
|
53
35
|
if (strategy == 'clean')
|
|
54
36
|
return function (sku) {
|
|
55
37
|
const brand = sku.BRANDHASH || (0, index_1.hashBrand)(sku.brand);
|
|
@@ -72,7 +54,7 @@ function default_1(brands, strategy) {
|
|
|
72
54
|
mappingPairs.forEach((pair) => {
|
|
73
55
|
var _a, _b, _c, _d, _e;
|
|
74
56
|
const from = evaluateFromExpr(sku, pair.from) || '';
|
|
75
|
-
const redirectedMappingSource = (_a = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _a === void 0 ? void 0 : _a['~~'];
|
|
57
|
+
const redirectedMappingSource = ((_a = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _a === void 0 ? void 0 : _a['~~']) || pair.defaultMappingSource;
|
|
76
58
|
const redirectedMapping = redirectedMappingSource ? indexedByBrandPropertyMapping[redirectedMappingSource] : {};
|
|
77
59
|
const to = ((_b = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _b === void 0 ? void 0 : _b[from]) || ((_c = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _c === void 0 ? void 0 : _c['']) || ((_d = redirectedMapping === null || redirectedMapping === void 0 ? void 0 : redirectedMapping[pair.category]) === null || _d === void 0 ? void 0 : _d[from]) || ((_e = redirectedMapping === null || redirectedMapping === void 0 ? void 0 : redirectedMapping[pair.category]) === null || _e === void 0 ? void 0 : _e['']);
|
|
78
60
|
if (to == undefined)
|
|
@@ -88,7 +70,7 @@ function default_1(brands, strategy) {
|
|
|
88
70
|
if (sku[pair.to])
|
|
89
71
|
return; // Do not replace sku-level-user-supplied values
|
|
90
72
|
const from = evaluateFromExpr(sku, pair.from);
|
|
91
|
-
const redirectedMappingSource = (_a = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _a === void 0 ? void 0 : _a['~~'];
|
|
73
|
+
const redirectedMappingSource = ((_a = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _a === void 0 ? void 0 : _a['~~']) || pair.defaultMappingSource;
|
|
92
74
|
const redirectedMapping = redirectedMappingSource ? indexedByBrandPropertyMapping[redirectedMappingSource] : {};
|
|
93
75
|
const to = ((_b = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _b === void 0 ? void 0 : _b[from]) || ((_c = mapping === null || mapping === void 0 ? void 0 : mapping[pair.category]) === null || _c === void 0 ? void 0 : _c['']) || ((_d = redirectedMapping === null || redirectedMapping === void 0 ? void 0 : redirectedMapping[pair.category]) === null || _d === void 0 ? void 0 : _d[from]) || ((_e = redirectedMapping === null || redirectedMapping === void 0 ? void 0 : redirectedMapping[pair.category]) === null || _e === void 0 ? void 0 : _e['']);
|
|
94
76
|
if (!from && !to)
|
package/dist/types.d.ts
CHANGED
|
@@ -191,6 +191,11 @@ interface ProductI {
|
|
|
191
191
|
warehouseLocation: string;
|
|
192
192
|
year?: string;
|
|
193
193
|
}
|
|
194
|
+
interface PropertyMappingI {
|
|
195
|
+
category: string;
|
|
196
|
+
from: string;
|
|
197
|
+
to: string;
|
|
198
|
+
}
|
|
194
199
|
interface BrandSettingI {
|
|
195
200
|
id: string;
|
|
196
201
|
name: string;
|
|
@@ -211,7 +216,7 @@ interface BrandSettingI {
|
|
|
211
216
|
whiteListTenants?: string[];
|
|
212
217
|
associates?: object[];
|
|
213
218
|
authGroups?: string[];
|
|
214
|
-
propertyMapping?:
|
|
219
|
+
propertyMapping?: PropertyMappingI[];
|
|
215
220
|
fashionCloudId?: string;
|
|
216
221
|
}
|
|
217
222
|
declare enum mappingStrategyE {
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { hashBrand, SkuI,
|
|
1
|
+
import { hashBrand, SkuI, BrandSettingI, mappingStrategyE } from './index'
|
|
2
2
|
|
|
3
3
|
// The order of the following mappingPairs is significant.
|
|
4
4
|
// The ERM mapping relies on the Gender and ProductGroup mapping to have been evaluated first
|
|
@@ -13,40 +13,31 @@ const mappingPairs = [
|
|
|
13
13
|
{ category: 'CustomSize', from: 'sizeSupplier', to: '_customsize' },
|
|
14
14
|
{ category: 'Size', from: 'sizeSupplier', to: 'size' },
|
|
15
15
|
{ category: 'Gender', from: 'articleGroupSupplier', to: '_gender', mustMatch: true },
|
|
16
|
-
{ category: 'ERM', from: ['_gender', 'articleGroup'], to: '_erm-code', mustMatch: true },
|
|
16
|
+
{ category: 'ERM', from: ['_gender', 'articleGroup'], to: '_erm-code', mustMatch: true, defaultMappingSource: 'ermmapping' },
|
|
17
17
|
]
|
|
18
18
|
|
|
19
19
|
const evaluateFromExpr = function (sku: SkuI, from: string | string[]): string {
|
|
20
20
|
if (typeof from == 'string') return sku[from]
|
|
21
21
|
return from.map((field) => sku[field] || '').join('.')
|
|
22
22
|
}
|
|
23
|
-
export default function (brands: Array<BrandSettingI>, strategy: mappingStrategyE): (sku: SkuI) => SkuI {
|
|
24
|
-
// Helper function to convert all mapping rules for given category to an indexed object
|
|
25
|
-
const indexedMapping = function (propertyMapping, category) {
|
|
26
|
-
const filteredMappings = propertyMapping.filter((mapping) => mapping.category == category && mapping.from != undefined)
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
// Helper function to convert all mapping rules to an indexed object
|
|
35
|
-
const indexFn = function (propertyMapping) {
|
|
36
|
-
if (!propertyMapping) return {}
|
|
37
|
-
const maps = {}
|
|
38
|
-
MAPPING_CATEGORIES.forEach((category) => {
|
|
39
|
-
const map = indexedMapping(propertyMapping, category)
|
|
40
|
-
if (map !== undefined) maps[category] = map
|
|
41
|
-
})
|
|
42
|
-
return maps
|
|
24
|
+
interface propertyMappingI {
|
|
25
|
+
[brandId: string]: {
|
|
26
|
+
[category: string]: {
|
|
27
|
+
[from: string]: string
|
|
28
|
+
}
|
|
43
29
|
}
|
|
44
|
-
|
|
45
|
-
if (!acc[item.id]) acc[item.id] = {}
|
|
46
|
-
Object.assign(acc[item.id], indexFn(item.propertyMapping))
|
|
47
|
-
return acc
|
|
48
|
-
}, {})
|
|
30
|
+
}
|
|
49
31
|
|
|
32
|
+
export default function (brands: Array<BrandSettingI>, strategy: mappingStrategyE): (sku: SkuI) => SkuI {
|
|
33
|
+
const indexedByBrandPropertyMapping = {} as propertyMappingI
|
|
34
|
+
brands.forEach(({ id, propertyMapping }) => {
|
|
35
|
+
if (!indexedByBrandPropertyMapping[id]) indexedByBrandPropertyMapping[id] = {}
|
|
36
|
+
propertyMapping?.forEach((mapping) => {
|
|
37
|
+
if (!indexedByBrandPropertyMapping[id][mapping.category]) indexedByBrandPropertyMapping[id][mapping.category] = {}
|
|
38
|
+
indexedByBrandPropertyMapping[id][mapping.category][mapping.from] = mapping.to
|
|
39
|
+
})
|
|
40
|
+
})
|
|
50
41
|
if (strategy == 'clean')
|
|
51
42
|
return function (sku: SkuI): SkuI {
|
|
52
43
|
const brand = sku.BRANDHASH || hashBrand(sku.brand)
|
|
@@ -65,7 +56,7 @@ export default function (brands: Array<BrandSettingI>, strategy: mappingStrategy
|
|
|
65
56
|
const mapping = indexedByBrandPropertyMapping[brand]
|
|
66
57
|
mappingPairs.forEach((pair) => {
|
|
67
58
|
const from = evaluateFromExpr(sku, pair.from) || ''
|
|
68
|
-
const redirectedMappingSource = mapping?.[pair.category]?.['~~']
|
|
59
|
+
const redirectedMappingSource = mapping?.[pair.category]?.['~~'] || pair.defaultMappingSource
|
|
69
60
|
const redirectedMapping = redirectedMappingSource ? indexedByBrandPropertyMapping[redirectedMappingSource] : {}
|
|
70
61
|
|
|
71
62
|
const to = mapping?.[pair.category]?.[from] || mapping?.[pair.category]?.[''] || redirectedMapping?.[pair.category]?.[from] || redirectedMapping?.[pair.category]?.['']
|
|
@@ -79,7 +70,7 @@ export default function (brands: Array<BrandSettingI>, strategy: mappingStrategy
|
|
|
79
70
|
mappingPairs.forEach((pair) => {
|
|
80
71
|
if (sku[pair.to]) return // Do not replace sku-level-user-supplied values
|
|
81
72
|
const from = evaluateFromExpr(sku, pair.from)
|
|
82
|
-
const redirectedMappingSource = mapping?.[pair.category]?.['~~']
|
|
73
|
+
const redirectedMappingSource = mapping?.[pair.category]?.['~~'] || pair.defaultMappingSource
|
|
83
74
|
const redirectedMapping = redirectedMappingSource ? indexedByBrandPropertyMapping[redirectedMappingSource] : {}
|
|
84
75
|
|
|
85
76
|
const to = mapping?.[pair.category]?.[from] || mapping?.[pair.category]?.[''] || redirectedMapping?.[pair.category]?.[from] || redirectedMapping?.[pair.category]?.['']
|
package/src/types.ts
CHANGED
|
@@ -204,6 +204,11 @@ interface ProductI {
|
|
|
204
204
|
year?: string
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
interface PropertyMappingI {
|
|
208
|
+
category: string
|
|
209
|
+
from: string
|
|
210
|
+
to: string
|
|
211
|
+
}
|
|
207
212
|
interface BrandSettingI {
|
|
208
213
|
id: string
|
|
209
214
|
name: string
|
|
@@ -224,7 +229,7 @@ interface BrandSettingI {
|
|
|
224
229
|
whiteListTenants?: string[]
|
|
225
230
|
associates?: object[]
|
|
226
231
|
authGroups?: string[]
|
|
227
|
-
propertyMapping?:
|
|
232
|
+
propertyMapping?: PropertyMappingI[]
|
|
228
233
|
fashionCloudId?: string
|
|
229
234
|
}
|
|
230
235
|
|
|
@@ -233,6 +238,7 @@ enum mappingStrategyE {
|
|
|
233
238
|
CLEAN = 'clean',
|
|
234
239
|
MARK = 'markMissingMapping',
|
|
235
240
|
}
|
|
241
|
+
|
|
236
242
|
export {
|
|
237
243
|
RowI,
|
|
238
244
|
StockTransferSelectionI,
|
|
@@ -107,6 +107,16 @@ const skus = [
|
|
|
107
107
|
collection: '22zomer',
|
|
108
108
|
_customsize: 'medium',
|
|
109
109
|
},
|
|
110
|
+
{
|
|
111
|
+
id: '1234567890138',
|
|
112
|
+
articleGroupSupplier: '11111',
|
|
113
|
+
brand: 'gstar',
|
|
114
|
+
collectionSupplier: 'SUMMER 2022',
|
|
115
|
+
colorCodeSupplier: '200',
|
|
116
|
+
colorFamily: 'Blue',
|
|
117
|
+
size: 'L',
|
|
118
|
+
sizeSupplier: 'L',
|
|
119
|
+
},
|
|
110
120
|
]
|
|
111
121
|
|
|
112
122
|
const articleGroupMapping = [
|
|
@@ -190,6 +200,36 @@ const fallbackMapping = [
|
|
|
190
200
|
],
|
|
191
201
|
},
|
|
192
202
|
]
|
|
203
|
+
|
|
204
|
+
const stackedMapping = [
|
|
205
|
+
{
|
|
206
|
+
id: 'gstar',
|
|
207
|
+
comment: 'LatestCollection level mapping',
|
|
208
|
+
propertyMapping: [
|
|
209
|
+
{
|
|
210
|
+
category: 'ProductGroup',
|
|
211
|
+
from: '12345',
|
|
212
|
+
to: 'LAT-articleGroupMapping',
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
category: 'ProductGroup',
|
|
216
|
+
from: '11111',
|
|
217
|
+
to: 'LAT-articleGroupMapping',
|
|
218
|
+
},
|
|
219
|
+
],
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: 'gstar',
|
|
223
|
+
comment: 'Tenant level mapping',
|
|
224
|
+
propertyMapping: [
|
|
225
|
+
{
|
|
226
|
+
category: 'ProductGroup',
|
|
227
|
+
from: '12345',
|
|
228
|
+
to: 'TENANT-articleGroupMapping',
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
]
|
|
193
233
|
describe('applyPropertyMapping', () => {
|
|
194
234
|
it('returns empty array on an empty array', function () {
|
|
195
235
|
expect(applyPropertyMapping([], []).length).to.equal(0)
|
|
@@ -345,4 +385,10 @@ describe('applyPropertyMapping', () => {
|
|
|
345
385
|
expect(cleanedSkus[9]._customsize).to.equal(undefined)
|
|
346
386
|
expect(cleanedSkus[9].collection).to.equal(undefined)
|
|
347
387
|
})
|
|
388
|
+
|
|
389
|
+
it('applies mapping from different sources', function () {
|
|
390
|
+
const mappedSkus = applyPropertyMapping(deepCopy(skus), stackedMapping)
|
|
391
|
+
expect(mappedSkus[6].articleGroup).to.equal('TENANT-articleGroupMapping')
|
|
392
|
+
expect(mappedSkus[10].articleGroup).to.equal('LAT-articleGroupMapping')
|
|
393
|
+
})
|
|
348
394
|
})
|