@contrail/flexplm 1.4.0-alpha.6954f61 → 1.5.0-alpha.6d9ffc4
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/CHANGELOG.md +2 -0
- package/lib/transform/identifier-conversion.js +1 -1
- package/lib/transform/identifier-conversion.spec.js +31 -0
- package/lib/util/config-defaults.d.ts +18 -0
- package/lib/util/config-defaults.js +22 -15
- package/lib/util/config-defaults.spec.js +47 -0
- package/lib/util/data-converter.js +1 -1
- package/lib/util/data-converter.spec.js +41 -0
- package/lib/util/type-defaults.d.ts +2 -0
- package/lib/util/type-defaults.js +31 -4
- package/lib/util/type-defaults.spec.js +110 -0
- package/package.json +1 -1
- package/src/transform/identifier-conversion.spec.ts +32 -0
- package/src/transform/identifier-conversion.ts +1 -1
- package/src/util/config-defaults.spec.ts +53 -0
- package/src/util/config-defaults.ts +25 -16
- package/src/util/data-converter.spec.ts +45 -0
- package/src/util/data-converter.ts +1 -1
- package/src/util/type-defaults.spec.ts +128 -0
- package/src/util/type-defaults.ts +41 -6
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,8 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
|
6
6
|
Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
|
+
### Added
|
|
10
|
+
- Added support for Inbound `LCSMaterial` to sync to the entity class `item` with type path `item:material` and `itemNumber` as identifier. This is controlled by an `LCSMaterial.processAsItem` (default `false`) config default.
|
|
9
11
|
|
|
10
12
|
## [1.4.0] - 2026-05-06
|
|
11
13
|
### Added
|
|
@@ -201,7 +201,7 @@ class IdentifierConversion {
|
|
|
201
201
|
}
|
|
202
202
|
static async getItemCriteriaFromObject(transformMapFile, mapFileUtil, dc, object) {
|
|
203
203
|
const criteria = await IdentifierConversion.getEntityCriteriaFromObject(transformMapFile, mapFileUtil, dc, object);
|
|
204
|
-
const roles = (object.flexPLMObjectClass
|
|
204
|
+
const roles = (['LCSProduct', 'LCSMaterial'].includes(object.flexPLMObjectClass)) ? 'family' : 'color';
|
|
205
205
|
criteria['roles'] = roles;
|
|
206
206
|
return criteria;
|
|
207
207
|
}
|
|
@@ -4,6 +4,7 @@ const transform_data_1 = require("@contrail/transform-data");
|
|
|
4
4
|
const identifier_conversion_1 = require("./identifier-conversion");
|
|
5
5
|
const data_converter_1 = require("../util/data-converter");
|
|
6
6
|
const sdk_1 = require("@contrail/sdk");
|
|
7
|
+
const type_defaults_1 = require("../util/type-defaults");
|
|
7
8
|
const mapFile1Data = require('./identifier-conversion-spec-mockData');
|
|
8
9
|
const mapFile1Mappings = mapFile1Data?.mapping;
|
|
9
10
|
const mapFile2Mappings = mapFile1Data?.mapping2;
|
|
@@ -296,6 +297,36 @@ describe('getItemCriteriaFromObject', () => {
|
|
|
296
297
|
}
|
|
297
298
|
}
|
|
298
299
|
});
|
|
300
|
+
it('should return the item family criteria from the object -LCSMaterial', async () => {
|
|
301
|
+
const object = {
|
|
302
|
+
"flexPLMObjectClass": "LCSMaterial",
|
|
303
|
+
"flexPLMTypePath": "Material\\form",
|
|
304
|
+
"itemNumber": "MAT-100"
|
|
305
|
+
};
|
|
306
|
+
const criteriaObject = {
|
|
307
|
+
flexPLMObjectClass: 'LCSMaterial',
|
|
308
|
+
itemNumber: 'MAT-100',
|
|
309
|
+
flexPLMTypePath: 'Material\\form',
|
|
310
|
+
};
|
|
311
|
+
const resultsObject = {
|
|
312
|
+
roles: 'family',
|
|
313
|
+
itemNumber: 'MAT-100'
|
|
314
|
+
};
|
|
315
|
+
let getEntityValuesSpyOn = undefined;
|
|
316
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
317
|
+
try {
|
|
318
|
+
getEntityValuesSpyOn = jest.spyOn(dc, 'getEntityValues');
|
|
319
|
+
const result = await identifier_conversion_1.IdentifierConversion.getItemCriteriaFromObject(transformMapFile1, mapFileUtil, dc, object);
|
|
320
|
+
expect(getEntityValuesSpyOn).toHaveBeenCalledWith('LCSMaterial', criteriaObject, []);
|
|
321
|
+
expect(result).toEqual(resultsObject);
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
if (getEntityValuesSpyOn) {
|
|
325
|
+
getEntityValuesSpyOn.mockRestore();
|
|
326
|
+
}
|
|
327
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
328
|
+
}
|
|
329
|
+
});
|
|
299
330
|
it('should return the item option criteria from the object -uniqueIdentifierA, uniqueIdentifierB', async () => {
|
|
300
331
|
const object = {
|
|
301
332
|
"flexBoolean": false,
|
|
@@ -3,6 +3,24 @@ export declare class ConfigDefaults {
|
|
|
3
3
|
static NEED_CONFIG_VALUES: string;
|
|
4
4
|
static STATIC_CONFIG_CACHE: {};
|
|
5
5
|
static setConfigDefaults(config: any): Promise<FCConfig>;
|
|
6
|
+
static getDefaultConfig(): {
|
|
7
|
+
urlContext: string;
|
|
8
|
+
sendMode: {
|
|
9
|
+
ASYNC_PUBLISH_SEASON: string;
|
|
10
|
+
};
|
|
11
|
+
itemPreDevelopmentLifecycleStages: string[];
|
|
12
|
+
identifierAtts: {
|
|
13
|
+
LCSProduct: string[];
|
|
14
|
+
LCSSeason: string[];
|
|
15
|
+
LCSSKU: string[];
|
|
16
|
+
};
|
|
17
|
+
LCSMaterial: {
|
|
18
|
+
processAsItem: boolean;
|
|
19
|
+
};
|
|
20
|
+
csrfEndpoint: string;
|
|
21
|
+
vibeEventEndpoint: string;
|
|
22
|
+
payloadDefaultAsArray: boolean;
|
|
23
|
+
};
|
|
6
24
|
static getConfigFile(fileId: string): Promise<any>;
|
|
7
25
|
static isPropertyTrue(value: any): boolean;
|
|
8
26
|
static clearConfigCache(): void;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ConfigDefaults = void 0;
|
|
4
4
|
const sdk_1 = require("@contrail/sdk");
|
|
5
5
|
const util_1 = require("@contrail/util");
|
|
6
|
+
const type_defaults_1 = require("./type-defaults");
|
|
6
7
|
class ConfigDefaults {
|
|
7
8
|
static async setConfigDefaults(config) {
|
|
8
9
|
if (!config.apiHost || !config.userName || !config.password) {
|
|
@@ -14,7 +15,24 @@ class ConfigDefaults {
|
|
|
14
15
|
else if (Object.keys(config).includes('itemPreDevelopmentLifecycleStages')) {
|
|
15
16
|
delete config['itemPreDevelopmentLifecycleStages'];
|
|
16
17
|
}
|
|
17
|
-
const
|
|
18
|
+
const configArr = [ConfigDefaults.getDefaultConfig()];
|
|
19
|
+
if (config.configFile) {
|
|
20
|
+
const fileConfig = await ConfigDefaults.getConfigFile(config.configFile);
|
|
21
|
+
configArr.push(fileConfig);
|
|
22
|
+
}
|
|
23
|
+
configArr.push(config);
|
|
24
|
+
const outputConfig = util_1.ObjectUtil.mergeDeep({}, ...configArr);
|
|
25
|
+
const uName = outputConfig.userName;
|
|
26
|
+
const pass = outputConfig.password;
|
|
27
|
+
outputConfig.userName = () => uName;
|
|
28
|
+
outputConfig.password = () => pass;
|
|
29
|
+
outputConfig['OOBvibeEventEndpoint'] = '/rfa/vibeiq/vibeEvents';
|
|
30
|
+
type_defaults_1.TypeDefaults.applyConfig(outputConfig);
|
|
31
|
+
console.log('outputConfig: ' + JSON.stringify(outputConfig));
|
|
32
|
+
return outputConfig;
|
|
33
|
+
}
|
|
34
|
+
static getDefaultConfig() {
|
|
35
|
+
return {
|
|
18
36
|
urlContext: '/Windchill',
|
|
19
37
|
sendMode: {
|
|
20
38
|
ASYNC_PUBLISH_SEASON: 'vibeiqfile'
|
|
@@ -25,24 +43,13 @@ class ConfigDefaults {
|
|
|
25
43
|
LCSSeason: ['flexPLMSeasonName'],
|
|
26
44
|
LCSSKU: ['itemNumber']
|
|
27
45
|
},
|
|
46
|
+
LCSMaterial: {
|
|
47
|
+
processAsItem: false
|
|
48
|
+
},
|
|
28
49
|
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
29
50
|
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
30
51
|
payloadDefaultAsArray: true
|
|
31
52
|
};
|
|
32
|
-
const configArr = [defaultConfig];
|
|
33
|
-
if (config.configFile) {
|
|
34
|
-
const fileConfig = await ConfigDefaults.getConfigFile(config.configFile);
|
|
35
|
-
configArr.push(fileConfig);
|
|
36
|
-
}
|
|
37
|
-
configArr.push(config);
|
|
38
|
-
const outputConfig = util_1.ObjectUtil.mergeDeep({}, ...configArr);
|
|
39
|
-
const uName = outputConfig.userName;
|
|
40
|
-
const pass = outputConfig.password;
|
|
41
|
-
outputConfig.userName = () => uName;
|
|
42
|
-
outputConfig.password = () => pass;
|
|
43
|
-
outputConfig['OOBvibeEventEndpoint'] = '/rfa/vibeiq/vibeEvents';
|
|
44
|
-
console.log('outputConfig: ' + JSON.stringify(outputConfig));
|
|
45
|
-
return outputConfig;
|
|
46
53
|
}
|
|
47
54
|
static async getConfigFile(fileId) {
|
|
48
55
|
try {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const config_defaults_1 = require("./config-defaults");
|
|
4
|
+
const type_defaults_1 = require("./type-defaults");
|
|
4
5
|
let entityObject = {};
|
|
5
6
|
jest.mock('@contrail/sdk', () => {
|
|
6
7
|
return {
|
|
@@ -296,6 +297,52 @@ describe('all tests', () => {
|
|
|
296
297
|
expect(config_defaults_1.ConfigDefaults.isPropertyTrue(1)).toBe(false);
|
|
297
298
|
});
|
|
298
299
|
});
|
|
300
|
+
describe('getDefaultConfig', () => {
|
|
301
|
+
it('returns LCSMaterial.processAsItem=false by default', () => {
|
|
302
|
+
const dc = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
303
|
+
expect(dc.LCSMaterial).toBeDefined();
|
|
304
|
+
expect(dc.LCSMaterial.processAsItem).toBe(false);
|
|
305
|
+
});
|
|
306
|
+
it('returns a fresh object each call (no shared reference)', () => {
|
|
307
|
+
const a = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
308
|
+
const b = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
309
|
+
expect(a).not.toBe(b);
|
|
310
|
+
expect(a.LCSMaterial).not.toBe(b.LCSMaterial);
|
|
311
|
+
a.LCSMaterial.processAsItem = true;
|
|
312
|
+
expect(b.LCSMaterial.processAsItem).toBe(false);
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
describe('setConfigDefaults - LCSMaterial', () => {
|
|
316
|
+
const config = {
|
|
317
|
+
apiHost: 'http://test.com',
|
|
318
|
+
userName: 'vibeiq',
|
|
319
|
+
password: 'vibeiq'
|
|
320
|
+
};
|
|
321
|
+
it('LCSMaterial.processAsItem-get default', async () => {
|
|
322
|
+
const startConfig = Object.assign({}, config);
|
|
323
|
+
const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
|
|
324
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(false);
|
|
325
|
+
});
|
|
326
|
+
it('LCSMaterial.processAsItem-override', async () => {
|
|
327
|
+
const startConfig = Object.assign({}, config);
|
|
328
|
+
startConfig.LCSMaterial = { processAsItem: true };
|
|
329
|
+
const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
|
|
330
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(true);
|
|
331
|
+
});
|
|
332
|
+
it('applies LCSMaterial.processAsItem to TypeDefaults', async () => {
|
|
333
|
+
try {
|
|
334
|
+
const startConfig = Object.assign({}, config, { LCSMaterial: { processAsItem: true } });
|
|
335
|
+
await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
|
|
336
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
337
|
+
const defaultStart = Object.assign({}, config);
|
|
338
|
+
await config_defaults_1.ConfigDefaults.setConfigDefaults(defaultStart);
|
|
339
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
340
|
+
}
|
|
341
|
+
finally {
|
|
342
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
});
|
|
299
346
|
describe('getConfigFile', () => {
|
|
300
347
|
beforeEach(() => {
|
|
301
348
|
config_defaults_1.ConfigDefaults.clearConfigCache();
|
|
@@ -235,7 +235,7 @@ class DataConverter {
|
|
|
235
235
|
const type = await this.typeUtils.getByRootAndPath(tco);
|
|
236
236
|
const typePath = type['typePath'];
|
|
237
237
|
if (typePath && (typePath.startsWith('item') || typePath.startsWith('project-item'))) {
|
|
238
|
-
if (['LCSProduct', 'LCSProductSeasonLink'].includes(objectClass)) {
|
|
238
|
+
if (['LCSProduct', 'LCSProductSeasonLink', 'LCSMaterial'].includes(objectClass)) {
|
|
239
239
|
entityValues['roles'] = ['family'];
|
|
240
240
|
}
|
|
241
241
|
else {
|
|
@@ -525,6 +525,47 @@ describe('getObjectReferenceValue - use mapping', () => {
|
|
|
525
525
|
}
|
|
526
526
|
});
|
|
527
527
|
});
|
|
528
|
+
describe('getEntityValues', () => {
|
|
529
|
+
const config = {
|
|
530
|
+
apiHost: 'host',
|
|
531
|
+
userName: () => 'user',
|
|
532
|
+
password: () => 'pass',
|
|
533
|
+
urlContext: 'xxx',
|
|
534
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
535
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
536
|
+
itemPreDevelopmentLifecycleStages: ['concept']
|
|
537
|
+
};
|
|
538
|
+
const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
|
|
539
|
+
const dc = new data_converter_1.DataConverter(config, mapFileUtil);
|
|
540
|
+
const runWithStubs = async (typePath, objectClass, data) => {
|
|
541
|
+
const tcoSpy = jest.spyOn(dc['typeUtils'], 'getEntityTypeClientOptionsUsingMapping')
|
|
542
|
+
.mockImplementation(async () => ({ root: 'item' }));
|
|
543
|
+
const typeSpy = jest.spyOn(dc['typeUtils'], 'getByRootAndPath')
|
|
544
|
+
.mockImplementation(async () => ({ typePath, typeProperties: [] }));
|
|
545
|
+
const filterSpy = jest.spyOn(dc['typeUtils'], 'filterTypeProperties')
|
|
546
|
+
.mockImplementation(() => []);
|
|
547
|
+
try {
|
|
548
|
+
return await dc.getEntityValues(objectClass, data);
|
|
549
|
+
}
|
|
550
|
+
finally {
|
|
551
|
+
tcoSpy.mockRestore();
|
|
552
|
+
typeSpy.mockRestore();
|
|
553
|
+
filterSpy.mockRestore();
|
|
554
|
+
}
|
|
555
|
+
};
|
|
556
|
+
it('LCSProduct -> roles family', async () => {
|
|
557
|
+
const result = await runWithStubs('item', 'LCSProduct', { itemNumber: 'X1' });
|
|
558
|
+
expect(result['roles']).toEqual(['family']);
|
|
559
|
+
});
|
|
560
|
+
it('LCSSKU -> roles color, option', async () => {
|
|
561
|
+
const result = await runWithStubs('item', 'LCSSKU', { itemNumber: 'X1' });
|
|
562
|
+
expect(result['roles']).toEqual(['color', 'option']);
|
|
563
|
+
});
|
|
564
|
+
it('LCSMaterial -> roles family', async () => {
|
|
565
|
+
const result = await runWithStubs('item:material', 'LCSMaterial', { itemNumber: 'MAT-100' });
|
|
566
|
+
expect(result['roles']).toEqual(['family']);
|
|
567
|
+
});
|
|
568
|
+
});
|
|
528
569
|
describe('setEnumerationKeys', () => {
|
|
529
570
|
const config = {
|
|
530
571
|
apiHost: 'host',
|
|
@@ -2,7 +2,9 @@ export declare class TypeDefaults {
|
|
|
2
2
|
static NO_ENTITY_TYPE: string;
|
|
3
3
|
static NO_OBJECT_CLASS: string;
|
|
4
4
|
static NO_TYPE_PATH: string;
|
|
5
|
+
static processLCSMaterialAsItem: boolean;
|
|
5
6
|
constructor();
|
|
7
|
+
static applyConfig(config: any): void;
|
|
6
8
|
static getDefaultObjectClass(entity: any): string;
|
|
7
9
|
static getDefaultObjectTypePath(entity: any): string;
|
|
8
10
|
static getDefaultIdentifierProperties(entity: any): string[];
|
|
@@ -4,6 +4,11 @@ exports.TypeDefaults = void 0;
|
|
|
4
4
|
class TypeDefaults {
|
|
5
5
|
constructor() {
|
|
6
6
|
}
|
|
7
|
+
static applyConfig(config) {
|
|
8
|
+
const val = config?.LCSMaterial?.processAsItem;
|
|
9
|
+
TypeDefaults.processLCSMaterialAsItem =
|
|
10
|
+
val === true || (typeof val === 'string' && val.toLowerCase() === 'true');
|
|
11
|
+
}
|
|
7
12
|
static getDefaultObjectClass(entity) {
|
|
8
13
|
const entityType = this.getEntityType(entity);
|
|
9
14
|
let objectClass = '';
|
|
@@ -130,7 +135,13 @@ class TypeDefaults {
|
|
|
130
135
|
static getDefaultEntityClass(object) {
|
|
131
136
|
let entityClass = '';
|
|
132
137
|
let objectClass = TypeDefaults.getObjectClass(object);
|
|
133
|
-
|
|
138
|
+
const itemClasses = TypeDefaults.processLCSMaterialAsItem
|
|
139
|
+
? ['LCSProduct', 'LCSSKU', 'LCSMaterial']
|
|
140
|
+
: ['LCSProduct', 'LCSSKU'];
|
|
141
|
+
const customEntityClasses = TypeDefaults.processLCSMaterialAsItem
|
|
142
|
+
? ['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast']
|
|
143
|
+
: ['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast', 'LCSMaterial'];
|
|
144
|
+
if (itemClasses.includes(objectClass)) {
|
|
134
145
|
entityClass = 'item';
|
|
135
146
|
}
|
|
136
147
|
else if (['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)) {
|
|
@@ -142,7 +153,7 @@ class TypeDefaults {
|
|
|
142
153
|
else if (['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
143
154
|
entityClass = 'assortment';
|
|
144
155
|
}
|
|
145
|
-
else if (
|
|
156
|
+
else if (customEntityClasses.includes(objectClass)) {
|
|
146
157
|
entityClass = 'custom-entity';
|
|
147
158
|
}
|
|
148
159
|
if (entityClass === '')
|
|
@@ -157,6 +168,11 @@ class TypeDefaults {
|
|
|
157
168
|
case 'LCSSKU':
|
|
158
169
|
typePath = 'item';
|
|
159
170
|
break;
|
|
171
|
+
case 'LCSMaterial':
|
|
172
|
+
if (TypeDefaults.processLCSMaterialAsItem) {
|
|
173
|
+
typePath = 'item:material';
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
160
176
|
case 'LCSProductSeasonLink':
|
|
161
177
|
case 'LCSSKUSeasonLink':
|
|
162
178
|
typePath = 'project-item';
|
|
@@ -181,6 +197,14 @@ class TypeDefaults {
|
|
|
181
197
|
case 'LCSSKU':
|
|
182
198
|
identifierProps.push('itemNumber');
|
|
183
199
|
break;
|
|
200
|
+
case 'LCSMaterial':
|
|
201
|
+
if (TypeDefaults.processLCSMaterialAsItem) {
|
|
202
|
+
identifierProps.push('itemNumber');
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
identifierProps.push('name');
|
|
206
|
+
}
|
|
207
|
+
break;
|
|
184
208
|
case 'LCSSeason':
|
|
185
209
|
identifierProps.push('flexPLMSeasonName');
|
|
186
210
|
break;
|
|
@@ -191,7 +215,6 @@ class TypeDefaults {
|
|
|
191
215
|
case 'LCSRevisableEntity':
|
|
192
216
|
case 'LCSLifecycleManaged':
|
|
193
217
|
case 'LCSLast':
|
|
194
|
-
case 'LCSMaterial':
|
|
195
218
|
identifierProps.push('name');
|
|
196
219
|
break;
|
|
197
220
|
}
|
|
@@ -200,7 +223,10 @@ class TypeDefaults {
|
|
|
200
223
|
static getDefaultInformationalPropertiesFromObject(object) {
|
|
201
224
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
202
225
|
let properties = [];
|
|
203
|
-
|
|
226
|
+
const itemClasses = TypeDefaults.processLCSMaterialAsItem
|
|
227
|
+
? ['LCSProduct', 'LCSMaterial']
|
|
228
|
+
: ['LCSProduct'];
|
|
229
|
+
if (itemClasses.includes(objectClass)) {
|
|
204
230
|
properties.push('name');
|
|
205
231
|
}
|
|
206
232
|
else if ('LCSSKU' === objectClass) {
|
|
@@ -219,3 +245,4 @@ exports.TypeDefaults = TypeDefaults;
|
|
|
219
245
|
TypeDefaults.NO_ENTITY_TYPE = 'Not able to determine the entity type of the entity object';
|
|
220
246
|
TypeDefaults.NO_OBJECT_CLASS = 'Please ensure that the flexPLMObjectClass property is provided.';
|
|
221
247
|
TypeDefaults.NO_TYPE_PATH = 'Please ensure that the flexPLMTypePath property is provided.';
|
|
248
|
+
TypeDefaults.processLCSMaterialAsItem = false;
|
|
@@ -369,6 +369,26 @@ describe('Type Defaults', () => {
|
|
|
369
369
|
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
370
370
|
expect(entityClass).toBe('custom-entity');
|
|
371
371
|
});
|
|
372
|
+
it('item - LCSMaterial - processAsItem=true', () => {
|
|
373
|
+
const object = {
|
|
374
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
375
|
+
};
|
|
376
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
377
|
+
try {
|
|
378
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
379
|
+
expect(entityClass).toBe('item');
|
|
380
|
+
}
|
|
381
|
+
finally {
|
|
382
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
it('custom-entity - LCSMaterial - processAsItem=false (default)', () => {
|
|
386
|
+
const object = {
|
|
387
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
388
|
+
};
|
|
389
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
390
|
+
expect(entityClass).toBe('custom-entity');
|
|
391
|
+
});
|
|
372
392
|
});
|
|
373
393
|
describe('getDefaultEntityTypePath', () => {
|
|
374
394
|
it('LCSProduct', () => {
|
|
@@ -420,6 +440,25 @@ describe('Type Defaults', () => {
|
|
|
420
440
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
421
441
|
expect(typePath).toBe('assortment');
|
|
422
442
|
});
|
|
443
|
+
it('LCSMaterial - processAsItem=true', () => {
|
|
444
|
+
const object = {
|
|
445
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
446
|
+
};
|
|
447
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
448
|
+
try {
|
|
449
|
+
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
450
|
+
expect(typePath).toBe('item:material');
|
|
451
|
+
}
|
|
452
|
+
finally {
|
|
453
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
454
|
+
}
|
|
455
|
+
});
|
|
456
|
+
it('LCSMaterial - processAsItem=false (default) throws', () => {
|
|
457
|
+
const object = {
|
|
458
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
459
|
+
};
|
|
460
|
+
expect(() => type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object)).toThrowError(type_defaults_1.TypeDefaults.NO_TYPE_PATH);
|
|
461
|
+
});
|
|
423
462
|
});
|
|
424
463
|
describe('getDefaultIdentifierPropertiesFromObject', () => {
|
|
425
464
|
it('LCSProduct', () => {
|
|
@@ -478,6 +517,28 @@ describe('Type Defaults', () => {
|
|
|
478
517
|
expect(defaultIdentifiers).toContain('name');
|
|
479
518
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
480
519
|
});
|
|
520
|
+
it('LCSMaterial - processAsItem=true', () => {
|
|
521
|
+
const object = {
|
|
522
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
523
|
+
};
|
|
524
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
525
|
+
try {
|
|
526
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
527
|
+
expect(defaultIdentifiers).toContain('itemNumber');
|
|
528
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
529
|
+
}
|
|
530
|
+
finally {
|
|
531
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
532
|
+
}
|
|
533
|
+
});
|
|
534
|
+
it('LCSMaterial - processAsItem=false (default)', () => {
|
|
535
|
+
const object = {
|
|
536
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
537
|
+
};
|
|
538
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
539
|
+
expect(defaultIdentifiers).toContain('name');
|
|
540
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
541
|
+
});
|
|
481
542
|
});
|
|
482
543
|
describe('getDefaultInformationalPropertiesFromObject', () => {
|
|
483
544
|
it('LCSProduct', () => {
|
|
@@ -512,5 +573,54 @@ describe('Type Defaults', () => {
|
|
|
512
573
|
expect(defaultIdentifiers).toContain('name');
|
|
513
574
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
514
575
|
});
|
|
576
|
+
it('LCSMaterial - processAsItem=true', () => {
|
|
577
|
+
const object = {
|
|
578
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
579
|
+
};
|
|
580
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
581
|
+
try {
|
|
582
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
583
|
+
expect(defaultIdentifiers).toContain('name');
|
|
584
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
585
|
+
}
|
|
586
|
+
finally {
|
|
587
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
it('LCSMaterial - processAsItem=false (default) yields no informational props', () => {
|
|
591
|
+
const object = {
|
|
592
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
593
|
+
};
|
|
594
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
595
|
+
expect(defaultIdentifiers).toHaveLength(0);
|
|
596
|
+
});
|
|
597
|
+
});
|
|
598
|
+
describe('applyConfig', () => {
|
|
599
|
+
afterEach(() => {
|
|
600
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
601
|
+
});
|
|
602
|
+
it('sets processLCSMaterialAsItem=true when processAsItem=true', () => {
|
|
603
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
604
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
605
|
+
});
|
|
606
|
+
it('sets processLCSMaterialAsItem=true when processAsItem=\"true\" (string)', () => {
|
|
607
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: 'true' } });
|
|
608
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
609
|
+
});
|
|
610
|
+
it('sets processLCSMaterialAsItem=false when processAsItem=false', () => {
|
|
611
|
+
type_defaults_1.TypeDefaults.processLCSMaterialAsItem = true;
|
|
612
|
+
type_defaults_1.TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: false } });
|
|
613
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
614
|
+
});
|
|
615
|
+
it('sets processLCSMaterialAsItem=false when LCSMaterial missing', () => {
|
|
616
|
+
type_defaults_1.TypeDefaults.processLCSMaterialAsItem = true;
|
|
617
|
+
type_defaults_1.TypeDefaults.applyConfig({});
|
|
618
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
619
|
+
});
|
|
620
|
+
it('sets processLCSMaterialAsItem=false when config is null/undefined', () => {
|
|
621
|
+
type_defaults_1.TypeDefaults.processLCSMaterialAsItem = true;
|
|
622
|
+
type_defaults_1.TypeDefaults.applyConfig(undefined);
|
|
623
|
+
expect(type_defaults_1.TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
624
|
+
});
|
|
515
625
|
});
|
|
516
626
|
});
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@ import { IdentifierConversion } from "./identifier-conversion";
|
|
|
3
3
|
import { DataConverter } from "../util/data-converter";
|
|
4
4
|
import { FCConfig } from "../interfaces/interfaces";
|
|
5
5
|
import { Entities } from "@contrail/sdk";
|
|
6
|
+
import { TypeDefaults } from "../util/type-defaults";
|
|
6
7
|
|
|
7
8
|
const mapFile1Data = require('./identifier-conversion-spec-mockData');
|
|
8
9
|
const mapFile1Mappings = mapFile1Data?.mapping;
|
|
@@ -309,6 +310,37 @@ describe('getItemCriteriaFromObject', () => {
|
|
|
309
310
|
}
|
|
310
311
|
});
|
|
311
312
|
|
|
313
|
+
it('should return the item family criteria from the object -LCSMaterial', async () => {
|
|
314
|
+
const object = {
|
|
315
|
+
"flexPLMObjectClass": "LCSMaterial",
|
|
316
|
+
"flexPLMTypePath": "Material\\form",
|
|
317
|
+
"itemNumber": "MAT-100"
|
|
318
|
+
};
|
|
319
|
+
const criteriaObject = {
|
|
320
|
+
flexPLMObjectClass: 'LCSMaterial',
|
|
321
|
+
itemNumber: 'MAT-100',
|
|
322
|
+
flexPLMTypePath: 'Material\\form',
|
|
323
|
+
};
|
|
324
|
+
const resultsObject = {
|
|
325
|
+
roles: 'family',
|
|
326
|
+
itemNumber: 'MAT-100'
|
|
327
|
+
};
|
|
328
|
+
let getEntityValuesSpyOn = undefined
|
|
329
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
330
|
+
try {
|
|
331
|
+
|
|
332
|
+
getEntityValuesSpyOn = jest.spyOn(dc, 'getEntityValues');
|
|
333
|
+
const result = await IdentifierConversion.getItemCriteriaFromObject(transformMapFile1, mapFileUtil, dc, object);
|
|
334
|
+
expect(getEntityValuesSpyOn).toHaveBeenCalledWith('LCSMaterial', criteriaObject, []);
|
|
335
|
+
expect(result).toEqual(resultsObject);
|
|
336
|
+
} finally {
|
|
337
|
+
if (getEntityValuesSpyOn) {
|
|
338
|
+
getEntityValuesSpyOn.mockRestore();
|
|
339
|
+
}
|
|
340
|
+
TypeDefaults.applyConfig({});
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
|
|
312
344
|
it('should return the item option criteria from the object -uniqueIdentifierA, uniqueIdentifierB', async () => {
|
|
313
345
|
const object = {
|
|
314
346
|
"flexBoolean": false,
|
|
@@ -274,7 +274,7 @@ export class IdentifierConversion {
|
|
|
274
274
|
|
|
275
275
|
static async getItemCriteriaFromObject(transformMapFile: string, mapFileUtil: MapFileUtil, dc: DataConverter, object: any): Promise<any> {
|
|
276
276
|
const criteria = await IdentifierConversion.getEntityCriteriaFromObject(transformMapFile, mapFileUtil, dc, object);
|
|
277
|
-
const roles = (object.flexPLMObjectClass
|
|
277
|
+
const roles = (['LCSProduct', 'LCSMaterial'].includes(object.flexPLMObjectClass)) ? 'family' : 'color';
|
|
278
278
|
criteria['roles'] = roles;
|
|
279
279
|
|
|
280
280
|
return criteria;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ConfigDefaults } from './config-defaults';
|
|
2
2
|
import { FCConfig } from '../interfaces/interfaces';
|
|
3
|
+
import { TypeDefaults } from './type-defaults';
|
|
3
4
|
|
|
4
5
|
let entityObject = {};
|
|
5
6
|
jest.mock('@contrail/sdk', () => {
|
|
@@ -356,6 +357,58 @@ describe('all tests', () => {
|
|
|
356
357
|
});
|
|
357
358
|
});
|
|
358
359
|
|
|
360
|
+
describe('getDefaultConfig', () => {
|
|
361
|
+
it('returns LCSMaterial.processAsItem=false by default', () => {
|
|
362
|
+
const dc: any = ConfigDefaults.getDefaultConfig();
|
|
363
|
+
expect(dc.LCSMaterial).toBeDefined();
|
|
364
|
+
expect(dc.LCSMaterial.processAsItem).toBe(false);
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it('returns a fresh object each call (no shared reference)', () => {
|
|
368
|
+
const a: any = ConfigDefaults.getDefaultConfig();
|
|
369
|
+
const b: any = ConfigDefaults.getDefaultConfig();
|
|
370
|
+
expect(a).not.toBe(b);
|
|
371
|
+
expect(a.LCSMaterial).not.toBe(b.LCSMaterial);
|
|
372
|
+
a.LCSMaterial.processAsItem = true;
|
|
373
|
+
expect(b.LCSMaterial.processAsItem).toBe(false);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
describe('setConfigDefaults - LCSMaterial', () => {
|
|
378
|
+
const config = {
|
|
379
|
+
apiHost: 'http://test.com',
|
|
380
|
+
userName: 'vibeiq',
|
|
381
|
+
password: 'vibeiq'
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
it('LCSMaterial.processAsItem-get default', async () => {
|
|
385
|
+
const startConfig = Object.assign({}, config);
|
|
386
|
+
const fcConfig: any = await ConfigDefaults.setConfigDefaults(startConfig);
|
|
387
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(false);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
it('LCSMaterial.processAsItem-override', async () => {
|
|
391
|
+
const startConfig: any = Object.assign({}, config);
|
|
392
|
+
startConfig.LCSMaterial = { processAsItem: true };
|
|
393
|
+
const fcConfig: any = await ConfigDefaults.setConfigDefaults(startConfig);
|
|
394
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(true);
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
it('applies LCSMaterial.processAsItem to TypeDefaults', async () => {
|
|
398
|
+
try {
|
|
399
|
+
const startConfig: any = Object.assign({}, config, { LCSMaterial: { processAsItem: true } });
|
|
400
|
+
await ConfigDefaults.setConfigDefaults(startConfig);
|
|
401
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
402
|
+
|
|
403
|
+
const defaultStart: any = Object.assign({}, config);
|
|
404
|
+
await ConfigDefaults.setConfigDefaults(defaultStart);
|
|
405
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
406
|
+
} finally {
|
|
407
|
+
TypeDefaults.applyConfig({});
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
359
412
|
describe('getConfigFile', () => {
|
|
360
413
|
beforeEach(() => {
|
|
361
414
|
ConfigDefaults.clearConfigCache();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Entities } from '@contrail/sdk';
|
|
2
2
|
import { FCConfig } from '../interfaces/interfaces';
|
|
3
3
|
import { ObjectUtil } from '@contrail/util';
|
|
4
|
+
import { TypeDefaults } from './type-defaults';
|
|
4
5
|
|
|
5
6
|
export class ConfigDefaults {
|
|
6
7
|
static NEED_CONFIG_VALUES = 'To connect to FlexPLM all these APP values need to be set apiHost, userName, and password';
|
|
@@ -18,22 +19,7 @@ export class ConfigDefaults {
|
|
|
18
19
|
delete config['itemPreDevelopmentLifecycleStages'];
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
const
|
|
22
|
-
urlContext: '/Windchill',
|
|
23
|
-
sendMode: {
|
|
24
|
-
ASYNC_PUBLISH_SEASON: 'vibeiqfile'
|
|
25
|
-
},
|
|
26
|
-
itemPreDevelopmentLifecycleStages: ['concept'],
|
|
27
|
-
identifierAtts: {
|
|
28
|
-
LCSProduct: ['itemNumber'],
|
|
29
|
-
LCSSeason: ['flexPLMSeasonName'],
|
|
30
|
-
LCSSKU: ['itemNumber']
|
|
31
|
-
},
|
|
32
|
-
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
33
|
-
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
34
|
-
payloadDefaultAsArray: true
|
|
35
|
-
};
|
|
36
|
-
const configArr = [defaultConfig];
|
|
22
|
+
const configArr = [ConfigDefaults.getDefaultConfig()];
|
|
37
23
|
|
|
38
24
|
if(config.configFile){
|
|
39
25
|
const fileConfig = await ConfigDefaults.getConfigFile(config.configFile);
|
|
@@ -49,10 +35,33 @@ export class ConfigDefaults {
|
|
|
49
35
|
//Don't allow overwriting this.
|
|
50
36
|
outputConfig['OOBvibeEventEndpoint'] = '/rfa/vibeiq/vibeEvents';
|
|
51
37
|
|
|
38
|
+
TypeDefaults.applyConfig(outputConfig);
|
|
39
|
+
|
|
52
40
|
console.log('outputConfig: ' + JSON.stringify(outputConfig));
|
|
53
41
|
return outputConfig as FCConfig;
|
|
54
42
|
}
|
|
55
43
|
|
|
44
|
+
static getDefaultConfig() {
|
|
45
|
+
return {
|
|
46
|
+
urlContext: '/Windchill',
|
|
47
|
+
sendMode: {
|
|
48
|
+
ASYNC_PUBLISH_SEASON: 'vibeiqfile'
|
|
49
|
+
},
|
|
50
|
+
itemPreDevelopmentLifecycleStages: ['concept'],
|
|
51
|
+
identifierAtts: {
|
|
52
|
+
LCSProduct: ['itemNumber'],
|
|
53
|
+
LCSSeason: ['flexPLMSeasonName'],
|
|
54
|
+
LCSSKU: ['itemNumber']
|
|
55
|
+
},
|
|
56
|
+
LCSMaterial: {
|
|
57
|
+
processAsItem: false
|
|
58
|
+
},
|
|
59
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
60
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
61
|
+
payloadDefaultAsArray: true
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
static async getConfigFile(fileId: string) {
|
|
57
66
|
try {
|
|
58
67
|
|
|
@@ -594,6 +594,51 @@ describe('getObjectReferenceValue - use mapping', () => {
|
|
|
594
594
|
});
|
|
595
595
|
});
|
|
596
596
|
|
|
597
|
+
describe('getEntityValues', () => {
|
|
598
|
+
const config: FCConfig = {
|
|
599
|
+
apiHost: 'host',
|
|
600
|
+
userName: () => 'user',
|
|
601
|
+
password: () => 'pass',
|
|
602
|
+
urlContext: 'xxx',
|
|
603
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
604
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
605
|
+
itemPreDevelopmentLifecycleStages: ['concept']
|
|
606
|
+
};
|
|
607
|
+
const mapFileUtil = new MapFileUtil(new Entities());
|
|
608
|
+
const dc = new DataConverter(config, mapFileUtil);
|
|
609
|
+
|
|
610
|
+
const runWithStubs = async (typePath: string, objectClass: string, data: any) => {
|
|
611
|
+
const tcoSpy = jest.spyOn(dc['typeUtils'], 'getEntityTypeClientOptionsUsingMapping')
|
|
612
|
+
.mockImplementation(async () => ({ root: 'item' }));
|
|
613
|
+
const typeSpy = jest.spyOn(dc['typeUtils'], 'getByRootAndPath')
|
|
614
|
+
.mockImplementation(async () => ({ typePath, typeProperties: [] }));
|
|
615
|
+
const filterSpy = jest.spyOn(dc['typeUtils'], 'filterTypeProperties')
|
|
616
|
+
.mockImplementation(() => []);
|
|
617
|
+
try {
|
|
618
|
+
return await dc.getEntityValues(objectClass, data);
|
|
619
|
+
} finally {
|
|
620
|
+
tcoSpy.mockRestore();
|
|
621
|
+
typeSpy.mockRestore();
|
|
622
|
+
filterSpy.mockRestore();
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
it('LCSProduct -> roles family', async () => {
|
|
627
|
+
const result = await runWithStubs('item', 'LCSProduct', { itemNumber: 'X1' });
|
|
628
|
+
expect(result['roles']).toEqual(['family']);
|
|
629
|
+
});
|
|
630
|
+
|
|
631
|
+
it('LCSSKU -> roles color, option', async () => {
|
|
632
|
+
const result = await runWithStubs('item', 'LCSSKU', { itemNumber: 'X1' });
|
|
633
|
+
expect(result['roles']).toEqual(['color', 'option']);
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
it('LCSMaterial -> roles family', async () => {
|
|
637
|
+
const result = await runWithStubs('item:material', 'LCSMaterial', { itemNumber: 'MAT-100' });
|
|
638
|
+
expect(result['roles']).toEqual(['family']);
|
|
639
|
+
});
|
|
640
|
+
});
|
|
641
|
+
|
|
597
642
|
describe('setEnumerationKeys', () =>{
|
|
598
643
|
const config: FCConfig = {
|
|
599
644
|
apiHost: 'host',
|
|
@@ -287,7 +287,7 @@ export class DataConverter {
|
|
|
287
287
|
const type = await this.typeUtils.getByRootAndPath(tco);
|
|
288
288
|
const typePath = type['typePath'];
|
|
289
289
|
if(typePath && (typePath.startsWith('item') || typePath.startsWith('project-item'))){
|
|
290
|
-
if(['LCSProduct', 'LCSProductSeasonLink'].includes(objectClass)){
|
|
290
|
+
if(['LCSProduct', 'LCSProductSeasonLink', 'LCSMaterial'].includes(objectClass)){
|
|
291
291
|
entityValues['roles'] = ['family'];
|
|
292
292
|
}else{
|
|
293
293
|
entityValues['roles'] = ['color', 'option'];
|
|
@@ -485,6 +485,30 @@ describe('Type Defaults', () =>{
|
|
|
485
485
|
expect(entityClass).toBe('custom-entity');
|
|
486
486
|
});
|
|
487
487
|
|
|
488
|
+
it('item - LCSMaterial - processAsItem=true', () =>{
|
|
489
|
+
const object = {
|
|
490
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
494
|
+
try {
|
|
495
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
496
|
+
expect(entityClass).toBe('item');
|
|
497
|
+
} finally {
|
|
498
|
+
TypeDefaults.applyConfig({});
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
|
|
502
|
+
it('custom-entity - LCSMaterial - processAsItem=false (default)', () =>{
|
|
503
|
+
const object = {
|
|
504
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
508
|
+
|
|
509
|
+
expect(entityClass).toBe('custom-entity');
|
|
510
|
+
});
|
|
511
|
+
|
|
488
512
|
});//getDefaultEntityClass
|
|
489
513
|
|
|
490
514
|
describe('getDefaultEntityTypePath', () =>{
|
|
@@ -549,6 +573,28 @@ describe('Type Defaults', () =>{
|
|
|
549
573
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
550
574
|
expect(typePath).toBe('assortment');
|
|
551
575
|
});
|
|
576
|
+
|
|
577
|
+
it('LCSMaterial - processAsItem=true', () =>{
|
|
578
|
+
const object = {
|
|
579
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
580
|
+
};
|
|
581
|
+
|
|
582
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
583
|
+
try {
|
|
584
|
+
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
585
|
+
expect(typePath).toBe('item:material');
|
|
586
|
+
} finally {
|
|
587
|
+
TypeDefaults.applyConfig({});
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
it('LCSMaterial - processAsItem=false (default) throws', () =>{
|
|
592
|
+
const object = {
|
|
593
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
expect(() => TypeDefaults.getDefaultEntityTypePath(object)).toThrowError(TypeDefaults.NO_TYPE_PATH);
|
|
597
|
+
});
|
|
552
598
|
});//getDefaultEntityTypePath
|
|
553
599
|
|
|
554
600
|
describe('getDefaultIdentifierPropertiesFromObject', () =>{
|
|
@@ -622,6 +668,30 @@ describe('Type Defaults', () =>{
|
|
|
622
668
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
623
669
|
});
|
|
624
670
|
|
|
671
|
+
it('LCSMaterial - processAsItem=true', () =>{
|
|
672
|
+
const object = {
|
|
673
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
674
|
+
};
|
|
675
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
676
|
+
try {
|
|
677
|
+
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
678
|
+
expect(defaultIdentifiers).toContain('itemNumber');
|
|
679
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
680
|
+
} finally {
|
|
681
|
+
TypeDefaults.applyConfig({});
|
|
682
|
+
}
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
it('LCSMaterial - processAsItem=false (default)', () =>{
|
|
686
|
+
const object = {
|
|
687
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
688
|
+
};
|
|
689
|
+
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
690
|
+
|
|
691
|
+
expect(defaultIdentifiers).toContain('name');
|
|
692
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
693
|
+
});
|
|
694
|
+
|
|
625
695
|
});//getDefaultIdentifierPropertiesFromObject
|
|
626
696
|
|
|
627
697
|
describe('getDefaultInformationalPropertiesFromObject', () =>{
|
|
@@ -665,5 +735,63 @@ describe('Type Defaults', () =>{
|
|
|
665
735
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
666
736
|
});
|
|
667
737
|
|
|
738
|
+
it('LCSMaterial - processAsItem=true', () =>{
|
|
739
|
+
const object = {
|
|
740
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
741
|
+
};
|
|
742
|
+
|
|
743
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
744
|
+
try {
|
|
745
|
+
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
746
|
+
expect(defaultIdentifiers).toContain('name');
|
|
747
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
748
|
+
} finally {
|
|
749
|
+
TypeDefaults.applyConfig({});
|
|
750
|
+
}
|
|
751
|
+
});
|
|
752
|
+
|
|
753
|
+
it('LCSMaterial - processAsItem=false (default) yields no informational props', () =>{
|
|
754
|
+
const object = {
|
|
755
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
759
|
+
expect(defaultIdentifiers).toHaveLength(0);
|
|
760
|
+
});
|
|
761
|
+
|
|
668
762
|
});//getDefaultInformationalPropertiesFromObject
|
|
763
|
+
|
|
764
|
+
describe('applyConfig', () => {
|
|
765
|
+
afterEach(() => {
|
|
766
|
+
TypeDefaults.applyConfig({});
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
it('sets processLCSMaterialAsItem=true when processAsItem=true', () => {
|
|
770
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: true } });
|
|
771
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
it('sets processLCSMaterialAsItem=true when processAsItem=\"true\" (string)', () => {
|
|
775
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: 'true' } });
|
|
776
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(true);
|
|
777
|
+
});
|
|
778
|
+
|
|
779
|
+
it('sets processLCSMaterialAsItem=false when processAsItem=false', () => {
|
|
780
|
+
TypeDefaults.processLCSMaterialAsItem = true;
|
|
781
|
+
TypeDefaults.applyConfig({ LCSMaterial: { processAsItem: false } });
|
|
782
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
783
|
+
});
|
|
784
|
+
|
|
785
|
+
it('sets processLCSMaterialAsItem=false when LCSMaterial missing', () => {
|
|
786
|
+
TypeDefaults.processLCSMaterialAsItem = true;
|
|
787
|
+
TypeDefaults.applyConfig({});
|
|
788
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
it('sets processLCSMaterialAsItem=false when config is null/undefined', () => {
|
|
792
|
+
TypeDefaults.processLCSMaterialAsItem = true;
|
|
793
|
+
TypeDefaults.applyConfig(undefined);
|
|
794
|
+
expect(TypeDefaults.processLCSMaterialAsItem).toBe(false);
|
|
795
|
+
});
|
|
796
|
+
});
|
|
669
797
|
});
|
|
@@ -2,8 +2,23 @@ export class TypeDefaults {
|
|
|
2
2
|
static NO_ENTITY_TYPE = 'Not able to determine the entity type of the entity object';
|
|
3
3
|
static NO_OBJECT_CLASS = 'Please ensure that the flexPLMObjectClass property is provided.';
|
|
4
4
|
static NO_TYPE_PATH = 'Please ensure that the flexPLMTypePath property is provided.';
|
|
5
|
+
static processLCSMaterialAsItem = false;
|
|
5
6
|
constructor() {
|
|
6
7
|
}
|
|
8
|
+
|
|
9
|
+
/** Applies values from the resolved config to TypeDefaults static state.
|
|
10
|
+
* Currently toggles whether LCSMaterial is treated as an item (new) or a
|
|
11
|
+
* custom-entity (old) based on config.LCSMaterial.processAsItem.
|
|
12
|
+
* Technically this could cause side effects if different parts of the code
|
|
13
|
+
* expect different behavior, but in practice * @param config will be
|
|
14
|
+
* consistent across the app and this is simpler than passing this config
|
|
15
|
+
* through multiple layers of function calls.
|
|
16
|
+
*/
|
|
17
|
+
static applyConfig(config: any): void {
|
|
18
|
+
const val = config?.LCSMaterial?.processAsItem;
|
|
19
|
+
TypeDefaults.processLCSMaterialAsItem =
|
|
20
|
+
val === true || (typeof val === 'string' && val.toLowerCase() === 'true');
|
|
21
|
+
}
|
|
7
22
|
/**Takes in full entity and returs the default FlexPLM
|
|
8
23
|
* object class.
|
|
9
24
|
*
|
|
@@ -87,7 +102,7 @@ export class TypeDefaults {
|
|
|
87
102
|
*/
|
|
88
103
|
|
|
89
104
|
static getDefaultIdentifierProperties(entity): string[] {
|
|
90
|
-
const identifierProps = [];
|
|
105
|
+
const identifierProps: string[] = [];
|
|
91
106
|
const entityType = this.getEntityType(entity);
|
|
92
107
|
|
|
93
108
|
switch (entityType) {
|
|
@@ -168,7 +183,13 @@ export class TypeDefaults {
|
|
|
168
183
|
static getDefaultEntityClass(object): string {
|
|
169
184
|
let entityClass = '';
|
|
170
185
|
let objectClass = TypeDefaults.getObjectClass(object);
|
|
171
|
-
|
|
186
|
+
const itemClasses = TypeDefaults.processLCSMaterialAsItem
|
|
187
|
+
? ['LCSProduct', 'LCSSKU', 'LCSMaterial']
|
|
188
|
+
: ['LCSProduct', 'LCSSKU'];
|
|
189
|
+
const customEntityClasses = TypeDefaults.processLCSMaterialAsItem
|
|
190
|
+
? ['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast']
|
|
191
|
+
: ['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast', 'LCSMaterial'];
|
|
192
|
+
if(itemClasses.includes(objectClass)){
|
|
172
193
|
entityClass = 'item';
|
|
173
194
|
}else if(['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)){
|
|
174
195
|
entityClass = 'project-item'
|
|
@@ -176,7 +197,7 @@ export class TypeDefaults {
|
|
|
176
197
|
entityClass = 'color';
|
|
177
198
|
} else if(['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
178
199
|
entityClass = 'assortment';
|
|
179
|
-
} else if(
|
|
200
|
+
} else if(customEntityClasses.includes(objectClass)) {
|
|
180
201
|
entityClass = 'custom-entity';
|
|
181
202
|
}
|
|
182
203
|
|
|
@@ -201,6 +222,11 @@ export class TypeDefaults {
|
|
|
201
222
|
case 'LCSSKU':
|
|
202
223
|
typePath = 'item';
|
|
203
224
|
break;
|
|
225
|
+
case 'LCSMaterial':
|
|
226
|
+
if (TypeDefaults.processLCSMaterialAsItem) {
|
|
227
|
+
typePath = 'item:material';
|
|
228
|
+
}
|
|
229
|
+
break;
|
|
204
230
|
case 'LCSProductSeasonLink':
|
|
205
231
|
case 'LCSSKUSeasonLink':
|
|
206
232
|
typePath = 'project-item';
|
|
@@ -229,7 +255,7 @@ export class TypeDefaults {
|
|
|
229
255
|
*/
|
|
230
256
|
|
|
231
257
|
static getDefaultIdentifierPropertiesFromObject(object): string[] {
|
|
232
|
-
const identifierProps = [];
|
|
258
|
+
const identifierProps: string[] = [];
|
|
233
259
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
234
260
|
|
|
235
261
|
switch (objectClass) {
|
|
@@ -237,6 +263,13 @@ export class TypeDefaults {
|
|
|
237
263
|
case 'LCSSKU':
|
|
238
264
|
identifierProps.push('itemNumber');
|
|
239
265
|
break;
|
|
266
|
+
case 'LCSMaterial':
|
|
267
|
+
if (TypeDefaults.processLCSMaterialAsItem) {
|
|
268
|
+
identifierProps.push('itemNumber');
|
|
269
|
+
} else {
|
|
270
|
+
identifierProps.push('name');
|
|
271
|
+
}
|
|
272
|
+
break;
|
|
240
273
|
case 'LCSSeason':
|
|
241
274
|
identifierProps.push('flexPLMSeasonName');
|
|
242
275
|
break;
|
|
@@ -247,7 +280,6 @@ export class TypeDefaults {
|
|
|
247
280
|
case 'LCSRevisableEntity':
|
|
248
281
|
case 'LCSLifecycleManaged':
|
|
249
282
|
case 'LCSLast':
|
|
250
|
-
case 'LCSMaterial':
|
|
251
283
|
identifierProps.push('name');
|
|
252
284
|
break;
|
|
253
285
|
}
|
|
@@ -265,7 +297,10 @@ export class TypeDefaults {
|
|
|
265
297
|
static getDefaultInformationalPropertiesFromObject(object): string[] {
|
|
266
298
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
267
299
|
let properties:string[] = [];
|
|
268
|
-
|
|
300
|
+
const itemClasses = TypeDefaults.processLCSMaterialAsItem
|
|
301
|
+
? ['LCSProduct', 'LCSMaterial']
|
|
302
|
+
: ['LCSProduct'];
|
|
303
|
+
if (itemClasses.includes(objectClass)) {
|
|
269
304
|
properties.push('name');
|
|
270
305
|
} else if ('LCSSKU' === objectClass) {
|
|
271
306
|
properties.push('optionName');
|