@contrail/flexplm 1.1.15 → 1.1.17
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/lib/entity-processor/base-entity-processor.d.ts +3 -1
- package/lib/entity-processor/base-entity-processor.js +18 -11
- package/lib/util/data-converter.d.ts +2 -0
- package/lib/util/data-converter.js +43 -20
- package/lib/util/type-conversion-utils.js +1 -1
- package/lib/util/type-conversion-utils.spec.js +11 -11
- package/lib/util/type-defaults.js +7 -1
- package/lib/util/type-defaults.spec.js +47 -19
- package/lib/util/type-utils.d.ts +1 -0
- package/lib/util/type-utils.js +10 -0
- package/package.json +1 -1
- package/src/entity-processor/base-entity-processor.ts +26 -12
- package/src/util/data-converter.ts +64 -21
- package/src/util/type-conversion-utils.spec.ts +11 -11
- package/src/util/type-conversion-utils.ts +1 -1
- package/src/util/type-defaults.spec.ts +60 -20
- package/src/util/type-defaults.ts +5 -1
- package/src/util/type-utils.ts +18 -0
|
@@ -16,13 +16,15 @@ export declare abstract class BaseEntityProcessor {
|
|
|
16
16
|
protected entities: any;
|
|
17
17
|
constructor(config: FCConfig, dc: DataConverter, mapFileUtil: MapFileUtil, baseType: string);
|
|
18
18
|
inbound(event: EntityPayloadType): Promise<any>;
|
|
19
|
-
|
|
19
|
+
handleIncomingUpsert(event: EntityPayloadType): Promise<any>;
|
|
20
20
|
handleIncomingDelete(event: any): Promise<void>;
|
|
21
21
|
getTransformedData(event: any): Promise<any>;
|
|
22
22
|
getUpdatesForEntity(entity: any, inboundData: any): Promise<object>;
|
|
23
23
|
getVibeOwningKeys(entity: any): Promise<any[]>;
|
|
24
|
+
createEntity(entityName: any, changes: any): Promise<any>;
|
|
24
25
|
updateEntity(entityName: any, entity: any, diffs: any): Promise<any>;
|
|
25
26
|
protected abstract getIncomingEntity(event: any, inboundData: any): Promise<IncomingEntityResponse>;
|
|
27
|
+
protected abstract getCreateEntity(inboundData: any): Promise<IncomingEntityResponse>;
|
|
26
28
|
outbound(event: any): Promise<void | import("../interfaces/interfaces").FlexPLMResponseData>;
|
|
27
29
|
handleOutgoingUpsert(entityType: any, event: any): Promise<import("../interfaces/interfaces").FlexPLMResponseData>;
|
|
28
30
|
handleOutgoingDelete(entityType: any, event: any): Promise<void>;
|
|
@@ -25,7 +25,7 @@ class BaseEntityProcessor {
|
|
|
25
25
|
console.log(`inbound entity: ${eventType}:${event.objectClass}`);
|
|
26
26
|
switch (eventType) {
|
|
27
27
|
case 'PERSIST':
|
|
28
|
-
return await this.
|
|
28
|
+
return await this.handleIncomingUpsert(event);
|
|
29
29
|
case 'DELETE':
|
|
30
30
|
return await this.handleIncomingDelete(event);
|
|
31
31
|
default:
|
|
@@ -36,7 +36,7 @@ class BaseEntityProcessor {
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
|
-
async
|
|
39
|
+
async handleIncomingUpsert(event) {
|
|
40
40
|
const inboundData = await this.getTransformedData(event);
|
|
41
41
|
const incomingEntityResponse = await this.getIncomingEntity(event, inboundData);
|
|
42
42
|
if (incomingEntityResponse.earlyReturn) {
|
|
@@ -44,12 +44,11 @@ class BaseEntityProcessor {
|
|
|
44
44
|
}
|
|
45
45
|
const entity = incomingEntityResponse.entity;
|
|
46
46
|
if (!entity) {
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
};
|
|
47
|
+
const createEntityResponse = await this.getCreateEntity(inboundData);
|
|
48
|
+
if (createEntityResponse.earlyReturn) {
|
|
49
|
+
return createEntityResponse.earlyReturn;
|
|
50
|
+
}
|
|
51
|
+
return this.createEntity(this.baseType, createEntityResponse.entity);
|
|
53
52
|
}
|
|
54
53
|
const diffs = await this.getUpdatesForEntity(entity, inboundData);
|
|
55
54
|
if (Object.getOwnPropertyNames(diffs).length == 0) {
|
|
@@ -68,8 +67,8 @@ class BaseEntityProcessor {
|
|
|
68
67
|
async getTransformedData(event) {
|
|
69
68
|
let inboundData = event.data;
|
|
70
69
|
console.debug('inboundData: ' + JSON.stringify(inboundData));
|
|
71
|
-
const
|
|
72
|
-
inboundData = await map_utils_1.MapUtil.applyTransformMap(this.transformMapFile, this.mapFileUtil, inboundData,
|
|
70
|
+
const mapKey = await type_conversion_utils_1.TypeConversionUtils.getMapKeyFromObject(this.transformMapFile, this.mapFileUtil, inboundData, type_conversion_utils_1.TypeConversionUtils.FLEX2VIBE_DIRECTION);
|
|
71
|
+
inboundData = await map_utils_1.MapUtil.applyTransformMap(this.transformMapFile, this.mapFileUtil, inboundData, mapKey, type_conversion_utils_1.TypeConversionUtils.FLEX2VIBE_DIRECTION);
|
|
73
72
|
console.debug('Transformed-inboundData: ' + JSON.stringify(inboundData));
|
|
74
73
|
return inboundData;
|
|
75
74
|
}
|
|
@@ -88,7 +87,7 @@ class BaseEntityProcessor {
|
|
|
88
87
|
}
|
|
89
88
|
async getVibeOwningKeys(entity) {
|
|
90
89
|
let vibeOwningKeys = [];
|
|
91
|
-
if (this.transformMapFile) {
|
|
90
|
+
if (this.transformMapFile && entity) {
|
|
92
91
|
const mapKey = await type_conversion_utils_1.TypeConversionUtils.getMapKey(this.transformMapFile, this.mapFileUtil, entity, type_conversion_utils_1.TypeConversionUtils.VIBE2FLEX_DIRECTION);
|
|
93
92
|
const mapSection = await map_utils_1.MapUtil.getFullMapSection(this.transformMapFile, this.mapFileUtil, mapKey);
|
|
94
93
|
vibeOwningKeys = mapSection?.vibeOwningKeys || [];
|
|
@@ -96,6 +95,14 @@ class BaseEntityProcessor {
|
|
|
96
95
|
console.debug('vibeOwningKeys: ' + vibeOwningKeys);
|
|
97
96
|
return vibeOwningKeys;
|
|
98
97
|
}
|
|
98
|
+
async createEntity(entityName, changes) {
|
|
99
|
+
const options = {
|
|
100
|
+
entityName: entityName,
|
|
101
|
+
object: changes,
|
|
102
|
+
};
|
|
103
|
+
console.log("options: " + JSON.stringify(options));
|
|
104
|
+
return await new sdk_1.Entities().create(options);
|
|
105
|
+
}
|
|
99
106
|
async updateEntity(entityName, entity, diffs) {
|
|
100
107
|
const options = {
|
|
101
108
|
entityName: entityName,
|
|
@@ -21,6 +21,8 @@ export declare class DataConverter {
|
|
|
21
21
|
setEnumerationKeys(prop: any, nd: any, matchByDisplay: any): any;
|
|
22
22
|
getPersistableChanges(entity: object, changes: object): object;
|
|
23
23
|
setUserListValue(prop: any, nd: any): Promise<any>;
|
|
24
|
+
getUserByEmail(nd: any): Promise<any>;
|
|
24
25
|
processGroupMemberCheck(prop: any, userEmail: any): Promise<void>;
|
|
25
26
|
getUserListValue(prop: any, newData: any): Promise<any>;
|
|
27
|
+
getUserById(userId: any): Promise<any>;
|
|
26
28
|
}
|
|
@@ -192,7 +192,7 @@ class DataConverter {
|
|
|
192
192
|
}
|
|
193
193
|
async setEntityValues(entity, data, keysToSkip = []) {
|
|
194
194
|
const type = await this.typeUtils.getTypeById(entity.typeId);
|
|
195
|
-
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'workspaceId']);
|
|
195
|
+
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'typePath', 'workspaceId']);
|
|
196
196
|
let typeProps = this.typeUtils.filterTypeProperties(type, entity);
|
|
197
197
|
typeProps = typeProps.filter(prop => !keysToSkip.includes(prop['slug']));
|
|
198
198
|
const dataKeys = Object.getOwnPropertyNames(data);
|
|
@@ -210,7 +210,7 @@ class DataConverter {
|
|
|
210
210
|
}
|
|
211
211
|
async getEntityValues(objectClass, data, keysToSkip = []) {
|
|
212
212
|
const entityValues = {};
|
|
213
|
-
const tco = this.typeUtils.
|
|
213
|
+
const tco = await this.typeUtils.getEntityTypeClientOptionsUsingMapping(this.transformMapFile, this.mapFileUtil, data);
|
|
214
214
|
const type = await this.typeUtils.getByRootAndPath(tco);
|
|
215
215
|
const typePath = type['typePath'];
|
|
216
216
|
if (typePath && (typePath.startsWith('item') || typePath.startsWith('project-item'))) {
|
|
@@ -332,17 +332,28 @@ class DataConverter {
|
|
|
332
332
|
await this.processGroupMemberCheck(prop, nd.email);
|
|
333
333
|
return this.userRefCache[nd.email];
|
|
334
334
|
}
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const result = entities.find(element => element['userEmail'] === nd.email);
|
|
340
|
-
const value = (result) ? result.id : undefined;
|
|
341
|
-
if (value) {
|
|
342
|
-
this.userRefCache[nd.email] = value;
|
|
335
|
+
const user = await this.getUserByEmail(nd);
|
|
336
|
+
const userId = (user) ? user.id : undefined;
|
|
337
|
+
if (userId) {
|
|
338
|
+
this.userRefCache[nd.email] = userId;
|
|
343
339
|
await this.processGroupMemberCheck(prop, nd.email);
|
|
344
340
|
}
|
|
345
|
-
return
|
|
341
|
+
return userId;
|
|
342
|
+
}
|
|
343
|
+
async getUserByEmail(nd) {
|
|
344
|
+
let userOrg = undefined;
|
|
345
|
+
let count = 0;
|
|
346
|
+
let size = 0;
|
|
347
|
+
const entities = new sdk_1.Entities();
|
|
348
|
+
const getOptionsCriteria = {
|
|
349
|
+
entityName: 'user-org',
|
|
350
|
+
take: 1000
|
|
351
|
+
};
|
|
352
|
+
do {
|
|
353
|
+
const userBatch = await entities.get(getOptionsCriteria);
|
|
354
|
+
userOrg = userBatch.find(uo => uo?.userEmail === nd?.email);
|
|
355
|
+
} while (!userOrg && size == getOptionsCriteria.take && count < 15);
|
|
356
|
+
return userOrg?.user;
|
|
346
357
|
}
|
|
347
358
|
async processGroupMemberCheck(prop, userEmail) {
|
|
348
359
|
let arrUserList = [];
|
|
@@ -381,20 +392,32 @@ class DataConverter {
|
|
|
381
392
|
}
|
|
382
393
|
return this.userRefCache[entityId];
|
|
383
394
|
}
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
firstName: entities.first,
|
|
391
|
-
lastName: entities.last,
|
|
392
|
-
isSsoUser: entities.isSsoUser,
|
|
395
|
+
const user = await this.getUserById(entityId);
|
|
396
|
+
const value = (user) ? {
|
|
397
|
+
email: user.email,
|
|
398
|
+
firstName: user.first,
|
|
399
|
+
lastName: user.last,
|
|
400
|
+
isSsoUser: user.isSsoUser,
|
|
393
401
|
} : undefined;
|
|
394
402
|
if (value) {
|
|
395
403
|
this.userRefCache[entityId] = value;
|
|
396
404
|
}
|
|
397
405
|
return value;
|
|
398
406
|
}
|
|
407
|
+
async getUserById(userId) {
|
|
408
|
+
let userOrg = undefined;
|
|
409
|
+
let count = 0;
|
|
410
|
+
let size = 0;
|
|
411
|
+
const entities = new sdk_1.Entities();
|
|
412
|
+
const getOptionsCriteria = {
|
|
413
|
+
entityName: 'user-org',
|
|
414
|
+
take: 1000
|
|
415
|
+
};
|
|
416
|
+
do {
|
|
417
|
+
const userBatch = await entities.get(getOptionsCriteria);
|
|
418
|
+
userOrg = userBatch.find(uo => uo?.user?.id === userId);
|
|
419
|
+
} while (!userOrg && size == getOptionsCriteria.take && count < 15);
|
|
420
|
+
return userOrg?.user;
|
|
421
|
+
}
|
|
399
422
|
}
|
|
400
423
|
exports.DataConverter = DataConverter;
|
|
@@ -290,7 +290,7 @@ describe('conversion-utils', () => {
|
|
|
290
290
|
it('uses mapping-catName', async () => {
|
|
291
291
|
const expectedClass = 'custom-entity';
|
|
292
292
|
const object = {
|
|
293
|
-
|
|
293
|
+
flexPLMObjectClass: 'LCSLast',
|
|
294
294
|
flexPLMTypePath: 'Last\\catName'
|
|
295
295
|
};
|
|
296
296
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -308,7 +308,7 @@ describe('conversion-utils', () => {
|
|
|
308
308
|
it('uses default-noMap', async () => {
|
|
309
309
|
const expectedClass = 'color';
|
|
310
310
|
const entity = {
|
|
311
|
-
|
|
311
|
+
flexPLMObjectClass: 'LCSColor',
|
|
312
312
|
flexPLMTypePath: 'Color'
|
|
313
313
|
};
|
|
314
314
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -341,7 +341,7 @@ describe('conversion-utils', () => {
|
|
|
341
341
|
it('uses mapping-catName', async () => {
|
|
342
342
|
const expectedTypePath = 'custom-entity:catName';
|
|
343
343
|
const entity = {
|
|
344
|
-
|
|
344
|
+
flexPLMObjectClass: 'LCSLast',
|
|
345
345
|
flexPLMTypePath: 'Last\\catName'
|
|
346
346
|
};
|
|
347
347
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -359,7 +359,7 @@ describe('conversion-utils', () => {
|
|
|
359
359
|
it('uses default-noMap', async () => {
|
|
360
360
|
const expectedTypePath = 'color';
|
|
361
361
|
const entity = {
|
|
362
|
-
|
|
362
|
+
flexPLMObjectClass: 'LCSColor',
|
|
363
363
|
flexPLMTypePath: 'Color'
|
|
364
364
|
};
|
|
365
365
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -393,7 +393,7 @@ describe('conversion-utils', () => {
|
|
|
393
393
|
it('uses mapping-catName', async () => {
|
|
394
394
|
const properties = ['catName', 'catNumber'];
|
|
395
395
|
const object = {
|
|
396
|
-
|
|
396
|
+
flexPLMObjectClass: 'LCSLast',
|
|
397
397
|
flexPLMTypePath: 'Last\\catName'
|
|
398
398
|
};
|
|
399
399
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -412,7 +412,7 @@ describe('conversion-utils', () => {
|
|
|
412
412
|
it('uses default-noMap', async () => {
|
|
413
413
|
const properties = ['itemNumber'];
|
|
414
414
|
const object = {
|
|
415
|
-
|
|
415
|
+
flexPLMObjectClass: 'LCSProduct',
|
|
416
416
|
flexPLMTypePath: 'Product'
|
|
417
417
|
};
|
|
418
418
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -447,7 +447,7 @@ describe('conversion-utils', () => {
|
|
|
447
447
|
it('uses mapping-catName', async () => {
|
|
448
448
|
const properties = ['longName'];
|
|
449
449
|
const object = {
|
|
450
|
-
|
|
450
|
+
flexPLMObjectClass: 'LCSLast',
|
|
451
451
|
flexPLMTypePath: 'Last\\catName'
|
|
452
452
|
};
|
|
453
453
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -466,7 +466,7 @@ describe('conversion-utils', () => {
|
|
|
466
466
|
it('uses default-noMap', async () => {
|
|
467
467
|
const properties = ['optionName', 'description'];
|
|
468
468
|
const object = {
|
|
469
|
-
|
|
469
|
+
flexPLMObjectClass: 'LCSSKU',
|
|
470
470
|
typePath: 'Product'
|
|
471
471
|
};
|
|
472
472
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -495,7 +495,7 @@ describe('conversion-utils', () => {
|
|
|
495
495
|
return mapping;
|
|
496
496
|
});
|
|
497
497
|
const object = {
|
|
498
|
-
|
|
498
|
+
flexPLMObjectClass: 'LCSRevisableEntity',
|
|
499
499
|
flexPLMTypePath: 'Revisable Entity\\packaging'
|
|
500
500
|
};
|
|
501
501
|
const expectedMapKey = 'packaging';
|
|
@@ -513,7 +513,7 @@ describe('conversion-utils', () => {
|
|
|
513
513
|
return mapping;
|
|
514
514
|
});
|
|
515
515
|
const object = {
|
|
516
|
-
|
|
516
|
+
flexPLMObjectClass: 'LCSRevisableEntity',
|
|
517
517
|
flexPLMTypePath: 'Revisable Entity\\prefix'
|
|
518
518
|
};
|
|
519
519
|
const expectedMapKey = 'prefix';
|
|
@@ -531,7 +531,7 @@ describe('conversion-utils', () => {
|
|
|
531
531
|
return mapping;
|
|
532
532
|
});
|
|
533
533
|
const object = {
|
|
534
|
-
|
|
534
|
+
flexPLMObjectClass: 'LCSColor',
|
|
535
535
|
flexPLMTypePath: 'Color'
|
|
536
536
|
};
|
|
537
537
|
const expectedMapKey = 'LCSColor';
|
|
@@ -136,6 +136,12 @@ class TypeDefaults {
|
|
|
136
136
|
else if ('LCSColor' === objectClass) {
|
|
137
137
|
entityClass = 'color';
|
|
138
138
|
}
|
|
139
|
+
else if (['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
140
|
+
entityClass = 'assortment';
|
|
141
|
+
}
|
|
142
|
+
else if (['LCSRevisableEntity', 'LCSLifecycleManaged'].includes(objectClass)) {
|
|
143
|
+
entityClass = 'custom-entity';
|
|
144
|
+
}
|
|
139
145
|
return entityClass;
|
|
140
146
|
}
|
|
141
147
|
static getDefaultEntityTypePath(object) {
|
|
@@ -191,7 +197,7 @@ class TypeDefaults {
|
|
|
191
197
|
return properties;
|
|
192
198
|
}
|
|
193
199
|
static getObjectClass(object) {
|
|
194
|
-
return (object) ? object['
|
|
200
|
+
return (object) ? object['flexPLMObjectClass'] : '';
|
|
195
201
|
}
|
|
196
202
|
}
|
|
197
203
|
exports.TypeDefaults = TypeDefaults;
|
|
@@ -308,58 +308,86 @@ describe('Type Defaults', () => {
|
|
|
308
308
|
describe('getDefaultEntityClass', () => {
|
|
309
309
|
it('item - LCSProduct', () => {
|
|
310
310
|
const object = {
|
|
311
|
-
|
|
311
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
312
312
|
};
|
|
313
313
|
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
314
314
|
expect(entityClass).toBe('item');
|
|
315
315
|
});
|
|
316
316
|
it('item - LCSSKU', () => {
|
|
317
317
|
const object = {
|
|
318
|
-
|
|
318
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
319
319
|
};
|
|
320
320
|
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
321
321
|
expect(entityClass).toBe('item');
|
|
322
322
|
});
|
|
323
323
|
it('color - LCSColor', () => {
|
|
324
324
|
const object = {
|
|
325
|
-
|
|
325
|
+
flexPLMObjectClass: 'LCSColor'
|
|
326
326
|
};
|
|
327
327
|
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
328
328
|
expect(entityClass).toBe('color');
|
|
329
329
|
});
|
|
330
|
+
it('assortment - LCSSeason', () => {
|
|
331
|
+
const object = {
|
|
332
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
333
|
+
};
|
|
334
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
335
|
+
expect(entityClass).toBe('assortment');
|
|
336
|
+
});
|
|
337
|
+
it('assortment - SeasonGroup', () => {
|
|
338
|
+
const object = {
|
|
339
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
340
|
+
};
|
|
341
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
342
|
+
expect(entityClass).toBe('assortment');
|
|
343
|
+
});
|
|
344
|
+
it('custom-entity - LCSRevisableEntity', () => {
|
|
345
|
+
const object = {
|
|
346
|
+
flexPLMObjectClass: 'LCSRevisableEntity'
|
|
347
|
+
};
|
|
348
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
349
|
+
expect(entityClass).toBe('custom-entity');
|
|
350
|
+
});
|
|
351
|
+
it('custom-entity - LCSLifecycleManaged', () => {
|
|
352
|
+
const object = {
|
|
353
|
+
flexPLMObjectClass: 'LCSLifecycleManaged'
|
|
354
|
+
};
|
|
355
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
356
|
+
expect(entityClass).toBe('custom-entity');
|
|
357
|
+
});
|
|
330
358
|
});
|
|
331
359
|
describe('getDefaultEntityTypePath', () => {
|
|
332
360
|
it('LCSProduct', () => {
|
|
333
361
|
const object = {
|
|
334
|
-
|
|
362
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
335
363
|
};
|
|
336
364
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
337
365
|
expect(typePath).toBe('item');
|
|
338
366
|
});
|
|
339
367
|
it('LCSSKU', () => {
|
|
340
368
|
const object = {
|
|
341
|
-
|
|
369
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
342
370
|
};
|
|
343
371
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
344
372
|
expect(typePath).toBe('item');
|
|
345
373
|
});
|
|
346
374
|
it('LCSProductSeasonLink', () => {
|
|
347
375
|
const object = {
|
|
348
|
-
|
|
376
|
+
flexPLMObjectClass: 'LCSProductSeasonLink'
|
|
349
377
|
};
|
|
350
378
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
351
379
|
expect(typePath).toBe('item');
|
|
352
380
|
});
|
|
353
381
|
it('LCSSKUSeasonLink', () => {
|
|
354
382
|
const object = {
|
|
355
|
-
|
|
383
|
+
flexPLMObjectClass: 'LCSSKUSeasonLink'
|
|
356
384
|
};
|
|
357
385
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
358
386
|
expect(typePath).toBe('item');
|
|
359
387
|
});
|
|
360
388
|
it('LCSColor', () => {
|
|
361
389
|
const object = {
|
|
362
|
-
|
|
390
|
+
flexPLMObjectClass: 'LCSColor'
|
|
363
391
|
};
|
|
364
392
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
365
393
|
expect(typePath).toBe('color');
|
|
@@ -368,7 +396,7 @@ describe('Type Defaults', () => {
|
|
|
368
396
|
describe('getDefaultIdentifierPropertiesFromObject', () => {
|
|
369
397
|
it('LCSProduct', () => {
|
|
370
398
|
const object = {
|
|
371
|
-
|
|
399
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
372
400
|
};
|
|
373
401
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
374
402
|
expect(defaultIdentifiers).toContain('itemNumber');
|
|
@@ -376,7 +404,7 @@ describe('Type Defaults', () => {
|
|
|
376
404
|
});
|
|
377
405
|
it('LCSSKU', () => {
|
|
378
406
|
const object = {
|
|
379
|
-
|
|
407
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
380
408
|
};
|
|
381
409
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
382
410
|
expect(defaultIdentifiers).toContain('itemNumber');
|
|
@@ -384,7 +412,7 @@ describe('Type Defaults', () => {
|
|
|
384
412
|
});
|
|
385
413
|
it('LCSSeason', () => {
|
|
386
414
|
const object = {
|
|
387
|
-
|
|
415
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
388
416
|
};
|
|
389
417
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
390
418
|
expect(defaultIdentifiers).toContain('flexPLMSeasonName');
|
|
@@ -392,7 +420,7 @@ describe('Type Defaults', () => {
|
|
|
392
420
|
});
|
|
393
421
|
it('SeasonGroup', () => {
|
|
394
422
|
const object = {
|
|
395
|
-
|
|
423
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
396
424
|
};
|
|
397
425
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
398
426
|
expect(defaultIdentifiers).toContain('seasonGroupName');
|
|
@@ -400,7 +428,7 @@ describe('Type Defaults', () => {
|
|
|
400
428
|
});
|
|
401
429
|
it('LCSColor', () => {
|
|
402
430
|
const object = {
|
|
403
|
-
|
|
431
|
+
flexPLMObjectClass: 'LCSColor'
|
|
404
432
|
};
|
|
405
433
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
406
434
|
expect(defaultIdentifiers).toContain('name');
|
|
@@ -408,7 +436,7 @@ describe('Type Defaults', () => {
|
|
|
408
436
|
});
|
|
409
437
|
it('LCSRevisableEntity', () => {
|
|
410
438
|
const object = {
|
|
411
|
-
|
|
439
|
+
flexPLMObjectClass: 'LCSRevisableEntity'
|
|
412
440
|
};
|
|
413
441
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
414
442
|
expect(defaultIdentifiers).toContain('name');
|
|
@@ -416,7 +444,7 @@ describe('Type Defaults', () => {
|
|
|
416
444
|
});
|
|
417
445
|
it('LCSLifecycleManaged', () => {
|
|
418
446
|
const object = {
|
|
419
|
-
|
|
447
|
+
flexPLMObjectClass: 'LCSLifecycleManaged'
|
|
420
448
|
};
|
|
421
449
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
422
450
|
expect(defaultIdentifiers).toContain('name');
|
|
@@ -426,7 +454,7 @@ describe('Type Defaults', () => {
|
|
|
426
454
|
describe('getDefaultInformationalPropertiesFromObject', () => {
|
|
427
455
|
it('LCSProduct', () => {
|
|
428
456
|
const object = {
|
|
429
|
-
|
|
457
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
430
458
|
};
|
|
431
459
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
432
460
|
expect(defaultIdentifiers).toContain('name');
|
|
@@ -434,7 +462,7 @@ describe('Type Defaults', () => {
|
|
|
434
462
|
});
|
|
435
463
|
it('LCSSKU', () => {
|
|
436
464
|
const object = {
|
|
437
|
-
|
|
465
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
438
466
|
};
|
|
439
467
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
440
468
|
expect(defaultIdentifiers).toContain('optionName');
|
|
@@ -442,7 +470,7 @@ describe('Type Defaults', () => {
|
|
|
442
470
|
});
|
|
443
471
|
it('LCSSeason', () => {
|
|
444
472
|
const object = {
|
|
445
|
-
|
|
473
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
446
474
|
};
|
|
447
475
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
448
476
|
expect(defaultIdentifiers).toContain('name');
|
|
@@ -450,7 +478,7 @@ describe('Type Defaults', () => {
|
|
|
450
478
|
});
|
|
451
479
|
it('SeasonGroup', () => {
|
|
452
480
|
const object = {
|
|
453
|
-
|
|
481
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
454
482
|
};
|
|
455
483
|
const defaultIdentifiers = type_defaults_1.TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
456
484
|
expect(defaultIdentifiers).toContain('name');
|
package/lib/util/type-utils.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export declare class TypeUtils {
|
|
|
7
7
|
getByRootAndPath(options: TypeClientOptions): Promise<import("@contrail/types").Type>;
|
|
8
8
|
static getFlexPLMTypePath(entity: any): any;
|
|
9
9
|
getEventObjectClass(entityType: string, newData: any): string;
|
|
10
|
+
getEntityTypeClientOptionsUsingMapping(transformMapFile: any, mapFileUtil: any, data: any): Promise<TypeClientOptions>;
|
|
10
11
|
getEntityTypeClientOptions(objectClass: string, data: any): TypeClientOptions;
|
|
11
12
|
filterTypeProperties(type: any, newData: any): TypeProperty[];
|
|
12
13
|
}
|
package/lib/util/type-utils.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.TypeUtils = void 0;
|
|
4
4
|
const app_framework_1 = require("@contrail/app-framework");
|
|
5
5
|
const sdk_1 = require("@contrail/sdk");
|
|
6
|
+
const type_conversion_utils_1 = require("./type-conversion-utils");
|
|
6
7
|
class TypeUtils {
|
|
7
8
|
constructor() {
|
|
8
9
|
this.typesObj = new sdk_1.Types();
|
|
@@ -47,6 +48,15 @@ class TypeUtils {
|
|
|
47
48
|
}
|
|
48
49
|
return objectClass;
|
|
49
50
|
}
|
|
51
|
+
async getEntityTypeClientOptionsUsingMapping(transformMapFile, mapFileUtil, data) {
|
|
52
|
+
const root = await type_conversion_utils_1.TypeConversionUtils.getEntityClassFromObject(transformMapFile, mapFileUtil, data);
|
|
53
|
+
const path = await type_conversion_utils_1.TypeConversionUtils.getEntityTypePathFromOjbect(transformMapFile, mapFileUtil, data);
|
|
54
|
+
let tco = {
|
|
55
|
+
root,
|
|
56
|
+
path
|
|
57
|
+
};
|
|
58
|
+
return tco;
|
|
59
|
+
}
|
|
50
60
|
getEntityTypeClientOptions(objectClass, data) {
|
|
51
61
|
let tco;
|
|
52
62
|
if (['LCSProduct', 'LCSSKU'].includes(objectClass)) {
|
package/package.json
CHANGED
|
@@ -35,7 +35,7 @@ export abstract class BaseEntityProcessor {
|
|
|
35
35
|
|
|
36
36
|
switch (eventType) {
|
|
37
37
|
case 'PERSIST':
|
|
38
|
-
return await this.
|
|
38
|
+
return await this.handleIncomingUpsert(event);
|
|
39
39
|
case 'DELETE':
|
|
40
40
|
return await this.handleIncomingDelete(event);
|
|
41
41
|
default:
|
|
@@ -47,7 +47,7 @@ export abstract class BaseEntityProcessor {
|
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
async
|
|
50
|
+
async handleIncomingUpsert (event: EntityPayloadType) {
|
|
51
51
|
const inboundData = await this.getTransformedData(event);
|
|
52
52
|
const incomingEntityResponse = await this.getIncomingEntity(event, inboundData);
|
|
53
53
|
// This case means there was an early return in the getIncomingEntity method
|
|
@@ -56,13 +56,13 @@ export abstract class BaseEntityProcessor {
|
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
const entity = incomingEntityResponse.entity;
|
|
59
|
-
if(!entity){
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
if (!entity) {
|
|
60
|
+
const createEntityResponse = await this.getCreateEntity(inboundData);
|
|
61
|
+
if (createEntityResponse.earlyReturn) {
|
|
62
|
+
return createEntityResponse.earlyReturn;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return this.createEntity(this.baseType, createEntityResponse.entity);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
const diffs = await this.getUpdatesForEntity(entity, inboundData);
|
|
@@ -86,9 +86,12 @@ export abstract class BaseEntityProcessor {
|
|
|
86
86
|
let inboundData = event.data;
|
|
87
87
|
console.debug('inboundData: ' + JSON.stringify(inboundData));
|
|
88
88
|
|
|
89
|
-
const
|
|
90
|
-
inboundData = await MapUtil.applyTransformMap(this.transformMapFile, this.mapFileUtil, inboundData,
|
|
89
|
+
const mapKey = await TypeConversionUtils.getMapKeyFromObject(this.transformMapFile, this.mapFileUtil, inboundData, TypeConversionUtils.FLEX2VIBE_DIRECTION);
|
|
90
|
+
inboundData = await MapUtil.applyTransformMap(this.transformMapFile, this.mapFileUtil, inboundData, mapKey, TypeConversionUtils.FLEX2VIBE_DIRECTION);
|
|
91
91
|
console.debug('Transformed-inboundData: ' + JSON.stringify(inboundData));
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
|
|
92
95
|
return inboundData;
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -110,7 +113,7 @@ export abstract class BaseEntityProcessor {
|
|
|
110
113
|
|
|
111
114
|
async getVibeOwningKeys(entity) {
|
|
112
115
|
let vibeOwningKeys = [];
|
|
113
|
-
if (this.transformMapFile) {
|
|
116
|
+
if (this.transformMapFile && entity) {
|
|
114
117
|
//Technically the transform is flex->vibe. But the vibe entity being updated was passed in,
|
|
115
118
|
// so we use VIBE2FLEX_DIRECTION to get the mapKey
|
|
116
119
|
const mapKey = await TypeConversionUtils.getMapKey(this.transformMapFile, this.mapFileUtil, entity, TypeConversionUtils.VIBE2FLEX_DIRECTION);
|
|
@@ -122,6 +125,16 @@ export abstract class BaseEntityProcessor {
|
|
|
122
125
|
return vibeOwningKeys;
|
|
123
126
|
}
|
|
124
127
|
|
|
128
|
+
async createEntity(entityName, changes) {
|
|
129
|
+
const options = {
|
|
130
|
+
entityName: entityName,
|
|
131
|
+
object: changes,
|
|
132
|
+
};
|
|
133
|
+
console.log("options: " + JSON.stringify(options));
|
|
134
|
+
|
|
135
|
+
return await new Entities().create(options);
|
|
136
|
+
}
|
|
137
|
+
|
|
125
138
|
async updateEntity(entityName, entity, diffs) {
|
|
126
139
|
const options = {
|
|
127
140
|
entityName: entityName,
|
|
@@ -135,6 +148,7 @@ export abstract class BaseEntityProcessor {
|
|
|
135
148
|
|
|
136
149
|
// This method must be implemented by derived classes
|
|
137
150
|
protected abstract getIncomingEntity(event, inboundData): Promise<IncomingEntityResponse>;
|
|
151
|
+
protected abstract getCreateEntity(inboundData): Promise<IncomingEntityResponse>;
|
|
138
152
|
|
|
139
153
|
// outbound
|
|
140
154
|
|
|
@@ -228,7 +228,7 @@ export class DataConverter {
|
|
|
228
228
|
// this.logger.log('setEntityValues: ' + JSON.stringify(entity));
|
|
229
229
|
// this.logger.log('data: ' + JSON.stringify(data));
|
|
230
230
|
const type = await this.typeUtils.getTypeById(entity.typeId);
|
|
231
|
-
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'workspaceId']);
|
|
231
|
+
keysToSkip = keysToSkip.concat(['updatedOn', 'updatedById', 'createdOn', 'createdById', 'modifiedAt', 'orgId', 'createdAt', 'id', 'typeId', 'typePath', 'workspaceId']);
|
|
232
232
|
let typeProps = this.typeUtils.filterTypeProperties(type, entity);
|
|
233
233
|
typeProps = typeProps.filter( prop => !keysToSkip.includes(prop['slug']));
|
|
234
234
|
//Only process properties that had a value sent; to not accidentally clear out values
|
|
@@ -260,7 +260,7 @@ export class DataConverter {
|
|
|
260
260
|
*/
|
|
261
261
|
async getEntityValues(objectClass: string, data: any, keysToSkip: string[] = []){
|
|
262
262
|
const entityValues = {};
|
|
263
|
-
const tco: TypeClientOptions = this.typeUtils.
|
|
263
|
+
const tco: TypeClientOptions = await this.typeUtils.getEntityTypeClientOptionsUsingMapping(this.transformMapFile, this.mapFileUtil, data);
|
|
264
264
|
const type = await this.typeUtils.getByRootAndPath(tco);
|
|
265
265
|
const typePath = type['typePath'];
|
|
266
266
|
if(typePath && (typePath.startsWith('item') || typePath.startsWith('project-item'))){
|
|
@@ -415,20 +415,41 @@ export class DataConverter {
|
|
|
415
415
|
return this.userRefCache[nd.email];
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
const
|
|
419
|
-
|
|
420
|
-
take: 1000
|
|
421
|
-
});
|
|
418
|
+
const user = await this.getUserByEmail(nd);
|
|
419
|
+
const userId = (user)?user.id:undefined;
|
|
422
420
|
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
if(value) {
|
|
427
|
-
this.userRefCache[nd.email] = value;
|
|
421
|
+
if(userId) {
|
|
422
|
+
this.userRefCache[nd.email] = userId;
|
|
428
423
|
await this.processGroupMemberCheck(prop, nd.email);
|
|
429
424
|
}
|
|
430
425
|
|
|
431
|
-
return
|
|
426
|
+
return userId;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/** Makes batch calls of 1000 of user-org entities until
|
|
430
|
+
* it find one with userEmail of passed in nd.email.
|
|
431
|
+
* Maxes out after querying for 15,000 user-org entities
|
|
432
|
+
*
|
|
433
|
+
* @param nd
|
|
434
|
+
* @returns
|
|
435
|
+
*/
|
|
436
|
+
async getUserByEmail(nd: any) {
|
|
437
|
+
let userOrg = undefined;
|
|
438
|
+
let count =0;
|
|
439
|
+
let size = 0;
|
|
440
|
+
const entities = new Entities();
|
|
441
|
+
const getOptionsCriteria = {
|
|
442
|
+
entityName: 'user-org',
|
|
443
|
+
take:1000
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
do {
|
|
447
|
+
const userBatch: [any] = await entities.get(getOptionsCriteria);
|
|
448
|
+
userOrg = userBatch.find(uo => uo?.userEmail === nd?.email);
|
|
449
|
+
|
|
450
|
+
}while( !userOrg && size == getOptionsCriteria.take && count < 15);
|
|
451
|
+
return userOrg?.user
|
|
452
|
+
|
|
432
453
|
}
|
|
433
454
|
|
|
434
455
|
/** Shows warning if user email address not present in group associated to property
|
|
@@ -485,16 +506,13 @@ export class DataConverter {
|
|
|
485
506
|
return this.userRefCache[entityId];
|
|
486
507
|
}
|
|
487
508
|
|
|
488
|
-
const
|
|
489
|
-
entityName: 'user-org',
|
|
490
|
-
id: entityId
|
|
491
|
-
});
|
|
509
|
+
const user = await this.getUserById(entityId);
|
|
492
510
|
|
|
493
|
-
const value = (
|
|
494
|
-
email:
|
|
495
|
-
firstName:
|
|
496
|
-
lastName:
|
|
497
|
-
isSsoUser:
|
|
511
|
+
const value = (user) ? {
|
|
512
|
+
email: user.email,
|
|
513
|
+
firstName: user.first,
|
|
514
|
+
lastName: user.last,
|
|
515
|
+
isSsoUser: user.isSsoUser,
|
|
498
516
|
} : undefined;
|
|
499
517
|
|
|
500
518
|
if(value) {
|
|
@@ -504,4 +522,29 @@ export class DataConverter {
|
|
|
504
522
|
return value;
|
|
505
523
|
}
|
|
506
524
|
|
|
525
|
+
/** Makes batch calls of 1000 of user-org entities until
|
|
526
|
+
* it find one with user.id of passed in userId.
|
|
527
|
+
* Maxes out after querying for 15,000 user-org entities
|
|
528
|
+
*
|
|
529
|
+
* @param userId
|
|
530
|
+
* @returns
|
|
531
|
+
*/
|
|
532
|
+
async getUserById(userId: any) {
|
|
533
|
+
let userOrg = undefined;
|
|
534
|
+
let count =0;
|
|
535
|
+
let size = 0;
|
|
536
|
+
const entities = new Entities();
|
|
537
|
+
const getOptionsCriteria = {
|
|
538
|
+
entityName: 'user-org',
|
|
539
|
+
take:1000
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
do {
|
|
543
|
+
const userBatch: [any] = await entities.get(getOptionsCriteria);
|
|
544
|
+
userOrg = userBatch.find(uo => uo?.user?.id === userId);
|
|
545
|
+
|
|
546
|
+
}while( !userOrg && size == getOptionsCriteria.take && count < 15);
|
|
547
|
+
return userOrg?.user
|
|
548
|
+
}
|
|
549
|
+
|
|
507
550
|
}
|
|
@@ -320,7 +320,7 @@ describe('conversion-utils', () => {
|
|
|
320
320
|
it('uses mapping-catName', async () =>{
|
|
321
321
|
const expectedClass = 'custom-entity';
|
|
322
322
|
const object = {
|
|
323
|
-
|
|
323
|
+
flexPLMObjectClass: 'LCSLast',
|
|
324
324
|
flexPLMTypePath: 'Last\\catName'
|
|
325
325
|
};
|
|
326
326
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -339,7 +339,7 @@ describe('conversion-utils', () => {
|
|
|
339
339
|
it('uses default-noMap', async () =>{
|
|
340
340
|
const expectedClass = 'color';
|
|
341
341
|
const entity = {
|
|
342
|
-
|
|
342
|
+
flexPLMObjectClass: 'LCSColor',
|
|
343
343
|
flexPLMTypePath: 'Color'
|
|
344
344
|
};
|
|
345
345
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -376,7 +376,7 @@ describe('conversion-utils', () => {
|
|
|
376
376
|
it('uses mapping-catName', async () =>{
|
|
377
377
|
const expectedTypePath = 'custom-entity:catName';
|
|
378
378
|
const entity = {
|
|
379
|
-
|
|
379
|
+
flexPLMObjectClass: 'LCSLast',
|
|
380
380
|
flexPLMTypePath: 'Last\\catName'
|
|
381
381
|
};
|
|
382
382
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -395,7 +395,7 @@ describe('conversion-utils', () => {
|
|
|
395
395
|
it('uses default-noMap', async () =>{
|
|
396
396
|
const expectedTypePath = 'color';
|
|
397
397
|
const entity = {
|
|
398
|
-
|
|
398
|
+
flexPLMObjectClass: 'LCSColor',
|
|
399
399
|
flexPLMTypePath: 'Color'
|
|
400
400
|
};
|
|
401
401
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -433,7 +433,7 @@ describe('conversion-utils', () => {
|
|
|
433
433
|
it('uses mapping-catName', async () =>{
|
|
434
434
|
const properties = ['catName', 'catNumber'];
|
|
435
435
|
const object = {
|
|
436
|
-
|
|
436
|
+
flexPLMObjectClass: 'LCSLast',
|
|
437
437
|
flexPLMTypePath: 'Last\\catName'
|
|
438
438
|
};
|
|
439
439
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -453,7 +453,7 @@ describe('conversion-utils', () => {
|
|
|
453
453
|
it('uses default-noMap', async () =>{
|
|
454
454
|
const properties = ['itemNumber'];
|
|
455
455
|
const object = {
|
|
456
|
-
|
|
456
|
+
flexPLMObjectClass: 'LCSProduct',
|
|
457
457
|
flexPLMTypePath: 'Product'
|
|
458
458
|
};
|
|
459
459
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -492,7 +492,7 @@ describe('conversion-utils', () => {
|
|
|
492
492
|
it('uses mapping-catName', async () =>{
|
|
493
493
|
const properties = ['longName'];
|
|
494
494
|
const object = {
|
|
495
|
-
|
|
495
|
+
flexPLMObjectClass: 'LCSLast',
|
|
496
496
|
flexPLMTypePath: 'Last\\catName'
|
|
497
497
|
};
|
|
498
498
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -512,7 +512,7 @@ describe('conversion-utils', () => {
|
|
|
512
512
|
it('uses default-noMap', async () =>{
|
|
513
513
|
const properties = ['optionName', 'description'];
|
|
514
514
|
const object = {
|
|
515
|
-
|
|
515
|
+
flexPLMObjectClass: 'LCSSKU',
|
|
516
516
|
typePath: 'Product'
|
|
517
517
|
};
|
|
518
518
|
const spy = jest.spyOn(mapFileUtil, 'getMapFile')
|
|
@@ -543,7 +543,7 @@ describe('conversion-utils', () => {
|
|
|
543
543
|
return mapping;
|
|
544
544
|
});
|
|
545
545
|
const object = {
|
|
546
|
-
|
|
546
|
+
flexPLMObjectClass: 'LCSRevisableEntity',
|
|
547
547
|
flexPLMTypePath: 'Revisable Entity\\packaging'
|
|
548
548
|
}
|
|
549
549
|
const expectedMapKey = 'packaging';
|
|
@@ -563,7 +563,7 @@ describe('conversion-utils', () => {
|
|
|
563
563
|
return mapping;
|
|
564
564
|
});
|
|
565
565
|
const object = {
|
|
566
|
-
|
|
566
|
+
flexPLMObjectClass: 'LCSRevisableEntity',
|
|
567
567
|
flexPLMTypePath: 'Revisable Entity\\prefix'
|
|
568
568
|
}
|
|
569
569
|
const expectedMapKey = 'prefix';
|
|
@@ -583,7 +583,7 @@ describe('conversion-utils', () => {
|
|
|
583
583
|
return mapping;
|
|
584
584
|
});
|
|
585
585
|
const object = {
|
|
586
|
-
|
|
586
|
+
flexPLMObjectClass: 'LCSColor',
|
|
587
587
|
flexPLMTypePath: 'Color'
|
|
588
588
|
}
|
|
589
589
|
const expectedMapKey = 'LCSColor';
|
|
@@ -392,12 +392,12 @@ describe('Type Defaults', () =>{
|
|
|
392
392
|
|
|
393
393
|
});
|
|
394
394
|
|
|
395
|
-
})
|
|
395
|
+
});//getEntityType
|
|
396
396
|
|
|
397
397
|
describe('getDefaultEntityClass', () =>{
|
|
398
398
|
it('item - LCSProduct', () =>{
|
|
399
399
|
const object = {
|
|
400
|
-
|
|
400
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
401
401
|
};
|
|
402
402
|
|
|
403
403
|
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
@@ -407,7 +407,7 @@ describe('Type Defaults', () =>{
|
|
|
407
407
|
|
|
408
408
|
it('item - LCSSKU', () =>{
|
|
409
409
|
const object = {
|
|
410
|
-
|
|
410
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
411
411
|
};
|
|
412
412
|
|
|
413
413
|
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
@@ -417,7 +417,7 @@ describe('Type Defaults', () =>{
|
|
|
417
417
|
|
|
418
418
|
it('color - LCSColor', () =>{
|
|
419
419
|
const object = {
|
|
420
|
-
|
|
420
|
+
flexPLMObjectClass: 'LCSColor'
|
|
421
421
|
};
|
|
422
422
|
|
|
423
423
|
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
@@ -425,12 +425,52 @@ describe('Type Defaults', () =>{
|
|
|
425
425
|
expect(entityClass).toBe('color');
|
|
426
426
|
});
|
|
427
427
|
|
|
428
|
+
it('assortment - LCSSeason', () =>{
|
|
429
|
+
const object = {
|
|
430
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
434
|
+
|
|
435
|
+
expect(entityClass).toBe('assortment');
|
|
436
|
+
});
|
|
437
|
+
|
|
438
|
+
it('assortment - SeasonGroup', () =>{
|
|
439
|
+
const object = {
|
|
440
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
441
|
+
};
|
|
442
|
+
|
|
443
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
444
|
+
|
|
445
|
+
expect(entityClass).toBe('assortment');
|
|
446
|
+
});
|
|
447
|
+
|
|
448
|
+
it('custom-entity - LCSRevisableEntity', () =>{
|
|
449
|
+
const object = {
|
|
450
|
+
flexPLMObjectClass: 'LCSRevisableEntity'
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
454
|
+
|
|
455
|
+
expect(entityClass).toBe('custom-entity');
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
it('custom-entity - LCSLifecycleManaged', () =>{
|
|
459
|
+
const object = {
|
|
460
|
+
flexPLMObjectClass: 'LCSLifecycleManaged'
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
464
|
+
|
|
465
|
+
expect(entityClass).toBe('custom-entity');
|
|
466
|
+
});
|
|
467
|
+
|
|
428
468
|
});//getDefaultEntityClass
|
|
429
469
|
|
|
430
470
|
describe('getDefaultEntityTypePath', () =>{
|
|
431
471
|
it('LCSProduct', () =>{
|
|
432
472
|
const object = {
|
|
433
|
-
|
|
473
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
434
474
|
};
|
|
435
475
|
|
|
436
476
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
@@ -439,7 +479,7 @@ describe('Type Defaults', () =>{
|
|
|
439
479
|
|
|
440
480
|
it('LCSSKU', () =>{
|
|
441
481
|
const object = {
|
|
442
|
-
|
|
482
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
443
483
|
};
|
|
444
484
|
|
|
445
485
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
@@ -447,7 +487,7 @@ describe('Type Defaults', () =>{
|
|
|
447
487
|
});
|
|
448
488
|
it('LCSProductSeasonLink', () =>{
|
|
449
489
|
const object = {
|
|
450
|
-
|
|
490
|
+
flexPLMObjectClass: 'LCSProductSeasonLink'
|
|
451
491
|
};
|
|
452
492
|
|
|
453
493
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
@@ -456,7 +496,7 @@ describe('Type Defaults', () =>{
|
|
|
456
496
|
|
|
457
497
|
it('LCSSKUSeasonLink', () =>{
|
|
458
498
|
const object = {
|
|
459
|
-
|
|
499
|
+
flexPLMObjectClass: 'LCSSKUSeasonLink'
|
|
460
500
|
};
|
|
461
501
|
|
|
462
502
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
@@ -465,7 +505,7 @@ describe('Type Defaults', () =>{
|
|
|
465
505
|
|
|
466
506
|
it('LCSColor', () =>{
|
|
467
507
|
const object = {
|
|
468
|
-
|
|
508
|
+
flexPLMObjectClass: 'LCSColor'
|
|
469
509
|
};
|
|
470
510
|
|
|
471
511
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
@@ -477,7 +517,7 @@ describe('Type Defaults', () =>{
|
|
|
477
517
|
describe('getDefaultIdentifierPropertiesFromObject', () =>{
|
|
478
518
|
it('LCSProduct', () =>{
|
|
479
519
|
const object = {
|
|
480
|
-
|
|
520
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
481
521
|
};
|
|
482
522
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
483
523
|
|
|
@@ -487,7 +527,7 @@ describe('Type Defaults', () =>{
|
|
|
487
527
|
|
|
488
528
|
it('LCSSKU', () =>{
|
|
489
529
|
const object = {
|
|
490
|
-
|
|
530
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
491
531
|
};
|
|
492
532
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
493
533
|
|
|
@@ -497,7 +537,7 @@ describe('Type Defaults', () =>{
|
|
|
497
537
|
|
|
498
538
|
it('LCSSeason', () =>{
|
|
499
539
|
const object = {
|
|
500
|
-
|
|
540
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
501
541
|
};
|
|
502
542
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
503
543
|
|
|
@@ -507,7 +547,7 @@ describe('Type Defaults', () =>{
|
|
|
507
547
|
|
|
508
548
|
it('SeasonGroup', () =>{
|
|
509
549
|
const object = {
|
|
510
|
-
|
|
550
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
511
551
|
};
|
|
512
552
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
513
553
|
|
|
@@ -517,7 +557,7 @@ describe('Type Defaults', () =>{
|
|
|
517
557
|
|
|
518
558
|
it('LCSColor', () =>{
|
|
519
559
|
const object = {
|
|
520
|
-
|
|
560
|
+
flexPLMObjectClass: 'LCSColor'
|
|
521
561
|
};
|
|
522
562
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
523
563
|
|
|
@@ -527,7 +567,7 @@ describe('Type Defaults', () =>{
|
|
|
527
567
|
|
|
528
568
|
it('LCSRevisableEntity', () =>{
|
|
529
569
|
const object = {
|
|
530
|
-
|
|
570
|
+
flexPLMObjectClass: 'LCSRevisableEntity'
|
|
531
571
|
};
|
|
532
572
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
533
573
|
|
|
@@ -537,7 +577,7 @@ describe('Type Defaults', () =>{
|
|
|
537
577
|
|
|
538
578
|
it('LCSLifecycleManaged', () =>{
|
|
539
579
|
const object = {
|
|
540
|
-
|
|
580
|
+
flexPLMObjectClass: 'LCSLifecycleManaged'
|
|
541
581
|
};
|
|
542
582
|
const defaultIdentifiers = TypeDefaults.getDefaultIdentifierPropertiesFromObject(object);
|
|
543
583
|
|
|
@@ -550,7 +590,7 @@ describe('Type Defaults', () =>{
|
|
|
550
590
|
describe('getDefaultInformationalPropertiesFromObject', () =>{
|
|
551
591
|
it('LCSProduct', () =>{
|
|
552
592
|
const object = {
|
|
553
|
-
|
|
593
|
+
flexPLMObjectClass: 'LCSProduct'
|
|
554
594
|
};
|
|
555
595
|
|
|
556
596
|
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
@@ -560,7 +600,7 @@ describe('Type Defaults', () =>{
|
|
|
560
600
|
|
|
561
601
|
it('LCSSKU', () =>{
|
|
562
602
|
const object = {
|
|
563
|
-
|
|
603
|
+
flexPLMObjectClass: 'LCSSKU'
|
|
564
604
|
};
|
|
565
605
|
|
|
566
606
|
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
@@ -570,7 +610,7 @@ describe('Type Defaults', () =>{
|
|
|
570
610
|
|
|
571
611
|
it('LCSSeason', () =>{
|
|
572
612
|
const object = {
|
|
573
|
-
|
|
613
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
574
614
|
};
|
|
575
615
|
|
|
576
616
|
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
@@ -580,7 +620,7 @@ describe('Type Defaults', () =>{
|
|
|
580
620
|
|
|
581
621
|
it('SeasonGroup', () =>{
|
|
582
622
|
const object = {
|
|
583
|
-
|
|
623
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
584
624
|
};
|
|
585
625
|
|
|
586
626
|
const defaultIdentifiers = TypeDefaults.getDefaultInformationalPropertiesFromObject(object);
|
|
@@ -173,6 +173,10 @@ export class TypeDefaults {
|
|
|
173
173
|
entityClass = 'item';
|
|
174
174
|
} else if('LCSColor' === objectClass){
|
|
175
175
|
entityClass = 'color';
|
|
176
|
+
} else if(['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
177
|
+
entityClass = 'assortment';
|
|
178
|
+
} else if(['LCSRevisableEntity', 'LCSLifecycleManaged'].includes(objectClass)) {
|
|
179
|
+
entityClass = 'custom-entity';
|
|
176
180
|
}
|
|
177
181
|
|
|
178
182
|
return entityClass;
|
|
@@ -256,6 +260,6 @@ export class TypeDefaults {
|
|
|
256
260
|
}
|
|
257
261
|
|
|
258
262
|
static getObjectClass(object: any): string {
|
|
259
|
-
return (object)? object['
|
|
263
|
+
return (object)? object['flexPLMObjectClass']: '';
|
|
260
264
|
}
|
|
261
265
|
}
|
package/src/util/type-utils.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Logger } from '@contrail/app-framework';
|
|
2
2
|
import { TypeClientOptions, Types } from '@contrail/sdk';
|
|
3
3
|
import { TypeProperty } from '@contrail/types';
|
|
4
|
+
import { TypeConversionUtils } from './type-conversion-utils';
|
|
4
5
|
|
|
5
6
|
export class TypeUtils {
|
|
6
7
|
private typesObj: Types;
|
|
@@ -55,6 +56,23 @@ export class TypeUtils {
|
|
|
55
56
|
return objectClass;
|
|
56
57
|
}
|
|
57
58
|
|
|
59
|
+
/** Gets the VibeIQ entity type for the object data
|
|
60
|
+
* @param data: object data
|
|
61
|
+
*/
|
|
62
|
+
async getEntityTypeClientOptionsUsingMapping(transformMapFile, mapFileUtil, data): Promise<TypeClientOptions> {
|
|
63
|
+
const root = await TypeConversionUtils.getEntityClassFromObject(transformMapFile, mapFileUtil, data);
|
|
64
|
+
const path = await TypeConversionUtils.getEntityTypePathFromOjbect(transformMapFile, mapFileUtil, data);
|
|
65
|
+
|
|
66
|
+
let tco: TypeClientOptions = {
|
|
67
|
+
root,
|
|
68
|
+
path
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
return tco;
|
|
74
|
+
}
|
|
75
|
+
|
|
58
76
|
/** Gets the VibeIQ entity type for the object data
|
|
59
77
|
* @param objectClass: string object class
|
|
60
78
|
* @param data: object data
|