@tomei/rental 0.17.4 → 0.17.5

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 (295) hide show
  1. package/.commitlintrc.json +23 -23
  2. package/.gitlab-ci.yml +16 -16
  3. package/.husky/commit-msg +9 -9
  4. package/.husky/pre-commit +7 -7
  5. package/.prettierrc +4 -4
  6. package/Jenkinsfile +51 -51
  7. package/README.md +8 -8
  8. package/dist/ClassMappings/ItemClassMap.d.ts +4 -0
  9. package/dist/ClassMappings/ItemClassMap.js +8 -0
  10. package/dist/ClassMappings/ItemClassMap.js.map +1 -0
  11. package/dist/ClassMappings/index.d.ts +2 -0
  12. package/dist/ClassMappings/index.js +6 -0
  13. package/dist/ClassMappings/index.js.map +1 -0
  14. package/dist/components/agreement/agreement.d.ts +27 -0
  15. package/dist/components/agreement/agreement.js +120 -0
  16. package/dist/components/agreement/agreement.js.map +1 -0
  17. package/dist/components/agreement/agreement.repository.d.ts +8 -0
  18. package/dist/components/agreement/agreement.repository.js +52 -0
  19. package/dist/components/agreement/agreement.repository.js.map +1 -0
  20. package/dist/components/agreement-history/agreement-history.d.ts +17 -0
  21. package/dist/components/agreement-history/agreement-history.js +40 -0
  22. package/dist/components/agreement-history/agreement-history.js.map +1 -0
  23. package/dist/components/agreement-history/agreement-history.repository.d.ts +8 -0
  24. package/dist/components/agreement-history/agreement-history.repository.js +52 -0
  25. package/dist/components/agreement-history/agreement-history.repository.js.map +1 -0
  26. package/dist/components/agreement-signature/agreement-signature.d.ts +27 -0
  27. package/dist/components/agreement-signature/agreement-signature.js +99 -0
  28. package/dist/components/agreement-signature/agreement-signature.js.map +1 -0
  29. package/dist/components/agreement-signature/agreement-signature.repository.d.ts +8 -0
  30. package/dist/components/agreement-signature/agreement-signature.repository.js +53 -0
  31. package/dist/components/agreement-signature/agreement-signature.repository.js.map +1 -0
  32. package/dist/components/booking/booking.d.ts +46 -0
  33. package/dist/components/booking/booking.js +289 -0
  34. package/dist/components/booking/booking.js.map +1 -0
  35. package/dist/components/booking/booking.repository.d.ts +8 -0
  36. package/dist/components/booking/booking.repository.js +52 -0
  37. package/dist/components/booking/booking.repository.js.map +1 -0
  38. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.d.ts +32 -0
  39. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.js +106 -0
  40. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.js.map +1 -0
  41. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.repository.d.ts +9 -0
  42. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.repository.js +62 -0
  43. package/dist/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.repository.js.map +1 -0
  44. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.d.ts +22 -0
  45. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.js +89 -0
  46. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.js.map +1 -0
  47. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.repository.d.ts +9 -0
  48. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.repository.js +63 -0
  49. package/dist/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.repository.js.map +1 -0
  50. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.d.ts +30 -0
  51. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.js +208 -0
  52. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.js.map +1 -0
  53. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.repository.d.ts +9 -0
  54. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.repository.js +63 -0
  55. package/dist/components/hirer-change-request-signature/hirer-change-request-signature.repository.js.map +1 -0
  56. package/dist/components/joint-hirer/joint-hirer.d.ts +26 -0
  57. package/dist/components/joint-hirer/joint-hirer.js +137 -0
  58. package/dist/components/joint-hirer/joint-hirer.js.map +1 -0
  59. package/dist/components/joint-hirer/joint-hirer.repository.d.ts +8 -0
  60. package/dist/components/joint-hirer/joint-hirer.repository.js +52 -0
  61. package/dist/components/joint-hirer/joint-hirer.repository.js.map +1 -0
  62. package/dist/components/rental/rental.d.ts +72 -0
  63. package/dist/components/rental/rental.js +844 -0
  64. package/dist/components/rental/rental.js.map +1 -0
  65. package/dist/components/rental/rental.repository.d.ts +8 -0
  66. package/dist/components/rental/rental.repository.js +52 -0
  67. package/dist/components/rental/rental.repository.js.map +1 -0
  68. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.d.ts +71 -0
  69. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.js +531 -0
  70. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.js.map +1 -0
  71. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.repository.d.ts +9 -0
  72. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.repository.js +62 -0
  73. package/dist/components/rental-hirer-change-request/rental-hirer-change-request.repository.js.map +1 -0
  74. package/dist/components/rental-price/rental-price.d.ts +18 -0
  75. package/dist/components/rental-price/rental-price.js +66 -0
  76. package/dist/components/rental-price/rental-price.js.map +1 -0
  77. package/dist/components/rental-price/rental-price.repository.d.ts +8 -0
  78. package/dist/components/rental-price/rental-price.repository.js +52 -0
  79. package/dist/components/rental-price/rental-price.repository.js.map +1 -0
  80. package/dist/database.d.ts +4 -0
  81. package/dist/database.js +37 -0
  82. package/dist/database.js.map +1 -0
  83. package/dist/enum/account-type.enum.d.ts +4 -0
  84. package/dist/enum/account-type.enum.js +9 -0
  85. package/dist/enum/account-type.enum.js.map +1 -0
  86. package/dist/enum/aggrement-status.enum.d.ts +5 -0
  87. package/dist/enum/aggrement-status.enum.js +10 -0
  88. package/dist/enum/aggrement-status.enum.js.map +1 -0
  89. package/dist/enum/agreement-signature-status.enum.d.ts +4 -0
  90. package/dist/enum/agreement-signature-status.enum.js +9 -0
  91. package/dist/enum/agreement-signature-status.enum.js.map +1 -0
  92. package/dist/enum/agreement-signature-verification-method.enum.d.ts +4 -0
  93. package/dist/enum/agreement-signature-verification-method.enum.js +9 -0
  94. package/dist/enum/agreement-signature-verification-method.enum.js.map +1 -0
  95. package/dist/enum/booking.enum.d.ts +5 -0
  96. package/dist/enum/booking.enum.js +10 -0
  97. package/dist/enum/booking.enum.js.map +1 -0
  98. package/dist/enum/hirer-type.enum.d.ts +4 -0
  99. package/dist/enum/hirer-type.enum.js +9 -0
  100. package/dist/enum/hirer-type.enum.js.map +1 -0
  101. package/dist/enum/index.d.ts +11 -0
  102. package/dist/enum/index.js +24 -0
  103. package/dist/enum/index.js.map +1 -0
  104. package/dist/enum/rental-hirer-change-request-hirer-role.d.ts +4 -0
  105. package/dist/enum/rental-hirer-change-request-hirer-role.js +9 -0
  106. package/dist/enum/rental-hirer-change-request-hirer-role.js.map +1 -0
  107. package/dist/enum/rental-hirer-change-request-status.d.ts +7 -0
  108. package/dist/enum/rental-hirer-change-request-status.js +12 -0
  109. package/dist/enum/rental-hirer-change-request-status.js.map +1 -0
  110. package/dist/enum/rental-hirer-change-request-type.d.ts +4 -0
  111. package/dist/enum/rental-hirer-change-request-type.js +9 -0
  112. package/dist/enum/rental-hirer-change-request-type.js.map +1 -0
  113. package/dist/enum/rental-status.enum.d.ts +9 -0
  114. package/dist/enum/rental-status.enum.js +14 -0
  115. package/dist/enum/rental-status.enum.js.map +1 -0
  116. package/dist/interfaces/agreemeent-signature-attr.interface.d.ts +14 -0
  117. package/dist/interfaces/agreemeent-signature-attr.interface.js +3 -0
  118. package/dist/interfaces/agreemeent-signature-attr.interface.js.map +1 -0
  119. package/dist/interfaces/agreement-attr.interface.d.ts +7 -0
  120. package/dist/interfaces/agreement-attr.interface.js +3 -0
  121. package/dist/interfaces/agreement-attr.interface.js.map +1 -0
  122. package/dist/interfaces/agreement-history-attr.interface.d.ts +7 -0
  123. package/dist/interfaces/agreement-history-attr.interface.js +3 -0
  124. package/dist/interfaces/agreement-history-attr.interface.js.map +1 -0
  125. package/dist/interfaces/booking-attr.interface.d.ts +18 -0
  126. package/dist/interfaces/booking-attr.interface.js +3 -0
  127. package/dist/interfaces/booking-attr.interface.js.map +1 -0
  128. package/dist/interfaces/booking-find-all-search-attr.interface.d.ts +12 -0
  129. package/dist/interfaces/booking-find-all-search-attr.interface.js +3 -0
  130. package/dist/interfaces/booking-find-all-search-attr.interface.js.map +1 -0
  131. package/dist/interfaces/hirer-change-request-new-hirer-attr.interface.d.ts +15 -0
  132. package/dist/interfaces/hirer-change-request-new-hirer-attr.interface.js +3 -0
  133. package/dist/interfaces/hirer-change-request-new-hirer-attr.interface.js.map +1 -0
  134. package/dist/interfaces/hirer-change-request-remove-hirer-attr.interface.d.ts +5 -0
  135. package/dist/interfaces/hirer-change-request-remove-hirer-attr.interface.js +3 -0
  136. package/dist/interfaces/hirer-change-request-remove-hirer-attr.interface.js.map +1 -0
  137. package/dist/interfaces/hirer-change-request-signature-attr.interface.d.ts +14 -0
  138. package/dist/interfaces/hirer-change-request-signature-attr.interface.js +3 -0
  139. package/dist/interfaces/hirer-change-request-signature-attr.interface.js.map +1 -0
  140. package/dist/interfaces/index.d.ts +14 -0
  141. package/dist/interfaces/index.js +3 -0
  142. package/dist/interfaces/index.js.map +1 -0
  143. package/dist/interfaces/joint-hirer-attr.interface.d.ts +11 -0
  144. package/dist/interfaces/joint-hirer-attr.interface.js +3 -0
  145. package/dist/interfaces/joint-hirer-attr.interface.js.map +1 -0
  146. package/dist/interfaces/rental-attr.interface.d.ts +24 -0
  147. package/dist/interfaces/rental-attr.interface.js +3 -0
  148. package/dist/interfaces/rental-attr.interface.js.map +1 -0
  149. package/dist/interfaces/rental-find-all-search-attr.interface.d.ts +10 -0
  150. package/dist/interfaces/rental-find-all-search-attr.interface.js +3 -0
  151. package/dist/interfaces/rental-find-all-search-attr.interface.js.map +1 -0
  152. package/dist/interfaces/rental-hirer-change-request.attr.interface.d.ts +16 -0
  153. package/dist/interfaces/rental-hirer-change-request.attr.interface.js +3 -0
  154. package/dist/interfaces/rental-hirer-change-request.attr.interface.js.map +1 -0
  155. package/dist/interfaces/rental-hirer-change-request.update.interface.d.ts +4 -0
  156. package/dist/interfaces/rental-hirer-change-request.update.interface.js +3 -0
  157. package/dist/interfaces/rental-hirer-change-request.update.interface.js.map +1 -0
  158. package/dist/interfaces/rental-price-attr.interface.d.ts +7 -0
  159. package/dist/interfaces/rental-price-attr.interface.js +3 -0
  160. package/dist/interfaces/rental-price-attr.interface.js.map +1 -0
  161. package/dist/interfaces/response-hirer-signature-attr.interface.d.ts +14 -0
  162. package/dist/interfaces/response-hirer-signature-attr.interface.js +3 -0
  163. package/dist/interfaces/response-hirer-signature-attr.interface.js.map +1 -0
  164. package/dist/models/agreement-history.entity.d.ts +10 -0
  165. package/dist/models/agreement-history.entity.js +65 -0
  166. package/dist/models/agreement-history.entity.js.map +1 -0
  167. package/dist/models/agreement-signature.entity.d.ts +22 -0
  168. package/dist/models/agreement-signature.entity.js +123 -0
  169. package/dist/models/agreement-signature.entity.js.map +1 -0
  170. package/dist/models/agreement.entity.d.ts +14 -0
  171. package/dist/models/agreement.entity.js +70 -0
  172. package/dist/models/agreement.entity.js.map +1 -0
  173. package/dist/models/booking.entity.d.ts +21 -0
  174. package/dist/models/booking.entity.js +128 -0
  175. package/dist/models/booking.entity.js.map +1 -0
  176. package/dist/models/hirer-change-request-new-hirer.entity.d.ts +19 -0
  177. package/dist/models/hirer-change-request-new-hirer.entity.js +121 -0
  178. package/dist/models/hirer-change-request-new-hirer.entity.js.map +1 -0
  179. package/dist/models/hirer-change-request-remove-hirer.entity.d.ts +11 -0
  180. package/dist/models/hirer-change-request-remove-hirer.entity.js +57 -0
  181. package/dist/models/hirer-change-request-remove-hirer.entity.js.map +1 -0
  182. package/dist/models/hirer-change-request-signature.entity.d.ts +18 -0
  183. package/dist/models/hirer-change-request-signature.entity.js +101 -0
  184. package/dist/models/hirer-change-request-signature.entity.js.map +1 -0
  185. package/dist/models/index.d.ts +12 -0
  186. package/dist/models/index.js +26 -0
  187. package/dist/models/index.js.map +1 -0
  188. package/dist/models/joint-hirer.entity.d.ts +14 -0
  189. package/dist/models/joint-hirer.entity.js +91 -0
  190. package/dist/models/joint-hirer.entity.js.map +1 -0
  191. package/dist/models/rental-hirer-change-request.entity.d.ts +22 -0
  192. package/dist/models/rental-hirer-change-request.entity.js +108 -0
  193. package/dist/models/rental-hirer-change-request.entity.js.map +1 -0
  194. package/dist/models/rental-price.entity.d.ts +8 -0
  195. package/dist/models/rental-price.entity.js +59 -0
  196. package/dist/models/rental-price.entity.js.map +1 -0
  197. package/dist/models/rental.entity.d.ts +29 -0
  198. package/dist/models/rental.entity.js +160 -0
  199. package/dist/models/rental.entity.js.map +1 -0
  200. package/dist/src/components/agreement/agreement.js +9 -9
  201. package/dist/src/components/rental/rental.d.ts +2 -1
  202. package/dist/src/components/rental/rental.js +19 -16
  203. package/dist/src/components/rental/rental.js.map +1 -1
  204. package/dist/src/enum/agreement-signature-verification-method.enum.d.ts +4 -0
  205. package/dist/src/enum/agreement-signature-verification-method.enum.js +9 -0
  206. package/dist/src/enum/agreement-signature-verification-method.enum.js.map +1 -0
  207. package/dist/src/enum/index.d.ts +2 -1
  208. package/dist/src/enum/index.js +3 -1
  209. package/dist/src/enum/index.js.map +1 -1
  210. package/dist/src/models/agreement-signature.entity.d.ts +4 -0
  211. package/dist/src/models/agreement-signature.entity.js +22 -0
  212. package/dist/src/models/agreement-signature.entity.js.map +1 -1
  213. package/dist/tsconfig.build.tsbuildinfo +1 -0
  214. package/dist/tsconfig.tsbuildinfo +1 -1
  215. package/eslint.config.mjs +58 -58
  216. package/jest.config.js +10 -10
  217. package/migrations/20250529092130-add-status-to-joint-hirer.js +19 -19
  218. package/migrations/agreement-signature-table-migration.js +76 -64
  219. package/migrations/booking-table-migration.js +79 -79
  220. package/migrations/hirer-change-request-new-hirer-migration.js +72 -72
  221. package/migrations/hirer-change-request-remove-hirer-migration.js +39 -39
  222. package/migrations/hirer-change-request-signature-migration.js +65 -65
  223. package/migrations/joint-hirer-table-migration.js +52 -52
  224. package/migrations/rental-aggreement-history-migration.js +41 -41
  225. package/migrations/rental-aggrement-table-migration.js +30 -30
  226. package/migrations/rental-hirer-change-request-migrations.js +64 -64
  227. package/migrations/rental-price-table-migration.js +32 -32
  228. package/migrations/rental-table-migrations.js +96 -96
  229. package/package.json +80 -80
  230. package/sonar-project.properties +12 -12
  231. package/src/ClassMappings/ItemClassMap.ts +7 -7
  232. package/src/ClassMappings/index.ts +3 -3
  233. package/src/components/agreement/agreement.repository.ts +54 -54
  234. package/src/components/agreement/agreement.ts +187 -187
  235. package/src/components/agreement-history/agreement-history.repository.ts +54 -54
  236. package/src/components/agreement-history/agreement-history.ts +57 -57
  237. package/src/components/agreement-signature/agreement-signature.repository.ts +55 -55
  238. package/src/components/agreement-signature/agreement-signature.ts +143 -143
  239. package/src/components/booking/booking.repository.ts +51 -51
  240. package/src/components/booking/booking.ts +492 -492
  241. package/src/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.repository.ts +64 -64
  242. package/src/components/hirer-change-request-new-hirer/hirer-change-request-new-hirer.ts +153 -153
  243. package/src/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.repository.ts +65 -65
  244. package/src/components/hirer-change-request-remove-hirer/hirer-change-request-remove-hirer.ts +134 -134
  245. package/src/components/hirer-change-request-signature/hirer-change-request-signature.repository.ts +65 -65
  246. package/src/components/hirer-change-request-signature/hirer-change-request-signature.ts +272 -272
  247. package/src/components/joint-hirer/joint-hirer.repository.ts +54 -54
  248. package/src/components/joint-hirer/joint-hirer.ts +252 -252
  249. package/src/components/rental/rental.repository.ts +51 -51
  250. package/src/components/rental/rental.ts +1466 -1460
  251. package/src/components/rental-hirer-change-request/rental-hirer-change-request.repository.ts +64 -64
  252. package/src/components/rental-hirer-change-request/rental-hirer-change-request.ts +907 -907
  253. package/src/components/rental-price/rental-price.repository.ts +54 -54
  254. package/src/components/rental-price/rental-price.ts +100 -100
  255. package/src/database.ts +39 -39
  256. package/src/enum/account-type.enum.ts +4 -4
  257. package/src/enum/agreement-signature-status.enum.ts +4 -4
  258. package/src/enum/agreement-signature-verification-method.enum.ts +4 -0
  259. package/src/enum/booking.enum.ts +5 -5
  260. package/src/enum/hirer-type.enum.ts +4 -4
  261. package/src/enum/index.ts +23 -21
  262. package/src/enum/rental-hirer-change-request-hirer-role.ts +4 -4
  263. package/src/enum/rental-hirer-change-request-status.ts +7 -7
  264. package/src/enum/rental-hirer-change-request-type.ts +4 -4
  265. package/src/enum/rental-status.enum.ts +39 -39
  266. package/src/index.ts +54 -54
  267. package/src/interfaces/agreemeent-signature-attr.interface.ts +15 -15
  268. package/src/interfaces/agreement-attr.interface.ts +7 -7
  269. package/src/interfaces/agreement-history-attr.interface.ts +7 -7
  270. package/src/interfaces/booking-attr.interface.ts +19 -19
  271. package/src/interfaces/booking-find-all-search-attr.interface.ts +12 -12
  272. package/src/interfaces/hirer-change-request-new-hirer-attr.interface.ts +15 -15
  273. package/src/interfaces/hirer-change-request-remove-hirer-attr.interface.ts +5 -5
  274. package/src/interfaces/hirer-change-request-signature-attr.interface.ts +15 -15
  275. package/src/interfaces/index.ts +29 -29
  276. package/src/interfaces/joint-hirer-attr.interface.ts +11 -11
  277. package/src/interfaces/rental-attr.interface.ts +25 -25
  278. package/src/interfaces/rental-find-all-search-attr.interface.ts +11 -11
  279. package/src/interfaces/rental-hirer-change-request.attr.interface.ts +17 -17
  280. package/src/interfaces/rental-hirer-change-request.update.interface.ts +4 -4
  281. package/src/interfaces/rental-price-attr.interface.ts +7 -7
  282. package/src/interfaces/response-hirer-signature-attr.interface.ts +15 -15
  283. package/src/models/agreement-history.entity.ts +51 -51
  284. package/src/models/agreement-signature.entity.ts +105 -86
  285. package/src/models/agreement.entity.ts +47 -47
  286. package/src/models/booking.entity.ts +105 -105
  287. package/src/models/hirer-change-request-new-hirer.entity.ts +102 -102
  288. package/src/models/hirer-change-request-remove-hirer.entity.ts +47 -47
  289. package/src/models/hirer-change-request-signature.entity.ts +86 -86
  290. package/src/models/index.ts +25 -25
  291. package/src/models/joint-hirer.entity.ts +70 -70
  292. package/src/models/rental-price.entity.ts +38 -38
  293. package/src/models/rental.entity.ts +133 -133
  294. package/tsconfig.build.json +5 -5
  295. package/tsconfig.json +24 -24
