@contrail/flexplm 1.5.0 → 1.5.1-alpha.14abddb

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,10 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.5.1] - 2026-05-14
11
+ ### Added
12
+ - Added sending an external event with the publish payload and trigger key of `VibeIQ|AssortmentPublishedToFlexPLM` to enable secondary events to run on the event / data which was generated. Also includes the payload in the data which can be passed to the next action.
13
+
10
14
  ## [1.5.0] - 2026-05-12
11
15
  ### Added
12
16
  - Added support for Inbound `LCSMaterial` to sync to the entity class `item` with type path `item:material` and `itemNumber` as identifier. This is controlled by an `LCSMaterial.processAsItem` (default `false`) config default.
@@ -79,6 +79,7 @@ export declare class BaseProcessPublishAssortment {
79
79
  private sendToFlexPLM;
80
80
  private saveToLocalFile;
81
81
  private handleVibeIQFile;
82
+ sendPublishPayloadEvent(outboundEvent: any): Promise<void>;
82
83
  private getCurrentDateString;
83
84
  getItemFamilyChanges(pcd: PublishChangeData, changeDetail: any, assortmentItemFullChangeMap: Map<string, any>, assortmentItemDeleteMap: Map<string, any>): Map<string, ItemFamilyChanges>;
84
85
  getEventsForPublishChangeData(publishChangeData: PublishChangeData): Promise<SeasonalPayload[]>;
@@ -569,14 +569,19 @@ class BaseProcessPublishAssortment {
569
569
  }
570
570
  }
