@contrail/flexplm 1.5.1-alpha.c9b11be → 1.6.0-alpha.6f15d4e

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.
Files changed (111) hide show
  1. package/lib/cli/commands/compile.d.ts +4 -0
  2. package/lib/cli/commands/compile.js +73 -0
  3. package/lib/cli/commands/compile.spec.d.ts +1 -0
  4. package/lib/cli/commands/compile.spec.js +80 -0
  5. package/lib/cli/commands/create.d.ts +5 -0
  6. package/lib/cli/commands/create.js +77 -0
  7. package/lib/cli/commands/create.spec.d.ts +1 -0
  8. package/lib/cli/commands/create.spec.js +78 -0
  9. package/lib/cli/commands/upload.d.ts +17 -0
  10. package/lib/cli/commands/upload.js +228 -0
  11. package/lib/cli/commands/upload.spec.d.ts +1 -0
  12. package/lib/cli/commands/upload.spec.js +88 -0
  13. package/lib/cli/index.d.ts +5 -0
  14. package/lib/cli/index.js +70 -0
  15. package/lib/cli/index.spec.d.ts +1 -0
  16. package/lib/cli/index.spec.js +85 -0
  17. package/lib/cli/template/mapping-template.ts.template +62 -0
  18. package/lib/entity-processor/base-entity-processor.d.ts +65 -0
  19. package/lib/entity-processor/base-entity-processor.js +71 -0
  20. package/lib/entity-processor/base-entity-processor.spec.js +1 -0
  21. package/lib/index.d.ts +1 -0
  22. package/lib/index.js +1 -0
  23. package/lib/interfaces/mapping-file.d.ts +460 -0
  24. package/lib/interfaces/mapping-file.js +2 -0
  25. package/lib/publish/base-process-publish-assortment.d.ts +25 -1
  26. package/lib/publish/base-process-publish-assortment.js +67 -48
  27. package/lib/publish/base-process-publish-assortment.spec.js +22 -143
  28. package/lib/publish/mockData.js +5 -0
  29. package/lib/transform/identifier-conversion-spec-mockData.js +34 -6
  30. package/lib/transform/identifier-conversion.d.ts +36 -0
  31. package/lib/transform/identifier-conversion.js +36 -0
  32. package/lib/transform/identifier-conversion.spec.js +4 -0
  33. package/lib/util/config-defaults.js +3 -0
  34. package/lib/util/config-defaults.spec.js +9 -0
  35. package/lib/util/data-converter-spec-mockData.js +17 -3
  36. package/lib/util/data-converter.d.ts +97 -0
  37. package/lib/util/data-converter.js +127 -1
  38. package/lib/util/data-converter.spec.js +2 -0
  39. package/lib/util/error-response-object.d.ts +5 -0
  40. package/lib/util/error-response-object.js +7 -0
  41. package/lib/util/event-short-message-status.js +1 -0
  42. package/lib/util/federation.js +8 -0
  43. package/lib/util/flexplm-connect.d.ts +7 -0
  44. package/lib/util/flexplm-connect.js +14 -0
  45. package/lib/util/logger-config.js +1 -0
  46. package/lib/util/map-util-spec-mockData.js +17 -3
  47. package/lib/util/map-utils.d.ts +27 -0
  48. package/lib/util/map-utils.js +27 -0
  49. package/lib/util/thumbnail-util.d.ts +21 -0
  50. package/lib/util/thumbnail-util.js +28 -1
  51. package/lib/util/thumbnail-util.spec.js +6 -0
  52. package/lib/util/type-conversion-utils-spec-mockData.js +3 -3
  53. package/lib/util/type-conversion-utils.d.ts +151 -0
  54. package/lib/util/type-conversion-utils.js +154 -0
  55. package/lib/util/type-defaults.d.ts +66 -0
  56. package/lib/util/type-defaults.js +66 -0
  57. package/lib/util/type-defaults.spec.js +5 -5
  58. package/lib/util/type-utils.d.ts +21 -0
  59. package/lib/util/type-utils.js +23 -0
  60. package/lib/util/type-utils.spec.js +2 -0
  61. package/package.json +21 -6
  62. package/scripts/copy-template.js +10 -0
  63. package/.github/pull_request_template.md +0 -31
  64. package/.github/workflows/flexplm-lib.yml +0 -27
  65. package/.github/workflows/publish-to-npm.yml +0 -121
  66. package/CHANGELOG.md +0 -49
  67. package/publish.bat +0 -5
  68. package/publish.sh +0 -5
  69. package/src/entity-processor/base-entity-processor.spec.ts +0 -689
  70. package/src/entity-processor/base-entity-processor.ts +0 -583
  71. package/src/flexplm-request.ts +0 -28
  72. package/src/flexplm-utils.spec.ts +0 -27
  73. package/src/flexplm-utils.ts +0 -29
  74. package/src/index.ts +0 -22
  75. package/src/interfaces/interfaces.ts +0 -122
  76. package/src/interfaces/item-family-changes.ts +0 -67
  77. package/src/interfaces/publish-change-data.ts +0 -43
  78. package/src/publish/base-process-publish-assortment-callback.ts +0 -50
  79. package/src/publish/base-process-publish-assortment.spec.ts +0 -2154
  80. package/src/publish/base-process-publish-assortment.ts +0 -1173
  81. package/src/publish/mockData.ts +0 -4561
  82. package/src/transform/identifier-conversion-spec-mockData.ts +0 -496
  83. package/src/transform/identifier-conversion.spec.ts +0 -386
  84. package/src/transform/identifier-conversion.ts +0 -282
  85. package/src/util/config-defaults.spec.ts +0 -445
  86. package/src/util/config-defaults.ts +0 -106
  87. package/src/util/data-converter-spec-mockData.ts +0 -231
  88. package/src/util/data-converter.spec.ts +0 -1622
  89. package/src/util/data-converter.ts +0 -819
  90. package/src/util/error-response-object.spec.ts +0 -116
  91. package/src/util/error-response-object.ts +0 -50
  92. package/src/util/event-short-message-status.ts +0 -22
  93. package/src/util/federation.ts +0 -172
  94. package/src/util/flexplm-connect.spec.ts +0 -132
  95. package/src/util/flexplm-connect.ts +0 -208
  96. package/src/util/logger-config.ts +0 -20
  97. package/src/util/map-util-spec-mockData.ts +0 -231
  98. package/src/util/map-utils.spec.ts +0 -103
  99. package/src/util/map-utils.ts +0 -41
  100. package/src/util/mockData.ts +0 -101
  101. package/src/util/thumbnail-util.spec.ts +0 -508
  102. package/src/util/thumbnail-util.ts +0 -272
  103. package/src/util/type-conversion-utils-spec-mockData.ts +0 -272
  104. package/src/util/type-conversion-utils.spec.ts +0 -1031
  105. package/src/util/type-conversion-utils.ts +0 -490
  106. package/src/util/type-defaults.spec.ts +0 -797
  107. package/src/util/type-defaults.ts +0 -320
  108. package/src/util/type-utils.spec.ts +0 -227
  109. package/src/util/type-utils.ts +0 -144
  110. package/tsconfig.json +0 -24
  111. package/tslint.json +0 -57
