@getjones/test-infra 1.9.0 → 1.12.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.
Files changed (33) hide show
  1. package/package.json +1 -1
  2. package/src/common/factory/index.js +3 -0
  3. package/src/common/factory/records/records.js +71 -0
  4. package/src/common/utils/timeUtils.js +162 -0
  5. package/src/env.js +2 -1
  6. package/src/index.js +5 -3
  7. package/src/saas/internal-api/contractors/api/contractors.api.js +2 -21
  8. package/src/saas/internal-api/contractors/api/contractors.service.js +1 -13
  9. package/src/saas/internal-api/contractors/models/create.contractor.model.js +2 -2
  10. package/src/saas/internal-api/contractors/models/edit.contractor.model.js +5 -22
  11. package/src/saas/internal-api/contractors/models/verification.contractor.model.js +4 -10
  12. package/src/saas/internal-api/dbEmails/api/db.emails.api.js +25 -0
  13. package/src/saas/internal-api/dbEmails/api/db.emails.service.js +127 -0
  14. package/src/saas/internal-api/dbEmails/consts/consts.js +3 -0
  15. package/src/saas/internal-api/dbEmails/index.js +4 -0
  16. package/src/saas/internal-api/dbEmails/models/db.emails.model.js +21 -0
  17. package/src/saas/internal-api/dbEmails/utils/util.js +59 -0
  18. package/src/saas/internal-api/globalRecord/api/global.record.api.js +4 -4
  19. package/src/saas/internal-api/globalRecord/api/global.record.service.js +3 -3
  20. package/src/saas/internal-api/requests/api/requests.api.js +9 -2
  21. package/src/saas/internal-api/requests/api/requests.service.js +6 -1
  22. package/src/saas/internal-api/requests/index.js +7 -1
  23. package/src/saas/internal-api/requests/models/tenant.request.model.js +9 -0
  24. package/src/saas/internal-api/users/api/users.api.js +2 -3
  25. package/src/saas/internal-api/users/api/users.service.js +2 -2
  26. package/src/saas/openapi/requests/index.js +6 -0
  27. package/src/saas/openapi/{contractors/models/invite.contractor.model.js → requests/models/invite.request.model.js} +2 -2
  28. package/src/saas/openapi/requests/requests.api.js +20 -0
  29. package/src/saas/openapi/requests/requests.service.js +18 -0
  30. package/src/common/utils/dateUtils.js +0 -6
  31. package/src/saas/openapi/contractors/contractors.api.js +0 -20
  32. package/src/saas/openapi/contractors/contractors.service.js +0 -18
  33. package/src/saas/openapi/contractors/index.js +0 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getjones/test-infra",
3
- "version": "1.9.0",
3
+ "version": "1.12.0",
4
4
  "description": "Providing internal and openapi interface",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -0,0 +1,3 @@
