@stamhoofd/models 2.39.1 → 2.40.1

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 (352) hide show
  1. package/dist/src/factories/AddressFactory.d.ts +3 -4
  2. package/dist/src/factories/AddressFactory.d.ts.map +1 -1
  3. package/dist/src/factories/AddressFactory.js +13 -13
  4. package/dist/src/factories/EmergencyContactFactory.d.ts +3 -4
  5. package/dist/src/factories/EmergencyContactFactory.d.ts.map +1 -1
  6. package/dist/src/factories/EmergencyContactFactory.js +27 -27
  7. package/dist/src/factories/EmergencyContactFactory.js.map +1 -1
  8. package/dist/src/factories/GroupFactory.d.ts +4 -4
  9. package/dist/src/factories/GroupFactory.d.ts.map +1 -1
  10. package/dist/src/factories/GroupFactory.js +8 -8
  11. package/dist/src/factories/GroupFactory.js.map +1 -1
  12. package/dist/src/factories/MemberFactory.d.ts +4 -4
  13. package/dist/src/factories/MemberFactory.d.ts.map +1 -1
  14. package/dist/src/factories/MemberFactory.js +17 -17
  15. package/dist/src/factories/MemberFactory.js.map +1 -1
  16. package/dist/src/factories/OrganizationFactory.d.ts +4 -4
  17. package/dist/src/factories/OrganizationFactory.js +8 -8
  18. package/dist/src/factories/OrganizationFactory.js.map +1 -1
  19. package/dist/src/factories/ParentFactory.d.ts +1 -1
  20. package/dist/src/factories/ParentFactory.js +19 -19
  21. package/dist/src/factories/ParentFactory.js.map +1 -1
  22. package/dist/src/factories/RecordFactory.d.ts +2 -3
  23. package/dist/src/factories/RecordFactory.d.ts.map +1 -1
  24. package/dist/src/factories/RecordFactory.js +1 -1
  25. package/dist/src/factories/RecordFactory.js.map +1 -1
  26. package/dist/src/factories/RegisterCodeFactory.d.ts +2 -2
  27. package/dist/src/factories/RegisterCodeFactory.d.ts.map +1 -1
  28. package/dist/src/factories/RegisterCodeFactory.js +2 -2
  29. package/dist/src/factories/RegistrationFactory.d.ts +3 -3
  30. package/dist/src/factories/RegistrationFactory.d.ts.map +1 -1
  31. package/dist/src/factories/RegistrationFactory.js.map +1 -1
  32. package/dist/src/factories/RegistrationPeriodFactory.d.ts +2 -2
  33. package/dist/src/factories/RegistrationPeriodFactory.js.map +1 -1
  34. package/dist/src/factories/UserFactory.d.ts +3 -3
  35. package/dist/src/factories/UserFactory.d.ts.map +1 -1
  36. package/dist/src/factories/UserFactory.js +3 -3
  37. package/dist/src/factories/UserFactory.js.map +1 -1
  38. package/dist/src/factories/WebshopFactory.d.ts +4 -4
  39. package/dist/src/factories/WebshopFactory.d.ts.map +1 -1
  40. package/dist/src/factories/WebshopFactory.js +1 -1
  41. package/dist/src/factories/WebshopFactory.js.map +1 -1
  42. package/dist/src/helpers/DNSValidator.d.ts +1 -1
  43. package/dist/src/helpers/DNSValidator.d.ts.map +1 -1
  44. package/dist/src/helpers/DNSValidator.js +33 -33
  45. package/dist/src/helpers/DNSValidator.js.map +1 -1
  46. package/dist/src/helpers/EmailBuilder.d.ts +10 -10
  47. package/dist/src/helpers/EmailBuilder.d.ts.map +1 -1
  48. package/dist/src/helpers/EmailBuilder.js +34 -34
  49. package/dist/src/helpers/EmailBuilder.js.map +1 -1
  50. package/dist/src/helpers/GroupBuilder.d.ts.map +1 -1
  51. package/dist/src/helpers/GroupBuilder.js +57 -57
  52. package/dist/src/helpers/GroupBuilder.js.map +1 -1
  53. package/dist/src/helpers/Handlebars.d.ts.map +1 -1
  54. package/dist/src/helpers/Handlebars.js +29 -29
  55. package/dist/src/helpers/Handlebars.js.map +1 -1
  56. package/dist/src/helpers/MemberMerger.d.ts +1 -1
  57. package/dist/src/helpers/MemberMerger.d.ts.map +1 -1
  58. package/dist/src/helpers/MemberMerger.js +33 -33
  59. package/dist/src/helpers/MemberMerger.js.map +1 -1
  60. package/dist/src/helpers/MemberMerger.test.js +194 -194
  61. package/dist/src/helpers/MemberMerger.test.js.map +1 -1
  62. package/dist/src/helpers/RateLimiter.d.ts.map +1 -1
  63. package/dist/src/helpers/RateLimiter.js +2 -2
  64. package/dist/src/helpers/RateLimiter.js.map +1 -1
  65. package/dist/src/helpers/SetupStepsUpdater.d.ts +22 -0
  66. package/dist/src/helpers/SetupStepsUpdater.d.ts.map +1 -0
  67. package/dist/src/helpers/SetupStepsUpdater.js +255 -0
  68. package/dist/src/helpers/SetupStepsUpdater.js.map +1 -0
  69. package/dist/src/helpers/WebshopCounter.d.ts +1 -1
  70. package/dist/src/helpers/WebshopCounter.d.ts.map +1 -1
  71. package/dist/src/helpers/WebshopCounter.js +1 -1
  72. package/dist/src/helpers/WebshopCounter.js.map +1 -1
  73. package/dist/src/helpers/WebshopCounter.test.js +6 -6
  74. package/dist/src/helpers/WebshopCounter.test.js.map +1 -1
  75. package/dist/src/index.d.ts +20 -19
  76. package/dist/src/index.d.ts.map +1 -1
  77. package/dist/src/index.js +1 -0
  78. package/dist/src/index.js.map +1 -1
  79. package/dist/src/migrations/1605262045-import-postcodes.js +12 -12
  80. package/dist/src/migrations/1605262046-import-postcodes-nl.js +10 -10
  81. package/dist/src/models/BalanceItem.d.ts.map +1 -1
  82. package/dist/src/models/BalanceItem.js +37 -37
  83. package/dist/src/models/BalanceItem.js.map +1 -1
  84. package/dist/src/models/BalanceItemPayment.d.ts.map +1 -1
  85. package/dist/src/models/BalanceItemPayment.js +13 -13
  86. package/dist/src/models/BalanceItemPayment.js.map +1 -1
  87. package/dist/src/models/BuckarooPayment.d.ts +1 -1
  88. package/dist/src/models/BuckarooPayment.d.ts.map +1 -1
  89. package/dist/src/models/BuckarooPayment.js +5 -5
  90. package/dist/src/models/BuckarooPayment.js.map +1 -1
  91. package/dist/src/models/CachedOutstandingBalance.d.ts.map +1 -1
  92. package/dist/src/models/CachedOutstandingBalance.js +37 -37
  93. package/dist/src/models/CachedOutstandingBalance.js.map +1 -1
  94. package/dist/src/models/Document.d.ts +4 -4
  95. package/dist/src/models/Document.d.ts.map +1 -1
  96. package/dist/src/models/Document.js +27 -27
  97. package/dist/src/models/Document.js.map +1 -1
  98. package/dist/src/models/DocumentTemplate.d.ts +4 -4
  99. package/dist/src/models/DocumentTemplate.d.ts.map +1 -1
  100. package/dist/src/models/DocumentTemplate.js +72 -72
  101. package/dist/src/models/DocumentTemplate.js.map +1 -1
  102. package/dist/src/models/Email.d.ts.map +1 -1
  103. package/dist/src/models/Email.js +63 -64
  104. package/dist/src/models/Email.js.map +1 -1
  105. package/dist/src/models/EmailRecipient.d.ts.map +1 -1
  106. package/dist/src/models/EmailRecipient.js +20 -20
  107. package/dist/src/models/EmailRecipient.js.map +1 -1
  108. package/dist/src/models/EmailTemplate.d.ts +3 -3
  109. package/dist/src/models/EmailTemplate.d.ts.map +1 -1
  110. package/dist/src/models/EmailTemplate.js +16 -16
  111. package/dist/src/models/EmailTemplate.js.map +1 -1
  112. package/dist/src/models/EmailVerificationCode.d.ts +2 -2
  113. package/dist/src/models/EmailVerificationCode.d.ts.map +1 -1
  114. package/dist/src/models/EmailVerificationCode.js +57 -55
  115. package/dist/src/models/EmailVerificationCode.js.map +1 -1
  116. package/dist/src/models/Event.d.ts +2 -2
  117. package/dist/src/models/Event.d.ts.map +1 -1
  118. package/dist/src/models/Event.js +15 -15
  119. package/dist/src/models/Event.js.map +1 -1
  120. package/dist/src/models/Group.d.ts +3 -1
  121. package/dist/src/models/Group.d.ts.map +1 -1
  122. package/dist/src/models/Group.js +46 -35
  123. package/dist/src/models/Group.js.map +1 -1
  124. package/dist/src/models/Image.d.ts +1 -1
  125. package/dist/src/models/Image.d.ts.map +1 -1
  126. package/dist/src/models/Image.js +26 -26
  127. package/dist/src/models/Image.js.map +1 -1
  128. package/dist/src/models/Member.d.ts +8 -8
  129. package/dist/src/models/Member.d.ts.map +1 -1
  130. package/dist/src/models/Member.js +60 -60
  131. package/dist/src/models/Member.js.map +1 -1
  132. package/dist/src/models/MemberPlatformMembership.d.ts +3 -3
  133. package/dist/src/models/MemberPlatformMembership.d.ts.map +1 -1
  134. package/dist/src/models/MemberPlatformMembership.js +26 -26
  135. package/dist/src/models/MemberPlatformMembership.js.map +1 -1
  136. package/dist/src/models/MemberResponsibilityRecord.d.ts.map +1 -1
  137. package/dist/src/models/MemberResponsibilityRecord.js +13 -13
  138. package/dist/src/models/MemberResponsibilityRecord.js.map +1 -1
  139. package/dist/src/models/MergedMember.d.ts +3 -3
  140. package/dist/src/models/MergedMember.d.ts.map +1 -1
  141. package/dist/src/models/MergedMember.js +19 -19
  142. package/dist/src/models/MergedMember.js.map +1 -1
  143. package/dist/src/models/MolliePayment.d.ts +1 -1
  144. package/dist/src/models/MolliePayment.d.ts.map +1 -1
  145. package/dist/src/models/MolliePayment.js +5 -5
  146. package/dist/src/models/MolliePayment.js.map +1 -1
  147. package/dist/src/models/MollieToken.d.ts.map +1 -1
  148. package/dist/src/models/MollieToken.js +60 -60
  149. package/dist/src/models/MollieToken.js.map +1 -1
  150. package/dist/src/models/OneTimeToken.d.ts +2 -2
  151. package/dist/src/models/OneTimeToken.d.ts.map +1 -1
  152. package/dist/src/models/OneTimeToken.js +13 -13
  153. package/dist/src/models/OneTimeToken.js.map +1 -1
  154. package/dist/src/models/Order.d.ts +1 -1
  155. package/dist/src/models/Order.d.ts.map +1 -1
  156. package/dist/src/models/Order.js +70 -70
  157. package/dist/src/models/Order.js.map +1 -1
  158. package/dist/src/models/Organization.d.ts +5 -5
  159. package/dist/src/models/Organization.d.ts.map +1 -1
  160. package/dist/src/models/Organization.js +127 -127
  161. package/dist/src/models/Organization.js.map +1 -1
  162. package/dist/src/models/OrganizationRegistrationPeriod.d.ts.map +1 -1
  163. package/dist/src/models/OrganizationRegistrationPeriod.js +15 -15
  164. package/dist/src/models/OrganizationRegistrationPeriod.js.map +1 -1
  165. package/dist/src/models/PasswordToken.d.ts +3 -3
  166. package/dist/src/models/PasswordToken.d.ts.map +1 -1
  167. package/dist/src/models/PasswordToken.js +17 -17
  168. package/dist/src/models/PasswordToken.js.map +1 -1
  169. package/dist/src/models/PayconiqPayment.d.ts +1 -1
  170. package/dist/src/models/PayconiqPayment.d.ts.map +1 -1
  171. package/dist/src/models/PayconiqPayment.js +49 -49
  172. package/dist/src/models/PayconiqPayment.js.map +1 -1
  173. package/dist/src/models/Payment.d.ts +3 -3
  174. package/dist/src/models/Payment.d.ts.map +1 -1
  175. package/dist/src/models/Payment.js +36 -36
  176. package/dist/src/models/Payment.js.map +1 -1
  177. package/dist/src/models/Platform.d.ts +2 -2
  178. package/dist/src/models/Platform.d.ts.map +1 -1
  179. package/dist/src/models/Platform.js +8 -8
  180. package/dist/src/models/Platform.js.map +1 -1
  181. package/dist/src/models/RegisterCode.d.ts +1 -1
  182. package/dist/src/models/RegisterCode.d.ts.map +1 -1
  183. package/dist/src/models/RegisterCode.js +11 -11
  184. package/dist/src/models/RegisterCode.js.map +1 -1
  185. package/dist/src/models/Registration.d.ts +1 -1
  186. package/dist/src/models/Registration.d.ts.map +1 -1
  187. package/dist/src/models/Registration.js +88 -88
  188. package/dist/src/models/Registration.js.map +1 -1
  189. package/dist/src/models/RegistrationPeriod.d.ts.map +1 -1
  190. package/dist/src/models/RegistrationPeriod.js +12 -12
  191. package/dist/src/models/RegistrationPeriod.js.map +1 -1
  192. package/dist/src/models/STCredit.d.ts +1 -1
  193. package/dist/src/models/STCredit.d.ts.map +1 -1
  194. package/dist/src/models/STCredit.js +12 -12
  195. package/dist/src/models/STCredit.js.map +1 -1
  196. package/dist/src/models/STInvoice.d.ts +1 -1
  197. package/dist/src/models/STInvoice.d.ts.map +1 -1
  198. package/dist/src/models/STInvoice.js +16 -16
  199. package/dist/src/models/STInvoice.js.map +1 -1
  200. package/dist/src/models/STPackage.d.ts +1 -1
  201. package/dist/src/models/STPackage.d.ts.map +1 -1
  202. package/dist/src/models/STPackage.js +39 -39
  203. package/dist/src/models/STPackage.js.map +1 -1
  204. package/dist/src/models/STPendingInvoice.d.ts +1 -1
  205. package/dist/src/models/STPendingInvoice.d.ts.map +1 -1
  206. package/dist/src/models/STPendingInvoice.js +11 -11
  207. package/dist/src/models/STPendingInvoice.js.map +1 -1
  208. package/dist/src/models/StripeAccount.d.ts.map +1 -1
  209. package/dist/src/models/StripeAccount.js +13 -13
  210. package/dist/src/models/StripeAccount.js.map +1 -1
  211. package/dist/src/models/StripeCheckoutSession.d.ts +1 -1
  212. package/dist/src/models/StripeCheckoutSession.d.ts.map +1 -1
  213. package/dist/src/models/StripeCheckoutSession.js +7 -7
  214. package/dist/src/models/StripeCheckoutSession.js.map +1 -1
  215. package/dist/src/models/StripePaymentIntent.d.ts +1 -1
  216. package/dist/src/models/StripePaymentIntent.d.ts.map +1 -1
  217. package/dist/src/models/StripePaymentIntent.js +7 -7
  218. package/dist/src/models/StripePaymentIntent.js.map +1 -1
  219. package/dist/src/models/Ticket.d.ts +2 -2
  220. package/dist/src/models/Ticket.d.ts.map +1 -1
  221. package/dist/src/models/Ticket.js +23 -23
  222. package/dist/src/models/Ticket.js.map +1 -1
  223. package/dist/src/models/Token.d.ts +3 -3
  224. package/dist/src/models/Token.d.ts.map +1 -1
  225. package/dist/src/models/Token.js +27 -27
  226. package/dist/src/models/Token.js.map +1 -1
  227. package/dist/src/models/Token.test.js +11 -11
  228. package/dist/src/models/UsedRegisterCode.d.ts +1 -1
  229. package/dist/src/models/UsedRegisterCode.d.ts.map +1 -1
  230. package/dist/src/models/UsedRegisterCode.js +10 -10
  231. package/dist/src/models/UsedRegisterCode.js.map +1 -1
  232. package/dist/src/models/User.d.ts +4 -4
  233. package/dist/src/models/User.d.ts.map +1 -1
  234. package/dist/src/models/User.js +53 -51
  235. package/dist/src/models/User.js.map +1 -1
  236. package/dist/src/models/UserPermissions.d.ts +3 -3
  237. package/dist/src/models/UserPermissions.d.ts.map +1 -1
  238. package/dist/src/models/UserPermissions.js +12 -12
  239. package/dist/src/models/UserPermissions.js.map +1 -1
  240. package/dist/src/models/Webshop.d.ts +1 -1
  241. package/dist/src/models/Webshop.d.ts.map +1 -1
  242. package/dist/src/models/Webshop.js +23 -23
  243. package/dist/src/models/Webshop.js.map +1 -1
  244. package/dist/src/models/WebshopDiscountCode.d.ts +1 -1
  245. package/dist/src/models/WebshopDiscountCode.d.ts.map +1 -1
  246. package/dist/src/models/WebshopDiscountCode.js +16 -16
  247. package/dist/src/models/WebshopDiscountCode.js.map +1 -1
  248. package/dist/src/models/addresses/City.d.ts.map +1 -1
  249. package/dist/src/models/addresses/City.js +9 -9
  250. package/dist/src/models/addresses/City.js.map +1 -1
  251. package/dist/src/models/addresses/PostalCode.d.ts.map +1 -1
  252. package/dist/src/models/addresses/PostalCode.js +11 -11
  253. package/dist/src/models/addresses/PostalCode.js.map +1 -1
  254. package/dist/src/models/addresses/PostalCode.test.js +22 -22
  255. package/dist/src/models/addresses/PostalCode.test.js.map +1 -1
  256. package/dist/src/models/addresses/Province.d.ts.map +1 -1
  257. package/dist/src/models/addresses/Province.js +5 -5
  258. package/dist/src/models/addresses/Province.js.map +1 -1
  259. package/dist/src/models/addresses/Street.d.ts.map +1 -1
  260. package/dist/src/models/addresses/Street.js +6 -6
  261. package/dist/src/models/addresses/Street.js.map +1 -1
  262. package/dist/src/models/index.d.ts +46 -46
  263. package/dist/src/models/index.d.ts.map +1 -1
  264. package/dist/src/models/index.js +0 -1
  265. package/dist/src/models/index.js.map +1 -1
  266. package/dist/src/structures/OrganizationServerMetaData.d.ts.map +1 -1
  267. package/dist/src/structures/OrganizationServerMetaData.js +4 -4
  268. package/dist/src/structures/OrganizationServerMetaData.js.map +1 -1
  269. package/dist/tests/jest.global.setup.d.ts.map +1 -1
  270. package/dist/tests/jest.global.setup.js +15 -13
  271. package/dist/tests/jest.global.setup.js.map +1 -1
  272. package/dist/tests/jest.setup.js +3 -1
  273. package/dist/tests/jest.setup.js.map +1 -1
  274. package/dist/tsconfig.tsbuildinfo +1 -0
  275. package/package.json +3 -3
  276. package/src/factories/AddressFactory.ts +17 -17
  277. package/src/factories/EmergencyContactFactory.ts +30 -31
  278. package/src/factories/GroupFactory.ts +30 -30
  279. package/src/factories/MemberFactory.ts +41 -38
  280. package/src/factories/OrganizationFactory.ts +15 -15
  281. package/src/factories/ParentFactory.ts +24 -24
  282. package/src/factories/RecordFactory.ts +5 -4
  283. package/src/factories/RegisterCodeFactory.ts +7 -7
  284. package/src/factories/RegistrationFactory.ts +16 -16
  285. package/src/factories/RegistrationPeriodFactory.ts +5 -5
  286. package/src/factories/UserFactory.ts +20 -19
  287. package/src/factories/WebshopFactory.ts +14 -14
  288. package/src/helpers/DNSValidator.ts +89 -84
  289. package/src/helpers/EmailBuilder.ts +141 -135
  290. package/src/helpers/GroupBuilder.ts +181 -181
  291. package/src/helpers/Handlebars.ts +57 -54
  292. package/src/helpers/MemberMerger.test.ts +702 -702
  293. package/src/helpers/MemberMerger.ts +83 -77
  294. package/src/helpers/RateLimiter.ts +25 -27
  295. package/src/helpers/SetupStepsUpdater.ts +402 -0
  296. package/src/helpers/WebshopCounter.test.ts +12 -12
  297. package/src/helpers/WebshopCounter.ts +20 -19
  298. package/src/index.ts +20 -19
  299. package/src/migrations/1605262045-import-postcodes.ts +59 -63
  300. package/src/migrations/1605262046-import-postcodes-nl.ts +41 -43
  301. package/src/models/BalanceItem.ts +173 -172
  302. package/src/models/BalanceItemPayment.ts +32 -33
  303. package/src/models/BuckarooPayment.ts +7 -7
  304. package/src/models/CachedOutstandingBalance.ts +98 -99
  305. package/src/models/Document.ts +90 -87
  306. package/src/models/DocumentTemplate.ts +207 -198
  307. package/src/models/Email.ts +198 -200
  308. package/src/models/EmailRecipient.ts +38 -39
  309. package/src/models/EmailTemplate.ts +36 -37
  310. package/src/models/EmailVerificationCode.ts +146 -142
  311. package/src/models/Event.ts +53 -53
  312. package/src/models/Group.ts +136 -123
  313. package/src/models/Image.ts +48 -48
  314. package/src/models/Member.ts +277 -275
  315. package/src/models/MemberPlatformMembership.ts +71 -71
  316. package/src/models/MemberResponsibilityRecord.ts +32 -32
  317. package/src/models/MergedMember.ts +77 -77
  318. package/src/models/MolliePayment.ts +7 -7
  319. package/src/models/MollieToken.ts +131 -126
  320. package/src/models/OneTimeToken.ts +40 -39
  321. package/src/models/Order.ts +379 -372
  322. package/src/models/Organization.ts +332 -325
  323. package/src/models/OrganizationRegistrationPeriod.ts +50 -50
  324. package/src/models/PasswordToken.ts +42 -42
  325. package/src/models/PayconiqPayment.ts +80 -76
  326. package/src/models/Payment.ts +86 -86
  327. package/src/models/Platform.ts +21 -22
  328. package/src/models/RegisterCode.ts +26 -26
  329. package/src/models/Registration.ts +167 -168
  330. package/src/models/RegistrationPeriod.ts +29 -29
  331. package/src/models/STCredit.ts +24 -25
  332. package/src/models/STInvoice.ts +34 -34
  333. package/src/models/STPackage.ts +143 -136
  334. package/src/models/STPendingInvoice.ts +26 -26
  335. package/src/models/StripeAccount.ts +27 -27
  336. package/src/models/StripeCheckoutSession.ts +10 -10
  337. package/src/models/StripePaymentIntent.ts +10 -10
  338. package/src/models/Ticket.ts +51 -52
  339. package/src/models/Token.test.ts +13 -13
  340. package/src/models/Token.ts +64 -63
  341. package/src/models/UsedRegisterCode.ts +20 -21
  342. package/src/models/User.ts +148 -144
  343. package/src/models/UserPermissions.ts +25 -28
  344. package/src/models/Webshop.ts +53 -53
  345. package/src/models/WebshopDiscountCode.ts +33 -33
  346. package/src/models/addresses/City.ts +12 -12
  347. package/src/models/addresses/PostalCode.test.ts +68 -69
  348. package/src/models/addresses/PostalCode.ts +57 -57
  349. package/src/models/addresses/Province.ts +8 -8
  350. package/src/models/addresses/Street.ts +10 -12
  351. package/src/models/index.ts +54 -55
  352. package/src/structures/OrganizationServerMetaData.ts +36 -36