571
571
  async sendToFlexPLM(events, eventType) {
572
- const asyncEvent = {
572
+ const outboundPublishEvent = {
573
573
  taskId: this.config.taskId,
574
574
  eventType,
575
575
  objectClass: 'LCSSeason',
576
576
  events
577
577
  };
578
578
  const flexPLMConnect = new flexplm_connect_1.FlexPLMConnect(this.config);
579
- return await flexPLMConnect.sendToFlexPLM(asyncEvent);
579
+ const [result] = await Promise.all([
580
+ flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
581
+ this.sendPublishPayloadEvent(outboundPublishEvent)
582
+ ]);
583
+ result['outboundPublishEvent'] = outboundPublishEvent;
584
+ return result;
580
585
  }
581
586
  async saveToLocalFile(events, eventType) {
582
587
  let results = {};
@@ -588,15 +593,16 @@ class BaseProcessPublishAssortment {
588
593
  const eventDirName = 'events-output';
589
594
  const fileName = `${path.sep}${eventDirName}${path.sep}events-${dateString}.json`;
590
595
  fileHandle = await fsPromise.open('.' + fileName, 'a');
591
- const asyncEvent = {
596
+ const outboundPublishEvent = {
592
597
  taskId: this.config.taskId,
593
598
  eventType,
594
599
  objectClass: 'LCSSeason',
595
600
  events
596
601
  };
597
- await fileHandle.writeFile(JSON.stringify(asyncEvent));
602
+ await fileHandle.writeFile(JSON.stringify(outboundPublishEvent));
598
603
  results = {
599
604
  message: 'Successfully Saved File',
605
+ outboundPublishEvent,
600
606
  fileLocation: dirName + fileName
601
607
  };
602
608
  }
@@ -612,7 +618,7 @@ class BaseProcessPublishAssortment {
612
618
  const eventBuffer = Buffer.from(JSON.stringify(events), 'utf-8');
613
619
  const fileName = 'ASYNC_PUBLISH_SEASON-events.json';
614
620
  const uploadFile = await new sdk_1.Files().createAndUploadFileFromBuffer(eventBuffer, 'application/json', fileName, null, this.TTL);
615
- const asyncEvent = {
621
+ const outboundPublishEvent = {
616
622
  taskId: this.config.taskId,
617
623
  eventType,
618
624
  objectClass: 'LCSSeason',
@@ -622,15 +628,39 @@ class BaseProcessPublishAssortment {
622
628
  };
623
629
  if (sendMode === 'vibeiqfile') {
624
630
  const flexPLMConnect = new flexplm_connect_1.FlexPLMConnect(this.config);
625
- return await flexPLMConnect.sendToFlexPLM(asyncEvent);
631
+ const [result] = await Promise.all([
632
+ flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
633
+ this.sendPublishPayloadEvent(outboundPublishEvent)
634
+ ]);
635
+ return { ...result, outboundPublishEvent };
626
636
  }
627
637
  else {
638
+ await this.sendPublishPayloadEvent(outboundPublishEvent);
628
639
  return {
629
640
  message: 'Successfully Uploaded File.',
630
- asyncEvent
641
+ outboundPublishEvent
631
642
  };
632
643
  }
633
644
  }
645
+ async sendPublishPayloadEvent(outboundEvent) {
646
+ console.info('sendPublishPayloadEvent()');
647
+ let initialEvent = {};
648
+ if (this.config?.event) {
649
+ initialEvent = (typeof this.config?.event === 'string')
650
+ ? JSON.parse(this.config?.event)
651
+ : this.config?.event;
652
+ }
653
+ const eventBody = {
654
+ originSystemType: 'VibeIQ',
655
+ objectClass: 'AssortmentPublishedToFlexPLM',
656
+ outboundEvent,
657
+ initialEvent
658
+ };
659
+ await new sdk_1.Entities().create({
660
+ entityName: 'external-event',
661
+ object: eventBody
662
+ });
663
+ }
634
664
  getCurrentDateString() {
635
665
  const d = new Date();
636
666
  return '' + d.getUTCFullYear()
@@ -9,6 +9,7 @@ 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");
12
13
  let federatedId = '';
13
14
  jest.mock('../util/data-converter', () => {
14
15
  return {
@@ -30,6 +31,13 @@ jest.mock('../util/federation', () => {
30
31
  });
31
32
  let entityObject = {};
32
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
+ };
33
41
  jest.mock('@contrail/sdk', () => {
34
42
  return {
35
43
  Entities: class {
@@ -37,6 +45,18 @@ jest.mock('@contrail/sdk', () => {
37
45
  getOptionsObject = _getOtionsObject;
38
46
  return entityObject;
39
47
  }
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 {
40
60
  }
41
61
  };
42
62
  });
@@ -1668,3 +1688,122 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1668
1688
  expect(type_conversion_utils_1.TypeConversionUtils.isOutboundCreatableFromEntity).toHaveBeenNthCalledWith(2, undefined, mapFileUtil, colorProjectItem, { item: itemData, assortment });
1669
1689
  });
1670
1690
  });
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 outboundEvent = { foo: 'bar' };
1783
+ await bppa.sendPublishPayloadEvent(outboundEvent);
1784
+ expect(createCallArg).toEqual({
1785
+ entityName: 'external-event',
1786
+ object: {
1787
+ originSystemType: 'VibeIQ',
1788
+ objectClass: 'AssortmentPublishedToFlexPLM',
1789
+ outboundEvent,
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 outboundEvent = { hello: 'world' };
1798
+ await bppa.sendPublishPayloadEvent(outboundEvent);
1799
+ expect(createCallArg).toEqual({
1800
+ entityName: 'external-event',
1801
+ object: {
1802
+ originSystemType: 'VibeIQ',
1803
+ objectClass: 'AssortmentPublishedToFlexPLM',
1804
+ outboundEvent,
1805
+ initialEvent: {}
1806
+ }
1807
+ });
1808
+ });
1809
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/flexplm",
3
- "version": "1.5.0",
3
+ "version": "1.5.1-alpha.14abddb",
4
4
  "description": "Library used for integration with flexplm.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -8,6 +8,7 @@ import { Entities } from '@contrail/sdk';
8
8
  import { TypeConversionUtils } from '../util/type-conversion-utils';
9
9
  import { MapUtil } from '../util/map-utils';
10
10
  import { ItemFamilyChanges } from '../interfaces/item-family-changes';
11
+ import { FlexPLMConnect } from '../util/flexplm-connect';
11
12
 
12
13
  let federatedId = '';
13
14
  jest.mock('../util/data-converter', () => {
@@ -32,6 +33,13 @@ jest.mock('../util/federation', () => {
32
33
  });
33
34
  let entityObject = {};
34
35
  let getOptionsObject = {};
36
+ let createCallArg: any = undefined;
37
+ let fileUploadCalls: any[] = [];
38
+ let fileUploadResult: any = {
39
+ id: 'file-123',
40
+ downloadUrl: 'https://download.url',
41
+ adminDownloadUrl: 'https://admin.download.url'
42
+ };
35
43
  jest.mock('@contrail/sdk', () => {
36
44
  return {
37
45
  Entities: class{
@@ -39,7 +47,18 @@ jest.mock('@contrail/sdk', () => {
39
47
  getOptionsObject = _getOtionsObject;
40
48
  return entityObject;
41
49
  }
42
- }
50
+ create(arg){
51
+ createCallArg = arg;
52
+ return Promise.resolve({});
53
+ }
54
+ },
55
+ Files: class{
56
+ createAndUploadFileFromBuffer(buffer, mimeType, fileName, _x, ttl){
57
+ fileUploadCalls.push({ buffer, mimeType, fileName, ttl });
58
+ return Promise.resolve(fileUploadResult);
59
+ }
60
+ },
61
+ Request: class{}
43
62
  };
44
63
  });
45
64
  describe('process publish assortment', () => {
@@ -1989,4 +2008,147 @@ describe('getEventsForItemFamilyChanges - conditional eventType', () => {
1989
2008
  );
1990
2009
  });
1991
2010
 
2011
+ });
2012
+
2013
+ describe('sendToFlexPLM / handleVibeIQFile / sendPublishPayloadEvent', () => {
2014
+ const config = {
2015
+ taskId: 'task-abc',
2016
+ event: '{"sourceEventId":"src-1"}'
2017
+ } as unknown as FCConfig;
2018
+ const mapFileUtil = new MapFileUtil(new Entities());
2019
+ const dc = new DataConverter(config, mapFileUtil);
2020
+ const events = [{ objectClass: 'LCSProductSeasonLink' }] as any;
2021
+ const eventType = 'ASYNC_PUBLISH_SEASON';
2022
+
2023
+ beforeEach(() => {
2024
+ createCallArg = undefined;
2025
+ fileUploadCalls = [];
2026
+ fileUploadResult = {
2027
+ id: 'file-123',
2028
+ downloadUrl: 'https://download.url',
2029
+ adminDownloadUrl: 'https://admin.download.url'
2030
+ };
2031
+ });
2032
+ afterEach(() => {
2033
+ jest.restoreAllMocks();
2034
+ });
2035
+
2036
+ it('sendToFlexPLM merges outboundPublishEvent into result and calls sendPublishPayloadEvent in parallel', async () => {
2037
+ const bppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
2038
+ const flexResponse = { status: 200, data: { ok: true } };
2039
+
2040
+ let flexResolved = false;
2041
+ let eventResolved = false;
2042
+ const spyFlex = jest.spyOn(FlexPLMConnect.prototype, 'sendToFlexPLM')
2043
+ .mockImplementation(async () => {
2044
+ await new Promise(r => setTimeout(r, 5));
2045
+ flexResolved = true;
2046
+ return flexResponse as any;
2047
+ });
2048
+ const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
2049
+ .mockImplementation(async () => {
2050
+ await new Promise(r => setTimeout(r, 5));
2051
+ eventResolved = true;
2052
+ });
2053
+
2054
+ const result = await (bppa as any).sendToFlexPLM(events, eventType);
2055
+
2056
+ expect(spyFlex).toHaveBeenCalledTimes(1);
2057
+ expect(spyEvent).toHaveBeenCalledTimes(1);
2058
+ expect(flexResolved).toBe(true);
2059
+ expect(eventResolved).toBe(true);
2060
+
2061
+ const passedOutboundPublishEvent = spyFlex.mock.calls[0][0] as any;
2062
+ expect(passedOutboundPublishEvent.taskId).toBe('task-abc');
2063
+ expect(passedOutboundPublishEvent.eventType).toBe(eventType);
2064
+ expect(passedOutboundPublishEvent.objectClass).toBe('LCSSeason');
2065
+ expect(passedOutboundPublishEvent.events).toBe(events);
2066
+ expect(spyEvent).toHaveBeenCalledWith(passedOutboundPublishEvent);
2067
+ expect(result).toEqual({ ...flexResponse, outboundPublishEvent: passedOutboundPublishEvent });
2068
+ });
2069
+
2070
+ it('handleVibeIQFile (vibeiqfile) merges outboundPublishEvent into FlexPLM result and calls sendPublishPayloadEvent', async () => {
2071
+ const bppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
2072
+ const flexResponse = { status: 200, data: { ok: true } };
2073
+
2074
+ const spyFlex = jest.spyOn(FlexPLMConnect.prototype, 'sendToFlexPLM')
2075
+ .mockResolvedValue(flexResponse as any);
2076
+ const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
2077
+ .mockResolvedValue(undefined as any);
2078
+
2079
+ const result = await (bppa as any).handleVibeIQFile(events, eventType, 'vibeiqfile');
2080
+
2081
+ expect(fileUploadCalls).toHaveLength(1);
2082
+ expect(fileUploadCalls[0].fileName).toBe('ASYNC_PUBLISH_SEASON-events.json');
2083
+ expect(fileUploadCalls[0].mimeType).toBe('application/json');
2084
+
2085
+ const passedOutboundPublishEvent = spyFlex.mock.calls[0][0] as any;
2086
+ expect(passedOutboundPublishEvent.taskId).toBe('task-abc');
2087
+ expect(passedOutboundPublishEvent.eventType).toBe(eventType);
2088
+ expect(passedOutboundPublishEvent.objectClass).toBe('LCSSeason');
2089
+ expect(passedOutboundPublishEvent.eventsFileId).toBe('file-123');
2090
+ expect(passedOutboundPublishEvent.eventsDownloadLink).toBe('https://download.url');
2091
+ expect(passedOutboundPublishEvent.eventsAdminDownloadLink).toBe('https://admin.download.url');
2092
+
2093
+ expect(spyFlex).toHaveBeenCalledTimes(1);
2094
+ expect(spyEvent).toHaveBeenCalledTimes(1);
2095
+ expect(spyEvent).toHaveBeenCalledWith(passedOutboundPublishEvent);
2096
+ expect(result).toEqual({ ...flexResponse, outboundPublishEvent: passedOutboundPublishEvent });
2097
+ });
2098
+
2099
+ it('handleVibeIQFile (vibeiqfile-dontsendtoflexplm) skips FlexPLM but still calls sendPublishPayloadEvent', async () => {
2100
+ const bppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
2101
+
2102
+ const spyFlex = jest.spyOn(FlexPLMConnect.prototype, 'sendToFlexPLM')
2103
+ .mockResolvedValue({} as any);
2104
+ const spyEvent = jest.spyOn(bppa, 'sendPublishPayloadEvent')
2105
+ .mockResolvedValue(undefined as any);
2106
+
2107
+ const result = await (bppa as any).handleVibeIQFile(events, eventType, 'vibeiqfile-dontsendtoflexplm');
2108
+
2109
+ expect(spyFlex).not.toHaveBeenCalled();
2110
+ expect(spyEvent).toHaveBeenCalledTimes(1);
2111
+
2112
+ const passedOutboundPublishEvent = spyEvent.mock.calls[0][0] as any;
2113
+ expect(passedOutboundPublishEvent.eventsFileId).toBe('file-123');
2114
+ expect(result).toEqual({
2115
+ message: 'Successfully Uploaded File.',
2116
+ outboundPublishEvent: passedOutboundPublishEvent
2117
+ });
2118
+ });
2119
+
2120
+ it('sendPublishPayloadEvent creates an external-event with initialEvent parsed from config', async () => {
2121
+ const bppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
2122
+ const outboundEvent = { foo: 'bar' };
2123
+
2124
+ await bppa.sendPublishPayloadEvent(outboundEvent);
2125
+
2126
+ expect(createCallArg).toEqual({
2127
+ entityName: 'external-event',
2128
+ object: {
2129
+ originSystemType: 'VibeIQ',
2130
+ objectClass: 'AssortmentPublishedToFlexPLM',
2131
+ outboundEvent,
2132
+ initialEvent: { sourceEventId: 'src-1' }
2133
+ }
2134
+ });
2135
+ });
2136
+
2137
+ it('sendPublishPayloadEvent defaults initialEvent to {} when config has no event', async () => {
2138
+ const bareConfig = { taskId: 'task-x' } as unknown as FCConfig;
2139
+ const bppa = new BaseProcessPublishAssortment(bareConfig, dc, mapFileUtil);
2140
+ const outboundEvent = { hello: 'world' };
2141
+
2142
+ await bppa.sendPublishPayloadEvent(outboundEvent);
2143
+
2144
+ expect(createCallArg).toEqual({
2145
+ entityName: 'external-event',
2146
+ object: {
2147
+ originSystemType: 'VibeIQ',
2148
+ objectClass: 'AssortmentPublishedToFlexPLM',
2149
+ outboundEvent,
2150
+ initialEvent: {}
2151
+ }
2152
+ });
2153
+ });
1992
2154
  });
@@ -685,7 +685,7 @@ export class BaseProcessPublishAssortment {
685
685
  }
686
686
 
687
687
  private async sendToFlexPLM(events: SeasonalPayload[], eventType: string) {
688
- const asyncEvent: AsyncEventsPayloadType = {
688
+ const outboundPublishEvent: AsyncEventsPayloadType = {
689
689
  taskId: this.config.taskId,
690
690
  eventType,
691
691
  objectClass: 'LCSSeason',
@@ -693,7 +693,12 @@ export class BaseProcessPublishAssortment {
693
693
  };
694
694
 
695
695
  const flexPLMConnect = new FlexPLMConnect(this.config);
696
- return await flexPLMConnect.sendToFlexPLM(asyncEvent);
696
+ const [result] = await Promise.all([
697
+ flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
698
+ this.sendPublishPayloadEvent(outboundPublishEvent)
699
+ ]);
700
+ result['outboundPublishEvent'] = outboundPublishEvent;
701
+ return result;
697
702
  }
698
703
 
699
704
  private async saveToLocalFile(events: SeasonalPayload[], eventType: string) {
@@ -708,17 +713,18 @@ export class BaseProcessPublishAssortment {
708
713
  const fileName = `${path.sep}${eventDirName}${path.sep}events-${dateString}.json`;
709
714
  fileHandle = await fsPromise.open('.' + fileName, 'a');
710
715
 
711
- const asyncEvent: AsyncEventsPayloadType = {
716
+ const outboundPublishEvent: AsyncEventsPayloadType = {
712
717
  taskId: this.config.taskId,
713
718
  eventType,
714
719
  objectClass: 'LCSSeason',
715
720
  events
716
721
  };
717
722
 
718
- await fileHandle.writeFile(JSON.stringify(asyncEvent));
723
+ await fileHandle.writeFile(JSON.stringify(outboundPublishEvent));
719
724
 
720
725
  results = {
721
726
  message: 'Successfully Saved File',
727
+ outboundPublishEvent,
722
728
  fileLocation: dirName + fileName
723
729
  };
724
730
  } catch (e) {
@@ -735,26 +741,53 @@ export class BaseProcessPublishAssortment {
735
741
  const fileName = 'ASYNC_PUBLISH_SEASON-events.json';
736
742
  const uploadFile = await new Files().createAndUploadFileFromBuffer(eventBuffer, 'application/json', fileName, null, this.TTL);
737
743
 
738
- const asyncEvent: AsyncEventsPayloadType = {
744
+ const outboundPublishEvent: AsyncEventsPayloadType = {
739
745
  taskId: this.config.taskId,
740
746
  eventType,
741
747
  objectClass: 'LCSSeason',
742
748
  eventsFileId: uploadFile.id,
743
749
  eventsDownloadLink: uploadFile.downloadUrl,
744
750
  eventsAdminDownloadLink: uploadFile.adminDownloadUrl
745
- };
751
+ };
746
752
 
747
753
  if (sendMode === 'vibeiqfile') {
748
754
  const flexPLMConnect = new FlexPLMConnect(this.config);
749
- return await flexPLMConnect.sendToFlexPLM(asyncEvent);
755
+ const [result] = await Promise.all([
756
+ flexPLMConnect.sendToFlexPLM(outboundPublishEvent),
757
+ this.sendPublishPayloadEvent(outboundPublishEvent)
758
+ ]);
759
+ return { ...result, outboundPublishEvent };
750
760
  } else {
761
+ await this.sendPublishPayloadEvent(outboundPublishEvent);
751
762
  return {
752
763
  message: 'Successfully Uploaded File.',
753
- asyncEvent
764
+ outboundPublishEvent
754
765
  };
755
766
  }
756
767
  }
757
768
 
769
+ public async sendPublishPayloadEvent(outboundEvent: any){
770
+ console.info('sendPublishPayloadEvent()');
771
+ let initialEvent = {};
772
+ if(this.config?.event){
773
+ initialEvent = (typeof this.config?.event === 'string')
774
+ ? JSON.parse(this.config?.event)
775
+ : this.config?.event;
776
+ }
777
+ const eventBody = {
778
+ originSystemType: 'VibeIQ',
779
+ objectClass: 'AssortmentPublishedToFlexPLM',
780
+ outboundEvent,
781
+ initialEvent
782
+ };
783
+
784
+ await new Entities().create({
785
+ entityName: 'external-event',
786
+ object: eventBody
787
+ });
788
+ }
789
+
790
+
758
791
  private getCurrentDateString() {
759
792
  const d = new Date();
760
793
  return '' + d.getUTCFullYear()