@contrail/flexplm 1.1.39 → 1.1.41

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.
@@ -24,7 +24,8 @@ export declare class BaseProcessPublishAssortment {
24
24
  results: any;
25
25
  skip_await?: undefined;
26
26
  }>;
27
- getPublishInfo(assortmentPublishChangeId: any, apcHistory: any, publisher: any): Promise<any>;
27
+ getPublishInfo(assortmentId: string, assortmentPublishChangeId: string, apcHistory: any, publisher: any): Promise<any>;
28
+ getSnapshotVersion(assortment: any, apc: any): Promise<number | string>;
28
29
  getSeasonFederation(assortmentId: any): Promise<SeasonFederation>;
29
30
  getAssortment(assortmentId: any): Promise<any>;
30
31
  getSinceDate(assortmentId: any, assortmentPublishChangeId: any, apcHistory: object[]): Promise<Date>;
@@ -25,9 +25,9 @@ class BaseProcessPublishAssortment {
25
25
  const assortmentPublishChangeId = event.assortmentPublishChangeId;
26
26
  let apcHistory;
27
27
  let publisher;
28
+ const assortmentId = event.assortmentId;
28
29
  try {
29
30
  console.info('process-start!');
30
- const assortmentId = event.assortmentId;
31
31
  let seasonFed;
32
32
  try {
33
33
  seasonFed = await this.getSeasonFederation(assortmentId);
@@ -54,13 +54,13 @@ class BaseProcessPublishAssortment {
54
54
  pcd.itemToFederatedIdMapping = itemToFederatedIdMapping;
55
55
  pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
56
56
  const output = await this.processPublish(pcd, changeDetail, assortmentBaseline, deleteChanges);
57
- output['publishInfo'] = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
57
+ output['publishInfo'] = await this.getPublishInfo(assortmentId, assortmentPublishChangeId, apcHistory, publisher);
58
58
  console.info('process-end');
59
59
  return output;
60
60
  }
61
61
  catch (e) {
62
62
  try {
63
- const publishInfo = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
63
+ const publishInfo = await this.getPublishInfo(assortmentId, assortmentPublishChangeId, apcHistory, publisher);
64
64
  e.publishInfo = publishInfo;
65
65
  }
66
66
  catch (e2) {
@@ -70,18 +70,54 @@ class BaseProcessPublishAssortment {
70
70
  throw e;
71
71
  }
72
72
  }
73
- async getPublishInfo(assortmentPublishChangeId, apcHistory, publisher) {
73
+ async getPublishInfo(assortmentId, assortmentPublishChangeId, apcHistory, publisher) {
74
74
  const apc = apcHistory?.find(apc => apc?.id === assortmentPublishChangeId) || {};
75
- const assortmentName = (await this.getAssortment(assortmentPublishChangeId))?.name;
75
+ const assortment = await this.getAssortment(assortmentId);
76
+ const assortmentName = assortment?.name;
77
+ const versionHistoryNumber = await this.getSnapshotVersion(assortment, apc);
76
78
  const publishInfo = {
77
79
  assortmentName,
78
80
  versionName: apc?.versionName,
79
81
  versionComments: apc?.versionComments,
80
82
  publishDate: apc?.createdOn,
81
- publisher
83
+ publisher,
84
+ versionHistoryNumber
82
85
  };
83
86
  return publishInfo;
84
87
  }
88
+ async getSnapshotVersion(assortment, apc) {
89
+ const entityReference = assortment?.createdForReference;
90
+ const createdOnString = apc?.createdOn;
91
+ if (!entityReference || !createdOnString || !apc?.id) {
92
+ return 'unknown';
93
+ }
94
+ const createdOnDate = new Date(createdOnString);
95
+ createdOnDate.setDate(createdOnDate.getDate() - 1);
96
+ const createdOnStringMinus1 = createdOnDate.toISOString();
97
+ const createdOn = 'ISGREATERTHAN ' + createdOnStringMinus1;
98
+ const snapshots = await new sdk_1.Entities().get({
99
+ entityName: 'entity-snapshot',
100
+ criteria: {
101
+ entityReference,
102
+ createdOn
103
+ }
104
+ });
105
+ const assortmentPublishChangeId = apc?.id;
106
+ const snapshot = snapshots.find(snap => snap?.assortmentChangeId === assortmentPublishChangeId);
107
+ let snapshotVersion = 'unknown';
108
+ if (snapshot && snapshot.versionNumber) {
109
+ snapshotVersion = snapshot.versionNumber;
110
+ }
111
+ else if (!snapshot) {
112
+ const createdOnTime = new Date(createdOnString).getTime();
113
+ const lastSnapshot = snapshots[snapshots.length - 1];
114
+ const lastSnapshotTime = new Date(lastSnapshot.createdOn).getTime();
115
+ if (createdOnTime > lastSnapshotTime) {
116
+ snapshotVersion = 'after: ' + lastSnapshot.versionNumber;
117
+ }
118
+ }
119
+ return snapshotVersion;
120
+ }
85
121
  async getSeasonFederation(assortmentId) {
86
122
  const assortment = await this.getAssortment(assortmentId);
87
123
  console.error('assortment-name: ' + assortment?.name);
@@ -28,11 +28,13 @@ jest.mock('../util/federation', () => {
28
28
  }
29
29
  };
30
30
  });
31
+ let entityObject = {};
32
+ let getOptionsObject = {};
31
33
  jest.mock('@contrail/sdk', () => {
32
- const entityObject = { publishToFlexPLM: true };
33
34
  return {
34
35
  Entities: class {
35
- get() {
36
+ get(_getOtionsObject) {
37
+ getOptionsObject = _getOtionsObject;
36
38
  return entityObject;
37
39
  }
38
40
  }
@@ -46,6 +48,8 @@ describe('process publish assortment', () => {
46
48
  };
47
49
  beforeEach(() => {
48
50
  federatedId = '';
51
+ entityObject = { publishToFlexPLM: true };
52
+ getOptionsObject = {};
49
53
  });
50
54
  it('No Federation Info', async () => {
51
55
  const event = {
@@ -61,6 +65,7 @@ describe('getPublishInfo', () => {
61
65
  const config = {};
62
66
  const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
63
67
  const dc = new data_converter_1.DataConverter(config, mapFileUtil);
68
+ const assortmentId = 'oqIFX3ELRy8sFRd0';
64
69
  const versionName = 'Version 1';
65
70
  const versionComments = 'Some Comments';
66
71
  const createdOn = '2023-01-15T19:13:58.902Z';
@@ -79,17 +84,24 @@ describe('getPublishInfo', () => {
79
84
  email: 'chris@vibeiq.com'
80
85
  };
81
86
  const assortmentName = 'VibeIQ Fall 2023';
82
- const spy = jest.spyOn(ppa, 'getAssortment')
87
+ const versionHistoryNumber = 1234;
88
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
83
89
  .mockImplementation(async (assortmentId) => {
84
90
  return { id: assortmentId, name: assortmentName };
85
91
  });
86
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
92
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
93
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
94
+ return versionHistoryNumber;
95
+ });
96
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
87
97
  expect(publishInfo.assortmentName).toEqual(assortmentName);
88
98
  expect(publishInfo.versionName).toEqual(versionName);
89
99
  expect(publishInfo.versionComments).toEqual(versionComments);
90
100
  expect(publishInfo.publishDate).toEqual(createdOn);
91
101
  expect(publishInfo.publisher).toEqual(publisher);
92
- spy.mockRestore();
102
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
103
+ spyGetAssortment.mockRestore();
104
+ spyyGetSnapshotVersion.mockRestore();
93
105
  });
94
106
  it('No Assortment Name', async () => {
95
107
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
@@ -97,17 +109,24 @@ describe('getPublishInfo', () => {
97
109
  const publisher = {
98
110
  email: 'chris@vibeiq.com'
99
111
  };
100
- const spy = jest.spyOn(ppa, 'getAssortment')
112
+ const versionHistoryNumber = 1234;
113
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
101
114
  .mockImplementation(async (assortmentId) => {
102
115
  return { id: assortmentId, name: undefined };
103
116
  });
104
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
117
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
118
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
119
+ return versionHistoryNumber;
120
+ });
121
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
105
122
  expect(publishInfo.assortmentName).toBeUndefined;
106
123
  expect(publishInfo.versionName).toEqual(versionName);
107
124
  expect(publishInfo.versionComments).toEqual(versionComments);
108
125
  expect(publishInfo.publishDate).toEqual(createdOn);
109
126
  expect(publishInfo.publisher).toEqual(publisher);
110
- spy.mockRestore();
127
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
128
+ spyGetAssortment.mockRestore();
129
+ spyyGetSnapshotVersion.mockRestore();
111
130
  });
112
131
  it('No Assortment', async () => {
113
132
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
@@ -115,17 +134,24 @@ describe('getPublishInfo', () => {
115
134
  const publisher = {
116
135
  email: 'chris@vibeiq.com'
117
136
  };
118
- const spy = jest.spyOn(ppa, 'getAssortment')
137
+ const versionHistoryNumber = 1234;
138
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
119
139
  .mockImplementation(async (assortmentId) => {
120
140
  return undefined;
121
141
  });
122
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
142
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
143
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
144
+ return versionHistoryNumber;
145
+ });
146
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
123
147
  expect(publishInfo.assortmentName).toBeUndefined();
124
148
  expect(publishInfo.versionName).toEqual(versionName);
125
149
  expect(publishInfo.versionComments).toEqual(versionComments);
126
150
  expect(publishInfo.publishDate).toEqual(createdOn);
127
151
  expect(publishInfo.publisher).toEqual(publisher);
128
- spy.mockRestore();
152
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
153
+ spyGetAssortment.mockRestore();
154
+ spyyGetSnapshotVersion.mockRestore();
129
155
  });
130
156
  it('Empty Version Name & Comments', async () => {
131
157
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
@@ -142,34 +168,48 @@ describe('getPublishInfo', () => {
142
168
  email: 'chris@vibeiq.com'
143
169
  };
144
170
  const assortmentName = 'VibeIQ Fall 2023';
145
- const spy = jest.spyOn(ppa, 'getAssortment')
171
+ const versionHistoryNumber = 1234;
172
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
146
173
  .mockImplementation(async (assortmentId) => {
147
174
  return { id: assortmentId, name: assortmentName };
148
175
  });
149
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, history, publisher);
176
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
177
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
178
+ return versionHistoryNumber;
179
+ });
180
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, history, publisher);
150
181
  expect(publishInfo.assortmentName).toEqual(assortmentName);
151
182
  expect(publishInfo.versionName).toEqual('');
152
183
  expect(publishInfo.versionComments).toEqual('');
153
184
  expect(publishInfo.publishDate).toEqual(createdOn);
154
185
  expect(publishInfo.publisher).toEqual(publisher);
155
- spy.mockRestore();
186
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
187
+ spyGetAssortment.mockRestore();
188
+ spyyGetSnapshotVersion.mockRestore();
156
189
  });
157
190
  it('Undefined Publisher', async () => {
158
191
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
159
192
  const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
160
193
  const publisher = undefined;
161
194
  const assortmentName = 'VibeIQ Fall 2023';
162
- const spy = jest.spyOn(ppa, 'getAssortment')
195
+ const versionHistoryNumber = 1234;
196
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
163
197
  .mockImplementation(async (assortmentId) => {
164
198
  return { id: assortmentId, name: assortmentName };
165
199
  });
166
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
200
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
201
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
202
+ return versionHistoryNumber;
203
+ });
204
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
167
205
  expect(publishInfo.assortmentName).toEqual(assortmentName);
168
206
  expect(publishInfo.versionName).toEqual(versionName);
169
207
  expect(publishInfo.versionComments).toEqual(versionComments);
170
208
  expect(publishInfo.publishDate).toEqual(createdOn);
171
209
  expect(publishInfo.publisher).toBeUndefined();
172
- spy.mockRestore();
210
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
211
+ spyGetAssortment.mockRestore();
212
+ spyyGetSnapshotVersion.mockRestore();
173
213
  });
174
214
  it('No APC', async () => {
175
215
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
@@ -178,17 +218,24 @@ describe('getPublishInfo', () => {
178
218
  email: 'chris@vibeiq.com'
179
219
  };
180
220
  const assortmentName = 'VibeIQ Fall 2023';
181
- const spy = jest.spyOn(ppa, 'getAssortment')
221
+ const versionHistoryNumber = 1234;
222
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
182
223
  .mockImplementation(async (assortmentId) => {
183
224
  return { id: assortmentId, name: assortmentName };
184
225
  });
185
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
226
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
227
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
228
+ return versionHistoryNumber;
229
+ });
230
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
186
231
  expect(publishInfo.assortmentName).toEqual(assortmentName);
187
232
  expect(publishInfo.versionName).toBeUndefined();
188
233
  expect(publishInfo.versionComments).toBeUndefined();
189
234
  expect(publishInfo.publishDate).toBeUndefined();
190
235
  expect(publishInfo.publisher).toEqual(publisher);
191
- spy.mockRestore();
236
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
237
+ spyGetAssortment.mockRestore();
238
+ spyyGetSnapshotVersion.mockRestore();
192
239
  });
193
240
  it('No APC history', async () => {
194
241
  const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
@@ -197,17 +244,125 @@ describe('getPublishInfo', () => {
197
244
  email: 'chris@vibeiq.com'
198
245
  };
199
246
  const assortmentName = 'VibeIQ Fall 2023';
200
- const spy = jest.spyOn(ppa, 'getAssortment')
247
+ const versionHistoryNumber = 1234;
248
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
201
249
  .mockImplementation(async (assortmentId) => {
202
250
  return { id: assortmentId, name: assortmentName };
203
251
  });
204
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, undefined, publisher);
252
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
253
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
254
+ return versionHistoryNumber;
255
+ });
256
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, undefined, publisher);
205
257
  expect(publishInfo.assortmentName).toEqual(assortmentName);
206
258
  expect(publishInfo.versionName).toBeUndefined();
207
259
  expect(publishInfo.versionComments).toBeUndefined();
208
260
  expect(publishInfo.publishDate).toBeUndefined();
209
261
  expect(publishInfo.publisher).toEqual(publisher);
210
- spy.mockRestore();
262
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
263
+ spyGetAssortment.mockRestore();
264
+ spyyGetSnapshotVersion.mockRestore();
265
+ });
266
+ });
267
+ describe('getSnapshotVersion', () => {
268
+ const config = {
269
+ identifierAtts: {
270
+ LCSSeason: ['flexPLMSeasonName']
271
+ }
272
+ };
273
+ const mapFileUtil = new transform_data_1.MapFileUtil(new sdk_1.Entities());
274
+ const dc = new data_converter_1.DataConverter(config, mapFileUtil);
275
+ const ppa = new base_process_publish_assortment_1.BaseProcessPublishAssortment(config, dc, mapFileUtil);
276
+ beforeEach(() => {
277
+ federatedId = '';
278
+ entityObject = { publishToFlexPLM: true };
279
+ getOptionsObject = {};
280
+ });
281
+ it('has snapshot version', async () => {
282
+ const assortment = {
283
+ id: 'rm35clTNxvS4wm6y',
284
+ name: 'VibeIQ Fall 2023',
285
+ createdForReference: 'plan:w23wre'
286
+ };
287
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
288
+ const apc = {
289
+ id: assortmentChangeId,
290
+ versionName: 'Version 1',
291
+ versionComments: 'Some Comments',
292
+ createdOn: '2023-01-15T19:13:58.902Z'
293
+ };
294
+ const versionNumber = 1234;
295
+ const snapshots = [
296
+ {
297
+ id: 'qewrwer',
298
+ assortmentChangeId,
299
+ versionNumber
300
+ }
301
+ ];
302
+ entityObject = snapshots;
303
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
304
+ expect(versionHistoryNumber).toEqual(versionNumber);
305
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
306
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
307
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
308
+ });
309
+ it('doesnt find snapshot version, last snapshot after apc', async () => {
310
+ const assortment = {
311
+ id: 'rm35clTNxvS4wm6y',
312
+ name: 'VibeIQ Fall 2023',
313
+ createdForReference: 'plan:w23wre'
314
+ };
315
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
316
+ const apc = {
317
+ id: assortmentChangeId,
318
+ versionName: 'Version 1',
319
+ versionComments: 'Some Comments',
320
+ createdOn: '2023-01-15T19:13:58.902Z'
321
+ };
322
+ const versionNumber = 1234;
323
+ const snapshots = [
324
+ {
325
+ id: 'qewrwer',
326
+ assortmentChangeId: 'bad-id',
327
+ createdOn: '2024-01-15T19:13:58.902Z',
328
+ versionNumber
329
+ }
330
+ ];
331
+ entityObject = snapshots;
332
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
333
+ expect(versionHistoryNumber).toEqual('unknown');
334
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
335
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
336
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
337
+ });
338
+ it('doesnt find snapshot version, last snapshot before apc', async () => {
339
+ const assortment = {
340
+ id: 'rm35clTNxvS4wm6y',
341
+ name: 'VibeIQ Fall 2023',
342
+ createdForReference: 'plan:w23wre'
343
+ };
344
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
345
+ const apc = {
346
+ id: assortmentChangeId,
347
+ versionName: 'Version 1',
348
+ versionComments: 'Some Comments',
349
+ createdOn: '2023-01-15T19:13:58.902Z'
350
+ };
351
+ const versionNumber = 1234;
352
+ const snapshots = [
353
+ {
354
+ id: 'qewrwer',
355
+ assortmentChangeId: 'bad-id',
356
+ createdOn: '2023-01-14T19:13:58.902Z',
357
+ versionNumber
358
+ }
359
+ ];
360
+ entityObject = snapshots;
361
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
362
+ expect(versionHistoryNumber).toEqual('after: ' + versionNumber);
363
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
364
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
365
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
211
366
  });
212
367
  });