@@ -1,11 +1,11 @@
1
1
  import { column, Model } from '@simonbackx/simple-database';
2
2
  import { EditorSmartButton, EditorSmartVariable, EmailAttachment, EmailPreview, EmailRecipientFilter, EmailRecipientFilterType, EmailRecipientsStatus, EmailRecipient as EmailRecipientStruct, EmailStatus, Email as EmailStruct, getExampleRecipient, LimitedFilteredRequest, PaginatedResponse, Recipient, SortItemDirection } from '@stamhoofd/structures';
3
- import { v4 as uuidv4 } from "uuid";
3
+ import { v4 as uuidv4 } from 'uuid';
4
4
 
5
5
  import { AnyDecoder, ArrayDecoder } from '@simonbackx/simple-encoding';
6
6
  import { SimpleError } from '@simonbackx/simple-errors';
7
7
  import { I18n } from '@stamhoofd/backend-i18n';
8
- import { Email as EmailClass } from "@stamhoofd/email";
8
+ import { Email as EmailClass } from '@stamhoofd/email';
9
9
  import { QueueHandler } from '@stamhoofd/queues';
10
10
  import { SQL, SQLWhereSign } from '@stamhoofd/sql';
11
11
  import { Formatter } from '@stamhoofd/utility';
@@ -14,201 +14,198 @@ import { EmailRecipient } from './EmailRecipient';
14
14
  import { Organization } from './Organization';
