@getjones/test-infra 3.0.2 → 3.1.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 +24 -1
- package/src/common/consts/accountSettings.js +10 -0
- package/src/common/consts/ocrStatuses.js +6 -0
- package/src/common/utils/complianceUtil.js +33 -10
- package/src/defaults/configs/auditConfigs.js +10 -2
- package/src/defaults/configs/polices.js +8 -5
- package/src/factory/records/records.js +78 -22
- package/src/saas/internal-api/contractors/api/contractors.api.js +18 -0
- package/src/saas/internal-api/contractors/api/contractors.service.js +59 -0
- package/src/saas/internal-api/contractors/models/subscription.contractor.model.js +13 -0
- package/src/saas/internal-api/dbEmails/api/db.emails.service.js +9 -0
- package/src/saas/internal-api/dbEmails/utils/util.js +7 -2
package/package.json
CHANGED
|
@@ -3,9 +3,11 @@ const { expect } = require('chai');
|
|
|
3
3
|
const threadScheduler = require('../../../saas/internal-api/thread-scheduler/runner');
|
|
4
4
|
const timeUtils = require('../../utils/timeUtils');
|
|
5
5
|
const httpResponseStatusCodes = require('../../../common/httpResponseStatusCodes.json');
|
|
6
|
+
const ocrStatuses = require('../../consts/ocrStatuses');
|
|
6
7
|
const contractors = require('../../../saas/internal-api/contractors');
|
|
7
8
|
const compliance = require('../../../saas/internal-api/compliance');
|
|
8
9
|
const requests = require('../../../saas/internal-api/requests');
|
|
10
|
+
const dbEmails = require('../../../saas/internal-api/dbEmails');
|
|
9
11
|
|
|
10
12
|
const makeRecordNotResponsive = async function(recordId, context, { isTenant } = {}) {
|
|
11
13
|
const offsetInDaysList = isTenant ?
|
|
@@ -112,6 +114,25 @@ const getHistoryEvents = async function(recordId, context) {
|
|
|
112
114
|
return recordHistory.data.map(item => item.itemTitle).reverse();
|
|
113
115
|
};
|
|
114
116
|
|
|
117
|
+
const waitForOcrStatus = async function(recordId, context, { expectedStatus = ocrStatuses.SUCCESS } = {}) {
|
|
118
|
+
let { data: recordOcrStatus } = await contractors.services.getRecordOcrStatus(recordId, context);
|
|
119
|
+
let maxRetries = 25;
|
|
120
|
+
while (recordOcrStatus !== expectedStatus && recordOcrStatus !== ocrStatuses.FAILED && maxRetries > 0) {
|
|
121
|
+
await timeUtils.waitFor(5).seconds;
|
|
122
|
+
recordOcrStatus = (await contractors.services.getRecordOcrStatus(recordId, context)).data;
|
|
123
|
+
maxRetries--;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (recordOcrStatus !== expectedStatus) {
|
|
127
|
+
throw new Error(`Record OCR status not is as expected. Expected: ${expectedStatus}, Actual: ${recordOcrStatus}`);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const generateSubscriptionModelFromMail = async function(recipients) {
|
|
132
|
+
const data = await dbEmails.services.getSubscriptionData(recipients);
|
|
133
|
+
return contractors.services.getSubscriptionModel(data);
|
|
134
|
+
};
|
|
135
|
+
|
|
115
136
|
module.exports = {
|
|
116
137
|
makeRecordNotResponsive,
|
|
117
138
|
runOverAllRenewalDatesForRecord,
|
|
@@ -119,5 +140,7 @@ module.exports = {
|
|
|
119
140
|
updateInviteDate,
|
|
120
141
|
updatePolicyExpiryDateForRecord,
|
|
121
142
|
getHistoryEvents,
|
|
122
|
-
updateLastInviteActionDate
|
|
143
|
+
updateLastInviteActionDate,
|
|
144
|
+
waitForOcrStatus,
|
|
145
|
+
generateSubscriptionModelFromMail
|
|
123
146
|
};
|
|
@@ -6,12 +6,17 @@ const { credentials } = getEnv();
|
|
|
6
6
|
|
|
7
7
|
const complianceStatuses = {
|
|
8
8
|
complaint: 'complaint',
|
|
9
|
+
awaitingCoi: 'awaitingCoi',
|
|
9
10
|
notCompliant: 'notCompliant',
|
|
10
|
-
|
|
11
|
-
aboutToExpired: 'aboutToExpired',
|
|
11
|
+
waived: 'waived',
|
|
12
12
|
awaitingNewCoi: 'awaitingNewCoi'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
const expiryStatuses = {
|
|
16
|
+
aboutToExpired: 'aboutToExpired',
|
|
17
|
+
expired: 'expired'
|
|
18
|
+
};
|
|
19
|
+
|
|
15
20
|
const isReaudit = (contractorId, context) => {
|
|
16
21
|
return auditApi.isReaudit(contractorId, context);
|
|
17
22
|
};
|
|
@@ -61,17 +66,34 @@ const getAuditMetadata = async (
|
|
|
61
66
|
return metadata;
|
|
62
67
|
};
|
|
63
68
|
|
|
64
|
-
const getAuditConfigByStatus = (status, { glPolicyNumber } = {}) => {
|
|
69
|
+
const getAuditConfigByStatus = (status, { expiryStatus, glPolicyNumber } = {}) => {
|
|
70
|
+
let config = {};
|
|
71
|
+
|
|
65
72
|
switch (status) {
|
|
66
73
|
case complianceStatuses.notCompliant:
|
|
67
74
|
case complianceStatuses.awaitingNewCoi:
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
75
|
+
case complianceStatuses.waived:
|
|
76
|
+
config = auditConfigs.getNotCompliantConfig({ glPolicyNumber });
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
config = auditConfigs.getCompliantAuditConfig({ glPolicyNumber });
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
expiryStatus && setExpiredByStatus(expiryStatus, config);
|
|
83
|
+
|
|
84
|
+
return config;
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const setExpiredByStatus = (expiryStatus, config) => {
|
|
88
|
+
switch (expiryStatus) {
|
|
89
|
+
case expiryStatuses.expired:
|
|
90
|
+
auditConfigs.setExpiredConfig(config);
|
|
91
|
+
break;
|
|
92
|
+
case expiryStatuses.aboutToExpired:
|
|
93
|
+
auditConfigs.setAboutExpiredConfig(config);
|
|
94
|
+
break;
|
|
73
95
|
default:
|
|
74
|
-
|
|
96
|
+
throw new Error(`Unknown expiry status: ${expiryStatus}`);
|
|
75
97
|
}
|
|
76
98
|
};
|
|
77
99
|
|
|
@@ -79,5 +101,6 @@ module.exports = {
|
|
|
79
101
|
getAuditMetadata,
|
|
80
102
|
isReaudit,
|
|
81
103
|
getAuditConfigByStatus,
|
|
82
|
-
complianceStatuses
|
|
104
|
+
complianceStatuses,
|
|
105
|
+
expiryStatuses
|
|
83
106
|
};
|
|
@@ -68,22 +68,30 @@ const getNotCompliantConfig = ({ glPolicyNumber } = {}) => {
|
|
|
68
68
|
|
|
69
69
|
const getAboutExpiredConfig = ({ glPolicyNumber } = {}) => {
|
|
70
70
|
const compliantConfig = getCompliantAuditConfig({ glPolicyNumber });
|
|
71
|
-
compliantConfig
|
|
71
|
+
setAboutExpiredConfig(compliantConfig);
|
|
72
72
|
return compliantConfig;
|
|
73
73
|
};
|
|
74
74
|
|
|
75
75
|
const getExpiredConfig = ({ glPolicyNumber } = {}) => {
|
|
76
76
|
const compliantConfig = getCompliantAuditConfig({ glPolicyNumber });
|
|
77
|
-
compliantConfig
|
|
77
|
+
setExpiredConfig(compliantConfig);
|
|
78
78
|
|
|
79
79
|
return compliantConfig;
|
|
80
80
|
};
|
|
81
81
|
|
|
82
|
+
const setAboutExpiredConfig = config =>
|
|
83
|
+
config[generalLiability][policyExpired] = `${getOneWeekAheadDate()}`;
|
|
84
|
+
|
|
85
|
+
const setExpiredConfig = config =>
|
|
86
|
+
config[generalLiability][policyExpired] = `${getOneWeekAgoDate()}`;
|
|
87
|
+
|
|
82
88
|
module.exports = {
|
|
83
89
|
getCompliantAuditConfig,
|
|
84
90
|
getNotCompliantConfig,
|
|
85
91
|
getAboutExpiredConfig,
|
|
86
92
|
getExpiredConfig,
|
|
93
|
+
setExpiredConfig,
|
|
94
|
+
setAboutExpiredConfig,
|
|
87
95
|
policySelections,
|
|
88
96
|
defaultPolicyDate: DEFAULT_POLICY_DATE,
|
|
89
97
|
defaultAMScore: DEFAULT_AM_SCORE,
|
|
@@ -48,14 +48,17 @@ const attributeNames = {
|
|
|
48
48
|
occur: 'Occur',
|
|
49
49
|
text: 'text',
|
|
50
50
|
limit: 'limit',
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
additionalInsuredEndorsement: 'Additional Insured Endorsement',
|
|
52
|
+
primaryNonContributoryProvision: 'Primary Non-Contributory Provision',
|
|
53
|
+
primaryNonContributoryEndorsement: 'Primary Non-Contributory Endorsement',
|
|
54
54
|
indemnityPeriod: 'Indemnity Period',
|
|
55
55
|
actualLossSustained: 'Actual Loss Sustained',
|
|
56
56
|
extraExpense: 'Extra Expense',
|
|
57
|
-
combinedSingleLimit: 'Combined Single Limit'
|
|
58
|
-
|
|
57
|
+
combinedSingleLimit: 'Combined Single Limit',
|
|
58
|
+
followsForm: 'Follows Form',
|
|
59
|
+
followFormEndorsement: 'Follow-Form Endorsement',
|
|
60
|
+
waiverOfSubrogation: 'Waiver of Subrogation',
|
|
61
|
+
waiverOfSubrogationEndorsement: 'Waiver of Subrogation Endorsement'
|
|
59
62
|
};
|
|
60
63
|
|
|
61
64
|
module.exports = {
|
|
@@ -9,15 +9,18 @@ const compliance = require('../../saas/internal-api/compliance');
|
|
|
9
9
|
const contractors = require('../../saas/internal-api/contractors');
|
|
10
10
|
const requests = require('../../saas/internal-api/requests');
|
|
11
11
|
|
|
12
|
-
const { complianceStatuses, getAuditConfigByStatus } = require('../../common/utils/complianceUtil');
|
|
12
|
+
const { complianceStatuses, getAuditConfigByStatus, expiryStatuses } = require('../../common/utils/complianceUtil');
|
|
13
13
|
const httpResponseStatusCodes = require('../../common/httpResponseStatusCodes.json');
|
|
14
14
|
const activationStatuses = require('../../common/consts/activationStatuses');
|
|
15
15
|
const timeUtils = require('../../common/utils/timeUtils');
|
|
16
16
|
const recordFlows = require('../../common/commonFlows/records/records');
|
|
17
|
+
const recordTypes = require('../../common/consts/recordTypes');
|
|
17
18
|
|
|
18
19
|
const filePath = path.join(__dirname, '../../resources/coi/coi.pdf');
|
|
19
20
|
|
|
20
|
-
const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirementId, context, { shouldSendNotificationToPM = false, recordConfig } = {}) => {
|
|
21
|
+
const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirementId, context, { expiryStatus, shouldSendNotificationToPM = false, recordConfig } = {}) => {
|
|
22
|
+
validateInsuranceAndExpiryStatus(status, expiryStatus);
|
|
23
|
+
|
|
21
24
|
const requestData = await requests.services.getOrCreateRequest(
|
|
22
25
|
context,
|
|
23
26
|
tabId,
|
|
@@ -39,6 +42,10 @@ const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirem
|
|
|
39
42
|
|
|
40
43
|
recordConfig && await recordFlows.editRequestAndRecordDetails(requestData, recordConfig, context);
|
|
41
44
|
|
|
45
|
+
if (status === complianceStatuses.awaitingCoi) {
|
|
46
|
+
return recordId;
|
|
47
|
+
}
|
|
48
|
+
|
|
42
49
|
const coiUpload = await coi.utils.uploadCoi(
|
|
43
50
|
recordId,
|
|
44
51
|
filePath,
|
|
@@ -56,7 +63,7 @@ const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirem
|
|
|
56
63
|
|
|
57
64
|
const auditorContext = await auth.services.getAuditorCookie();
|
|
58
65
|
|
|
59
|
-
const auditConfig = getAuditConfigByStatus(status);
|
|
66
|
+
const auditConfig = getAuditConfigByStatus(status, { expiryStatus });
|
|
60
67
|
|
|
61
68
|
let auditResponse, retries = 5;
|
|
62
69
|
do {
|
|
@@ -76,37 +83,60 @@ const prepareRecord = async (recordCompany, recordEmail, status, tabId, requirem
|
|
|
76
83
|
throw Error(`Failed to audit record ${recordCompany}\n${auditResponse}`);
|
|
77
84
|
}
|
|
78
85
|
|
|
86
|
+
if (status === complianceStatuses.waived) {
|
|
87
|
+
await waiveAllGaps(recordId, context);
|
|
88
|
+
} else if (status === complianceStatuses.awaitingNewCoi) {
|
|
89
|
+
await sendGaps(recordId, tabId, context);
|
|
90
|
+
}
|
|
91
|
+
|
|
79
92
|
return recordId;
|
|
80
93
|
};
|
|
81
94
|
|
|
82
|
-
const prepareCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig } = {}) => {
|
|
83
|
-
return prepareRecord(recordCompany, recordEmail, complianceStatuses.complaint, tabId, requirementId, context, { recordConfig });
|
|
95
|
+
const prepareCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig, expiryStatus } = {}) => {
|
|
96
|
+
return prepareRecord(recordCompany, recordEmail, complianceStatuses.complaint, tabId, requirementId, context, { recordConfig, expiryStatus });
|
|
84
97
|
};
|
|
85
98
|
|
|
86
|
-
const prepareNotCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { shouldSendNotificationToPM = false, recordConfig } = {}) => {
|
|
87
|
-
return prepareRecord(recordCompany, recordEmail, complianceStatuses.notCompliant, tabId, requirementId, context, { shouldSendNotificationToPM, recordConfig });
|
|
99
|
+
const prepareNotCompliantRecord = (recordCompany, recordEmail, tabId, requirementId, context, { shouldSendNotificationToPM = false, recordConfig, expiryStatus } = {}) => {
|
|
100
|
+
return prepareRecord(recordCompany, recordEmail, complianceStatuses.notCompliant, tabId, requirementId, context, { shouldSendNotificationToPM, recordConfig, expiryStatus });
|
|
88
101
|
};
|
|
89
102
|
|
|
90
|
-
const
|
|
91
|
-
|
|
103
|
+
const prepareWaivedRecord = async (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig, expiryStatus } = {}) => {
|
|
104
|
+
const recordId = await prepareRecord(recordCompany, recordEmail, complianceStatuses.notCompliant, tabId, requirementId, context, { recordConfig, expiryStatus });
|
|
105
|
+
await waiveAllGaps(recordId, context);
|
|
106
|
+
return recordId;
|
|
92
107
|
};
|
|
93
108
|
|
|
94
|
-
const
|
|
95
|
-
|
|
109
|
+
const prepareAwaitingNewCoiRecord = async (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig, expiryStatus, isNotResponsive = false } = {}) => {
|
|
110
|
+
const recordId = await prepareRecord(recordCompany, recordEmail, complianceStatuses.awaitingNewCoi, tabId, requirementId, context, { recordConfig, expiryStatus });
|
|
111
|
+
|
|
112
|
+
if (isNotResponsive) {
|
|
113
|
+
await makeRecordNotResponsive(recordId, context);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return recordId;
|
|
96
117
|
};
|
|
97
118
|
|
|
98
|
-
const
|
|
99
|
-
const recordId = await prepareRecord(recordCompany, recordEmail, complianceStatuses.
|
|
119
|
+
const prepareAwaitingCoiRecord = async (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig, isNotResponsive = false } = {}) => {
|
|
120
|
+
const recordId = await prepareRecord(recordCompany, recordEmail, complianceStatuses.awaitingCoi, tabId, requirementId, context, { recordConfig });
|
|
100
121
|
|
|
101
|
-
|
|
102
|
-
|
|
122
|
+
if (isNotResponsive) {
|
|
123
|
+
await makeRecordNotResponsive(recordId, context);
|
|
124
|
+
}
|
|
103
125
|
|
|
104
126
|
return recordId;
|
|
105
127
|
};
|
|
106
128
|
|
|
107
|
-
const
|
|
108
|
-
|
|
129
|
+
const prepareUnderReviewRecord = (recordCompany, recordEmail, tabId, requirementId, context, { recordConfig } = {}) => {
|
|
130
|
+
return prepareRecord(recordCompany, recordEmail, complianceStatuses.underReview, tabId, requirementId, context, { recordConfig });
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const makeRecordNotResponsive = async (recordId, context) => {
|
|
134
|
+
const { data: record } = await contractors.services.getContractorById(recordId, context);
|
|
135
|
+
const isTenant = record.recordType === recordTypes.TENANTS;
|
|
136
|
+
await recordFlows.makeRecordNotResponsive(recordId, context, { isTenant });
|
|
137
|
+
};
|
|
109
138
|
|
|
139
|
+
const sendGaps = async (recordId, tabId, context) => {
|
|
110
140
|
const { id: requestId } = await requests.services.getRequestFromTabByRecordId(recordId, tabId, context);
|
|
111
141
|
const recordVerificationModel = await contractors.services.getRecordVerificationModel(recordId, context);
|
|
112
142
|
const sendGapsResponse = await contractors.services.sendGaps(requestId, recordVerificationModel, context);
|
|
@@ -114,12 +144,39 @@ const prepareAwaitingNewCoiRecord = async (recordCompany, recordEmail, tabId, re
|
|
|
114
144
|
if (sendGapsResponse.status !== httpResponseStatusCodes.OK) {
|
|
115
145
|
throw Error(`Failed to send gaps to ${recordCompany}\n${sendGapsResponse}`);
|
|
116
146
|
}
|
|
147
|
+
};
|
|
117
148
|
|
|
118
|
-
|
|
149
|
+
const waiveAllGaps = async (recordId, context) => {
|
|
150
|
+
const { data: record } = await contractors.services.getContractorById(recordId, context);
|
|
151
|
+
await compliance.services.overrideGap.waiveAll(record, context);
|
|
119
152
|
};
|
|
120
|
-
|
|
121
|
-
|
|
153
|
+
|
|
154
|
+
const validateInsuranceAndExpiryStatus = async (insuranceStatus, expiryStatus) => {
|
|
155
|
+
let isValid = false;
|
|
156
|
+
const isWithoutExpiryStatus = Boolean(expiryStatus);
|
|
157
|
+
|
|
158
|
+
switch (insuranceStatus) {
|
|
159
|
+
case complianceStatuses.complaint:
|
|
160
|
+
case complianceStatuses.waived:
|
|
161
|
+
isValid = isWithoutExpiryStatus || expiryStatus === expiryStatuses.aboutToExpired ;
|
|
162
|
+
break;
|
|
163
|
+
case complianceStatuses.awaitingNewCoi:
|
|
164
|
+
case complianceStatuses.notCompliant:
|
|
165
|
+
isValid = isWithoutExpiryStatus || Object.values(expiryStatuses).includes(expiryStatus) ;
|
|
166
|
+
break;
|
|
167
|
+
case complianceStatuses.awaitingCoi:
|
|
168
|
+
case complianceStatuses.underReview:
|
|
169
|
+
isValid = true;
|
|
170
|
+
break;
|
|
171
|
+
default:
|
|
172
|
+
throw new Error(`Invalid insurance status: ${insuranceStatus}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (!isValid) {
|
|
176
|
+
throw new Error(`Invalid insurance and expiry status combination: insuranceStatus=${insuranceStatus}, expiryStatus=${expiryStatus}`);
|
|
177
|
+
}
|
|
122
178
|
};
|
|
179
|
+
|
|
123
180
|
const prepareDraftRecord = async (recordCompany, tabId, context, { recordEmail, requirementId, uploadCoi, recordConfig } = {}) => {
|
|
124
181
|
const requestData = await requests.services.getOrCreateRequest(
|
|
125
182
|
context,
|
|
@@ -160,10 +217,9 @@ const prepareDraftRecord = async (recordCompany, tabId, context, { recordEmail,
|
|
|
160
217
|
module.exports = {
|
|
161
218
|
prepareCompliantRecord,
|
|
162
219
|
prepareNotCompliantRecord,
|
|
163
|
-
prepareExpiredRecord,
|
|
164
220
|
prepareWaivedRecord,
|
|
165
|
-
prepareAboutToExpiredRecord,
|
|
166
221
|
prepareAwaitingNewCoiRecord,
|
|
167
222
|
prepareUnderReviewRecord,
|
|
223
|
+
prepareAwaitingCoiRecord,
|
|
168
224
|
prepareDraftRecord
|
|
169
225
|
};
|
|
@@ -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
|
+
getRecordOcrStatus: contractorId => `${backendUrl}/saas/contractor/${contractorId}/ocr/status`,
|
|
10
11
|
delete: contractorId => `${backendUrl}/saas/contractor/${contractorId}`,
|
|
11
12
|
archive: contractorId => `${backendUrl}/saas/contractor/${contractorId}/archive`,
|
|
12
13
|
restore: contractorId => `${backendUrl}/saas/contractor/${contractorId}/restore`,
|
|
@@ -17,6 +18,8 @@ const Endpoints = {
|
|
|
17
18
|
requestNewCoiExpired: requestId => `${backendUrl}/saas/coi/${requestId}/expired`,
|
|
18
19
|
muteNotifications: `${backendUrl}/saas/record/notifications/mute`,
|
|
19
20
|
unmuteNotifications: `${backendUrl}/saas/record/notifications/unmute`,
|
|
21
|
+
unsubscribe: `${backendUrl}/record/email/unsubscribe`,
|
|
22
|
+
subscribe: `${backendUrl}/record/email/subscribe`,
|
|
20
23
|
changeRequirement: `${backendUrl}/saas/contractor/requirement`,
|
|
21
24
|
updateVendorExpiryDate: contractorId => `${backendUrl}/_saas/automation/contractor/${contractorId}/expiry-date`,
|
|
22
25
|
updateContractorInviteDate: contractorId => `${backendUrl}/_saas/automation/contractor/${contractorId}/invite-date`,
|
|
@@ -44,6 +47,10 @@ const getRecordHistory = (contractorId, context) => {
|
|
|
44
47
|
return requests.getRequestHandler(Endpoints.getRecordHistory(contractorId), {}, context);
|
|
45
48
|
};
|
|
46
49
|
|
|
50
|
+
const getRecordOcrStatus = (contractorId, context) => {
|
|
51
|
+
return requests.getRequestHandler(Endpoints.getRecordOcrStatus(contractorId), {}, context);
|
|
52
|
+
};
|
|
53
|
+
|
|
47
54
|
const deleteByContractorId = (contractorId, context) => {
|
|
48
55
|
return requests.deleteRequestHandler(Endpoints.delete(contractorId), context);
|
|
49
56
|
};
|
|
@@ -70,6 +77,14 @@ const unmuteNotifications = (recordModifyDateVerificationModel, context) => {
|
|
|
70
77
|
return requests.postRequestHandler(Endpoints.unmuteNotifications, recordModifyDateVerificationModel, context);
|
|
71
78
|
};
|
|
72
79
|
|
|
80
|
+
const unsubscribe = subscriptionModel => {
|
|
81
|
+
return requests.postRequestHandler(Endpoints.unsubscribe, subscriptionModel);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const subscribe = subscriptionModel => {
|
|
85
|
+
return requests.postRequestHandler(Endpoints.subscribe, subscriptionModel);
|
|
86
|
+
};
|
|
87
|
+
|
|
73
88
|
const changeRequirement = (recordModifyDateVerificationModel, context) => {
|
|
74
89
|
return requests.putRequestHandler(Endpoints.changeRequirement, recordModifyDateVerificationModel, context);
|
|
75
90
|
};
|
|
@@ -161,6 +176,7 @@ module.exports = {
|
|
|
161
176
|
getContractorsByAccountId,
|
|
162
177
|
getContractorById,
|
|
163
178
|
getRecordHistory,
|
|
179
|
+
getRecordOcrStatus,
|
|
164
180
|
deleteByContractorId,
|
|
165
181
|
archiveRecord,
|
|
166
182
|
restoreRecord,
|
|
@@ -176,6 +192,8 @@ module.exports = {
|
|
|
176
192
|
resendInvitation,
|
|
177
193
|
muteNotifications,
|
|
178
194
|
unmuteNotifications,
|
|
195
|
+
unsubscribe,
|
|
196
|
+
subscribe,
|
|
179
197
|
getLinkedProjectsCount,
|
|
180
198
|
updateLastInviteActionDate,
|
|
181
199
|
getInviteLinkStatus,
|
|
@@ -5,6 +5,7 @@ const { RecordModifyDateVerificationModel } = require('../models/verification.co
|
|
|
5
5
|
const { AssignRequirementModel } = require('../models/assign.requirement.model');
|
|
6
6
|
const { ContractorDetailsModel } = require('../models/edit.contractor.model');
|
|
7
7
|
const { LinkRequestModel } = require('../models/link.request.model');
|
|
8
|
+
const { SubscriptionModel } = require('../models/subscription.contractor.model');
|
|
8
9
|
const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
|
|
9
10
|
const { waitFor } = require('../../../../common/utils/timeUtils');
|
|
10
11
|
const activationStatuses = require('../../../../common/consts/activationStatuses');
|
|
@@ -26,6 +27,10 @@ const getRecordHistory = (contractorId, context) => {
|
|
|
26
27
|
return contractorsAPI.getRecordHistory(contractorId, context);
|
|
27
28
|
};
|
|
28
29
|
|
|
30
|
+
const getRecordOcrStatus = (recordId, context) => {
|
|
31
|
+
return contractorsAPI.getRecordOcrStatus(recordId, context);
|
|
32
|
+
};
|
|
33
|
+
|
|
29
34
|
const archiveRecord = (recordVerificationModel, context) => {
|
|
30
35
|
validateType(recordVerificationModel, RecordModifyDateVerificationModel);
|
|
31
36
|
return contractorsAPI.archiveRecord(recordVerificationModel, context);
|
|
@@ -100,11 +105,59 @@ const muteNotifications = (recordModifyDateVerificationModel, context) => {
|
|
|
100
105
|
return contractorsAPI.muteNotifications(recordModifyDateVerificationModel, context);
|
|
101
106
|
};
|
|
102
107
|
|
|
108
|
+
const muteNotificationsByRecordId = async (recordId, context) => {
|
|
109
|
+
const recordModifyDateVerificationModel = await getRecordVerificationModel(recordId, context);
|
|
110
|
+
const muteResponse = await contractorsAPI.muteNotifications(recordModifyDateVerificationModel, context);
|
|
111
|
+
|
|
112
|
+
if (muteResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
|
|
113
|
+
throw new Error(`Failed to mute record: ${muteResponse.statusText}`);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return muteResponse;
|
|
117
|
+
};
|
|
118
|
+
|
|
103
119
|
const unmuteNotifications = (recordModifyDateVerificationModel, context) => {
|
|
104
120
|
validateType(recordModifyDateVerificationModel, RecordModifyDateVerificationModel);
|
|
105
121
|
return contractorsAPI.unmuteNotifications(recordModifyDateVerificationModel, context);
|
|
106
122
|
};
|
|
107
123
|
|
|
124
|
+
const unmuteNotificationsByRecordId = async (recordId, context) => {
|
|
125
|
+
const recordModifyDateVerificationModel = await getRecordVerificationModel(recordId, context);
|
|
126
|
+
const unmuteResponse = await contractorsAPI.unmuteNotifications(recordModifyDateVerificationModel, context);
|
|
127
|
+
|
|
128
|
+
if (unmuteResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
|
|
129
|
+
throw new Error(`Failed to unmute record: ${unmuteResponse.statusText}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return unmuteResponse;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const unsubscribe = async (subscriptionModel, { expectError } = {}) => {
|
|
136
|
+
validateType(subscriptionModel, SubscriptionModel);
|
|
137
|
+
const unsubscribeResponse = await contractorsAPI.unsubscribe(subscriptionModel);
|
|
138
|
+
|
|
139
|
+
if (unsubscribeResponse.status !== httpResponseStatusCodes.OK && !expectError) {
|
|
140
|
+
throw new Error(`Failed to unsubscribe record: ${unsubscribeResponse.statusText}`);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return unsubscribeResponse;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const subscribe = async (subscriptionModel, { expectError } = {}) => {
|
|
147
|
+
validateType(subscriptionModel, SubscriptionModel);
|
|
148
|
+
const subscribeResponse = await contractorsAPI.subscribe(subscriptionModel);
|
|
149
|
+
|
|
150
|
+
if (subscribeResponse.status !== httpResponseStatusCodes.OK && !expectError) {
|
|
151
|
+
throw new Error(`Failed to subscribe record: ${subscribeResponse.statusText}`);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return subscribeResponse;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const getSubscriptionModel = (data, { recaptchaResponse = 'recaptchaResponse' } = {}) => {
|
|
158
|
+
return new SubscriptionModel(data, recaptchaResponse);
|
|
159
|
+
};
|
|
160
|
+
|
|
108
161
|
const deleteByContractorId = (contractorId, context) => {
|
|
109
162
|
return contractorsAPI.deleteByContractorId(contractorId, context);
|
|
110
163
|
};
|
|
@@ -226,6 +279,7 @@ module.exports = {
|
|
|
226
279
|
getContractorsByAccountId,
|
|
227
280
|
getContractorById,
|
|
228
281
|
getRecordHistory,
|
|
282
|
+
getRecordOcrStatus,
|
|
229
283
|
archiveRecord,
|
|
230
284
|
restoreRecord,
|
|
231
285
|
editContractor,
|
|
@@ -239,7 +293,12 @@ module.exports = {
|
|
|
239
293
|
requestNewCoiExpired,
|
|
240
294
|
resendInvitation,
|
|
241
295
|
muteNotifications,
|
|
296
|
+
muteNotificationsByRecordId,
|
|
242
297
|
unmuteNotifications,
|
|
298
|
+
unmuteNotificationsByRecordId,
|
|
299
|
+
unsubscribe,
|
|
300
|
+
subscribe,
|
|
301
|
+
getSubscriptionModel,
|
|
243
302
|
deleteByContractorId,
|
|
244
303
|
deleteAllRecordsInAccount,
|
|
245
304
|
deleteAllActiveRecordsInAccount,
|
|
@@ -137,11 +137,20 @@ const waitForMail = async (emailModel, { maxSecondToWait = 30 } = {}) => {
|
|
|
137
137
|
return foundMails;
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
+
const getSubscriptionData = async function(recipients) {
|
|
141
|
+
const regex = util.getUnsubscribeButtonUrlRegex();
|
|
142
|
+
const unsubscribeButtonUrl = await getLastMessage({ recipients, regex, returnType: 'url' });
|
|
143
|
+
|
|
144
|
+
const data = util.getEncryptedDataFromLink(unsubscribeButtonUrl);
|
|
145
|
+
return decodeURIComponent(data);
|
|
146
|
+
};
|
|
147
|
+
|
|
140
148
|
module.exports = {
|
|
141
149
|
util,
|
|
142
150
|
waitForMail,
|
|
143
151
|
getAllMessages,
|
|
144
152
|
getLastMessage,
|
|
153
|
+
getSubscriptionData,
|
|
145
154
|
deleteMultipleMessages,
|
|
146
155
|
deleteAllMessages
|
|
147
156
|
};
|
|
@@ -66,9 +66,13 @@ const getMailActionButtonUrlRegex = () => {
|
|
|
66
66
|
return /(https:\/\/[a-zA-Z0-9.].*[a-zA-Z.]+\/CheckCustomersInviteLinkJSON\?data=[^"]+)/g;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
const
|
|
69
|
+
const getUnsubscribeButtonUrlRegex = () => {
|
|
70
|
+
return /(\/[a-zA-Z0-9.].*[a-zA-Z.]+\/vendor-app\/email\/unsubscribe\?data=[^"]+)/g;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const getEncryptedDataFromLink = (link, { removeLastTwoCharts } = {}) => {
|
|
70
74
|
const encryptedData = link.split('data=').pop();
|
|
71
|
-
return encryptedData.slice(0, -2);
|
|
75
|
+
return removeLastTwoCharts ? encryptedData.slice(0, -2) : encryptedData;
|
|
72
76
|
};
|
|
73
77
|
|
|
74
78
|
module.exports = {
|
|
@@ -78,5 +82,6 @@ module.exports = {
|
|
|
78
82
|
logRetrievedEmailInfo,
|
|
79
83
|
getEmailTextInSubject,
|
|
80
84
|
getMailActionButtonUrlRegex,
|
|
85
|
+
getUnsubscribeButtonUrlRegex,
|
|
81
86
|
getEncryptedDataFromLink
|
|
82
87
|
};
|