@getjones/test-infra 5.3.1 → 5.3.3
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/package.json +1 -1
- package/src/common/commonFlows/records/records.js +49 -2
- package/src/common/consts/accountSettings.js +0 -4
- package/src/common/consts/projectSettings.js +7 -0
- package/src/index.js +0 -2
- package/src/saas/internal-api/accountDirectory/api/accountDirectory.service.js +3 -9
- package/src/saas/internal-api/accountDirectory/models/accountDirectory.models.js +1 -3
- package/src/saas/internal-api/accounts/models/settings/update.settings.model.js +1 -3
- package/src/saas/internal-api/agreement/api/agreement.service.js +3 -3
- package/src/saas/internal-api/coi/consts/uploaderTypes.js +1 -1
- package/src/saas/internal-api/coi/index.js +0 -1
- package/src/saas/internal-api/coi/utils/utils.js +10 -11
- package/src/saas/internal-api/compliance/api/overrideGap/override.gap.api.js +25 -2
- package/src/saas/internal-api/compliance/api/overrideGap/override.gap.service.js +93 -2
- package/src/saas/internal-api/compliance/consts/overrideGapRequest/override.gap.request.js +6 -1
- package/src/saas/internal-api/compliance/models/overrideGapRequest/override.gap.request.model.js +16 -1
- package/src/saas/internal-api/dbEmails/consts/consts.js +5 -10
- package/src/saas/internal-api/dbEmails/utils/util.js +5 -0
- package/src/saas/internal-api/notificationCenter/consts.js +4 -1
- package/src/saas/internal-api/projects/models/settings/update.project.settings.model.js +8 -0
- package/src/saas/internal-api/thread-scheduler/runner.js +0 -3
- package/src/saas/internal-api/thread-scheduler/schedulerJobs.js +0 -1
- package/src/saas/internal-api/coi/consts/coiUploaderTypes.js +0 -9
- package/src/saas/internal-api/weeklyDigest/api/weekly.digest.api.js +0 -32
- package/src/saas/internal-api/weeklyDigest/api/weekly.digest.service.js +0 -69
- package/src/saas/internal-api/weeklyDigest/consts/weekly.digest.consts.js +0 -21
- package/src/saas/internal-api/weeklyDigest/index.js +0 -4
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@ const coi = require('../../../saas/internal-api/coi');
|
|
|
14
14
|
const usersAPI = require('../../../saas/internal-api/users/index');
|
|
15
15
|
const auth = require('../../../saas/internal-api/auth/index');
|
|
16
16
|
const accounts = require('../../../saas/internal-api/accounts');
|
|
17
|
+
const { getIcsCookie } = require('../../../saas/internal-api/auth/api/auth.service');
|
|
17
18
|
const activationStatuses = require('../../../common/consts/activationStatuses');
|
|
18
19
|
const recordTypes = require('../../../common/consts/recordTypes');
|
|
19
20
|
const policyNames = require('../../../defaults/index').polices;
|
|
@@ -327,6 +328,45 @@ const rejectOverrideGapRequest = async (overrideGapRequestId, rejectReason, reco
|
|
|
327
328
|
return compliance.services.overrideGap.rejectOverrideGapRequest(overrideGapRequestId, rejectReason, record.dateModified, context);
|
|
328
329
|
};
|
|
329
330
|
|
|
331
|
+
const createPmOverrideRequest = async (recordId, policyName, attributeName, assigneeUserIds, context, {
|
|
332
|
+
requestReason = 'PM override request reason for integration tests exceeding minimum length of 35 characters.',
|
|
333
|
+
expiryType = EXPIRY_TYPES.NEVER,
|
|
334
|
+
expiryDate = null,
|
|
335
|
+
expectError
|
|
336
|
+
} = {}) => {
|
|
337
|
+
const { data: record } = await contractors.services.getContractorById(recordId, context);
|
|
338
|
+
const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
|
|
339
|
+
return compliance.services.overrideGap.createPmOverrideRequest(auditorContractorId, context, {
|
|
340
|
+
requestReason,
|
|
341
|
+
expiryType,
|
|
342
|
+
expiryDate,
|
|
343
|
+
assigneeUserIds,
|
|
344
|
+
recordDateModified: record.dateModified,
|
|
345
|
+
expectError
|
|
346
|
+
});
|
|
347
|
+
};
|
|
348
|
+
|
|
349
|
+
const editPmOverrideRequest = async (overrideGapRequestId, recordId, context, {
|
|
350
|
+
requestReason,
|
|
351
|
+
expiryType,
|
|
352
|
+
expiryDate = null,
|
|
353
|
+
assigneeUserIds,
|
|
354
|
+
expectError
|
|
355
|
+
} = {}) => {
|
|
356
|
+
const { data: record } = await contractors.services.getContractorById(recordId, context);
|
|
357
|
+
return compliance.services.overrideGap.editPmOverrideRequest(overrideGapRequestId, context, {
|
|
358
|
+
requestReason,
|
|
359
|
+
expiryType,
|
|
360
|
+
expiryDate,
|
|
361
|
+
assigneeUserIds,
|
|
362
|
+
recordDateModified: record.dateModified,
|
|
363
|
+
expectError
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
|
|
367
|
+
const deletePmOverrideRequest = (overrideGapRequestId, context, { expectError } = {}) =>
|
|
368
|
+
compliance.services.overrideGap.deletePmOverrideRequest(overrideGapRequestId, context, { expectError });
|
|
369
|
+
|
|
330
370
|
const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, uploaderEmail, context, { uploaderContext, duplicateHandling } = {}) => {
|
|
331
371
|
const recordResponse = await contractors.services.getContractorById(recordId, context);
|
|
332
372
|
const recordDateModified = recordResponse.data.dateModified;
|
|
@@ -336,12 +376,16 @@ const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, upload
|
|
|
336
376
|
fileIds.push(await coi.utils.uploadFileToStorage(recordId, filePath));
|
|
337
377
|
}
|
|
338
378
|
|
|
379
|
+
if (!uploaderContext) {
|
|
380
|
+
uploaderContext = await getIcsCookie();
|
|
381
|
+
}
|
|
382
|
+
|
|
339
383
|
const submitResponse = fileIds && await coi.utils.submitCoiFilesUpload({
|
|
340
384
|
recordId,
|
|
341
385
|
fileIds,
|
|
342
|
-
uploadedBy,
|
|
386
|
+
uploadedBy, // If provided, uploaderContext will be ignored
|
|
343
387
|
uploaderEmail,
|
|
344
|
-
uploaderContext,
|
|
388
|
+
uploaderContext, // Can be used instead of uploadedBy + uploaderEmail
|
|
345
389
|
recordDateModified,
|
|
346
390
|
duplicateHandling
|
|
347
391
|
});
|
|
@@ -442,6 +486,9 @@ module.exports = {
|
|
|
442
486
|
getActiveOverrides,
|
|
443
487
|
createOverrideGapRequest,
|
|
444
488
|
rejectOverrideGapRequest,
|
|
489
|
+
createPmOverrideRequest,
|
|
490
|
+
editPmOverrideRequest,
|
|
491
|
+
deletePmOverrideRequest,
|
|
445
492
|
uploadMultipleCoiFiles,
|
|
446
493
|
createTenantUser,
|
|
447
494
|
deleteRecordByName,
|
|
@@ -7,10 +7,6 @@ module.exports = {
|
|
|
7
7
|
on: { isAccountRequirementsEnabled: true },
|
|
8
8
|
off: { isAccountRequirementsEnabled: false }
|
|
9
9
|
},
|
|
10
|
-
isWeeklyDigestEnabled: {
|
|
11
|
-
on: { isWeeklyDigestEnabled: true },
|
|
12
|
-
off: { isWeeklyDigestEnabled: false }
|
|
13
|
-
},
|
|
14
10
|
isPolicyVerificationEnabled: {
|
|
15
11
|
on: { hasPolicyVerification: true },
|
|
16
12
|
off: { hasPolicyVerification: false }
|
|
@@ -21,6 +21,13 @@ module.exports = {
|
|
|
21
21
|
onForTenants: { overrideGapRequestSettings: { isOverrideGapRequestEnabledForVendors: false, isOverrideGapRequestEnabledForTenants: true, isOverrideGapRequestEnabledForGuests: false } },
|
|
22
22
|
onForGuests: { overrideGapRequestSettings: { isOverrideGapRequestEnabledForVendors: false, isOverrideGapRequestEnabledForTenants: false, isOverrideGapRequestEnabledForGuests: true } }
|
|
23
23
|
},
|
|
24
|
+
userOverrideRequest: {
|
|
25
|
+
onForAll: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: true, isUserOverrideRequestEnabledForTenants: true, isUserOverrideRequestEnabledForGuests: true } },
|
|
26
|
+
offForAll: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: false } },
|
|
27
|
+
onForVendors: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: true, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: false } },
|
|
28
|
+
onForTenants: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: true, isUserOverrideRequestEnabledForGuests: false } },
|
|
29
|
+
onForGuests: { userOverrideRequestSettings: { isUserOverrideRequestEnabledForVendors: false, isUserOverrideRequestEnabledForTenants: false, isUserOverrideRequestEnabledForGuests: true } }
|
|
30
|
+
},
|
|
24
31
|
onboardingPhase: {
|
|
25
32
|
on: { onboardingPhase: true },
|
|
26
33
|
off: { onboardingPhase: false }
|
package/src/index.js
CHANGED
|
@@ -48,7 +48,6 @@ const getInternalAPI = () => {
|
|
|
48
48
|
|
|
49
49
|
const threadScheduler = require('./saas/internal-api/thread-scheduler/runner');
|
|
50
50
|
const schedulerJobRun = require('./saas/internal-api/schedulerJobRun');
|
|
51
|
-
const weeklyDigest = require('./saas/internal-api/weeklyDigest');
|
|
52
51
|
const certificial = require('./saas/internal-api/certificial');
|
|
53
52
|
const dbEmails = require('./saas/internal-api/dbEmails/index');
|
|
54
53
|
const agreement = require('./saas/internal-api/agreement/index');
|
|
@@ -90,7 +89,6 @@ const getInternalAPI = () => {
|
|
|
90
89
|
sampleCoi,
|
|
91
90
|
threadScheduler,
|
|
92
91
|
schedulerJobRun,
|
|
93
|
-
weeklyDigest,
|
|
94
92
|
certificial,
|
|
95
93
|
dbEmails,
|
|
96
94
|
emailCustomization,
|
|
@@ -289,7 +289,6 @@ const getAllRecords = async (accountId, context, {
|
|
|
289
289
|
sortOrder,
|
|
290
290
|
pageNum,
|
|
291
291
|
rowsPerPage,
|
|
292
|
-
digestScope,
|
|
293
292
|
expectError
|
|
294
293
|
} = {}) => {
|
|
295
294
|
const model = new accountDirectoryModels.AllRecordsTableRequestModel({
|
|
@@ -305,8 +304,7 @@ const getAllRecords = async (accountId, context, {
|
|
|
305
304
|
sortBy,
|
|
306
305
|
sortOrder,
|
|
307
306
|
pageNum,
|
|
308
|
-
rowsPerPage
|
|
309
|
-
digestScope
|
|
307
|
+
rowsPerPage
|
|
310
308
|
});
|
|
311
309
|
|
|
312
310
|
const response = await accountDirectoryAPI.getAllRecords(model, context);
|
|
@@ -331,7 +329,6 @@ const selectAllRecords = async (accountId, context, {
|
|
|
331
329
|
selectedTagIds,
|
|
332
330
|
expiryDateFrom,
|
|
333
331
|
expiryDateTo,
|
|
334
|
-
digestScope,
|
|
335
332
|
expectError
|
|
336
333
|
} = {}) => {
|
|
337
334
|
const model = new accountDirectoryModels.AllRecordsTableRequestModel({
|
|
@@ -343,8 +340,7 @@ const selectAllRecords = async (accountId, context, {
|
|
|
343
340
|
selectedRequirementIds,
|
|
344
341
|
selectedTagIds,
|
|
345
342
|
expiryDateFrom,
|
|
346
|
-
expiryDateTo
|
|
347
|
-
digestScope
|
|
343
|
+
expiryDateTo
|
|
348
344
|
});
|
|
349
345
|
|
|
350
346
|
const response = await accountDirectoryAPI.selectAllRecords(model, context);
|
|
@@ -401,7 +397,6 @@ const exportAllRecords = async (accountId, context, {
|
|
|
401
397
|
expiryDateTo,
|
|
402
398
|
sortBy,
|
|
403
399
|
sortOrder,
|
|
404
|
-
digestScope,
|
|
405
400
|
expectError
|
|
406
401
|
} = {}) => {
|
|
407
402
|
const model = new accountDirectoryModels.AllRecordsTableRequestModel({
|
|
@@ -415,8 +410,7 @@ const exportAllRecords = async (accountId, context, {
|
|
|
415
410
|
expiryDateFrom,
|
|
416
411
|
expiryDateTo,
|
|
417
412
|
sortBy,
|
|
418
|
-
sortOrder
|
|
419
|
-
digestScope
|
|
413
|
+
sortOrder
|
|
420
414
|
});
|
|
421
415
|
|
|
422
416
|
const response = await accountDirectoryAPI.exportAllRecords(model, context);
|
|
@@ -80,8 +80,7 @@ class AllRecordsTableRequestModel {
|
|
|
80
80
|
sortBy = ALL_RECORDS_TABLE_SORT_BY.COMPANY_NAME,
|
|
81
81
|
sortOrder = 'ASC',
|
|
82
82
|
pageNum = 1,
|
|
83
|
-
rowsPerPage = ROWS_PER_PAGE.TEN
|
|
84
|
-
digestScope = undefined
|
|
83
|
+
rowsPerPage = ROWS_PER_PAGE.TEN
|
|
85
84
|
} = {}) {
|
|
86
85
|
this.accountId = accountId;
|
|
87
86
|
this.searchTerm = searchTerm;
|
|
@@ -96,7 +95,6 @@ class AllRecordsTableRequestModel {
|
|
|
96
95
|
this.sortOrder = sortOrder;
|
|
97
96
|
this.pageNum = pageNum;
|
|
98
97
|
this.rowsPerPage = rowsPerPage;
|
|
99
|
-
this.digestScope = digestScope;
|
|
100
98
|
}
|
|
101
99
|
}
|
|
102
100
|
|
|
@@ -33,7 +33,6 @@ class UpdateAccountSettingsModel {
|
|
|
33
33
|
inviteGapCadence = null,
|
|
34
34
|
isAcord25SplitExtractionEnabled = false,
|
|
35
35
|
isCertificialEnabled = false,
|
|
36
|
-
isWeeklyDigestEnabled = false,
|
|
37
36
|
sampleCoi = {}
|
|
38
37
|
} = {}
|
|
39
38
|
) {
|
|
@@ -65,7 +64,6 @@ class UpdateAccountSettingsModel {
|
|
|
65
64
|
this.isConfigurableRenewalCadenceEnabled = isConfigurableRenewalCadenceEnabled;
|
|
66
65
|
this.isAcord25SplitExtractionEnabled = isAcord25SplitExtractionEnabled;
|
|
67
66
|
this.isCertificialEnabled = isCertificialEnabled;
|
|
68
|
-
this.isWeeklyDigestEnabled = isWeeklyDigestEnabled;
|
|
69
67
|
this.gapsChat = { ... DEFAULT_GAPS_CHAT, ... gapsChat };
|
|
70
68
|
this.supportAutomation = { ... DEFAULT_SUPPORT_AUTOMATION, ... supportAutomation };
|
|
71
69
|
this.sampleCoi = { ... DEFAULT_SAMPLE_COI, ... sampleCoi };
|
|
@@ -99,7 +97,7 @@ const DEFAULT_GAPS_CHAT = {
|
|
|
99
97
|
const DEFAULT_SUPPORT_AUTOMATION = {
|
|
100
98
|
isSupportAutomationAutoReplyEnabled: false,
|
|
101
99
|
isSupportAutomationTiersClassificationEnabled: false,
|
|
102
|
-
isSupportAutomationNoActionNeededEnabled:
|
|
100
|
+
isSupportAutomationNoActionNeededEnabled: false,
|
|
103
101
|
isSupportAutomationStandardAutoUploadEnabled: true,
|
|
104
102
|
isSupportAutomationEnhancedAutoUploadEnabled: false
|
|
105
103
|
};
|
|
@@ -56,19 +56,19 @@ const uploadAgreementByPM = async (
|
|
|
56
56
|
context,
|
|
57
57
|
{ contractorDateModified } = {}
|
|
58
58
|
) => {
|
|
59
|
-
const { data: { preSignedUrl, fileName:
|
|
59
|
+
const { data: { preSignedUrl, fileName: fullFilePath } } = await getAgreementPreSignedUrl(recordId, context, { filePath });
|
|
60
60
|
|
|
61
61
|
const uploadResults = await uploadAgreementToTempBucket(preSignedUrl, filePath);
|
|
62
62
|
validateResponse(uploadResults, recordId);
|
|
63
63
|
|
|
64
|
-
const response = await uploadAgreementToS3(
|
|
64
|
+
const response = await uploadAgreementToS3(fullFilePath, recordId);
|
|
65
65
|
validateResponse(response, recordId);
|
|
66
66
|
|
|
67
67
|
const createAgreementModel = new CreateAgreementByPMModel({
|
|
68
68
|
contractorId: recordId,
|
|
69
69
|
contractorDateModified,
|
|
70
70
|
uploaderId,
|
|
71
|
-
signedContractName:
|
|
71
|
+
signedContractName: fullFilePath
|
|
72
72
|
});
|
|
73
73
|
|
|
74
74
|
const createResponse = await createAgreement(createAgreementModel, context);
|
|
@@ -9,7 +9,6 @@ const utils = require('./utils/utils');
|
|
|
9
9
|
|
|
10
10
|
const consts = {
|
|
11
11
|
UPLOADER_TYPES: require('./consts/uploaderTypes'),
|
|
12
|
-
COI_UPLOADER_TYPES: require('./consts/coiUploaderTypes'),
|
|
13
12
|
HASHES: require('./consts/hashes'),
|
|
14
13
|
DUPLICATE_HANDLING: require('./consts/duplicateHandling')
|
|
15
14
|
};
|
|
@@ -27,9 +27,6 @@ const submitCoiFilesUpload = async ({
|
|
|
27
27
|
recordDateModified,
|
|
28
28
|
duplicateHandling
|
|
29
29
|
}) => {
|
|
30
|
-
// ICS is the default uploader, so without a session it falls back to the ICS cookie; other types go out unauthenticated
|
|
31
|
-
const isUnauthenticatedUpload = !uploaderContext && uploadedBy !== UPLOADER_TYPES.ICS;
|
|
32
|
-
|
|
33
30
|
const submitCoiModel = new SubmitCoiModel({
|
|
34
31
|
recordId,
|
|
35
32
|
fileIds,
|
|
@@ -40,12 +37,11 @@ const submitCoiFilesUpload = async ({
|
|
|
40
37
|
duplicateHandling
|
|
41
38
|
});
|
|
42
39
|
|
|
43
|
-
if (
|
|
40
|
+
if (uploadedBy != UPLOADER_TYPES.ICS) { // Upload by user role
|
|
44
41
|
return services.submitCoi(submitCoiModel);
|
|
45
42
|
}
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
return services.submitCoiByUserContext(submitCoiModel, sessionContext);
|
|
44
|
+
return services.submitCoiByUserContext(submitCoiModel, uploaderContext); // Upload by user context
|
|
49
45
|
};
|
|
50
46
|
|
|
51
47
|
const uploadCoi = async (
|
|
@@ -54,13 +50,16 @@ const uploadCoi = async (
|
|
|
54
50
|
uploadedBy,
|
|
55
51
|
uploaderEmail,
|
|
56
52
|
{
|
|
57
|
-
markAsScaned,
|
|
53
|
+
markAsScaned, // Should be passed with context
|
|
58
54
|
uploaderContext,
|
|
59
55
|
duplicateHandling
|
|
60
56
|
} = {}
|
|
61
57
|
) => {
|
|
62
|
-
|
|
63
|
-
|
|
58
|
+
if (!uploaderContext) {
|
|
59
|
+
uploaderContext = await getIcsCookie();
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const recordResponse = await getContractorById(recordId, uploaderContext);
|
|
64
63
|
const recordDateModified = recordResponse.data.dateModified;
|
|
65
64
|
const fileId = await uploadFileToStorage(recordId, filePath);
|
|
66
65
|
|
|
@@ -76,8 +75,8 @@ const uploadCoi = async (
|
|
|
76
75
|
|
|
77
76
|
const uploadedCoi = !!submitResponse.data.fileName && { id: fileId, name: submitResponse.data.fileName };
|
|
78
77
|
|
|
79
|
-
if (uploadedCoi.name && markAsScaned) {
|
|
80
|
-
await fileScanService.completeCoiScan(recordId, uploadedCoi.name,
|
|
78
|
+
if (uploadedCoi.name && markAsScaned && uploaderContext) {
|
|
79
|
+
await fileScanService.completeCoiScan(recordId, uploadedCoi.name, uploaderContext);
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
return uploadedCoi;
|
|
@@ -13,7 +13,10 @@ const Endpoints = {
|
|
|
13
13
|
updateOverrideExpiryDate: auditorContractorId => `${backendUrl}/saas/integration-tests/override/${auditorContractorId}/expiry-date`,
|
|
14
14
|
getOverrideGapRequestById: overrideGapRequestId => `${backendUrl}/saas/gaps/override-gap-request/${overrideGapRequestId}`,
|
|
15
15
|
createOverrideGapRequest: `${backendUrl}/secured/vendor-app/record/override-gap-request`,
|
|
16
|
-
rejectOverrideGapRequest: `${backendUrl}/saas/gaps/override-gap-request/reject
|
|
16
|
+
rejectOverrideGapRequest: `${backendUrl}/saas/gaps/override-gap-request/reject`,
|
|
17
|
+
createPmOverrideRequest: `${backendUrl}/saas/gaps/override-gap-request`,
|
|
18
|
+
pmOverrideRequestById: overrideGapRequestId => `${backendUrl}/saas/gaps/override-gap-request/${overrideGapRequestId}`,
|
|
19
|
+
eligibleOverrideAssignees: requestId => `${backendUrl}/saas/gaps/override-gap-request/assignees/${requestId}`
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
const waive = async (contractorId, waiveRequestModel, context) => {
|
|
@@ -70,6 +73,22 @@ const rejectOverrideGapRequest = (rejectModel, context) => {
|
|
|
70
73
|
return requests.patchRequestHandler(Endpoints.rejectOverrideGapRequest, context, rejectModel);
|
|
71
74
|
};
|
|
72
75
|
|
|
76
|
+
const createPmOverrideRequest = (pmOverrideRequestModel, context) => {
|
|
77
|
+
return requests.postRequestHandler(Endpoints.createPmOverrideRequest, pmOverrideRequestModel, context);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const editPmOverrideRequest = (overrideGapRequestId, pmOverrideRequestModel, context) => {
|
|
81
|
+
return requests.patchRequestHandler(Endpoints.pmOverrideRequestById(overrideGapRequestId), context, pmOverrideRequestModel);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const deletePmOverrideRequest = (overrideGapRequestId, context) => {
|
|
85
|
+
return requests.deleteRequestHandler(Endpoints.pmOverrideRequestById(overrideGapRequestId), context);
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const getEligibleOverrideAssignees = (requestId, context) => {
|
|
89
|
+
return requests.getRequestHandler(Endpoints.eligibleOverrideAssignees(requestId), {}, context);
|
|
90
|
+
};
|
|
91
|
+
|
|
73
92
|
module.exports = {
|
|
74
93
|
waive,
|
|
75
94
|
retract,
|
|
@@ -82,5 +101,9 @@ module.exports = {
|
|
|
82
101
|
updateOverrideExpiryDate,
|
|
83
102
|
getOverrideGapRequestById,
|
|
84
103
|
createOverrideGapRequest,
|
|
85
|
-
rejectOverrideGapRequest
|
|
104
|
+
rejectOverrideGapRequest,
|
|
105
|
+
createPmOverrideRequest,
|
|
106
|
+
editPmOverrideRequest,
|
|
107
|
+
deletePmOverrideRequest,
|
|
108
|
+
getEligibleOverrideAssignees
|
|
86
109
|
};
|
|
@@ -10,7 +10,7 @@ const {
|
|
|
10
10
|
WAIVER_REASONS,
|
|
11
11
|
EXPIRY_TYPES
|
|
12
12
|
} = require('../../models/waive/waive.model');
|
|
13
|
-
const { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel } = require('../../models/overrideGapRequest/override.gap.request.model');
|
|
13
|
+
const { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel, PmOverrideRequestModel } = require('../../models/overrideGapRequest/override.gap.request.model');
|
|
14
14
|
const { validateType } = require('../../../../../common/validations/typeValidations');
|
|
15
15
|
const auditUtil = require('../../utils/auditUtil');
|
|
16
16
|
const httpResponseStatusCodes = require('../../../../../common/httpResponseStatusCodes.json');
|
|
@@ -277,6 +277,93 @@ const updateOverrideExpiryDate = async (auditorContractorId, expiryDate, context
|
|
|
277
277
|
return response;
|
|
278
278
|
};
|
|
279
279
|
|
|
280
|
+
const createPmOverrideRequest = async (auditorContractorId, context, {
|
|
281
|
+
requestReason,
|
|
282
|
+
expiryType,
|
|
283
|
+
expiryDate = null,
|
|
284
|
+
assigneeUserIds,
|
|
285
|
+
recordDateModified,
|
|
286
|
+
expectError
|
|
287
|
+
} = {}) => {
|
|
288
|
+
const model = new PmOverrideRequestModel({
|
|
289
|
+
auditorContractorId,
|
|
290
|
+
requestReason,
|
|
291
|
+
expiryType,
|
|
292
|
+
expiryDate,
|
|
293
|
+
assigneeUserIds,
|
|
294
|
+
recordDateModified
|
|
295
|
+
});
|
|
296
|
+
validateType(model, PmOverrideRequestModel);
|
|
297
|
+
const response = await overrideGapApi.createPmOverrideRequest(model, context);
|
|
298
|
+
|
|
299
|
+
if (expectError) {
|
|
300
|
+
return response;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (response.status !== httpResponseStatusCodes.CREATED) {
|
|
304
|
+
throw Error(`Failed to create PM override request. Status code: ${response.status}`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return response.data;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const editPmOverrideRequest = async (overrideGapRequestId, context, {
|
|
311
|
+
requestReason,
|
|
312
|
+
expiryType,
|
|
313
|
+
expiryDate = null,
|
|
314
|
+
assigneeUserIds,
|
|
315
|
+
recordDateModified,
|
|
316
|
+
expectError
|
|
317
|
+
} = {}) => {
|
|
318
|
+
const model = new PmOverrideRequestModel({
|
|
319
|
+
requestReason,
|
|
320
|
+
expiryType,
|
|
321
|
+
expiryDate,
|
|
322
|
+
assigneeUserIds,
|
|
323
|
+
recordDateModified
|
|
324
|
+
});
|
|
325
|
+
validateType(model, PmOverrideRequestModel);
|
|
326
|
+
const response = await overrideGapApi.editPmOverrideRequest(overrideGapRequestId, model, context);
|
|
327
|
+
|
|
328
|
+
if (expectError) {
|
|
329
|
+
return response;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
|
|
333
|
+
throw Error(`Failed to edit PM override request. Status code: ${response.status}`);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return response;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
const deletePmOverrideRequest = async (overrideGapRequestId, context, { expectError } = {}) => {
|
|
340
|
+
const response = await overrideGapApi.deletePmOverrideRequest(overrideGapRequestId, context);
|
|
341
|
+
|
|
342
|
+
if (expectError) {
|
|
343
|
+
return response;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
|
|
347
|
+
throw Error(`Failed to delete PM override request. Status code: ${response.status}`);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
return response;
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
const getEligibleOverrideAssignees = async (requestId, context, { expectError } = {}) => {
|
|
354
|
+
const response = await overrideGapApi.getEligibleOverrideAssignees(requestId, context);
|
|
355
|
+
|
|
356
|
+
if (expectError) {
|
|
357
|
+
return response;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
if (response.status !== httpResponseStatusCodes.OK) {
|
|
361
|
+
throw Error(`Failed to get eligible override assignees. Status code: ${response.status}`);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return response.data;
|
|
365
|
+
};
|
|
366
|
+
|
|
280
367
|
module.exports = {
|
|
281
368
|
waive,
|
|
282
369
|
waiveAll,
|
|
@@ -296,5 +383,9 @@ module.exports = {
|
|
|
296
383
|
getOverrideGapRequestById,
|
|
297
384
|
rejectOverrideGapRequest,
|
|
298
385
|
getAuditorContractorIdFromGap,
|
|
299
|
-
updateOverrideExpiryDate
|
|
386
|
+
updateOverrideExpiryDate,
|
|
387
|
+
createPmOverrideRequest,
|
|
388
|
+
editPmOverrideRequest,
|
|
389
|
+
deletePmOverrideRequest,
|
|
390
|
+
getEligibleOverrideAssignees
|
|
300
391
|
};
|
|
@@ -4,4 +4,9 @@ const OVERRIDE_GAP_REQUEST_STATUS = {
|
|
|
4
4
|
REJECTED: 'REJECTED'
|
|
5
5
|
};
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
const OVERRIDE_REQUESTER_TYPE = {
|
|
8
|
+
HUB_USER: 'HUB_USER',
|
|
9
|
+
INVITER: 'INVITER'
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
module.exports = { OVERRIDE_GAP_REQUEST_STATUS, OVERRIDE_REQUESTER_TYPE };
|
package/src/saas/internal-api/compliance/models/overrideGapRequest/override.gap.request.model.js
CHANGED
|
@@ -13,4 +13,19 @@ class OverrideGapRequestRejectModel {
|
|
|
13
13
|
this.recordDateModified = recordDateModified;
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
|
|
17
|
+
class PmOverrideRequestModel {
|
|
18
|
+
constructor({ auditorContractorId, requestReason, expiryType, expiryDate = null, assigneeUserIds, recordDateModified }) {
|
|
19
|
+
if (auditorContractorId !== undefined) {
|
|
20
|
+
this.auditorContractorId = auditorContractorId;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
this.requestReason = requestReason;
|
|
24
|
+
this.expiryType = expiryType;
|
|
25
|
+
this.expiryDate = expiryDate;
|
|
26
|
+
this.assigneeUserIds = assigneeUserIds;
|
|
27
|
+
this.recordDateModified = recordDateModified;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
module.exports = { OverrideGapRequestCreateModel, OverrideGapRequestRejectModel, PmOverrideRequestModel };
|
|
@@ -54,16 +54,11 @@ const EMAIL_SUBJECT = {
|
|
|
54
54
|
overrideGapRequestPending: ({ vendorCompanyName }) => `${vendorCompanyName} asked for an exception`,
|
|
55
55
|
overrideGapRequestRejected: ({ accountName }) => `${accountName} denied your exception request`,
|
|
56
56
|
overrideGapRequestApproved: ({ accountName }) => `${accountName} approved your exception request`,
|
|
57
|
+
pmOverrideRequestAssigned: ({ requesterFullName, companyName }) => `${requesterFullName} asked you to override a gap for ${companyName}`,
|
|
58
|
+
pmOverrideRequestDenied: ({ rejecterFullName, companyName }) => `${rejecterFullName} Rejected your override request for ${companyName}`,
|
|
59
|
+
pmOverrideRequestApproved: ({ approverFullName, companyName }) => `${approverFullName} Approved your override request for ${companyName}`,
|
|
57
60
|
timedOverrideExpired: ({ recordCompanyName, requesterName }) => `Override ended - ${recordCompanyName} in ${requesterName}`,
|
|
58
|
-
allRecordsExport: 'Jones - All Records Export'
|
|
59
|
-
weeklyDigest: ({ accountName }) => `Your Weekly updates for ${accountName}`
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const EMAIL_LINK_REGEX = {
|
|
63
|
-
mailActionButton: /(https:\/\/[a-zA-Z0-9.].*[a-zA-Z.]+\/CheckCustomersInviteLinkJSON\?data=[^"]+)/g,
|
|
64
|
-
sampleCoiDownload: /\/sample-coi\/requirement\/([^/]+)\/download\?source=email/,
|
|
65
|
-
allRecordsExportDownload: /href="(https?:\/\/[^"]+)"/,
|
|
66
|
-
weeklyDigestViewAll: issue => new RegExp(`(https:\\/\\/[^"]+\\/all-records\\?digestIssue=${issue}[^"]*)`)
|
|
61
|
+
allRecordsExport: 'Jones - All Records Export'
|
|
67
62
|
};
|
|
68
63
|
|
|
69
64
|
const EMAIL_POLLING = {
|
|
@@ -71,4 +66,4 @@ const EMAIL_POLLING = {
|
|
|
71
66
|
expectNoMail: { maxRetries: 3, pollIntervalSeconds: 1 }
|
|
72
67
|
};
|
|
73
68
|
|
|
74
|
-
module.exports = { DEFAULT_EMAIL_SENDER, EMAIL_TYPES, EMAIL_SUBJECT,
|
|
69
|
+
module.exports = { DEFAULT_EMAIL_SENDER, EMAIL_TYPES, EMAIL_SUBJECT, EMAIL_POLLING, tenantUserExtension };
|
|
@@ -62,6 +62,10 @@ const getEmailTextInSubject = (recordCompanyName, emailType, isAfterUpdateRequir
|
|
|
62
62
|
return isAfterUpdateRequirements ? `Updated Requirements - ${subject}` : subject;
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
+
const getMailActionButtonUrlRegex = () => {
|
|
66
|
+
return /(https:\/\/[a-zA-Z0-9.].*[a-zA-Z.]+\/CheckCustomersInviteLinkJSON\?data=[^"]+)/g;
|
|
67
|
+
};
|
|
68
|
+
|
|
65
69
|
const getEncryptedDataFromLink = (link, { removeLastTwoCharts } = {}) => {
|
|
66
70
|
const encryptedData = link.split('data=').pop();
|
|
67
71
|
return removeLastTwoCharts ? encryptedData.slice(0, -2) : encryptedData;
|
|
@@ -73,5 +77,6 @@ module.exports = {
|
|
|
73
77
|
extractEmailFromNameAndEmailFormat,
|
|
74
78
|
logRetrievedEmailInfo,
|
|
75
79
|
getEmailTextInSubject,
|
|
80
|
+
getMailActionButtonUrlRegex,
|
|
76
81
|
getEncryptedDataFromLink
|
|
77
82
|
};
|
|
@@ -3,7 +3,10 @@ const NOTIFICATION_TYPES = {
|
|
|
3
3
|
OVERRIDE_GAP_REQUEST_PENDING: 'NewOverrideGapRequest',
|
|
4
4
|
RELATED_DOC_UPDATED: 'RelatedDocUpdated',
|
|
5
5
|
GLOBAL_RECORD_RELATED_DOC_UPDATED: 'GlobalRecordRelatedDocUpdated',
|
|
6
|
-
TIMED_OVERRIDE_EXPIRED: 'TimedOverrideExpired'
|
|
6
|
+
TIMED_OVERRIDE_EXPIRED: 'TimedOverrideExpired',
|
|
7
|
+
PM_OVERRIDE_REQUEST: 'NewPmOverrideRequest',
|
|
8
|
+
PM_OVERRIDE_REQUEST_APPROVED: 'PmOverrideRequestApproved',
|
|
9
|
+
PM_OVERRIDE_REQUEST_REJECTED: 'PmOverrideRequestRejected'
|
|
7
10
|
};
|
|
8
11
|
|
|
9
12
|
module.exports = { NOTIFICATION_TYPES };
|
|
@@ -9,6 +9,7 @@ class UpdateProjectSettingsModel {
|
|
|
9
9
|
tenantSolution = false,
|
|
10
10
|
autocompleteSettings = {},
|
|
11
11
|
overrideGapRequestSettings = {},
|
|
12
|
+
userOverrideRequestSettings = {},
|
|
12
13
|
relevantComplianceDocumentsSettings = {}
|
|
13
14
|
} = {}
|
|
14
15
|
) {
|
|
@@ -20,6 +21,7 @@ class UpdateProjectSettingsModel {
|
|
|
20
21
|
this.tenantSolution = tenantSolution;
|
|
21
22
|
this.autocompleteSettings = { ... DEFAULT_AUTOCOMPLETE_ADD_VENDORS, ... autocompleteSettings };
|
|
22
23
|
this.overrideGapRequestSettings = { ... DEFAULT_OVERRIDE_GAP_REQUEST, ... overrideGapRequestSettings };
|
|
24
|
+
this.userOverrideRequestSettings = { ... DEFAULT_USER_OVERRIDE_REQUEST, ... userOverrideRequestSettings };
|
|
23
25
|
this.relevantComplianceDocumentsSettings = { ... DEFAULT_RELEVANT_COMPLIANCE_DOCUMENTS, ... relevantComplianceDocumentsSettings };
|
|
24
26
|
}
|
|
25
27
|
}
|
|
@@ -49,6 +51,12 @@ const DEFAULT_OVERRIDE_GAP_REQUEST = {
|
|
|
49
51
|
isOverrideGapRequestEnabledForGuests: false
|
|
50
52
|
};
|
|
51
53
|
|
|
54
|
+
const DEFAULT_USER_OVERRIDE_REQUEST = {
|
|
55
|
+
isUserOverrideRequestEnabledForVendors: false,
|
|
56
|
+
isUserOverrideRequestEnabledForTenants: false,
|
|
57
|
+
isUserOverrideRequestEnabledForGuests: false
|
|
58
|
+
};
|
|
59
|
+
|
|
52
60
|
const DEFAULT_RELEVANT_COMPLIANCE_DOCUMENTS = {
|
|
53
61
|
isRelevantComplianceDocumentsEnabledForVendors: false,
|
|
54
62
|
isRelevantComplianceDocumentsEnabledForTenants: false,
|
|
@@ -66,9 +66,6 @@ module.exports = {
|
|
|
66
66
|
requireScope(entityIds, schedulerJobs.CERTIFICIAL_MONITORING);
|
|
67
67
|
return runSchedulerJob({ jobType: schedulerJobs.CERTIFICIAL_MONITORING, entityIds });
|
|
68
68
|
},
|
|
69
|
-
runJobForWeeklyDigest: function(entityIds) {
|
|
70
|
-
return runSchedulerJob({ jobType: schedulerJobs.WEEKLY_DIGEST, entityIds });
|
|
71
|
-
},
|
|
72
69
|
runAllJobsNew: function(entityIds) {
|
|
73
70
|
return runSchedulerJob({ jobType: schedulerJobs.ALL, entityIds });
|
|
74
71
|
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
const requests = require('../../../../common/requests/cookieAuth/requests');
|
|
2
|
-
const { backendUrl } = require('../../../../env').getEnv();
|
|
3
|
-
|
|
4
|
-
const Endpoints = {
|
|
5
|
-
snapshot: `${backendUrl}/saas/integration-tests/weekly-digest/snapshot`,
|
|
6
|
-
accountSnapshot: accountId => `${backendUrl}/saas/integration-tests/weekly-digest/account/${accountId}/snapshot`,
|
|
7
|
-
run: accountId => `${backendUrl}/saas/integration-tests/weekly-digest/account/${accountId}/run`,
|
|
8
|
-
reportLog: `${backendUrl}/saas/integration-tests/weekly-digest/report-log`
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const takeAccountSnapshot = (accountId, context) => {
|
|
12
|
-
return requests.postRequestHandler(Endpoints.accountSnapshot(accountId), null, context);
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const takeAccountsSnapshot = (accountIds, context) => {
|
|
16
|
-
return requests.postRequestHandler(Endpoints.snapshot, { accountIds }, context);
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const runWeeklyDigest = (accountId, body, context) => {
|
|
20
|
-
return requests.postRequestHandler(Endpoints.run(accountId), body, context);
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
const getWeeklyDigestReports = (accountId, weekStart, context) => {
|
|
24
|
-
return requests.getRequestHandler(Endpoints.reportLog, { accountId, weekStart }, context);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
module.exports = {
|
|
28
|
-
takeAccountSnapshot,
|
|
29
|
-
takeAccountsSnapshot,
|
|
30
|
-
runWeeklyDigest,
|
|
31
|
-
getWeeklyDigestReports
|
|
32
|
-
};
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
|
|
2
|
-
const timeUtils = require('../../../../common/utils/timeUtils');
|
|
3
|
-
|
|
4
|
-
const authService = require('../../auth/api/auth.service');
|
|
5
|
-
const weeklyDigestApi = require('./weekly.digest.api');
|
|
6
|
-
const { REPORT_STATUS } = require('../consts/weekly.digest.consts');
|
|
7
|
-
|
|
8
|
-
const takeAccountSnapshot = async accountId => {
|
|
9
|
-
const response = await weeklyDigestApi.takeAccountSnapshot(accountId, await authService.getIcsCookie());
|
|
10
|
-
|
|
11
|
-
if (response.status !== httpResponseStatusCodes.OK) {
|
|
12
|
-
throw new Error(`Account snapshot failed for account ${accountId}. Status code: ${response.status}`);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
return response.data.snapshotId;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const takeAccountsSnapshot = async accountIds => {
|
|
19
|
-
const response = await weeklyDigestApi.takeAccountsSnapshot(accountIds, await authService.getIcsCookie());
|
|
20
|
-
|
|
21
|
-
if (response.status !== httpResponseStatusCodes.OK) {
|
|
22
|
-
throw new Error(`Accounts snapshot failed for accounts ${accountIds}. Status code: ${response.status}`);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
return response.data.snapshotId;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Runs synchronously for next Monday's week, after clearing the account's report-log rows for that week.
|
|
29
|
-
const runWeeklyDigest = async (accountId, { previousRunId, currentRunId }) => {
|
|
30
|
-
const body = { beforeSnapshotId: previousRunId, afterSnapshotId: currentRunId };
|
|
31
|
-
const response = await weeklyDigestApi.runWeeklyDigest(accountId, body, await authService.getIcsCookie());
|
|
32
|
-
|
|
33
|
-
if (response.status !== httpResponseStatusCodes.OK) {
|
|
34
|
-
throw new Error(`Weekly digest run failed for account ${accountId}. Status code: ${response.status}`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return response.data;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const getWeeklyDigestReports = async (accountId, weekStart) => {
|
|
41
|
-
const response = await weeklyDigestApi.getWeeklyDigestReports(accountId, weekStart, await authService.getIcsCookie());
|
|
42
|
-
|
|
43
|
-
if (response.status !== httpResponseStatusCodes.OK) {
|
|
44
|
-
throw new Error(`Weekly digest reports failed for account ${accountId}. Status code: ${response.status}`);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return response.data;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// The scheduler endpoint returns before the job runs, so a real-job run has to poll the report log.
|
|
51
|
-
const waitForWeeklyDigestReport = async (accountId, weekStart, userId, { expectedStatus = REPORT_STATUS.SENT, retries = 10 } = {}) => {
|
|
52
|
-
let report;
|
|
53
|
-
|
|
54
|
-
while (report?.reportData.status !== expectedStatus && retries-- > 0) {
|
|
55
|
-
await timeUtils.waitFor(3).seconds;
|
|
56
|
-
const reports = await getWeeklyDigestReports(accountId, weekStart);
|
|
57
|
-
report = reports.find(row => row.userId === userId);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return report;
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
module.exports = {
|
|
64
|
-
takeAccountSnapshot,
|
|
65
|
-
takeAccountsSnapshot,
|
|
66
|
-
runWeeklyDigest,
|
|
67
|
-
getWeeklyDigestReports,
|
|
68
|
-
waitForWeeklyDigestReport
|
|
69
|
-
};
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
const REPORT_STATUS = {
|
|
2
|
-
IN_PROGRESS: 'IN_PROGRESS',
|
|
3
|
-
SENT: 'SENT',
|
|
4
|
-
NO_VISIBLE_REQUESTS: 'NO_VISIBLE_REQUESTS'
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
const NEW_ISSUE_TYPE = {
|
|
8
|
-
EXPIRED_LAST_WEEK: 'EXPIRED_LAST_WEEK',
|
|
9
|
-
BECAME_NOT_COMPLIANT: 'BECAME_NOT_COMPLIANT',
|
|
10
|
-
EXPIRING_THIS_WEEK: 'EXPIRING_THIS_WEEK',
|
|
11
|
-
BECAME_NOT_RESPONSIVE: 'BECAME_NOT_RESPONSIVE'
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const ACTIVITY_TYPE = {
|
|
15
|
-
TIMED_OVERRIDE_ENDING: 'TIMED_OVERRIDE_ENDING',
|
|
16
|
-
EXCEPTION_REQUEST: 'EXCEPTION_REQUEST',
|
|
17
|
-
MENTION: 'MENTION',
|
|
18
|
-
RELATED_DOC: 'RELATED_DOC'
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
module.exports = { REPORT_STATUS, NEW_ISSUE_TYPE, ACTIVITY_TYPE };
|