15
15
 
16
16
  export class Email extends Model {
17
- static table = "emails";
17
+ static table = 'emails';
18
18
 
19
19
  @column({
20
- primary: true, type: "string", beforeSave(value) {
20
+ primary: true, type: 'string', beforeSave(value) {
21
21
  return value ?? uuidv4();
22
- }
22
+ },
23
23
  })
24
24
  id!: string;
25
25
 
26
- @column({ type: "string", nullable: true })
27
- organizationId: string|null = null;
26
+ @column({ type: 'string', nullable: true })
27
+ organizationId: string | null = null;
28
28
 
29
- @column({ type: "string", nullable: true})
30
- userId: string|null = null;
29
+ @column({ type: 'string', nullable: true })
30
+ userId: string | null = null;
31
31
 
32
- @column({ type: "json", decoder: EmailRecipientFilter })
33
- recipientFilter: EmailRecipientFilter = EmailRecipientFilter.create({})
32
+ @column({ type: 'json', decoder: EmailRecipientFilter })
33
+ recipientFilter: EmailRecipientFilter = EmailRecipientFilter.create({});
34
34
 
35
- @column({ type: "string", nullable: true })
36
- subject: string|null
35
+ @column({ type: 'string', nullable: true })
36
+ subject: string | null;
37
37
 
38
- /** Raw json structure to edit the template */
39
- @column({ type: "json", decoder: AnyDecoder })
38
+ /** Raw json structure to edit the template */
39
+ @column({ type: 'json', decoder: AnyDecoder })
40
40
  json: any = {};
41
41
 
42
- @column({ type: "string", nullable: true })
43
- html: string|null = null
42
+ @column({ type: 'string', nullable: true })
43
+ html: string | null = null;
44
44
 
45
- @column({ type: "string", nullable: true})
46
- text: string|null = null
45
+ @column({ type: 'string', nullable: true })
46
+ text: string | null = null;
47
47
 
48
- @column({ type: "string", nullable: true})
49
- fromAddress: string|null = null
48
+ @column({ type: 'string', nullable: true })
49
+ fromAddress: string | null = null;
50
50
 
51
- @column({ type: "string", nullable: true})
52
- fromName: string|null = null
51
+ @column({ type: 'string', nullable: true })
52
+ fromName: string | null = null;
53
53
 
54
- @column({ type: "integer", nullable: true})
55
- recipientCount: number|null = null
54
+ @column({ type: 'integer', nullable: true })
55
+ recipientCount: number | null = null;
56
56
 
57
- @column({ type: "string" })
57
+ @column({ type: 'string' })
58
58
  status = EmailStatus.Draft;
59
59
 
60
- @column({ type: "string" })
60
+ @column({ type: 'string' })
61
61
  recipientsStatus = EmailRecipientsStatus.NotCreated;
62
62
 
63
63
  /**
64
64
  * todo: ignore automatically
65
65
  */
66
- @column({ type: "json", decoder: new ArrayDecoder(EmailAttachment) })
67
- attachments: EmailAttachment[] = []
66
+ @column({ type: 'json', decoder: new ArrayDecoder(EmailAttachment) })
67
+ attachments: EmailAttachment[] = [];
68
68
 
69
-
70
69
  @column({
71
- type: "datetime",
72
- nullable: true
70
+ type: 'datetime',
71
+ nullable: true,
73
72
  })
74
- sentAt: Date|null = null
73
+ sentAt: Date | null = null;
75
74
 
76
75
  @column({
77
- type: "datetime", beforeSave(old?: any) {
76
+ type: 'datetime', beforeSave(old?: any) {
78
77
  if (old !== undefined) {
79
78
  return old;
80
79
  }
81
- const date = new Date()
82
- date.setMilliseconds(0)
83
- return date
84
- }
80
+ const date = new Date();
81
+ date.setMilliseconds(0);
82
+ return date;
83
+ },
85
84
  })
86
- createdAt: Date
85
+ createdAt: Date;
87
86
 
88
87
  @column({
89
- type: "datetime", beforeSave() {
90
- const date = new Date()
91
- date.setMilliseconds(0)
92
- return date
88
+ type: 'datetime', beforeSave() {
89
+ const date = new Date();
90
+ date.setMilliseconds(0);
91
+ return date;
93
92
  },
94
- skipUpdate: true
93
+ skipUpdate: true,
95
94
  })
96
- updatedAt: Date
95
+ updatedAt: Date;
97
96
 
98
97
  static recipientLoaders: Map<EmailRecipientFilterType, {
99
- fetch(request: LimitedFilteredRequest): Promise<PaginatedResponse<EmailRecipientStruct[], LimitedFilteredRequest>>
100
- count(request: LimitedFilteredRequest): Promise<number>
101
- }> = new Map()
98
+ fetch(request: LimitedFilteredRequest): Promise<PaginatedResponse<EmailRecipientStruct[], LimitedFilteredRequest>>;
99
+ count(request: LimitedFilteredRequest): Promise<number>;
100
+ }> = new Map();
102
101
 
103
102
  throwIfNotReadyToSend() {
104
103
  if (this.subject == null || this.subject.length == 0) {
105
104
  throw new SimpleError({
106
105
  code: 'invalid_field',
107
106
  message: 'Missing subject',
108
- human: 'Vul een onderwerp in voor je een e-mail verstuurt'
109
- })
107
+ human: 'Vul een onderwerp in voor je een e-mail verstuurt',
108
+ });
110
109
  }
