@plusscommunities/pluss-maintenance-aws-forms 2.1.20 → 2.1.21-auth.0
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/feature.config.js +9 -0
- package/getData.js +7 -0
- package/integration/IntegrationStrategy.js +6 -0
- package/integration/archibus/ArchibusStrategy.js +706 -607
- package/integration/index.js +3 -0
- package/integration/seestuff/SeeStuffStrategy.js +298 -0
- package/jobChanged.js +1 -1
- package/jobTypesChanged.js +55 -0
- package/package.json +6 -2
- package/requests/getExternalSync.js +147 -0
- package/requests/getRequests.js +6 -0
- package/requests/retrySync.js +161 -0
- package/requests/setExternalJobId.js +4 -1
- package/scheduleJobImport.js +9 -3
- package/updateData.js +4 -0
- package/values.config.a.js +1 -0
- package/values.config.default.js +1 -0
- package/values.config.enquiry.js +1 -0
- package/values.config.feedback.js +1 -0
- package/values.config.food.js +1 -0
- package/values.config.forms.js +1 -0
- package/values.config.js +1 -0
- package/package-lock.json +0 -8051
|
@@ -13,613 +13,712 @@ const getString = require("@plusscommunities/pluss-core-aws/db/strings/getString
|
|
|
13
13
|
const { values } = require("../../values.config");
|
|
14
14
|
|
|
15
15
|
class ArchibusStrategy extends IntegrationStrategy {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
16
|
+
constructor(config) {
|
|
17
|
+
super();
|
|
18
|
+
this.baseUrl = config.BaseUrl; // base URL for the API
|
|
19
|
+
this.apiKeyHeader = config.APIKeyHeader; // header to use for API key
|
|
20
|
+
this.apiKey = config.APIKey; // API key
|
|
21
|
+
|
|
22
|
+
const url = new URL(this.baseUrl);
|
|
23
|
+
this.host = url.host;
|
|
24
|
+
|
|
25
|
+
this.statusMap = config.StatusMap;
|
|
26
|
+
this.completedStatuses = config.CompletedStatuses ?? [];
|
|
27
|
+
this.siteMap = config.SiteMap ?? {};
|
|
28
|
+
this.buildingCodes = [];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Gets the entity type for the integration
|
|
33
|
+
*
|
|
34
|
+
* @returns {String} The entity type for the integration
|
|
35
|
+
*/
|
|
36
|
+
getEntityType = () => {
|
|
37
|
+
return `${values.serviceKey}_Archibus`;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Validates the integration
|
|
42
|
+
*
|
|
43
|
+
* @returns {Boolean} Whether the integration is valid
|
|
44
|
+
*/
|
|
45
|
+
isValidIntegration = () => {
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Gets the refresh interval for the Archibus system
|
|
51
|
+
*
|
|
52
|
+
* @returns {Number} The refresh interval in milliseconds
|
|
53
|
+
*/
|
|
54
|
+
getRefreshInterval = () => {
|
|
55
|
+
return 60 * 60 * 1000; // 60 minutes
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a request from the Archibus system
|
|
60
|
+
*
|
|
61
|
+
* @param {Object} request - Request definition on Pluss
|
|
62
|
+
* @param {Object} mockResponse - Mock response from Archibus to simulate response
|
|
63
|
+
* @returns {Boolean} Whether the request was created on Archibus
|
|
64
|
+
*/
|
|
65
|
+
createRequest = async (request, mockResponse = null) => {
|
|
66
|
+
const logId = log("Archibus:CreateRequest", "Start", request);
|
|
67
|
+
|
|
68
|
+
let siteId = this.siteMap[request.site];
|
|
69
|
+
let buildingCode = null;
|
|
70
|
+
if (request.room) {
|
|
71
|
+
if (this.buildingCodes.length === 0) {
|
|
72
|
+
this.buildingCodes = await getString(
|
|
73
|
+
getRowId(request.site, `${values.serviceKey}buildingcodes`),
|
|
74
|
+
"plussSpace",
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
const building = this.buildingCodes.find((b) => {
|
|
78
|
+
const address = request.room.toLowerCase();
|
|
79
|
+
const search = b.SearchString.toLowerCase();
|
|
80
|
+
const name = b.BuildingName.toLowerCase();
|
|
81
|
+
return address.includes(search) || address.includes(name);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
if (building?.SiteCode) siteId = building.SiteCode.toString();
|
|
85
|
+
buildingCode = building?.BuildingCode;
|
|
86
|
+
}
|
|
87
|
+
if (!siteId) return false;
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const data = {
|
|
91
|
+
prob_type: "1.ON-SITE|1. MAINTENANCE",
|
|
92
|
+
requestor: "PLUSS",
|
|
93
|
+
description: `${request.title}${
|
|
94
|
+
_.isEmpty(request.description) ? "" : `\n\n${request.description}`
|
|
95
|
+
}${_.isEmpty(request.room) ? "" : `\n\nLocation: ${request.room}`}${
|
|
96
|
+
_.isEmpty(request.userName) ? "" : `\n\nName: ${request.userName}`
|
|
97
|
+
}${_.isEmpty(request.phone) ? "" : `\n\nPhone: ${request.phone}`}${
|
|
98
|
+
_.isEmpty(request.type) ? "" : `\n\nJob Type: ${request.type}`
|
|
99
|
+
}${
|
|
100
|
+
_.isEmpty(request.images)
|
|
101
|
+
? ""
|
|
102
|
+
: `\n\nImages: ${request.images.join("\n")}`
|
|
103
|
+
}`,
|
|
104
|
+
site_id: siteId,
|
|
105
|
+
};
|
|
106
|
+
if (buildingCode) data.bl_id = buildingCode;
|
|
107
|
+
log("Archibus:CreateRequest", "Request", data, logId);
|
|
108
|
+
|
|
109
|
+
const response =
|
|
110
|
+
mockResponse ??
|
|
111
|
+
(await axios({
|
|
112
|
+
method: "PUT",
|
|
113
|
+
url: `${this.baseUrl}/createWorkRequest`,
|
|
114
|
+
timeout: 30000,
|
|
115
|
+
headers: {
|
|
116
|
+
[this.apiKeyHeader]: this.apiKey,
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
Host: this.host,
|
|
119
|
+
},
|
|
120
|
+
data,
|
|
121
|
+
}));
|
|
122
|
+
log("Archibus:CreateRequest", "Response", response.data, logId);
|
|
123
|
+
|
|
124
|
+
// Save the ID to external entities for future reference
|
|
125
|
+
await updateRef("externalentities", {
|
|
126
|
+
RowId: `${this.getEntityType()}_${response.data.wrId}`,
|
|
127
|
+
LastUpdated: moment().valueOf(),
|
|
128
|
+
EntityType: this.getEntityType(),
|
|
129
|
+
ActiveEntityType: this.getEntityType(),
|
|
130
|
+
InternalId: request.id,
|
|
131
|
+
ExternalId: response.data.wrId,
|
|
132
|
+
TrackedData: {},
|
|
133
|
+
SystemType: "Archibus",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Save the Archibus ID as the job number and add history entry
|
|
137
|
+
const updatedJob = await getRef(
|
|
138
|
+
values.tableNameMaintenance,
|
|
139
|
+
"id",
|
|
140
|
+
request.id,
|
|
141
|
+
);
|
|
142
|
+
if (!updatedJob.history) updatedJob.history = [];
|
|
143
|
+
updatedJob.history.push({
|
|
144
|
+
timestamp: moment.utc().valueOf(),
|
|
145
|
+
EntryType: "ExternalIDSet",
|
|
146
|
+
externalId: response.data.wrId,
|
|
147
|
+
user: {
|
|
148
|
+
displayName: "Archibus Integration",
|
|
149
|
+
id: "system",
|
|
150
|
+
},
|
|
151
|
+
systemType: "Archibus",
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await editRef(values.tableNameMaintenance, "id", request.id, {
|
|
155
|
+
jobNo: response.data.wrId,
|
|
156
|
+
jobId: response.data.wrId + "",
|
|
157
|
+
history: updatedJob.history,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
// add images
|
|
161
|
+
if (!mockResponse && !_.isEmpty(request.images)) {
|
|
162
|
+
const imagePromises = [];
|
|
163
|
+
request.images.forEach((url) => {
|
|
164
|
+
imagePromises.push(this.addFileToRequest(response.data.wrId, url));
|
|
165
|
+
});
|
|
166
|
+
await Promise.all(imagePromises);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return true;
|
|
170
|
+
} catch (e) {
|
|
171
|
+
log("Archibus:CreateRequest", "Error", e, logId);
|
|
172
|
+
|
|
173
|
+
// Add history entry for failed integration
|
|
174
|
+
try {
|
|
175
|
+
const failedJob = await getRef(
|
|
176
|
+
values.tableNameMaintenance,
|
|
177
|
+
"id",
|
|
178
|
+
request.id,
|
|
179
|
+
);
|
|
180
|
+
if (!failedJob.history) failedJob.history = [];
|
|
181
|
+
failedJob.history.push({
|
|
182
|
+
timestamp: moment.utc().valueOf(),
|
|
183
|
+
EntryType: "ExternalIDSetFailed",
|
|
184
|
+
user: {
|
|
185
|
+
displayName: "Archibus Integration",
|
|
186
|
+
id: "system",
|
|
187
|
+
},
|
|
188
|
+
systemType: "Archibus",
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
await editRef(values.tableNameMaintenance, "id", request.id, {
|
|
192
|
+
history: failedJob.history,
|
|
193
|
+
});
|
|
194
|
+
} catch (historyError) {
|
|
195
|
+
log("Archibus:CreateRequest", "HistoryError", historyError, logId);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return false;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Fetches a request from the Archibus system
|
|
203
|
+
*
|
|
204
|
+
* @param {String} externalId - Id of the request on the Archibus
|
|
205
|
+
* @returns {Object} The request as it exists on Archibus
|
|
206
|
+
*/
|
|
207
|
+
getRequest = async (externalId) => {
|
|
208
|
+
const logId = log("Archibus:GetRequest", "Start", externalId);
|
|
209
|
+
try {
|
|
210
|
+
const response = await axios({
|
|
211
|
+
method: "GET",
|
|
212
|
+
url: `${this.baseUrl}/getWorkRequest/${externalId}`,
|
|
213
|
+
timeout: 30000,
|
|
214
|
+
headers: {
|
|
215
|
+
[this.apiKeyHeader]: this.apiKey,
|
|
216
|
+
"Content-Type": "application/json",
|
|
217
|
+
Host: this.host,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
log("Archibus:GetRequest", "Response", response.data, logId);
|
|
221
|
+
|
|
222
|
+
return response.data;
|
|
223
|
+
} catch (e) {
|
|
224
|
+
log("Archibus:GetRequest", "Error", e, logId);
|
|
225
|
+
}
|
|
226
|
+
return null;
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Refreshes a request from the Archibus system
|
|
231
|
+
*
|
|
232
|
+
* @param {String} requestId - Id of the request on Pluss.
|
|
233
|
+
* @param {String} externalId - Id of the request on Archibus.
|
|
234
|
+
* @param {Object} trackedData - The set of fields tracked.
|
|
235
|
+
* @returns {Boolean} Whether the request had any changes on Archibus.
|
|
236
|
+
*/
|
|
237
|
+
refreshFromSource = async (requestId, externalId, trackedData) => {
|
|
238
|
+
const logId = log("Archibus:RefreshFromSource", "Start", {
|
|
239
|
+
requestId,
|
|
240
|
+
externalId,
|
|
241
|
+
trackedData,
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Skip API calls overnight (8pm–6am Sydney time)
|
|
245
|
+
const sydneyNow = new Date(
|
|
246
|
+
new Date().toLocaleString("en-US", { timeZone: "Australia/Sydney" }),
|
|
247
|
+
);
|
|
248
|
+
const sydneyHour = sydneyNow.getHours();
|
|
249
|
+
if (sydneyHour >= 20 || sydneyHour < 6) {
|
|
250
|
+
log(
|
|
251
|
+
"Archibus:RefreshFromSource",
|
|
252
|
+
"SkippedOvernight",
|
|
253
|
+
{ sydneyHour },
|
|
254
|
+
logId,
|
|
255
|
+
);
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// If the external status is terminal, remove ActiveEntityType to exclude from sparse GSI
|
|
260
|
+
if (this.completedStatuses.includes(trackedData.status)) {
|
|
261
|
+
log(
|
|
262
|
+
"Archibus:RefreshFromSource",
|
|
263
|
+
"TerminalStatus",
|
|
264
|
+
trackedData.status,
|
|
265
|
+
logId,
|
|
266
|
+
);
|
|
267
|
+
const entityRowId = `${this.getEntityType()}_${externalId}`;
|
|
268
|
+
const entity = await getRef("externalentities", "RowId", entityRowId);
|
|
269
|
+
if (entity?.ActiveEntityType) {
|
|
270
|
+
delete entity.ActiveEntityType;
|
|
271
|
+
await updateRef("externalentities", entity);
|
|
272
|
+
}
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const request = await this.getRequest(externalId);
|
|
277
|
+
if (!request) {
|
|
278
|
+
log("Archibus:RefreshFromSource", "Result:NoResponse", false, logId);
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
if (trackedData && trackedData.status === request.status) {
|
|
283
|
+
log("Archibus:RefreshFromSource", "Result:UnchangedStatus", false, logId);
|
|
284
|
+
// status has not changed
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const statusToUse = this.statusMap[request.status];
|
|
289
|
+
log("Archibus:RefreshFromSource", "UpdatedStatus", statusToUse, logId);
|
|
290
|
+
|
|
291
|
+
if (statusToUse) {
|
|
292
|
+
let plussRequest = await getRef(
|
|
293
|
+
values.tableNameMaintenance,
|
|
294
|
+
"id",
|
|
295
|
+
requestId,
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
if (!plussRequest) {
|
|
299
|
+
log(
|
|
300
|
+
"Archibus:RefreshFromSource",
|
|
301
|
+
"RequestDeletedLocally",
|
|
302
|
+
requestId,
|
|
303
|
+
logId,
|
|
304
|
+
);
|
|
305
|
+
const entityRowId = `${this.getEntityType()}_${externalId}`;
|
|
306
|
+
const entity = await getRef("externalentities", "RowId", entityRowId);
|
|
307
|
+
if (entity?.ActiveEntityType) {
|
|
308
|
+
delete entity.ActiveEntityType;
|
|
309
|
+
await updateRef("externalentities", entity);
|
|
310
|
+
}
|
|
311
|
+
} else if (statusToUse.Status !== plussRequest?.status) {
|
|
312
|
+
// save updated status
|
|
313
|
+
|
|
314
|
+
plussRequest = await editRef(
|
|
315
|
+
values.tableNameMaintenance,
|
|
316
|
+
"id",
|
|
317
|
+
requestId,
|
|
318
|
+
{
|
|
319
|
+
status: statusToUse.Status,
|
|
320
|
+
},
|
|
321
|
+
);
|
|
322
|
+
log(
|
|
323
|
+
"Archibus:RefreshFromSource",
|
|
324
|
+
"SavedStatus",
|
|
325
|
+
statusToUse.Status,
|
|
326
|
+
logId,
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
if (statusToUse.Notification) {
|
|
330
|
+
publishNotifications(
|
|
331
|
+
[plussRequest.userID],
|
|
332
|
+
values.activityMaintenanceJobStatusChanged,
|
|
333
|
+
plussRequest.site,
|
|
334
|
+
plussRequest.id,
|
|
335
|
+
plussRequest,
|
|
336
|
+
true,
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// save tracked data
|
|
343
|
+
await editRef(
|
|
344
|
+
"externalentities",
|
|
345
|
+
"RowId",
|
|
346
|
+
`${this.getEntityType()}_${externalId}`,
|
|
347
|
+
{
|
|
348
|
+
TrackedData: {
|
|
349
|
+
status: request.status,
|
|
350
|
+
},
|
|
351
|
+
},
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
log("Archibus:RefreshFromSource", "Result", true, logId);
|
|
355
|
+
return true;
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Adds a comment to a request in Archibus
|
|
360
|
+
*
|
|
361
|
+
* @param {Number} externalId - Id of the request on Archibus.
|
|
362
|
+
* @param {String} comment - Text to add to Archibus request.
|
|
363
|
+
* @param {moment.Moment} time - The time to save against the comment
|
|
364
|
+
*/
|
|
365
|
+
addCommentToRequest = async (externalId, comment, time) => {
|
|
366
|
+
const logId = log("Archibus:AddComment", "Start", {
|
|
367
|
+
externalId,
|
|
368
|
+
comment,
|
|
369
|
+
time,
|
|
370
|
+
});
|
|
371
|
+
try {
|
|
372
|
+
// Format the time
|
|
373
|
+
const timeToUse = (time || moment()).format("YYYY-MM-DD hh:mm:ss");
|
|
374
|
+
|
|
375
|
+
// Generate the POST data
|
|
376
|
+
const postData = {
|
|
377
|
+
actionTime: timeToUse,
|
|
378
|
+
comments: comment,
|
|
379
|
+
wr_id: externalId,
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
log("Archibus:AddComment", "PostData", postData, logId);
|
|
383
|
+
|
|
384
|
+
// Save to Archibus
|
|
385
|
+
const response = await axios({
|
|
386
|
+
method: "POST",
|
|
387
|
+
url: `${this.baseUrl}/addCommentsToWRSteps`,
|
|
388
|
+
data: postData,
|
|
389
|
+
timeout: 30000,
|
|
390
|
+
headers: {
|
|
391
|
+
[this.apiKeyHeader]: this.apiKey,
|
|
392
|
+
"Content-Type": "application/json",
|
|
393
|
+
Host: this.host,
|
|
394
|
+
},
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
log("Archibus:AddComment", "ResponseStatus", response.status, logId);
|
|
398
|
+
|
|
399
|
+
return response;
|
|
400
|
+
} catch (error) {
|
|
401
|
+
log("Archibus:AddComment", "Error", error, logId);
|
|
402
|
+
}
|
|
403
|
+
return false;
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Adds a file to a request in Archibus
|
|
408
|
+
*
|
|
409
|
+
* @param {Number} externalId - Id of the request on Archibus.
|
|
410
|
+
* @param {String} fileUrl - URL of the file to attach
|
|
411
|
+
* @param {moment.Moment} time - The time to save against the file
|
|
412
|
+
* @returns
|
|
413
|
+
*/
|
|
414
|
+
addFileToRequest = async (externalId, fileUrl, time) => {
|
|
415
|
+
const logId = log("Archibus:AddFile", "Start", {
|
|
416
|
+
externalId,
|
|
417
|
+
fileUrl,
|
|
418
|
+
time,
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// This endpoint is not currently functional. Instead, use the addCommentToRequest method to add a comment with the file URL.
|
|
422
|
+
// return this.addCommentToRequest(externalId, fileUrl, time);
|
|
423
|
+
|
|
424
|
+
try {
|
|
425
|
+
// Download the file content from the URL
|
|
426
|
+
const fileResponse = await axios.get(fileUrl, {
|
|
427
|
+
responseType: "arraybuffer",
|
|
428
|
+
});
|
|
429
|
+
log("Archibus:AddFile", "GotFileResponse", fileResponse.status, logId);
|
|
430
|
+
|
|
431
|
+
// Encode the file content in base64
|
|
432
|
+
const fileContentBase64 = encode(fileResponse.data);
|
|
433
|
+
log("Archibus:AddFile", "EncodedFileResponse", true, logId);
|
|
434
|
+
|
|
435
|
+
// Extract file name from the URL
|
|
436
|
+
const fileName = fileUrl.split("/").pop();
|
|
437
|
+
|
|
438
|
+
// Format the time
|
|
439
|
+
const timeToUse = (time || moment()).format("YYYY-MM-DD hh:mm:ss");
|
|
440
|
+
|
|
441
|
+
// Generate the POST data
|
|
442
|
+
const postData = {
|
|
443
|
+
actionTime: timeToUse,
|
|
444
|
+
docName: fileName,
|
|
445
|
+
docUrl: "https://anglicare.plusscommunities.com/",
|
|
446
|
+
fileContent: fileContentBase64,
|
|
447
|
+
fileName: fileName,
|
|
448
|
+
wrId: externalId,
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
log("Archibus:AddFile", "PostData", postData, logId);
|
|
452
|
+
|
|
453
|
+
// Save to Archibus
|
|
454
|
+
const response = await axios({
|
|
455
|
+
method: "POST",
|
|
456
|
+
url: `${this.baseUrl}/addDocumentToWorkRequest`,
|
|
457
|
+
data: postData,
|
|
458
|
+
timeout: 60000,
|
|
459
|
+
headers: {
|
|
460
|
+
[this.apiKeyHeader]: this.apiKey,
|
|
461
|
+
"Content-Type": "application/json",
|
|
462
|
+
Host: this.host,
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
log("Archibus:AddFile", "ResponseStatus", response.status, logId);
|
|
467
|
+
|
|
468
|
+
return response;
|
|
469
|
+
} catch (error) {
|
|
470
|
+
log("Archibus:AddFile", "Error", error, logId);
|
|
471
|
+
}
|
|
472
|
+
return false;
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Get Archibus Id of the request
|
|
477
|
+
*
|
|
478
|
+
* @param {Object} request - Request definition on Pluss
|
|
479
|
+
* @returns {Number} Id of the request on Archibus (null if not exists)
|
|
480
|
+
*/
|
|
481
|
+
getExternalId = async (request) => {
|
|
482
|
+
const logId = log("Archibus:GetExternalId", "Start", { Id: request.id });
|
|
483
|
+
|
|
484
|
+
// get external id
|
|
485
|
+
const externalEntityQuery = await indexQuery("externalentities", {
|
|
486
|
+
IndexName: "InternalIdIndex",
|
|
487
|
+
KeyConditionExpression:
|
|
488
|
+
"EntityType = :entityType AND InternalId = :internalId",
|
|
489
|
+
ExpressionAttributeValues: {
|
|
490
|
+
":entityType": this.getEntityType(),
|
|
491
|
+
":internalId": request.id,
|
|
492
|
+
},
|
|
493
|
+
});
|
|
494
|
+
|
|
495
|
+
log(
|
|
496
|
+
"Archibus:GetExternalId",
|
|
497
|
+
"ExternalLength",
|
|
498
|
+
externalEntityQuery.Items.length,
|
|
499
|
+
logId,
|
|
500
|
+
);
|
|
501
|
+
if (_.isEmpty(externalEntityQuery.Items)) {
|
|
502
|
+
return null;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
const externalId = externalEntityQuery.Items[0].ExternalId;
|
|
506
|
+
log("Archibus:GetExternalId", "ExternalId", externalId, logId);
|
|
507
|
+
|
|
508
|
+
return externalId;
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Get latest comment for a request
|
|
513
|
+
*
|
|
514
|
+
* @param {Object} request - Request definition on Pluss
|
|
515
|
+
* @param {String} entityKey - Request entity key (e.g. maintenancerequest)
|
|
516
|
+
* @returns {Object} Latest comment (null if not exists)
|
|
517
|
+
*/
|
|
518
|
+
getLatestComment = async (request, entityKey) => {
|
|
519
|
+
const logId = log("Archibus:GetLatestComment", "Start", { Id: request.id });
|
|
520
|
+
|
|
521
|
+
// get comments
|
|
522
|
+
const commentsQuery = {
|
|
523
|
+
IndexName: "CommentsEntityIdIndex",
|
|
524
|
+
KeyConditionExpression: "EntityId = :groupId",
|
|
525
|
+
ExpressionAttributeValues: {
|
|
526
|
+
":groupId": getRowId(request.id, entityKey),
|
|
527
|
+
},
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
const commentsQueryRes = await indexQuery("comments", commentsQuery);
|
|
531
|
+
const comments = _.orderBy(commentsQueryRes.Items, "Timestamp", "desc");
|
|
532
|
+
log(
|
|
533
|
+
"Archibus:GetLatestComment",
|
|
534
|
+
`CommentsLength - ${entityKey}`,
|
|
535
|
+
comments.length,
|
|
536
|
+
logId,
|
|
537
|
+
);
|
|
538
|
+
|
|
539
|
+
return comments.length > 0 ? comments[0] : null;
|
|
540
|
+
};
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Perform actions when a task's status has changed
|
|
544
|
+
*
|
|
545
|
+
* @param {Object} request - Request definition on Pluss
|
|
546
|
+
* @returns {Boolean} Represents whether the actions were successful
|
|
547
|
+
*/
|
|
548
|
+
onStatusChanged = async (request) => {
|
|
549
|
+
const logId = log("Archibus:OnStatusChanged", "Start", { Id: request.id });
|
|
550
|
+
|
|
551
|
+
try {
|
|
552
|
+
const externalId = await this.getExternalId(request);
|
|
553
|
+
if (_.isNil(externalId)) return true;
|
|
554
|
+
|
|
555
|
+
const statues = _.orderBy(
|
|
556
|
+
(request.history ?? []).filter(
|
|
557
|
+
(entry) => entry.EntryType !== "assignment",
|
|
558
|
+
),
|
|
559
|
+
"timestamp",
|
|
560
|
+
"desc",
|
|
561
|
+
);
|
|
562
|
+
const latest = statues.length > 0 ? statues[0] : null;
|
|
563
|
+
|
|
564
|
+
if (latest) {
|
|
565
|
+
const time = moment(Number.parseFloat(latest.timestamp + "")).format(
|
|
566
|
+
"D MMM YYYY HH:mm:ss",
|
|
567
|
+
);
|
|
568
|
+
const user = latest.user ? ` by ${latest.user.displayName}` : "";
|
|
569
|
+
const comment = `${time}: Marked ${latest.status}${user}`;
|
|
570
|
+
await this.addCommentToRequest(externalId, comment);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return true;
|
|
574
|
+
} catch (error) {
|
|
575
|
+
log("Archibus:OnStatusChanged", "Error", error.toString(), logId);
|
|
576
|
+
}
|
|
577
|
+
return false;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Perform actions when a a comment has been added to a task
|
|
582
|
+
*
|
|
583
|
+
* @param {Object} request - Request definition on Pluss
|
|
584
|
+
* @returns {Boolean} Represents whether the actions were successful
|
|
585
|
+
*/
|
|
586
|
+
onCommentAdded = async (request) => {
|
|
587
|
+
const logId = log("Archibus:OnCommentAdded", "Start", {
|
|
588
|
+
Id: request.id,
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
try {
|
|
592
|
+
const externalId = await this.getExternalId(request);
|
|
593
|
+
if (_.isNil(externalId)) return true;
|
|
594
|
+
|
|
595
|
+
let comment = await this.getLatestComment(request, values.serviceKey);
|
|
596
|
+
if (!comment)
|
|
597
|
+
comment = await this.getLatestComment(request, values.entityKey);
|
|
598
|
+
|
|
599
|
+
if (comment) {
|
|
600
|
+
const commentText = `${comment.User.displayName}:\n\n${
|
|
601
|
+
comment.Comment
|
|
602
|
+
}${!_.isEmpty(comment.Image) ? `\n\nImage: ${comment.Image}` : ""}}`;
|
|
603
|
+
const commentTime = moment(comment.Timestamp);
|
|
604
|
+
await this.addCommentToRequest(externalId, commentText, commentTime);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return true;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
log("Archibus:OnCommentAdded", "Error", error.toString(), logId);
|
|
610
|
+
}
|
|
611
|
+
return false;
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Perform actions when a note has been added to a task
|
|
616
|
+
*
|
|
617
|
+
* @param {Object} request - Request definition on Pluss
|
|
618
|
+
* @returns {Boolean} Represents whether the actions were successful
|
|
619
|
+
*/
|
|
620
|
+
onNotesAdded = async (request) => {
|
|
621
|
+
const logId = log("Archibus:OnNotesAdded", "Start", { Id: request.id });
|
|
622
|
+
|
|
623
|
+
try {
|
|
624
|
+
const externalId = await this.getExternalId(request);
|
|
625
|
+
if (_.isNil(externalId)) return true;
|
|
626
|
+
|
|
627
|
+
const notes = _.orderBy(request.Notes ?? [], "Timestamp", "desc");
|
|
628
|
+
const latest = notes.length > 0 ? notes[0] : null;
|
|
629
|
+
|
|
630
|
+
if (latest) {
|
|
631
|
+
const promises = [];
|
|
632
|
+
|
|
633
|
+
const time = moment(Number.parseFloat(latest.Timestamp + "")).format(
|
|
634
|
+
"YYYY-MM-DD HH:mm:ss",
|
|
635
|
+
);
|
|
636
|
+
const user = latest.User ? latest.User.displayName : "Unknown User";
|
|
637
|
+
const note = latest.Note ? `Note: ${latest.Note}` : "No Note";
|
|
638
|
+
if (!_.isEmpty(latest.Attachments)) {
|
|
639
|
+
latest.Attachments.forEach((att) => {
|
|
640
|
+
promises.push(this.addFileToRequest(externalId, att.Source));
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
const attachments =
|
|
644
|
+
latest.Attachments && latest.Attachments.length > 0
|
|
645
|
+
? `Attachments: ${latest.Attachments.map(
|
|
646
|
+
(att) => `${att.Title} (${att.Source})`,
|
|
647
|
+
).join(", ")}`
|
|
648
|
+
: "No Attachments";
|
|
649
|
+
if (!_.isEmpty(latest.Images)) {
|
|
650
|
+
latest.Images.forEach((image) => {
|
|
651
|
+
promises.push(this.addFileToRequest(externalId, image));
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
const images =
|
|
655
|
+
latest.Images && latest.Images.length > 0
|
|
656
|
+
? `Images: ${latest.Images.map((image) => image).join(", ")}`
|
|
657
|
+
: "No Images";
|
|
658
|
+
const comment = `${time} by ${user}\n${note}\n${attachments}\n${images}`;
|
|
659
|
+
promises.push(this.addCommentToRequest(externalId, comment));
|
|
660
|
+
|
|
661
|
+
await Promise.all(promises);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return true;
|
|
665
|
+
} catch (error) {
|
|
666
|
+
log("Archibus:OnNotesAdded", "Error", error.toString(), logId);
|
|
667
|
+
}
|
|
668
|
+
return false;
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Perform completion actions when a task is completed
|
|
673
|
+
*
|
|
674
|
+
* @param {Object} request - Request definition on Pluss
|
|
675
|
+
* @returns {Boolean} Represents whether the actions were successful
|
|
676
|
+
*/
|
|
677
|
+
onCompleteRequest = async (request) => {
|
|
678
|
+
return true;
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
// TODO: Remove once all existing records have ActiveEntityType (PC-1382)
|
|
682
|
+
// Backfills ActiveEntityType on existing externalentities records for the sparse GSI migration.
|
|
683
|
+
// Runs as part of the cron job after normal processing, respecting the given timeout.
|
|
684
|
+
backfillActiveEntityType = async (timeout) => {
|
|
685
|
+
const logId = log("Archibus:Backfill", "Start", true);
|
|
686
|
+
const startTime = moment().valueOf();
|
|
687
|
+
let backfillCount = 0;
|
|
688
|
+
let lastEvaluatedKey = null;
|
|
689
|
+
|
|
690
|
+
do {
|
|
691
|
+
const query = {
|
|
692
|
+
IndexName: "EntityTypeIndex",
|
|
693
|
+
KeyConditionExpression: "EntityType = :entityType",
|
|
694
|
+
ExpressionAttributeValues: {
|
|
695
|
+
":entityType": this.getEntityType(),
|
|
696
|
+
},
|
|
697
|
+
Limit: 25,
|
|
698
|
+
};
|
|
699
|
+
if (lastEvaluatedKey) query.ExclusiveStartKey = lastEvaluatedKey;
|
|
700
|
+
|
|
701
|
+
const result = await indexQuery("externalentities", query);
|
|
702
|
+
lastEvaluatedKey = result.LastEvaluatedKey;
|
|
703
|
+
|
|
704
|
+
for (const item of result.Items) {
|
|
705
|
+
if (!item.ActiveEntityType) {
|
|
706
|
+
// Skip records already in a terminal status — they should stay out of the sparse GSI
|
|
707
|
+
const trackedStatus = item.TrackedData && item.TrackedData.status;
|
|
708
|
+
if (trackedStatus && this.completedStatuses.includes(trackedStatus)) {
|
|
709
|
+
continue;
|
|
710
|
+
}
|
|
711
|
+
item.ActiveEntityType = item.EntityType;
|
|
712
|
+
await updateRef("externalentities", item);
|
|
713
|
+
backfillCount++;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
} while (lastEvaluatedKey && moment().valueOf() < startTime + timeout);
|
|
717
|
+
|
|
718
|
+
const complete = !lastEvaluatedKey;
|
|
719
|
+
log("Archibus:Backfill", "End", { backfillCount, complete }, logId);
|
|
720
|
+
return { backfillCount, complete };
|
|
721
|
+
};
|
|
623
722
|
}
|
|
624
723
|
|
|
625
724
|
module.exports = ArchibusStrategy;
|