@contrail/flexplm 1.1.36 → 1.1.39

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.
@@ -13,6 +13,7 @@ export declare class BaseProcessPublishAssortment {
13
13
  private mapFileUtil;
14
14
  private transformMapFile;
15
15
  private cache;
16
+ private assortment;
16
17
  constructor(_config: FCConfig, _dc: DataConverter, _mapFileUtil: MapFileUtil);
17
18
  process(event: any): Promise<{
18
19
  results: {
@@ -23,7 +24,9 @@ export declare class BaseProcessPublishAssortment {
23
24
  results: any;
24
25
  skip_await?: undefined;
25
26
  }>;
27
+ getPublishInfo(assortmentPublishChangeId: any, apcHistory: any, publisher: any): Promise<any>;
26
28
  getSeasonFederation(assortmentId: any): Promise<SeasonFederation>;
29
+ getAssortment(assortmentId: any): Promise<any>;
27
30
  getSinceDate(assortmentId: any, assortmentPublishChangeId: any, apcHistory: object[]): Promise<Date>;
28
31
  getApcHistory(assortmentId: any): Promise<any>;
29
32
  protected updatedSinceDate(entity: any, sinceDate: Date): boolean;
@@ -22,6 +22,9 @@ class BaseProcessPublishAssortment {
22
22
  this.transformMapFile = this.config['transformMapFile'];
23
23
  }
24
24
  async process(event) {
25
+ const assortmentPublishChangeId = event.assortmentPublishChangeId;
26
+ let apcHistory;
27
+ let publisher;
25
28
  try {
26
29
  console.info('process-start!');
27
30
  const assortmentId = event.assortmentId;
@@ -38,40 +41,50 @@ class BaseProcessPublishAssortment {
38
41
  };
39
42
  return output;
40
43
  }
41
- const assortmentPublishChangeId = event.assortmentPublishChangeId;
42
- const apcHistory = await this.getApcHistory(assortmentId);
44
+ apcHistory = await this.getApcHistory(assortmentId);
43
45
  const sinceDate = await this.getSinceDate(assortmentId, assortmentPublishChangeId, apcHistory);
44
46
  const assortmentPublishChange = await this.downloadAssortmentPublishChange(assortmentId, assortmentPublishChangeId);
47
+ publisher = this.getPublisher(assortmentPublishChange);
45
48
  const changeDetail = await this.downloadHydratedChangeDetail(assortmentPublishChange);
46
49
  const assortmentBaseline = await this.downloadAssortmentBaseline(assortmentPublishChange);
47
50
  const deleteChanges = await this.getDeleteChanges(assortmentPublishChange, apcHistory, assortmentBaseline, sinceDate);
48
51
  const releasedForDevelopmentItemIds = this.getReleasedForDevelopmentItemAndFamilyIds(assortmentBaseline, deleteChanges);
49
52
  const itemToFederatedIdMapping = await this.getItemFederatedIds();
50
- const publisher = this.getPublisher(assortmentPublishChange);
51
53
  const pcd = new publish_change_data_1.PublishChangeData(assortmentId, seasonFed, assortmentPublishChangeId, sinceDate, publisher);
52
54
  pcd.itemToFederatedIdMapping = itemToFederatedIdMapping;
53
55
  pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
54
56
  const output = await this.processPublish(pcd, changeDetail, assortmentBaseline, deleteChanges);
57
+ output['publishInfo'] = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
55
58
  console.info('process-end');
56
59
  return output;
57
60
  }
58
61
  catch (e) {
62
+ try {
63
+ const publishInfo = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
64
+ e.publishInfo = publishInfo;
65
+ }
66
+ catch (e2) {
67
+ console.log('catch e2: ' + e2.message);
68
+ }
59
69
  console.log('catch e: ' + e.message);
60
70
  throw e;
61
71
  }
62
72
  }
73
+ async getPublishInfo(assortmentPublishChangeId, apcHistory, publisher) {
74
+ const apc = apcHistory?.find(apc => apc?.id === assortmentPublishChangeId) || {};
75
+ const assortmentName = (await this.getAssortment(assortmentPublishChangeId))?.name;
76
+ const publishInfo = {
77
+ assortmentName,
78
+ versionName: apc?.versionName,
79
+ versionComments: apc?.versionComments,
80
+ publishDate: apc?.createdOn,
81
+ publisher
82
+ };
83
+ return publishInfo;
84
+ }
63
85
  async getSeasonFederation(assortmentId) {
64
- let assortment;
65
- try {
66
- assortment = await new sdk_1.Entities().get({
67
- entityName: 'assortment',
68
- id: assortmentId
69
- });
70
- console.info('assortment-name: ' + assortment['name']);
71
- }
72
- catch (e) {
73
- console.warn(`No Assortment found for id: ${assortmentId}`);
74
- }
86
+ const assortment = await this.getAssortment(assortmentId);
87
+ console.error('assortment-name: ' + assortment?.name);
75
88
  const publishToFlexPLM = assortment?.publishToFlexPLM;
76
89
  if (!publishToFlexPLM) {
77
90
  throw new Error(BaseProcessPublishAssortment.ASSORTMENT_NOT_PUBLISHABLE);
@@ -95,6 +108,16 @@ class BaseProcessPublishAssortment {
95
108
  seasonObj = await map_utils_1.MapUtil.applyTransformMap(this.transformMapFile, this.mapFileUtil, seasonObj, 'LCSSeason', 'vibe2flex');
96
109
  return seasonObj;
97
110
  }
111
+ async getAssortment(assortmentId) {
112
+ if (this.assortment != undefined) {
113
+ return this.assortment;
114
+ }
115
+ this.assortment = await new sdk_1.Entities().get({
116
+ entityName: 'assortment',
117
+ id: assortmentId
118
+ });
119
+ return this.assortment;
120
+ }
98
121
  async getSinceDate(assortmentId, assortmentPublishChangeId, apcHistory) {
99
122
  let sinceDate = null;
100
123
  let pastPublishCount = 1;
@@ -226,7 +249,7 @@ class BaseProcessPublishAssortment {
226
249
  return publisher;
227
250
  }
228
251
  async downloadAssortmentPublishChange(assortmentId, assortmentPublishChangeId) {
229
- const resourceString = '/assortments/' + assortmentId + '/history/' + assortmentPublishChangeId;
252
+ const resourceString = '/assortments/' + assortmentId + '/history/' + assortmentPublishChangeId + '?relations=createdBy';
230
253
  return await sdk_1.Request.request(resourceString, {
231
254
  method: 'GET',
232
255
  Headers: {
@@ -57,6 +57,159 @@ describe('process publish assortment', () => {
57
57
  expect(results['results']['message']).toEqual(base_process_publish_assortment_1.BaseProcessPublishAssortment.ASSORTMENT_NO_FED_INFO + config.identifierAtts.LCSSeason);
58
58
  });
59
59
  });
60
+ describe('getPublishInfo', () => {
61
+ const config = {};
62
+ const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
63
+ const dc = new data_converter_1.DataConverter(config, mapFileUtil);
64
+ const versionName = 'Version 1';
65
+ const versionComments = 'Some Comments';
66
+ const createdOn = '2023-01-15T19:13:58.902Z';
67
+ const plan_history = [
68
+ {
69
+ id: 'sJbGx1Fpq1v2MmcI',
70
+ versionName,
71
+ versionComments,
72
+ createdOn
73
+ }
74
+ ];
75
+ it('All Publish Info', async () => {
76
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
77
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
78
+ const publisher = {
79
+ email: 'chris@vibeiq.com'
80
+ };
81
+ const assortmentName = 'VibeIQ Fall 2023';
82
+ const spy = jest.spyOn(ppa, 'getAssortment')
83
+ .mockImplementation(async (assortmentId) => {
84
+ return { id: assortmentId, name: assortmentName };
85
+ });
86
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
87
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
88
+ expect(publishInfo.versionName).toEqual(versionName);
89
+ expect(publishInfo.versionComments).toEqual(versionComments);
90
+ expect(publishInfo.publishDate).toEqual(createdOn);
91
+ expect(publishInfo.publisher).toEqual(publisher);
92
+ spy.mockRestore();
93
+ });
94
+ it('No Assortment Name', async () => {
95
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
96
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
97
+ const publisher = {
98
+ email: 'chris@vibeiq.com'
99
+ };
100
+ const spy = jest.spyOn(ppa, 'getAssortment')
101
+ .mockImplementation(async (assortmentId) => {
102
+ return { id: assortmentId, name: undefined };
103
+ });
104
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
105
+ expect(publishInfo.assortmentName).toBeUndefined;
106
+ expect(publishInfo.versionName).toEqual(versionName);
107
+ expect(publishInfo.versionComments).toEqual(versionComments);
108
+ expect(publishInfo.publishDate).toEqual(createdOn);
109
+ expect(publishInfo.publisher).toEqual(publisher);
110
+ spy.mockRestore();
111
+ });
112
+ it('No Assortment', async () => {
113
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
114
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
115
+ const publisher = {
116
+ email: 'chris@vibeiq.com'
117
+ };
118
+ const spy = jest.spyOn(ppa, 'getAssortment')
119
+ .mockImplementation(async (assortmentId) => {
120
+ return undefined;
121
+ });
122
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
123
+ expect(publishInfo.assortmentName).toBeUndefined();
124
+ expect(publishInfo.versionName).toEqual(versionName);
125
+ expect(publishInfo.versionComments).toEqual(versionComments);
126
+ expect(publishInfo.publishDate).toEqual(createdOn);
127
+ expect(publishInfo.publisher).toEqual(publisher);
128
+ spy.mockRestore();
129
+ });
130
+ it('Empty Version Name & Comments', async () => {
131
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
132
+ const history = [
133
+ {
134
+ id: 'sJbGx1Fpq1v2MmcI',
135
+ versionName: '',
136
+ versionComments: '',
137
+ createdOn
138
+ }
139
+ ];
140
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
141
+ const publisher = {
142
+ email: 'chris@vibeiq.com'
143
+ };
144
+ const assortmentName = 'VibeIQ Fall 2023';
145
+ const spy = jest.spyOn(ppa, 'getAssortment')
146
+ .mockImplementation(async (assortmentId) => {
147
+ return { id: assortmentId, name: assortmentName };
148
+ });
149
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, history, publisher);
150
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
151
+ expect(publishInfo.versionName).toEqual('');
152
+ expect(publishInfo.versionComments).toEqual('');
153
+ expect(publishInfo.publishDate).toEqual(createdOn);
154
+ expect(publishInfo.publisher).toEqual(publisher);
155
+ spy.mockRestore();
156
+ });
157
+ it('Undefined Publisher', async () => {
158
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
159
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
160
+ const publisher = undefined;
161
+ const assortmentName = 'VibeIQ Fall 2023';
162
+ const spy = jest.spyOn(ppa, 'getAssortment')
163
+ .mockImplementation(async (assortmentId) => {
164
+ return { id: assortmentId, name: assortmentName };
165
+ });
166
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
167
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
168
+ expect(publishInfo.versionName).toEqual(versionName);
169
+ expect(publishInfo.versionComments).toEqual(versionComments);
170
+ expect(publishInfo.publishDate).toEqual(createdOn);
171
+ expect(publishInfo.publisher).toBeUndefined();
172
+ spy.mockRestore();
173
+ });
174
+ it('No APC', async () => {
175
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
176
+ const assortmentPublishChangeId = 'bad-id';
177
+ const publisher = {
178
+ email: 'chris@vibeiq.com'
179
+ };
180
+ const assortmentName = 'VibeIQ Fall 2023';
181
+ const spy = jest.spyOn(ppa, 'getAssortment')
182
+ .mockImplementation(async (assortmentId) => {
183
+ return { id: assortmentId, name: assortmentName };
184
+ });
185
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
186
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
187
+ expect(publishInfo.versionName).toBeUndefined();
188
+ expect(publishInfo.versionComments).toBeUndefined();
189
+ expect(publishInfo.publishDate).toBeUndefined();
190
+ expect(publishInfo.publisher).toEqual(publisher);
191
+ spy.mockRestore();
192
+ });
193
+ it('No APC history', async () => {
194
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
195
+ const assortmentPublishChangeId = 'bad-id';
196
+ const publisher = {
197
+ email: 'chris@vibeiq.com'
198
+ };
199
+ const assortmentName = 'VibeIQ Fall 2023';
200
+ const spy = jest.spyOn(ppa, 'getAssortment')
201
+ .mockImplementation(async (assortmentId) => {
202
+ return { id: assortmentId, name: assortmentName };
203
+ });
204
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, undefined, publisher);
205
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
206
+ expect(publishInfo.versionName).toBeUndefined();
207
+ expect(publishInfo.versionComments).toBeUndefined();
208
+ expect(publishInfo.publishDate).toBeUndefined();
209
+ expect(publishInfo.publisher).toEqual(publisher);
210
+ spy.mockRestore();
211
+ });
212
+ });
60
213
  describe('getSeasonFederation', () => {
61
214
  const config = {
62
215
  identifierAtts: {
@@ -11,6 +11,9 @@ class ConfigDefaults {
11
11
  if (config?.itemPreDevelopmentLifecycleStages && !(config?.itemPreDevelopmentLifecycleStages instanceof Array)) {
12
12
  config.itemPreDevelopmentLifecycleStages = config.itemPreDevelopmentLifecycleStages.split(',');
13
13
  }
14
+ else if (Object.keys(config).includes('itemPreDevelopmentLifecycleStages')) {
15
+ delete config['itemPreDevelopmentLifecycleStages'];
16
+ }
14
17
  const defaultConfig = {
15
18
  urlContext: '/Windchill',
16
19
  sendMode: {
@@ -159,6 +159,32 @@ describe('all tests', () => {
159
159
  expect(itemPreDevelopmentLifecycleStages.includes(concept));
160
160
  expect(itemPreDevelopmentLifecycleStages.includes(development));
161
161
  });
162
+ it('itemPreDevelopmentLifecycleStages as empty string', async () => {
163
+ console.log('itemPreDevelopmentLifecycleStages as empty string');
164
+ const concept = 'concept';
165
+ const startConfig = Object.assign({}, config);
166
+ startConfig['itemPreDevelopmentLifecycleStages'] = '';
167
+ console.log('startConfig: ' + JSON.stringify(startConfig));
168
+ const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
169
+ console.log('fcConfig: ' + JSON.stringify(fcConfig));
170
+ const itemPreDevelopmentLifecycleStages = fcConfig['itemPreDevelopmentLifecycleStages'];
171
+ expect(itemPreDevelopmentLifecycleStages instanceof Array).toBeTruthy();
172
+ expect(itemPreDevelopmentLifecycleStages.length).toBe(1);
173
+ expect(itemPreDevelopmentLifecycleStages.includes(concept));
174
+ });
175
+ it('itemPreDevelopmentLifecycleStages as empty array', async () => {
176
+ console.log('itemPreDevelopmentLifecycleStages as empty string');
177
+ const concept = 'concept';
178
+ const startConfig = Object.assign({}, config);
179
+ startConfig['itemPreDevelopmentLifecycleStages'] = [];
180
+ console.log('startConfig: ' + JSON.stringify(startConfig));
181
+ const fcConfig = await config_defaults_1.ConfigDefaults.setConfigDefaults(startConfig);
182
+ console.log('fcConfig: ' + JSON.stringify(fcConfig));
183
+ const itemPreDevelopmentLifecycleStages = fcConfig['itemPreDevelopmentLifecycleStages'];
184
+ expect(itemPreDevelopmentLifecycleStages instanceof Array).toBeTruthy();
185
+ expect(itemPreDevelopmentLifecycleStages.length).toBe(1);
186
+ expect(itemPreDevelopmentLifecycleStages.includes(concept));
187
+ });
162
188
  it('identifierAtts-LCSProduct-get default', async () => {
163
189
  const startConfig = Object.assign({}, config);
164
190
  const objectClass = 'LCSProduct';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/flexplm",
3
- "version": "1.1.36",
3
+ "version": "1.1.39",
4
4
  "description": "Library used for integration with flexplm.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -9,7 +9,8 @@
9
9
  "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
10
10
  "lint": "tslint -p tsconfig.json",
11
11
  "test": "jest",
12
- "test-watch": "jest --watch"
12
+ "test-watch": "jest --watch",
13
+ "test-debug": "jest --runInBand"
13
14
  },
14
15
  "keywords": [],
15
16
  "author": "",
@@ -60,6 +60,174 @@ describe('process publish assortment', () => {
60
60
  });
61
61
  });
62
62
 
63
+ describe('getPublishInfo', () =>{
64
+ const config = {} as FCConfig;
65
+ const mapFileUtil = new MapFileUtil(new Entities());
66
+ const dc = new DataConverter(config, mapFileUtil);
67
+
68
+ const versionName = 'Version 1';
69
+ const versionComments = 'Some Comments';
70
+ const createdOn = '2023-01-15T19:13:58.902Z';
71
+ const plan_history = [
72
+ {
73
+ id: 'sJbGx1Fpq1v2MmcI',
74
+ versionName,
75
+ versionComments,
76
+ createdOn
77
+
78
+ }
79
+ ];
80
+ it('All Publish Info', async () =>{
81
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
82
+
83
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
84
+ const publisher = {
85
+ email: 'chris@vibeiq.com'
86
+ };
87
+ const assortmentName = 'VibeIQ Fall 2023';
88
+ const spy = jest.spyOn(ppa, 'getAssortment')
89
+ .mockImplementation(async (assortmentId) => {
90
+ return {id: assortmentId, name: assortmentName};
91
+ });
92
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
93
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
94
+ expect(publishInfo.versionName).toEqual(versionName);
95
+ expect(publishInfo.versionComments).toEqual(versionComments);
96
+ expect(publishInfo.publishDate).toEqual(createdOn);
97
+ expect(publishInfo.publisher).toEqual(publisher);
98
+ spy.mockRestore();
99
+ });
100
+
101
+ it('No Assortment Name', async () =>{
102
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
103
+
104
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
105
+ const publisher = {
106
+ email: 'chris@vibeiq.com'
107
+ };
108
+ const spy = jest.spyOn(ppa, 'getAssortment')
109
+ .mockImplementation(async (assortmentId) => {
110
+ return {id: assortmentId, name: undefined};
111
+ });
112
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
113
+ expect(publishInfo.assortmentName).toBeUndefined;
114
+ expect(publishInfo.versionName).toEqual(versionName);
115
+ expect(publishInfo.versionComments).toEqual(versionComments);
116
+ expect(publishInfo.publishDate).toEqual(createdOn);
117
+ expect(publishInfo.publisher).toEqual(publisher);
118
+ spy.mockRestore();
119
+ });
120
+
121
+ it('No Assortment', async () =>{
122
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
123
+
124
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
125
+ const publisher = {
126
+ email: 'chris@vibeiq.com'
127
+ };
128
+ const spy = jest.spyOn(ppa, 'getAssortment')
129
+ .mockImplementation(async (assortmentId) => {
130
+ return undefined;
131
+ });
132
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
133
+ expect(publishInfo.assortmentName).toBeUndefined();
134
+ expect(publishInfo.versionName).toEqual(versionName);
135
+ expect(publishInfo.versionComments).toEqual(versionComments);
136
+ expect(publishInfo.publishDate).toEqual(createdOn);
137
+ expect(publishInfo.publisher).toEqual(publisher);
138
+ spy.mockRestore();
139
+ });
140
+
141
+ it('Empty Version Name & Comments', async () =>{
142
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
143
+ const history = [
144
+ {
145
+ id: 'sJbGx1Fpq1v2MmcI',
146
+ versionName: '',
147
+ versionComments: '',
148
+ createdOn
149
+ }
150
+ ];
151
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
152
+ const publisher = {
153
+ email: 'chris@vibeiq.com'
154
+ };
155
+ const assortmentName = 'VibeIQ Fall 2023';
156
+ const spy = jest.spyOn(ppa, 'getAssortment')
157
+ .mockImplementation(async (assortmentId) => {
158
+ return {id: assortmentId, name: assortmentName};
159
+ });
160
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, history, publisher);
161
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
162
+ expect(publishInfo.versionName).toEqual('');
163
+ expect(publishInfo.versionComments).toEqual('');
164
+ expect(publishInfo.publishDate).toEqual(createdOn);
165
+ expect(publishInfo.publisher).toEqual(publisher);
166
+ spy.mockRestore();
167
+ });
168
+
169
+ it('Undefined Publisher', async () =>{
170
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
171
+
172
+ const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
173
+ const publisher = undefined;
174
+ const assortmentName = 'VibeIQ Fall 2023';
175
+ const spy = jest.spyOn(ppa, 'getAssortment')
176
+ .mockImplementation(async (assortmentId) => {
177
+ return {id: assortmentId, name: assortmentName};
178
+ });
179
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
180
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
181
+ expect(publishInfo.versionName).toEqual(versionName);
182
+ expect(publishInfo.versionComments).toEqual(versionComments);
183
+ expect(publishInfo.publishDate).toEqual(createdOn);
184
+ expect(publishInfo.publisher).toBeUndefined();
185
+ spy.mockRestore();
186
+ });
187
+
188
+ it('No APC', async () =>{
189
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
190
+
191
+ const assortmentPublishChangeId = 'bad-id';
192
+ const publisher = {
193
+ email: 'chris@vibeiq.com'
194
+ };
195
+ const assortmentName = 'VibeIQ Fall 2023';
196
+ const spy = jest.spyOn(ppa, 'getAssortment')
197
+ .mockImplementation(async (assortmentId) => {
198
+ return {id: assortmentId, name: assortmentName};
199
+ });
200
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
201
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
202
+ expect(publishInfo.versionName).toBeUndefined();
203
+ expect(publishInfo.versionComments).toBeUndefined();
204
+ expect(publishInfo.publishDate).toBeUndefined();
205
+ expect(publishInfo.publisher).toEqual(publisher);
206
+ spy.mockRestore();
207
+ });
208
+
209
+ it('No APC history', async () =>{
210
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
211
+
212
+ const assortmentPublishChangeId = 'bad-id';
213
+ const publisher = {
214
+ email: 'chris@vibeiq.com'
215
+ };
216
+ const assortmentName = 'VibeIQ Fall 2023';
217
+ const spy = jest.spyOn(ppa, 'getAssortment')
218
+ .mockImplementation(async (assortmentId) => {
219
+ return {id: assortmentId, name: assortmentName};
220
+ });
221
+ const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, undefined, publisher);
222
+ expect(publishInfo.assortmentName).toEqual(assortmentName);
223
+ expect(publishInfo.versionName).toBeUndefined();
224
+ expect(publishInfo.versionComments).toBeUndefined();
225
+ expect(publishInfo.publishDate).toBeUndefined();
226
+ expect(publishInfo.publisher).toEqual(publisher);
227
+ spy.mockRestore();
228
+ });
229
+
230
+ });
63
231
  describe('getSeasonFederation', () => {
64
232
  const config = {
65
233
  identifierAtts: {
@@ -25,6 +25,8 @@ export class BaseProcessPublishAssortment {
25
25
  private cache = {
26
26
  carriedFromSeason: {}
27
27
  };
28
+ private assortment: any;
29
+
28
30
  constructor(_config: FCConfig, _dc: DataConverter, _mapFileUtil: MapFileUtil) {
29
31
  this.config = _config;
30
32
  this.dc = _dc;
@@ -33,6 +35,10 @@ export class BaseProcessPublishAssortment {
33
35
  }
34
36
 
35
37
  public async process(event) {
38
+
39
+ const assortmentPublishChangeId = event.assortmentPublishChangeId;
40
+ let apcHistory;
41
+ let publisher;
36
42
  try {
37
43
  console.info('process-start!');
38
44
  const assortmentId = event.assortmentId;
@@ -49,12 +55,13 @@ export class BaseProcessPublishAssortment {
49
55
  return output;
50
56
  }
51
57
 
52
- const assortmentPublishChangeId = event.assortmentPublishChangeId;
53
- const apcHistory = await this.getApcHistory(assortmentId);
58
+ apcHistory = await this.getApcHistory(assortmentId);
59
+
54
60
  const sinceDate = await this.getSinceDate(assortmentId, assortmentPublishChangeId, apcHistory);
55
61
 
56
62
  //Get detail information
57
63
  const assortmentPublishChange = await this.downloadAssortmentPublishChange(assortmentId, assortmentPublishChangeId);
64
+ publisher = this.getPublisher(assortmentPublishChange);
58
65
 
59
66
  const changeDetail = await this.downloadHydratedChangeDetail(assortmentPublishChange);
60
67
 
@@ -65,33 +72,45 @@ export class BaseProcessPublishAssortment {
65
72
  const releasedForDevelopmentItemIds = this.getReleasedForDevelopmentItemAndFamilyIds(assortmentBaseline, deleteChanges);
66
73
  const itemToFederatedIdMapping = await this.getItemFederatedIds(/*allItemIds*/);
67
74
 
68
- const publisher = this.getPublisher(assortmentPublishChange);
69
75
  const pcd = new PublishChangeData(assortmentId, seasonFed, assortmentPublishChangeId, sinceDate, publisher);
70
76
  pcd.itemToFederatedIdMapping = itemToFederatedIdMapping;
71
77
 
72
78
  pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
73
79
 
74
80
  const output = await this.processPublish(pcd, changeDetail, assortmentBaseline, deleteChanges);
81
+ output ['publishInfo'] = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
75
82
  console.info('process-end');
76
83
 
77
84
  return output;
78
85
  } catch (e) {
86
+ try {
87
+ const publishInfo = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
88
+ e.publishInfo = publishInfo;
89
+ }catch(e2){
90
+ console.log('catch e2: ' + e2.message);
91
+ }
79
92
  console.log('catch e: ' + e.message);
80
93
  throw e;
81
94
  }
82
95
  }
96
+ async getPublishInfo(assortmentPublishChangeId: any, apcHistory: any, publisher: any): Promise<any> {
97
+ const apc = apcHistory?.find(apc => apc?.id === assortmentPublishChangeId) || {};
98
+ const assortmentName = (await this.getAssortment(assortmentPublishChangeId))?.name;
99
+ const publishInfo = {
100
+ assortmentName,
101
+ versionName: apc?.versionName,
102
+ versionComments: apc?.versionComments,
103
+ publishDate: apc?.createdOn,
104
+ publisher
105
+ };
106
+
107
+ return publishInfo;
108
+ }
83
109
 
84
110
  async getSeasonFederation(assortmentId): Promise<SeasonFederation> {
85
- let assortment;
86
- try {
87
- assortment = await new Entities().get({
88
- entityName: 'assortment',
89
- id: assortmentId
90
- });
91
- console.info('assortment-name: ' + assortment['name']);
92
- } catch (e) {
93
- console.warn(`No Assortment found for id: ${assortmentId}`);
94
- }
111
+ const assortment = await this.getAssortment(assortmentId);
112
+ console.error('assortment-name: ' + assortment?.name);
113
+
95
114
  const publishToFlexPLM = assortment?.publishToFlexPLM;
96
115
  if (!publishToFlexPLM) {
97
116
  throw new Error(BaseProcessPublishAssortment.ASSORTMENT_NOT_PUBLISHABLE);
@@ -120,6 +139,18 @@ export class BaseProcessPublishAssortment {
120
139
  return seasonObj as SeasonFederation;
121
140
  }
122
141
 
142
+ async getAssortment(assortmentId: any) {
143
+ if(this.assortment != undefined){
144
+ return this.assortment;
145
+ }
146
+
147
+ this.assortment = await new Entities().get({
148
+ entityName: 'assortment',
149
+ id: assortmentId
150
+ });
151
+ return this.assortment;
152
+ }
153
+
123
154
  public async getSinceDate(assortmentId: any, assortmentPublishChangeId: any, apcHistory: object[]): Promise<Date> {
124
155
 
125
156
  let sinceDate = null;
@@ -265,7 +296,7 @@ export class BaseProcessPublishAssortment {
265
296
  }
266
297
 
267
298
  async downloadAssortmentPublishChange(assortmentId: string, assortmentPublishChangeId: string) {
268
- const resourceString = '/assortments/' + assortmentId + '/history/' + assortmentPublishChangeId;
299
+ const resourceString = '/assortments/' + assortmentId + '/history/' + assortmentPublishChangeId + '?relations=createdBy';
269
300
  return await Request.request(
270
301
  resourceString,
271
302
  {
@@ -190,6 +190,37 @@ describe('all tests', () => {
190
190
  expect(itemPreDevelopmentLifecycleStages.includes(development));
191
191
  });
192
192
 
193
+ it('itemPreDevelopmentLifecycleStages as empty string', async () => {
194
+ console.log('itemPreDevelopmentLifecycleStages as empty string');
195
+ const concept = 'concept';
196
+ const startConfig = Object.assign({}, config);
197
+ startConfig['itemPreDevelopmentLifecycleStages'] = '';
198
+ console.log('startConfig: ' + JSON.stringify(startConfig));
199
+
200
+ const fcConfig: FCConfig = await ConfigDefaults.setConfigDefaults(startConfig);
201
+ console.log('fcConfig: ' + JSON.stringify(fcConfig));
202
+ const itemPreDevelopmentLifecycleStages = fcConfig['itemPreDevelopmentLifecycleStages'];
203
+ expect(itemPreDevelopmentLifecycleStages instanceof Array).toBeTruthy();
204
+ expect(itemPreDevelopmentLifecycleStages.length).toBe(1);
205
+ expect(itemPreDevelopmentLifecycleStages.includes(concept));
206
+
207
+ });
208
+
209
+ it('itemPreDevelopmentLifecycleStages as empty array', async () => {
210
+ console.log('itemPreDevelopmentLifecycleStages as empty string');
211
+ const concept = 'concept';
212
+ const startConfig = Object.assign({}, config);
213
+ startConfig['itemPreDevelopmentLifecycleStages'] = [];
214
+ console.log('startConfig: ' + JSON.stringify(startConfig));
215
+
216
+ const fcConfig: FCConfig = await ConfigDefaults.setConfigDefaults(startConfig);
217
+ console.log('fcConfig: ' + JSON.stringify(fcConfig));
218
+ const itemPreDevelopmentLifecycleStages = fcConfig['itemPreDevelopmentLifecycleStages'];
219
+ expect(itemPreDevelopmentLifecycleStages instanceof Array).toBeTruthy();
220
+ expect(itemPreDevelopmentLifecycleStages.length).toBe(1);
221
+ expect(itemPreDevelopmentLifecycleStages.includes(concept));
222
+
223
+ });
193
224
  it('identifierAtts-LCSProduct-get default', async () => {
194
225
  const startConfig = Object.assign({}, config);
195
226
  const objectClass = 'LCSProduct';
@@ -13,6 +13,8 @@ export class ConfigDefaults {
13
13
  //List will be comma separated list in UI, so convert to array
14
14
  if(config?.itemPreDevelopmentLifecycleStages && !(config?.itemPreDevelopmentLifecycleStages instanceof Array)){
15
15
  config.itemPreDevelopmentLifecycleStages = config.itemPreDevelopmentLifecycleStages.split(',');
16
+ } else if(Object.keys(config).includes('itemPreDevelopmentLifecycleStages')){
17
+ delete config['itemPreDevelopmentLifecycleStages'];
16
18
  }
17
19
 
18
20
  const defaultConfig = {
@@ -37,10 +37,6 @@ export class ThumbnailUtil {
37
37
  }
38
38
  /** Determines if a new image has been generated. If any viewable is new, there might be a better
39
39
  * sized image. So send the fileId as new.
40
- *
41
- * @param event
42
- * @param customSizes
43
- * @returns boolean
44
40
  */
45
41
  public isThumbnailNew(event, customSizes: any[]): boolean {
46
42
  const propertyDiffs = event?.propertyDiffs;