111
110
 
112
111
  if (this.text == null || this.text.length == 0) {
113
112
  throw new SimpleError({
114
113
  code: 'invalid_field',
115
114
  message: 'Missing text',
116
- human: 'Vul een tekst in voor je een e-mail verstuurt'
117
- })
115
+ human: 'Vul een tekst in voor je een e-mail verstuurt',
116
+ });
118
117
  }
119
118
 
120
119
  if (this.html == null || this.html.length == 0) {
121
120
  throw new SimpleError({
122
121
  code: 'invalid_field',
123
122
  message: 'Missing html',
124
- human: 'Vul een tekst in voor je een e-mail verstuurt'
125
- })
123
+ human: 'Vul een tekst in voor je een e-mail verstuurt',
124
+ });
126
125
  }
127
126
 
128
127
  if (this.fromAddress == null || this.fromAddress.length == 0) {
129
128
  throw new SimpleError({
130
129
  code: 'invalid_field',
131
130
  message: 'Missing from',
132
- human: 'Vul een afzender in voor je een e-mail verstuurt'
133
- })
131
+ human: 'Vul een afzender in voor je een e-mail verstuurt',
132
+ });
134
133
  }
135
134
 
136
- this.validateAttachments()
135
+ this.validateAttachments();
137
136
  }
