@getjones/test-infra 5.2.14 → 5.2.16

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 (296) hide show
  1. package/eslint.config.mjs +156 -156
  2. package/package.json +43 -43
  3. package/src/common/commonFlows/auth/auth.js +95 -95
  4. package/src/common/commonFlows/index.js +5 -5
  5. package/src/common/commonFlows/records/records.js +452 -452
  6. package/src/common/commonFlows/users/users.js +15 -15
  7. package/src/common/consts/accountSettings.js +112 -112
  8. package/src/common/consts/activationStatuses.js +6 -6
  9. package/src/common/consts/analysisStatuses.js +7 -7
  10. package/src/common/consts/autocomplete.js +10 -10
  11. package/src/common/consts/constantsForRecordsSortingAndFilters.js +49 -49
  12. package/src/common/consts/dashboardCharts.js +18 -18
  13. package/src/common/consts/homepage/AttentionTab.js +6 -6
  14. package/src/common/consts/homepage/sortOptions.js +19 -19
  15. package/src/common/consts/projectSettings.js +28 -28
  16. package/src/common/consts/recordTypes.js +5 -5
  17. package/src/common/consts/requirementActions.js +10 -10
  18. package/src/common/consts/s3FileTypes.js +12 -12
  19. package/src/common/consts/userRoles.js +21 -21
  20. package/src/common/consts/userTypes.js +16 -16
  21. package/src/common/errorCodes.js +13 -13
  22. package/src/common/httpResponseStatusCodes.json +19 -19
  23. package/src/common/httpResponseTypes.json +2 -2
  24. package/src/common/requests/apiKeyAuth/requests.js +45 -45
  25. package/src/common/requests/cookieAuth/requests.js +40 -40
  26. package/src/common/requests/internalAuth/requests.js +48 -48
  27. package/src/common/requests/requestHandlers.js +112 -112
  28. package/src/common/utils/arrayUtils.js +19 -19
  29. package/src/common/utils/complianceUtil.js +114 -114
  30. package/src/common/utils/configsUtil.js +22 -22
  31. package/src/common/utils/dataTypeUtils.js +41 -41
  32. package/src/common/utils/numberUtils.js +22 -22
  33. package/src/common/utils/objectUtils.js +102 -102
  34. package/src/common/utils/timeUtils.js +202 -202
  35. package/src/common/validations/typeValidations.js +36 -36
  36. package/src/defaults/configs/attributes.js +170 -170
  37. package/src/defaults/configs/auditConfigs.js +129 -129
  38. package/src/defaults/configs/coverage.js +144 -144
  39. package/src/defaults/configs/polices.js +28 -28
  40. package/src/defaults/configs/requirement.js +218 -218
  41. package/src/defaults/index.js +7 -7
  42. package/src/env.js +58 -58
  43. package/src/factory/globalRecord/globalRecord.js +43 -43
  44. package/src/factory/index.js +8 -8
  45. package/src/factory/records/records.js +295 -295
  46. package/src/factory/users/users.js +70 -70
  47. package/src/index.js +118 -118
  48. package/src/reporters/mochaReporter.js +273 -273
  49. package/src/saas/internal-api/accountDirectory/api/accountDirectory.api.js +152 -152
  50. package/src/saas/internal-api/accountDirectory/api/accountDirectory.service.js +576 -576
  51. package/src/saas/internal-api/accountDirectory/consts/accountDirectory.consts.js +75 -75
  52. package/src/saas/internal-api/accountDirectory/index.js +5 -5
  53. package/src/saas/internal-api/accountDirectory/models/accountDirectory.models.js +172 -172
  54. package/src/saas/internal-api/accounts/api/core/accounts.core.api.js +54 -54
  55. package/src/saas/internal-api/accounts/api/core/accounts.core.service.js +114 -114
  56. package/src/saas/internal-api/accounts/api/emailCustomization/accounts.email.customizations.api.js +29 -29
  57. package/src/saas/internal-api/accounts/api/emailCustomization/accounts.email.customizations.service.js +60 -60
  58. package/src/saas/internal-api/accounts/api/emailCustomization/consts.js +8 -8
  59. package/src/saas/internal-api/accounts/api/openapi/accounts.openapi.api.js +54 -54
  60. package/src/saas/internal-api/accounts/api/openapi/accounts.openapi.service.js +67 -67
  61. package/src/saas/internal-api/accounts/api/settings/settings.api.js +21 -21
  62. package/src/saas/internal-api/accounts/api/settings/settings.service.js +58 -58
  63. package/src/saas/internal-api/accounts/consts/consts.js +8 -8
  64. package/src/saas/internal-api/accounts/index.js +22 -22
  65. package/src/saas/internal-api/accounts/models/core/create.account.model.js +16 -16
  66. package/src/saas/internal-api/accounts/models/settings/update.settings.model.js +110 -110
  67. package/src/saas/internal-api/accounts/utils/utils.js +60 -60
  68. package/src/saas/internal-api/agreement/api/agreement.api.js +39 -39
  69. package/src/saas/internal-api/agreement/api/agreement.service.js +121 -121
  70. package/src/saas/internal-api/agreement/consts/consts.js +11 -11
  71. package/src/saas/internal-api/agreement/index.js +12 -12
  72. package/src/saas/internal-api/agreement/models/create.agreement.model.js +12 -12
  73. package/src/saas/internal-api/agreement/models/createAgreementByAuditorModel.js +11 -11
  74. package/src/saas/internal-api/agreement/models/createAgreementByPMModel.js +13 -13
  75. package/src/saas/internal-api/auditCustomerRules/api/customer.rules.api.js +49 -49
  76. package/src/saas/internal-api/auditCustomerRules/api/customer.rules.service.js +121 -121
  77. package/src/saas/internal-api/auditCustomerRules/consts/customer.rule.js +40 -40
  78. package/src/saas/internal-api/auditCustomerRules/index.js +7 -7
  79. package/src/saas/internal-api/auditCustomerRules/models/customer.rule.model.js +55 -55
  80. package/src/saas/internal-api/auditCustomerRules/utils/customer.rule.util.js +70 -70
  81. package/src/saas/internal-api/auditNotes/api/audit.notes.api.js +40 -40
  82. package/src/saas/internal-api/auditNotes/api/audit.notes.service.js +116 -116
  83. package/src/saas/internal-api/auditNotes/index.js +4 -4
  84. package/src/saas/internal-api/auditNotes/models/audit.note.model.js +32 -32
  85. package/src/saas/internal-api/auditorComments/api/auditor.comments.api.js +20 -20
  86. package/src/saas/internal-api/auditorComments/api/auditor.comments.service.js +27 -27
  87. package/src/saas/internal-api/auditorComments/consts/auditor.comment.js +16 -16
  88. package/src/saas/internal-api/auditorComments/index.js +5 -5
  89. package/src/saas/internal-api/auditorComments/models/auditor.comment.model.js +40 -40
  90. package/src/saas/internal-api/auth/api/auth.api.js +78 -78
  91. package/src/saas/internal-api/auth/api/auth.service.js +217 -217
  92. package/src/saas/internal-api/auth/index.js +3 -3
  93. package/src/saas/internal-api/certificial/api/certificial.api.js +15 -15
  94. package/src/saas/internal-api/certificial/api/certificial.service.js +24 -24
  95. package/src/saas/internal-api/certificial/consts.js +8 -8
  96. package/src/saas/internal-api/certificial/index.js +4 -4
  97. package/src/saas/internal-api/coi/api/coi.api.js +76 -76
  98. package/src/saas/internal-api/coi/api/coi.service.js +104 -104
  99. package/src/saas/internal-api/coi/consts/{uploaderStatuses.js → coiUploaderTypes.js} +9 -9
  100. package/src/saas/internal-api/coi/consts/duplicateHandling.js +7 -7
  101. package/src/saas/internal-api/coi/consts/hashes.js +5 -5
  102. package/src/saas/internal-api/coi/consts/uploaderTypes.js +3 -3
  103. package/src/saas/internal-api/coi/index.js +17 -17
  104. package/src/saas/internal-api/coi/models/Combine.last.two.cois.model.js +25 -25
  105. package/src/saas/internal-api/coi/models/submit.coi.batch.model.js +23 -23
  106. package/src/saas/internal-api/coi/models/submit.coi.model.js +23 -23
  107. package/src/saas/internal-api/coi/utils/utils.js +186 -185
  108. package/src/saas/internal-api/compliance/api/amBestRating/am.best.rating.api.js +12 -12
  109. package/src/saas/internal-api/compliance/api/amBestRating/am.best.rating.service.js +14 -14
  110. package/src/saas/internal-api/compliance/api/audit/aiAudit/aiAudit.api.js +63 -63
  111. package/src/saas/internal-api/compliance/api/audit/aiAudit/aiAudit.service.js +99 -99
  112. package/src/saas/internal-api/compliance/api/audit/audit.api.js +124 -124
  113. package/src/saas/internal-api/compliance/api/audit/audit.service.js +390 -390
  114. package/src/saas/internal-api/compliance/api/complianceSnapshot/compliance.snapshot.api.js +32 -32
  115. package/src/saas/internal-api/compliance/api/complianceSnapshot/compliance.snapshot.service.js +73 -73
  116. package/src/saas/internal-api/compliance/api/convert/convert.api.js +12 -12
  117. package/src/saas/internal-api/compliance/api/convert/convert.service.js +7 -7
  118. package/src/saas/internal-api/compliance/api/coverage/coverage.api.js +33 -33
  119. package/src/saas/internal-api/compliance/api/coverage/coverage.service.js +46 -46
  120. package/src/saas/internal-api/compliance/api/overrideGap/override.gap.api.js +86 -86
  121. package/src/saas/internal-api/compliance/api/overrideGap/override.gap.service.js +300 -300
  122. package/src/saas/internal-api/compliance/consts/audit.js +130 -130
  123. package/src/saas/internal-api/compliance/consts/overrideGapRequest/override.gap.request.js +7 -7
  124. package/src/saas/internal-api/compliance/index.js +41 -41
  125. package/src/saas/internal-api/compliance/models/audit/audit.model.js +109 -109
  126. package/src/saas/internal-api/compliance/models/overrideGapRequest/override.gap.request.model.js +16 -16
  127. package/src/saas/internal-api/compliance/models/waive/waive.model.js +112 -112
  128. package/src/saas/internal-api/compliance/utils/auditUtil.js +308 -308
  129. package/src/saas/internal-api/compliance/utils/coverageUtil.js +45 -45
  130. package/src/saas/internal-api/contractors/api/contractors.api.js +251 -251
  131. package/src/saas/internal-api/contractors/api/contractors.service.js +482 -482
  132. package/src/saas/internal-api/contractors/consts/consts.js +6 -6
  133. package/src/saas/internal-api/contractors/index.js +8 -8
  134. package/src/saas/internal-api/contractors/models/assign.requirement.model.js +11 -11
  135. package/src/saas/internal-api/contractors/models/edit.contractor.model.js +73 -73
  136. package/src/saas/internal-api/contractors/models/link.request.model.js +10 -10
  137. package/src/saas/internal-api/contractors/models/verification.contractor.model.js +29 -29
  138. package/src/saas/internal-api/contractors/utils.js +25 -25
  139. package/src/saas/internal-api/customTags/api/customTags.api.js +47 -47
  140. package/src/saas/internal-api/customTags/api/customTags.service.js +96 -96
  141. package/src/saas/internal-api/customTags/index.js +4 -4
  142. package/src/saas/internal-api/customTags/models/customTagsModels.js +17 -17
  143. package/src/saas/internal-api/dashboard/api/recordList.api.js +38 -38
  144. package/src/saas/internal-api/dashboard/api/recordList.service.js +60 -60
  145. package/src/saas/internal-api/dashboard/index.js +5 -5
  146. package/src/saas/internal-api/dashboard/models/dashboard.filter.criteria.model.js +38 -38
  147. package/src/saas/internal-api/dbEmails/api/db.emails.api.js +25 -25
  148. package/src/saas/internal-api/dbEmails/api/db.emails.service.js +209 -209
  149. package/src/saas/internal-api/dbEmails/consts/consts.js +66 -66
  150. package/src/saas/internal-api/dbEmails/index.js +6 -6
  151. package/src/saas/internal-api/dbEmails/models/db.emails.model.js +22 -22
  152. package/src/saas/internal-api/dbEmails/utils/util.js +82 -82
  153. package/src/saas/internal-api/emailCustomization/api/email.customization.api.js +26 -26
  154. package/src/saas/internal-api/emailCustomization/api/email.customization.service.js +50 -50
  155. package/src/saas/internal-api/emailCustomization/index.js +3 -3
  156. package/src/saas/internal-api/fileScan/api/file.scan.api.js +14 -14
  157. package/src/saas/internal-api/fileScan/api/file.scan.service.js +35 -35
  158. package/src/saas/internal-api/fileScan/index.js +3 -3
  159. package/src/saas/internal-api/fileScan/models/update.scan.status.model.js +13 -13
  160. package/src/saas/internal-api/globalRecord/api/global.record.api.js +95 -95
  161. package/src/saas/internal-api/globalRecord/api/global.record.service.js +112 -112
  162. package/src/saas/internal-api/globalRecord/consts.js +20 -20
  163. package/src/saas/internal-api/globalRecord/index.js +6 -6
  164. package/src/saas/internal-api/globalRecord/models/global.record.model.js +60 -60
  165. package/src/saas/internal-api/globalRecord/utils/util.js +161 -161
  166. package/src/saas/internal-api/homepageCharts/api/charts.api.js +12 -12
  167. package/src/saas/internal-api/homepageCharts/api/charts.service.js +7 -7
  168. package/src/saas/internal-api/homepageCharts/index.js +3 -3
  169. package/src/saas/internal-api/notificationCenter/api/notification.center.api.js +32 -32
  170. package/src/saas/internal-api/notificationCenter/api/notification.center.service.js +49 -49
  171. package/src/saas/internal-api/notificationCenter/consts.js +9 -9
  172. package/src/saas/internal-api/notificationCenter/index.js +4 -4
  173. package/src/saas/internal-api/outlook/api/outlook.api.js +14 -14
  174. package/src/saas/internal-api/outlook/api/outlook.service.js +14 -14
  175. package/src/saas/internal-api/outlook/index.js +3 -3
  176. package/src/saas/internal-api/policyFile/api/policy.file.api.js +43 -43
  177. package/src/saas/internal-api/policyFile/api/policy.file.service.js +117 -117
  178. package/src/saas/internal-api/policyFile/consts.js +21 -21
  179. package/src/saas/internal-api/policyFile/index.js +11 -11
  180. package/src/saas/internal-api/policyFile/models/create.policy.file.model.js +11 -11
  181. package/src/saas/internal-api/policyFile/models/set.publish.flag.to.policy.model.js +13 -13
  182. package/src/saas/internal-api/projects/api/core/projects.api.js +39 -39
  183. package/src/saas/internal-api/projects/api/core/projects.service.js +77 -77
  184. package/src/saas/internal-api/projects/api/settings/project.settings.api.js +18 -18
  185. package/src/saas/internal-api/projects/api/settings/project.settings.service.js +35 -35
  186. package/src/saas/internal-api/projects/consts/defaultProject.js +3 -3
  187. package/src/saas/internal-api/projects/index.js +24 -24
  188. package/src/saas/internal-api/projects/models/core/create.project.model.js +41 -41
  189. package/src/saas/internal-api/projects/models/core/update.project.model.js +47 -47
  190. package/src/saas/internal-api/projects/models/settings/update.project.settings.model.js +56 -56
  191. package/src/saas/internal-api/projects/utils/utils.js +159 -159
  192. package/src/saas/internal-api/recordHub/api/record.hub.api.js +20 -20
  193. package/src/saas/internal-api/recordHub/api/record.hub.service.js +86 -86
  194. package/src/saas/internal-api/recordHub/index.js +3 -3
  195. package/src/saas/internal-api/recordNotes/api/record.notes.api.js +38 -38
  196. package/src/saas/internal-api/recordNotes/api/record.notes.service.js +56 -56
  197. package/src/saas/internal-api/recordNotes/api/record.notes.utils.js +12 -12
  198. package/src/saas/internal-api/recordNotes/index.js +3 -3
  199. package/src/saas/internal-api/relatedDocs/api/related.docs.api.js +98 -98
  200. package/src/saas/internal-api/relatedDocs/api/related.docs.service.js +180 -180
  201. package/src/saas/internal-api/relatedDocs/index.js +4 -4
  202. package/src/saas/internal-api/relatedDocs/models/related.doc.model.js +36 -36
  203. package/src/saas/internal-api/reports/api/reports.api.js +56 -56
  204. package/src/saas/internal-api/reports/api/reports.service.js +68 -68
  205. package/src/saas/internal-api/reports/consts/consts.js +71 -71
  206. package/src/saas/internal-api/reports/index.js +15 -15
  207. package/src/saas/internal-api/reports/models/report.model.js +27 -27
  208. package/src/saas/internal-api/requests/api/requests.api.js +132 -132
  209. package/src/saas/internal-api/requests/api/requests.service.js +315 -315
  210. package/src/saas/internal-api/requests/index.js +21 -21
  211. package/src/saas/internal-api/requests/models/create.request.model.js +39 -39
  212. package/src/saas/internal-api/requests/models/draft.request.criteria.model.js +18 -18
  213. package/src/saas/internal-api/requests/models/draft.request.report.model.js +14 -14
  214. package/src/saas/internal-api/requests/models/edit.request.model.js +31 -31
  215. package/src/saas/internal-api/requests/models/homepageRequestCriteriaModel.js +19 -19
  216. package/src/saas/internal-api/requests/models/requestListCriteriaModel.js +17 -17
  217. package/src/saas/internal-api/requests/models/tenant.request.model.js +9 -9
  218. package/src/saas/internal-api/requests/utils.js +16 -16
  219. package/src/saas/internal-api/requestsTable/api/requests.table.api.js +20 -20
  220. package/src/saas/internal-api/requestsTable/api/requests.table.service.js +14 -14
  221. package/src/saas/internal-api/requestsTable/index.js +3 -3
  222. package/src/saas/internal-api/requirements/api/lease/lease.api.js +74 -74
  223. package/src/saas/internal-api/requirements/api/lease/lease.service.js +167 -167
  224. package/src/saas/internal-api/requirements/api/requirements.api.js +65 -65
  225. package/src/saas/internal-api/requirements/api/requirements.service.js +198 -198
  226. package/src/saas/internal-api/requirements/consts/attributeTypes.json +8 -8
  227. package/src/saas/internal-api/requirements/consts/consts.js +22 -22
  228. package/src/saas/internal-api/requirements/index.js +22 -22
  229. package/src/saas/internal-api/requirements/models/create.requirement.model.js +17 -17
  230. package/src/saas/internal-api/requirements/models/extraction.request.model.js +16 -16
  231. package/src/saas/internal-api/requirements/models/policy.model.js +35 -35
  232. package/src/saas/internal-api/requirements/models/tab.extraction.request.model.js +14 -14
  233. package/src/saas/internal-api/requirements/models/update.requirement.model.js +19 -19
  234. package/src/saas/internal-api/requirements/utils/utils.js +129 -129
  235. package/src/saas/internal-api/sampleCoi/api/sample.coi.api.js +15 -15
  236. package/src/saas/internal-api/sampleCoi/api/sample.coi.service.js +48 -48
  237. package/src/saas/internal-api/sampleCoi/consts/consts.js +22 -22
  238. package/src/saas/internal-api/sampleCoi/index.js +4 -4
  239. package/src/saas/internal-api/schedulerJobRun/api/scheduler.job.run.api.js +31 -31
  240. package/src/saas/internal-api/schedulerJobRun/api/scheduler.job.run.service.js +56 -56
  241. package/src/saas/internal-api/schedulerJobRun/index.js +3 -3
  242. package/src/saas/internal-api/serviceArea/api/coordinates.api.js +12 -12
  243. package/src/saas/internal-api/serviceArea/api/coordinates.service.js +7 -7
  244. package/src/saas/internal-api/serviceArea/index.js +4 -4
  245. package/src/saas/internal-api/serviceArea/utils/utils.js +8 -8
  246. package/src/saas/internal-api/tableOfContents/api/table.of.contents.api.js +37 -37
  247. package/src/saas/internal-api/tableOfContents/api/table.of.contents.service.js +19 -19
  248. package/src/saas/internal-api/tableOfContents/index.js +3 -3
  249. package/src/saas/internal-api/tabs/api/tabs.api.js +32 -32
  250. package/src/saas/internal-api/tabs/api/tabs.service.js +60 -60
  251. package/src/saas/internal-api/tabs/index.js +3 -3
  252. package/src/saas/internal-api/tabs/models/tabs.model.js +19 -19
  253. package/src/saas/internal-api/thread-scheduler/runner.js +86 -86
  254. package/src/saas/internal-api/thread-scheduler/schedulerJobs.js +10 -10
  255. package/src/saas/internal-api/uploadFiles/api/upload.file.api.js +49 -49
  256. package/src/saas/internal-api/uploadFiles/api/upload.file.service.js +176 -176
  257. package/src/saas/internal-api/uploadFiles/consts.js +36 -36
  258. package/src/saas/internal-api/uploadFiles/index.js +5 -5
  259. package/src/saas/internal-api/uploadFiles/utils.js +34 -34
  260. package/src/saas/internal-api/users/api/tenantApp/tenant.app.api.js +38 -38
  261. package/src/saas/internal-api/users/api/tenantApp/tenant.app.service.js +109 -109
  262. package/src/saas/internal-api/users/api/users.api.js +158 -158
  263. package/src/saas/internal-api/users/api/users.service.js +363 -363
  264. package/src/saas/internal-api/users/index.js +17 -17
  265. package/src/saas/internal-api/users/models/create.inner.system.user.model.js +18 -18
  266. package/src/saas/internal-api/users/models/notification.settings.model.js +15 -15
  267. package/src/saas/internal-api/users/models/tenant.user.model.js +11 -11
  268. package/src/saas/internal-api/users/models/users.model.js +43 -43
  269. package/src/saas/internal-api/users/utils/util.js +50 -50
  270. package/src/saas/internal-api/vendorProfile/api/vendor.profile.api.js +26 -26
  271. package/src/saas/internal-api/vendorProfile/api/vendor.profile.service.js +19 -19
  272. package/src/saas/internal-api/vendorProfile/index.js +3 -3
  273. package/src/saas/openapi/accounts/accounts.api.js +17 -17
  274. package/src/saas/openapi/accounts/accounts.service.js +11 -11
  275. package/src/saas/openapi/coi/coi.api.js +35 -35
  276. package/src/saas/openapi/coi/coi.service.js +53 -53
  277. package/src/saas/openapi/projects/projects.api.js +83 -83
  278. package/src/saas/openapi/projects/projects.service.js +89 -89
  279. package/src/saas/openapi/relatedDocs/related.docs.api.js +30 -30
  280. package/src/saas/openapi/relatedDocs/related.docs.service.js +56 -56
  281. package/src/saas/openapi/requests/index.js +7 -7
  282. package/src/saas/openapi/requests/models/invite.request.model.js +42 -42
  283. package/src/saas/openapi/requests/models/update.request.model.js +37 -37
  284. package/src/saas/openapi/requests/requests.api.js +93 -93
  285. package/src/saas/openapi/requests/requests.service.js +100 -100
  286. package/src/saas/openapi/requirements/index.js +6 -6
  287. package/src/saas/openapi/requirements/models/copy.requirement.model.js +10 -10
  288. package/src/saas/openapi/requirements/requirements.api.js +41 -41
  289. package/src/saas/openapi/requirements/requirements.service.js +61 -61
  290. package/src/saas/openapi/tabs/index.js +6 -6
  291. package/src/saas/openapi/tabs/models/create.tab.model.js +6 -6
  292. package/src/saas/openapi/tabs/tabs.api.js +27 -27
  293. package/src/saas/openapi/tabs/tabs.service.js +26 -26
  294. package/src/saas/openapi/users/user.model.js +10 -10
  295. package/src/saas/openapi/users/users.api.js +33 -33
  296. package/src/saas/openapi/users/users.service.js +51 -51