@@ -1,907 +1,907 @@
1
- import { ClassError, ObjectBase } from '@tomei/general';
2
- import { RentalHirerChangeRequestRepository } from './rental-hirer-change-request.repository';
3
- import { ApplicationConfig, ComponentConfig } from '@tomei/config';
4
- import { LoginUser } from '@tomei/sso';
5
- import { ActionEnum, Activity } from '@tomei/activity-history';
6
- import { HirerChangeRequestTypeEnum } from '../../enum/rental-hirer-change-request-type';
7
- import { HirerChangeRequestStatusEnum } from '../../enum/rental-hirer-change-request-status';
8
- import {
9
- IRentalHirerChangeRequestAttr,
10
- IRentalHirerChangeRequestUpdate,
11
- } from '../../interfaces';
12
- import { Rental } from '../rental/rental';
13
- import {
14
- HirerChangeRequestHirerRoleEnum,
15
- RentalAccountTypeEnum,
16
- } from '../../enum';
17
- import { Op } from 'sequelize';
18
- import { JointHirerRepository } from '../../components/joint-hirer/joint-hirer.repository';
19
- import { HirerChangeRequestSignatureRepository } from '../hirer-change-request-signature/hirer-change-request-signature.repository';
20
- import { HirerChangeRequestSignature } from '../hirer-change-request-signature/hirer-change-request-signature';
21
- import { HirerChangeRequestNewHirer } from '../hirer-change-request-new-hirer/hirer-change-request-new-hirer';
22
- import { HirerChangeRequestRemoveHirer } from '../hirer-change-request-remove-hirer/hirer-change-request-remove-hirer';
23
- import { JointHirer } from '../joint-hirer/joint-hirer';
24
-
25
- export class RentalHirerChangeRequest
26
- extends ObjectBase
27
- implements IRentalHirerChangeRequestAttr
28
- {
29
- ObjectId: string;
30
- ObjectName: string;
31
- ObjectType: string = 'RentalHirerChangeRequest';
32
- TableName: string = 'rental_HirerChangeRequest';
33
-
34
- RentalId: string;
35
- Type: HirerChangeRequestTypeEnum;
36
- Status: HirerChangeRequestStatusEnum;
37
- RequestedAt: Date;
38
- RequestedById: string;
39
- RequestingHirerId: string;
40
- RequestingHirerType: HirerChangeRequestHirerRoleEnum;
41
- CancelRemarks: string;
42
- UpdatedAt: Date;
43
- UpdatedById: string;
44
-
45
- Signatures: HirerChangeRequestSignature[] = [];
46
- Rental: Rental | null = null;
47
-
48
- get RequestId(): string {
49
- return this.ObjectId;
50
- }
51
-
52
- set RequestId(value: string) {
53
- this.ObjectId = value;
54
- }
55
-
56
- protected static _Repository = new RentalHirerChangeRequestRepository();
57
- protected static _HirerSignatureRepository =
58
- new HirerChangeRequestSignatureRepository();
59
- protected static _JointHirerRepository = new JointHirerRepository();
60
-
61
- protected constructor(
62
- hirerChangeRequestAttr?: IRentalHirerChangeRequestAttr,
63
- ) {
64
- super();
65
- if (hirerChangeRequestAttr) {
66
- this.RequestId = hirerChangeRequestAttr.RequestId;
67
- this.RentalId = hirerChangeRequestAttr.RentalId;
68
- this.Type = hirerChangeRequestAttr.Type;
69
- this.Status = hirerChangeRequestAttr.Status;
70
- this.RequestedAt = hirerChangeRequestAttr.RequestedAt;
71
- this.RequestedById = hirerChangeRequestAttr.RequestedById;
72
- this.RequestingHirerId = hirerChangeRequestAttr.RequestingHirerId;
73
- this.RequestingHirerType = hirerChangeRequestAttr.RequestingHirerType;
74
- this.CancelRemarks = hirerChangeRequestAttr.CancelRemarks;
75
- this.UpdatedAt = hirerChangeRequestAttr.UpdatedAt;
76
- this.UpdatedById = hirerChangeRequestAttr.UpdatedById;
77
- }
78
- }
79
-
80
- toJSON(): IRentalHirerChangeRequestAttr {
81
- return {
82
- RequestId: this.RequestId,
83
- RentalId: this.RentalId,
84
- Type: this.Type,
85
- Status: this.Status,
86
- RequestedAt: this.RequestedAt,
87
- RequestedById: this.RequestedById,
88
- RequestingHirerId: this.RequestingHirerId,
89
- RequestingHirerType: this.RequestingHirerType,
90
- CancelRemarks: this.CancelRemarks,
91
- UpdatedAt: this.UpdatedAt,
92
- UpdatedById: this.UpdatedById,
93
- };
94
- }
95
-
96
- public static async init(requestId?: string, dbTransaction?: any) {
97
- try {
98
- if (requestId) {
99
- const hirerChangeReq =
100
- await RentalHirerChangeRequest._Repository.findByPk(
101
- requestId,
102
- dbTransaction,
103
- );
104
- if (hirerChangeReq) {
105
- return new RentalHirerChangeRequest(
106
- hirerChangeReq.get({ plain: true }),
107
- );
108
- } else {
109
- throw new ClassError(
110
- 'HirerChangeRequest',
111
- 'HirerChangeRequestErrMsg00',
112
- 'HirerChangeRequest not found',
113
- );
114
- }
115
- }
116
- return new RentalHirerChangeRequest();
117
- } catch (error) {
118
- console.error('Error initializing RentalHirerChangeRequest:', error);
119
- throw error;
120
- }
121
- }
122
-
123
- private async checkForDuplicate(dbTransaction: any) {
124
- try {
125
- if (!this.RentalId) {
126
- throw new ClassError(
127
- 'HirerChangeRequest',
128
- 'HirerChangeRequestErrMsg08',
129
- 'RentalId is required to check for duplicate requests.',
130
- );
131
- }
132
-
133
- const isDuplicate = await RentalHirerChangeRequest._Repository.findAll({
134
- where: {
135
- RentalId: this.RentalId,
136
- Type: this.Type,
137
- Status: {
138
- [Op.notIn]: [
139
- HirerChangeRequestStatusEnum.COMPLETED,
140
- HirerChangeRequestStatusEnum.CANCELLED,
141
- ],
142
- },
143
- },
144
- transaction: dbTransaction,
145
- });
146
-
147
- if (isDuplicate.length > 0) {
148
- throw new ClassError(
149
- 'HirerChangeRequest',
150
- 'HirerChangeRequestErrMsg04',
151
- 'Duplicate record detected.',
152
- );
153
- }
154
- } catch (error) {
155
- throw error;
156
- }
157
- }
158
-
159
- public async getSignatures(dbTransaction: any) {
160
- try {
161
- if (this.Signatures.length > 0) {
162
- return this.Signatures;
163
- }
164
-
165
- const hirers =
166
- await RentalHirerChangeRequest._HirerSignatureRepository.findAll({
167
- where: {
168
- RequestId: this.RequestId,
169
- },
170
- transaction: dbTransaction,
171
- });
172
-
173
- this.Signatures = await Promise.all(
174
- hirers.map(async (hirer) => {
175
- return await HirerChangeRequestSignature.init(
176
- hirer.SignatureId,
177
- dbTransaction,
178
- );
179
- }),
180
- );
181
- return this.Signatures;
182
- } catch (error) {
183
- throw error;
184
- }
185
- }
186
-
187
- private async checkIsAllSigned(dbTransaction) {
188
- try {
189
- const listUpdatedHirer = await this.getSignatures(dbTransaction);
190
- if (listUpdatedHirer.length > 0) {
191
- return listUpdatedHirer.every((record) => record.SignedAt !== null);
192
- } else {
193
- return false;
194
- }
195
- } catch (error) {
196
- throw error;
197
- }
198
- }
199
-
200
- private async create(loginUser: LoginUser, dbTransaction?: any) {
201
- try {
202
- // Part 1: Check Privilege
203
- // 1.1 Make sure user got "HIRER_CHANGE_REQUEST" privilege
204
- const systemCode =
205
- ApplicationConfig.getComponentConfigValue('system-code');
206
- const isPrivileged = await loginUser.checkPrivileges(
207
- systemCode,
208
- 'HIRER_CHANGE_REQUEST',
209
- );
210
-
211
- if (!isPrivileged) {
212
- throw new ClassError(
213
- 'HirerChangeRequest',
214
- 'HirerChangeRequestErrMsg01',
215
- "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
216
- );
217
- }
218
-
219
- // Part 2: Validation Rental
220
- // 2.1 Make sure this.RentalId and this.RequestingHirerId got value.
221
- if (!this.RentalId || !this.RequestingHirerId) {
222
- throw new ClassError(
223
- 'HirerChangeRequest',
224
- 'HirerChangeRequestErrMsg02',
225
- 'RentalId and RequestingHirerId are required.',
226
- );
227
- }
228
- const rental = await Rental.init(dbTransaction, this.RentalId);
229
-
230
- // 2.3 only allow for rental account where its joint hirer not maximum yet (at this step you've retrieve the number of joint hirer)
231
- rental.AccountType = RentalAccountTypeEnum.JOINT;
232
- const jointHirers = await rental.getJointHirers(dbTransaction);
233
-
234
- if (this.Type === HirerChangeRequestTypeEnum.ADD) {
235
- const maxJointHirer = ComponentConfig.getComponentConfigValue(
236
- '@tomei/rental',
237
- 'maxJointHirerLength',
238
- );
239
-
240
- if (jointHirers?.length >= maxJointHirer) {
241
- throw new ClassError(
242
- 'HirerChangeRequest',
243
- 'HirerChangeRequestErrMsg05',
244
- 'Joint Hirer exceed max joint hirer length.',
245
- );
246
- }
247
- }
248
-
249
- // 2.4 avoid duplicate request, call this.checkForDuplicate() private method, this method will ensure no record with same RentalId and same Type and Status is not "Completed" or "Cancelled"
250
- await this.checkForDuplicate(dbTransaction);
251
-
252
- // Part 3: Create Hirer Change Request and Hirer Change Request Hirer Records
253
- // 3.1 Set other attributes
254
- this.ObjectId = this.createId();
255
- this.RequestedById = loginUser.ObjectId;
256
- this.RequestedAt = new Date();
257
- this.UpdatedById = loginUser.ObjectId;
258
- this.UpdatedAt = new Date();
259
- this.Status = HirerChangeRequestStatusEnum.PENDINGSIGNATURES;
260
- this.RequestingHirerType =
261
- rental.CustomerId === this.RequestingHirerId
262
- ? HirerChangeRequestHirerRoleEnum.MAIN
263
- : HirerChangeRequestHirerRoleEnum.JOINT;
264
-
265
- // 3.2 Set Entity value after
266
- const entityValueAfter: IRentalHirerChangeRequestAttr = {
267
- RequestId: this.RequestId,
268
- RentalId: this.RentalId,
269
- Type: this.Type,
270
- Status: this.Status,
271
- RequestedById: this.RequestedById,
272
- RequestedAt: this.RequestedAt,
273
- RequestingHirerId: this.RequestingHirerId,
274
- RequestingHirerType: this.RequestingHirerType,
275
- CancelRemarks: this.CancelRemarks,
276
- UpdatedById: this.UpdatedById,
277
- UpdatedAt: this.UpdatedAt,
278
- };
279
-
280
- // 3.3 Call repo class create method by passing the class attributes and db transaction.
281
- await RentalHirerChangeRequest._Repository.create(entityValueAfter, {
282
- transaction: dbTransaction,
283
- });
284
-
285
- // Generate signatures, call this.generateSignature by passing:
286
- await this.generateSignatures(loginUser, dbTransaction);
287
-
288
- //Part 4: Record Create Hirer Change Request Activity
289
- const activity = new Activity();
290
- activity.ObjectId = this._createId();
291
- activity.Action = ActionEnum.CREATE;
292
- activity.Description =
293
- this.Type === HirerChangeRequestTypeEnum.ADD
294
- ? 'Add New Hirer'
295
- : 'Remove Hirer';
296
- activity.EntityId = this.ObjectId;
297
- activity.EntityType = this.ObjectType;
298
- activity.EntityValueBefore = JSON.stringify({});
299
- activity.EntityValueAfter = JSON.stringify(entityValueAfter);
300
-
301
- await activity.create(loginUser.ObjectId, dbTransaction);
302
-
303
- return this;
304
- } catch (error) {
305
- throw error;
306
- }
307
- }
308
-
309
- public async update(
310
- loginUser: LoginUser,
311
- dbTransaction: any,
312
- params: IRentalHirerChangeRequestUpdate,
313
- ) {
314
- try {
315
- // Part 1: Validation
316
- // 1.1 Check if RequestId is not null if null return error
317
- if (!this.RequestId) {
318
- throw new ClassError(
319
- 'HirerChangeRequest',
320
- 'HirerChangeRequestErrMsg06',
321
- 'RequestId are required.',
322
- );
323
- }
324
-
325
- // Part 2: Update Hirer Change Request Hirer Records
326
- // 2.1 Set entityValueBefore
327
- const entityValueBefore: IRentalHirerChangeRequestAttr = {
328
- RequestId: this.RequestId,
329
- RentalId: this.RentalId,
330
- Type: this.Type,
331
- Status: this.Status,
332
- RequestedById: this.RequestedById,
333
- RequestedAt: this.RequestedAt,
334
- RequestingHirerId: this.RequestingHirerId,
335
- RequestingHirerType: this.RequestingHirerType,
336
- CancelRemarks: this.CancelRemarks,
337
- UpdatedById: this.UpdatedById,
338
- UpdatedAt: this.UpdatedAt,
339
- };
340
-
341
- // 2.2 Check if jointHirerId, customerId is null or not
342
- let { jointHirerId, customerId } = params;
343
- if (!customerId && !jointHirerId) {
344
- throw new ClassError(
345
- 'HirerChangeRequest',
346
- 'HirerChangeRequestErrMsg07',
347
- 'At least one of customerId or jointHirerId must be provided.',
348
- );
349
- }
350
-
351
- // 2.3 Get list hirer related to request then find hirer with same CustomerId, if found update the hirer record (make it signed)
352
- const listHirer = await this.getSignatures(dbTransaction);
353
-
354
- if (listHirer?.length > 0) {
355
- let foundHirer = listHirer?.find((record) => {
356
- record.CustomerId === customerId;
357
- });
358
-
359
- let hirer = await HirerChangeRequestSignature.init(
360
- foundHirer.SignatureId,
361
- dbTransaction,
362
- );
363
-
364
- await hirer.update(loginUser, dbTransaction);
365
- }
366
-
367
- // 2.4 Check if all hirer in request is signed, if yes check request Type:
368
- // Type = "Add" = update Request status to “AwaitingNewHirer”
369
- // Type = "Remove" = flag the joint hirer record status to "Inactive" & update Request status to "Completed"
370
- const isSigned = await this.checkIsAllSigned(dbTransaction);
371
-
372
- if (isSigned) {
373
- if (this.Type === HirerChangeRequestTypeEnum.ADD) {
374
- this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
375
- } else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
376
- // TODO: Currently JointHirer dont have status props
377
-
378
- await RentalHirerChangeRequest._JointHirerRepository.update(
379
- { Status: 'Inactive' },
380
- {
381
- where: {
382
- HirerId: this.RequestId,
383
- },
384
- transaction: dbTransaction,
385
- },
386
- );
387
- this.Status = HirerChangeRequestStatusEnum.COMPLETED;
388
- }
389
- }
390
-
391
- // 2.5 Set entityValueAfter
392
- const entityValueAfter: IRentalHirerChangeRequestAttr = {
393
- RequestId: this.RequestId,
394
- RentalId: this.RentalId,
395
- Type: this.Type,
396
- Status: this.Status,
397
- RequestedById: this.RequestedById,
398
- RequestedAt: this.RequestedAt,
399
- RequestingHirerId: this.RequestingHirerId,
400
- RequestingHirerType: this.RequestingHirerType,
401
- CancelRemarks: this.CancelRemarks,
402
- UpdatedById: this.UpdatedById,
403
- UpdatedAt: this.UpdatedAt,
404
- };
405
-
406
- // 2.6 Call repo class update method by passing the class attributes and db transaction.
407
- await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
408
- where: {
409
- RequestId: this.RequestId,
410
- },
411
- transaction: dbTransaction,
412
- });
413
-
414
- //Part 3: Record Create Hirer Change Request Activity
415
- const activity = new Activity();
416
- activity.ObjectId = this._createId();
417
- activity.Action = ActionEnum.UPDATE;
418
- activity.Description = 'Update Hirer Change Request';
419
- activity.EntityId = this.ObjectId;
420
- activity.EntityType = this.ObjectType;
421
- activity.EntityValueBefore = JSON.stringify(entityValueBefore);
422
- activity.EntityValueAfter = JSON.stringify(entityValueAfter);
423
-
424
- await activity.create(loginUser.ObjectId, dbTransaction);
425
-
426
- return this;
427
- } catch (error) {
428
- throw error;
429
- }
430
- }
431
-
432
- public async generateSignatures(loginUser: LoginUser, dbTransaction?: any) {
433
- try {
434
- if (!this.RentalId) {
435
- throw new ClassError(
436
- 'HirerChangeRequest',
437
- 'HirerChangeRequestErrMsg09',
438
- 'RentalId is required to create signatures.',
439
- );
440
- }
441
-
442
- // 1. If this.Rental is null, set it to Rental instantiation using this.RentalId
443
- if (!this.Rental) {
444
- this.Rental = await Rental.init(dbTransaction, this.RentalId);
445
- }
446
-
447
- // 2. Prepare all signature data (main + joint) in one go
448
- this.Rental.AccountType = RentalAccountTypeEnum.JOINT;
449
- const jointHirers = await this.Rental.getJointHirers(dbTransaction);
450
-
451
- // Main hirer signature
452
- const mainSignature = await HirerChangeRequestSignature.init();
453
- mainSignature.RequestId = this.RequestId;
454
- mainSignature.CustomerId = this.Rental.CustomerId;
455
- mainSignature.HirerType = HirerChangeRequestHirerRoleEnum.MAIN;
456
- mainSignature.Method = 'Upload';
457
-
458
- // Joint hirer signatures - only if there are joint hirers
459
- let jointSignatures = [];
460
- if (jointHirers.length > 0) {
461
- const jointSignaturePromises = jointHirers.map(async (jointHirer) => {
462
- const signature = await HirerChangeRequestSignature.init();
463
- signature.RequestId = this.RequestId;
464
- signature.JointHirerId = jointHirer.HirerId;
465
- signature.HirerType = HirerChangeRequestHirerRoleEnum.JOINT;
466
- signature.Method = 'Upload';
467
- return signature;
468
- });
469
-
470
- jointSignatures = await Promise.all(jointSignaturePromises);
471
- }
472
-
473
- // 3. Create all signatures in parallel
474
- const signaturesToCreate = [
475
- mainSignature.create(loginUser, dbTransaction),
476
- ];
477
- if (jointSignatures.length > 0) {
478
- signaturesToCreate.push(
479
- ...jointSignatures.map((sig) => sig.create(loginUser, dbTransaction)),
480
- );
481
- }
482
-
483
- await Promise.all(signaturesToCreate);
484
-
485
- this.Signatures = [mainSignature, ...jointSignatures];
486
- } catch (error) {
487
- console.error('Error creating signatures:', error);
488
- throw error;
489
- }
490
- }
491
-
492
- public async createAddRequest(
493
- newHirer: {
494
- FullName: string;
495
- IdNo: string;
496
- IdType: string;
497
- Email?: string;
498
- ContactNo: string;
499
- Relationship: string;
500
- Address: string;
501
- City: string;
502
- State: string;
503
- Postcode: string;
504
- Country: string;
505
- },
506
- loginUser: LoginUser,
507
- dbTransaction?: any,
508
- ): Promise<{
509
- hirerChangeRequest: RentalHirerChangeRequest;
510
- NewHirer: HirerChangeRequestNewHirer;
511
- }> {
512
- try {
513
- // Validations
514
- // 1. Make sure newHirer required fields cannot be null.
515
- if (
516
- !newHirer.FullName ||
517
- !newHirer.IdNo ||
518
- !newHirer.IdType ||
519
- !newHirer.ContactNo ||
520
- !newHirer.Address ||
521
- !newHirer.City ||
522
- !newHirer.State ||
523
- !newHirer.Postcode ||
524
- !newHirer.Country
525
- ) {
526
- throw new ClassError(
527
- 'HirerChangeRequest',
528
- 'HirerChangeRequestErrMsg10',
529
- 'FullName, IdNo, IdType, ContactNo, and Address are required.',
530
- );
531
- }
532
-
533
- // 2. Set this.Type to "Add".
534
- this.Type = HirerChangeRequestTypeEnum.ADD;
535
-
536
- // 3. Call this.create by passing:
537
- // loginUser, dbTransaction
538
- await this.create(loginUser, dbTransaction);
539
-
540
- // 4. Insert into hirerChangeRequest_NewHirer
541
- const nh = await HirerChangeRequestNewHirer.init();
542
- nh.RequestId = this.RequestId;
543
- nh.FullName = newHirer.FullName;
544
- nh.Email = newHirer.Email;
545
- nh.IdType = newHirer.IdType;
546
- nh.IdNo = newHirer.IdNo;
547
- nh.ContactNo = newHirer.ContactNo;
548
- nh.Relationship = newHirer.Relationship;
549
- nh.Address = newHirer.Address;
550
- nh.City = newHirer.City;
551
- nh.State = newHirer.State;
552
- nh.Postcode = newHirer.Postcode;
553
- nh.Country = newHirer.Country;
554
-
555
- await nh.create(loginUser, dbTransaction);
556
-
557
- // 5. Return HirerChangeRequest instance and NewHirer instance.
558
- return {
559
- hirerChangeRequest: this,
560
- NewHirer: nh,
561
- };
562
- } catch (error) {
563
- console.error('Error creating add request:', error);
564
- throw error;
565
- }
566
- }
567
-
568
- public async createRemoveRequest(
569
- loginUser: LoginUser,
570
- dbTransaction: any,
571
- targetHirerId: string,
572
- ): Promise<{
573
- hirerChangeRequest: RentalHirerChangeRequest;
574
- RemoveHirer: HirerChangeRequestRemoveHirer;
575
- }> {
576
- try {
577
- // 1. Make sure targetHirerId can be instantiated into JointHirer class (existing joint hirer)
578
- await JointHirer.init(targetHirerId, dbTransaction);
579
-
580
- // 2. Set this.Type to "Remove"
581
- this.Type = HirerChangeRequestTypeEnum.REMOVE;
582
-
583
- // 3. Call this.create() method by passing loginUser, dbTransaction
584
- await this.create(loginUser, dbTransaction);
585
-
586
- // 4. Insert into hirerChangeRequest_RemoveHirer
587
- const removeHirer = await HirerChangeRequestRemoveHirer.init();
588
- removeHirer.RequestId = this.RequestId;
589
- removeHirer.TargetHirerId = targetHirerId;
590
-
591
- await removeHirer.create(loginUser, dbTransaction);
592
-
593
- // 5. Return the returned HirerChangeRequest instance and RemoveHirer instance.
594
- return {
595
- hirerChangeRequest: this,
596
- RemoveHirer: removeHirer,
597
- };
598
- } catch (error) {
599
- console.error('Error creating remove request:', error);
600
- throw error;
601
- }
602
- }
603
-
604
- public static async findAll(
605
- loginUser: LoginUser,
606
- dbTransaction: any,
607
- rentalId: string,
608
- ): Promise<RentalHirerChangeRequest[]> {
609
- try {
610
- // 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
611
- const systemCode =
612
- ApplicationConfig.getComponentConfigValue('system-code');
613
- const isPrivileged = await loginUser.checkPrivileges(
614
- systemCode,
615
- 'HIRER_CHANGE_REQUEST',
616
- );
617
- if (!isPrivileged) {
618
- throw new ClassError(
619
- 'HirerChangeRequest',
620
- 'HirerChangeRequestErrMsg01',
621
- "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
622
- );
623
- }
624
-
625
- // 2. Make sure rentalId not null.
626
- if (!rentalId) {
627
- throw new ClassError(
628
- 'HirerChangeRequest',
629
- 'HirerChangeRequestErrMsg12',
630
- 'rentalId is required.',
631
- );
632
- }
633
-
634
- // 3. Instantiate rental (to check rental id valid)
635
- await Rental.init(dbTransaction, rentalId);
636
-
637
- // 4. Call Repo.findAll({ where: { RentalId: rentalId }, transaction: dbTransaction })
638
- const records = await RentalHirerChangeRequest._Repository.findAll({
639
- where: { RentalId: rentalId },
640
- transaction: dbTransaction,
641
- });
642
-
643
- // 5. Instantiate the returned items
644
- const result = (records || []).map(
645
- (rec) => new RentalHirerChangeRequest(rec.get({ plain: true })),
646
- );
647
-
648
- // 6. Return the instance array
649
- return result;
650
- } catch (error) {
651
- console.error('Error finding all RentalHirerChangeRequest:', error);
652
- throw error;
653
- }
654
- }
655
-
656
- public async getNewHirer(
657
- dbTransaction: any,
658
- ): Promise<HirerChangeRequestNewHirer> {
659
- try {
660
- // 1. Make sure this.RequestId got value.
661
- if (!this.RequestId) {
662
- throw new ClassError(
663
- 'HirerChangeRequest',
664
- 'HirerChangeRequestErrMsg13',
665
- 'RequestId is required to get new hirer.',
666
- );
667
- }
668
-
669
- // 2. Call HirerChangeRequestNewHirer.findAll()
670
- const newHirerRecords = await HirerChangeRequestNewHirer.findAll(
671
- {
672
- RequestId: this.RequestId,
673
- },
674
- dbTransaction,
675
- );
676
-
677
- // 3. Return the newHirer instance
678
- return newHirerRecords[0] || null;
679
- } catch (error) {
680
- console.error('Error getting new hirer:', error);
681
- throw error;
682
- }
683
- }
684
-
685
- public async getRemoveHirer(
686
- dbTransaction: any,
687
- ): Promise<HirerChangeRequestRemoveHirer> {
688
- try {
689
- // 1. Make sure this.RequestId got value.
690
- if (!this.RequestId) {
691
- throw new ClassError(
692
- 'HirerChangeRequest',
693
- 'HirerChangeRequestErrMsg13',
694
- 'RequestId is required to get remove hirer.',
695
- );
696
- }
697
-
698
- // 2. Call HirerChangeRequestRemoveHirer.findAll()
699
- const removeHirerRecords = await HirerChangeRequestRemoveHirer.findAll(
700
- {
701
- RequestId: this.RequestId,
702
- },
703
- dbTransaction,
704
- );
705
-
706
- // 3. Return the removeHirer instance
707
- return removeHirerRecords[0] || null;
708
- } catch (error) {
709
- console.error('Error getting remove hirer:', error);
710
- throw error;
711
- }
712
- }
713
-
714
- public async sign(
715
- loginUser: LoginUser,
716
- dbTransaction: any,
717
- signatureId: string,
718
- ): Promise<HirerChangeRequestSignature> {
719
- try {
720
- // 1. Make sure this.RequestId got value.
721
- if (!this.RequestId) {
722
- throw new ClassError(
723
- 'HirerChangeRequest',
724
- 'HirerChangeRequestErrMsg13',
725
- 'RequestId is required to sign signature.',
726
- );
727
- }
728
-
729
- // Validate signatureId
730
- const hcrSignature = await HirerChangeRequestSignature.init(
731
- signatureId,
732
- dbTransaction,
733
- );
734
-
735
- //Call hcrSignature.markSigned() method by passing loginUser and dbTransaction
736
- await hcrSignature.markSigned(loginUser, dbTransaction);
737
-
738
- // const isSigned = await this.checkIsAllSigned(dbTransaction);
739
-
740
- // if (isSigned && this.Type === HirerChangeRequestTypeEnum.ADD) {
741
- // this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
742
- // this.UpdatedAt = new Date();
743
- // this.UpdatedById = loginUser.ObjectId;
744
- // await RentalHirerChangeRequest._Repository.update(this.toJSON(), {
745
- // where: { RequestId: this.RequestId },
746
- // transaction: dbTransaction,
747
- // });
748
- // }
749
- return hcrSignature;
750
- } catch (error) {
751
- throw error;
752
- }
753
- }
754
-
755
- public async complete(
756
- loginUser: LoginUser,
757
- dbTransaction: any,
758
- customerId?: string,
759
- customerType?: string,
760
- ): Promise<RentalHirerChangeRequest> {
761
- // 1. Validations
762
- // a. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
763
- const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
764
- const isPrivileged = await loginUser.checkPrivileges(
765
- systemCode,
766
- 'HIRER_CHANGE_REQUEST',
767
- );
768
- if (!isPrivileged) {
769
- throw new ClassError(
770
- 'HirerChangeRequest',
771
- 'HirerChangeRequestErrMsg01',
772
- "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
773
- );
774
- }
775
-
776
- // b. Make sure this.RequestId not null.
777
- if (!this.RequestId) {
778
- throw new ClassError(
779
- 'HirerChangeRequest',
780
- 'HirerChangeRequestErrMsg06',
781
- 'RequestId is required.',
782
- );
783
- }
784
-
785
- // c. Make sure all signatures are signed.
786
- const signatures = await this.getSignatures(dbTransaction);
787
- if (!signatures.length || !signatures.every((sig) => sig.SignedAt)) {
788
- throw new ClassError(
789
- 'HirerChangeRequest',
790
- 'HirerChangeRequestErrMsg14',
791
- 'All signatures must be signed before completing the request.',
792
- );
793
- }
794
-
795
- // 2. Create/Remove Hirer
796
- if (this.Type === HirerChangeRequestTypeEnum.ADD) {
797
- //Make sure CustomerId is set, if not throw error
798
- if (!customerId || !customerType) {
799
- throw new ClassError(
800
- 'HirerChangeRequest',
801
- 'HirerChangeRequestErrMsg15',
802
- 'CustomerId and CustomerType are required for new hirer.',
803
- );
804
- }
805
- // c. Create joint hirer using JointHirer.create()
806
- const jointHirer = await JointHirer.init();
807
- jointHirer.RentalId = this.RentalId;
808
- jointHirer.CustomerId = customerId;
809
- jointHirer.CustomerType = customerType;
810
- await jointHirer.create(loginUser, dbTransaction);
811
- } else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
812
- // a. Get joint hirer from remove hirer request
813
- const removeHirer = await this.getRemoveHirer(dbTransaction);
814
- const jointHirer = await JointHirer.init(
815
- removeHirer.TargetHirerId,
816
- dbTransaction,
817
- );
818
-
819
- //Call jointHirer.remove() method by passing loginUser and dbTransaction
820
- await jointHirer.remove(loginUser, dbTransaction);
821
- }
822
-
823
- // 3. Call _Repo update method
824
- const now = new Date();
825
- const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
826
- this.Status = HirerChangeRequestStatusEnum.COMPLETED;
827
- this.UpdatedAt = new Date();
828
- this.UpdatedById = loginUser.ObjectId;
829
- const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
830
- await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
831
- where: { RequestId: this.RequestId },
832
- transaction: dbTransaction,
833
- });
834
-
835
- // 4. Record activity history
836
- const activity = new Activity();
837
- activity.ObjectId = this._createId();
838
- activity.Action = ActionEnum.UPDATE;
839
- activity.Description = `Mark request as completed.`;
840
- activity.EntityId = this.RequestId;
841
- activity.EntityType = this.ObjectType;
842
- activity.EntityValueBefore = JSON.stringify(entityValueBefore);
843
- activity.EntityValueAfter = JSON.stringify(entityValueAfter);
844
-
845
- await activity.create(loginUser.ObjectId, dbTransaction);
846
-
847
- // 5. Return updated instance
848
- return this;
849
- }
850
-
851
- public async cancel(
852
- loginUser: LoginUser,
853
- dbTransaction: any,
854
- cancelRemarks: string,
855
- ): Promise<RentalHirerChangeRequest> {
856
- // 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
857
- const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
858
- const isPrivileged = await loginUser.checkPrivileges(
859
- systemCode,
860
- 'HIRER_CHANGE_REQUEST',
861
- );
862
- if (!isPrivileged) {
863
- throw new ClassError(
864
- 'HirerChangeRequest',
865
- 'HirerChangeRequestErrMsg01',
866
- "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
867
- );
868
- }
869
-
870
- // 2. Make sure this.RequestId not null.
871
- if (!this.RequestId) {
872
- throw new ClassError(
873
- 'HirerChangeRequest',
874
- 'HirerChangeRequestErrMsg06',
875
- 'RequestId is required.',
876
- );
877
- }
878
-
879
- // 3. Call _Repo.update() method
880
- const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
881
- this.Status = HirerChangeRequestStatusEnum.CANCELLED;
882
- this.CancelRemarks = cancelRemarks;
883
- this.UpdatedAt = new Date();
884
- this.UpdatedById = loginUser.ObjectId;
885
- const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
886
-
887
- await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
888
- where: { RequestId: this.RequestId },
889
- transaction: dbTransaction,
890
- });
891
-
892
- // 4. Record activity history
893
- const activity = new Activity();
894
- activity.ObjectId = this._createId();
895
- activity.Action = ActionEnum.UPDATE;
896
- activity.Description = `Cancel hirer change request.`;
897
- activity.EntityId = this.RequestId;
898
- activity.EntityType = this.ObjectType;
899
- activity.EntityValueBefore = JSON.stringify(entityValueBefore);
900
- activity.EntityValueAfter = JSON.stringify(entityValueAfter);
901
-
902
- await activity.create(loginUser.ObjectId, dbTransaction);
903
-
904
- // 5. Return updated instance
905
- return this;
906
- }
907
- }
1
+ import { ClassError, ObjectBase } from '@tomei/general';
2
+ import { RentalHirerChangeRequestRepository } from './rental-hirer-change-request.repository';
3
+ import { ApplicationConfig, ComponentConfig } from '@tomei/config';
4
+ import { LoginUser } from '@tomei/sso';
5
+ import { ActionEnum, Activity } from '@tomei/activity-history';
6
+ import { HirerChangeRequestTypeEnum } from '../../enum/rental-hirer-change-request-type';
7
+ import { HirerChangeRequestStatusEnum } from '../../enum/rental-hirer-change-request-status';
8
+ import {
9
+ IRentalHirerChangeRequestAttr,
10
+ IRentalHirerChangeRequestUpdate,
11
+ } from '../../interfaces';
12
+ import { Rental } from '../rental/rental';
13
+ import {
14
+ HirerChangeRequestHirerRoleEnum,
15
+ RentalAccountTypeEnum,
16
+ } from '../../enum';
17
+ import { Op } from 'sequelize';
18
+ import { JointHirerRepository } from '../../components/joint-hirer/joint-hirer.repository';
19
+ import { HirerChangeRequestSignatureRepository } from '../hirer-change-request-signature/hirer-change-request-signature.repository';
20
+ import { HirerChangeRequestSignature } from '../hirer-change-request-signature/hirer-change-request-signature';
21
+ import { HirerChangeRequestNewHirer } from '../hirer-change-request-new-hirer/hirer-change-request-new-hirer';
22
+ import { HirerChangeRequestRemoveHirer } from '../hirer-change-request-remove-hirer/hirer-change-request-remove-hirer';
23
+ import { JointHirer } from '../joint-hirer/joint-hirer';
24
+
25
+ export class RentalHirerChangeRequest
26
+ extends ObjectBase
27
+ implements IRentalHirerChangeRequestAttr
28
+ {
29
+ ObjectId: string;
30
+ ObjectName: string;
31
+ ObjectType: string = 'RentalHirerChangeRequest';
32
+ TableName: string = 'rental_HirerChangeRequest';
33
+
34
+ RentalId: string;
35
+ Type: HirerChangeRequestTypeEnum;
36
+ Status: HirerChangeRequestStatusEnum;
37
+ RequestedAt: Date;
38
+ RequestedById: string;
39
+ RequestingHirerId: string;
40
+ RequestingHirerType: HirerChangeRequestHirerRoleEnum;
41
+ CancelRemarks: string;
42
+ UpdatedAt: Date;
43
+ UpdatedById: string;
44
+
45
+ Signatures: HirerChangeRequestSignature[] = [];
46
+ Rental: Rental | null = null;
47
+
48
+ get RequestId(): string {
49
+ return this.ObjectId;
50
+ }
51
+
52
+ set RequestId(value: string) {
53
+ this.ObjectId = value;
54
+ }
55
+
56
+ protected static _Repository = new RentalHirerChangeRequestRepository();
57
+ protected static _HirerSignatureRepository =
58
+ new HirerChangeRequestSignatureRepository();
59
+ protected static _JointHirerRepository = new JointHirerRepository();
60
+
61
+ protected constructor(
62
+ hirerChangeRequestAttr?: IRentalHirerChangeRequestAttr,
63
+ ) {
64
+ super();
65
+ if (hirerChangeRequestAttr) {
66
+ this.RequestId = hirerChangeRequestAttr.RequestId;
67
+ this.RentalId = hirerChangeRequestAttr.RentalId;
68
+ this.Type = hirerChangeRequestAttr.Type;
69
+ this.Status = hirerChangeRequestAttr.Status;
70
+ this.RequestedAt = hirerChangeRequestAttr.RequestedAt;
71
+ this.RequestedById = hirerChangeRequestAttr.RequestedById;
72
+ this.RequestingHirerId = hirerChangeRequestAttr.RequestingHirerId;
73
+ this.RequestingHirerType = hirerChangeRequestAttr.RequestingHirerType;
74
+ this.CancelRemarks = hirerChangeRequestAttr.CancelRemarks;
75
+ this.UpdatedAt = hirerChangeRequestAttr.UpdatedAt;
76
+ this.UpdatedById = hirerChangeRequestAttr.UpdatedById;
77
+ }
78
+ }
79
+
80
+ toJSON(): IRentalHirerChangeRequestAttr {
81
+ return {
82
+ RequestId: this.RequestId,
83
+ RentalId: this.RentalId,
84
+ Type: this.Type,
85
+ Status: this.Status,
86
+ RequestedAt: this.RequestedAt,
87
+ RequestedById: this.RequestedById,
88
+ RequestingHirerId: this.RequestingHirerId,
89
+ RequestingHirerType: this.RequestingHirerType,
90
+ CancelRemarks: this.CancelRemarks,
91
+ UpdatedAt: this.UpdatedAt,
92
+ UpdatedById: this.UpdatedById,
93
+ };
94
+ }
95
+
96
+ public static async init(requestId?: string, dbTransaction?: any) {
97
+ try {
98
+ if (requestId) {
99
+ const hirerChangeReq =
100
+ await RentalHirerChangeRequest._Repository.findByPk(
101
+ requestId,
102
+ dbTransaction,
103
+ );
104
+ if (hirerChangeReq) {
105
+ return new RentalHirerChangeRequest(
106
+ hirerChangeReq.get({ plain: true }),
107
+ );
108
+ } else {
109
+ throw new ClassError(
110
+ 'HirerChangeRequest',
111
+ 'HirerChangeRequestErrMsg00',
112
+ 'HirerChangeRequest not found',
113
+ );
114
+ }
115
+ }
116
+ return new RentalHirerChangeRequest();
117
+ } catch (error) {
118
+ console.error('Error initializing RentalHirerChangeRequest:', error);
119
+ throw error;
120
+ }
121
+ }
122
+
123
+ private async checkForDuplicate(dbTransaction: any) {
124
+ try {
125
+ if (!this.RentalId) {
126
+ throw new ClassError(
127
+ 'HirerChangeRequest',
128
+ 'HirerChangeRequestErrMsg08',
129
+ 'RentalId is required to check for duplicate requests.',
130
+ );
131
+ }
132
+
133
+ const isDuplicate = await RentalHirerChangeRequest._Repository.findAll({
134
+ where: {
135
+ RentalId: this.RentalId,
136
+ Type: this.Type,
137
+ Status: {
138
+ [Op.notIn]: [
139
+ HirerChangeRequestStatusEnum.COMPLETED,
140
+ HirerChangeRequestStatusEnum.CANCELLED,
141
+ ],
142
+ },
143
+ },
144
+ transaction: dbTransaction,
145
+ });
146
+
147
+ if (isDuplicate.length > 0) {
148
+ throw new ClassError(
149
+ 'HirerChangeRequest',
150
+ 'HirerChangeRequestErrMsg04',
151
+ 'Duplicate record detected.',
152
+ );
153
+ }
154
+ } catch (error) {
155
+ throw error;
156
+ }
157
+ }
158
+
159
+ public async getSignatures(dbTransaction: any) {
160
+ try {
161
+ if (this.Signatures.length > 0) {
162
+ return this.Signatures;
163
+ }
164
+
165
+ const hirers =
166
+ await RentalHirerChangeRequest._HirerSignatureRepository.findAll({
167
+ where: {
168
+ RequestId: this.RequestId,
169
+ },
170
+ transaction: dbTransaction,
171
+ });
172
+
173
+ this.Signatures = await Promise.all(
174
+ hirers.map(async (hirer) => {
175
+ return await HirerChangeRequestSignature.init(
176
+ hirer.SignatureId,
177
+ dbTransaction,
178
+ );
179
+ }),
180
+ );
181
+ return this.Signatures;
182
+ } catch (error) {
183
+ throw error;
184
+ }
185
+ }
186
+
187
+ private async checkIsAllSigned(dbTransaction) {
188
+ try {
189
+ const listUpdatedHirer = await this.getSignatures(dbTransaction);
190
+ if (listUpdatedHirer.length > 0) {
191
+ return listUpdatedHirer.every((record) => record.SignedAt !== null);
192
+ } else {
193
+ return false;
194
+ }
195
+ } catch (error) {
196
+ throw error;
197
+ }
198
+ }
199
+
200
+ private async create(loginUser: LoginUser, dbTransaction?: any) {
201
+ try {
202
+ // Part 1: Check Privilege
203
+ // 1.1 Make sure user got "HIRER_CHANGE_REQUEST" privilege
204
+ const systemCode =
205
+ ApplicationConfig.getComponentConfigValue('system-code');
206
+ const isPrivileged = await loginUser.checkPrivileges(
207
+ systemCode,
208
+ 'HIRER_CHANGE_REQUEST',
209
+ );
210
+
211
+ if (!isPrivileged) {
212
+ throw new ClassError(
213
+ 'HirerChangeRequest',
214
+ 'HirerChangeRequestErrMsg01',
215
+ "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
216
+ );
217
+ }
218
+
219
+ // Part 2: Validation Rental
220
+ // 2.1 Make sure this.RentalId and this.RequestingHirerId got value.
221
+ if (!this.RentalId || !this.RequestingHirerId) {
222
+ throw new ClassError(
223
+ 'HirerChangeRequest',
224
+ 'HirerChangeRequestErrMsg02',
225
+ 'RentalId and RequestingHirerId are required.',
226
+ );
227
+ }
228
+ const rental = await Rental.init(dbTransaction, this.RentalId);
229
+
230
+ // 2.3 only allow for rental account where its joint hirer not maximum yet (at this step you've retrieve the number of joint hirer)
231
+ rental.AccountType = RentalAccountTypeEnum.JOINT;
232
+ const jointHirers = await rental.getJointHirers(dbTransaction);
233
+
234
+ if (this.Type === HirerChangeRequestTypeEnum.ADD) {
235
+ const maxJointHirer = ComponentConfig.getComponentConfigValue(
236
+ '@tomei/rental',
237
+ 'maxJointHirerLength',
238
+ );
239
+
240
+ if (jointHirers?.length >= maxJointHirer) {
241
+ throw new ClassError(
242
+ 'HirerChangeRequest',
243
+ 'HirerChangeRequestErrMsg05',
244
+ 'Joint Hirer exceed max joint hirer length.',
245
+ );
246
+ }
247
+ }
248
+
249
+ // 2.4 avoid duplicate request, call this.checkForDuplicate() private method, this method will ensure no record with same RentalId and same Type and Status is not "Completed" or "Cancelled"
250
+ await this.checkForDuplicate(dbTransaction);
251
+
252
+ // Part 3: Create Hirer Change Request and Hirer Change Request Hirer Records
253
+ // 3.1 Set other attributes
254
+ this.ObjectId = this.createId();
255
+ this.RequestedById = loginUser.ObjectId;
256
+ this.RequestedAt = new Date();
257
+ this.UpdatedById = loginUser.ObjectId;
258
+ this.UpdatedAt = new Date();
259
+ this.Status = HirerChangeRequestStatusEnum.PENDINGSIGNATURES;
260
+ this.RequestingHirerType =
261
+ rental.CustomerId === this.RequestingHirerId
262
+ ? HirerChangeRequestHirerRoleEnum.MAIN
263
+ : HirerChangeRequestHirerRoleEnum.JOINT;
264
+
265
+ // 3.2 Set Entity value after
266
+ const entityValueAfter: IRentalHirerChangeRequestAttr = {
267
+ RequestId: this.RequestId,
268
+ RentalId: this.RentalId,
269
+ Type: this.Type,
270
+ Status: this.Status,
271
+ RequestedById: this.RequestedById,
272
+ RequestedAt: this.RequestedAt,
273
+ RequestingHirerId: this.RequestingHirerId,
274
+ RequestingHirerType: this.RequestingHirerType,
275
+ CancelRemarks: this.CancelRemarks,
276
+ UpdatedById: this.UpdatedById,
277
+ UpdatedAt: this.UpdatedAt,
278
+ };
279
+
280
+ // 3.3 Call repo class create method by passing the class attributes and db transaction.
281
+ await RentalHirerChangeRequest._Repository.create(entityValueAfter, {
282
+ transaction: dbTransaction,
283
+ });
284
+
285
+ // Generate signatures, call this.generateSignature by passing:
286
+ await this.generateSignatures(loginUser, dbTransaction);
287
+
288
+ //Part 4: Record Create Hirer Change Request Activity
289
+ const activity = new Activity();
290
+ activity.ObjectId = this._createId();
291
+ activity.Action = ActionEnum.CREATE;
292
+ activity.Description =
293
+ this.Type === HirerChangeRequestTypeEnum.ADD
294
+ ? 'Add New Hirer'
295
+ : 'Remove Hirer';
296
+ activity.EntityId = this.ObjectId;
297
+ activity.EntityType = this.ObjectType;
298
+ activity.EntityValueBefore = JSON.stringify({});
299
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
300
+
301
+ await activity.create(loginUser.ObjectId, dbTransaction);
302
+
303
+ return this;
304
+ } catch (error) {
305
+ throw error;
306
+ }
307
+ }
308
+
309
+ public async update(
310
+ loginUser: LoginUser,
311
+ dbTransaction: any,
312
+ params: IRentalHirerChangeRequestUpdate,
313
+ ) {
314
+ try {
315
+ // Part 1: Validation
316
+ // 1.1 Check if RequestId is not null if null return error
317
+ if (!this.RequestId) {
318
+ throw new ClassError(
319
+ 'HirerChangeRequest',
320
+ 'HirerChangeRequestErrMsg06',
321
+ 'RequestId are required.',
322
+ );
323
+ }
324
+
325
+ // Part 2: Update Hirer Change Request Hirer Records
326
+ // 2.1 Set entityValueBefore
327
+ const entityValueBefore: IRentalHirerChangeRequestAttr = {
328
+ RequestId: this.RequestId,
329
+ RentalId: this.RentalId,
330
+ Type: this.Type,
331
+ Status: this.Status,
332
+ RequestedById: this.RequestedById,
333
+ RequestedAt: this.RequestedAt,
334
+ RequestingHirerId: this.RequestingHirerId,
335
+ RequestingHirerType: this.RequestingHirerType,
336
+ CancelRemarks: this.CancelRemarks,
337
+ UpdatedById: this.UpdatedById,
338
+ UpdatedAt: this.UpdatedAt,
339
+ };
340
+
341
+ // 2.2 Check if jointHirerId, customerId is null or not
342
+ let { jointHirerId, customerId } = params;
343
+ if (!customerId && !jointHirerId) {
344
+ throw new ClassError(
345
+ 'HirerChangeRequest',
346
+ 'HirerChangeRequestErrMsg07',
347
+ 'At least one of customerId or jointHirerId must be provided.',
348
+ );
349
+ }
350
+
351
+ // 2.3 Get list hirer related to request then find hirer with same CustomerId, if found update the hirer record (make it signed)
352
+ const listHirer = await this.getSignatures(dbTransaction);
353
+
354
+ if (listHirer?.length > 0) {
355
+ let foundHirer = listHirer?.find((record) => {
356
+ record.CustomerId === customerId;
357
+ });
358
+
359
+ let hirer = await HirerChangeRequestSignature.init(
360
+ foundHirer.SignatureId,
361
+ dbTransaction,
362
+ );
363
+
364
+ await hirer.update(loginUser, dbTransaction);
365
+ }
366
+
367
+ // 2.4 Check if all hirer in request is signed, if yes check request Type:
368
+ // Type = "Add" = update Request status to “AwaitingNewHirer”
369
+ // Type = "Remove" = flag the joint hirer record status to "Inactive" & update Request status to "Completed"
370
+ const isSigned = await this.checkIsAllSigned(dbTransaction);
371
+
372
+ if (isSigned) {
373
+ if (this.Type === HirerChangeRequestTypeEnum.ADD) {
374
+ this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
375
+ } else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
376
+ // TODO: Currently JointHirer dont have status props
377
+
378
+ await RentalHirerChangeRequest._JointHirerRepository.update(
379
+ { Status: 'Inactive' },
380
+ {
381
+ where: {
382
+ HirerId: this.RequestId,
383
+ },
384
+ transaction: dbTransaction,
385
+ },
386
+ );
387
+ this.Status = HirerChangeRequestStatusEnum.COMPLETED;
388
+ }
389
+ }
390
+
391
+ // 2.5 Set entityValueAfter
392
+ const entityValueAfter: IRentalHirerChangeRequestAttr = {
393
+ RequestId: this.RequestId,
394
+ RentalId: this.RentalId,
395
+ Type: this.Type,
396
+ Status: this.Status,
397
+ RequestedById: this.RequestedById,
398
+ RequestedAt: this.RequestedAt,
399
+ RequestingHirerId: this.RequestingHirerId,
400
+ RequestingHirerType: this.RequestingHirerType,
401
+ CancelRemarks: this.CancelRemarks,
402
+ UpdatedById: this.UpdatedById,
403
+ UpdatedAt: this.UpdatedAt,
404
+ };
405
+
406
+ // 2.6 Call repo class update method by passing the class attributes and db transaction.
407
+ await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
408
+ where: {
409
+ RequestId: this.RequestId,
410
+ },
411
+ transaction: dbTransaction,
412
+ });
413
+
414
+ //Part 3: Record Create Hirer Change Request Activity
415
+ const activity = new Activity();
416
+ activity.ObjectId = this._createId();
417
+ activity.Action = ActionEnum.UPDATE;
418
+ activity.Description = 'Update Hirer Change Request';
419
+ activity.EntityId = this.ObjectId;
420
+ activity.EntityType = this.ObjectType;
421
+ activity.EntityValueBefore = JSON.stringify(entityValueBefore);
422
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
423
+
424
+ await activity.create(loginUser.ObjectId, dbTransaction);
425
+
426
+ return this;
427
+ } catch (error) {
428
+ throw error;
429
+ }
430
+ }
431
+
432
+ public async generateSignatures(loginUser: LoginUser, dbTransaction?: any) {
433
+ try {
434
+ if (!this.RentalId) {
435
+ throw new ClassError(
436
+ 'HirerChangeRequest',
437
+ 'HirerChangeRequestErrMsg09',
438
+ 'RentalId is required to create signatures.',
439
+ );
440
+ }
441
+
442
+ // 1. If this.Rental is null, set it to Rental instantiation using this.RentalId
443
+ if (!this.Rental) {
444
+ this.Rental = await Rental.init(dbTransaction, this.RentalId);
445
+ }
446
+
447
+ // 2. Prepare all signature data (main + joint) in one go
448
+ this.Rental.AccountType = RentalAccountTypeEnum.JOINT;
449
+ const jointHirers = await this.Rental.getJointHirers(dbTransaction);
450
+
451
+ // Main hirer signature
452
+ const mainSignature = await HirerChangeRequestSignature.init();
453
+ mainSignature.RequestId = this.RequestId;
454
+ mainSignature.CustomerId = this.Rental.CustomerId;
455
+ mainSignature.HirerType = HirerChangeRequestHirerRoleEnum.MAIN;
456
+ mainSignature.Method = 'Upload';
457
+
458
+ // Joint hirer signatures - only if there are joint hirers
459
+ let jointSignatures = [];
460
+ if (jointHirers.length > 0) {
461
+ const jointSignaturePromises = jointHirers.map(async (jointHirer) => {
462
+ const signature = await HirerChangeRequestSignature.init();
463
+ signature.RequestId = this.RequestId;
464
+ signature.JointHirerId = jointHirer.HirerId;
465
+ signature.HirerType = HirerChangeRequestHirerRoleEnum.JOINT;
466
+ signature.Method = 'Upload';
467
+ return signature;
468
+ });
469
+
470
+ jointSignatures = await Promise.all(jointSignaturePromises);
471
+ }
472
+
473
+ // 3. Create all signatures in parallel
474
+ const signaturesToCreate = [
475
+ mainSignature.create(loginUser, dbTransaction),
476
+ ];
477
+ if (jointSignatures.length > 0) {
478
+ signaturesToCreate.push(
479
+ ...jointSignatures.map((sig) => sig.create(loginUser, dbTransaction)),
480
+ );
481
+ }
482
+
483
+ await Promise.all(signaturesToCreate);
484
+
485
+ this.Signatures = [mainSignature, ...jointSignatures];
486
+ } catch (error) {
487
+ console.error('Error creating signatures:', error);
488
+ throw error;
489
+ }
490
+ }
491
+
492
+ public async createAddRequest(
493
+ newHirer: {
494
+ FullName: string;
495
+ IdNo: string;
496
+ IdType: string;
497
+ Email?: string;
498
+ ContactNo: string;
499
+ Relationship: string;
500
+ Address: string;
501
+ City: string;
502
+ State: string;
503
+ Postcode: string;
504
+ Country: string;
505
+ },
506
+ loginUser: LoginUser,
507
+ dbTransaction?: any,
508
+ ): Promise<{
509
+ hirerChangeRequest: RentalHirerChangeRequest;
510
+ NewHirer: HirerChangeRequestNewHirer;
511
+ }> {
512
+ try {
513
+ // Validations
514
+ // 1. Make sure newHirer required fields cannot be null.
515
+ if (
516
+ !newHirer.FullName ||
517
+ !newHirer.IdNo ||
518
+ !newHirer.IdType ||
519
+ !newHirer.ContactNo ||
520
+ !newHirer.Address ||
521
+ !newHirer.City ||
522
+ !newHirer.State ||
523
+ !newHirer.Postcode ||
524
+ !newHirer.Country
525
+ ) {
526
+ throw new ClassError(
527
+ 'HirerChangeRequest',
528
+ 'HirerChangeRequestErrMsg10',
529
+ 'FullName, IdNo, IdType, ContactNo, and Address are required.',
530
+ );
531
+ }
532
+
533
+ // 2. Set this.Type to "Add".
534
+ this.Type = HirerChangeRequestTypeEnum.ADD;
535
+
536
+ // 3. Call this.create by passing:
537
+ // loginUser, dbTransaction
538
+ await this.create(loginUser, dbTransaction);
539
+
540
+ // 4. Insert into hirerChangeRequest_NewHirer
541
+ const nh = await HirerChangeRequestNewHirer.init();
542
+ nh.RequestId = this.RequestId;
543
+ nh.FullName = newHirer.FullName;
544
+ nh.Email = newHirer.Email;
545
+ nh.IdType = newHirer.IdType;
546
+ nh.IdNo = newHirer.IdNo;
547
+ nh.ContactNo = newHirer.ContactNo;
548
+ nh.Relationship = newHirer.Relationship;
549
+ nh.Address = newHirer.Address;
550
+ nh.City = newHirer.City;
551
+ nh.State = newHirer.State;
552
+ nh.Postcode = newHirer.Postcode;
553
+ nh.Country = newHirer.Country;
554
+
555
+ await nh.create(loginUser, dbTransaction);
556
+
557
+ // 5. Return HirerChangeRequest instance and NewHirer instance.
558
+ return {
559
+ hirerChangeRequest: this,
560
+ NewHirer: nh,
561
+ };
562
+ } catch (error) {
563
+ console.error('Error creating add request:', error);
564
+ throw error;
565
+ }
566
+ }
567
+
568
+ public async createRemoveRequest(
569
+ loginUser: LoginUser,
570
+ dbTransaction: any,
571
+ targetHirerId: string,
572
+ ): Promise<{
573
+ hirerChangeRequest: RentalHirerChangeRequest;
574
+ RemoveHirer: HirerChangeRequestRemoveHirer;
575
+ }> {
576
+ try {
577
+ // 1. Make sure targetHirerId can be instantiated into JointHirer class (existing joint hirer)
578
+ await JointHirer.init(targetHirerId, dbTransaction);
579
+
580
+ // 2. Set this.Type to "Remove"
581
+ this.Type = HirerChangeRequestTypeEnum.REMOVE;
582
+
583
+ // 3. Call this.create() method by passing loginUser, dbTransaction
584
+ await this.create(loginUser, dbTransaction);
585
+
586
+ // 4. Insert into hirerChangeRequest_RemoveHirer
587
+ const removeHirer = await HirerChangeRequestRemoveHirer.init();
588
+ removeHirer.RequestId = this.RequestId;
589
+ removeHirer.TargetHirerId = targetHirerId;
590
+
591
+ await removeHirer.create(loginUser, dbTransaction);
592
+
593
+ // 5. Return the returned HirerChangeRequest instance and RemoveHirer instance.
594
+ return {
595
+ hirerChangeRequest: this,
596
+ RemoveHirer: removeHirer,
597
+ };
598
+ } catch (error) {
599
+ console.error('Error creating remove request:', error);
600
+ throw error;
601
+ }
602
+ }
603
+
604
+ public static async findAll(
605
+ loginUser: LoginUser,
606
+ dbTransaction: any,
607
+ rentalId: string,
608
+ ): Promise<RentalHirerChangeRequest[]> {
609
+ try {
610
+ // 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
611
+ const systemCode =
612
+ ApplicationConfig.getComponentConfigValue('system-code');
613
+ const isPrivileged = await loginUser.checkPrivileges(
614
+ systemCode,
615
+ 'HIRER_CHANGE_REQUEST',
616
+ );
617
+ if (!isPrivileged) {
618
+ throw new ClassError(
619
+ 'HirerChangeRequest',
620
+ 'HirerChangeRequestErrMsg01',
621
+ "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
622
+ );
623
+ }
624
+
625
+ // 2. Make sure rentalId not null.
626
+ if (!rentalId) {
627
+ throw new ClassError(
628
+ 'HirerChangeRequest',
629
+ 'HirerChangeRequestErrMsg12',
630
+ 'rentalId is required.',
631
+ );
632
+ }
633
+
634
+ // 3. Instantiate rental (to check rental id valid)
635
+ await Rental.init(dbTransaction, rentalId);
636
+
637
+ // 4. Call Repo.findAll({ where: { RentalId: rentalId }, transaction: dbTransaction })
638
+ const records = await RentalHirerChangeRequest._Repository.findAll({
639
+ where: { RentalId: rentalId },
640
+ transaction: dbTransaction,
641
+ });
642
+
643
+ // 5. Instantiate the returned items
644
+ const result = (records || []).map(
645
+ (rec) => new RentalHirerChangeRequest(rec.get({ plain: true })),
646
+ );
647
+
648
+ // 6. Return the instance array
649
+ return result;
650
+ } catch (error) {
651
+ console.error('Error finding all RentalHirerChangeRequest:', error);
652
+ throw error;
653
+ }
654
+ }
655
+
656
+ public async getNewHirer(
657
+ dbTransaction: any,
658
+ ): Promise<HirerChangeRequestNewHirer> {
659
+ try {
660
+ // 1. Make sure this.RequestId got value.
661
+ if (!this.RequestId) {
662
+ throw new ClassError(
663
+ 'HirerChangeRequest',
664
+ 'HirerChangeRequestErrMsg13',
665
+ 'RequestId is required to get new hirer.',
666
+ );
667
+ }
668
+
669
+ // 2. Call HirerChangeRequestNewHirer.findAll()
670
+ const newHirerRecords = await HirerChangeRequestNewHirer.findAll(
671
+ {
672
+ RequestId: this.RequestId,
673
+ },
674
+ dbTransaction,
675
+ );
676
+
677
+ // 3. Return the newHirer instance
678
+ return newHirerRecords[0] || null;
679
+ } catch (error) {
680
+ console.error('Error getting new hirer:', error);
681
+ throw error;
682
+ }
683
+ }
684
+
685
+ public async getRemoveHirer(
686
+ dbTransaction: any,
687
+ ): Promise<HirerChangeRequestRemoveHirer> {
688
+ try {
689
+ // 1. Make sure this.RequestId got value.
690
+ if (!this.RequestId) {
691
+ throw new ClassError(
692
+ 'HirerChangeRequest',
693
+ 'HirerChangeRequestErrMsg13',
694
+ 'RequestId is required to get remove hirer.',
695
+ );
696
+ }
697
+
698
+ // 2. Call HirerChangeRequestRemoveHirer.findAll()
699
+ const removeHirerRecords = await HirerChangeRequestRemoveHirer.findAll(
700
+ {
701
+ RequestId: this.RequestId,
702
+ },
703
+ dbTransaction,
704
+ );
705
+
706
+ // 3. Return the removeHirer instance
707
+ return removeHirerRecords[0] || null;
708
+ } catch (error) {
709
+ console.error('Error getting remove hirer:', error);
710
+ throw error;
711
+ }
712
+ }
713
+
714
+ public async sign(
715
+ loginUser: LoginUser,
716
+ dbTransaction: any,
717
+ signatureId: string,
718
+ ): Promise<HirerChangeRequestSignature> {
719
+ try {
720
+ // 1. Make sure this.RequestId got value.
721
+ if (!this.RequestId) {
722
+ throw new ClassError(
723
+ 'HirerChangeRequest',
724
+ 'HirerChangeRequestErrMsg13',
725
+ 'RequestId is required to sign signature.',
726
+ );
727
+ }
728
+
729
+ // Validate signatureId
730
+ const hcrSignature = await HirerChangeRequestSignature.init(
731
+ signatureId,
732
+ dbTransaction,
733
+ );
734
+
735
+ //Call hcrSignature.markSigned() method by passing loginUser and dbTransaction
736
+ await hcrSignature.markSigned(loginUser, dbTransaction);
737
+
738
+ // const isSigned = await this.checkIsAllSigned(dbTransaction);
739
+
740
+ // if (isSigned && this.Type === HirerChangeRequestTypeEnum.ADD) {
741
+ // this.Status = HirerChangeRequestStatusEnum.AWAITINGNEWHIRER;
742
+ // this.UpdatedAt = new Date();
743
+ // this.UpdatedById = loginUser.ObjectId;
744
+ // await RentalHirerChangeRequest._Repository.update(this.toJSON(), {
745
+ // where: { RequestId: this.RequestId },
746
+ // transaction: dbTransaction,
747
+ // });
748
+ // }
749
+ return hcrSignature;
750
+ } catch (error) {
751
+ throw error;
752
+ }
753
+ }
754
+
755
+ public async complete(
756
+ loginUser: LoginUser,
757
+ dbTransaction: any,
758
+ customerId?: string,
759
+ customerType?: string,
760
+ ): Promise<RentalHirerChangeRequest> {
761
+ // 1. Validations
762
+ // a. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
763
+ const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
764
+ const isPrivileged = await loginUser.checkPrivileges(
765
+ systemCode,
766
+ 'HIRER_CHANGE_REQUEST',
767
+ );
768
+ if (!isPrivileged) {
769
+ throw new ClassError(
770
+ 'HirerChangeRequest',
771
+ 'HirerChangeRequestErrMsg01',
772
+ "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
773
+ );
774
+ }
775
+
776
+ // b. Make sure this.RequestId not null.
777
+ if (!this.RequestId) {
778
+ throw new ClassError(
779
+ 'HirerChangeRequest',
780
+ 'HirerChangeRequestErrMsg06',
781
+ 'RequestId is required.',
782
+ );
783
+ }
784
+
785
+ // c. Make sure all signatures are signed.
786
+ const signatures = await this.getSignatures(dbTransaction);
787
+ if (!signatures.length || !signatures.every((sig) => sig.SignedAt)) {
788
+ throw new ClassError(
789
+ 'HirerChangeRequest',
790
+ 'HirerChangeRequestErrMsg14',
791
+ 'All signatures must be signed before completing the request.',
792
+ );
793
+ }
794
+
795
+ // 2. Create/Remove Hirer
796
+ if (this.Type === HirerChangeRequestTypeEnum.ADD) {
797
+ //Make sure CustomerId is set, if not throw error
798
+ if (!customerId || !customerType) {
799
+ throw new ClassError(
800
+ 'HirerChangeRequest',
801
+ 'HirerChangeRequestErrMsg15',
802
+ 'CustomerId and CustomerType are required for new hirer.',
803
+ );
804
+ }
805
+ // c. Create joint hirer using JointHirer.create()
806
+ const jointHirer = await JointHirer.init();
807
+ jointHirer.RentalId = this.RentalId;
808
+ jointHirer.CustomerId = customerId;
809
+ jointHirer.CustomerType = customerType;
810
+ await jointHirer.create(loginUser, dbTransaction);
811
+ } else if (this.Type === HirerChangeRequestTypeEnum.REMOVE) {
812
+ // a. Get joint hirer from remove hirer request
813
+ const removeHirer = await this.getRemoveHirer(dbTransaction);
814
+ const jointHirer = await JointHirer.init(
815
+ removeHirer.TargetHirerId,
816
+ dbTransaction,
817
+ );
818
+
819
+ //Call jointHirer.remove() method by passing loginUser and dbTransaction
820
+ await jointHirer.remove(loginUser, dbTransaction);
821
+ }
822
+
823
+ // 3. Call _Repo update method
824
+ const now = new Date();
825
+ const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
826
+ this.Status = HirerChangeRequestStatusEnum.COMPLETED;
827
+ this.UpdatedAt = new Date();
828
+ this.UpdatedById = loginUser.ObjectId;
829
+ const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
830
+ await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
831
+ where: { RequestId: this.RequestId },
832
+ transaction: dbTransaction,
833
+ });
834
+
835
+ // 4. Record activity history
836
+ const activity = new Activity();
837
+ activity.ObjectId = this._createId();
838
+ activity.Action = ActionEnum.UPDATE;
839
+ activity.Description = `Mark request as completed.`;
840
+ activity.EntityId = this.RequestId;
841
+ activity.EntityType = this.ObjectType;
842
+ activity.EntityValueBefore = JSON.stringify(entityValueBefore);
843
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
844
+
845
+ await activity.create(loginUser.ObjectId, dbTransaction);
846
+
847
+ // 5. Return updated instance
848
+ return this;
849
+ }
850
+
851
+ public async cancel(
852
+ loginUser: LoginUser,
853
+ dbTransaction: any,
854
+ cancelRemarks: string,
855
+ ): Promise<RentalHirerChangeRequest> {
856
+ // 1. Make sure user got "HIRER_CHANGE_REQUEST" privilege.
857
+ const systemCode = ApplicationConfig.getComponentConfigValue('system-code');
858
+ const isPrivileged = await loginUser.checkPrivileges(
859
+ systemCode,
860
+ 'HIRER_CHANGE_REQUEST',
861
+ );
862
+ if (!isPrivileged) {
863
+ throw new ClassError(
864
+ 'HirerChangeRequest',
865
+ 'HirerChangeRequestErrMsg01',
866
+ "You do not have 'HIRER_CHANGE_REQUEST' privilege.",
867
+ );
868
+ }
869
+
870
+ // 2. Make sure this.RequestId not null.
871
+ if (!this.RequestId) {
872
+ throw new ClassError(
873
+ 'HirerChangeRequest',
874
+ 'HirerChangeRequestErrMsg06',
875
+ 'RequestId is required.',
876
+ );
877
+ }
878
+
879
+ // 3. Call _Repo.update() method
880
+ const entityValueBefore: IRentalHirerChangeRequestAttr = this.toJSON();
881
+ this.Status = HirerChangeRequestStatusEnum.CANCELLED;
882
+ this.CancelRemarks = cancelRemarks;
883
+ this.UpdatedAt = new Date();
884
+ this.UpdatedById = loginUser.ObjectId;
885
+ const entityValueAfter: IRentalHirerChangeRequestAttr = this.toJSON();
886
+
887
+ await RentalHirerChangeRequest._Repository.update(entityValueAfter, {
888
+ where: { RequestId: this.RequestId },
889
+ transaction: dbTransaction,
890
+ });
891
+
892
+ // 4. Record activity history
893
+ const activity = new Activity();
894
+ activity.ObjectId = this._createId();
895
+ activity.Action = ActionEnum.UPDATE;
896
+ activity.Description = `Cancel hirer change request.`;
897
+ activity.EntityId = this.RequestId;
898
+ activity.EntityType = this.ObjectType;
899
+ activity.EntityValueBefore = JSON.stringify(entityValueBefore);
900
+ activity.EntityValueAfter = JSON.stringify(entityValueAfter);
901
+
902
+ await activity.create(loginUser.ObjectId, dbTransaction);
903
+
904
+ // 5. Return updated instance
905
+ return this;
906
+ }
907
+ }