138
-
137
+
139
138
  validateAttachments() {
140
139
  // Validate attachments
141
140
  const size = this.attachments.reduce((value: number, attachment) => {
142
- return value + attachment.bytes
143
- }, 0)
144
-
145
- if (size > 9.5*1024*1024) {
141
+ return value + attachment.bytes;
142
+ }, 0);
143
+
144
+ if (size > 9.5 * 1024 * 1024) {
146
145
  throw new SimpleError({
147
- code: "too_big_attachments",
148
- message: "Too big attachments",
149
- human: "Jouw bericht is te groot. Grote bijlages verstuur je beter niet via e-mail, je plaatst dan best een link naar de locatie in bv. Google Drive. De maximale grootte van een e-mail is 10MB, inclusief het bericht. Als je grote bestanden verstuurt kan je ze ook proberen te verkleinen.",
150
- field: "attachments"
151
- })
146
+ code: 'too_big_attachments',
147
+ message: 'Too big attachments',
148
+ human: 'Jouw bericht is te groot. Grote bijlages verstuur je beter niet via e-mail, je plaatst dan best een link naar de locatie in bv. Google Drive. De maximale grootte van een e-mail is 10MB, inclusief het bericht. Als je grote bestanden verstuurt kan je ze ook proberen te verkleinen.',
149
+ field: 'attachments',
150
+ });
152
151
  }
153
152
 
154
153
  const safeContentTypes = [
155
- "application/msword",
156
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
157
- "application/vnd.ms-excel",
158
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
159
- "application/pdf",
160
- "image/jpeg",
161
- "image/png",
162
- "image/gif"
163
- ]
154
+ 'application/msword',
155
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
156
+ 'application/vnd.ms-excel',
157
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
158
+ 'application/pdf',
159
+ 'image/jpeg',
160
+ 'image/png',
161
+ 'image/gif',
162
+ ];
164
163
 
165
164
  for (const attachment of this.attachments) {
166
165
  if (attachment.contentType && !safeContentTypes.includes(attachment.contentType)) {
167
166
  throw new SimpleError({
168
- code: "content_type_not_supported",
169
- message: "Content-Type not supported",
170
- human: "Het bestandstype van jouw bijlage wordt niet ondersteund of is onveilig om in een e-mail te plaatsen. Overweeg om je bestand op bv. Google Drive te zetten en de link in jouw e-mail te zetten.",
171
- field: "attachments"
172
- })
167
+ code: 'content_type_not_supported',
168
+ message: 'Content-Type not supported',
169
+ human: 'Het bestandstype van jouw bijlage wordt niet ondersteund of is onveilig om in een e-mail te plaatsen. Overweeg om je bestand op bv. Google Drive te zetten en de link in jouw e-mail te zetten.',
170
+ field: 'attachments',
171
+ });
173
172
  }