@@ -13,7 +13,7 @@ const app_framework_1 = require("@contrail/app-framework");
13
13
  const event_short_message_status_1 = require("../util/event-short-message-status");
14
14
  class BaseProcessPublishAssortment {
15
15
  constructor(_config, _dc, _mapFileUtil) {
16
- this.TTL = 30 * 24 * 60 * 60 * 1000;
16
+ this.TTL = 30 * 24 * 60 * 60 * 1000; // 30 days
17
17
  this.cache = {
18
18
  carriedFromSeason: {}
19
19
  };
@@ -52,13 +52,14 @@ class BaseProcessPublishAssortment {
52
52
  }
53
53
  apcHistory = await this.getApcHistory(assortmentId);
54
54
  const sinceDate = await this.getSinceDate(assortmentId, assortmentPublishChangeId, apcHistory);
55
+ //Get detail information
55
56
  const assortmentPublishChange = await this.downloadAssortmentPublishChange(assortmentId, assortmentPublishChangeId);
56
57
  publisher = this.getPublisher(assortmentPublishChange);
57
58
  const changeDetail = await this.downloadHydratedChangeDetail(assortmentPublishChange);
58
59
  const assortmentBaseline = await this.downloadAssortmentBaseline(assortmentPublishChange);
59
60
  const deleteChanges = await this.getDeleteChanges(assortmentPublishChange, apcHistory, assortmentBaseline, sinceDate);
60
61
  const releasedForDevelopmentItemIds = this.getReleasedForDevelopmentItemAndFamilyIds(assortmentBaseline, deleteChanges);
61
- const itemToFederatedIdMapping = await this.getItemFederatedIds();
62
+ const itemToFederatedIdMapping = await this.getItemFederatedIds( /*allItemIds*/);
62
63
  const pcd = new publish_change_data_1.PublishChangeData(assortmentId, seasonFed, assortmentPublishChangeId, sinceDate, publisher);
63
64
  pcd.itemToFederatedIdMapping = itemToFederatedIdMapping;
64
65
  pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
@@ -94,6 +95,15 @@ class BaseProcessPublishAssortment {
94
95
  };
95
96
  return publishInfo;
96
97
  }
98
+ /** Gets the version number of the snapshot that was created for the publish change.
99
+ * But if no snapshot was found for the publish change, and the last snapshot was
100
+ * created before the publish change, then it returns 'after: versionNumber' where
101
+ * versionNumber is the version number of the last snapshot.
102
+ * If no snapshot was found for the publish change, and the last snapshot was
103
+ * created after the publish change, then it returns 'unknown'.
104
+ *
105
+ * @returns versionNumber or 'unknown' or 'after: versionNumber'
106
+ */
97
107
  async getSnapshotVersion(assortment, apc) {
98
108
  const entityReference = assortment?.createdForReference;
99
109
  const createdOnString = apc?.createdOn;
@@ -101,7 +111,7 @@ class BaseProcessPublishAssortment {
101
111
  return 'unknown';
102
112
  }
103
113
  const createdOnDate = new Date(createdOnString);
104
- createdOnDate.setMonth(createdOnDate.getMonth() - 1);
114
+ createdOnDate.setMonth(createdOnDate.getMonth() - 1); //subtract 1 month
105
115
  const createdOnStringMinus1 = createdOnDate.toISOString();
106
116
  const createdOn = 'ISGREATERTHAN ' + createdOnStringMinus1;
107
117
  const snapshots = await new sdk_1.Entities().get({
@@ -348,6 +358,7 @@ class BaseProcessPublishAssortment {
348
358
  console.info('sinceDateMilliseconds: ' + sinceDateMilliseconds);
349
359
  console.info('apcDateMilliseconds: ' + previousApcDate);
350
360
  }
361
+ //if only 1 apc, no processing needed
351
362
  if (sinceDateMilliseconds !== previousApcDate) {
352
363
  console.info('sinceDateMilliseconds !== apcDateMilliseconds');
353
364
  const currentAssortmentItemIds = this.getBaselineItemIds(assortmentBaseline);
@@ -433,12 +444,27 @@ class BaseProcessPublishAssortment {
433
444
  previousBaseline = await this.downloadAssortmentBaseline(previousApc);
434
445
  }
435
446
  const deleteIds = apc?.detail?.deletes.map(dItem => dItem?.id);
447
+ //building deletes based on previous baseline; because some APCs don't have delete data
436
448
  const deleteArray = previousBaseline?.assortmentItems.filter(aItem => deleteIds.includes(aItem?.itemId));
437
449
  console.info('deleteArray.length: ' + deleteArray.length);
438
450
  return deleteArray;
439
451
  }
440
- async getItemFederatedIds() {
452
+ async getItemFederatedIds( /*itemIds*/) {
441
453
  const itemFederatedIds = new Map();
454
+ // const expandedItemIds = itemIds.map(id => 'item:' + id);
455
+ // const fedRecords = await new Federation(this.logger).getFederationRecordsFromIdsBulk(expandedItemIds);
456
+ // for (let i = 0; i < fedRecords.length; i++) {
457
+ // const federationRecord = fedRecords[i];
458
+ // // console.log('federationRecord: ' + JSON.stringify(federationRecord));
459
+ // // console.log('federationRecord.reference: ' + federationRecord.reference);
460
+ // // console.log('federationRecord.mappedReference: ' + federationRecord.mappedReference);
461
+ // let vibeId = federationRecord.reference;
462
+ // if (vibeId && vibeId.startsWith('item:')) {
463
+ // vibeId = vibeId.substring(5);
464
+ // }
465
+ // itemFederatedIds.set(vibeId, federationRecord.mappedReference);
466
+ // }
467
+ // console.log('itemFederatedIds: ' + JSON.stringify(Object.fromEntries(itemFederatedIds)));
442
468
  return itemFederatedIds;
443
469
  }
444
470
  getFullChangeAssortmentMap(fullChange) {
@@ -565,27 +591,18 @@ class BaseProcessPublishAssortment {
565
591
  case 'vibeiqfile-dontsendtoflexplm':
566
592
  return this.handleVibeIQFile(events, eventType, sendMode);
567
593
  default:
568
- return {};
594
+ return {}; // Or handle other cases as required
569
595
  }
570
596
  }
571
597
  async sendToFlexPLM(events, eventType) {
572
- const outboundPublishEvent = {
598
+ const asyncEvent = {
573
599
  taskId: this.config.taskId,
574
600
  eventType,
575
601
  objectClass: 'LCSSeason',
576
602
  events
577
603
  };
578
604
  const flexPLMConnect = new flexplm_connect_1.FlexPLMConnect(this.config);
579
- const [sendResult] = await Promise.allSettled([
580
- flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
581
- this.sendPublishPayloadEvent(outboundPublishEvent)
582
- ]);
583
- const result = sendResult.status === 'fulfilled' ? sendResult.value : { error: sendResult.reason?.message };
584
- const isResultObject = typeof result === 'object' && result !== null;
585
- const resultWithOutboundPublishEvent = isResultObject
586
- ? { ...result, outboundPublishEvent }
587
- : { result, outboundPublishEvent };
588
- return resultWithOutboundPublishEvent;
605
+ return await flexPLMConnect.sendToFlexPLM(asyncEvent);
589
606
  }
590
607
  async saveToLocalFile(events, eventType) {
591
608
  let results = {};
@@ -597,16 +614,15 @@ class BaseProcessPublishAssortment {
597
614
  const eventDirName = 'events-output';
598
615
  const fileName = `${path.sep}${eventDirName}${path.sep}events-${dateString}.json`;
599
616
  fileHandle = await fsPromise.open('.' + fileName, 'a');
600
- const outboundPublishEvent = {
617
+ const asyncEvent = {
601
618
  taskId: this.config.taskId,
602
619
  eventType,
603
620
  objectClass: 'LCSSeason',
604
621
  events
605
622
  };
606
- await fileHandle.writeFile(JSON.stringify(outboundPublishEvent));
623
+ await fileHandle.writeFile(JSON.stringify(asyncEvent));
607
624
  results = {
608
625
  message: 'Successfully Saved File',
609
- outboundPublishEvent,
610
626
  fileLocation: dirName + fileName
611
627
  };
612
628
  }
@@ -622,7 +638,7 @@ class BaseProcessPublishAssortment {
622
638
  const eventBuffer = Buffer.from(JSON.stringify(events), 'utf-8');
623
639
  const fileName = 'ASYNC_PUBLISH_SEASON-events.json';
624
640
  const uploadFile = await new sdk_1.Files().createAndUploadFileFromBuffer(eventBuffer, 'application/json', fileName, null, this.TTL);
625
- const outboundPublishEvent = {
641
+ const asyncEvent = {
626
642
  taskId: this.config.taskId,
627
643
  eventType,
628
644
  objectClass: 'LCSSeason',
@@ -632,40 +648,15 @@ class BaseProcessPublishAssortment {
632
648
  };
633
649
  if (sendMode === 'vibeiqfile') {
634
650
  const flexPLMConnect = new flexplm_connect_1.FlexPLMConnect(this.config);
635
- const [sendResult] = await Promise.allSettled([
636
- flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
637
- this.sendPublishPayloadEvent(outboundPublishEvent)
638
- ]);
639
- const result = sendResult.status === 'fulfilled' ? sendResult.value : { error: sendResult.reason?.message };
640
- return { ...result, outboundPublishEvent };
651
+ return await flexPLMConnect.sendToFlexPLM(asyncEvent);
641
652
  }
642
653
  else {
643
- await this.sendPublishPayloadEvent(outboundPublishEvent);
644
654
  return {
645
655
  message: 'Successfully Uploaded File.',
646
- outboundPublishEvent
656
+ asyncEvent
647
657
  };
648
658
  }
649
659
  }
650
- async sendPublishPayloadEvent(outboundPublishEvent) {
651
- console.info('sendPublishPayloadEvent()');
652
- let initialEvent = {};
653
- if (this.config?.event) {
654
- initialEvent = (typeof this.config?.event === 'string')
655
- ? JSON.parse(this.config?.event)
656
- : this.config?.event;
657
- }
658
- const eventBody = {
659
- originSystemType: 'VibeIQ',
660
- objectClass: 'AssortmentPublishedToFlexPLM',
661
- outboundPublishEvent,
662
- initialEvent
663
- };
664
- await new sdk_1.Entities().create({
665
- entityName: 'external-event',
666
- object: eventBody
667
- });
668
- }
669
660
  getCurrentDateString() {
670
661
  const d = new Date();
671
662
  return '' + d.getUTCFullYear()
@@ -770,7 +761,7 @@ class BaseProcessPublishAssortment {
770
761
  else {
771
762
  ifc.colorDeletes.push(itemId);
772
763
  }
773
- }
764
+ } //End deletes for loop
774
765
  if (app_framework_1.Logger.isDebugOn()) {
775
766
  console.debug('returning size: ' + itemFamilyChanges.size);
776
767
  for (const [key, value] of itemFamilyChanges) {
@@ -790,6 +781,22 @@ class BaseProcessPublishAssortment {
790
781
  }
791
782
  return seasonalPayloads;
792
783
  }
784
+ /**Returns the events for a given ItemFamilyChanges object
785
+ *
786
+ * Cases:
787
+ * Add just family:
788
+ * Add option to family (with existing option):
789
+ * Add option to family (no options on assortment):
790
+ * Remove family and option:
791
+ * Remove only option and leave family:
792
+ * Remove one option of multiple for family:
793
+ *
794
+ * @param itemFamilyChanges
795
+ * @param assortmentId
796
+ * @param assortmentFederationId
797
+ * @param itemToFederatedIdMapping
798
+ * @returns
799
+ */
793
800
  async getEventsForItemFamilyChanges(itemFamilyChanges, assortmentId, seasonFed, itemToFederatedIdMapping) {
794
801
  console.info('getEventsForItemFamilyChanges()');
795
802
  const events = [];
@@ -799,7 +806,10 @@ class BaseProcessPublishAssortment {
799
806
  const familyAssortmentItem = itemFamilyChanges.familyAdd || itemFamilyChanges.familyUpdate || itemFamilyChanges.familyDelete
800
807
  || itemFamilyChanges.colorAdds.length > 0 || itemFamilyChanges.colorUpdates.length > 0 || itemFamilyChanges.colorDeletes.length > 0
801
808
  || (projectItem && this.updatedSinceDate(projectItem, itemFamilyChanges.sinceDate));
809
+ //familyItemRemoved is used when adding the first option to an assortment
810
+ //and will have updates for the family item.
802
811
  if (familyAssortmentItem) {
812
+ //Product-season add
803
813
  const entityReference = itemFamilyChanges.itemFamilyId;
804
814
  const prodEntityData = (itemFamilyChanges.assortmentItemFullChangeMap.has(entityReference))
805
815
  ? itemFamilyChanges.assortmentItemFullChangeMap.get(entityReference)?.item
@@ -825,6 +835,9 @@ class BaseProcessPublishAssortment {
825
835
  }
826
836
  events.push(psUpsert);
827
837
  }
838
+ //colorway-season adds
839
+ //colorAdds
840
+ //colorUpdates
828
841
  const colorwayChanges = [];
829
842
  colorwayChanges.push(...itemFamilyChanges.colorAdds);
830
843
  colorwayChanges.push(...itemFamilyChanges.colorUpdates);
@@ -865,6 +878,9 @@ class BaseProcessPublishAssortment {
865
878
  const aItem = itemFamilyChanges?.assortmentItemFullChangeMap.get(id);
866
879
  projectItem = aItem?.projectItem;
867
880
  }
881
+ /////////////////////////////////////////////////////////////////////////////
882
+ //Get from option assortmentItem because family not in assortmentItemFullChangeMap:start
883
+ /////////////////////////////////////////////////////////////////////////////
868
884
  if (id === itemFamilyChanges.itemFamilyId && Object.keys(projectItem).length == 0) {
869
885
  for (const asstItem of itemFamilyChanges.assortmentItemFullChangeMap.values()) {
870
886
  if (asstItem?.familyProjectItem) {
@@ -873,6 +889,9 @@ class BaseProcessPublishAssortment {
873
889
  }
874
890
  }
875
891
  }
892
+ /////////////////////////////////////////////////////////////////////////////
893
+ //Get from option assortmentItem because family not in assortmentItemFullChangeMap:end
894
+ /////////////////////////////////////////////////////////////////////////////
876
895
  return projectItem;
877
896
  }
878
897
  async getSeasonalData(projectItem) {
@@ -9,11 +9,11 @@ const sdk_1 = require("@contrail/sdk");
9
9
  const type_conversion_utils_1 = require("../util/type-conversion-utils");
10
10
  const map_utils_1 = require("../util/map-utils");
11
11
  const item_family_changes_1 = require("../interfaces/item-family-changes");
12
- const flexplm_connect_1 = require("../util/flexplm-connect");
13
12
  let federatedId = '';
14
13
  jest.mock('../util/data-converter', () => {
15
14
  return {
16
15
  DataConverter: class {
16
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars, unused-imports/no-unused-vars
17
17
  getFlexPLMObjectData(newData, dataToSkip, inflateObjRef) {
18
18
  return newData;
19
19
  }
@@ -31,13 +31,6 @@ jest.mock('../util/federation', () => {
31
31
  });
32
32
  let entityObject = {};
33
33
  let getOptionsObject = {};
34
- let createCallArg = undefined;
35
- let fileUploadCalls = [];
36
- let fileUploadResult = {
37
- id: 'file-123',
38
- downloadUrl: 'https://download.url',
39
- adminDownloadUrl: 'https://admin.download.url'
40
- };
41
34
  jest.mock('@contrail/sdk', () => {
42
35
  return {
43
36
  Entities: class {
@@ -45,18 +38,6 @@ jest.mock('@contrail/sdk', () => {
45
38
  getOptionsObject = _getOtionsObject;
46
39
  return entityObject;
47
40
  }
48
- create(arg) {
49
- createCallArg = arg;
50
- return Promise.resolve({});
51
- }
52
- },
53
- Files: class {
54
- createAndUploadFileFromBuffer(buffer, mimeType, fileName, _x, ttl) {
55
- fileUploadCalls.push({ buffer, mimeType, fileName, ttl });
56
- return Promise.resolve(fileUploadResult);
57
- }
58
- },
59
- Request: class {
60
41
  }
61
42
  };
62
43
  });
@@ -115,6 +96,7 @@ describe('getPublishInfo', () => {
115
96
  return { id: assortmentId, name: assortmentName };
116
97
  });
117
98
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
99
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
118
100
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
119
101
  return versionHistoryNumber;
120
102
  });
@@ -140,6 +122,7 @@ describe('getPublishInfo', () => {
140
122
  return { id: assortmentId, name: undefined };
141
123
  });
142
124
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
125
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
143
126
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
144
127
  return versionHistoryNumber;
145
128
  });
@@ -165,6 +148,7 @@ describe('getPublishInfo', () => {
165
148
  return undefined;
166
149
  });
167
150
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
151
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
168
152
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
169
153
  return versionHistoryNumber;
170
154
  });
@@ -199,6 +183,7 @@ describe('getPublishInfo', () => {
199
183
  return { id: assortmentId, name: assortmentName };
200
184
  });
201
185
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
186
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
202
187
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
203
188
  return versionHistoryNumber;
204
189
  });
@@ -223,6 +208,7 @@ describe('getPublishInfo', () => {
223
208
  return { id: assortmentId, name: assortmentName };
224
209
  });
225
210
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
211
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
226
212
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
227
213
  return versionHistoryNumber;
228
214
  });
@@ -249,6 +235,7 @@ describe('getPublishInfo', () => {
249
235
  return { id: assortmentId, name: assortmentName };
250
236
  });
251
237
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
238
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
252
239
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
253
240
  return versionHistoryNumber;
254
241
  });
@@ -275,6 +262,7 @@ describe('getPublishInfo', () => {
275
262
  return { id: assortmentId, name: assortmentName };
276
263
  });
277
264
  const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
265
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
278
266
  .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
279
267
  return versionHistoryNumber;
280
268
  });
@@ -428,6 +416,7 @@ describe('getSnapshotVersion', () => {
428
416
  {
429
417
  id: 'qewrwer',
430
418
  assortmentChangeId: 'bad-id',
419
+ // createdOn: '2023-01-14T19:13:58.902Z',
431
420
  versionNumber
432
421
  }
433
422
  ];
@@ -1160,6 +1149,7 @@ describe('getItemFamilyChanges', () => {
1160
1149
  const ifcs = pcd.itemFamilyChanges;
1161
1150
  expect(ifcs.size).toEqual(1);
1162
1151
  const ifc = ifcs.get(itemFamilyId);
1152
+ // expect(ifc.familyAdd).toBe(true);
1163
1153
  expect(ifc.colorAdds.length).toEqual(1);
1164
1154
  });
1165
1155
  it('Feb 3 - 2+ Option A', () => {
@@ -1189,6 +1179,7 @@ describe('getItemFamilyChanges', () => {
1189
1179
  const ifcs = pcd.itemFamilyChanges;
1190
1180
  expect(ifcs.size).toEqual(1);
1191
1181
  const ifc = ifcs.get(itemFamilyId);
1182
+ // expect(ifc.familyAdd).toBe(true);
1192
1183
  expect(ifc.colorAdds.length).toEqual(2);
1193
1184
  });
1194
1185
  it('Feb 3 - 2+ Option A & Feb 3 - 1 Option A', () => {
@@ -1320,6 +1311,8 @@ describe('getItemFamilyChanges', () => {
1320
1311
  const ifcs = pcd.itemFamilyChanges;
1321
1312
  expect(ifcs.size).toEqual(1);
1322
1313
  const ifc = ifcs.get(itemFamilyId);
1314
+ //TODO fix
1315
+ // expect(ifc.familyDelete).toBe(true);
1323
1316
  expect(ifc.colorAdds.length).toEqual(0);
1324
1317
  expect(ifc.colorDeletes.length).toEqual(1);
1325
1318
  });
@@ -1592,9 +1585,10 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1592
1585
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getIdentifierProperties').mockResolvedValue(['identifier']);
1593
1586
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getInformationalProperties').mockResolvedValue([]);
1594
1587
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'isOutboundCreatableFromEntity')
1595
- .mockResolvedValueOnce(true)
1596
- .mockResolvedValueOnce(true);
1588
+ .mockResolvedValueOnce(true) // for family
1589
+ .mockResolvedValueOnce(true); // for SKU
1597
1590
  const events = await bppa.getEventsForItemFamilyChanges(itemFamilyChanges, 'assort123', seasonFed, new Map());
1591
+ // Should have both family and SKU events because familyAssortmentItem is true when colorAdds.length > 0
1598
1592
  expect(events).toHaveLength(2);
1599
1593
  const skuEvent = events.find(e => e.objectClass === 'LCSSKUSeasonLink');
1600
1594
  expect(skuEvent.eventType).toBe('UPSERT_ON_SEASON');
@@ -1633,9 +1627,10 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1633
1627
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getIdentifierProperties').mockResolvedValue(['identifier']);
1634
1628
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getInformationalProperties').mockResolvedValue([]);
1635
1629
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'isOutboundCreatableFromEntity')
1636
- .mockResolvedValueOnce(false)
1637
- .mockResolvedValueOnce(false);
1630
+ .mockResolvedValueOnce(false) // for family
1631
+ .mockResolvedValueOnce(false); // for SKU
1638
1632
  const events = await bppa.getEventsForItemFamilyChanges(itemFamilyChanges, 'assort123', seasonFed, new Map());
1633
+ // Should have both family and SKU events because familyAssortmentItem is true when colorUpdates.length > 0
1639
1634
  expect(events).toHaveLength(2);
1640
1635
  const skuEvent = events.find(e => e.objectClass === 'LCSSKUSeasonLink');
1641
1636
  expect(skuEvent.eventType).toBe('UPDATE_ON_SEASON');
@@ -1674,6 +1669,7 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1674
1669
  jest.spyOn(map_utils_1.MapUtil, 'applyTransformMap').mockResolvedValue({ transformedData: 'value' });
1675
1670
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getIdentifierProperties').mockResolvedValue(['identifier']);
1676
1671
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'getInformationalProperties').mockResolvedValue([]);
1672
+ // Product is creatable (true), SKU is not (false)
1677
1673
  jest.spyOn(type_conversion_utils_1.TypeConversionUtils, 'isOutboundCreatableFromEntity')
1678
1674
  .mockResolvedValueOnce(true)
1679
1675
  .mockResolvedValueOnce(false);
@@ -1684,126 +1680,9 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1684
1680
  expect(productEvent.eventType).toBe('UPSERT_ON_SEASON');
1685
1681
  expect(skuEvent.eventType).toBe('UPDATE_ON_SEASON');
1686
1682
  expect(type_conversion_utils_1.TypeConversionUtils.isOutboundCreatableFromEntity).toHaveBeenCalledTimes(2);
1683
+ // Verify product event called with assortment entity
1687
1684
  expect(type_conversion_utils_1.TypeConversionUtils.isOutboundCreatableFromEntity).toHaveBeenNthCalledWith(1, undefined, mapFileUtil, familyProjectItem, { item: prodEntityData, assortment });
1685
+ // Verify SKU event called with assortment entity
1688
1686
  expect(type_conversion_utils_1.TypeConversionUtils.isOutboundCreatableFromEntity).toHaveBeenNthCalledWith(2, undefined, mapFileUtil, colorProjectItem, { item: itemData, assortment });
1689
1687
  });
1690
1688
  });
1691
- describe('sendToFlexPLM / handleVibeIQFile / sendPublishPayloadEvent', () => {
1692
- const config = {
1693
- taskId: 'task-abc',
1694
- event: '{"sourceEventId":"src-1"}'
1695
- };
1696
- const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
1697
- const dc = new data_converter_1.DataConverter(config, mapFileUtil);
1698
- const events = [{ objectClass: 'LCSProductSeasonLink' }];
1699
- const eventType = 'ASYNC_PUBLISH_SEASON';
1700
- beforeEach(() => {
1701
- createCallArg = undefined;
1702
- fileUploadCalls = [];
1703
- fileUploadResult = {
1704
- id: 'file-123',
1705
- downloadUrl: 'https://download.url',
1706
- adminDownloadUrl: 'https://admin.download.url'
1707
- };
1708
- });
1709
- afterEach(() => {
1710
- jest.restoreAllMocks();
1711
- });
1712
- it('sendToFlexPLM merges outboundPublishEvent into result and calls sendPublishPayloadEvent in parallel', async () => {
1713
- const bppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
1714
- const flexResponse = { status: 200, data: { ok: true } };
1715
- let flexResolved = false;
1716
- let eventResolved = false;
1717
- const spyFlex = jest.spyOn(flexplm_connect_1.FlexPLMConnect.prototype, 'sendToFlexPLM')
1718
- .mockImplementation(async () => {
1719
- await new Promise(r => setTimeout(r, 5));
1720
- flexResolved = true;
1721
- return flexResponse;
1722
- });
1723
- const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
1724
- .mockImplementation(async () => {
1725
- await new Promise(r => setTimeout(r, 5));
1726
- eventResolved = true;
1727
- });
1728
- const result = await bppa.sendToFlexPLM(events, eventType);
1729
- expect(spyFlex).toHaveBeenCalledTimes(1);
1730
- expect(spyEvent).toHaveBeenCalledTimes(1);
1731
- expect(flexResolved).toBe(true);
1732
- expect(eventResolved).toBe(true);
1733
- const passedOutboundPublishEvent = spyFlex.mock.calls[0][0];
1734
- expect(passedOutboundPublishEvent.taskId).toBe('task-abc');
1735
- expect(passedOutboundPublishEvent.eventType).toBe(eventType);
1736
- expect(passedOutboundPublishEvent.objectClass).toBe('LCSSeason');
1737
- expect(passedOutboundPublishEvent.events).toBe(events);
1738
- expect(spyEvent).toHaveBeenCalledWith(passedOutboundPublishEvent);
1739
- expect(result).toEqual({ ...flexResponse, outboundPublishEvent: passedOutboundPublishEvent });
1740
- });
1741
- it('handleVibeIQFile (vibeiqfile) merges outboundPublishEvent into FlexPLM result and calls sendPublishPayloadEvent', async () => {
1742
- const bppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
1743
- const flexResponse = { status: 200, data: { ok: true } };
1744
- const spyFlex = jest.spyOn(flexplm_connect_1.FlexPLMConnect.prototype, 'sendToFlexPLM')
1745
- .mockResolvedValue(flexResponse);
1746
- const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
1747
- .mockResolvedValue(undefined);
1748
- const result = await bppa.handleVibeIQFile(events, eventType, 'vibeiqfile');
1749
- expect(fileUploadCalls).toHaveLength(1);
1750
- expect(fileUploadCalls[0].fileName).toBe('ASYNC_PUBLISH_SEASON-events.json');
1751
- expect(fileUploadCalls[0].mimeType).toBe('application/json');
1752
- const passedOutboundPublishEvent = spyFlex.mock.calls[0][0];
1753
- expect(passedOutboundPublishEvent.taskId).toBe('task-abc');
1754
- expect(passedOutboundPublishEvent.eventType).toBe(eventType);
1755
- expect(passedOutboundPublishEvent.objectClass).toBe('LCSSeason');
1756
- expect(passedOutboundPublishEvent.eventsFileId).toBe('file-123');
1757
- expect(passedOutboundPublishEvent.eventsDownloadLink).toBe('https://download.url');
1758
- expect(passedOutboundPublishEvent.eventsAdminDownloadLink).toBe('https://admin.download.url');
1759
- expect(spyFlex).toHaveBeenCalledTimes(1);
1760
- expect(spyEvent).toHaveBeenCalledTimes(1);
1761
- expect(spyEvent).toHaveBeenCalledWith(passedOutboundPublishEvent);
1762
- expect(result).toEqual({ ...flexResponse, outboundPublishEvent: passedOutboundPublishEvent });
1763
- });
1764
- it('handleVibeIQFile (vibeiqfile-dontsendtoflexplm) skips FlexPLM but still calls sendPublishPayloadEvent', async () => {
1765
- const bppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
1766
- const spyFlex = jest.spyOn(flexplm_connect_1.FlexPLMConnect.prototype, 'sendToFlexPLM')
1767
- .mockResolvedValue({});
1768
- const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
1769
- .mockResolvedValue(undefined);
1770
- const result = await bppa.handleVibeIQFile(events, eventType, 'vibeiqfile-dontsendtoflexplm');
1771
- expect(spyFlex).not.toHaveBeenCalled();
1772
- expect(spyEvent).toHaveBeenCalledTimes(1);
1773
- const passedOutboundPublishEvent = spyEvent.mock.calls[0][0];
1774
- expect(passedOutboundPublishEvent.eventsFileId).toBe('file-123');
1775
- expect(result).toEqual({
1776
- message: 'Successfully Uploaded File.',
1777
- outboundPublishEvent: passedOutboundPublishEvent
1778
- });
1779
- });
1780
- it('sendPublishPayloadEvent creates an external-event with initialEvent parsed from config', async () => {
1781
- const bppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
1782
- const outboundPublishEvent = { foo: 'bar' };
1783
- await bppa.sendPublishPayloadEvent(outboundPublishEvent);
1784
- expect(createCallArg).toEqual({
1785
- entityName: 'external-event',
1786
- object: {
1787
- originSystemType: 'VibeIQ',
1788
- objectClass: 'AssortmentPublishedToFlexPLM',
1789
- outboundPublishEvent,
1790
- initialEvent: { sourceEventId: 'src-1' }
1791
- }
1792
- });
1793
- });
1794
- it('sendPublishPayloadEvent defaults initialEvent to {} when config has no event', async () => {
1795
- const bareConfig = { taskId: 'task-x' };
1796
- const bppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(bareConfig, dc, mapFileUtil);
1797
- const outboundPublishEvent = { hello: 'world' };
1798
- await bppa.sendPublishPayloadEvent(outboundPublishEvent);
1799
- expect(createCallArg).toEqual({
1800
- entityName: 'external-event',
1801
- object: {
1802
- originSystemType: 'VibeIQ',
1803
- objectClass: 'AssortmentPublishedToFlexPLM',
1804
- outboundPublishEvent,
1805
- initialEvent: {}
1806
- }
1807
- });
1808
- });
1809
- });
@@ -3399,6 +3399,11 @@ exports.fall_2003_fedMapping = [
3399
3399
  mappedReference: 'VR:com.lcs.wc.product.LCSSKU:372509'
3400
3400
  }
3401
3401
  ];
3402
+ //SYHfQzYWlfXDqK7r - 4 adds
3403
+ //JreGRNvoJ3FsoRZI - 1 delete
3404
+ //NaPUhAdEzKB-5tQ3 - no changes
3405
+ //CHGKSCT358qyh1Nu - 1 delete
3406
+ //H4L4dHziO6WZRIwa - re-add from JreGRNvoJ3FsoRZI
3402
3407
  exports.apc_2bOWR2j9R0QThDVu_delete_history = [
3403
3408
  {
3404
3409
  adds: 4,
@@ -31,6 +31,20 @@ exports.mapping = {
31
31
  }
32
32
  }
33
33
  }
34
+ // flex2vibe: {
35
+ // LCSRevisableEntity: {
36
+ // getMapKey: (object) =>{ return object;}
37
+ // },
38
+ // LCSLast: {
39
+ // getMapKey: (object) => {return object;}
40
+ // },
41
+ // LCSMaterial: {
42
+ // getMapKey: (object) =>{ return object;}
43
+ // },
44
+ // LCSBusinessObject: {
45
+ // getMapKey: (object) => {return object;}
46
+ // }
47
+ // },
34
48
  },
35
49
  LCSSeason: {
36
50
  vibe2flex: {
@@ -54,7 +68,7 @@ exports.mapping = {
54
68
  vibeOwningKeys: ['itemNumber', 'lifecycleStage'],
55
69
  vibe2flex: {
56
70
  getClass: () => 'LCSProduct',
57
- getSoftType: (entity) => {
71
+ getSoftType: (entity /*, dependencies*/) => {
58
72
  const prodType = entity['prodType'];
59
73
  let val = '';
60
74
  switch (prodType) {
@@ -79,7 +93,7 @@ exports.mapping = {
79
93
  vibeIQIdentifier: 'itemNumber'
80
94
  },
81
95
  valueTransform: {
82
- transformEx: (row) => {
96
+ transformEx: (row /*, dependencies*/) => {
83
97
  return row['otherProp'] + 'xxx';
84
98
  }
85
99
  }
@@ -97,7 +111,7 @@ exports.mapping = {
97
111
  vibeOwningKeys: ['itemNumber', 'lifecycleStage'],
98
112
  vibe2flex: {
99
113
  getClass: () => 'LCSSKU',
100
- getSoftType: (entity) => {
114
+ getSoftType: (entity /*, dependencies*/) => {
101
115
  const prodType = entity['prodType'];
102
116
  let val = '';
103
117
  switch (prodType) {
@@ -252,6 +266,20 @@ exports.mapping2 = {
252
266
  }
253
267
  }
254
268
  }
269
+ // flex2vibe: {
270
+ // LCSRevisableEntity: {
271
+ // getMapKey: (object) =>{ return object;}
272
+ // },
273
+ // LCSLast: {
274
+ // getMapKey: (object) => {return object;}
275
+ // },
276
+ // LCSMaterial: {
277
+ // getMapKey: (object) =>{ return object;}
278
+ // },
279
+ // LCSBusinessObject: {
280
+ // getMapKey: (object) => {return object;}
281
+ // }
282
+ // },
255
283
  },
256
284
  LCSSeason: {
257
285
  getIdentifierProperties: () => ['brand', 'year', 'seasonType'],
@@ -274,7 +302,7 @@ exports.mapping2 = {
274
302
  vibeOwningKeys: ['itemNumber', 'lifecycleStage'],
275
303
  vibe2flex: {
276
304
  getClass: () => 'LCSProduct',
277
- getSoftType: (entity) => {
305
+ getSoftType: (entity /*, dependencies*/) => {
278
306
  const prodType = entity['prodType'];
279
307
  let val = '';
280
308
  switch (prodType) {
@@ -299,7 +327,7 @@ exports.mapping2 = {
299
327
  vibeIQIdentifier: 'itemNumber'
300
328
  },
301
329
  valueTransform: {
302
- transformEx: (row) => {
330
+ transformEx: (row /*, dependencies*/) => {
303
331
  return row['otherProp'] + 'xxx';
304
332
  }
305
333
  }
@@ -318,7 +346,7 @@ exports.mapping2 = {
318
346
  getIdentifierProperties: () => ['uniqueIdentifierA', 'uniqueIdentifierB'],
319
347
  vibe2flex: {
320
348
  getClass: () => 'LCSSKU',
321
- getSoftType: (entity) => {
349
+ getSoftType: (entity /*, dependencies*/) => {
322
350
  const prodType = entity['prodType'];
323
351
  let val = '';
324
352
  switch (prodType) {