@contrail/flexplm 1.1.21 → 1.1.23
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/util/data-converter.d.ts +3 -0
- package/lib/util/data-converter.js +90 -1
- package/lib/util/data-converter.spec.js +63 -0
- package/lib/util/type-defaults.js +10 -1
- package/lib/util/type-defaults.spec.js +30 -2
- package/package.json +1 -1
- package/src/util/data-converter.spec.ts +71 -0
- package/src/util/data-converter.ts +126 -4
- package/src/util/type-defaults.spec.ts +39 -2
- package/src/util/type-defaults.ts +10 -2
|
@@ -20,6 +20,9 @@ export declare class DataConverter {
|
|
|
20
20
|
getEntityValue(prop: any, data: any): Promise<any>;
|
|
21
21
|
setEnumerationKeys(prop: any, nd: any, matchByDisplay: any): any;
|
|
22
22
|
getPersistableChanges(entity: object, changes: object): object;
|
|
23
|
+
setObjectReferenceValue(prop: any, nd: any): Promise<any>;
|
|
24
|
+
getAllObjectReferences(entityType: any, rootTypeCriteria: any): Promise<any[]>;
|
|
25
|
+
checkKeysAndValues(criteria: any, arrayOfObjects: any, entityTypePath: any): any[];
|
|
23
26
|
setUserListValue(prop: any, nd: any): Promise<any>;
|
|
24
27
|
getUserByEmail(nd: any): Promise<any>;
|
|
25
28
|
processGroupMemberCheck(prop: any, userEmail: any): Promise<void>;
|
|
@@ -201,7 +201,7 @@ class DataConverter {
|
|
|
201
201
|
const propertyType = prop['propertyType'];
|
|
202
202
|
const slug = prop['slug'];
|
|
203
203
|
let keyName = slug;
|
|
204
|
-
if (propertyType === 'userList') {
|
|
204
|
+
if (propertyType === 'userList' || propertyType === 'object_reference') {
|
|
205
205
|
keyName = slug + 'Id';
|
|
206
206
|
}
|
|
207
207
|
entity[keyName] = await this.getEntityValue(prop, data);
|
|
@@ -262,6 +262,7 @@ class DataConverter {
|
|
|
262
262
|
value = this.setEnumerationKeys(prop, nd, this.useDisplayForEnumerationMatching);
|
|
263
263
|
}
|
|
264
264
|
else if ('object_reference' === propertyType) {
|
|
265
|
+
value = await this.setObjectReferenceValue(prop, nd);
|
|
265
266
|
}
|
|
266
267
|
else if ('image' === propertyType) {
|
|
267
268
|
}
|
|
@@ -321,6 +322,94 @@ class DataConverter {
|
|
|
321
322
|
}
|
|
322
323
|
return diffValues;
|
|
323
324
|
}
|
|
325
|
+
async setObjectReferenceValue(prop, nd) {
|
|
326
|
+
let objectReferenceId = "";
|
|
327
|
+
if (!nd) {
|
|
328
|
+
return objectReferenceId;
|
|
329
|
+
}
|
|
330
|
+
const entityType = prop['referencedTypeRootSlug'];
|
|
331
|
+
const entityTypePath = prop['referencedTypePath'];
|
|
332
|
+
const entityKeys = Object.keys(nd);
|
|
333
|
+
const identifierKeys = await type_conversion_utils_1.TypeConversionUtils.getIdentifierPropertiesFromObject(this.transformMapFile, this.mapFileUtil, nd);
|
|
334
|
+
const hasAllIdentifiers = identifierKeys.every(key => entityKeys.includes(key));
|
|
335
|
+
if (identifierKeys.length == 0 || !hasAllIdentifiers) {
|
|
336
|
+
console.warn(`The inbound ${entityType} doesnt have all "identifier properties, so there is no processing. Identifier properties: ${identifierKeys}`);
|
|
337
|
+
return objectReferenceId;
|
|
338
|
+
}
|
|
339
|
+
const rootType = await this.typeUtils.getByRootAndPath({ root: entityType });
|
|
340
|
+
const rootTypeProps = this.typeUtils.filterTypeProperties(rootType, nd);
|
|
341
|
+
let rootTypeCriteria = {};
|
|
342
|
+
let typeCriteria = {};
|
|
343
|
+
identifierKeys.forEach(keyName => {
|
|
344
|
+
const foundInObjects = rootTypeProps.some(obj => obj.slug === keyName);
|
|
345
|
+
if (foundInObjects) {
|
|
346
|
+
rootTypeCriteria[keyName] = nd[keyName];
|
|
347
|
+
}
|
|
348
|
+
else {
|
|
349
|
+
typeCriteria[keyName] = nd[keyName];
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
const combinedCriteria = { ...rootTypeCriteria, ...typeCriteria, typePath: entityTypePath };
|
|
353
|
+
const cacheKey = Object.values(combinedCriteria).join('_');
|
|
354
|
+
if (this.objRefCache[cacheKey]) {
|
|
355
|
+
if (app_framework_1.Logger.isDebugOn()) {
|
|
356
|
+
console.debug(`object reference cache hit: ${cacheKey}`);
|
|
357
|
+
}
|
|
358
|
+
return this.objRefCache[cacheKey];
|
|
359
|
+
}
|
|
360
|
+
let arrObjectReferences = await this.getAllObjectReferences(entityType, rootTypeCriteria);
|
|
361
|
+
if (entityType !== entityTypePath) {
|
|
362
|
+
arrObjectReferences = this.checkKeysAndValues(typeCriteria, arrObjectReferences, entityTypePath);
|
|
363
|
+
}
|
|
364
|
+
if (arrObjectReferences.length) {
|
|
365
|
+
if (arrObjectReferences.length === 1) {
|
|
366
|
+
objectReferenceId = arrObjectReferences[0].id;
|
|
367
|
+
}
|
|
368
|
+
else {
|
|
369
|
+
console.warn(`The passed in object reference criteria has duplicate records found ${JSON.stringify(combinedCriteria)}.`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
if (!objectReferenceId) {
|
|
373
|
+
console.warn(`The passed in object reference criteria ${JSON.stringify(combinedCriteria)} not found.`);
|
|
374
|
+
return objectReferenceId;
|
|
375
|
+
}
|
|
376
|
+
this.objRefCache[cacheKey] = objectReferenceId;
|
|
377
|
+
return objectReferenceId;
|
|
378
|
+
}
|
|
379
|
+
async getAllObjectReferences(entityType, rootTypeCriteria) {
|
|
380
|
+
let loads = [];
|
|
381
|
+
let nextPageKey;
|
|
382
|
+
do {
|
|
383
|
+
const loadPage = await new sdk_1.Entities().get({ entityName: entityType, criteria: rootTypeCriteria, apiVersion: sdk_1.API_VERSION.V2, nextPageKey });
|
|
384
|
+
nextPageKey = loadPage.nextPageKey;
|
|
385
|
+
loads.push(...loadPage.results);
|
|
386
|
+
} while (nextPageKey);
|
|
387
|
+
return loads;
|
|
388
|
+
}
|
|
389
|
+
checkKeysAndValues(criteria, arrayOfObjects, entityTypePath) {
|
|
390
|
+
let arrOfMatchObjects = [];
|
|
391
|
+
for (let i = 0; i < arrayOfObjects.length; i++) {
|
|
392
|
+
const currentObj = arrayOfObjects[i];
|
|
393
|
+
let found = true;
|
|
394
|
+
if (entityTypePath && currentObj['typePath']) {
|
|
395
|
+
const currentObjPath = '' + currentObj['typePath'];
|
|
396
|
+
if (!currentObjPath.startsWith(entityTypePath)) {
|
|
397
|
+
found = false;
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
for (const key in criteria) {
|
|
402
|
+
if (!(key in currentObj) || currentObj[key] !== criteria[key]) {
|
|
403
|
+
found = false;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
if (found) {
|
|
408
|
+
arrOfMatchObjects.push(currentObj);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return arrOfMatchObjects;
|
|
412
|
+
}
|
|
324
413
|
async setUserListValue(prop, nd) {
|
|
325
414
|
if (!nd?.email) {
|
|
326
415
|
return "";
|
|
@@ -589,3 +589,66 @@ describe('setEnumerationKeys', () => {
|
|
|
589
589
|
expect(returnValue).toEqual([]);
|
|
590
590
|
});
|
|
591
591
|
});
|
|
592
|
+
describe('checkKeysAndValues', () => {
|
|
593
|
+
const config = {
|
|
594
|
+
apiHost: 'host',
|
|
595
|
+
userName: () => 'user',
|
|
596
|
+
password: () => 'pass',
|
|
597
|
+
urlContext: 'xxx',
|
|
598
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
599
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
600
|
+
itemPreDevelopmentLifecycleStages: ['concept']
|
|
601
|
+
};
|
|
602
|
+
const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
|
|
603
|
+
const dc = new data_converter_1.DataConverter(config, mapFileUtil);
|
|
604
|
+
const groupData = [
|
|
605
|
+
{ name: 'Group 1', typePath: 'custom-entity:grouping' },
|
|
606
|
+
{ name: 'Group 2', typePath: 'custom-entity:grouping' },
|
|
607
|
+
{ name: 'Group 2', typePath: 'custom-entity:grouping' },
|
|
608
|
+
{ name: 'Group 4', typePath: 'custom-entity:grouping' },
|
|
609
|
+
{ name: 'Group 4', typePath: 'custom-entity:grouping:sub' },
|
|
610
|
+
{ name: 'Group 5', typePath: 'custom-entity:grouping:sub' }
|
|
611
|
+
];
|
|
612
|
+
it('Group 1', () => {
|
|
613
|
+
const criteria = {
|
|
614
|
+
name: 'Group 1'
|
|
615
|
+
};
|
|
616
|
+
const typePath = 'custom-entity:grouping';
|
|
617
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
618
|
+
expect(results.length).toBe(1);
|
|
619
|
+
});
|
|
620
|
+
it('Group 5 - sub type of typePath', () => {
|
|
621
|
+
const criteria = {
|
|
622
|
+
name: 'Group 5'
|
|
623
|
+
};
|
|
624
|
+
const typePath = 'custom-entity:grouping';
|
|
625
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
626
|
+
expect(results.length).toBe(1);
|
|
627
|
+
});
|
|
628
|
+
it('Group 2 - returns the 2 matching', () => {
|
|
629
|
+
const criteria = {
|
|
630
|
+
name: 'Group 2'
|
|
631
|
+
};
|
|
632
|
+
const typePath = 'custom-entity:grouping';
|
|
633
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
634
|
+
expect(results.length).toBe(2);
|
|
635
|
+
});
|
|
636
|
+
it('2 Same Name - but 1 is a sub type; returns 2', () => {
|
|
637
|
+
const criteria = {
|
|
638
|
+
name: 'Group 4'
|
|
639
|
+
};
|
|
640
|
+
const typePath = 'custom-entity:grouping';
|
|
641
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
642
|
+
expect(results.length).toBe(2);
|
|
643
|
+
});
|
|
644
|
+
it('2 Same Name - but 1 wrong type', () => {
|
|
645
|
+
const criteria = {
|
|
646
|
+
name: 'Group 1'
|
|
647
|
+
};
|
|
648
|
+
const testData = [...groupData];
|
|
649
|
+
testData.push({ name: 'Group 1', typePath: 'custom-entity:label' });
|
|
650
|
+
const typePath = 'custom-entity:grouping';
|
|
651
|
+
const results = dc.checkKeysAndValues(criteria, testData, typePath);
|
|
652
|
+
expect(results.length).toBe(1);
|
|
653
|
+
});
|
|
654
|
+
});
|
|
@@ -133,6 +133,9 @@ class TypeDefaults {
|
|
|
133
133
|
if (['LCSProduct', 'LCSSKU'].includes(objectClass)) {
|
|
134
134
|
entityClass = 'item';
|
|
135
135
|
}
|
|
136
|
+
else if (['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)) {
|
|
137
|
+
entityClass = 'project-item';
|
|
138
|
+
}
|
|
136
139
|
else if ('LCSColor' === objectClass) {
|
|
137
140
|
entityClass = 'color';
|
|
138
141
|
}
|
|
@@ -152,13 +155,19 @@ class TypeDefaults {
|
|
|
152
155
|
switch (objectClass) {
|
|
153
156
|
case 'LCSProduct':
|
|
154
157
|
case 'LCSSKU':
|
|
158
|
+
typePath = 'item';
|
|
159
|
+
break;
|
|
155
160
|
case 'LCSProductSeasonLink':
|
|
156
161
|
case 'LCSSKUSeasonLink':
|
|
157
|
-
typePath = 'item';
|
|
162
|
+
typePath = 'project-item';
|
|
158
163
|
break;
|
|
159
164
|
case 'LCSColor':
|
|
160
165
|
typePath = 'color';
|
|
161
166
|
break;
|
|
167
|
+
case 'LCSSeason':
|
|
168
|
+
case 'SeasonGroup':
|
|
169
|
+
typePath = 'assortment';
|
|
170
|
+
break;
|
|
162
171
|
}
|
|
163
172
|
if (typePath === '')
|
|
164
173
|
throw Error(TypeDefaults.NO_TYPE_PATH);
|
|
@@ -320,6 +320,20 @@ describe('Type Defaults', () => {
|
|
|
320
320
|
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
321
321
|
expect(entityClass).toBe('item');
|
|
322
322
|
});
|
|
323
|
+
it('project-item - LCSProductSeasonLink', () => {
|
|
324
|
+
const object = {
|
|
325
|
+
flexPLMObjectClass: 'LCSProductSeasonLink'
|
|
326
|
+
};
|
|
327
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
328
|
+
expect(entityClass).toBe('project-item');
|
|
329
|
+
});
|
|
330
|
+
it('project-item - LCSSKUSeasonLink', () => {
|
|
331
|
+
const object = {
|
|
332
|
+
flexPLMObjectClass: 'LCSSKUSeasonLink'
|
|
333
|
+
};
|
|
334
|
+
const entityClass = type_defaults_1.TypeDefaults.getDefaultEntityClass(object);
|
|
335
|
+
expect(entityClass).toBe('project-item');
|
|
336
|
+
});
|
|
323
337
|
it('color - LCSColor', () => {
|
|
324
338
|
const object = {
|
|
325
339
|
flexPLMObjectClass: 'LCSColor'
|
|
@@ -376,14 +390,14 @@ describe('Type Defaults', () => {
|
|
|
376
390
|
flexPLMObjectClass: 'LCSProductSeasonLink'
|
|
377
391
|
};
|
|
378
392
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
379
|
-
expect(typePath).toBe('item');
|
|
393
|
+
expect(typePath).toBe('project-item');
|
|
380
394
|
});
|
|
381
395
|
it('LCSSKUSeasonLink', () => {
|
|
382
396
|
const object = {
|
|
383
397
|
flexPLMObjectClass: 'LCSSKUSeasonLink'
|
|
384
398
|
};
|
|
385
399
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
386
|
-
expect(typePath).toBe('item');
|
|
400
|
+
expect(typePath).toBe('project-item');
|
|
387
401
|
});
|
|
388
402
|
it('LCSColor', () => {
|
|
389
403
|
const object = {
|
|
@@ -392,6 +406,20 @@ describe('Type Defaults', () => {
|
|
|
392
406
|
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
393
407
|
expect(typePath).toBe('color');
|
|
394
408
|
});
|
|
409
|
+
it('LCSSeason', () => {
|
|
410
|
+
const object = {
|
|
411
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
412
|
+
};
|
|
413
|
+
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
414
|
+
expect(typePath).toBe('assortment');
|
|
415
|
+
});
|
|
416
|
+
it('SeasonGroup', () => {
|
|
417
|
+
const object = {
|
|
418
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
419
|
+
};
|
|
420
|
+
const typePath = type_defaults_1.TypeDefaults.getDefaultEntityTypePath(object);
|
|
421
|
+
expect(typePath).toBe('assortment');
|
|
422
|
+
});
|
|
395
423
|
});
|
|
396
424
|
describe('getDefaultIdentifierPropertiesFromObject', () => {
|
|
397
425
|
it('LCSProduct', () => {
|
package/package.json
CHANGED
|
@@ -869,4 +869,75 @@ describe('setEnumerationKeys', () =>{
|
|
|
869
869
|
expect(returnValue).toEqual([]);
|
|
870
870
|
});
|
|
871
871
|
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
describe('checkKeysAndValues', () =>{
|
|
875
|
+
const config: FCConfig = {
|
|
876
|
+
apiHost: 'host',
|
|
877
|
+
userName: () => 'user',
|
|
878
|
+
password: () => 'pass',
|
|
879
|
+
urlContext: 'xxx',
|
|
880
|
+
vibeEventEndpoint: '/rfa/vibeiq/vibeEvents',
|
|
881
|
+
csrfEndpoint: '/servlet/rest/security/csrf',
|
|
882
|
+
itemPreDevelopmentLifecycleStages: ['concept']
|
|
883
|
+
};
|
|
884
|
+
|
|
885
|
+
const mapFileUtil = new MapFileUtil(new Entities());
|
|
886
|
+
const dc = new DataConverter(config, mapFileUtil);
|
|
887
|
+
const groupData = [
|
|
888
|
+
{name: 'Group 1', typePath: 'custom-entity:grouping'},
|
|
889
|
+
{name: 'Group 2', typePath: 'custom-entity:grouping'},
|
|
890
|
+
{name: 'Group 2', typePath: 'custom-entity:grouping'},
|
|
891
|
+
{name: 'Group 4', typePath: 'custom-entity:grouping'},
|
|
892
|
+
{name: 'Group 4', typePath: 'custom-entity:grouping:sub'},
|
|
893
|
+
{name: 'Group 5', typePath: 'custom-entity:grouping:sub'}
|
|
894
|
+
];
|
|
895
|
+
//item:product:newBalance:accessories, item:product:newBalance:apparel
|
|
896
|
+
|
|
897
|
+
it('Group 1', () =>{
|
|
898
|
+
const criteria = {
|
|
899
|
+
name: 'Group 1'
|
|
900
|
+
}
|
|
901
|
+
const typePath = 'custom-entity:grouping';
|
|
902
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
903
|
+
expect(results.length).toBe(1);
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
it('Group 5 - sub type of typePath', () =>{
|
|
907
|
+
const criteria = {
|
|
908
|
+
name: 'Group 5'
|
|
909
|
+
}
|
|
910
|
+
const typePath = 'custom-entity:grouping';
|
|
911
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
912
|
+
expect(results.length).toBe(1);
|
|
913
|
+
});
|
|
914
|
+
it('Group 2 - returns the 2 matching', () =>{
|
|
915
|
+
const criteria = {
|
|
916
|
+
name: 'Group 2'
|
|
917
|
+
}
|
|
918
|
+
const typePath = 'custom-entity:grouping';
|
|
919
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
920
|
+
expect(results.length).toBe(2);
|
|
921
|
+
});
|
|
922
|
+
|
|
923
|
+
it('2 Same Name - but 1 is a sub type; returns 2', () =>{
|
|
924
|
+
const criteria = {
|
|
925
|
+
name: 'Group 4'
|
|
926
|
+
}
|
|
927
|
+
const typePath = 'custom-entity:grouping';
|
|
928
|
+
const results = dc.checkKeysAndValues(criteria, groupData, typePath);
|
|
929
|
+
expect(results.length).toBe(2);
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
it('2 Same Name - but 1 wrong type', () =>{
|
|
933
|
+
const criteria = {
|
|
934
|
+
name: 'Group 1'
|
|
935
|
+
}
|
|
936
|
+
const testData =[...groupData];
|
|
937
|
+
testData.push({name: 'Group 1', typePath: 'custom-entity:label'});
|
|
938
|
+
const typePath = 'custom-entity:grouping';
|
|
939
|
+
const results = dc.checkKeysAndValues(criteria, testData, typePath);
|
|
940
|
+
expect(results.length).toBe(1);
|
|
941
|
+
});
|
|
942
|
+
|
|
872
943
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Entities, TypeClientOptions } from '@contrail/sdk';
|
|
1
|
+
import { API_VERSION, Entities, TypeClientOptions } from '@contrail/sdk';
|
|
2
2
|
import { TypeUtils } from './type-utils';
|
|
3
3
|
import { FCConfig } from '../interfaces/interfaces';
|
|
4
4
|
import { MapFileUtil } from '@contrail/transform-data';
|
|
@@ -240,7 +240,7 @@ export class DataConverter {
|
|
|
240
240
|
const propertyType = prop['propertyType'];
|
|
241
241
|
const slug = prop['slug'];
|
|
242
242
|
let keyName = slug;
|
|
243
|
-
if(propertyType === 'userList') {
|
|
243
|
+
if (propertyType === 'userList' || propertyType === 'object_reference') {
|
|
244
244
|
keyName = slug + 'Id';
|
|
245
245
|
}
|
|
246
246
|
entity[keyName] = await this.getEntityValue(prop, data);
|
|
@@ -323,8 +323,7 @@ export class DataConverter {
|
|
|
323
323
|
value = this.setEnumerationKeys(prop, nd, this.useDisplayForEnumerationMatching);
|
|
324
324
|
|
|
325
325
|
} else if ('object_reference' === propertyType) {
|
|
326
|
-
|
|
327
|
-
//use referencedTypeRootSlug to get the entity type
|
|
326
|
+
value = await this.setObjectReferenceValue(prop, nd);
|
|
328
327
|
} else if ('image' === propertyType) {
|
|
329
328
|
// console.log('TODO-image');
|
|
330
329
|
} else if ('formula' === propertyType) {
|
|
@@ -395,6 +394,129 @@ export class DataConverter {
|
|
|
395
394
|
|
|
396
395
|
}
|
|
397
396
|
|
|
397
|
+
/** Sets object reference value from FlexPLM data passed in
|
|
398
|
+
*
|
|
399
|
+
* @param prop the VibeIQ property
|
|
400
|
+
* @param nd the VibeIQ data
|
|
401
|
+
* @returns the object reference id from VibeIQ
|
|
402
|
+
*/
|
|
403
|
+
async setObjectReferenceValue(prop, nd) {
|
|
404
|
+
let objectReferenceId = "";
|
|
405
|
+
if(!nd) {
|
|
406
|
+
return objectReferenceId;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const entityType = prop['referencedTypeRootSlug'];
|
|
410
|
+
const entityTypePath = prop['referencedTypePath'];
|
|
411
|
+
const entityKeys = Object.keys(nd);
|
|
412
|
+
const identifierKeys = await TypeConversionUtils.getIdentifierPropertiesFromObject(this.transformMapFile, this.mapFileUtil, nd)
|
|
413
|
+
const hasAllIdentifiers = identifierKeys.every(key => entityKeys.includes(key));
|
|
414
|
+
if(identifierKeys.length == 0 || !hasAllIdentifiers){
|
|
415
|
+
console.warn(`The inbound ${entityType} doesnt have all "identifier properties, so there is no processing. Identifier properties: ${identifierKeys}`);
|
|
416
|
+
return objectReferenceId;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
const rootType = await this.typeUtils.getByRootAndPath({root: entityType});
|
|
420
|
+
const rootTypeProps = this.typeUtils.filterTypeProperties(rootType, nd);
|
|
421
|
+
|
|
422
|
+
let rootTypeCriteria = {};
|
|
423
|
+
let typeCriteria = { };
|
|
424
|
+
identifierKeys.forEach(keyName => {
|
|
425
|
+
const foundInObjects = rootTypeProps.some(obj => obj.slug === keyName);
|
|
426
|
+
if (foundInObjects) {
|
|
427
|
+
rootTypeCriteria[keyName] = nd[keyName];
|
|
428
|
+
} else {
|
|
429
|
+
typeCriteria[keyName] = nd[keyName];
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
const combinedCriteria = { ...rootTypeCriteria, ...typeCriteria, typePath: entityTypePath };
|
|
434
|
+
const cacheKey = Object.values(combinedCriteria).join('_');
|
|
435
|
+
|
|
436
|
+
if (this.objRefCache[cacheKey]) {
|
|
437
|
+
if (Logger.isDebugOn()) {
|
|
438
|
+
console.debug(`object reference cache hit: ${cacheKey}`);
|
|
439
|
+
}
|
|
440
|
+
return this.objRefCache[cacheKey];
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
let arrObjectReferences = await this.getAllObjectReferences(entityType, rootTypeCriteria);
|
|
444
|
+
if(entityType !== entityTypePath) {
|
|
445
|
+
arrObjectReferences = this.checkKeysAndValues(typeCriteria, arrObjectReferences, entityTypePath);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if(arrObjectReferences.length) {
|
|
449
|
+
if(arrObjectReferences.length === 1) {
|
|
450
|
+
objectReferenceId = arrObjectReferences[0].id;
|
|
451
|
+
} else {
|
|
452
|
+
console.warn(`The passed in object reference criteria has duplicate records found ${JSON.stringify(combinedCriteria)}.`);
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (!objectReferenceId) {
|
|
457
|
+
console.warn(`The passed in object reference criteria ${JSON.stringify(combinedCriteria)} not found.`);
|
|
458
|
+
return objectReferenceId;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
this.objRefCache[cacheKey] = objectReferenceId;
|
|
462
|
+
|
|
463
|
+
return objectReferenceId;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Retrieves all object references of a specified entity type based on the provided criteria.
|
|
468
|
+
* This function handles pagination and asynchronously fetches object references until there are no more pages.
|
|
469
|
+
* @param {string} entityType - The type of entity for which object references are to be retrieved.
|
|
470
|
+
* @param {object} rootTypeCriteria - The criteria used to filter object references.
|
|
471
|
+
* @returns {Promise<Array>} A Promise that resolves to an array containing all object references.
|
|
472
|
+
*/
|
|
473
|
+
async getAllObjectReferences(entityType, rootTypeCriteria) {
|
|
474
|
+
let loads = []
|
|
475
|
+
let nextPageKey;
|
|
476
|
+
do {
|
|
477
|
+
const loadPage = await new Entities().get({ entityName: entityType, criteria: rootTypeCriteria, apiVersion: API_VERSION.V2, nextPageKey })
|
|
478
|
+
nextPageKey = loadPage.nextPageKey;
|
|
479
|
+
loads.push(...loadPage.results);
|
|
480
|
+
} while (nextPageKey);
|
|
481
|
+
return loads;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/**
|
|
485
|
+
* Checks if all keys and values of a given object are present in an array of objects.
|
|
486
|
+
* @param {Object} criteria - The object whose keys and values are to be checked in the array of objects.
|
|
487
|
+
* @param {Array<Object>} arrayOfObjects - The array of objects to be searched for matching keys and values.
|
|
488
|
+
* @param {string} entityTypePath - The type / subtype for the property; objects must be this type or a sub type of it.
|
|
489
|
+
* @returns {(Object|boolean)} Returns the array of objects that matches all keys and values of the provided object.
|
|
490
|
+
* If no match is found, returns empty array.
|
|
491
|
+
*/
|
|
492
|
+
checkKeysAndValues(criteria, arrayOfObjects, entityTypePath) {
|
|
493
|
+
let arrOfMatchObjects = [];
|
|
494
|
+
for (let i = 0; i < arrayOfObjects.length; i++) {
|
|
495
|
+
const currentObj = arrayOfObjects[i];
|
|
496
|
+
let found = true;
|
|
497
|
+
|
|
498
|
+
if(entityTypePath && currentObj['typePath']){
|
|
499
|
+
const currentObjPath = '' + currentObj['typePath'];
|
|
500
|
+
if(!currentObjPath.startsWith(entityTypePath)){
|
|
501
|
+
found = false;
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
for (const key in criteria) {
|
|
506
|
+
if (!(key in currentObj) || currentObj[key] !== criteria[key]) {
|
|
507
|
+
found = false;
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (found) {
|
|
513
|
+
arrOfMatchObjects.push(currentObj);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
return arrOfMatchObjects;
|
|
518
|
+
}
|
|
519
|
+
|
|
398
520
|
/** Sets userListId value from FlexPLM data passed in
|
|
399
521
|
*
|
|
400
522
|
* @param prop the VibeIQ property
|
|
@@ -415,6 +415,26 @@ describe('Type Defaults', () =>{
|
|
|
415
415
|
expect(entityClass).toBe('item');
|
|
416
416
|
});
|
|
417
417
|
|
|
418
|
+
it('project-item - LCSProductSeasonLink', () =>{
|
|
419
|
+
const object = {
|
|
420
|
+
flexPLMObjectClass: 'LCSProductSeasonLink'
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
424
|
+
|
|
425
|
+
expect(entityClass).toBe('project-item');
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it('project-item - LCSSKUSeasonLink', () =>{
|
|
429
|
+
const object = {
|
|
430
|
+
flexPLMObjectClass: 'LCSSKUSeasonLink'
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
const entityClass = TypeDefaults.getDefaultEntityClass(object);
|
|
434
|
+
|
|
435
|
+
expect(entityClass).toBe('project-item');
|
|
436
|
+
});
|
|
437
|
+
|
|
418
438
|
it('color - LCSColor', () =>{
|
|
419
439
|
const object = {
|
|
420
440
|
flexPLMObjectClass: 'LCSColor'
|
|
@@ -491,7 +511,7 @@ describe('Type Defaults', () =>{
|
|
|
491
511
|
};
|
|
492
512
|
|
|
493
513
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
494
|
-
expect(typePath).toBe('item');
|
|
514
|
+
expect(typePath).toBe('project-item');
|
|
495
515
|
});
|
|
496
516
|
|
|
497
517
|
it('LCSSKUSeasonLink', () =>{
|
|
@@ -500,7 +520,7 @@ describe('Type Defaults', () =>{
|
|
|
500
520
|
};
|
|
501
521
|
|
|
502
522
|
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
503
|
-
expect(typePath).toBe('item');
|
|
523
|
+
expect(typePath).toBe('project-item');
|
|
504
524
|
});
|
|
505
525
|
|
|
506
526
|
it('LCSColor', () =>{
|
|
@@ -512,6 +532,23 @@ describe('Type Defaults', () =>{
|
|
|
512
532
|
expect(typePath).toBe('color');
|
|
513
533
|
});
|
|
514
534
|
|
|
535
|
+
it('LCSSeason', () =>{
|
|
536
|
+
const object = {
|
|
537
|
+
flexPLMObjectClass: 'LCSSeason'
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
541
|
+
expect(typePath).toBe('assortment');
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
it('SeasonGroup', () =>{
|
|
545
|
+
const object = {
|
|
546
|
+
flexPLMObjectClass: 'SeasonGroup'
|
|
547
|
+
};
|
|
548
|
+
|
|
549
|
+
const typePath = TypeDefaults.getDefaultEntityTypePath(object);
|
|
550
|
+
expect(typePath).toBe('assortment');
|
|
551
|
+
});
|
|
515
552
|
});//getDefaultEntityTypePath
|
|
516
553
|
|
|
517
554
|
describe('getDefaultIdentifierPropertiesFromObject', () =>{
|
|
@@ -170,6 +170,8 @@ export class TypeDefaults {
|
|
|
170
170
|
let objectClass = TypeDefaults.getObjectClass(object);
|
|
171
171
|
if(['LCSProduct', 'LCSSKU'].includes(objectClass)){
|
|
172
172
|
entityClass = 'item';
|
|
173
|
+
}else if(['LCSProductSeasonLink', 'LCSSKUSeasonLink'].includes(objectClass)){
|
|
174
|
+
entityClass = 'project-item'
|
|
173
175
|
} else if('LCSColor' === objectClass){
|
|
174
176
|
entityClass = 'color';
|
|
175
177
|
} else if(['LCSSeason', 'SeasonGroup'].includes(objectClass)) {
|
|
@@ -197,14 +199,20 @@ export class TypeDefaults {
|
|
|
197
199
|
switch (objectClass) {
|
|
198
200
|
case 'LCSProduct':
|
|
199
201
|
case 'LCSSKU':
|
|
202
|
+
typePath = 'item';
|
|
203
|
+
break;
|
|
200
204
|
case 'LCSProductSeasonLink':
|
|
201
205
|
case 'LCSSKUSeasonLink':
|
|
202
|
-
typePath = 'item';
|
|
206
|
+
typePath = 'project-item';
|
|
203
207
|
break;
|
|
204
208
|
case 'LCSColor':
|
|
205
209
|
typePath = 'color';
|
|
206
210
|
break;
|
|
207
|
-
|
|
211
|
+
case 'LCSSeason':
|
|
212
|
+
case 'SeasonGroup':
|
|
213
|
+
typePath = 'assortment';
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
208
216
|
|
|
209
217
|
if(typePath === '')
|
|
210
218
|
throw Error(TypeDefaults.NO_TYPE_PATH);
|