174
173
  }
175
174
  }
176
175
 
177
176
  getFromAddress() {
178
177
  if (!this.fromName) {
179
- return this.fromAddress!
178
+ return this.fromAddress!;
180
179
  }
181
180
 
182
- const cleanedName = Formatter.emailSenderName(this.fromName)
181
+ const cleanedName = Formatter.emailSenderName(this.fromName);
183
182
  if (cleanedName.length < 2) {
184
- return this.fromAddress!
183
+ return this.fromAddress!;
185
184
  }
186
- return '"'+cleanedName+'" <'+this.fromAddress+'>'
187
-
185
+ return '"' + cleanedName + '" <' + this.fromAddress + '>';
188
186
  }
189
187
 
190
- getDefaultFromAddress(organization?: Organization|null): string {
191
- const i18n = new I18n("nl", "BE")
192
- let address = "noreply@" + i18n.localizedDomains.defaultBroadcastEmail()
188
+ getDefaultFromAddress(organization?: Organization | null): string {
189
+ const i18n = new I18n('nl', 'BE');
190
+ let address = 'noreply@' + i18n.localizedDomains.defaultBroadcastEmail();
193
191
 
194
192
  if (organization) {
195
193
  address = organization.getDefaultFrom(organization.i18n, false, 'broadcast');
196
194
  }
197
195
 
198
196
  if (!this.fromName) {
199
- return address
197
+ return address;
200
198
  }
201
199
 
202
- const cleanedName = Formatter.emailSenderName(this.fromName)
200
+ const cleanedName = Formatter.emailSenderName(this.fromName);
203
201
  if (cleanedName.length < 2) {
204
- return address
202
+ return address;
205
203
  }
206
- return '"'+cleanedName+'" <'+address+'>'
207
-
204
+ return '"' + cleanedName + '" <' + address + '>';
208
205
  }
209
206
 
210
207
  async send() {
211
- this.throwIfNotReadyToSend()
208
+ this.throwIfNotReadyToSend();
212
209
  await this.save();
213
210
 
214
211
  const id = this.id;
@@ -218,8 +215,8 @@ export class Email extends Model {
218
215
  throw new SimpleError({
219
216
  code: 'not_found',
220
217
  message: 'Email not found',
221
- human: 'De e-mail die je probeert te versturen bestaat niet meer'
222
- })
218
+ human: 'De e-mail die je probeert te versturen bestaat niet meer',
219
+ });
223
220
  }
224
221
  if (upToDate.status === EmailStatus.Sent) {
225
222
  // Already done
@@ -227,35 +224,36 @@ export class Email extends Model {
227
224
  return;
228
225
  }
229
226
  const organization = upToDate.organizationId ? await Organization.getByID(upToDate.organizationId) : null;
230
- upToDate.throwIfNotReadyToSend()
227
+ upToDate.throwIfNotReadyToSend();
231
228
 
232
- let from = upToDate.getDefaultFromAddress(organization)
229
+ let from = upToDate.getDefaultFromAddress(organization);
233
230
  let replyTo: string | null = upToDate.getFromAddress();
234
231
 
235
232
  if (!from) {
236
233
  throw new SimpleError({
237
234
  code: 'invalid_field',
238
235
  message: 'Missing from',
239
- human: 'Vul een afzender in voor je een e-mail verstuurt'
240
- })
236
+ human: 'Vul een afzender in voor je een e-mail verstuurt',
237
+ });
241
238
  }
242
239
 
243
240
  // Can we send from this e-mail or reply-to?
244
241
  if (organization) {
245
- if (organization.privateMeta.mailDomain && organization.privateMeta.mailDomainActive && upToDate.fromAddress!.endsWith("@"+organization.privateMeta.mailDomain)) {
242
+ if (organization.privateMeta.mailDomain && organization.privateMeta.mailDomainActive && upToDate.fromAddress!.endsWith('@' + organization.privateMeta.mailDomain)) {
246
243
  from = upToDate.getFromAddress();
247
244
  replyTo = null;
248
245
  }
249
- } else {
246
+ }
247
+ else {
250
248
  // Platform
251
249
  // Is the platform allowed to send from the provided email address?
252
250
  const domains = [
253
251
  ...Object.values(STAMHOOFD.domains.defaultTransactionalEmail ?? {}),
254
- ...Object.values(STAMHOOFD.domains.defaultBroadcastEmail ?? {})
255
- ]
252
+ ...Object.values(STAMHOOFD.domains.defaultBroadcastEmail ?? {}),
253
+ ];
256
254
 
257
255
  for (const domain of domains) {
258
- if (upToDate.fromAddress!.endsWith("@"+domain)) {
256
+ if (upToDate.fromAddress!.endsWith('@' + domain)) {
259
257
  from = upToDate.getFromAddress();
260
258
  replyTo = null;
261
259
  break;
@@ -263,12 +261,12 @@ export class Email extends Model {
263
261
  }
264
262
  }
265
263
 
266
- upToDate.status = EmailStatus.Sending
267
- upToDate.sentAt = upToDate.sentAt ?? new Date()
264
+ upToDate.status = EmailStatus.Sending;
265
+ upToDate.sentAt = upToDate.sentAt ?? new Date();
268
266
  await upToDate.save();
269
267
 
270
268
  // Create recipients if not yet created
271
- await upToDate.buildRecipients()
269
+ await upToDate.buildRecipients();
272
270
 
273
271
  // Refresh model
274
272
  upToDate = await Email.getByID(id);
@@ -276,16 +274,16 @@ export class Email extends Model {
276
274
  throw new SimpleError({
277
275
  code: 'not_found',
278
276
  message: 'Email not found',
279
- human: 'De e-mail die je probeert te versturen bestaat niet meer'
280
- })
277
+ human: 'De e-mail die je probeert te versturen bestaat niet meer',
278
+ });
281
279
  }
282
280
 
283
281
  if (upToDate.recipientsStatus !== EmailRecipientsStatus.Created) {
284
282
  throw new SimpleError({
285
283
  code: 'recipients_not_created',
286
284
  message: 'Failed to create recipients',
287
- human: 'Er ging iets mis bij het aanmaken van de afzenders.'
288
- })
285
+ human: 'Er ging iets mis bij het aanmaken van de afzenders.',
286
+ });
289
287
  }
290
288
 
291
289
  // Start actually sending in batches of recipients that are not yet sent