1
+ const records = require('./records/records');
2
+
3
+ module.exports = { records };
@@ -0,0 +1,71 @@
1
+ const { expect } = require('chai');
2
+
3
+ const threadScheduler = require('../../../saas/internal-api/thread-scheduler/runner');
4
+ const timeUtils = require('../../utils/timeUtils');
5
+ const httpResponseStatusCodes = require('../../../common/httpResponseStatusCodes.json');
6
+ const contractors = require('../../../saas/internal-api/contractors');
7
+
8
+ const makeRecordNotResponsive = async function(recordId, context, { isTenant } = {}) {
9
+ const dates = isTenant ?
10
+ timeUtils.getInvitationDatesForNotResponsiveTenant() :
11
+ timeUtils.getInvitationDatesForNotResponsiveVendor();
12
+
13
+ for (const date of dates) {
14
+ await updateInviteDate(recordId, date, context);
15
+ }
16
+ };
17
+
18
+ const updateInviteDate = async function(recordId, inviteDate, context) {
19
+ const updateResponse = await contractors.services.updateInviteDate(recordId, inviteDate, context);
20
+
21
+ if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
22
+ throw new Error('Record invite date could not be updated', updateResponse);
23
+ }
24
+
25
+ const threadSchedulerResponse = await threadScheduler.runThreadScheduler({ contractorIds: [recordId] });
26
+
27
+ if (threadSchedulerResponse.status !== httpResponseStatusCodes.OK) {
28
+ throw new Error('Thread scheduler has failed to run', threadSchedulerResponse);
29
+ }
30
+
31
+ await timeUtils.waitFor(2.5).seconds; // calls for the same records can override each other
32
+ };
33
+
34
+ const runOverAllRenewalDatesForRecord = async function(recordId, policyName) {
35
+ const dates = timeUtils.getAutomaticRenewalsExpirationDates();
36
+
37
+ for (const date of dates) {
38
+ await updatePolicyExpiryDateForRecord(recordId, date, policyName);
39
+ }
40
+ };
41
+
42
+ const updatePolicyExpiryDateForRecord = async function(recordId, expiryDate, policyName) {
43
+ const updateResponse = await contractors.services.updateExpiryDate(recordId, expiryDate, policyName);
44
+
45
+ if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
46
+ throw new Error('Record expiry date could not be updated', updateResponse);
47
+ }
48
+
49
+ const threadSchedulerResponse = await threadScheduler.runThreadScheduler({ contractorIds: [recordId] });
50
+
51
+ if (threadSchedulerResponse.status !== httpResponseStatusCodes.OK) {
52
+ throw new Error('Thread scheduler has failed to run', threadSchedulerResponse);
53
+ }
54
+
55
+ await timeUtils.waitFor(2.5).seconds; // calls for the same records can override each other
56
+ };
57
+
58
+ const getHistoryEvents = async function(recordId, context) {
59
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
60
+ expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
61
+
62
+ return recordHistory.data.map(item => item.itemTitle).reverse();
63
+ };
64
+
65
+ module.exports = {
66
+ makeRecordNotResponsive,
67
+ runOverAllRenewalDatesForRecord,
68
+ updateInviteDate,
69
+ updatePolicyExpiryDateForRecord,
70
+ getHistoryEvents
71
+ };
@@ -0,0 +1,162 @@
1
+ const moment = require('moment');
2
+
3
+ const secondsInDay = 86400;
4
+ const millisecondsToSeconds = 1000;
5
+ const formats = {
6
+ logTimeStampFormat: 'YYYY-MM-DD hh:mm:ss',
7
+ dayMonthYear: 'DD/MM/YYYY',
8
+ numericMonthDayYear: 'MM/DD/YYYY',
9
+ monthDayYear: 'MMM DD, YYYY',
10
+ monthDayYear_noZeroPrefix: 'MMM D, YYYY',
11
+ dateTime: 'YYYY/MM/DD-hh:mm:ss',
12
+ fullMonthDayYear: 'MMMM DD, YYYY',
13
+ threadScheduler: '', // Passing empty string resolves moment.js format to ISO8601 standard like 2020-04-12T09:49:59Z;
14
+ monthDayYear12hTime: 'MMM D, YYYY h:mm A',
15
+ amPmTime: 'h:mm A'
16
+ };
17
+
18
+ const peroids = {
19
+ days: 'days',
20
+ months: 'months',
21
+ years: 'years'
22
+ };
23
+
24
+ const getOneYearAgoDate = format => moment().utc().subtract(1, peroids.years).format(format || formats.threadScheduler);
25
+ const getSixMonthAgoDate = format => moment().utc().subtract(6, peroids.months).format(format || formats.threadScheduler);
26
+ const getOneMonthAgoDate = format => moment().utc().subtract(1, peroids.months).format(format || formats.threadScheduler);
27
+ const getFifteenDaysAgoDate = format => moment().utc().subtract(15, peroids.days).format(format || formats.threadScheduler);
28
+ const getTenDaysAgoDate = format => moment().utc().subtract(10, peroids.days).format(format || formats.threadScheduler);
29
+ const getEightDaysAgoDate = format => moment().utc().subtract(8, peroids.days).format(format || formats.threadScheduler);
30
+ const getFiveDaysAgoDate = format => moment().utc().subtract(5, peroids.days).format(format || formats.threadScheduler);
31
+ const getTwoDaysAgoDate = format => moment().utc().subtract(2, peroids.days).format(format || formats.threadScheduler);
32
+ const getOneDayAgoDate = format => moment().utc().subtract(1, peroids.days).format(format || formats.threadScheduler);
33
+ const getThirtyFiveDaysAgoDate = format => moment().utc().subtract(35, peroids.days).format(format || formats.threadScheduler);
34
+ const getCurrentDate = format => moment().utc().format(format || formats.threadScheduler);
35
+ const getDateInOneDay = format => moment().utc().add(1, peroids.days).format(format || formats.threadScheduler);
36
+ const getDateinSixDays = format => moment().utc().add(6, peroids.days).format(format || formats.threadScheduler);
37
+ const getDateinThirteenDays = format => moment().utc().add(13, peroids.days).format(format || formats.threadScheduler);
38
+ const getDateinTwentyNineDays = format => moment().utc().add(29, peroids.days).format(format || formats.threadScheduler);
39
+
40
+ const getLogTimestamp = () => {
41
+ return moment().format(formats.logTimeStampFormat);
42
+ };
43
+
44
+ const getCurrentFormattedDate = () => {
45
+ return new Date().toISOString();
46
+ };
47
+
48
+ const getDateWithOffset = (date, offsetInDays) => {
49
+ date.setDate(date.getDate() + offsetInDays);
50
+ return date;
51
+ };
52
+
53
+ const getAuditDateFormat = date => {
54
+ const year = date.getUTCFullYear();
55
+ const month = date.getUTCMonth() + 1; //getMonth is zero-based
56
+ const day = date.getUTCDate();
57
+
58
+ return `${month}/${day}/${year}`;
59
+ };
60
+
61
+ const getYearMonthDayFormat = date => {
62
+ const year = date.getUTCFullYear();
63
+ const month = String(date.getUTCMonth() + 1).length === 1 ? `0${(date.getUTCMonth() + 1)}` : (date.getUTCMonth() + 1);
64
+ const day = String(date.getUTCDate()).length === 1 ? `0${date.getUTCDate()}` : date.getUTCDate();
65
+
66
+ return `${year}-${month}-${day}`;
67
+ };
68
+
69
+ const dateToIsoFormat = date => {
70
+ return new Date(date).toISOString();
71
+ };
72
+
73
+ const extractDateFromDateTime = date => {
74
+ let extractedDate = date;
75
+
76
+ if (date != null && date.length > 10) {
77
+ extractedDate = date.substr(0, 10);
78
+ }
79
+
80
+ return extractedDate;
81
+ };
82
+
83
+ function waitFor(num) {
84
+ return {
85
+ mSeconds: new Promise(resolve => {
86
+ setTimeout(resolve, num);
87
+ }),
88
+ seconds: new Promise(resolve => {
89
+ setTimeout(resolve, num * 1000);
90
+ })
91
+ };
92
+ }
93
+
94
+ function getDayInMilliseconds() {
95
+ return secondsInDay * millisecondsToSeconds;
96
+ }
97
+
98
+ function getPreviousDateByDays(days) {
99
+ return new Date(new Date().getTime() - getDayInMilliseconds() * days);
100
+ }
101
+
102
+ const getInvitationDatesForNotResponsiveVendor = function() {
103
+ const twoDaysAgoUtc = getTwoDaysAgoDate();
104
+ const fiveDaysAgoUtc = getFiveDaysAgoDate();
105
+ const eightDaysAgoUtc = getEightDaysAgoDate();
106
+
107
+ return [twoDaysAgoUtc, fiveDaysAgoUtc, eightDaysAgoUtc];
108
+ };
109
+
110
+ const getInvitationDatesForNotResponsiveTenant = function() {
111
+ const fiveDaysAgoUtc = getFiveDaysAgoDate();
112
+ const tenDaysAgoUtc = getTenDaysAgoDate();
113
+ const fifteenDaysAgoUtc = getFifteenDaysAgoDate();
114
+
115
+ return [fiveDaysAgoUtc, tenDaysAgoUtc, fifteenDaysAgoUtc];
116
+ };
117
+
118
+ const isDateAfterOther = (date, other) => {
119
+ return moment(date).isAfter(other);
120
+ };
121
+
122
+ const getAutomaticRenewalsExpirationDates = function() {
123
+ const inTwentyNineDaysUtc = getDateinTwentyNineDays();
124
+ const inThirteenDaysUtc = getDateinThirteenDays();
125
+ const inSixDaysUtc = getDateinSixDays();
126
+ const todayUtc = getCurrentDate();
127
+
128
+ return [inTwentyNineDaysUtc, inThirteenDaysUtc, inSixDaysUtc, todayUtc];
129
+ };
130
+
131
+ module.exports = {
132
+ formats,
133
+ getOneYearAgoDate,
134
+ getSixMonthAgoDate,
135
+ getOneMonthAgoDate,
136
+ getFifteenDaysAgoDate,
137
+ getTenDaysAgoDate,
138
+ getEightDaysAgoDate,
139
+ getFiveDaysAgoDate,
140
+ getTwoDaysAgoDate,
141
+ getOneDayAgoDate,
142
+ getThirtyFiveDaysAgoDate,
143
+ getCurrentDate,
144
+ getDateInOneDay,
145
+ getDateinSixDays,
146
+ getDateinThirteenDays,
147
+ getDateinTwentyNineDays,
148
+ getInvitationDatesForNotResponsiveVendor,
149
+ getInvitationDatesForNotResponsiveTenant,
150
+ getAutomaticRenewalsExpirationDates,
151
+ getLogTimestamp,
152
+ getCurrentFormattedDate,
153
+ getAuditDateFormat,
154
+ getDateWithOffset,
155
+ getYearMonthDayFormat,
156
+ dateToIsoFormat,
157
+ getDayInMilliseconds,
158
+ extractDateFromDateTime,
159
+ getPreviousDateByDays,
160
+ waitFor,
161
+ isDateAfterOther
162
+ };
package/src/env.js CHANGED
@@ -6,7 +6,8 @@ let privateMembers = {
6
6
  environment: null,
7
7
  accountCreationSecret: null,
8
8
  threadSchedulerSecret: null,
9
- nodeBackendSecret: null
9
+ nodeBackendSecret: null,
10
+ dbEmailsSecrets: null
10
11
  };
