@contrail/flexplm 1.4.0-alpha.6954f61 → 1.5.0-alpha.6fc44c4
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 +28 -0
- package/lib/util/config-defaults.d.ts +18 -0
- package/lib/util/config-defaults.js +20 -15
- package/lib/util/config-defaults.spec.js +33 -0
- package/lib/util/data-converter.js +1 -1
- package/lib/util/data-converter.spec.js +41 -0
- package/lib/util/type-defaults.js +7 -4
- package/lib/util/type-defaults.spec.js +30 -0
- package/package.json +1 -1
- package/src/transform/identifier-conversion.spec.ts +29 -0
- package/src/transform/identifier-conversion.ts +1 -1
- package/src/util/config-defaults.spec.ts +38 -0
- package/src/util/config-defaults.ts +22 -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 +39 -0
- package/src/util/type-defaults.ts +8 -5
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
|
}
|
|
@@ -296,6 +296,34 @@ describe('getItemCriteriaFromObject', () => {
|
|
|
296
296
|
}
|
|
297
297
|
}
|
|
298
298
|
});
|
|
299
|
+
it('should return the item family criteria from the object -LCSMaterial', async () => {
|
|
300
|
+
const object = {
|
|
301
|
+
"flexPLMObjectClass": "LCSMaterial",
|
|
302
|
+
"flexPLMTypePath": "Material\\form",
|
|
303
|
+
"itemNumber": "MAT-100"
|
|
304
|
+
};
|
|
305
|
+
const criteriaObject = {
|
|
306
|
+
flexPLMObjectClass: 'LCSMaterial',
|
|
307
|
+
itemNumber: 'MAT-100',
|
|
308
|
+
flexPLMTypePath: 'Material\\form',
|
|
309
|
+
};
|
|
310
|
+
const resultsObject = {
|
|
311
|
+
roles: 'family',
|
|
312
|
+
itemNumber: 'MAT-100'
|
|
313
|
+
};
|
|
314
|
+
let getEntityValuesSpyOn = undefined;
|
|
315
|
+
try {
|
|
316
|
+
getEntityValuesSpyOn = jest.spyOn(dc, 'getEntityValues');
|
|
317
|
+
const result = await identifier_conversion_1.IdentifierConversion.getItemCriteriaFromObject(transformMapFile1, mapFileUtil, dc, object);
|
|
318
|
+
expect(getEntityValuesSpyOn).toHaveBeenCalledWith('LCSMaterial', criteriaObject, []);
|
|
319
|
+
expect(result).toEqual(resultsObject);
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
if (getEntityValuesSpyOn) {
|
|
323
|
+
getEntityValuesSpyOn.mockRestore();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
});
|
|
299
327
|
it('should return the item option criteria from the object -uniqueIdentifierA, uniqueIdentifierB', async () => {
|
|
300
328
|
const object = {
|
|
301
329
|
"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;
|
|
@@ -14,7 +14,23 @@ class ConfigDefaults {
|
|
|
14
14
|
else if (Object.keys(config).includes('itemPreDevelopmentLifecycleStages')) {
|
|
15
15
|
delete config['itemPreDevelopmentLifecycleStages'];
|
|
16
16
|
}
|
|
17
|
-
const
|
|
17
|
+
const configArr = [ConfigDefaults.getDefaultConfig()];
|
|
18
|
+
if (config.configFile) {
|
|
19
|
+
const fileConfig = await ConfigDefaults.getConfigFile(config.configFile);
|
|
20
|
+
configArr.push(fileConfig);
|
|
21
|
+
}
|
|
22
|
+
configArr.push(config);
|
|
23
|
+
const outputConfig = util_1.ObjectUtil.mergeDeep({}, ...configArr);
|
|
24
|
+
const uName = outputConfig.userName;
|
|
25
|
+
const pass = outputConfig.password;
|
|
26
|
+
outputConfig.userName = () => uName;
|
|
27
|
+
outputConfig.password = () => pass;
|
|
28
|
+
outputConfig['OOBvibeEventEndpoint'] = '/rfa/vibeiq/vibeEvents';
|
|
29
|
+
console.log('outputConfig: ' + JSON.stringify(outputConfig));
|
|
30
|
+
return outputConfig;
|
|
31
|
+
}
|
|
32
|
+
static getDefaultConfig() {
|
|
33
|
+
return {
|
|
18
34
|
urlContext: '/Windchill',
|
|
19
35
|
sendMode: {
|
|
20
36
|
ASYNC_PUBLISH_SEASON: 'vibeiqfile'
|
|
@@ -25,24 +41,13 @@ class ConfigDefaults {
|
|
|
25
41
|
LCSSeason: ['flexPLMSeasonName'],
|
|
26
42
|
LCSSKU: ['itemNumber']
|
|
27
43
|
},
|
|
44
|
+
LCSMaterial: {
|
|
45
|
+
processAsItem: false
|
|
46
|
+
},
|
|
28
47
|
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
29
48
|
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
30
49
|
payloadDefaultAsArray: true
|
|
31
50
|
};
|
|
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
51
|
}
|
|
47
52
|
static async getConfigFile(fileId) {
|
|
48
53
|
try {
|
|
@@ -296,6 +296,39 @@ describe('all tests', () => {
|
|
|
296
296
|
expect(config_defaults_1.ConfigDefaults.isPropertyTrue(1)).toBe(false);
|
|
297
297
|
});
|
|
298
298
|
});
|
|
299
|
+
describe('getDefaultConfig', () => {
|
|
300
|
+
it('returns LCSMaterial.processAsItem=false by default', () => {
|
|
301
|
+
const dc = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
302
|
+
expect(dc.LCSMaterial).toBeDefined();
|
|
303
|
+
expect(dc.LCSMaterial.processAsItem).toBe(false);
|
|
304
|
+
});
|
|
305
|
+
it('returns a fresh object each call (no shared reference)', () => {
|
|
306
|
+
const a = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
307
|
+
const b = config_defaults_1.ConfigDefaults.getDefaultConfig();
|
|
308
|
+
expect(a).not.toBe(b);
|
|
309
|
+
expect(a.LCSMaterial).not.toBe(b.LCSMaterial);
|
|
310
|
+
a.LCSMaterial.processAsItem = true;
|
|
311
|
+
expect(b.LCSMaterial.processAsItem).toBe(false);
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
describe('setConfigDefaults - LCSMaterial', () => {
|
|
315
|
+
const config = {
|
|
316
|
+
apiHost: 'http://test.com',
|
|
317
|
+
userName: 'vibeiq',
|
|
318
|
+
password: 'vibeiq'
|
|
319
|
+
};
|
|
320
|
+
it('LCSMaterial.processAsItem-get default', async () => {
|
|
321
|
+
const startConfig = Object.assign({}, config);
|
|
322
|
+
const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
|
|
323
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(false);
|
|
324
|
+
});
|
|
325
|
+
it('LCSMaterial.processAsItem-override', async () => {
|
|
326
|
+
const startConfig = Object.assign({}, config);
|
|
327
|
+
startConfig.LCSMaterial = { processAsItem: true };
|
|
328
|
+
const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
|
|
329
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(true);
|
|
330
|
+
});
|
|
331
|
+
});
|
|
299
332
|
describe('getConfigFile', () => {
|
|
300
333
|
beforeEach(() => {
|
|
301
334
|
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',
|
|
@@ -130,7 +130,7 @@ class TypeDefaults {
|
|
|
130
130
|
static getDefaultEntityClass(object) {
|
|
131
131
|
let entityClass = '';
|
|
132
132
|
let objectClass = TypeDefaults.getObjectClass(object);
|
|
133
|
-
if (['LCSProduct', 'LCSSKU'].includes(objectClass)) {
|
|
133
|
+
if (['LCSProduct', 'LCSSKU', 'LCSMaterial'].includes(objectClass)) {
|
|
134
134
|
entityClass = 'item';
|
|
135
135
|
}
|
|
136
136
|
else if (['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)) {
|
|
@@ -142,7 +142,7 @@ class TypeDefaults {
|
|
|
142
142
|
else if (['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
143
143
|
entityClass = 'assortment';
|
|
144
144
|
}
|
|
145
|
-
else if (['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast'
|
|
145
|
+
else if (['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast'].includes(objectClass)) {
|
|
146
146
|
entityClass = 'custom-entity';
|
|
147
147
|
}
|
|
148
148
|
if (entityClass === '')
|
|
@@ -157,6 +157,9 @@ class TypeDefaults {
|
|
|
157
157
|
case 'LCSSKU':
|
|
158
158
|
typePath = 'item';
|
|
159
159
|
break;
|
|
160
|
+
case 'LCSMaterial':
|
|
161
|
+
typePath = 'item:material';
|
|
162
|
+
break;
|
|
160
163
|
case 'LCSProductSeasonLink':
|
|
161
164
|
case 'LCSSKUSeasonLink':
|
|
162
165
|
typePath = 'project-item';
|
|
@@ -179,6 +182,7 @@ class TypeDefaults {
|
|
|
179
182
|
switch (objectClass) {
|
|
180
183
|
case 'LCSProduct':
|
|
181
184
|
case 'LCSSKU':
|
|
185
|
+
case 'LCSMaterial':
|
|
182
186
|
identifierProps.push('itemNumber');
|
|
183
187
|
break;
|
|
184
188
|
case 'LCSSeason':
|
|
@@ -191,7 +195,6 @@ class TypeDefaults {
|
|
|
191
195
|
case 'LCSRevisableEntity':
|
|
192
196
|
case 'LCSLifecycleManaged':
|
|
193
197
|
case 'LCSLast':
|
|
194
|
-
case 'LCSMaterial':
|
|
195
198
|
identifierProps.push('name');
|
|
196
199
|
break;
|
|
197
200
|
}
|
|
@@ -200,7 +203,7 @@ class TypeDefaults {
|
|
|
200
203
|
static getDefaultInformationalPropertiesFromObject(object) {
|
|
201
204
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
202
205
|
let properties = [];
|
|
203
|
-
if ('LCSProduct'
|
|
206
|
+
if (['LCSProduct', 'LCSMaterial'].includes(objectClass)) {
|
|
204
207
|
properties.push('name');
|
|
205
208
|
}
|
|
206
209
|
else if ('LCSSKU' === objectClass) {
|
|
@@ -369,6 +369,13 @@ 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', () => {
|
|
373
|
+
const object = {
|
|
374
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
375
|
+
};
|
|
376
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
377
|
+
expect(entityClass).toBe('item');
|
|
378
|
+
});
|
|
372
379
|
});
|
|
373
380
|
describe('getDefaultEntityTypePath', () => {
|
|
374
381
|
it('LCSProduct', () => {
|
|
@@ -420,6 +427,13 @@ describe('Type Defaults', () => {
|
|
|
420
427
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
421
428
|
expect(typePath).toBe('assortment');
|
|
422
429
|
});
|
|
430
|
+
it('LCSMaterial', () => {
|
|
431
|
+
const object = {
|
|
432
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
433
|
+
};
|
|
434
|
+
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
435
|
+
expect(typePath).toBe('item:material');
|
|
436
|
+
});
|
|
423
437
|
});
|
|
424
438
|
describe('getDefaultIdentifierPropertiesFromObject', () => {
|
|
425
439
|
it('LCSProduct', () => {
|
|
@@ -478,6 +492,14 @@ describe('Type Defaults', () => {
|
|
|
478
492
|
expect(defaultIdentifiers).toContain('name');
|
|
479
493
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
480
494
|
});
|
|
495
|
+
it('LCSMaterial', () => {
|
|
496
|
+
const object = {
|
|
497
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
498
|
+
};
|
|
499
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
500
|
+
expect(defaultIdentifiers).toContain('itemNumber');
|
|
501
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
502
|
+
});
|
|
481
503
|
});
|
|
482
504
|
describe('getDefaultInformationalPropertiesFromObject', () => {
|
|
483
505
|
it('LCSProduct', () => {
|
|
@@ -512,5 +534,13 @@ describe('Type Defaults', () => {
|
|
|
512
534
|
expect(defaultIdentifiers).toContain('name');
|
|
513
535
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
514
536
|
});
|
|
537
|
+
it('LCSMaterial', () => {
|
|
538
|
+
const object = {
|
|
539
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
540
|
+
};
|
|
541
|
+
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
542
|
+
expect(defaultIdentifiers).toContain('name');
|
|
543
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
544
|
+
});
|
|
515
545
|
});
|
|
516
546
|
});
|
package/package.json
CHANGED
|
@@ -309,6 +309,35 @@ describe('getItemCriteriaFromObject', () => {
|
|
|
309
309
|
}
|
|
310
310
|
});
|
|
311
311
|
|
|
312
|
+
it('should return the item family criteria from the object -LCSMaterial', async () => {
|
|
313
|
+
const object = {
|
|
314
|
+
"flexPLMObjectClass": "LCSMaterial",
|
|
315
|
+
"flexPLMTypePath": "Material\\form",
|
|
316
|
+
"itemNumber": "MAT-100"
|
|
317
|
+
};
|
|
318
|
+
const criteriaObject = {
|
|
319
|
+
flexPLMObjectClass: 'LCSMaterial',
|
|
320
|
+
itemNumber: 'MAT-100',
|
|
321
|
+
flexPLMTypePath: 'Material\\form',
|
|
322
|
+
};
|
|
323
|
+
const resultsObject = {
|
|
324
|
+
roles: 'family',
|
|
325
|
+
itemNumber: 'MAT-100'
|
|
326
|
+
};
|
|
327
|
+
let getEntityValuesSpyOn = undefined
|
|
328
|
+
try {
|
|
329
|
+
|
|
330
|
+
getEntityValuesSpyOn = jest.spyOn(dc, 'getEntityValues');
|
|
331
|
+
const result = await IdentifierConversion.getItemCriteriaFromObject(transformMapFile1, mapFileUtil, dc, object);
|
|
332
|
+
expect(getEntityValuesSpyOn).toHaveBeenCalledWith('LCSMaterial', criteriaObject, []);
|
|
333
|
+
expect(result).toEqual(resultsObject);
|
|
334
|
+
} finally {
|
|
335
|
+
if (getEntityValuesSpyOn) {
|
|
336
|
+
getEntityValuesSpyOn.mockRestore();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
|
|
312
341
|
it('should return the item option criteria from the object -uniqueIdentifierA, uniqueIdentifierB', async () => {
|
|
313
342
|
const object = {
|
|
314
343
|
"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;
|
|
@@ -356,6 +356,44 @@ describe('all tests', () => {
|
|
|
356
356
|
});
|
|
357
357
|
});
|
|
358
358
|
|
|
359
|
+
describe('getDefaultConfig', () => {
|
|
360
|
+
it('returns LCSMaterial.processAsItem=false by default', () => {
|
|
361
|
+
const dc: any = ConfigDefaults.getDefaultConfig();
|
|
362
|
+
expect(dc.LCSMaterial).toBeDefined();
|
|
363
|
+
expect(dc.LCSMaterial.processAsItem).toBe(false);
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
it('returns a fresh object each call (no shared reference)', () => {
|
|
367
|
+
const a: any = ConfigDefaults.getDefaultConfig();
|
|
368
|
+
const b: any = ConfigDefaults.getDefaultConfig();
|
|
369
|
+
expect(a).not.toBe(b);
|
|
370
|
+
expect(a.LCSMaterial).not.toBe(b.LCSMaterial);
|
|
371
|
+
a.LCSMaterial.processAsItem = true;
|
|
372
|
+
expect(b.LCSMaterial.processAsItem).toBe(false);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
describe('setConfigDefaults - LCSMaterial', () => {
|
|
377
|
+
const config = {
|
|
378
|
+
apiHost: 'http://test.com',
|
|
379
|
+
userName: 'vibeiq',
|
|
380
|
+
password: 'vibeiq'
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
it('LCSMaterial.processAsItem-get default', async () => {
|
|
384
|
+
const startConfig = Object.assign({}, config);
|
|
385
|
+
const fcConfig: any = await ConfigDefaults.setConfigDefaults(startConfig);
|
|
386
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(false);
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
it('LCSMaterial.processAsItem-override', async () => {
|
|
390
|
+
const startConfig: any = Object.assign({}, config);
|
|
391
|
+
startConfig.LCSMaterial = { processAsItem: true };
|
|
392
|
+
const fcConfig: any = await ConfigDefaults.setConfigDefaults(startConfig);
|
|
393
|
+
expect(fcConfig.LCSMaterial.processAsItem).toBe(true);
|
|
394
|
+
});
|
|
395
|
+
});
|
|
396
|
+
|
|
359
397
|
describe('getConfigFile', () => {
|
|
360
398
|
beforeEach(() => {
|
|
361
399
|
ConfigDefaults.clearConfigCache();
|
|
@@ -18,22 +18,7 @@ export class ConfigDefaults {
|
|
|
18
18
|
delete config['itemPreDevelopmentLifecycleStages'];
|
|
19
19
|
}
|
|
20
20
|
|
|
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];
|
|
21
|
+
const configArr = [ConfigDefaults.getDefaultConfig()];
|
|
37
22
|
|
|
38
23
|
if(config.configFile){
|
|
39
24
|
const fileConfig = await ConfigDefaults.getConfigFile(config.configFile);
|
|
@@ -53,6 +38,27 @@ export class ConfigDefaults {
|
|
|
53
38
|
return outputConfig as FCConfig;
|
|
54
39
|
}
|
|
55
40
|
|
|
41
|
+
static getDefaultConfig() {
|
|
42
|
+
return {
|
|
43
|
+
urlContext: '/Windchill',
|
|
44
|
+
sendMode: {
|
|
45
|
+
ASYNC_PUBLISH_SEASON: 'vibeiqfile'
|
|
46
|
+
},
|
|
47
|
+
itemPreDevelopmentLifecycleStages: ['concept'],
|
|
48
|
+
identifierAtts: {
|
|
49
|
+
LCSProduct: ['itemNumber'],
|
|
50
|
+
LCSSeason: ['flexPLMSeasonName'],
|
|
51
|
+
LCSSKU: ['itemNumber']
|
|
52
|
+
},
|
|
53
|
+
LCSMaterial: {
|
|
54
|
+
processAsItem: false
|
|
55
|
+
},
|
|
56
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
57
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
58
|
+
payloadDefaultAsArray: true
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
56
62
|
static async getConfigFile(fileId: string) {
|
|
57
63
|
try {
|
|
58
64
|
|
|
@@ -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,16 @@ describe('Type Defaults', () =>{
|
|
|
485
485
|
expect(entityClass).toBe('custom-entity');
|
|
486
486
|
});
|
|
487
487
|
|
|
488
|
+
it('item - LCSMaterial', () =>{
|
|
489
|
+
const object = {
|
|
490
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
494
|
+
|
|
495
|
+
expect(entityClass).toBe('item');
|
|
496
|
+
});
|
|
497
|
+
|
|
488
498
|
});//getDefaultEntityClass
|
|
489
499
|
|
|
490
500
|
describe('getDefaultEntityTypePath', () =>{
|
|
@@ -549,6 +559,15 @@ describe('Type Defaults', () =>{
|
|
|
549
559
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
550
560
|
expect(typePath).toBe('assortment');
|
|
551
561
|
});
|
|
562
|
+
|
|
563
|
+
it('LCSMaterial', () =>{
|
|
564
|
+
const object = {
|
|
565
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
566
|
+
};
|
|
567
|
+
|
|
568
|
+
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
569
|
+
expect(typePath).toBe('item:material');
|
|
570
|
+
});
|
|
552
571
|
});//getDefaultEntityTypePath
|
|
553
572
|
|
|
554
573
|
describe('getDefaultIdentifierPropertiesFromObject', () =>{
|
|
@@ -622,6 +641,16 @@ describe('Type Defaults', () =>{
|
|
|
622
641
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
623
642
|
});
|
|
624
643
|
|
|
644
|
+
it('LCSMaterial', () =>{
|
|
645
|
+
const object = {
|
|
646
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
647
|
+
};
|
|
648
|
+
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
649
|
+
|
|
650
|
+
expect(defaultIdentifiers).toContain('itemNumber');
|
|
651
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
652
|
+
});
|
|
653
|
+
|
|
625
654
|
});//getDefaultIdentifierPropertiesFromObject
|
|
626
655
|
|
|
627
656
|
describe('getDefaultInformationalPropertiesFromObject', () =>{
|
|
@@ -665,5 +694,15 @@ describe('Type Defaults', () =>{
|
|
|
665
694
|
expect(defaultIdentifiers).toHaveLength(1);
|
|
666
695
|
});
|
|
667
696
|
|
|
697
|
+
it('LCSMaterial', () =>{
|
|
698
|
+
const object = {
|
|
699
|
+
flexPLMObjectClass: 'LCSMaterial'
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
703
|
+
expect(defaultIdentifiers).toContain('name');
|
|
704
|
+
expect(defaultIdentifiers).toHaveLength(1);
|
|
705
|
+
});
|
|
706
|
+
|
|
668
707
|
});//getDefaultInformationalPropertiesFromObject
|
|
669
708
|
});
|
|
@@ -168,7 +168,7 @@ export class TypeDefaults {
|
|
|
168
168
|
static getDefaultEntityClass(object): string {
|
|
169
169
|
let entityClass = '';
|
|
170
170
|
let objectClass = TypeDefaults.getObjectClass(object);
|
|
171
|
-
if(['LCSProduct', 'LCSSKU'].includes(objectClass)){
|
|
171
|
+
if(['LCSProduct', 'LCSSKU', 'LCSMaterial'].includes(objectClass)){
|
|
172
172
|
entityClass = 'item';
|
|
173
173
|
}else if(['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)){
|
|
174
174
|
entityClass = 'project-item'
|
|
@@ -176,7 +176,7 @@ export class TypeDefaults {
|
|
|
176
176
|
entityClass = 'color';
|
|
177
177
|
} else if(['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
178
178
|
entityClass = 'assortment';
|
|
179
|
-
} else if(['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast'
|
|
179
|
+
} else if(['LCSRevisableEntity', 'LCSLifecycleManaged', 'LCSLast'].includes(objectClass)) {
|
|
180
180
|
entityClass = 'custom-entity';
|
|
181
181
|
}
|
|
182
182
|
|
|
@@ -201,6 +201,9 @@ export class TypeDefaults {
|
|
|
201
201
|
case 'LCSSKU':
|
|
202
202
|
typePath = 'item';
|
|
203
203
|
break;
|
|
204
|
+
case 'LCSMaterial':
|
|
205
|
+
typePath = 'item:material';
|
|
206
|
+
break;
|
|
204
207
|
case 'LCSProductSeasonLink':
|
|
205
208
|
case 'LCSSKUSeasonLink':
|
|
206
209
|
typePath = 'project-item';
|
|
@@ -229,12 +232,13 @@ export class TypeDefaults {
|
|
|
229
232
|
*/
|
|
230
233
|
|
|
231
234
|
static getDefaultIdentifierPropertiesFromObject(object): string[] {
|
|
232
|
-
const identifierProps = [];
|
|
235
|
+
const identifierProps: string[] = [];
|
|
233
236
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
234
237
|
|
|
235
238
|
switch (objectClass) {
|
|
236
239
|
case 'LCSProduct':
|
|
237
240
|
case 'LCSSKU':
|
|
241
|
+
case 'LCSMaterial':
|
|
238
242
|
identifierProps.push('itemNumber');
|
|
239
243
|
break;
|
|
240
244
|
case 'LCSSeason':
|
|
@@ -247,7 +251,6 @@ export class TypeDefaults {
|
|
|
247
251
|
case 'LCSRevisableEntity':
|
|
248
252
|
case 'LCSLifecycleManaged':
|
|
249
253
|
case 'LCSLast':
|
|
250
|
-
case 'LCSMaterial':
|
|
251
254
|
identifierProps.push('name');
|
|
252
255
|
break;
|
|
253
256
|
}
|
|
@@ -265,7 +268,7 @@ export class TypeDefaults {
|
|
|
265
268
|
static getDefaultInformationalPropertiesFromObject(object): string[] {
|
|
266
269
|
const objectClass = TypeDefaults.getObjectClass(object);
|
|
267
270
|
let properties:string[] = [];
|
|
268
|
-
if ('LCSProduct'
|
|
271
|
+
if (['LCSProduct', 'LCSMaterial'].includes(objectClass)) {
|
|
269
272
|
properties.push('name');
|
|
270
273
|
} else if ('LCSSKU' === objectClass) {
|
|
271
274
|
properties.push('optionName');
|