@@ -294,27 +292,26 @@ export class Email extends Model {
294
292
  const recipientsSet = new Set<string>();
295
293
 
296
294
  const attachments = upToDate.attachments.map((attachment, index) => {
297
- let filename = "bijlage-"+index;
298
-
299
- if (attachment.contentType == "application/pdf") {
295
+ let filename = 'bijlage-' + index;
296
+
297
+ if (attachment.contentType == 'application/pdf') {
300
298
  // tmp solution for pdf only
301
- filename += ".pdf"
299
+ filename += '.pdf';
302
300
  }
303
-
301
+
304
302
  // Correct file name if needed
305
303
  if (attachment.filename) {
306
- filename = attachment.filename.toLowerCase().replace(/[^a-z0-9.]+/g, "-").replace(/^-+/, "").replace(/-+$/, "")
304
+ filename = attachment.filename.toLowerCase().replace(/[^a-z0-9.]+/g, '-').replace(/^-+/, '').replace(/-+$/, '');
307
305
  }
308
-
306
+
309
307
  return {
310
308
  filename: filename,
311
309
  content: attachment.content,
312
310
  contentType: attachment.contentType ?? undefined,
313
- encoding: "base64"
314
- }
315
- })
311
+ encoding: 'base64',
312
+ };
313
+ });
316
314
 
