@getjones/test-infra 4.4.1 → 4.4.2
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 +30 -2
- package/src/common/utils/complianceUtil.js +3 -1
- package/src/factory/records/records.js +4 -4
- package/src/resources/virusFile.pdf +0 -0
- package/src/saas/internal-api/agreement/api/agreement.api.js +8 -2
- package/src/saas/internal-api/agreement/api/agreement.service.js +13 -1
- package/src/saas/internal-api/coi/utils/utils.js +22 -0
- package/src/saas/internal-api/compliance/api/audit/audit.service.js +12 -1
- package/src/saas/internal-api/compliance/models/audit/audit.model.js +2 -1
- package/src/saas/internal-api/compliance/utils/auditUtil.js +14 -5
- package/src/saas/internal-api/contractors/api/contractors.api.js +6 -0
- package/src/saas/internal-api/contractors/api/contractors.service.js +13 -0
package/package.json
CHANGED
|
@@ -39,7 +39,7 @@ const editRequestAndRecordDetails = async function(request, recordConfig, contex
|
|
|
39
39
|
const editRequestResponse = await requests.services.editRequestAndRecordDetails(requestEditModel, context);
|
|
40
40
|
|
|
41
41
|
if (editRequestResponse.status !== httpResponseStatusCodes.OK) {
|
|
42
|
-
throw Error(`Failed to edit record
|
|
42
|
+
throw Error(`Failed to edit record \n${editRequestResponse.data.message}`);
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -119,6 +119,31 @@ const getHistoryEvents = async function(recordId, context) {
|
|
|
119
119
|
return recordHistory.data.map(item => item.itemTitle).reverse();
|
|
120
120
|
};
|
|
121
121
|
|
|
122
|
+
const getFirstHistoryEventId = async function(recordId, context) {
|
|
123
|
+
const recordHistory = await contractors.services.getRecordHistory(recordId, context);
|
|
124
|
+
expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
|
|
125
|
+
return recordHistory.data[recordHistory.data.length - 1].itemId;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const getLatestHistoryEventId = async function(recordId, context) {
|
|
129
|
+
const recordHistory = await contractors.services.getRecordHistory(recordId, context);
|
|
130
|
+
expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
|
|
131
|
+
return recordHistory.data[0].itemId;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const getLatestRecordHistoryEventIdByItemTitle = async function(recordId, itemTitle, context) {
|
|
135
|
+
const recordHistory = await contractors.services.getRecordHistory(recordId, context);
|
|
136
|
+
expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
|
|
137
|
+
|
|
138
|
+
const latestHistoryByTitle = recordHistory.data.find(historyItem => historyItem.itemTitle === itemTitle);
|
|
139
|
+
|
|
140
|
+
if (!latestHistoryByTitle) {
|
|
141
|
+
throw new Error(`History event with title ${itemTitle} not found`);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return latestHistoryByTitle.itemId;
|
|
145
|
+
};
|
|
146
|
+
|
|
122
147
|
const waitForOcrStatus = async function(recordId, context, { expectedStatus = ocrStatuses.SUCCESS } = {}) {
|
|
123
148
|
let { data: recordOcrStatus } = await contractors.services.getRecordOcrStatus(recordId, context);
|
|
124
149
|
let maxRetries = 25;
|
|
@@ -160,8 +185,11 @@ module.exports = {
|
|
|
160
185
|
updateInviteDate,
|
|
161
186
|
updatePolicyExpiryDateForRecord,
|
|
162
187
|
getHistoryEvents,
|
|
188
|
+
getFirstHistoryEventId,
|
|
189
|
+
getLatestHistoryEventId,
|
|
163
190
|
updateLastInviteActionDate,
|
|
164
191
|
waitForOcrStatus,
|
|
165
192
|
generateSubscriptionModelFromMail,
|
|
166
|
-
deleteAllRequestsInProject
|
|
193
|
+
deleteAllRequestsInProject,
|
|
194
|
+
getLatestRecordHistoryEventIdByItemTitle
|
|
167
195
|
};
|
|
@@ -56,11 +56,13 @@ const prepareMetadataForAudit = async (
|
|
|
56
56
|
const auditResponse = await auditApi.getAuditMetadata(recordDetails.auditId, auditorContext);
|
|
57
57
|
const { currentAudit } = auditResponse.data;
|
|
58
58
|
|
|
59
|
+
const enterAuditResponse = await auditApi.enterAudit(recordId, auditorContext);
|
|
60
|
+
|
|
59
61
|
metadata.certificateId = recordDetails.certificateDetails.certificateuploadId;
|
|
60
62
|
metadata.auditDates = {
|
|
61
63
|
contractorId: recordId,
|
|
62
64
|
contractorDateModified: recordDetails.dateModified,
|
|
63
|
-
dateStartedAudit:
|
|
65
|
+
dateStartedAudit: enterAuditResponse.data.dateStartedAudit,
|
|
64
66
|
contractorOverrideDateModified: recordDetails.contractorOverrideDateModified,
|
|
65
67
|
contractCreateDate: recordDetails.contractCreateDate,
|
|
66
68
|
auditDateModified: currentAudit.dateModified
|
|
@@ -17,7 +17,7 @@ const recordFlows = require('../../common/commonFlows/records/records');
|
|
|
17
17
|
|
|
18
18
|
const filePath = path.join(__dirname, '../../resources/coi/coi.pdf');
|
|
19
19
|
|
|
20
|
-
const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirementId, context, { expiryStatus, shouldSendNotificationToPM = false, recordConfig, glPolicyNumber } = {}) => {
|
|
20
|
+
const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirementId, context, { inviterEmail = credentials.superUser, expiryStatus, shouldSendNotificationToPM = false, recordConfig, glPolicyNumber } = {}) => {
|
|
21
21
|
validateInsuranceAndExpiryStatus(status, expiryStatus);
|
|
22
22
|
|
|
23
23
|
const requestData = await requests.services.getOrCreateRequest(
|
|
@@ -25,7 +25,7 @@ const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirem
|
|
|
25
25
|
tabId,
|
|
26
26
|
requirementId,
|
|
27
27
|
{ // record
|
|
28
|
-
inviterEmail
|
|
28
|
+
inviterEmail,
|
|
29
29
|
email: recordEmail,
|
|
30
30
|
companyName: recordCompany
|
|
31
31
|
}
|
|
@@ -89,8 +89,8 @@ const prepareCompliantRecord = (recordCompany, recordEmail, tabId, requirementId
|
|
|
89
89
|
return prepareRecord(recordCompany, recordEmail, complianceStatuses.compliant, tabId, requirementId, context, { recordConfig, expiryStatus, glPolicyNumber });
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
const prepareNotCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { shouldSendNotificationToPM = false, recordConfig, expiryStatus, glPolicyNumber } = {}) => {
|
|
93
|
-
return prepareRecord(recordCompany, recordEmail, complianceStatuses.notCompliant, tabId, requirementId, context, {
|
|
92
|
+
const prepareNotCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { inviterEmail, shouldSendNotificationToPM = false, recordConfig, expiryStatus, glPolicyNumber } = {}) => {
|
|
93
|
+
return prepareRecord(recordCompany, recordEmail, complianceStatuses.notCompliant, tabId, requirementId, context, { inviterEmail, shouldSendNotificationToPM, recordConfig, expiryStatus, glPolicyNumber });
|
|
94
94
|
};
|
|
95
95
|
|
|
96
96
|
const prepareWaivedRecord = async (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig, expiryStatus, glPolicyNumber } = {}) => {
|
|
Binary file
|
|
@@ -6,7 +6,8 @@ const AGREEMENT_API_URL = `${backendUrl}/saas/contractor/agreement`;
|
|
|
6
6
|
const Endpoints = {
|
|
7
7
|
create: AGREEMENT_API_URL,
|
|
8
8
|
createByAuditor: `${backendUrl}/UpdateSnippetService`,
|
|
9
|
-
getAgreementPreSignedUrl: `${backendUrl}/saas/pre-signed-url/upload/agreement
|
|
9
|
+
getAgreementPreSignedUrl: `${backendUrl}/saas/pre-signed-url/upload/agreement`,
|
|
10
|
+
getAgreementLinkByRecordId: recordId => `${backendUrl}/saas/contractor/${recordId}/agreement`
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const getAgreementPreSignedUrl = (formData, context) => {
|
|
@@ -25,9 +26,14 @@ const createAgreementByAuditor = (createAgreementModel, context) => {
|
|
|
25
26
|
return requests.postRequestHandler(Endpoints.createByAuditor, createAgreementModel, context);
|
|
26
27
|
};
|
|
27
28
|
|
|
29
|
+
const getAgreementLinkByRecordId = (recordId, context) => {
|
|
30
|
+
return requests.getRequestHandler(Endpoints.getAgreementLinkByRecordId(recordId), null, context);
|
|
31
|
+
};
|
|
32
|
+
|
|
28
33
|
module.exports = {
|
|
29
34
|
createAgreement,
|
|
30
35
|
createAgreementByAuditor,
|
|
31
36
|
uploadAgreementToS3,
|
|
32
|
-
getAgreementPreSignedUrl
|
|
37
|
+
getAgreementPreSignedUrl,
|
|
38
|
+
getAgreementLinkByRecordId
|
|
33
39
|
};
|
|
@@ -102,8 +102,20 @@ const uploadAgreementByAuditor = async (
|
|
|
102
102
|
|
|
103
103
|
return createResponse;
|
|
104
104
|
};
|
|
105
|
+
|
|
106
|
+
const getAgreementLinkByRecordId = async (recordId, context) => {
|
|
107
|
+
const linkResponse = await agreementAPI.getAgreementLinkByRecordId(recordId, context);
|
|
108
|
+
|
|
109
|
+
if (linkResponse.status !== httpResponseStatusCodes.OK) {
|
|
110
|
+
throw new Error(`Failed to get agreement for record ${recordId}`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return linkResponse.data;
|
|
114
|
+
};
|
|
115
|
+
|
|
105
116
|
module.exports = {
|
|
106
117
|
createAgreement,
|
|
107
118
|
uploadAgreementByPM,
|
|
108
|
-
uploadAgreementByAuditor
|
|
119
|
+
uploadAgreementByAuditor,
|
|
120
|
+
getAgreementLinkByRecordId
|
|
109
121
|
};
|
|
@@ -5,6 +5,7 @@ const { SubmitCoiModel } = require('../models/submit.coi.model');
|
|
|
5
5
|
const { CombineLastTwoCOIsModel } = require('../models/Combine.last.two.cois.model');
|
|
6
6
|
const { getContractorById } = require('../../contractors/api/contractors.service');
|
|
7
7
|
const { getIcsCookie } = require('../../auth/api/auth.service');
|
|
8
|
+
const timeUtils = require('../../../../common/utils/timeUtils');
|
|
8
9
|
|
|
9
10
|
const uploadFileToStorage = (recordId, filePath) => {
|
|
10
11
|
const fileData = fs.createReadStream(filePath);
|
|
@@ -64,6 +65,26 @@ const uploadCoi = async (
|
|
|
64
65
|
return uploadedCoi;
|
|
65
66
|
};
|
|
66
67
|
|
|
68
|
+
const waitForAntiVirusRecordCoiScanToFinish = async (recordId, context, { maxSecondToWait = 10 } = {}) => {
|
|
69
|
+
let isScanned = false;
|
|
70
|
+
const oneSecondInMilliseconds = 1000;
|
|
71
|
+
let timeFromTheStart = 0;
|
|
72
|
+
let coiLink;
|
|
73
|
+
const started = Date.now();
|
|
74
|
+
|
|
75
|
+
const { data: record } = await getContractorById(recordId, context);
|
|
76
|
+
|
|
77
|
+
while (!isScanned && timeFromTheStart < maxSecondToWait) {
|
|
78
|
+
({ data: coiLink } = await services.getCoiPreSignedUrl(record.certificatePdf));
|
|
79
|
+
isScanned = coiLink.isInProgress;
|
|
80
|
+
const now = Date.now();
|
|
81
|
+
timeFromTheStart = (now - started) / oneSecondInMilliseconds;
|
|
82
|
+
await timeUtils.waitFor(1).seconds;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return coiLink.coiPreSignedUrl;
|
|
86
|
+
};
|
|
87
|
+
|
|
67
88
|
const combineLastTwoCOIs = async ({
|
|
68
89
|
recordId,
|
|
69
90
|
fileIds,
|
|
@@ -91,5 +112,6 @@ module.exports = {
|
|
|
91
112
|
uploadCoi,
|
|
92
113
|
uploadFileToStorage,
|
|
93
114
|
submitCoiFilesUpload,
|
|
115
|
+
waitForAntiVirusRecordCoiScanToFinish,
|
|
94
116
|
combineLastTwoCOIs
|
|
95
117
|
};
|
|
@@ -62,6 +62,15 @@ const getAuditRecordModel = (recordId, context) => {
|
|
|
62
62
|
const getRequirementDetailsForAudit = (contractorId, context) => {
|
|
63
63
|
return auditApi.getRequirementDetailsForAudit(contractorId, context);
|
|
64
64
|
};
|
|
65
|
+
const getAuditorContractorReviewByRecordId = async (recordId, context) => {
|
|
66
|
+
const response = await auditApi.getAuditorContractorReviewByRecordId(recordId, context);
|
|
67
|
+
|
|
68
|
+
if (response.status !== httpResponseStatusCodes.OK) {
|
|
69
|
+
throw Error(`Failed to get auditor review fields from recordId - ${recordId} error status ${response.status}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return response.data;
|
|
73
|
+
};
|
|
65
74
|
|
|
66
75
|
const prepareMetadataForAudit = async (
|
|
67
76
|
auditorContext,
|
|
@@ -99,11 +108,12 @@ const getAuditByRecordId = async (recordId, context, { isRecordDeleted } = {}) =
|
|
|
99
108
|
|
|
100
109
|
const getAuditEntities = async (recordId, auditData, auditorContext) => {
|
|
101
110
|
const requirementDetailsForAuditResponse = await getRequirementDetailsForAudit(recordId, auditorContext);
|
|
111
|
+
const previousAuditData = await getAuditRawData(recordId, auditorContext);
|
|
102
112
|
const requirement = requirementDetailsForAuditResponse.data;
|
|
103
113
|
|
|
104
114
|
const auditEntities = [];
|
|
105
115
|
auditData.forEach(auditEntity => auditEntities.push(
|
|
106
|
-
auditUtil.createAuditEntity(requirement, { ... auditEntity }))
|
|
116
|
+
auditUtil.createAuditEntity(requirement, previousAuditData, { ... auditEntity }))
|
|
107
117
|
);
|
|
108
118
|
return auditEntities;
|
|
109
119
|
};
|
|
@@ -285,5 +295,6 @@ module.exports = {
|
|
|
285
295
|
updateComplianceAuditActionsDate,
|
|
286
296
|
getCurrentAuditUniqueCoiId,
|
|
287
297
|
getAuditRawData,
|
|
298
|
+
getAuditorContractorReviewByRecordId,
|
|
288
299
|
getAttributeKey
|
|
289
300
|
};
|
|
@@ -42,11 +42,12 @@ class AuditRequestModel {
|
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
class AuditEntityModel {
|
|
45
|
-
constructor(policyId, attributeName, status, value) {
|
|
45
|
+
constructor(policyId, attributeName, status, value, auditorReviewId) {
|
|
46
46
|
this.contractorInsuranceId = policyId;
|
|
47
47
|
this.limitname = attributeName;
|
|
48
48
|
this.status = status;
|
|
49
49
|
this.value = value;
|
|
50
|
+
this.auditorReviewId = auditorReviewId;
|
|
50
51
|
}
|
|
51
52
|
}
|
|
52
53
|
|
|
@@ -83,6 +83,13 @@ const getPolicyId = (policyName, requirement) => {
|
|
|
83
83
|
return policy.id;
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
+
const getAuditorReviewIdFromPreviousAudit = (policyId, attributeName, previousAuditData) => {
|
|
87
|
+
const reviewField = previousAuditData.
|
|
88
|
+
find(reviewField => reviewField.insuranceTypeId === policyId && reviewField.limitName === attributeName);
|
|
89
|
+
|
|
90
|
+
return reviewField?.auditorcontractorId;
|
|
91
|
+
};
|
|
92
|
+
|
|
86
93
|
const parseAuditConfig = function(config) {
|
|
87
94
|
const auditDataArr = [];
|
|
88
95
|
for (const field in config) {
|
|
@@ -145,7 +152,7 @@ const parseAuditConfig = function(config) {
|
|
|
145
152
|
|
|
146
153
|
const auditValue = config[field][1];
|
|
147
154
|
|
|
148
|
-
if (
|
|
155
|
+
if (multipleErrorsEndorsementAndAttributesList.includes(field) && isArray(auditValue)) {
|
|
149
156
|
// in case of 'Other' with multiple errors in special policies (Additional Information, Certificate Holder, etc)
|
|
150
157
|
let i = 0;
|
|
151
158
|
while (i < auditValue.length) {
|
|
@@ -174,14 +181,16 @@ const parseAuditConfig = function(config) {
|
|
|
174
181
|
};
|
|
175
182
|
|
|
176
183
|
const createAuditEntity = (
|
|
177
|
-
requirement, {
|
|
184
|
+
requirement, previousAuditData, {
|
|
178
185
|
policyName = null,
|
|
179
186
|
attributeName = null,
|
|
180
187
|
value = emptyValue,
|
|
181
188
|
status = emptyValue
|
|
182
189
|
}) => {
|
|
183
190
|
const policyId = getPolicyId(policyName, requirement);
|
|
184
|
-
const
|
|
191
|
+
const auditorReviewId = getAuditorReviewIdFromPreviousAudit(policyId, attributeName, previousAuditData);
|
|
192
|
+
const auditEntityModel = new auditModels.AuditEntityModel(policyId, attributeName, status, value, auditorReviewId);
|
|
193
|
+
|
|
185
194
|
return auditEntityModel;
|
|
186
195
|
};
|
|
187
196
|
|
|
@@ -203,12 +212,12 @@ const certificateEndorsementsList = [
|
|
|
203
212
|
'Agreement'
|
|
204
213
|
];
|
|
205
214
|
|
|
206
|
-
const
|
|
215
|
+
const multipleErrorsEndorsementAndAttributesList = [
|
|
207
216
|
'Certificate Holder',
|
|
208
217
|
'Additional Information',
|
|
209
218
|
'Additional Insured',
|
|
210
219
|
'Agreement',
|
|
211
|
-
'Other'
|
|
220
|
+
'Other'
|
|
212
221
|
];
|
|
213
222
|
|
|
214
223
|
const specialAttributes = {
|
|
@@ -7,6 +7,7 @@ const Endpoints = {
|
|
|
7
7
|
get: `${backendUrl}/saas/contractors`,
|
|
8
8
|
getContractorById: contractorId => `${backendUrl}/saas/contractor/${contractorId}`,
|
|
9
9
|
getRecordHistory: contractorId => `${backendUrl}/saas/record/${contractorId}/history`,
|
|
10
|
+
getRecordHistoryEventReport: recordHistoryId => `${backendUrl}/saas/record/compliance-history-report/${recordHistoryId}`,
|
|
10
11
|
getRecordOcrStatus: contractorId => `${backendUrl}/saas/contractor/${contractorId}/ocr/status`,
|
|
11
12
|
delete: contractorId => `${backendUrl}/saas/contractor/${contractorId}`,
|
|
12
13
|
archive: contractorId => `${backendUrl}/saas/contractor/${contractorId}/archive`,
|
|
@@ -48,6 +49,10 @@ const getRecordHistory = (contractorId, context) => {
|
|
|
48
49
|
return requests.getRequestHandler(Endpoints.getRecordHistory(contractorId), {}, context);
|
|
49
50
|
};
|
|
50
51
|
|
|
52
|
+
const getRecordHistoryEventReport = (recordHistoryId, context) => {
|
|
53
|
+
return requests.getRequestHandler(Endpoints.getRecordHistoryEventReport(recordHistoryId), {}, context);
|
|
54
|
+
};
|
|
55
|
+
|
|
51
56
|
const getComplianceReport = (encryptedData, context) => {
|
|
52
57
|
return requests.getRequestHandler(Endpoints.getComplianceReport(encryptedData), {}, context);
|
|
53
58
|
};
|
|
@@ -170,6 +175,7 @@ module.exports = {
|
|
|
170
175
|
getContractorsByAccountId,
|
|
171
176
|
getContractorById,
|
|
172
177
|
getRecordHistory,
|
|
178
|
+
getRecordHistoryEventReport,
|
|
173
179
|
getRecordOcrStatus,
|
|
174
180
|
getComplianceReport,
|
|
175
181
|
deleteByContractorId,
|
|
@@ -27,6 +27,18 @@ const getRecordHistory = (contractorId, context) => {
|
|
|
27
27
|
return contractorsAPI.getRecordHistory(contractorId, context);
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
+
const getRecordHistoryEventReport = async (recordHistoryId, context, { expectError } = {}) => {
|
|
31
|
+
const historyEventReportResponse = await contractorsAPI.getRecordHistoryEventReport(recordHistoryId, context);
|
|
32
|
+
|
|
33
|
+
if (expectError) {
|
|
34
|
+
return historyEventReportResponse;
|
|
35
|
+
} else if (historyEventReportResponse.status !== httpResponseStatusCodes.OK) {
|
|
36
|
+
throw new Error(`Failed to get record history event report: ${historyEventReportResponse.statusText}`);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return historyEventReportResponse.data;
|
|
40
|
+
};
|
|
41
|
+
|
|
30
42
|
const getRecordOcrStatus = (recordId, context) => {
|
|
31
43
|
return contractorsAPI.getRecordOcrStatus(recordId, context);
|
|
32
44
|
};
|
|
@@ -289,6 +301,7 @@ module.exports = {
|
|
|
289
301
|
getContractorsByAccountId,
|
|
290
302
|
getContractorById,
|
|
291
303
|
getRecordHistory,
|
|
304
|
+
getRecordHistoryEventReport,
|
|
292
305
|
getRecordOcrStatus,
|
|
293
306
|
getComplianceReport,
|
|
294
307
|
archiveRecord,
|