11
12
 
12
13
  const init = conf => {
package/src/index.js CHANGED
@@ -31,6 +31,7 @@ const getInternalAPI = () => {
31
31
  const serviceArea = require('./saas/internal-api/serviceArea');
32
32
 
33
33
  const threadScheduler = require('./saas/internal-api/thread-scheduler/runner');
34
+ const dbEmails = require('./saas/internal-api/dbEmails/index');
34
35
 
35
36
  const internalAPI = {
36
37
  auth,
@@ -48,7 +49,8 @@ const getInternalAPI = () => {
48
49
  globalRecord,
49
50
  vendorProfile,
50
51
  serviceArea,
51
- threadScheduler
52
+ threadScheduler,
53
+ dbEmails
52
54
  };
53
55
 
54
56
  return internalAPI;
@@ -57,10 +59,10 @@ const getInternalAPI = () => {
57
59
  const getOpenAPI = () => {
58
60
  const accounts = require('./saas/openapi/accounts/accounts.service');
59
61
  const tabs = require('./saas/openapi/tabs/tabs.service');
60
- const contractors = require('./saas/openapi/contractors');
62
+ const requests = require('./saas/openapi/requests');
61
63
  const projects = require('./saas/openapi/projects/projects.service');
62
64
  const requirements = require('./saas/openapi/requirements');
63
- const openAPI = { accounts, tabs, contractors, projects, requirements };
65
+ const openAPI = { accounts, tabs, requests, projects, requirements };
64
66
  return openAPI;
65
67
  };
66
68
 
@@ -19,11 +19,8 @@ const Endpoints = {
19
19
  changeRequirement: `${backendUrl}/saas/contractor/requirement`,
20
20
  updateVendorExpiryDate: contractorId => `${backendUrl}/_saas/automation/contractor/${contractorId}/expiry-date`,
21
21
  updateContractorInviteDate: contractorId => `${backendUrl}/_saas/automation/contractor/${contractorId}/invite-date`,
22
- assignMptToProperties: (accountId, tenantId) => `${backendUrl}/saas/account/${accountId}/multi-properties/${tenantId}`,
23
22
  searchInAutocomplete: ({ tabId, searchWord }) =>
24
23
  `${backendUrl}/saas/contractors/search/audited?&tabId=${tabId}&searchWord=${searchWord}`,
25
- requestsGlobalSearch: (projectId, searchWord) =>
26
- `${backendUrl}/saas/contractors/search?&projectId=${projectId}&searchWord=${searchWord}`,
27
24
  automationUpdateContractorUploadDate: contractorId => `${backendUrl}/saas/automation/contractor/${contractorId}/upload-date`,
28
25
  publicLinkInvite: `${backendUrl}/_saas/contractors/publicinvite`
29
26
  };
@@ -86,7 +83,8 @@ const requestNewCoiExpired = (recordModifyDateVerificationModel, context) => {
86
83
  };
87
84
 
88
85
  const resendInvitation = (recordModifyDateVerificationModel, context) => {
89
- return requests.postRequestHandler(Endpoints.resendInvitation, recordModifyDateVerificationModel, context);
86
+ const recordId = recordModifyDateVerificationModel.contractorId;
87
+ return requests.postRequestHandler(Endpoints.resendInvitation(recordId), recordModifyDateVerificationModel, context);
90
88
  };
91
89
 
92
90
  const updateExpiryDate = (contractorId, expiryDate, policyName) => {
@@ -99,17 +97,6 @@ const updateInviteDate = (contractorId, inviteDate, context) => {
99
97
  return requests.postRequestHandler(Endpoints.updateContractorInviteDate(contractorId), data, context);
100
98
  };
101
99
 
102
- const assignMptToProperties = (assignToMptModel, context) => {
103
- const params = { updateInfoUser: 'EditVendor' };
104
- return requests.postRequestHandler(
105
- Endpoints.assignMptToProperties(assignToMptModel.accountId, assignToMptModel.tenantId),
106
- assignToMptModel.properties,
107
- context,
108
- {},
109
- params
110
- );
111
- };
112
-
113
100
  const getContractorsByTabId = async (tabId, context, activityStatus) => {
114
101
  const body = { tabId, activityStatus };
115
102
  const response = await requests.postRequestHandler(Endpoints.get, body, context);
@@ -125,10 +112,6 @@ const searchInAutocomplete = ({ tabId, searchWord }, context) => {
125
112
  return requests.getRequestHandler(Endpoints.searchInAutocomplete({ tabId, searchWord }), {}, context);
126
113
  };
127
114
 
128
- const searchInGlobalSearch = (projectId, searchWord, context) => {
129
- return requests.getRequestHandler(Endpoints.requestsGlobalSearch(projectId, searchWord), {}, context);
130
- };
131
-
132
115
  const updateContractorUploadDate = (contractorId, uploadDate, context) => {
133
116
  const url = `${Endpoints.automationUpdateContractorUploadDate(contractorId) }?uploadDate=${uploadDate.toISOString()}`;
134
117
  return requests.patchRequestHandler(url, context);
@@ -150,10 +133,8 @@ module.exports = {
150
133
  editContractor,
151
134
  updateInviteDate,
152
135
  updateExpiryDate,
153
- assignMptToProperties,
154
136
  getContractorsByTabId,
155
137
  searchInAutocomplete,
156
- searchInGlobalSearch,
157
138
  updateContractorUploadDate,
158
139
  inviteContractorViaPublicLink,
159
140
  sendGaps,
@@ -1,6 +1,6 @@
1
1
  const contractorsAPI = require('./contractors.api');
2
2
  const { CreateContractorModel } = require('../models/create.contractor.model');
3
- const { ContractorModel, MptModel } = require('../models/edit.contractor.model');
3
+ const { ContractorModel } = require('../models/edit.contractor.model');
4
4
  const { validateType } = require('../../../../common/validations/typeValidations');
5
5
  const { RecordModifyDateVerificationModel } = require('../models/verification.contractor.model');
6
6
 
@@ -48,7 +48,6 @@ const updateExpiryDate = (contractorId, expiryDate, policyName) => {
48
48
  };
49
49
 
50
50
  const updateInviteDate = (contractorId, inviteDate, context) => {
51
- validateType(inviteDate, Date);
52
51
  return contractorsAPI.updateInviteDate(contractorId, inviteDate, context);
53
52
  };
54
53
 
@@ -56,19 +55,10 @@ const getContractorsByTabId = (tabId, context, activityStatus = 'ACTIVE') => {
56
55
  return contractorsAPI.getContractorsByTabId(tabId, context, activityStatus);
57
56
  };
58
57
 
59
- const assignMptToProperties = (assignToMptModel, context) => {
60
- validateType(assignToMptModel, MptModel);
61
- return contractorsAPI.assignMptToProperties(assignToMptModel, context);
62
- };
63
-
64
58
  const searchInAutoComplete = ({ tabId, searchWord }, context) => {
65
59
  return contractorsAPI.searchInAutocomplete({ tabId, searchWord }, context);
66
60
  };
67
61
 
68
- const searchInGlobalSearch = (projectId, searchWord, context) => {
69
- return contractorsAPI.searchInGlobalSearch(projectId, searchWord, context);
70
- };
71
-
72
62
  const updateContractorUploadDate = (contractorId, uploadDate, context) => {
73
63
  validateType(uploadDate, Date);
74
64
  return contractorsAPI.updateContractorUploadDate(contractorId, uploadDate, context);
@@ -127,9 +117,7 @@ module.exports = {
127
117
  updateInviteDate,
128
118
  updateExpiryDate,
129
119
  getContractorsByTabId,
130
- assignMptToProperties,
131
120
  searchInAutoComplete,
132
- searchInGlobalSearch,
133
121
  updateContractorUploadDate,
134
122
  inviteContractorViaPublicLink,
135
123
  sendGaps,
@@ -1,10 +1,10 @@
1
1
  const { validateType } = require('../../../../common/validations/typeValidations');
2
2
 
3
- function CreateContractorModel(requirementId, inviterEmail, vendorInfo, { tabId = null, disableMail = true, publicLink } = {}) {
3
+ function CreateContractorModel(requirementId, inviterEmail, vendorInfo, { tabId = null, sendMail = false, publicLink } = {}) {
4
4
  this.reqId = requirementId;
5
5
  this.inviterEmail = inviterEmail;
6
6
  this.vendorInfo = vendorInfo;
7
- this.disableMail = disableMail;
7
+ this.disableMail = !sendMail;
8
8
  this.tabId = tabId;
9
9
  this.publicLink = publicLink;
10
10
 
@@ -1,4 +1,5 @@
1
1
  const { validateType } = require('../../../../common/validations/typeValidations');
2
+ const TenantRequestModel = require('../../requests/models/tenant.request.model');
2
3
 
3
4
  class ContractorModel {
4
5
  constructor(contractorId, recordType, company, emailAddress, tab, additionalDetails) {
@@ -34,7 +35,7 @@ class ContractorDetailsModel {
34
35
  projectDescription = null,
35
36
  startDate = null,
36
37
  endDate = null,
37
- tenantRecord = {}
38
+ tenantRequest = {}
38
39
  } = {}) {
39
40
  this.dba = dba;
40
41
  this.fName = firstName;
@@ -49,8 +50,8 @@ class ContractorDetailsModel {
49
50
  this.startDate = startDate;
50
51
  this.endDate = endDate;
51
52
 
52
- Object.keys(tenantRecord).length && validateType(tenantRecord, TenantRecordModel);
53
- this.tenantRecord = tenantRecord;
53
+ Object.keys(tenantRequest).length && validateType(tenantRequest, TenantRequestModel);
54
+ this.tenantRequest = tenantRequest;
54
55
 
55
56
  this.additionalEmails = [];
56
57
 
@@ -60,32 +61,14 @@ class ContractorDetailsModel {
60
61
  }
61
62
  }
62
63
 
63
- class TenantRecordModel {
64
- constructor(id, companyName, emailAddress) {
65
- this.id = id;
66
- this.companyName = companyName;
67
- this.emailAddress = emailAddress;
68
- }
69
- }
70
-
71
64
  class VendorTabModel {
72
65
  constructor(type) {
73
66
  this.type = type;
74
67
  }
75
68
  }
76
69
 
77
- class MptModel {
78
- constructor(accountId, tenantId, properties) {
79
- this.accountId = accountId;
80
- this.tenantId = tenantId;
81
- this.properties = properties;
82
- }
83
- }
84
-
85
70
  module.exports = {
86
71
  ContractorModel,
87
- TenantRecordModel,
88
72
  VendorTabModel,
89
- ContractorDetailsModel,
90
- MptModel
73
+ ContractorDetailsModel
91
74
  };
@@ -3,22 +3,16 @@ const { validateDateString } = require('../../../../common/validations/typeValid
3
3
  class RecordModifyDateVerificationModel {
4
4
  constructor(
5
5
  contractorId,
6
- contractorDateModified,
7
6
  {
7
+ contractorDateModified,
8
8
  contractorOverrideDateModified,
9
9
  requirementId,
10
10
  requirementDateModified
11
11
  } = {}
12
12
  ) {
13
- validateDateString(contractorDateModified);
14
-
15
- if (contractorOverrideDateModified) {
16
- validateDateString(contractorOverrideDateModified);
17
- }
18
-
19
- if (requirementId) {
20
- validateDateString(requirementDateModified);
21
- }
13
+ contractorDateModified && validateDateString(contractorDateModified);
14
+ contractorOverrideDateModified && validateDateString(contractorOverrideDateModified);
15
+ requirementId && validateDateString(requirementDateModified);
22
16
 
23
17
  this.contractorId = contractorId;
24
18
  this.contractorDateModified = contractorDateModified;
@@ -0,0 +1,25 @@
1
+ const requests = require('../../../../common/requests/requestHandlers');
2
+ const { backendUrl, dbEmailsSecrets } = require('../../../../env').getEnv();
3
+
4
+ const Endpoints = {
5
+ dbEmails: `${backendUrl}/_saas/automation/emails/${dbEmailsSecrets}`,
6
+ deleteAllDbEmails: `${backendUrl}/_saas/automation/emails/all/${dbEmailsSecrets}`
7
+ };
8
+
9
+ const getAllMessages = emailModel => {
10
+ return requests.postRequestHandler(Endpoints.dbEmails, emailModel);
11
+ };
12
+
13
+ const deleteMultipleMessages = emailIds => {
14
+ return requests.deleteRequestHandler(Endpoints.dbEmails, {}, {}, emailIds);
15
+ };
16
+
17
+ const deleteAllMessages = () => {
18
+ return requests.deleteRequestHandler(Endpoints.deleteAllDbEmails);
19
+ };
20
+
21
+ module.exports = {
22
+ getAllMessages,
23
+ deleteMultipleMessages,
24
+ deleteAllMessages
25
+ };
@@ -0,0 +1,127 @@
1
+ const dbEmailsApi = require('./db.emails.api');
2
+ const util = require('../utils/util');
3
+ const timeUtils = require('../../../../common/utils/timeUtils');
4
+ const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
5
+ const { EmailModel } = require('../models/db.emails.model');
6
+
7
+ const strict = 'strict';
8
+
9
+ const getAllMessages = emailModel => {
10
+ return dbEmailsApi.getAllMessages(emailModel);
11
+ };
12
+
13
+ const deleteMultipleMessages = emailIds => {
14
+ return dbEmailsApi.deleteMultipleMessages(emailIds);
15
+ };
16
+
17
+ const deleteAllMessages = () => {
18
+ return dbEmailsApi.deleteAllMessages();
19
+ };
20
+
21
+ const getLastMessage = async (
22
+ {
23
+ recipients,
24
+ recipientsVerification = strict,
25
+ textInSubject,
26
+ textInBody,
27
+ excludingPhrasesInBody,
28
+ regex,
29
+ returnType
30
+ } = {}
31
+ ) => {
32
+ async function getLatestMessage(messages) {
33
+ for (const message of messages) {
34
+ /* The query we use to search for messages guarantees the recipients are included,
35
+ but it doesn't guarantee other emails aren't in to, cc or bcc */
36
+ let emailsMatch = true;
37
+
38
+ if (recipientsVerification === strict) {
39
+ const emptyArray = [''];
40
+
41
+ const expectedRecipients = {
42
+ from: util.extractEmailFromNameAndEmailFormat(recipients.from),
43
+ to: recipients.to || emptyArray,
44
+ cc: recipients.cc || emptyArray
45
+ };
46
+
47
+ const actualRecipients = {
48
+ from: util.extractEmailFromNameAndEmailFormat(message.from),
49
+ to: message.recipientsTo || emptyArray,
50
+ cc: message.recipientsCc || emptyArray
51
+ };
52
+
53
+ emailsMatch = util.recipientsMatchVerification(expectedRecipients, actualRecipients);
54
+ }
55
+
56
+ if (!emailsMatch) {
57
+ continue;
58
+ }
59
+
60
+ const result = regex ? util.regexVerification(message.body, regex, { returnType }) : message.body;
61
+
62
+ const isMessageNewest = timeUtils.isDateAfterOther(message.insertedTime, newestDateTime);
63
+
64
+ if (result && (!newestResult || !newestId || isMessageNewest)) {
65
+ newestResult = result;
66
+ newestId = message.id;
67
+ newestDateTime = message.insertedTime;
68
+
69
+ // Used for logging purposes only
70
+ newestTo = message.recipientsTo;
71
+ newestCc = message.recipientsCc;
72
+ newestSubject = message.subject;
73
+ }
74
+ }
75
+ }
76
+
77
+ let newestDateTime = '2020-01-01T01:01:01.000+0000';
78
+ let newestId, newestResult, newestTo, newestCc, newestSubject;
79
+
80
+ let recipientsTo = recipients.to;
81
+ let includesOneOfRecipientsTo;
82
+
83
+ if (recipientsVerification !== strict) {
84
+ recipientsTo = null;
85
+ includesOneOfRecipientsTo = recipients.to;
86
+ }
87
+
88
+ // In case the format is 'First Last <username@domain.com>' we need the email part only
89
+ const emailModel = new EmailModel(
90
+ util.extractEmailFromNameAndEmailFormat(recipients.from),
91
+ recipientsTo,
92
+ includesOneOfRecipientsTo,
93
+ recipients.cc,
94
+ textInSubject,
95
+ textInBody,
96
+ excludingPhrasesInBody
97
+ );
98
+
99
+ const response = await getAllMessages(emailModel);
100
+
101
+ if (response.status !== httpResponseStatusCodes.OK) {
102
+ throw new Error('Inbox messages could not be retrieved', response);
103
+ }
104
+
105
+ await getLatestMessage(response.data);
106
+
107
+ if (newestId) {
108
+ util.logRetrievedEmailInfo(newestTo, newestSubject, { cc: newestCc });
109
+
110
+ const response = await deleteMultipleMessages([newestId]);
111
+
112
+ if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
113
+ throw new Error(`Failed to delete email with ID : ${newestId}`, response);
114
+ }
115
+ }
116
+
117
+ return newestResult;
118
+ };
119
+
120
+ module.exports = {
121
+ util,
122
+
123
+ getAllMessages,
124
+ getLastMessage,
125
+ deleteMultipleMessages,
126
+ deleteAllMessages
127
+ };
@@ -0,0 +1,3 @@
1
+ const DEFAULT_EMAIL_SENDER = 'hellogetjonestest@gmail.com';
2
+
3
+ module.exports = { DEFAULT_EMAIL_SENDER };
@@ -0,0 +1,4 @@
1
+ const services = require('./api/db.emails.service');
2
+ const consts = require('./consts/consts');
3
+
4
+ module.exports = { services, consts };
@@ -0,0 +1,21 @@
1
+ class EmailModel {
2
+ constructor(
3
+ from,
4
+ recipientsTo,
5
+ includesOneOfRecipientsTo,
6
+ recipientsCc,
7
+ textInSubject,
8
+ textInBody,
9
+ excludingPhrasesInBody
10
+ ) {
11
+ this.from = from;
12
+ this.recipientsTo = recipientsTo;
13
+ this.includesOneOfRecipientsTo = includesOneOfRecipientsTo;
14
+ this.recipientsCc = recipientsCc;
15
+ this.textInSubject = textInSubject;
16
+ this.textInBody = textInBody;
17
+ this.excludingPhrasesInBody = excludingPhrasesInBody;
18
+ }
19
+ }
20
+
21
+ module.exports = { EmailModel };
@@ -0,0 +1,59 @@
1
+ const compareUnorderedArrays = (arr, other, { caseSensitive = true } = {}) => {
2
+ const isEachElementEqual = arr.sort().every((mail, i) => {
3
+ if (caseSensitive) {
4
+ return mail === other.sort()[i];
5
+ } else {
6
+ return mail.toLowerCase() === other.sort()[i].toLowerCase();
7
+ }
8
+ });
9
+ return arr.length === other.length && isEachElementEqual;
10
+ };
11
+
12
+ const recipientsMatchVerification = (expectedRecipients, actualRecipients) => {
13
+ const caseSensitive = false;
14
+
15
+ return expectedRecipients.from.includes(actualRecipients.from) && // For some emails can be few sendor options (ex: branded emails)
16
+ compareUnorderedArrays(actualRecipients.to, expectedRecipients.to, { caseSensitive }) &&
17
+ compareUnorderedArrays(actualRecipients.cc, expectedRecipients.cc, { caseSensitive });
18
+ };
19
+
20
+ const regexVerification = (message, regex, { returnType } = {}) => {
21
+ const capturingGroupsArr = message.match(regex);
22
+
23
+ if (!capturingGroupsArr || capturingGroupsArr.length < 1) {
24
+ return null;
25
+ }
26
+
27
+ const capturingGroups = capturingGroupsArr[capturingGroupsArr.length - 1];
28
+
29
+ if (!capturingGroups || capturingGroups.length < 2) {
30
+ return null;
31
+ }
32
+
33
+ switch (returnType) {
34
+ case 'url':
35
+ return typeof capturingGroups === 'string' ? capturingGroups : capturingGroups[capturingGroups.length - 1];
36
+ case 'body':
37
+ return message;
38
+ default:
39
+ return 'Bad "returnType" argument';
40
+ }
41
+ };
42
+
43
+ const extractEmailFromNameAndEmailFormat = str => {
44
+ // In case the format is 'First Last <username@domain.com>' we will return username@domain.com only
45
+ return str.split('<').pop().split('>')[0];
46
+ };
47
+ const logRetrievedEmailInfo = (to, subject, { cc } = {}) => {
48
+ let log = 'The following email retrieved and will be sent to trash:';
49
+ log += `\n| To: ${to}`;
50
+ cc ? log += `\n| Cc: ${cc}` : '';
51
+ log += `\n| Subject: ${subject}`;
52
+ };
53
+
54
+ module.exports = {
55
+ recipientsMatchVerification,
56
+ regexVerification,
57
+ extractEmailFromNameAndEmailFormat,
58
+ logRetrievedEmailInfo
59
+ };
@@ -13,7 +13,7 @@ const Endpoints = {
13
13
  getRecordProfileDetails: id => `${nodeBackendUrl}/global-record/record-profile/id/${id}`,
14
14
  getGlobalRecordByPolicyNumber: policyNumber => `${nodeBackendUrl}/global-record/policyNumber/${policyNumber}`,
15
15
  publishGlobalRecord: `${backendUrl}/saas/global-record/publish`,
16
- getGlobalRecordLinkedRequests: id => `${backendUrl}/saas/global-record/${id}/linked-requests`,
16
+ getGlobalRecordLinkedRecords: id => `${backendUrl}/saas/global-record/${id}/linked-records`,
17
17
  splitToNewGlobalRecord: `${backendUrl}/saas/global-record/split-to-new`
18
18
  };
19
19
 
@@ -53,8 +53,8 @@ const getGlobalRecordByPolicyNumber = async (policyNumber, nodeBackendSecret) =>
53
53
  return apiKeyAuthRequests.getRequestHandler(Endpoints.getGlobalRecordByPolicyNumber(policyNumber), nodeBackendSecret);
54
54
  };
55
55
 
56
- const getGlobalRecordLinkedRequests = async (id, context) => {
57
- return cookieAuthRequests.getRequestHandler(Endpoints.getGlobalRecordLinkedRequests(id), {}, context);
56
+ const getGlobalRecordLinkedRecords = async (id, context) => {
57
+ return cookieAuthRequests.getRequestHandler(Endpoints.getGlobalRecordLinkedRecords(id), {}, context);
58
58
  };
59
59
 
60
60
  const splitToNewGlobalRecord = ({ recordId, glPolicyNumber }, context) => {
@@ -71,6 +71,6 @@ module.exports = {
71
71
  getRecordProfileDetails,
72
72
  getGlobalRecordByPolicyNumber,
73
73
  publishGlobalRecord,
74
- getGlobalRecordLinkedRequests,
74
+ getGlobalRecordLinkedRecords,
75
75
  splitToNewGlobalRecord
76
76
  };
@@ -56,8 +56,8 @@ const publishGlobalRecord = async (globalRecordDetails, context) => {
56
56
  return globalRecordAPI.publishGlobalRecord(globalRecordDetails, context);
57
57
  };
58
58
 
59
- const getGlobalRecordLinkedRequests = async (id, context) => {
60
- return globalRecordAPI.getGlobalRecordLinkedRequests(id, context);
59
+ const getGlobalRecordLinkedRecords = async (id, context) => {
60
+ return globalRecordAPI.getGlobalRecordLinkedRecords(id, context);
61
61
  };
62
62
 
63
63
  const splitToNewGlobalRecord = async (recordId, glPolicyNumber, context) => {
@@ -78,6 +78,6 @@ module.exports = {
78
78
  getRecordProfileDetails,
79
79
  getGlobalRecordByPolicyNumber,
80
80
  publishGlobalRecord,
81
- getGlobalRecordLinkedRequests,
81
+ getGlobalRecordLinkedRecords,
82
82
  splitToNewGlobalRecord
83
83
  };
@@ -3,7 +3,9 @@ const { backendUrl } = require('../../../../env').getEnv();
3
3
 
4
4
  const Endpoints = {
5
5
  getById: requestId => `${backendUrl}/saas/request/${requestId}`,
6
- getByTabId: `${backendUrl}/saas/contractors`
6
+ getByTabId: `${backendUrl}/saas/contractors`,
7
+ requestsGlobalSearch: (projectId, searchWord) =>
8
+ `${backendUrl}/saas/contractors/search?&projectId=${projectId}&searchWord=${searchWord}`
7
9
  };
8
10
 
9
11
  const getReqeustById = (requestId, context) => {
@@ -15,7 +17,12 @@ const getRequestsByTabId = (tabId, context, activityStatus) => {
15
17
  return requests.postRequestHandler(Endpoints.getByTabId, body, context);
16
18
  };
17
19
 
20
+ const requestsGlobalSearch = (projectId, searchWord, context) => {
21
+ return requests.getRequestHandler(Endpoints.requestsGlobalSearch(projectId, searchWord), {}, context);
22
+ };
23
+
18
24
  module.exports = {
19
25
  getReqeustById,
20
- getRequestsByTabId
26
+ getRequestsByTabId,
27
+ requestsGlobalSearch
21
28
  };
@@ -8,7 +8,12 @@ const getReqeustById = (requestId, context) => {
8
8
  return requestsAPI.getReqeustById(requestId, context);
9
9
  };
10
10
 
11
+ const requestsGlobalSearch = (projectId, searchWord, context) => {
12
+ return requestsAPI.requestsGlobalSearch(projectId, searchWord, context);
13
+ };
14
+
11
15
  module.exports = {
12
16
  getRequestsByTabId,
13
- getReqeustById
17
+ getReqeustById,
18
+ requestsGlobalSearch
14
19
  };
@@ -1,3 +1,9 @@
1
1
  const services = require('./api/requests.service');
2
2
 
3
- module.exports = { services };
3
+ const TenantRequestModel = require('./models/tenant.request.model');
4
+
5
+ const models = {
6
+ TenantRequestModel
7
+ };
8
+
9
+ module.exports = { services, models };
@@ -0,0 +1,9 @@
1
+ class TenantRequestModel {
2
+ constructor(id, companyName, emailAddress) {
3
+ this.id = id;
4
+ this.companyName = companyName;
5
+ this.emailAddress = emailAddress;
6
+ }
7
+ }
8
+
9
+ module.exports = TenantRequestModel;
@@ -16,9 +16,8 @@ const Endpoints = {
16
16
  removeAllUserTraceFromDb: userId => `${backendUrl}/saas/user/automation/${userId}`
17
17
  };
18
18
 
19
- const invite = (invitedUser, context) => {
20
- const params = { disableSendMail: true };
21
- return requests.putRequestHandler(Endpoints.invite, invitedUser, context, {}, params);
19
+ const invite = (invitedUser, context, { disableSendMail = true } = {}) => {
20
+ return requests.putRequestHandler(Endpoints.invite, invitedUser, context, {}, { disableSendMail });
22
21
  };
23
22
 
24
23
  const signupUser = (signupUserModel, context) => {
@@ -6,8 +6,8 @@ const userAPI = require('./users.api');
6
6
  const util = require('../utils/util');
7
7
  const httpResponseStatusCodes = require('../../../../common/httpResponseStatusCodes.json');
8
8
 
9
- const inviteUser = async (invitedUser, context) => {
10
- return userAPI.invite(invitedUser, context);
9
+ const inviteUser = async (invitedUser, context, { disableSendMail } = {}) => {
10
+ return userAPI.invite(invitedUser, context, { disableSendMail });
11
11
  };
12
12
 
13
13
  const signupUser = (signupUserModel, context) => {
@@ -0,0 +1,6 @@
1
+ const services = require('./requests.service');
2
+
3
+ const InviteRequestModel = require('./models/invite.request.model');
4
+ const models = { InviteRequestModel };
5
+
6
+ module.exports = { ... services, models };
@@ -1,4 +1,4 @@
1
- class InviteContractorModel {
1
+ class InviteRequestModel {
2
2
  constructor(
3
3
  email,
4
4
  company,
@@ -33,5 +33,5 @@ class InviteContractorModel {
33
33
  }
34
34
 
35
35
  module.exports = {
36
- InviteContractorModel
36
+ InviteRequestModel
37
37
  };
@@ -0,0 +1,20 @@
1
+ const requests = require('../../../common/requests/apiKeyAuth/requests');
2
+ const { openapiUrl } = require('../../../env').getEnv();
3
+ const { isLocalhost } = require('../../../env');
4
+
5
+ const contractorUrl = isLocalhost() ? 'contractors' : 'records';
6
+
7
+ const Endpoints = {
8
+ getAllRequests: `${openapiUrl}/${contractorUrl}/all`,
9
+ inviteRequest: tabId => `${openapiUrl}/tabs/${tabId}/${contractorUrl}`
10
+ };
11
+
12
+ const getAllRequests = async (apiKey, params) => {
13
+ return requests.getRequestHandler(Endpoints.getAllRequests, apiKey, params).then(res => res.data);
14
+ };
15
+
16
+ const inviteRequest = async (apiKey, tabId, params) => {
17
+ return requests.postRequestHandler(Endpoints.inviteRequest(tabId), apiKey, params).then(res => res.data);
18
+ };
19
+
20
+ module.exports = { getAllRequests, inviteRequest };
@@ -0,0 +1,18 @@
1
+ const requestsApi = require('./requests.api');
2
+ const { InviteRequestModel } = require('./models/invite.request.model');
3
+ const { validateType } = require('../../../common/validations/typeValidations');
4
+
5
+ const getAllAccountRequests = async (apiKey, { projectId, type, activationStatuses } = {}) => {
6
+ if (activationStatuses) {
7
+ activationStatuses = activationStatuses.reduce((f, s) => `${f},${s}`);
8
+ }
9
+
10
+ return requestsApi.getAllRequests(apiKey, { propertyId: projectId, type, activationStatuses });
11
+ };
12
+
13
+ const inviteRequest = async (apiKey, tabId, inviteRequestModel = {}) => {
14
+ validateType(inviteRequestModel, InviteRequestModel);
15
+ return requestsApi.inviteRequest(apiKey, tabId, inviteRequestModel);
16
+ };
17
+
18
+ module.exports = { getAllAccountRequests, inviteRequest };
@@ -1,6 +0,0 @@
1
- const convertStringToDate = date => {
2
- const [day, month, year] = date.split('/').map(Number);
3
- return new Date(year, month - 1, day + 1);
4
- };
5
-
6
- module.exports = { convertStringToDate };
@@ -1,20 +0,0 @@
1
- const requests = require('../../../common/requests/apiKeyAuth/requests');
2
- const { openapiUrl } = require('../../../env').getEnv();
3
- const { isLocalhost } = require('../../../env');
4
-
5
- const contractorUrl = isLocalhost() ? 'contractors' : 'records';
6
-
7
- const Endpoints = {
8
- getAllContractors: `${openapiUrl}/${contractorUrl}/all`,
9
- inviteContractor: tabId => `${openapiUrl}/tabs/${tabId}/${contractorUrl}`
10
- };
11
-
12
- const getAllContractors = async (apiKey, params) => {
13
- return requests.getRequestHandler(Endpoints.getAllContractors, apiKey, params).then(res => res.data);
14
- };
15
-
16
- const inviteContractor = async (apiKey, tabId, params) => {
17
- return requests.postRequestHandler(Endpoints.inviteContractor(tabId), apiKey, params).then(res => res.data);
18
- };
19
-
20
- module.exports = { getAllContractors, inviteContractor };
@@ -1,18 +0,0 @@
1
- const contractorsApi = require('./contractors.api');
2
- const { InviteContractorModel } = require('./models/invite.contractor.model');
3
- const { validateType } = require('../../../common/validations/typeValidations');
4
-
5
- const getContractors = async (apiKey, { projectId, type, activationStatuses } = {}) => {
6
- if (activationStatuses) {
7
- activationStatuses = activationStatuses.reduce((f, s) => `${f},${s}`);
8
- }
9
-
10
- return contractorsApi.getAllContractors(apiKey, { propertyId: projectId, type, activationStatuses });
11
- };
12
-
13
- const inviteContractor = async (apiKey, tabId, inviteContractorModel = {}) => {
14
- validateType(inviteContractorModel, InviteContractorModel);
15
- return contractorsApi.inviteContractor(apiKey, tabId, inviteContractorModel);
16
- };
17
-
18
- module.exports = { getContractors, inviteContractor };
@@ -1,6 +0,0 @@
1
- const services = require('./contractors.service');
2
-
3
- const InviteContractorModel = require('./models/invite.contractor.model');
4
- const models = { InviteContractorModel };
5
-
6
- module.exports = { ... services, models };