213
368
  describe('getSeasonFederation', () => {
@@ -218,6 +373,8 @@ describe('getSeasonFederation', () => {
218
373
  };
219
374
  beforeEach(() => {
220
375
  federatedId = '';
376
+ entityObject = { publishToFlexPLM: true };
377
+ getOptionsObject = {};
221
378
  });
222
379
  it('No Federation Info', async () => {
223
380
  const assortmentId = 'B3oRQpYVYzcJAJtQ';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/flexplm",
3
- "version": "1.1.39",
3
+ "version": "1.1.41",
4
4
  "description": "Library used for integration with flexplm.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -30,11 +30,13 @@ jest.mock('../util/federation', () => {
30
30
  }
31
31
  };
32
32
  });
33
+ let entityObject = {};
34
+ let getOptionsObject = {};
33
35
  jest.mock('@contrail/sdk', () => {
34
- const entityObject = { publishToFlexPLM: true };
35
36
  return {
36
- Entities: class {
37
- get() {
37
+ Entities: class{
38
+ get(_getOtionsObject){
39
+ getOptionsObject = _getOtionsObject;
38
40
  return entityObject;
39
41
  }
40
42
  }
@@ -48,6 +50,8 @@ describe('process publish assortment', () => {
48
50
  } as unknown as FCConfig;
49
51
  beforeEach(() => {
50
52
  federatedId = '';
53
+ entityObject = {publishToFlexPLM:true};
54
+ getOptionsObject = {};
51
55
  });
52
56
  it('No Federation Info', async () => {
53
57
  const event = {
@@ -65,6 +69,7 @@ describe('getPublishInfo', () =>{
65
69
  const mapFileUtil = new MapFileUtil(new Entities());
66
70
  const dc = new DataConverter(config, mapFileUtil);
67
71
 
72
+ const assortmentId = 'oqIFX3ELRy8sFRd0';
68
73
  const versionName = 'Version 1';
69
74
  const versionComments = 'Some Comments';
70
75
  const createdOn = '2023-01-15T19:13:58.902Z';
@@ -85,17 +90,25 @@ describe('getPublishInfo', () =>{
85
90
  email: 'chris@vibeiq.com'
86
91
  };
87
92
  const assortmentName = 'VibeIQ Fall 2023';
88
- const spy = jest.spyOn(ppa, 'getAssortment')
93
+ const versionHistoryNumber = 1234;
94
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
89
95
  .mockImplementation(async (assortmentId) => {
90
96
  return {id: assortmentId, name: assortmentName};
91
97
  });
92
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
98
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
99
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
100
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
101
+ return versionHistoryNumber;
102
+ });
103
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
93
104
  expect(publishInfo.assortmentName).toEqual(assortmentName);
94
105
  expect(publishInfo.versionName).toEqual(versionName);
95
106
  expect(publishInfo.versionComments).toEqual(versionComments);
96
107
  expect(publishInfo.publishDate).toEqual(createdOn);
97
108
  expect(publishInfo.publisher).toEqual(publisher);
98
- spy.mockRestore();
109
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
110
+ spyGetAssortment.mockRestore();
111
+ spyyGetSnapshotVersion.mockRestore();
99
112
  });
100
113
 
101
114
  it('No Assortment Name', async () =>{
@@ -105,17 +118,25 @@ describe('getPublishInfo', () =>{
105
118
  const publisher = {
106
119
  email: 'chris@vibeiq.com'
107
120
  };
108
- const spy = jest.spyOn(ppa, 'getAssortment')
121
+ const versionHistoryNumber = 1234;
122
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
109
123
  .mockImplementation(async (assortmentId) => {
110
124
  return {id: assortmentId, name: undefined};
111
125
  });
112
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
126
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
127
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
128
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
129
+ return versionHistoryNumber;
130
+ });
131
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
113
132
  expect(publishInfo.assortmentName).toBeUndefined;
114
133
  expect(publishInfo.versionName).toEqual(versionName);
115
134
  expect(publishInfo.versionComments).toEqual(versionComments);
116
135
  expect(publishInfo.publishDate).toEqual(createdOn);
117
136
  expect(publishInfo.publisher).toEqual(publisher);
118
- spy.mockRestore();
137
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
138
+ spyGetAssortment.mockRestore();
139
+ spyyGetSnapshotVersion.mockRestore();
119
140
  });
120
141
 
121
142
  it('No Assortment', async () =>{
@@ -125,17 +146,25 @@ describe('getPublishInfo', () =>{
125
146
  const publisher = {
126
147
  email: 'chris@vibeiq.com'
127
148
  };
128
- const spy = jest.spyOn(ppa, 'getAssortment')
149
+ const versionHistoryNumber = 1234;
150
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
129
151
  .mockImplementation(async (assortmentId) => {
130
152
  return undefined;
131
153
  });
132
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
154
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
155
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
156
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
157
+ return versionHistoryNumber;
158
+ });
159
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
133
160
  expect(publishInfo.assortmentName).toBeUndefined();
134
161
  expect(publishInfo.versionName).toEqual(versionName);
135
162
  expect(publishInfo.versionComments).toEqual(versionComments);
136
163
  expect(publishInfo.publishDate).toEqual(createdOn);
137
164
  expect(publishInfo.publisher).toEqual(publisher);
138
- spy.mockRestore();
165
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
166
+ spyGetAssortment.mockRestore();
167
+ spyyGetSnapshotVersion.mockRestore();
139
168
  });
140
169
 
141
170
  it('Empty Version Name & Comments', async () =>{
@@ -153,17 +182,25 @@ describe('getPublishInfo', () =>{
153
182
  email: 'chris@vibeiq.com'
154
183
  };
155
184
  const assortmentName = 'VibeIQ Fall 2023';
156
- const spy = jest.spyOn(ppa, 'getAssortment')
185
+ const versionHistoryNumber = 1234;
186
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
157
187
  .mockImplementation(async (assortmentId) => {
158
188
  return {id: assortmentId, name: assortmentName};
159
189
  });
160
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, history, publisher);
190
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
191
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
192
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
193
+ return versionHistoryNumber;
194
+ });
195
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, history, publisher);
161
196
  expect(publishInfo.assortmentName).toEqual(assortmentName);
162
197
  expect(publishInfo.versionName).toEqual('');
163
198
  expect(publishInfo.versionComments).toEqual('');
164
199
  expect(publishInfo.publishDate).toEqual(createdOn);
165
200
  expect(publishInfo.publisher).toEqual(publisher);
166
- spy.mockRestore();
201
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
202
+ spyGetAssortment.mockRestore();
203
+ spyyGetSnapshotVersion.mockRestore();
167
204
  });
168
205
 
169
206
  it('Undefined Publisher', async () =>{
@@ -172,17 +209,25 @@ describe('getPublishInfo', () =>{
172
209
  const assortmentPublishChangeId = 'sJbGx1Fpq1v2MmcI';
173
210
  const publisher = undefined;
174
211
  const assortmentName = 'VibeIQ Fall 2023';
175
- const spy = jest.spyOn(ppa, 'getAssortment')
212
+ const versionHistoryNumber = 1234;
213
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
176
214
  .mockImplementation(async (assortmentId) => {
177
215
  return {id: assortmentId, name: assortmentName};
178
216
  });
179
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
217
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
218
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
219
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
220
+ return versionHistoryNumber;
221
+ });
222
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
180
223
  expect(publishInfo.assortmentName).toEqual(assortmentName);
181
224
  expect(publishInfo.versionName).toEqual(versionName);
182
225
  expect(publishInfo.versionComments).toEqual(versionComments);
183
226
  expect(publishInfo.publishDate).toEqual(createdOn);
184
227
  expect(publishInfo.publisher).toBeUndefined();
185
- spy.mockRestore();
228
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
229
+ spyGetAssortment.mockRestore();
230
+ spyyGetSnapshotVersion.mockRestore();
186
231
  });
187
232
 
188
233
  it('No APC', async () =>{
@@ -193,17 +238,25 @@ describe('getPublishInfo', () =>{
193
238
  email: 'chris@vibeiq.com'
194
239
  };
195
240
  const assortmentName = 'VibeIQ Fall 2023';
196
- const spy = jest.spyOn(ppa, 'getAssortment')
241
+ const versionHistoryNumber = 1234;
242
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
197
243
  .mockImplementation(async (assortmentId) => {
198
244
  return {id: assortmentId, name: assortmentName};
199
245
  });
200
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, plan_history, publisher);
246
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
247
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
248
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
249
+ return versionHistoryNumber;
250
+ });
251
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, plan_history, publisher);
201
252
  expect(publishInfo.assortmentName).toEqual(assortmentName);
202
253
  expect(publishInfo.versionName).toBeUndefined();
203
254
  expect(publishInfo.versionComments).toBeUndefined();
204
255
  expect(publishInfo.publishDate).toBeUndefined();
205
256
  expect(publishInfo.publisher).toEqual(publisher);
206
- spy.mockRestore();
257
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
258
+ spyGetAssortment.mockRestore();
259
+ spyyGetSnapshotVersion.mockRestore();
207
260
  });
208
261
 
209
262
  it('No APC history', async () =>{
@@ -214,21 +267,148 @@ describe('getPublishInfo', () =>{
214
267
  email: 'chris@vibeiq.com'
215
268
  };
216
269
  const assortmentName = 'VibeIQ Fall 2023';
217
- const spy = jest.spyOn(ppa, 'getAssortment')
270
+ const versionHistoryNumber = 1234;
271
+ const spyGetAssortment = jest.spyOn(ppa, 'getAssortment')
218
272
  .mockImplementation(async (assortmentId) => {
219
273
  return {id: assortmentId, name: assortmentName};
220
274
  });
221
- const publishInfo = await ppa.getPublishInfo(assortmentPublishChangeId, undefined, publisher);
275
+ const spyyGetSnapshotVersion = jest.spyOn(ppa, 'getSnapshotVersion')
276
+ // eslint-disable-next-line unused-imports/no-unused-vars, @typescript-eslint/no-unused-vars
277
+ .mockImplementation(async (assortmentId, assortmentPublishChangeId) => {
278
+ return versionHistoryNumber;
279
+ });
280
+ const publishInfo = await ppa.getPublishInfo(assortmentId, assortmentPublishChangeId, undefined, publisher);
222
281
  expect(publishInfo.assortmentName).toEqual(assortmentName);
223
282
  expect(publishInfo.versionName).toBeUndefined();
224
283
  expect(publishInfo.versionComments).toBeUndefined();
225
284
  expect(publishInfo.publishDate).toBeUndefined();
226
285
  expect(publishInfo.publisher).toEqual(publisher);
227
- spy.mockRestore();
286
+ expect(publishInfo.versionHistoryNumber).toEqual(versionHistoryNumber);
287
+ spyGetAssortment.mockRestore();
288
+ spyyGetSnapshotVersion.mockRestore();
228
289
  });
229
290
 
230
291
  });
231
- describe('getSeasonFederation', () => {
292
+
293
+ describe('getSnapshotVersion', () =>{
294
+ const config = {
295
+ identifierAtts: {
296
+ LCSSeason: ['flexPLMSeasonName']
297
+ }
298
+ } as unknown as FCConfig;
299
+ const mapFileUtil = new MapFileUtil(new Entities());
300
+ const dc = new DataConverter(config, mapFileUtil);
301
+ const ppa = new BaseProcessPublishAssortment(config, dc, mapFileUtil);
302
+ beforeEach(() =>{
303
+ federatedId = '';
304
+ entityObject = { publishToFlexPLM:true};
305
+ getOptionsObject = {};
306
+ });
307
+
308
+ it('has snapshot version', async () =>{
309
+ const assortment = {
310
+ id: 'rm35clTNxvS4wm6y',
311
+ name: 'VibeIQ Fall 2023',
312
+ createdForReference: 'plan:w23wre'
313
+ };
314
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
315
+ const apc = {
316
+ id: assortmentChangeId,
317
+ versionName: 'Version 1',
318
+ versionComments: 'Some Comments',
319
+ createdOn: '2023-01-15T19:13:58.902Z'
320
+ };
321
+
322
+ const versionNumber = 1234;
323
+ const snapshots = [
324
+ {
325
+ id: 'qewrwer',
326
+ assortmentChangeId,
327
+ versionNumber
328
+ }
329
+ ];
330
+
331
+ entityObject = snapshots;
332
+
333
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
334
+
335
+ expect(versionHistoryNumber).toEqual(versionNumber);
336
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
337
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
338
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
339
+ });
340
+
341
+ it('doesnt find snapshot version, last snapshot after apc', async () =>{
342
+ const assortment = {
343
+ id: 'rm35clTNxvS4wm6y',
344
+ name: 'VibeIQ Fall 2023',
345
+ createdForReference: 'plan:w23wre'
346
+ };
347
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
348
+ const apc = {
349
+ id: assortmentChangeId,
350
+ versionName: 'Version 1',
351
+ versionComments: 'Some Comments',
352
+ createdOn: '2023-01-15T19:13:58.902Z'
353
+ };
354
+
355
+ const versionNumber = 1234;
356
+ const snapshots = [
357
+ {
358
+ id: 'qewrwer',
359
+ assortmentChangeId: 'bad-id',
360
+ createdOn: '2024-01-15T19:13:58.902Z',
361
+ versionNumber
362
+ }
363
+ ];
364
+
365
+ entityObject = snapshots;
366
+
367
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
368
+
369
+ expect(versionHistoryNumber).toEqual('unknown');
370
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
371
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
372
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
373
+ });
374
+
375
+ it('doesnt find snapshot version, last snapshot before apc', async () =>{
376
+ const assortment = {
377
+ id: 'rm35clTNxvS4wm6y',
378
+ name: 'VibeIQ Fall 2023',
379
+ createdForReference: 'plan:w23wre'
380
+ };
381
+ const assortmentChangeId = 'sJbGx1Fpq1v2MmcI';
382
+ const apc = {
383
+ id: assortmentChangeId,
384
+ versionName: 'Version 1',
385
+ versionComments: 'Some Comments',
386
+ createdOn: '2023-01-15T19:13:58.902Z'
387
+ };
388
+
389
+ const versionNumber = 1234;
390
+ const snapshots = [
391
+ {
392
+ id: 'qewrwer',
393
+ assortmentChangeId: 'bad-id',
394
+ createdOn: '2023-01-14T19:13:58.902Z',
395
+ versionNumber
396
+ }
397
+ ];
398
+
399
+ entityObject = snapshots;
400
+
401
+ const versionHistoryNumber = await ppa.getSnapshotVersion(assortment, apc);
402
+
403
+ expect(versionHistoryNumber).toEqual('after: '+ versionNumber);
404
+ expect(getOptionsObject['entityName']).toEqual('entity-snapshot');
405
+ expect(getOptionsObject['criteria']['entityReference']).toEqual(assortment.createdForReference);
406
+ expect(getOptionsObject['criteria']['createdOn'].indexOf('ISGREATERTHAN')).toEqual(0);
407
+ });
408
+
409
+ });
410
+
411
+ describe('getSeasonFederation', () =>{
232
412
  const config = {
233
413
  identifierAtts: {
234
414
  LCSSeason: ['flexPLMSeasonName']
@@ -236,6 +416,8 @@ describe('getSeasonFederation', () => {
236
416
  } as unknown as FCConfig;
237
417
  beforeEach(() => {
238
418
  federatedId = '';
419
+ entityObject = { publishToFlexPLM:true};
420
+ getOptionsObject = {};
239
421
  });
240
422
  it('No Federation Info', async () => {
241
423
  const assortmentId = 'B3oRQpYVYzcJAJtQ';
@@ -39,9 +39,9 @@ export class BaseProcessPublishAssortment {
39
39
  const assortmentPublishChangeId = event.assortmentPublishChangeId;
40
40
  let apcHistory;
41
41
  let publisher;
42
+ const assortmentId = event.assortmentId;
42
43
  try {
43
44
  console.info('process-start!');
44
- const assortmentId = event.assortmentId;
45
45
  let seasonFed: SeasonFederation;
46
46
  try {
47
47
  seasonFed = await this.getSeasonFederation(assortmentId);
@@ -78,13 +78,13 @@ export class BaseProcessPublishAssortment {
78
78
  pcd.releasedForDevelopmentItemIds = releasedForDevelopmentItemIds;
79
79
 
80
80
  const output = await this.processPublish(pcd, changeDetail, assortmentBaseline, deleteChanges);
81
- output ['publishInfo'] = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
81
+ output ['publishInfo'] = await this.getPublishInfo(assortmentId, assortmentPublishChangeId, apcHistory, publisher);
82
82
  console.info('process-end');
83
83
 
84
84
  return output;
85
85
  } catch (e) {
86
86
  try {
87
- const publishInfo = await this.getPublishInfo(assortmentPublishChangeId, apcHistory, publisher);
87
+ const publishInfo = await this.getPublishInfo(assortmentId, assortmentPublishChangeId, apcHistory, publisher);
88
88
  e.publishInfo = publishInfo;
89
89
  }catch(e2){
90
90
  console.log('catch e2: ' + e2.message);
@@ -93,20 +93,68 @@ export class BaseProcessPublishAssortment {
93
93
  throw e;
94
94
  }
95
95
  }
96
- async getPublishInfo(assortmentPublishChangeId: any, apcHistory: any, publisher: any): Promise<any> {
96
+ async getPublishInfo(assortmentId: string, assortmentPublishChangeId: string, apcHistory: any, publisher: any): Promise<any> {
97
97
  const apc = apcHistory?.find(apc => apc?.id === assortmentPublishChangeId) || {};
98
- const assortmentName = (await this.getAssortment(assortmentPublishChangeId))?.name;
98
+ const assortment = await this.getAssortment(assortmentId);
99
+ const assortmentName = assortment?.name;
100
+ const versionHistoryNumber = await this.getSnapshotVersion(assortment, apc);
99
101
  const publishInfo = {
100
102
  assortmentName,
101
103
  versionName: apc?.versionName,
102
104
  versionComments: apc?.versionComments,
103
105
  publishDate: apc?.createdOn,
104
- publisher
106
+ publisher,
107
+ versionHistoryNumber
105
108
  };
106
109
 
107
110
  return publishInfo;
108
111
  }
109
112
 
113
+ /** Gets the version number of the snapshot that was created for the publish change.
114
+ * But if no snapshot was found for the publish change, and the last snapshot was
115
+ * created before the publish change, then it returns 'after: versionNumber' where
116
+ * versionNumber is the version number of the last snapshot.
117
+ * If no snapshot was found for the publish change, and the last snapshot was
118
+ * created after the publish change, then it returns 'unknown'.
119
+ *
120
+ * @returns versionNumber or 'unknown' or 'after: versionNumber'
121
+ */
122
+ async getSnapshotVersion(assortment: any, apc: any ): Promise<number|string>{
123
+ const entityReference = assortment?.createdForReference;
124
+ const createdOnString = apc?.createdOn;
125
+ if(!entityReference || !createdOnString || !apc?.id){
126
+ return 'unknown';
127
+ }
128
+ const createdOnDate = new Date(createdOnString);
129
+ createdOnDate.setDate(createdOnDate.getDate() - 1);//subtract 1 day
130
+ const createdOnStringMinus1 = createdOnDate.toISOString();
131
+ const createdOn = 'ISGREATERTHAN ' + createdOnStringMinus1;
132
+
133
+ const snapshots = await new Entities().get({
134
+ entityName: 'entity-snapshot',
135
+ criteria: {
136
+ entityReference,
137
+ createdOn
138
+ }
139
+ });
140
+
141
+ const assortmentPublishChangeId = apc?.id;
142
+ const snapshot = snapshots.find(snap => snap?.assortmentChangeId === assortmentPublishChangeId);
143
+ let snapshotVersion = 'unknown';
144
+ if(snapshot && snapshot.versionNumber){
145
+ snapshotVersion = snapshot.versionNumber;
146
+ } else if(!snapshot){
147
+ const createdOnTime = new Date(createdOnString).getTime();
148
+ const lastSnapshot = snapshots[snapshots.length - 1];
149
+ const lastSnapshotTime = new Date(lastSnapshot.createdOn).getTime();
150
+ if(createdOnTime > lastSnapshotTime){
151
+ snapshotVersion = 'after: ' + lastSnapshot.versionNumber;
152
+ }
153
+
154
+ }
155
+
156
+ return snapshotVersion;
157
+ }
110
158
  async getSeasonFederation(assortmentId): Promise<SeasonFederation> {
111
159
  const assortment = await this.getAssortment(assortmentId);
112
160
  console.error('assortment-name: ' + assortment?.name);