317
- // eslint-disable-next-line no-constant-condition
318
315
  while (true) {
319
316
  const data = await SQL.select()
320
317
  .from('email_recipients')
@@ -324,7 +321,7 @@ export class Email extends Model {
324
321
  .orderBy(SQL.column('id'), 'ASC')
325
322
  .limit(batchSize)
326
323
  .fetch();
327
-
324
+
328
325
  const recipients = EmailRecipient.fromRows(data, 'email_recipients');
329
326
 
330
327
  if (recipients.length == 0) {
@@ -335,54 +332,55 @@ export class Email extends Model {
335
332
 
336
333
  for (const recipient of recipients) {
337
334
  if (recipientsSet.has(recipient.id)) {
338
- console.error('Found duplicate recipient while sending email', recipient.id)
335
+ console.error('Found duplicate recipient while sending email', recipient.id);
339
336
  continue;
340
337
  }
341
338
 
342
339
  recipientsSet.add(recipient.email);
343
340
  idPointer = recipient.id;
344
341
 
345
- let promiseResolve: (value: void | PromiseLike<void>) => void
342
+ let promiseResolve: (value: void | PromiseLike<void>) => void;
346
343
  const promise = new Promise<void>((resolve) => {
347
344
  promiseResolve = resolve;
348
345
  });
349
- sendingPromises.push(promise)
346
+ sendingPromises.push(promise);
350
347
 
351
- const callback = async (error: Error|null) => {
348
+ const callback = async (error: Error | null) => {
352
349
  if (error === null) {
353
350
  // Mark saved
354
351
  recipient.sentAt = new Date();
355
- await recipient.save()
356
- } else {
352
+ await recipient.save();
353
+ }
354
+ else {
357
355
  recipient.failCount += 1;
358
356
  recipient.failErrorMessage = error.message;
359
357
  recipient.firstFailedAt = recipient.firstFailedAt ?? new Date();
360
358
  recipient.lastFailedAt = new Date();
361
- await recipient.save()
359
+ await recipient.save();
362
360
  }
363
- promiseResolve()
364
- }
361
+ promiseResolve();
362
+ };
365
363
 
366
364
  // Do send the email
367
365
  // Create e-mail builder
368
366
  const builder = await getEmailBuilder(organization ?? null, {
369
367
  recipients: [
370
368
  Recipient.create({
371
- ...recipient
372
- })
369
+ ...recipient,
370
+ }),
373
371
  ],
374
- from,
372
+ from,
375
373
  replyTo,
376
- subject: upToDate.subject!,
374
+ subject: upToDate.subject!,
377
375
  html: upToDate.html!,
378
- type: "broadcast",
376
+ type: 'broadcast',
379
377
  attachments,
380
- callback(error: Error|null ) {
381
- callback(error).catch(console.error)
378
+ callback(error: Error | null) {
379
+ callback(error).catch(console.error);
382
380
  },
383
- })
381
+ });
384
382
 
385
- EmailClass.schedule(builder)
383
+ EmailClass.schedule(builder);
386
384
  }
387
385
 
388
386
  await Promise.all(sendingPromises);
@@ -398,7 +396,7 @@ export class Email extends Model {
398
396
 
399
397
  updateCount() {
400
398
  const id = this.id;
401
- QueueHandler.schedule('email-count-'+this.id, async function () {
399
+ QueueHandler.schedule('email-count-' + this.id, async function () {
402
400
  let upToDate = await Email.getByID(id);
403
401
 
404
402
  if (!upToDate || upToDate.sentAt || !upToDate.id || upToDate.status !== EmailStatus.Draft) {
@@ -413,24 +411,23 @@ export class Email extends Model {
413
411
 
414
412
  try {
415
413
  for (const subfilter of upToDate.recipientFilter.filters) {
416
-
417
414
  // Create recipients
418
415
  const loader = Email.recipientLoaders.get(subfilter.type);
419
416
 
420
417
  if (!loader) {
421
- throw new Error('Loader for type ' + subfilter.type+' has not been initialised on the Email model')
418
+ throw new Error('Loader for type ' + subfilter.type + ' has not been initialised on the Email model');
422
419
  }
423
420
 
424
421
  const request = new LimitedFilteredRequest({
425
422
  filter: subfilter.filter,
426
- sort: [{key: 'id', order: SortItemDirection.ASC}],
423
+ sort: [{ key: 'id', order: SortItemDirection.ASC }],
427
424
  limit: 1,
428
425
  search: subfilter.search,
429
- })
426
+ });
430
427
 
431
428
  const c = await loader.count(request);
432
-
433
- count += c
429
+
430
+ count += c;
434
431
  }
435
432
 
436
433
  // Check if we have a more reliable recipientCount in the meantime
@@ -444,8 +441,9 @@ export class Email extends Model {
444
441
  }
445
442
  upToDate.recipientCount = count;
446
443
  await upToDate.save();
447
- } catch (e) {
448
- console.error("Failed to update count for email", id);
444
+ }
445
+ catch (e) {
446
+ console.error('Failed to update count for email', id);
449
447
  console.error(e);
450
448
  }
451
449
  }).catch(console.error);
@@ -453,7 +451,7 @@ export class Email extends Model {
453
451
 
454
452
  async buildRecipients() {
455
453
  const id = this.id;
456
- await QueueHandler.schedule('email-build-recipients-'+this.id, async function () {
454
+ await QueueHandler.schedule('email-build-recipients-' + this.id, async function () {
457
455
  const upToDate = await Email.getByID(id);
458
456
 
459
457
  if (!upToDate || !upToDate.id) {
@@ -480,28 +478,27 @@ export class Email extends Model {
480
478
  await SQL
481
479
  .delete()
482
480
  .from(
483
- SQL.table('email_recipients')
481
+ SQL.table('email_recipients'),
484
482
  )
485
483
  .where(SQL.column('emailId'), upToDate.id);
486
484
 
487
485
  for (const subfilter of upToDate.recipientFilter.filters) {
488
-
489
486
  // Create recipients
490
487
  const loader = Email.recipientLoaders.get(subfilter.type);
491
488
 
492
489
  if (!loader) {
493
- throw new Error('Loader for type ' + subfilter.type+' has not been initialised on the Email model')
490
+ throw new Error('Loader for type ' + subfilter.type + ' has not been initialised on the Email model');
494
491
  }
495
492
 
496
- let request: LimitedFilteredRequest|null = new LimitedFilteredRequest({
493
+ let request: LimitedFilteredRequest | null = new LimitedFilteredRequest({
497
494
  filter: subfilter.filter,
498
- sort: [{key: 'id', order: SortItemDirection.ASC}],
495
+ sort: [{ key: 'id', order: SortItemDirection.ASC }],
499
496
  limit: 1000,
500
497
  search: subfilter.search,
501
- })
498
+ });
502
499
 
503
500
  while (request) {
504
- console.log('Loading email page', subfilter.type, request)
501
+ console.log('Loading email page', subfilter.type, request);
505
502
  const response = await loader.fetch(request);
506
503
 
507
504
  count += response.results.length;
@@ -509,10 +506,10 @@ export class Email extends Model {
509
506
  for (const item of response.results) {
510
507
  const recipient = new EmailRecipient();
511
508
  recipient.emailId = upToDate.id;
512
- recipient.email = item.email
513
- recipient.firstName = item.firstName
514
- recipient.lastName = item.lastName
515
- recipient.replacements = item.replacements
509
+ recipient.email = item.email;
510
+ recipient.firstName = item.firstName;
511
+ recipient.lastName = item.lastName;
512
+ recipient.replacements = item.replacements;
516
513
 
517
514
  await recipient.save();
518
515
  }
@@ -528,8 +525,9 @@ export class Email extends Model {
528
525
  upToDate.recipientsStatus = EmailRecipientsStatus.Created;
529
526
  upToDate.recipientCount = count;
530
527
  await upToDate.save();
531
- } catch (e) {
532
- console.error("Failed to build recipients for email", id);
528
+ }
529
+ catch (e) {
530
+ console.error('Failed to build recipients for email', id);
533
531
  console.error(e);
534
532
  upToDate.recipientsStatus = EmailRecipientsStatus.NotCreated;
535
533
  await upToDate.save();
@@ -539,7 +537,7 @@ export class Email extends Model {
539
537
 
540
538
  async buildExampleRecipient() {
541
539
  const id = this.id;
542
- await QueueHandler.schedule('email-build-recipients-'+this.id, async function () {
540
+ await QueueHandler.schedule('email-build-recipients-' + this.id, async function () {
543
541
  const upToDate = await Email.getByID(id);
544
542
 
545
543
  if (!upToDate || upToDate.sentAt || !upToDate.id) {
@@ -555,28 +553,27 @@ export class Email extends Model {
555
553
  await SQL
556
554
  .delete()
557
555
  .from(
558
- SQL.table('email_recipients')
556
+ SQL.table('email_recipients'),
559
557
  )
560
558
  .where(SQL.column('emailId'), upToDate.id);
561
559
 
562
560
  for (const subfilter of upToDate.recipientFilter.filters) {
563
-
564
561
  // Create recipients
565
562
  const loader = Email.recipientLoaders.get(subfilter.type);
566
563
 
567
564
  if (!loader) {
568
- throw new Error('Loader for type ' + subfilter.type+' has not been initialised on the Email model')
565
+ throw new Error('Loader for type ' + subfilter.type + ' has not been initialised on the Email model');
569
566
  }
570
567
 
571
- let request: LimitedFilteredRequest|null = new LimitedFilteredRequest({
568
+ let request: LimitedFilteredRequest | null = new LimitedFilteredRequest({
572
569
  filter: subfilter.filter,
573
- sort: [{key: 'id', order: SortItemDirection.ASC}],
570
+ sort: [{ key: 'id', order: SortItemDirection.ASC }],
574
571
  limit: 10,
575
572
  search: subfilter.search,
576
- })
573
+ });
577
574
 
578
575
  while (request) {
579
- console.log('Loading email page', subfilter.type, request)
576
+ console.log('Loading email page', subfilter.type, request);
580
577
  const response = await loader.fetch(request);
581
578
 
582
579
  // Note: it is possible that a result in the database doesn't return a recipient (in memory filtering)
@@ -585,10 +582,10 @@ export class Email extends Model {
585
582
  for (const item of response.results) {
586
583
  const recipient = new EmailRecipient();
587
584
  recipient.emailId = upToDate.id;
588
- recipient.email = item.email
589
- recipient.firstName = item.firstName
590
- recipient.lastName = item.lastName
591
- recipient.replacements = item.replacements
585
+ recipient.email = item.email;
586
+ recipient.firstName = item.firstName;
587
+ recipient.lastName = item.lastName;
588
+ recipient.replacements = item.replacements;
592
589
  await recipient.save();
593
590
  return;
594
591
  }
@@ -597,16 +594,17 @@ export class Email extends Model {
597
594
  }
598
595
  }
599
596
 
600
- console.warn('No example recipient found for email', id)
601
- } catch (e) {
602
- console.error("Failed to build example recipient for email", id);
597
+ console.warn('No example recipient found for email', id);
598
+ }
599
+ catch (e) {
600
+ console.error('Failed to build example recipient for email', id);
603
601
  console.error(e);
604
602
  }
605
603
  }).catch(console.error);
606
604
  }
607
605
 
608
606
  getStructure() {
609
- return EmailStruct.create(this)
607
+ return EmailStruct.create(this);
610
608
  }
611
609
 
612
610
  async getPreviewStructure() {
@@ -615,27 +613,27 @@ export class Email extends Model {
615
613
  .where(SQL.column('emailId'), this.id)
616
614
  .first(false);
617
615
 
618
- let recipientRow: EmailRecipientStruct | undefined;
616
+ let recipientRow: EmailRecipientStruct | undefined;
619
617
 
620
- if(recipient) {
621
- const emailRecipient = EmailRecipient.fromRow(recipient[EmailRecipient.table]);
622
- if(emailRecipient) {
623
- recipientRow = emailRecipient.getStructure();
624
- }
618
+ if (recipient) {
619
+ const emailRecipient = EmailRecipient.fromRow(recipient[EmailRecipient.table]);
620
+ if (emailRecipient) {
621
+ recipientRow = emailRecipient.getStructure();
625
622
  }
623
+ }
626
624
 
627
- if(!recipientRow) {
628
- recipientRow = getExampleRecipient();
629
- }
625
+ if (!recipientRow) {
626
+ recipientRow = getExampleRecipient();
627
+ }
630
628
 
631
- const smartVariables = recipientRow ? EditorSmartVariable.forRecipient(recipientRow) : []
632
- const smartButtons = recipientRow ? EditorSmartButton.forRecipient(recipientRow) : []
633
-
634
- return EmailPreview.create({
635
- ...this,
636
- exampleRecipient: recipientRow,
637
- smartVariables,
638
- smartButtons
639
- })
629
+ const smartVariables = recipientRow ? EditorSmartVariable.forRecipient(recipientRow) : [];
630
+ const smartButtons = recipientRow ? EditorSmartButton.forRecipient(recipientRow) : [];
631
+
632
+ return EmailPreview.create({
633
+ ...this,
634
+ exampleRecipient: recipientRow,
635
+ smartVariables,
636
+ smartButtons,
637
+ });
640
638
  }
641
639
  }