@@ -1,452 +1,452 @@
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 ocrStatuses = require('../../consts/analysisStatuses');
7
- const contractors = require('../../../saas/internal-api/contractors');
8
- const compliance = require('../../../saas/internal-api/compliance');
9
- const aiAuditApi = require('../../../saas/internal-api/compliance/api/audit/aiAudit/aiAudit.api');
10
- const requests = require('../../../saas/internal-api/requests');
11
- const requirements = require('../../../saas/internal-api/requirements');
12
- const uploadFile = require('../../../saas/internal-api/uploadFiles');
13
- const coi = require('../../../saas/internal-api/coi');
14
- const usersAPI = require('../../../saas/internal-api/users/index');
15
- const auth = require('../../../saas/internal-api/auth/index');
16
- const accounts = require('../../../saas/internal-api/accounts');
17
- const activationStatuses = require('../../../common/consts/activationStatuses');
18
- const recordTypes = require('../../../common/consts/recordTypes');
19
- const policyNames = require('../../../defaults/index').polices;
20
- const { ExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/extraction.request.model');
21
- const { TabExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/tab.extraction.request.model');
22
- const { DEFAULT_LEASE_PATH } = require('../../../saas/internal-api/requirements/consts/consts');
23
- const { RELATED_DOC_TYPES } = require('../../../saas/internal-api/uploadFiles/consts');
24
- const { WAIVER_REASONS, EXPIRY_TYPES } = compliance.models.waive;
25
-
26
- const makeRecordNotResponsive = async function(recordId, context) {
27
- const { data: record } = await contractors.services.getContractorById(recordId, context);
28
- const isTenant = record.recordType === recordTypes.TENANTS;
29
-
30
- const offsetInDaysList = isTenant ?
31
- timeUtils.getInviteActionOffsetInDaysForNotResponsiveTenant() :
32
- timeUtils.getInviteActionOffsetInDaysForNotResponsiveVendor();
33
-
34
- for (const offsetInDays of offsetInDaysList) {
35
- await updateLastInviteActionDate(recordId, offsetInDays, context);
36
- }
37
- };
38
-
39
- const runThreadSchedulerForRecord = async recordId => {
40
- const threadSchedulerResponse = await threadScheduler.runForRecords([recordId]);
41
-
42
- if (threadSchedulerResponse.status !== httpResponseStatusCodes.OK) {
43
- throw new Error(`Thread scheduler has failed to run\n${threadSchedulerResponse}`);
44
- }
45
-
46
- await timeUtils.waitFor(2.5).seconds; // calls for the same records can override each other
47
- };
48
-
49
- const makeRecordAboutToExpire = async (recordId, policyExpiryDate, { policyName = policyNames.generalLiability } = {}) => {
50
- const updateResponse = await contractors.services.updateExpiryDate(recordId, policyExpiryDate, policyName);
51
-
52
- if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
53
- throw new Error(`Record expiry date could not be updated\n${updateResponse}`);
54
- }
55
-
56
- await runThreadSchedulerForRecord(recordId);
57
- };
58
-
59
- const resendInvitationByRecordId = async (recordId, tabId, context) => {
60
- const { id: requestId } = await requests.services.getRequestFromTabByRecordId(recordId, tabId, context);
61
- const recordModifyDateVerificationModel = await contractors.services.getRecordVerificationModel(recordId, context);
62
-
63
- const resendInvitationResponse = await contractors.services.resendInvitation(requestId, recordModifyDateVerificationModel, context);
64
-
65
- if (resendInvitationResponse.status !== httpResponseStatusCodes.OK) {
66
- throw new Error(`Failed to resend invitation for record: ${resendInvitationResponse.statusText}`);
67
- }
68
-
69
- return resendInvitationResponse;
70
- };
71
-
72
- const editRequestAndRecordDetails = async function(request, recordConfig, context, { isDraft, expectError } = {}) {
73
- const tabModel = new requests.models.TabModel(request.tab.type);
74
- const recordDetailsModel = contractors.services.getContractorDetailsModel(recordConfig);
75
-
76
- const record = isDraft ?
77
- new contractors.models.edit.DraftRecordModel(
78
- request.record.contractorId,
79
- request.record.recordType,
80
- recordConfig.company,
81
- recordConfig.emailAddress,
82
- recordDetailsModel,
83
- isDraft,
84
- recordConfig.requirementsAction
85
- ) :
86
- new contractors.models.edit.ContractorModel(
87
- request.record.contractorId,
88
- request.record.recordType,
89
- recordConfig.company,
90
- recordConfig.emailAddress,
91
- recordDetailsModel
92
- );
93
-
94
- const requestEditModel = new requests.models.RequestModel(request.id, record, tabModel, {});
95
-
96
- const editRequestResponse = await requests.services.editRequestAndRecordDetails(requestEditModel, context);
97
-
98
- if (editRequestResponse.status !== httpResponseStatusCodes.OK && !expectError) {
99
- throw Error(`Failed to edit record \nStatus: ${editRequestResponse.status}\n${JSON.stringify(editRequestResponse.data)}`);
100
- }
101
-
102
- return editRequestResponse;
103
- };
104
-
105
- const updateInviteDate = async function(recordId, inviteDate, context) {
106
- await timeUtils.waitFor(1).seconds;
107
- const updateResponse = await contractors.services.updateInviteDate(recordId, inviteDate, context);
108
-
109
- if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
110
- throw new Error(`Failed to update record invite date\n${updateResponse}`);
111
- }
112
-
113
- await runThreadSchedulerForRecord(recordId);
114
- };
115
-
116
- const updateLastInviteActionDate = async function(recordId, offsetInDays, context) {
117
- await timeUtils.waitFor(1).seconds;
118
- //In order to prevent situations where the date of the compliance audit action is equal or greater than the date of the last mail send audit,
119
- //we move back another day!!
120
- const complianceAuditActionOffsetInDays = offsetInDays + 1;
121
- /*
122
- To run the reminders mails successfully we must first update the compliance audit actions date,
123
- Since the thread scheduler will trigger the logic of the reminders mails
124
- only if last invite action date will be equal or after compliance audit actions date
125
- */
126
- const updateComplianceAuditResponse = await compliance.services.audit.updateComplianceAuditActionsDate(recordId, complianceAuditActionOffsetInDays, context);
127
-
128
- if (updateComplianceAuditResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
129
- throw new Error(`Failed to update compliance audit date\n${updateComplianceAuditResponse}`);
130
- }
131
-
132
- const updateLastInviteActionResponse = await contractors.services.updateLastInviteActionDate(recordId, offsetInDays, context);
133
-
134
- if (updateLastInviteActionResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
135
- throw new Error(`Failed to update record invite date\n${updateLastInviteActionResponse}`);
136
- }
137
-
138
- await runThreadSchedulerForRecord(recordId);
139
- };
140
-
141
- const runOverAllRenewalDatesForRecord = async function(recordId, policyName) {
142
- const dates = timeUtils.getAutomaticRenewalsExpirationDates();
143
-
144
- for (const date of dates) {
145
- await updatePolicyExpiryDateForRecord(recordId, date, policyName);
146
- }
147
- };
148
-
149
- const updatePolicyExpiryDateForRecord = async function(recordId, expiryDate, policyName) {
150
- const updateResponse = await contractors.services.updateExpiryDate(recordId, expiryDate, policyName);
151
-
152
- if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
153
- throw new Error(`Record expiry date could not be updated\n${updateResponse}`);
154
- }
155
-
156
- await runThreadSchedulerForRecord(recordId);
157
- };
158
-
159
- const getHistoryEvents = async function(recordId, context) {
160
- const recordHistory = await contractors.services.getRecordHistory(recordId, context);
161
- expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
162
-
163
- return recordHistory.data.items.map(item => item.itemTitle).reverse();
164
- };
165
-
166
- const getFirstHistoryEventId = async function(recordId, context) {
167
- const recordHistory = await contractors.services.getRecordHistory(recordId, context);
168
- expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
169
- return recordHistory.data.items[recordHistory.data.items.length - 1].itemId;
170
- };
171
-
172
- const getLatestHistoryEventId = async function(recordId, context) {
173
- const recordHistory = await contractors.services.getRecordHistory(recordId, context);
174
- expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
175
- return recordHistory.data.items[0].itemId;
176
- };
177
-
178
- const getLatestRecordHistoryEventByItemTitle = async function(recordId, itemTitle, context) {
179
- const recordHistory = await contractors.services.getRecordHistory(recordId, context);
180
- expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
181
-
182
- const latestHistoryByTitle = recordHistory.data.items.find(historyItem => historyItem.itemTitle === itemTitle);
183
-
184
- if (!latestHistoryByTitle) {
185
- throw new Error(`History event with title ${itemTitle} not found`);
186
- }
187
-
188
- return latestHistoryByTitle;
189
- };
190
-
191
- const getLatestRecordHistoryEventIdByItemTitle = async function(recordId, itemTitle, context) {
192
- const latestHistoryByTitle = await getLatestRecordHistoryEventByItemTitle(recordId, itemTitle, context);
193
-
194
- return latestHistoryByTitle.itemId;
195
- };
196
-
197
- const getRecordHistoryItemById = async (recordId, itemId, context) => {
198
- const recordHistory = await contractors.services.getRecordHistory(recordId, context);
199
-
200
- return recordHistory.data.items.find(item => item.itemId === itemId);
201
- };
202
-
203
- const waitForAiAnalysisStatus = async (recordId, context, { expectedStatus = ocrStatuses.SUCCESS, isCheckPreviousCoi = false, retries = 30 } = {}) => {
204
- const timeout = expectedStatus === ocrStatuses.EXTRACTION ? 1 : 5;
205
- let isExpectedStatus = false;
206
- const isExpectingNoAnalysis = expectedStatus === ocrStatuses.UNKNOWN;
207
- let lastStatus = null;
208
-
209
- do {
210
- await timeUtils.waitFor(timeout).seconds;
211
- console.log(`Waiting for AI analysis extraction to be ${expectedStatus}, retries left: ${retries}`);
212
- const { status: httpStatus, data } = await aiAuditApi.getAiAnalysisProcess(recordId, context);
213
-
214
- if (httpStatus === httpResponseStatusCodes.NOT_FOUND) {
215
- if (isExpectingNoAnalysis) {
216
- isExpectedStatus = true;
217
- }
218
-
219
- break;
220
- }
221
-
222
- if (httpStatus === httpResponseStatusCodes.OK) {
223
- const processModel = data.aiAnalysisProcessModel;
224
- lastStatus = processModel.status;
225
-
226
- if (isExpectingNoAnalysis) {
227
- throw new Error(`Expected no AI analysis (UNKNOWN), but found status ${processModel.status}`);
228
- }
229
-
230
- if (isCheckPreviousCoi) {
231
- const extractionSteps = data.aiAnalysisCoiExtractionSteps || [];
232
- const [currentExtractionStep, previousExtractionStep] = extractionSteps;
233
-
234
- const isCurrentExtractionStatus = currentExtractionStep?.status === expectedStatus;
235
- const isPreviousExtractionStatus = previousExtractionStep?.status === expectedStatus;
236
- const isProcessStatus = processModel.status === expectedStatus;
237
-
238
- if (isCurrentExtractionStatus && isPreviousExtractionStatus && isProcessStatus) {
239
- isExpectedStatus = true;
240
- break;
241
- }
242
-
243
- continue;
244
- }
245
-
246
- if (processModel.status === expectedStatus) {
247
- isExpectedStatus = true;
248
- break;
249
- }
250
-
251
- if (processModel.status === ocrStatuses.FAILED && expectedStatus !== ocrStatuses.FAILED) {
252
- throw new Error(`AI Analysis failed. Expected status: ${expectedStatus}`);
253
- }
254
- }
255
- } while (--retries);
256
-
257
- if (!isExpectedStatus) {
258
- throw new Error(`AI analysis status not as expected For record ${recordId}. Expected: ${expectedStatus} but got: ${lastStatus}. Retries left: ${retries}`);
259
- }
260
- };
261
-
262
- const deleteAllRequestsInProject = async function(accountId, projectId, context) {
263
- const activationStatus = [activationStatuses.ACTIVE, activationStatuses.ARCHIVED, activationStatuses.DRAFT];
264
- const { data: requestsInAccount } = await requests.services.getRequestsByAccountId(accountId, context, activationStatus);
265
-
266
- for (const request of requestsInAccount) {
267
- if (request.projectInfo.projectId === projectId) {
268
- const response = await contractors.services.deleteByContractorId(request.record.contractorId, context);
269
-
270
- if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
271
- throw new Error(`Failed to delete request ${request.id}\n${response}`);
272
- }
273
- }
274
- }
275
- };
276
-
277
- const deleteAllRecordsInAccountByName = async (accountName, context) => {
278
- const accountId = await accounts.services.core.getAccountId(accountName, context);
279
-
280
- if (accountId) {
281
- await contractors.services.deleteAllRecordsInAccount(accountId, context);
282
- }
283
- };
284
-
285
- const overrideGap = async (recordId, reason, note, policyName, attributeName, context, { expiryType, expiryDate } = {}) => {
286
- const { data: record } = await contractors.services.getContractorById(recordId, context);
287
- const overrideModel = compliance.services.overrideGap.getWaiveModel(record, policyName, attributeName, reason, note, { expiryType, expiryDate });
288
- return compliance.services.overrideGap.overrideGap({ waiveRequestModel: overrideModel, context });
289
- };
290
-
291
- const makeExpiredTimedOverride = async (recordId, policyName, attributeName, context, { expiryDate = timeUtils.getOneDayAgoDate(timeUtils.formats.yearMonthDay) } = {}) => {
292
- await overrideGap(recordId, WAIVER_REASONS.BUSINESS_DECISION, 'timed', policyName, attributeName, context, {
293
- expiryType: EXPIRY_TYPES.SPECIFIC_DATE,
294
- expiryDate: timeUtils.getDateInOneDay(timeUtils.formats.yearMonthDay)
295
- });
296
-
297
- const { data: record } = await contractors.services.getContractorById(recordId, context);
298
- const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
299
-
300
- return compliance.services.overrideGap.updateOverrideExpiryDate(auditorContractorId, expiryDate, context);
301
- };
302
-
303
- const retractOverriddenGap = async (recordId, policyName, attributeName, context) => {
304
- const { data: record } = await contractors.services.getContractorById(recordId, context);
305
- const retractModel = compliance.services.overrideGap.getRetractModel(record, policyName, attributeName);
306
- return compliance.services.overrideGap.retractOverride(retractModel, context);
307
- };
308
-
309
- const getActiveOverrides = async (recordId, context) => {
310
- const overrides = await compliance.services.overrideGap.getOverridesByRecordId(recordId, context);
311
- return overrides.filter(override => !override.dateDeleted);
312
- };
313
-
314
- const waiveAllGaps = async (recordId, context) => {
315
- const { data: record } = await contractors.services.getContractorById(recordId, context);
316
- await compliance.services.overrideGap.waiveAll(record, context);
317
- };
318
-
319
- const createOverrideGapRequest = async (recordId, policyName, attributeName, requestReason, context) => {
320
- const { data: record } = await contractors.services.getContractorById(recordId, context);
321
- const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
322
- return compliance.services.overrideGap.createOverrideGapRequest(auditorContractorId, requestReason, record.dateModified, context);
323
- };
324
-
325
- const rejectOverrideGapRequest = async (overrideGapRequestId, rejectReason, recordId, context) => {
326
- const { data: record } = await contractors.services.getContractorById(recordId, context);
327
- return compliance.services.overrideGap.rejectOverrideGapRequest(overrideGapRequestId, rejectReason, record.dateModified, context);
328
- };
329
-
330
- const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, uploaderEmail, context, { uploaderContext, duplicateHandling } = {}) => {
331
- const recordResponse = await contractors.services.getContractorById(recordId, context);
332
- const recordDateModified = recordResponse.data.dateModified;
333
-
334
- const fileIds = [];
335
- for (const filePath of coiFilePaths) {
336
- fileIds.push(await coi.utils.uploadFileToStorage(recordId, filePath));
337
- }
338
-
339
- const submitResponse = fileIds && await coi.utils.submitCoiFilesUpload({
340
- recordId,
341
- fileIds,
342
- uploadedBy,
343
- uploaderEmail,
344
- uploaderContext,
345
- recordDateModified,
346
- duplicateHandling
347
- });
348
-
349
- return submitResponse;
350
- };
351
-
352
- const deleteRecordByName = async (companyName, tabId, context) => {
353
- const req = await requests.services.getRequestByName(companyName, tabId, context).catch(() => null);
354
-
355
- if (req?.record?.contractorId) {
356
- await contractors.services.deleteByContractorId(req.record.contractorId, context).catch(() => null);
357
- }
358
- };
359
-
360
- const advanceLastInviteActionToDay = async (recordId, days, context) => {
361
- await contractors.services.updateLastInviteActionDate(recordId, days, context);
362
- await threadScheduler.runJobForReminders([recordId]);
363
- };
364
-
365
- const createTenantUser = async (tenant, password, projectId, tabId, context) => {
366
- const noCoiRequired = null;
367
- const createContractorModel = requests.services.getCreateRequestModel(noCoiRequired, tenant, { tabId });
368
- const createdTenantRequestResponse = await requests.services.createRequest(createContractorModel, context);
369
- await usersAPI.tenants.services.getOrCreateTenantUser(projectId, tenant.email, tenant.companyName, createdTenantRequestResponse.data.id, context);
370
- return auth.services.getAuthCookie(tenant.email, password);
371
- };
372
-
373
- const requestRequirementsExtraction = async (recordId, context, { leaseFilePath, notes, docType, coiFilePath } = {}, { expectError } = {}) => {
374
- const leaseDocument = await uploadFile.services.stageDocumentToTempBucket(recordId, context, { filePath: leaseFilePath });
375
- const coiDoc = coiFilePath
376
- ? { tempFileName: await coi.utils.stageMergedCertificate(recordId, coiFilePath, context) }
377
- : null;
378
-
379
- const extractionRequestModel = new ExtractionRequestModel({ ... leaseDocument, docType, notes, coiDoc });
380
- const requestResponse = await requirements.lease.services.requestLeaseExtraction(recordId, extractionRequestModel, context, { expectError });
381
-
382
- if (expectError) {
383
- return requestResponse;
384
- }
385
-
386
- const { leaseId } = await requirements.lease.services.getLeaseByRecordId(recordId, context);
387
-
388
- return leaseId;
389
- };
390
-
391
- const requestTabRequirementsExtraction = async (tabId, context,
392
- { leaseFilePath = DEFAULT_LEASE_PATH, requirementName, notes, docType = RELATED_DOC_TYPES.SERVICE_AGREEMENT } = {}, { expectError, readContext = context } = {}) => {
393
- const stagedDocument = await uploadFile.services.stageDocumentToTempBucket(tabId, context, { filePath: leaseFilePath });
394
- const tabExtractionRequestModel = new TabExtractionRequestModel({ ... stagedDocument, requirementName, docType, notes });
395
- const existingLeases = expectError ? [] : await requirements.lease.services.getLeasesByTabId(tabId, readContext, { openOnly: false });
396
- const existingLeaseIds = new Set(existingLeases.map(({ leaseId }) => leaseId));
397
- const requestResponse = await requirements.lease.services.requestTabLeaseExtraction(tabId, tabExtractionRequestModel, context, { expectError });
398
-
399
- if (expectError) {
400
- return { requestResponse, stagedDocument };
401
- }
402
-
403
- const openLeases = await requirements.lease.services.getLeasesByTabId(tabId, readContext);
404
- const createdLease = openLeases.find(({ leaseId }) => !existingLeaseIds.has(leaseId));
405
-
406
- if (!createdLease) {
407
- throw Error(`No new tab-level lease found for tab: ${tabId}`);
408
- }
409
-
410
- return createdLease.leaseId;
411
- };
412
-
413
- const cancelOpenTabRequests = async (tabId, icsContext) => {
414
- const openLeases = await requirements.lease.services.getLeasesByTabId(tabId, icsContext);
415
-
416
- await Promise.all(openLeases.map(({ leaseId }) =>
417
- requirements.lease.services.cancelExtractionRequest(leaseId, icsContext, { expectError: true })));
418
- };
419
-
420
- module.exports = {
421
- makeRecordNotResponsive,
422
- makeRecordAboutToExpire,
423
- resendInvitationByRecordId,
424
- runOverAllRenewalDatesForRecord,
425
- editRequestAndRecordDetails,
426
- updateInviteDate,
427
- updatePolicyExpiryDateForRecord,
428
- getHistoryEvents,
429
- getFirstHistoryEventId,
430
- getLatestHistoryEventId,
431
- updateLastInviteActionDate,
432
- waitForAiAnalysisStatus,
433
- deleteAllRequestsInProject,
434
- deleteAllRecordsInAccountByName,
435
- getLatestRecordHistoryEventIdByItemTitle,
436
- getRecordHistoryItemById,
437
- getLatestRecordHistoryEventByItemTitle,
438
- waiveAllGaps,
439
- overrideGap,
440
- makeExpiredTimedOverride,
441
- retractOverriddenGap,
442
- getActiveOverrides,
443
- createOverrideGapRequest,
444
- rejectOverrideGapRequest,
445
- uploadMultipleCoiFiles,
446
- createTenantUser,
447
- deleteRecordByName,
448
- advanceLastInviteActionToDay,
449
- requestRequirementsExtraction,
450
- requestTabRequirementsExtraction,
451
- cancelOpenTabRequests
452
- };
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 ocrStatuses = require('../../consts/analysisStatuses');
7
+ const contractors = require('../../../saas/internal-api/contractors');
8
+ const compliance = require('../../../saas/internal-api/compliance');
9
+ const aiAuditApi = require('../../../saas/internal-api/compliance/api/audit/aiAudit/aiAudit.api');
10
+ const requests = require('../../../saas/internal-api/requests');
11
+ const requirements = require('../../../saas/internal-api/requirements');
12
+ const uploadFile = require('../../../saas/internal-api/uploadFiles');
13
+ const coi = require('../../../saas/internal-api/coi');
14
+ const usersAPI = require('../../../saas/internal-api/users/index');
15
+ const auth = require('../../../saas/internal-api/auth/index');
16
+ const accounts = require('../../../saas/internal-api/accounts');
17
+ const activationStatuses = require('../../../common/consts/activationStatuses');
18
+ const recordTypes = require('../../../common/consts/recordTypes');
19
+ const policyNames = require('../../../defaults/index').polices;
20
+ const { ExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/extraction.request.model');
21
+ const { TabExtractionRequestModel } = require('../../../saas/internal-api/requirements/models/tab.extraction.request.model');
22
+ const { DEFAULT_LEASE_PATH } = require('../../../saas/internal-api/requirements/consts/consts');
23
+ const { RELATED_DOC_TYPES } = require('../../../saas/internal-api/uploadFiles/consts');
24
+ const { WAIVER_REASONS, EXPIRY_TYPES } = compliance.models.waive;
25
+
26
+ const makeRecordNotResponsive = async function(recordId, context) {
27
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
28
+ const isTenant = record.recordType === recordTypes.TENANTS;
29
+
30
+ const offsetInDaysList = isTenant ?
31
+ timeUtils.getInviteActionOffsetInDaysForNotResponsiveTenant() :
32
+ timeUtils.getInviteActionOffsetInDaysForNotResponsiveVendor();
33
+
34
+ for (const offsetInDays of offsetInDaysList) {
35
+ await updateLastInviteActionDate(recordId, offsetInDays, context);
36
+ }
37
+ };
38
+
39
+ const runThreadSchedulerForRecord = async recordId => {
40
+ const threadSchedulerResponse = await threadScheduler.runForRecords([recordId]);
41
+
42
+ if (threadSchedulerResponse.status !== httpResponseStatusCodes.OK) {
43
+ throw new Error(`Thread scheduler has failed to run\n${threadSchedulerResponse}`);
44
+ }
45
+
46
+ await timeUtils.waitFor(2.5).seconds; // calls for the same records can override each other
47
+ };
48
+
49
+ const makeRecordAboutToExpire = async (recordId, policyExpiryDate, { policyName = policyNames.generalLiability } = {}) => {
50
+ const updateResponse = await contractors.services.updateExpiryDate(recordId, policyExpiryDate, policyName);
51
+
52
+ if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
53
+ throw new Error(`Record expiry date could not be updated\n${updateResponse}`);
54
+ }
55
+
56
+ await runThreadSchedulerForRecord(recordId);
57
+ };
58
+
59
+ const resendInvitationByRecordId = async (recordId, tabId, context) => {
60
+ const { id: requestId } = await requests.services.getRequestFromTabByRecordId(recordId, tabId, context);
61
+ const recordModifyDateVerificationModel = await contractors.services.getRecordVerificationModel(recordId, context);
62
+
63
+ const resendInvitationResponse = await contractors.services.resendInvitation(requestId, recordModifyDateVerificationModel, context);
64
+
65
+ if (resendInvitationResponse.status !== httpResponseStatusCodes.OK) {
66
+ throw new Error(`Failed to resend invitation for record: ${resendInvitationResponse.statusText}`);
67
+ }
68
+
69
+ return resendInvitationResponse;
70
+ };
71
+
72
+ const editRequestAndRecordDetails = async function(request, recordConfig, context, { isDraft, expectError } = {}) {
73
+ const tabModel = new requests.models.TabModel(request.tab.type);
74
+ const recordDetailsModel = contractors.services.getContractorDetailsModel(recordConfig);
75
+
76
+ const record = isDraft ?
77
+ new contractors.models.edit.DraftRecordModel(
78
+ request.record.contractorId,
79
+ request.record.recordType,
80
+ recordConfig.company,
81
+ recordConfig.emailAddress,
82
+ recordDetailsModel,
83
+ isDraft,
84
+ recordConfig.requirementsAction
85
+ ) :
86
+ new contractors.models.edit.ContractorModel(
87
+ request.record.contractorId,
88
+ request.record.recordType,
89
+ recordConfig.company,
90
+ recordConfig.emailAddress,
91
+ recordDetailsModel
92
+ );
93
+
94
+ const requestEditModel = new requests.models.RequestModel(request.id, record, tabModel, {});
95
+
96
+ const editRequestResponse = await requests.services.editRequestAndRecordDetails(requestEditModel, context);
97
+
98
+ if (editRequestResponse.status !== httpResponseStatusCodes.OK && !expectError) {
99
+ throw Error(`Failed to edit record \nStatus: ${editRequestResponse.status}\n${JSON.stringify(editRequestResponse.data)}`);
100
+ }
101
+
102
+ return editRequestResponse;
103
+ };
104
+
105
+ const updateInviteDate = async function(recordId, inviteDate, context) {
106
+ await timeUtils.waitFor(1).seconds;
107
+ const updateResponse = await contractors.services.updateInviteDate(recordId, inviteDate, context);
108
+
109
+ if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
110
+ throw new Error(`Failed to update record invite date\n${updateResponse}`);
111
+ }
112
+
113
+ await runThreadSchedulerForRecord(recordId);
114
+ };
115
+
116
+ const updateLastInviteActionDate = async function(recordId, offsetInDays, context) {
117
+ await timeUtils.waitFor(1).seconds;
118
+ //In order to prevent situations where the date of the compliance audit action is equal or greater than the date of the last mail send audit,
119
+ //we move back another day!!
120
+ const complianceAuditActionOffsetInDays = offsetInDays + 1;
121
+ /*
122
+ To run the reminders mails successfully we must first update the compliance audit actions date,
123
+ Since the thread scheduler will trigger the logic of the reminders mails
124
+ only if last invite action date will be equal or after compliance audit actions date
125
+ */
126
+ const updateComplianceAuditResponse = await compliance.services.audit.updateComplianceAuditActionsDate(recordId, complianceAuditActionOffsetInDays, context);
127
+
128
+ if (updateComplianceAuditResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
129
+ throw new Error(`Failed to update compliance audit date\n${updateComplianceAuditResponse}`);
130
+ }
131
+
132
+ const updateLastInviteActionResponse = await contractors.services.updateLastInviteActionDate(recordId, offsetInDays, context);
133
+
134
+ if (updateLastInviteActionResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
135
+ throw new Error(`Failed to update record invite date\n${updateLastInviteActionResponse}`);
136
+ }
137
+
138
+ await runThreadSchedulerForRecord(recordId);
139
+ };
140
+
141
+ const runOverAllRenewalDatesForRecord = async function(recordId, policyName) {
142
+ const dates = timeUtils.getAutomaticRenewalsExpirationDates();
143
+
144
+ for (const date of dates) {
145
+ await updatePolicyExpiryDateForRecord(recordId, date, policyName);
146
+ }
147
+ };
148
+
149
+ const updatePolicyExpiryDateForRecord = async function(recordId, expiryDate, policyName) {
150
+ const updateResponse = await contractors.services.updateExpiryDate(recordId, expiryDate, policyName);
151
+
152
+ if (updateResponse.status !== httpResponseStatusCodes.NO_CONTENT) {
153
+ throw new Error(`Record expiry date could not be updated\n${updateResponse}`);
154
+ }
155
+
156
+ await runThreadSchedulerForRecord(recordId);
157
+ };
158
+
159
+ const getHistoryEvents = async function(recordId, context) {
160
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
161
+ expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
162
+
163
+ return recordHistory.data.items.map(item => item.itemTitle).reverse();
164
+ };
165
+
166
+ const getFirstHistoryEventId = async function(recordId, context) {
167
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
168
+ expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
169
+ return recordHistory.data.items[recordHistory.data.items.length - 1].itemId;
170
+ };
171
+
172
+ const getLatestHistoryEventId = async function(recordId, context) {
173
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
174
+ expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
175
+ return recordHistory.data.items[0].itemId;
176
+ };
177
+
178
+ const getLatestRecordHistoryEventByItemTitle = async function(recordId, itemTitle, context) {
179
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
180
+ expect(recordHistory.status, 'Expected record history response status to equal 200.').to.equal(httpResponseStatusCodes.OK);
181
+
182
+ const latestHistoryByTitle = recordHistory.data.items.find(historyItem => historyItem.itemTitle === itemTitle);
183
+
184
+ if (!latestHistoryByTitle) {
185
+ throw new Error(`History event with title ${itemTitle} not found`);
186
+ }
187
+
188
+ return latestHistoryByTitle;
189
+ };
190
+
191
+ const getLatestRecordHistoryEventIdByItemTitle = async function(recordId, itemTitle, context) {
192
+ const latestHistoryByTitle = await getLatestRecordHistoryEventByItemTitle(recordId, itemTitle, context);
193
+
194
+ return latestHistoryByTitle.itemId;
195
+ };
196
+
197
+ const getRecordHistoryItemById = async (recordId, itemId, context) => {
198
+ const recordHistory = await contractors.services.getRecordHistory(recordId, context);
199
+
200
+ return recordHistory.data.items.find(item => item.itemId === itemId);
201
+ };
202
+
203
+ const waitForAiAnalysisStatus = async (recordId, context, { expectedStatus = ocrStatuses.SUCCESS, isCheckPreviousCoi = false, retries = 30 } = {}) => {
204
+ const timeout = expectedStatus === ocrStatuses.EXTRACTION ? 1 : 5;
205
+ let isExpectedStatus = false;
206
+ const isExpectingNoAnalysis = expectedStatus === ocrStatuses.UNKNOWN;
207
+ let lastStatus = null;
208
+
209
+ do {
210
+ await timeUtils.waitFor(timeout).seconds;
211
+ console.log(`Waiting for AI analysis extraction to be ${expectedStatus}, retries left: ${retries}`);
212
+ const { status: httpStatus, data } = await aiAuditApi.getAiAnalysisProcess(recordId, context);
213
+
214
+ if (httpStatus === httpResponseStatusCodes.NOT_FOUND) {
215
+ if (isExpectingNoAnalysis) {
216
+ isExpectedStatus = true;
217
+ }
218
+
219
+ break;
220
+ }
221
+
222
+ if (httpStatus === httpResponseStatusCodes.OK) {
223
+ const processModel = data.aiAnalysisProcessModel;
224
+ lastStatus = processModel.status;
225
+
226
+ if (isExpectingNoAnalysis) {
227
+ throw new Error(`Expected no AI analysis (UNKNOWN), but found status ${processModel.status}`);
228
+ }
229
+
230
+ if (isCheckPreviousCoi) {
231
+ const extractionSteps = data.aiAnalysisCoiExtractionSteps || [];
232
+ const [currentExtractionStep, previousExtractionStep] = extractionSteps;
233
+
234
+ const isCurrentExtractionStatus = currentExtractionStep?.status === expectedStatus;
235
+ const isPreviousExtractionStatus = previousExtractionStep?.status === expectedStatus;
236
+ const isProcessStatus = processModel.status === expectedStatus;
237
+
238
+ if (isCurrentExtractionStatus && isPreviousExtractionStatus && isProcessStatus) {
239
+ isExpectedStatus = true;
240
+ break;
241
+ }
242
+
243
+ continue;
244
+ }
245
+
246
+ if (processModel.status === expectedStatus) {
247
+ isExpectedStatus = true;
248
+ break;
249
+ }
250
+
251
+ if (processModel.status === ocrStatuses.FAILED && expectedStatus !== ocrStatuses.FAILED) {
252
+ throw new Error(`AI Analysis failed. Expected status: ${expectedStatus}`);
253
+ }
254
+ }
255
+ } while (--retries);
256
+
257
+ if (!isExpectedStatus) {
258
+ throw new Error(`AI analysis status not as expected For record ${recordId}. Expected: ${expectedStatus} but got: ${lastStatus}. Retries left: ${retries}`);
259
+ }
260
+ };
261
+
262
+ const deleteAllRequestsInProject = async function(accountId, projectId, context) {
263
+ const activationStatus = [activationStatuses.ACTIVE, activationStatuses.ARCHIVED, activationStatuses.DRAFT];
264
+ const { data: requestsInAccount } = await requests.services.getRequestsByAccountId(accountId, context, activationStatus);
265
+
266
+ for (const request of requestsInAccount) {
267
+ if (request.projectInfo.projectId === projectId) {
268
+ const response = await contractors.services.deleteByContractorId(request.record.contractorId, context);
269
+
270
+ if (response.status !== httpResponseStatusCodes.NO_CONTENT) {
271
+ throw new Error(`Failed to delete request ${request.id}\n${response}`);
272
+ }
273
+ }
274
+ }
275
+ };
276
+
277
+ const deleteAllRecordsInAccountByName = async (accountName, context) => {
278
+ const accountId = await accounts.services.core.getAccountId(accountName, context);
279
+
280
+ if (accountId) {
281
+ await contractors.services.deleteAllRecordsInAccount(accountId, context);
282
+ }
283
+ };
284
+
285
+ const overrideGap = async (recordId, reason, note, policyName, attributeName, context, { expiryType, expiryDate } = {}) => {
286
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
287
+ const overrideModel = compliance.services.overrideGap.getWaiveModel(record, policyName, attributeName, reason, note, { expiryType, expiryDate });
288
+ return compliance.services.overrideGap.overrideGap({ waiveRequestModel: overrideModel, context });
289
+ };
290
+
291
+ const makeExpiredTimedOverride = async (recordId, policyName, attributeName, context, { expiryDate = timeUtils.getOneDayAgoDate(timeUtils.formats.yearMonthDay) } = {}) => {
292
+ await overrideGap(recordId, WAIVER_REASONS.BUSINESS_DECISION, 'timed', policyName, attributeName, context, {
293
+ expiryType: EXPIRY_TYPES.SPECIFIC_DATE,
294
+ expiryDate: timeUtils.getDateInOneDay(timeUtils.formats.yearMonthDay)
295
+ });
296
+
297
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
298
+ const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
299
+
300
+ return compliance.services.overrideGap.updateOverrideExpiryDate(auditorContractorId, expiryDate, context);
301
+ };
302
+
303
+ const retractOverriddenGap = async (recordId, policyName, attributeName, context) => {
304
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
305
+ const retractModel = compliance.services.overrideGap.getRetractModel(record, policyName, attributeName);
306
+ return compliance.services.overrideGap.retractOverride(retractModel, context);
307
+ };
308
+
309
+ const getActiveOverrides = async (recordId, context) => {
310
+ const overrides = await compliance.services.overrideGap.getOverridesByRecordId(recordId, context);
311
+ return overrides.filter(override => !override.dateDeleted);
312
+ };
313
+
314
+ const waiveAllGaps = async (recordId, context) => {
315
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
316
+ await compliance.services.overrideGap.waiveAll(record, context);
317
+ };
318
+
319
+ const createOverrideGapRequest = async (recordId, policyName, attributeName, requestReason, context) => {
320
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
321
+ const auditorContractorId = compliance.services.overrideGap.getAuditorContractorIdFromGap(record, policyName, attributeName);
322
+ return compliance.services.overrideGap.createOverrideGapRequest(auditorContractorId, requestReason, record.dateModified, context);
323
+ };
324
+
325
+ const rejectOverrideGapRequest = async (overrideGapRequestId, rejectReason, recordId, context) => {
326
+ const { data: record } = await contractors.services.getContractorById(recordId, context);
327
+ return compliance.services.overrideGap.rejectOverrideGapRequest(overrideGapRequestId, rejectReason, record.dateModified, context);
328
+ };
329
+
330
+ const uploadMultipleCoiFiles = async (recordId, coiFilePaths, uploadedBy, uploaderEmail, context, { uploaderContext, duplicateHandling } = {}) => {
331
+ const recordResponse = await contractors.services.getContractorById(recordId, context);
332
+ const recordDateModified = recordResponse.data.dateModified;
333
+
334
+ const fileIds = [];
335
+ for (const filePath of coiFilePaths) {
336
+ fileIds.push(await coi.utils.uploadFileToStorage(recordId, filePath));
337
+ }
338
+
339
+ const submitResponse = fileIds && await coi.utils.submitCoiFilesUpload({
340
+ recordId,
341
+ fileIds,
342
+ uploadedBy,
343
+ uploaderEmail,
344
+ uploaderContext,
345
+ recordDateModified,
346
+ duplicateHandling
347
+ });
348
+
349
+ return submitResponse;
350
+ };
351
+
352
+ const deleteRecordByName = async (companyName, tabId, context) => {
353
+ const req = await requests.services.getRequestByName(companyName, tabId, context).catch(() => null);
354
+
355
+ if (req?.record?.contractorId) {
356
+ await contractors.services.deleteByContractorId(req.record.contractorId, context).catch(() => null);
357
+ }
358
+ };
359
+
360
+ const advanceLastInviteActionToDay = async (recordId, days, context) => {
361
+ await contractors.services.updateLastInviteActionDate(recordId, days, context);
362
+ await threadScheduler.runJobForReminders([recordId]);
363
+ };
364
+
365
+ const createTenantUser = async (tenant, password, projectId, tabId, context) => {
366
+ const noCoiRequired = null;
367
+ const createContractorModel = requests.services.getCreateRequestModel(noCoiRequired, tenant, { tabId });
368
+ const createdTenantRequestResponse = await requests.services.createRequest(createContractorModel, context);
369
+ await usersAPI.tenants.services.getOrCreateTenantUser(projectId, tenant.email, tenant.companyName, createdTenantRequestResponse.data.id, context);
370
+ return auth.services.getAuthCookie(tenant.email, password);
371
+ };
372
+
373
+ const requestRequirementsExtraction = async (recordId, context, { leaseFilePath, notes, docType, coiFilePath } = {}, { expectError } = {}) => {
374
+ const leaseDocument = await uploadFile.services.stageDocumentToTempBucket(recordId, context, { filePath: leaseFilePath });
375
+ const coiDoc = coiFilePath
376
+ ? { tempFileName: await coi.utils.stageMergedCertificate(recordId, coiFilePath, context) }
377
+ : null;
378
+
379
+ const extractionRequestModel = new ExtractionRequestModel({ ... leaseDocument, docType, notes, coiDoc });
380
+ const requestResponse = await requirements.lease.services.requestLeaseExtraction(recordId, extractionRequestModel, context, { expectError });
381
+
382
+ if (expectError) {
383
+ return requestResponse;
384
+ }
385
+
386
+ const { leaseId } = await requirements.lease.services.getLeaseByRecordId(recordId, context);
387
+
388
+ return leaseId;
389
+ };
390
+
391
+ const requestTabRequirementsExtraction = async (tabId, context,
392
+ { leaseFilePath = DEFAULT_LEASE_PATH, requirementName, notes, docType = RELATED_DOC_TYPES.SERVICE_AGREEMENT } = {}, { expectError, readContext = context } = {}) => {
393
+ const stagedDocument = await uploadFile.services.stageDocumentToTempBucket(tabId, context, { filePath: leaseFilePath });
394
+ const tabExtractionRequestModel = new TabExtractionRequestModel({ ... stagedDocument, requirementName, docType, notes });
395
+ const existingLeases = expectError ? [] : await requirements.lease.services.getLeasesByTabId(tabId, readContext, { openOnly: false });
396
+ const existingLeaseIds = new Set(existingLeases.map(({ leaseId }) => leaseId));
397
+ const requestResponse = await requirements.lease.services.requestTabLeaseExtraction(tabId, tabExtractionRequestModel, context, { expectError });
398
+
399
+ if (expectError) {
400
+ return { requestResponse, stagedDocument };
401
+ }
402
+
403
+ const openLeases = await requirements.lease.services.getLeasesByTabId(tabId, readContext);
404
+ const createdLease = openLeases.find(({ leaseId }) => !existingLeaseIds.has(leaseId));
405
+
406
+ if (!createdLease) {
407
+ throw Error(`No new tab-level lease found for tab: ${tabId}`);
408
+ }
409
+
410
+ return createdLease.leaseId;
411
+ };
412
+
413
+ const cancelOpenTabRequests = async (tabId, icsContext) => {
414
+ const openLeases = await requirements.lease.services.getLeasesByTabId(tabId, icsContext);
415
+
416
+ await Promise.all(openLeases.map(({ leaseId }) =>
417
+ requirements.lease.services.cancelExtractionRequest(leaseId, icsContext, { expectError: true })));
418
+ };
419
+
420
+ module.exports = {
421
+ makeRecordNotResponsive,
422
+ makeRecordAboutToExpire,
423
+ resendInvitationByRecordId,
424
+ runOverAllRenewalDatesForRecord,
425
+ editRequestAndRecordDetails,
426
+ updateInviteDate,
427
+ updatePolicyExpiryDateForRecord,
428
+ getHistoryEvents,
429
+ getFirstHistoryEventId,
430
+ getLatestHistoryEventId,
431
+ updateLastInviteActionDate,
432
+ waitForAiAnalysisStatus,
433
+ deleteAllRequestsInProject,
434
+ deleteAllRecordsInAccountByName,
435
+ getLatestRecordHistoryEventIdByItemTitle,
436
+ getRecordHistoryItemById,
437
+ getLatestRecordHistoryEventByItemTitle,
438
+ waiveAllGaps,
439
+ overrideGap,
440
+ makeExpiredTimedOverride,
441
+ retractOverriddenGap,
442
+ getActiveOverrides,
443
+ createOverrideGapRequest,
444
+ rejectOverrideGapRequest,
445
+ uploadMultipleCoiFiles,
446
+ createTenantUser,
447
+ deleteRecordByName,
448
+ advanceLastInviteActionToDay,
449
+ requestRequirementsExtraction,
450
+ requestTabRequirementsExtraction,
451
+ cancelOpenTabRequests
452
+ };