@stamhoofd/models 2.1.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 (481) hide show
  1. package/dist/src/assets/Metropolis-Black.woff2 +0 -0
  2. package/dist/src/assets/Metropolis-BlackItalic.woff2 +0 -0
  3. package/dist/src/assets/Metropolis-Bold.woff2 +0 -0
  4. package/dist/src/assets/Metropolis-BoldItalic.woff2 +0 -0
  5. package/dist/src/assets/Metropolis-ExtraBold.woff2 +0 -0
  6. package/dist/src/assets/Metropolis-ExtraBoldItalic.woff2 +0 -0
  7. package/dist/src/assets/Metropolis-ExtraLight.woff2 +0 -0
  8. package/dist/src/assets/Metropolis-ExtraLightItalic.woff2 +0 -0
  9. package/dist/src/assets/Metropolis-Light.woff2 +0 -0
  10. package/dist/src/assets/Metropolis-LightItalic.woff2 +0 -0
  11. package/dist/src/assets/Metropolis-Medium.woff2 +0 -0
  12. package/dist/src/assets/Metropolis-MediumItalic.woff2 +0 -0
  13. package/dist/src/assets/Metropolis-Regular.woff2 +0 -0
  14. package/dist/src/assets/Metropolis-RegularItalic.woff2 +0 -0
  15. package/dist/src/assets/Metropolis-SemiBold.woff2 +0 -0
  16. package/dist/src/assets/Metropolis-SemiBoldItalic.woff2 +0 -0
  17. package/dist/src/assets/Metropolis-Thin.woff2 +0 -0
  18. package/dist/src/assets/Metropolis-ThinItalic.woff2 +0 -0
  19. package/dist/src/assets/assets/Metropolis-Black.woff2 +0 -0
  20. package/dist/src/assets/assets/Metropolis-BlackItalic.woff2 +0 -0
  21. package/dist/src/assets/assets/Metropolis-Bold.woff2 +0 -0
  22. package/dist/src/assets/assets/Metropolis-BoldItalic.woff2 +0 -0
  23. package/dist/src/assets/assets/Metropolis-ExtraBold.woff2 +0 -0
  24. package/dist/src/assets/assets/Metropolis-ExtraBoldItalic.woff2 +0 -0
  25. package/dist/src/assets/assets/Metropolis-ExtraLight.woff2 +0 -0
  26. package/dist/src/assets/assets/Metropolis-ExtraLightItalic.woff2 +0 -0
  27. package/dist/src/assets/assets/Metropolis-Light.woff2 +0 -0
  28. package/dist/src/assets/assets/Metropolis-LightItalic.woff2 +0 -0
  29. package/dist/src/assets/assets/Metropolis-Medium.woff2 +0 -0
  30. package/dist/src/assets/assets/Metropolis-MediumItalic.woff2 +0 -0
  31. package/dist/src/assets/assets/Metropolis-Regular.woff2 +0 -0
  32. package/dist/src/assets/assets/Metropolis-RegularItalic.woff2 +0 -0
  33. package/dist/src/assets/assets/Metropolis-SemiBold.woff2 +0 -0
  34. package/dist/src/assets/assets/Metropolis-SemiBoldItalic.woff2 +0 -0
  35. package/dist/src/assets/assets/Metropolis-Thin.woff2 +0 -0
  36. package/dist/src/assets/assets/Metropolis-ThinItalic.woff2 +0 -0
  37. package/dist/src/assets/assets/logo.png +0 -0
  38. package/dist/src/assets/logo.png +0 -0
  39. package/dist/src/factories/AddressFactory.d.ts +10 -0
  40. package/dist/src/factories/AddressFactory.d.ts.map +1 -0
  41. package/dist/src/factories/AddressFactory.js +42 -0
  42. package/dist/src/factories/AddressFactory.js.map +1 -0
  43. package/dist/src/factories/EmergencyContactFactory.d.ts +9 -0
  44. package/dist/src/factories/EmergencyContactFactory.d.ts.map +1 -0
  45. package/dist/src/factories/EmergencyContactFactory.js +42 -0
  46. package/dist/src/factories/EmergencyContactFactory.js.map +1 -0
  47. package/dist/src/factories/GroupFactory.d.ts +19 -0
  48. package/dist/src/factories/GroupFactory.d.ts.map +1 -0
  49. package/dist/src/factories/GroupFactory.js +52 -0
  50. package/dist/src/factories/GroupFactory.js.map +1 -0
  51. package/dist/src/factories/MemberFactory.d.ts +16 -0
  52. package/dist/src/factories/MemberFactory.d.ts.map +1 -0
  53. package/dist/src/factories/MemberFactory.js +98 -0
  54. package/dist/src/factories/MemberFactory.js.map +1 -0
  55. package/dist/src/factories/OrganizationFactory.d.ts +16 -0
  56. package/dist/src/factories/OrganizationFactory.d.ts.map +1 -0
  57. package/dist/src/factories/OrganizationFactory.js +40 -0
  58. package/dist/src/factories/OrganizationFactory.js.map +1 -0
  59. package/dist/src/factories/ParentFactory.d.ts +10 -0
  60. package/dist/src/factories/ParentFactory.d.ts.map +1 -0
  61. package/dist/src/factories/ParentFactory.js +44 -0
  62. package/dist/src/factories/ParentFactory.js.map +1 -0
  63. package/dist/src/factories/RecordFactory.d.ts +10 -0
  64. package/dist/src/factories/RecordFactory.d.ts.map +1 -0
  65. package/dist/src/factories/RecordFactory.js +14 -0
  66. package/dist/src/factories/RecordFactory.js.map +1 -0
  67. package/dist/src/factories/RegisterCodeFactory.d.ts +18 -0
  68. package/dist/src/factories/RegisterCodeFactory.d.ts.map +1 -0
  69. package/dist/src/factories/RegisterCodeFactory.js +19 -0
  70. package/dist/src/factories/RegisterCodeFactory.js.map +1 -0
  71. package/dist/src/factories/RegistrationFactory.d.ts +14 -0
  72. package/dist/src/factories/RegistrationFactory.d.ts.map +1 -0
  73. package/dist/src/factories/RegistrationFactory.js +26 -0
  74. package/dist/src/factories/RegistrationFactory.js.map +1 -0
  75. package/dist/src/factories/UserFactory.d.ts +21 -0
  76. package/dist/src/factories/UserFactory.d.ts.map +1 -0
  77. package/dist/src/factories/UserFactory.js +41 -0
  78. package/dist/src/factories/UserFactory.js.map +1 -0
  79. package/dist/src/factories/WebshopFactory.d.ts +16 -0
  80. package/dist/src/factories/WebshopFactory.d.ts.map +1 -0
  81. package/dist/src/factories/WebshopFactory.js +35 -0
  82. package/dist/src/factories/WebshopFactory.js.map +1 -0
  83. package/dist/src/helpers/DNSValidator.d.ts +6 -0
  84. package/dist/src/helpers/DNSValidator.d.ts.map +1 -0
  85. package/dist/src/helpers/DNSValidator.js +144 -0
  86. package/dist/src/helpers/DNSValidator.js.map +1 -0
  87. package/dist/src/helpers/EmailBuilder.d.ts +22 -0
  88. package/dist/src/helpers/EmailBuilder.d.ts.map +1 -0
  89. package/dist/src/helpers/EmailBuilder.js +100 -0
  90. package/dist/src/helpers/EmailBuilder.js.map +1 -0
  91. package/dist/src/helpers/GroupBuilder.d.ts +9 -0
  92. package/dist/src/helpers/GroupBuilder.d.ts.map +1 -0
  93. package/dist/src/helpers/GroupBuilder.js +382 -0
  94. package/dist/src/helpers/GroupBuilder.js.map +1 -0
  95. package/dist/src/helpers/Handlebars.d.ts +2 -0
  96. package/dist/src/helpers/Handlebars.d.ts.map +1 -0
  97. package/dist/src/helpers/Handlebars.js +192 -0
  98. package/dist/src/helpers/Handlebars.js.map +1 -0
  99. package/dist/src/helpers/InvoiceBuilder.d.ts +29 -0
  100. package/dist/src/helpers/InvoiceBuilder.d.ts.map +1 -0
  101. package/dist/src/helpers/InvoiceBuilder.js +406 -0
  102. package/dist/src/helpers/InvoiceBuilder.js.map +1 -0
  103. package/dist/src/helpers/InvoiceBuilder.test.d.ts +2 -0
  104. package/dist/src/helpers/InvoiceBuilder.test.d.ts.map +1 -0
  105. package/dist/src/helpers/InvoiceBuilder.test.js +52 -0
  106. package/dist/src/helpers/InvoiceBuilder.test.js.map +1 -0
  107. package/dist/src/helpers/RateLimiter.d.ts +27 -0
  108. package/dist/src/helpers/RateLimiter.d.ts.map +1 -0
  109. package/dist/src/helpers/RateLimiter.js +57 -0
  110. package/dist/src/helpers/RateLimiter.js.map +1 -0
  111. package/dist/src/helpers/WebshopCounter.d.ts +6 -0
  112. package/dist/src/helpers/WebshopCounter.d.ts.map +1 -0
  113. package/dist/src/helpers/WebshopCounter.js +36 -0
  114. package/dist/src/helpers/WebshopCounter.js.map +1 -0
  115. package/dist/src/helpers/WebshopCounter.test.d.ts +2 -0
  116. package/dist/src/helpers/WebshopCounter.test.d.ts.map +1 -0
  117. package/dist/src/helpers/WebshopCounter.test.js +17 -0
  118. package/dist/src/helpers/WebshopCounter.test.js.map +1 -0
  119. package/dist/src/index.d.ts +18 -0
  120. package/dist/src/index.d.ts.map +1 -0
  121. package/dist/src/index.js +23 -0
  122. package/dist/src/index.js.map +1 -0
  123. package/dist/src/migrations/1593773929-create-initial-tables.sql +634 -0
  124. package/dist/src/migrations/1605261999-gemeenten-tmp.sql +2820 -0
  125. package/dist/src/migrations/1605262045-import-postcodes.d.ts +16 -0
  126. package/dist/src/migrations/1605262045-import-postcodes.d.ts.map +1 -0
  127. package/dist/src/migrations/1605262045-import-postcodes.js +116 -0
  128. package/dist/src/migrations/1605262045-import-postcodes.js.map +1 -0
  129. package/dist/src/migrations/1605262046-import-postcodes-nl.d.ts +4 -0
  130. package/dist/src/migrations/1605262046-import-postcodes-nl.d.ts.map +1 -0
  131. package/dist/src/migrations/1605262046-import-postcodes-nl.js +83 -0
  132. package/dist/src/migrations/1605262046-import-postcodes-nl.js.map +1 -0
  133. package/dist/src/migrations/1605279038-drop-gemeenten-tmp.sql +1 -0
  134. package/dist/src/migrations/1648392491-default-templates.sql +9 -0
  135. package/dist/src/migrations/1651245707-default-templates-reminders.sql +6 -0
  136. package/dist/src/migrations/1708607340-tickets-deleted-at.sql +1 -0
  137. package/dist/src/migrations/1710459176-register-code-invoices.sql +3 -0
  138. package/dist/src/migrations/1712158247-discount-codes.sql +17 -0
  139. package/dist/src/migrations/1713178665-drop-invites.sql +1 -0
  140. package/dist/src/migrations/1713178666-drop-keychain.sql +1 -0
  141. package/dist/src/migrations/1713178667-drop-challenges.sql +1 -0
  142. package/dist/src/migrations/1713178668-drop-user-keys.sql +7 -0
  143. package/dist/src/migrations/1713178669-drop-organization-key.sql +2 -0
  144. package/dist/src/migrations/data/postcodes/nl/Drenthe +291 -0
  145. package/dist/src/migrations/data/postcodes/nl/Flevoland +107 -0
  146. package/dist/src/migrations/data/postcodes/nl/Friesland +518 -0
  147. package/dist/src/migrations/data/postcodes/nl/Gelderland +601 -0
  148. package/dist/src/migrations/data/postcodes/nl/Groningen +279 -0
  149. package/dist/src/migrations/data/postcodes/nl/Limburg +324 -0
  150. package/dist/src/migrations/data/postcodes/nl/Noord-Brabant +620 -0
  151. package/dist/src/migrations/data/postcodes/nl/Noord-Holland +566 -0
  152. package/dist/src/migrations/data/postcodes/nl/Overrijsel +344 -0
  153. package/dist/src/migrations/data/postcodes/nl/Utrecht +278 -0
  154. package/dist/src/migrations/data/postcodes/nl/Zeeland +179 -0
  155. package/dist/src/migrations/data/postcodes/nl/Zuid-Holland +662 -0
  156. package/dist/src/models/BalanceItem.d.ts +57 -0
  157. package/dist/src/models/BalanceItem.d.ts.map +1 -0
  158. package/dist/src/models/BalanceItem.js +346 -0
  159. package/dist/src/models/BalanceItem.js.map +1 -0
  160. package/dist/src/models/BalanceItemPayment.d.ts +31 -0
  161. package/dist/src/models/BalanceItemPayment.d.ts.map +1 -0
  162. package/dist/src/models/BalanceItemPayment.js +101 -0
  163. package/dist/src/models/BalanceItemPayment.js.map +1 -0
  164. package/dist/src/models/BuckarooPayment.d.ts +8 -0
  165. package/dist/src/models/BuckarooPayment.d.ts.map +1 -0
  166. package/dist/src/models/BuckarooPayment.js +24 -0
  167. package/dist/src/models/BuckarooPayment.js.map +1 -0
  168. package/dist/src/models/Document.d.ts +44 -0
  169. package/dist/src/models/Document.d.ts.map +1 -0
  170. package/dist/src/models/Document.js +194 -0
  171. package/dist/src/models/Document.js.map +1 -0
  172. package/dist/src/models/DocumentTemplate.d.ts +45 -0
  173. package/dist/src/models/DocumentTemplate.d.ts.map +1 -0
  174. package/dist/src/models/DocumentTemplate.js +533 -0
  175. package/dist/src/models/DocumentTemplate.js.map +1 -0
  176. package/dist/src/models/EmailTemplate.d.ts +22 -0
  177. package/dist/src/models/EmailTemplate.d.ts.map +1 -0
  178. package/dist/src/models/EmailTemplate.js +70 -0
  179. package/dist/src/models/EmailTemplate.js.map +1 -0
  180. package/dist/src/models/EmailVerificationCode.d.ts +60 -0
  181. package/dist/src/models/EmailVerificationCode.d.ts.map +1 -0
  182. package/dist/src/models/EmailVerificationCode.js +307 -0
  183. package/dist/src/models/EmailVerificationCode.js.map +1 -0
  184. package/dist/src/models/Group.d.ts +36 -0
  185. package/dist/src/models/Group.d.ts.map +1 -0
  186. package/dist/src/models/Group.js +231 -0
  187. package/dist/src/models/Group.js.map +1 -0
  188. package/dist/src/models/Image.d.ts +12 -0
  189. package/dist/src/models/Image.d.ts.map +1 -0
  190. package/dist/src/models/Image.js +137 -0
  191. package/dist/src/models/Image.js.map +1 -0
  192. package/dist/src/models/Member.d.ts +66 -0
  193. package/dist/src/models/Member.d.ts.map +1 -0
  194. package/dist/src/models/Member.js +309 -0
  195. package/dist/src/models/Member.js.map +1 -0
  196. package/dist/src/models/MemberResponsibilityRecord.d.ts +11 -0
  197. package/dist/src/models/MemberResponsibilityRecord.d.ts.map +1 -0
  198. package/dist/src/models/MemberResponsibilityRecord.js +47 -0
  199. package/dist/src/models/MemberResponsibilityRecord.js.map +1 -0
  200. package/dist/src/models/MolliePayment.d.ts +8 -0
  201. package/dist/src/models/MolliePayment.d.ts.map +1 -0
  202. package/dist/src/models/MolliePayment.js +24 -0
  203. package/dist/src/models/MolliePayment.js.map +1 -0
  204. package/dist/src/models/MollieToken.d.ts +45 -0
  205. package/dist/src/models/MollieToken.d.ts.map +1 -0
  206. package/dist/src/models/MollieToken.js +333 -0
  207. package/dist/src/models/MollieToken.js.map +1 -0
  208. package/dist/src/models/OneTimeToken.d.ts +38 -0
  209. package/dist/src/models/OneTimeToken.d.ts.map +1 -0
  210. package/dist/src/models/OneTimeToken.js +126 -0
  211. package/dist/src/models/OneTimeToken.js.map +1 -0
  212. package/dist/src/models/Order.d.ts +99 -0
  213. package/dist/src/models/Order.d.ts.map +1 -0
  214. package/dist/src/models/Order.js +912 -0
  215. package/dist/src/models/Order.js.map +1 -0
  216. package/dist/src/models/Organization.d.ts +119 -0
  217. package/dist/src/models/Organization.d.ts.map +1 -0
  218. package/dist/src/models/Organization.js +900 -0
  219. package/dist/src/models/Organization.js.map +1 -0
  220. package/dist/src/models/OrganizationRegistrationPeriod.d.ts +14 -0
  221. package/dist/src/models/OrganizationRegistrationPeriod.d.ts.map +1 -0
  222. package/dist/src/models/OrganizationRegistrationPeriod.js +62 -0
  223. package/dist/src/models/OrganizationRegistrationPeriod.js.map +1 -0
  224. package/dist/src/models/PasswordToken.d.ts +29 -0
  225. package/dist/src/models/PasswordToken.d.ts.map +1 -0
  226. package/dist/src/models/PasswordToken.js +118 -0
  227. package/dist/src/models/PasswordToken.js.map +1 -0
  228. package/dist/src/models/PayconiqPayment.d.ts +18 -0
  229. package/dist/src/models/PayconiqPayment.d.ts.map +1 -0
  230. package/dist/src/models/PayconiqPayment.js +216 -0
  231. package/dist/src/models/PayconiqPayment.js.map +1 -0
  232. package/dist/src/models/Payment.d.ts +62 -0
  233. package/dist/src/models/Payment.d.ts.map +1 -0
  234. package/dist/src/models/Payment.js +199 -0
  235. package/dist/src/models/Payment.js.map +1 -0
  236. package/dist/src/models/Platform.d.ts +15 -0
  237. package/dist/src/models/Platform.d.ts.map +1 -0
  238. package/dist/src/models/Platform.js +77 -0
  239. package/dist/src/models/Platform.js.map +1 -0
  240. package/dist/src/models/RegisterCode.d.ts +27 -0
  241. package/dist/src/models/RegisterCode.d.ts.map +1 -0
  242. package/dist/src/models/RegisterCode.js +162 -0
  243. package/dist/src/models/RegisterCode.js.map +1 -0
  244. package/dist/src/models/Registration.d.ts +47 -0
  245. package/dist/src/models/Registration.d.ts.map +1 -0
  246. package/dist/src/models/Registration.js +369 -0
  247. package/dist/src/models/Registration.js.map +1 -0
  248. package/dist/src/models/RegistrationPeriod.d.ts +15 -0
  249. package/dist/src/models/RegistrationPeriod.d.ts.map +1 -0
  250. package/dist/src/models/RegistrationPeriod.js +64 -0
  251. package/dist/src/models/RegistrationPeriod.js.map +1 -0
  252. package/dist/src/models/STCredit.d.ts +20 -0
  253. package/dist/src/models/STCredit.d.ts.map +1 -0
  254. package/dist/src/models/STCredit.js +129 -0
  255. package/dist/src/models/STCredit.js.map +1 -0
  256. package/dist/src/models/STInvoice.d.ts +51 -0
  257. package/dist/src/models/STInvoice.d.ts.map +1 -0
  258. package/dist/src/models/STInvoice.js +453 -0
  259. package/dist/src/models/STInvoice.js.map +1 -0
  260. package/dist/src/models/STPackage.d.ts +36 -0
  261. package/dist/src/models/STPackage.d.ts.map +1 -0
  262. package/dist/src/models/STPackage.js +300 -0
  263. package/dist/src/models/STPackage.js.map +1 -0
  264. package/dist/src/models/STPendingInvoice.d.ts +45 -0
  265. package/dist/src/models/STPendingInvoice.d.ts.map +1 -0
  266. package/dist/src/models/STPendingInvoice.js +284 -0
  267. package/dist/src/models/STPendingInvoice.js.map +1 -0
  268. package/dist/src/models/StripeAccount.d.ts +17 -0
  269. package/dist/src/models/StripeAccount.d.ts.map +1 -0
  270. package/dist/src/models/StripeAccount.js +81 -0
  271. package/dist/src/models/StripeAccount.js.map +1 -0
  272. package/dist/src/models/StripeCheckoutSession.d.ts +9 -0
  273. package/dist/src/models/StripeCheckoutSession.d.ts.map +1 -0
  274. package/dist/src/models/StripeCheckoutSession.js +31 -0
  275. package/dist/src/models/StripeCheckoutSession.js.map +1 -0
  276. package/dist/src/models/StripePaymentIntent.d.ts +9 -0
  277. package/dist/src/models/StripePaymentIntent.d.ts.map +1 -0
  278. package/dist/src/models/StripePaymentIntent.js +31 -0
  279. package/dist/src/models/StripePaymentIntent.js.map +1 -0
  280. package/dist/src/models/Ticket.d.ts +61 -0
  281. package/dist/src/models/Ticket.d.ts.map +1 -0
  282. package/dist/src/models/Ticket.js +143 -0
  283. package/dist/src/models/Ticket.js.map +1 -0
  284. package/dist/src/models/Token.d.ts +49 -0
  285. package/dist/src/models/Token.d.ts.map +1 -0
  286. package/dist/src/models/Token.js +218 -0
  287. package/dist/src/models/Token.js.map +1 -0
  288. package/dist/src/models/Token.test.d.ts +2 -0
  289. package/dist/src/models/Token.test.d.ts.map +1 -0
  290. package/dist/src/models/Token.test.js +60 -0
  291. package/dist/src/models/Token.test.js.map +1 -0
  292. package/dist/src/models/UsedRegisterCode.d.ts +22 -0
  293. package/dist/src/models/UsedRegisterCode.d.ts.map +1 -0
  294. package/dist/src/models/UsedRegisterCode.js +158 -0
  295. package/dist/src/models/UsedRegisterCode.js.map +1 -0
  296. package/dist/src/models/User.d.ts +55 -0
  297. package/dist/src/models/User.d.ts.map +1 -0
  298. package/dist/src/models/User.js +314 -0
  299. package/dist/src/models/User.js.map +1 -0
  300. package/dist/src/models/UserPermissions.d.ts +15 -0
  301. package/dist/src/models/UserPermissions.d.ts.map +1 -0
  302. package/dist/src/models/UserPermissions.js +57 -0
  303. package/dist/src/models/UserPermissions.js.map +1 -0
  304. package/dist/src/models/Webshop.d.ts +44 -0
  305. package/dist/src/models/Webshop.d.ts.map +1 -0
  306. package/dist/src/models/Webshop.js +184 -0
  307. package/dist/src/models/Webshop.js.map +1 -0
  308. package/dist/src/models/WebshopDiscountCode.d.ts +18 -0
  309. package/dist/src/models/WebshopDiscountCode.d.ts.map +1 -0
  310. package/dist/src/models/WebshopDiscountCode.js +88 -0
  311. package/dist/src/models/WebshopDiscountCode.js.map +1 -0
  312. package/dist/src/models/addresses/City.d.ts +14 -0
  313. package/dist/src/models/addresses/City.d.ts.map +1 -0
  314. package/dist/src/models/addresses/City.js +37 -0
  315. package/dist/src/models/addresses/City.js.map +1 -0
  316. package/dist/src/models/addresses/PostalCode.d.ts +20 -0
  317. package/dist/src/models/addresses/PostalCode.d.ts.map +1 -0
  318. package/dist/src/models/addresses/PostalCode.js +138 -0
  319. package/dist/src/models/addresses/PostalCode.js.map +1 -0
  320. package/dist/src/models/addresses/PostalCode.test.d.ts +2 -0
  321. package/dist/src/models/addresses/PostalCode.test.d.ts.map +1 -0
  322. package/dist/src/models/addresses/PostalCode.test.js +98 -0
  323. package/dist/src/models/addresses/PostalCode.test.js.map +1 -0
  324. package/dist/src/models/addresses/Province.d.ts +9 -0
  325. package/dist/src/models/addresses/Province.d.ts.map +1 -0
  326. package/dist/src/models/addresses/Province.js +24 -0
  327. package/dist/src/models/addresses/Province.js.map +1 -0
  328. package/dist/src/models/addresses/Street.d.ts +10 -0
  329. package/dist/src/models/addresses/Street.d.ts.map +1 -0
  330. package/dist/src/models/addresses/Street.js +26 -0
  331. package/dist/src/models/addresses/Street.js.map +1 -0
  332. package/dist/src/models/index.d.ts +37 -0
  333. package/dist/src/models/index.d.ts.map +1 -0
  334. package/dist/src/models/index.js +53 -0
  335. package/dist/src/models/index.js.map +1 -0
  336. package/dist/src/structures/OrganizationServerMetaData.d.ts +43 -0
  337. package/dist/src/structures/OrganizationServerMetaData.d.ts.map +1 -0
  338. package/dist/src/structures/OrganizationServerMetaData.js +128 -0
  339. package/dist/src/structures/OrganizationServerMetaData.js.map +1 -0
  340. package/dist/tests/jest.global.setup.d.ts +3 -0
  341. package/dist/tests/jest.global.setup.d.ts.map +1 -0
  342. package/dist/tests/jest.global.setup.js +20 -0
  343. package/dist/tests/jest.global.setup.js.map +1 -0
  344. package/dist/tests/jest.setup.d.ts +2 -0
  345. package/dist/tests/jest.setup.d.ts.map +1 -0
  346. package/dist/tests/jest.setup.js +15 -0
  347. package/dist/tests/jest.setup.js.map +1 -0
  348. package/package.json +30 -0
  349. package/src/assets/Metropolis-Black.woff2 +0 -0
  350. package/src/assets/Metropolis-BlackItalic.woff2 +0 -0
  351. package/src/assets/Metropolis-Bold.woff2 +0 -0
  352. package/src/assets/Metropolis-BoldItalic.woff2 +0 -0
  353. package/src/assets/Metropolis-ExtraBold.woff2 +0 -0
  354. package/src/assets/Metropolis-ExtraBoldItalic.woff2 +0 -0
  355. package/src/assets/Metropolis-ExtraLight.woff2 +0 -0
  356. package/src/assets/Metropolis-ExtraLightItalic.woff2 +0 -0
  357. package/src/assets/Metropolis-Light.woff2 +0 -0
  358. package/src/assets/Metropolis-LightItalic.woff2 +0 -0
  359. package/src/assets/Metropolis-Medium.woff2 +0 -0
  360. package/src/assets/Metropolis-MediumItalic.woff2 +0 -0
  361. package/src/assets/Metropolis-Regular.woff2 +0 -0
  362. package/src/assets/Metropolis-RegularItalic.woff2 +0 -0
  363. package/src/assets/Metropolis-SemiBold.woff2 +0 -0
  364. package/src/assets/Metropolis-SemiBoldItalic.woff2 +0 -0
  365. package/src/assets/Metropolis-Thin.woff2 +0 -0
  366. package/src/assets/Metropolis-ThinItalic.woff2 +0 -0
  367. package/src/assets/logo.png +0 -0
  368. package/src/factories/AddressFactory.ts +42 -0
  369. package/src/factories/EmergencyContactFactory.ts +43 -0
  370. package/src/factories/GroupFactory.ts +66 -0
  371. package/src/factories/MemberFactory.ts +122 -0
  372. package/src/factories/OrganizationFactory.ts +45 -0
  373. package/src/factories/ParentFactory.ts +49 -0
  374. package/src/factories/RecordFactory.ts +12 -0
  375. package/src/factories/RegisterCodeFactory.ts +25 -0
  376. package/src/factories/RegistrationFactory.ts +32 -0
  377. package/src/factories/UserFactory.ts +66 -0
  378. package/src/factories/WebshopFactory.ts +43 -0
  379. package/src/helpers/DNSValidator.ts +153 -0
  380. package/src/helpers/EmailBuilder.ts +127 -0
  381. package/src/helpers/GroupBuilder.ts +438 -0
  382. package/src/helpers/Handlebars.ts +203 -0
  383. package/src/helpers/InvoiceBuilder.test.ts +57 -0
  384. package/src/helpers/InvoiceBuilder.ts +501 -0
  385. package/src/helpers/RateLimiter.ts +75 -0
  386. package/src/helpers/WebshopCounter.test.ts +16 -0
  387. package/src/helpers/WebshopCounter.ts +36 -0
  388. package/src/index.ts +21 -0
  389. package/src/migrations/1593773929-create-initial-tables.sql +634 -0
  390. package/src/migrations/1605261999-gemeenten-tmp.sql +2820 -0
  391. package/src/migrations/1605262045-import-postcodes.ts +132 -0
  392. package/src/migrations/1605262046-import-postcodes-nl.ts +97 -0
  393. package/src/migrations/1605279038-drop-gemeenten-tmp.sql +1 -0
  394. package/src/migrations/1648392491-default-templates.sql +9 -0
  395. package/src/migrations/1651245707-default-templates-reminders.sql +6 -0
  396. package/src/migrations/1708607340-tickets-deleted-at.sql +1 -0
  397. package/src/migrations/1710459176-register-code-invoices.sql +3 -0
  398. package/src/migrations/1712158247-discount-codes.sql +17 -0
  399. package/src/migrations/1713178665-drop-invites.sql +1 -0
  400. package/src/migrations/1713178666-drop-keychain.sql +1 -0
  401. package/src/migrations/1713178667-drop-challenges.sql +1 -0
  402. package/src/migrations/1713178668-drop-user-keys.sql +7 -0
  403. package/src/migrations/1713178669-drop-organization-key.sql +2 -0
  404. package/src/migrations/1714985451-user-nullable-organization-id.sql +2 -0
  405. package/src/migrations/1714985452-email-verification-code-nullable-organization-id.sql +2 -0
  406. package/src/migrations/1714985453-user-organization-permissions.sql +2 -0
  407. package/src/migrations/1714985454-user-organization-permissions.sql +2 -0
  408. package/src/migrations/1715079362-platform.sql +6 -0
  409. package/src/migrations/1715181649-registrations-organization-id.sql +2 -0
  410. package/src/migrations/1715181650-registrations-organization-id-fill.sql +1 -0
  411. package/src/migrations/1715181651-registrations-organization-id-drop-null.sql +2 -0
  412. package/src/migrations/1716117067-members-nullable-organization-id.sql +2 -0
  413. package/src/migrations/1719567581-registration-periods.sql +13 -0
  414. package/src/migrations/1719567582-organization-registration-periods.sql +13 -0
  415. package/src/migrations/1719567881-organization-periodId.sql +2 -0
  416. package/src/migrations/1719567882-groups-periodId.sql +2 -0
  417. package/src/migrations/1719567883-platform-periodId.sql +2 -0
  418. package/src/migrations/1719568079-default-period.sql +2 -0
  419. package/src/migrations/1719568080-set-default-period-platform.sql +1 -0
  420. package/src/migrations/1719568081-set-default-period-organizations.sql +1 -0
  421. package/src/migrations/1719568082-set-default-period-groups.sql +1 -0
  422. package/src/migrations/1719580828-registrations-periodId.sql +2 -0
  423. package/src/migrations/1719580829-set-default-period-registrations.sql +1 -0
  424. package/src/migrations/data/postcodes/nl/Drenthe +291 -0
  425. package/src/migrations/data/postcodes/nl/Flevoland +107 -0
  426. package/src/migrations/data/postcodes/nl/Friesland +518 -0
  427. package/src/migrations/data/postcodes/nl/Gelderland +601 -0
  428. package/src/migrations/data/postcodes/nl/Groningen +279 -0
  429. package/src/migrations/data/postcodes/nl/Limburg +324 -0
  430. package/src/migrations/data/postcodes/nl/Noord-Brabant +620 -0
  431. package/src/migrations/data/postcodes/nl/Noord-Holland +566 -0
  432. package/src/migrations/data/postcodes/nl/Overrijsel +344 -0
  433. package/src/migrations/data/postcodes/nl/Utrecht +278 -0
  434. package/src/migrations/data/postcodes/nl/Zeeland +179 -0
  435. package/src/migrations/data/postcodes/nl/Zuid-Holland +662 -0
  436. package/src/models/BalanceItem.ts +392 -0
  437. package/src/models/BalanceItemPayment.ts +106 -0
  438. package/src/models/BuckarooPayment.ts +19 -0
  439. package/src/models/Document.ts +203 -0
  440. package/src/models/DocumentTemplate.ts +583 -0
  441. package/src/models/EmailTemplate.ts +64 -0
  442. package/src/models/EmailVerificationCode.ts +352 -0
  443. package/src/models/Group.ts +293 -0
  444. package/src/models/Image.ts +147 -0
  445. package/src/models/Member.ts +386 -0
  446. package/src/models/MemberResponsibilityRecord.ts +39 -0
  447. package/src/models/MolliePayment.ts +19 -0
  448. package/src/models/MollieToken.ts +369 -0
  449. package/src/models/OneTimeToken.ts +131 -0
  450. package/src/models/Order.ts +1030 -0
  451. package/src/models/Organization.ts +1085 -0
  452. package/src/models/OrganizationRegistrationPeriod.ts +54 -0
  453. package/src/models/PasswordToken.ts +139 -0
  454. package/src/models/PayconiqPayment.ts +241 -0
  455. package/src/models/Payment.ts +216 -0
  456. package/src/models/Platform.ts +76 -0
  457. package/src/models/RegisterCode.ts +164 -0
  458. package/src/models/Registration.ts +405 -0
  459. package/src/models/RegistrationPeriod.ts +55 -0
  460. package/src/models/STCredit.ts +134 -0
  461. package/src/models/STInvoice.ts +507 -0
  462. package/src/models/STPackage.ts +324 -0
  463. package/src/models/STPendingInvoice.ts +308 -0
  464. package/src/models/StripeAccount.ts +71 -0
  465. package/src/models/StripeCheckoutSession.ts +22 -0
  466. package/src/models/StripePaymentIntent.ts +22 -0
  467. package/src/models/Ticket.ts +145 -0
  468. package/src/models/Token.test.ts +69 -0
  469. package/src/models/Token.ts +269 -0
  470. package/src/models/UsedRegisterCode.ts +166 -0
  471. package/src/models/User.ts +445 -0
  472. package/src/models/UserPermissions.ts +54 -0
  473. package/src/models/Webshop.ts +206 -0
  474. package/src/models/WebshopDiscountCode.ts +81 -0
  475. package/src/models/addresses/City.ts +31 -0
  476. package/src/models/addresses/PostalCode.test.ts +117 -0
  477. package/src/models/addresses/PostalCode.ts +164 -0
  478. package/src/models/addresses/Province.ts +20 -0
  479. package/src/models/addresses/Street.ts +25 -0
  480. package/src/models/index.ts +49 -0
  481. package/src/structures/OrganizationServerMetaData.ts +117 -0
@@ -0,0 +1,206 @@
1
+ import { column, Database, ManyToOneRelation, Model } from "@simonbackx/simple-database";
2
+ import { ArrayDecoder } from '@simonbackx/simple-encoding';
3
+ import { Category, DNSRecordStatus, Product, WebshopMetaData, WebshopPrivateMetaData, WebshopServerMetaData } from '@stamhoofd/structures';
4
+ import { v4 as uuidv4 } from "uuid";
5
+ import { validateDNSRecords } from "../helpers/DNSValidator";
6
+
7
+ import { Organization } from './';
8
+
9
+ export class Webshop extends Model {
10
+ static table = "webshops";
11
+
12
+ // Columns
13
+ @column({
14
+ primary: true, type: "string", beforeSave(value) {
15
+ return value ?? uuidv4();
16
+ }
17
+ })
18
+ id!: string;
19
+
20
+ @column({ foreignKey: Webshop.organization, type: "string" })
21
+ organizationId: string;
22
+
23
+ // A custom domain name that is used to host the webshop application (should be unique)
24
+ // E.g. webshop.scoutswetteren.be
25
+ @column({ type: "string", nullable: true })
26
+ domain: string | null = null;
27
+
28
+ // If a domain is used, the optional suffix on that domain
29
+ // E.g. webshop.scoutswetteren.be/wafelbak
30
+ @column({ type: "string", nullable: true })
31
+ domainUri: string | null = null;
32
+
33
+ // Unique representation of this webshop from a string, that is used to provide the default domains
34
+ // in shop.stamhoofd.be/uri, and stamhoofd.be/shop/uri
35
+ @column({ type: "string" })
36
+ uri: string;
37
+
38
+ // Old uri format, which was only unique on a per-organization basis
39
+ // in org.stamhoofd.shop/legacyUri
40
+ @column({ type: "string", nullable: true })
41
+ legacyUri: string | null = null;
42
+
43
+ /**
44
+ * Public meta data
45
+ */
46
+ @column({ type: "json", decoder: WebshopMetaData })
47
+ meta: WebshopMetaData = WebshopMetaData.create({})
48
+
49
+ /**
50
+ * Data only accessible by the owners / users with special permissions
51
+ */
52
+ @column({ type: "json", decoder: WebshopPrivateMetaData })
53
+ privateMeta: WebshopPrivateMetaData = WebshopPrivateMetaData.create({})
54
+
55
+ /**
56
+ * Data only accessible by the server
57
+ */
58
+ @column({ type: "json", decoder: WebshopServerMetaData })
59
+ serverMeta: WebshopServerMetaData = WebshopServerMetaData.create({})
60
+
61
+
62
+ /**
63
+ * Contains all the products
64
+ */
65
+ @column({ type: "json", decoder: new ArrayDecoder(Product) })
66
+ products: Product[] = [];
67
+
68
+ /**
69
+ * Contains all the categories in the right order
70
+ */
71
+ @column({ type: "json", decoder: new ArrayDecoder(Category) })
72
+ categories: Category[] = [];
73
+
74
+ @column({
75
+ type: "datetime", beforeSave(old?: any) {
76
+ if (old !== undefined) {
77
+ return old;
78
+ }
79
+ const date = new Date()
80
+ date.setMilliseconds(0)
81
+ return date
82
+ }
83
+ })
84
+ createdAt: Date
85
+
86
+ @column({
87
+ type: "datetime", beforeSave() {
88
+ const date = new Date()
89
+ date.setMilliseconds(0)
90
+ return date
91
+ },
92
+ skipUpdate: true
93
+ })
94
+ updatedAt: Date
95
+
96
+ static organization = new ManyToOneRelation(Organization, "organization");
97
+
98
+ // Methods
99
+ static async getByLegacyURI(organizationId: string, uri: string): Promise<Webshop | undefined> {
100
+ const [rows] = await Database.select(
101
+ `SELECT ${this.getDefaultSelect()} FROM ${this.table} WHERE \`organizationId\` = ? AND \`legacyUri\` = ? LIMIT 1`,
102
+ [organizationId, uri]
103
+ );
104
+
105
+ if (rows.length == 0) {
106
+ return undefined;
107
+ }
108
+
109
+ // Read member + address from first row
110
+ return this.fromRow(rows[0][this.table]);
111
+ }
112
+
113
+ // Methods
114
+ static async getByURI(uri: string): Promise<Webshop | undefined> {
115
+ const [rows] = await Database.select(
116
+ `SELECT ${this.getDefaultSelect()} FROM ${this.table} WHERE \`uri\` = ? LIMIT 1`,
117
+ [uri]
118
+ );
119
+
120
+ if (rows.length == 0) {
121
+ return undefined;
122
+ }
123
+
124
+ // Read member + address from first row
125
+ return this.fromRow(rows[0][this.table]);
126
+ }
127
+
128
+ // Methods
129
+ static async getByDomainOnly(host: string): Promise<Webshop[]> {
130
+ const [rows] = await Database.select(
131
+ `SELECT ${this.getDefaultSelect()} FROM ${this.table} WHERE \`domain\` = ? LIMIT 200`,
132
+ [host]
133
+ );
134
+
135
+ // Read member + address from first row
136
+ return this.fromRows(rows, this.table);
137
+ }
138
+
139
+ // Methods
140
+ static async getByDomain(host: string, uri: string | null): Promise<Webshop | undefined> {
141
+ if (uri === null || uri.length == 0) {
142
+ const [rows] = await Database.select(
143
+ `SELECT ${this.getDefaultSelect()} FROM ${this.table} WHERE \`domain\` = ? AND (\`domainUri\` is null OR \`domainUri\` = "") LIMIT 1`,
144
+ [host]
145
+ );
146
+
147
+ if (rows.length == 0) {
148
+ return undefined;
149
+ }
150
+
151
+ // Read member + address from first row
152
+ return this.fromRow(rows[0][this.table]);
153
+ }
154
+ const [rows] = await Database.select(
155
+ `SELECT ${this.getDefaultSelect()} FROM ${this.table} WHERE \`domain\` = ? AND \`domainUri\` = ? LIMIT 1`,
156
+ [host, uri]
157
+ );
158
+
159
+ if (rows.length == 0) {
160
+ return undefined;
161
+ }
162
+
163
+ // Read member + address from first row
164
+ return this.fromRow(rows[0][this.table]);
165
+ }
166
+
167
+ // Return the location of the webshop
168
+ getHost(this: Webshop & { organization: Organization }) {
169
+ if (this.domain && this.meta.domainActive) {
170
+ if (this.domainUri) {
171
+ return this.domain+"/"+this.domainUri
172
+ }
173
+ return this.domain
174
+ }
175
+
176
+ const domain = STAMHOOFD.domains.webshop[this.organization.address.country] ?? STAMHOOFD.domains.webshop[""];
177
+ return domain+"/"+this.uri
178
+ }
179
+
180
+ async updateDNSRecords(background = false) {
181
+ // Check initial status
182
+ let isValidRecords = true
183
+ for (const record of this.privateMeta.dnsRecords) {
184
+ if (record.status != DNSRecordStatus.Valid) {
185
+ isValidRecords = false
186
+ }
187
+ }
188
+
189
+ let { allValid } = await validateDNSRecords(this.privateMeta.dnsRecords)
190
+
191
+ if (STAMHOOFD.environment === "development" || STAMHOOFD.environment === "staging") {
192
+ allValid = true
193
+ }
194
+
195
+ if (allValid) {
196
+ if (!this.meta.domainActive && background) {
197
+ // TODO: send an email
198
+ // + prevent ping pong emails when the dns is not workign properly
199
+ }
200
+ this.meta.domainActive = true
201
+ } else {
202
+ this.meta.domainActive = false
203
+ }
204
+ await this.save()
205
+ }
206
+ }
@@ -0,0 +1,81 @@
1
+ import { column, Model } from "@simonbackx/simple-database";
2
+ import { ArrayDecoder } from '@simonbackx/simple-encoding';
3
+ import { Discount, DiscountCode } from '@stamhoofd/structures';
4
+ import { v4 as uuidv4 } from "uuid";
5
+
6
+ export class WebshopDiscountCode extends Model {
7
+ static table = "webshop_discount_codes";
8
+
9
+ // Columns
10
+ @column({
11
+ primary: true, type: "string", beforeSave(value) {
12
+ return value ?? uuidv4();
13
+ }
14
+ })
15
+ id!: string;
16
+
17
+ @column({ type: "string" })
18
+ organizationId: string;
19
+
20
+ @column({ type: "string" })
21
+ webshopId: string;
22
+
23
+ @column({ type: "string" })
24
+ code: string;
25
+
26
+ @column({ type: "string" })
27
+ description = ''
28
+
29
+ @column({ type: "json", decoder: new ArrayDecoder(Discount) })
30
+ discounts: Discount[] = []
31
+
32
+ @column({ type: "integer" })
33
+ usageCount = 0
34
+
35
+ @column({ type: "integer", nullable: true })
36
+ maximumUsage: number|null = null
37
+
38
+ @column({
39
+ type: "datetime", beforeSave(old?: any) {
40
+ if (old !== undefined) {
41
+ return old;
42
+ }
43
+ const date = new Date()
44
+ date.setMilliseconds(0)
45
+ return date
46
+ }
47
+ })
48
+ createdAt: Date
49
+
50
+ @column({
51
+ type: "datetime", beforeSave() {
52
+ const date = new Date()
53
+ date.setMilliseconds(0)
54
+ return date
55
+ },
56
+ skipUpdate: true
57
+ })
58
+ updatedAt: Date
59
+
60
+ getStructure(): DiscountCode {
61
+ return DiscountCode.create(this)
62
+ }
63
+
64
+ static async getActiveCodes(webshopId: string, codes: string[]) {
65
+ if (codes.length === 0) {
66
+ return [];
67
+ }
68
+
69
+ let models = await WebshopDiscountCode.where({
70
+ webshopId,
71
+ code: {
72
+ sign: 'IN',
73
+ value: codes
74
+ }
75
+ });
76
+
77
+ // Remove used discount codes
78
+ models = models.filter(c => c.maximumUsage === null || c.maximumUsage > c.usageCount)
79
+ return models;
80
+ }
81
+ }
@@ -0,0 +1,31 @@
1
+ import { column,ManyToOneRelation,Model } from '@simonbackx/simple-database';
2
+ import { Country } from '@stamhoofd/structures';
3
+ import { v4 as uuidv4 } from "uuid";
4
+
5
+ import { Province } from './Province';
6
+
7
+ export class City extends Model {
8
+ static table = "cities"
9
+
10
+ @column({
11
+ primary: true, type: "string", beforeSave(value) {
12
+ return value ?? uuidv4();
13
+ }
14
+ })
15
+ id!: string;
16
+
17
+ @column({ type: "string" })
18
+ name: string;
19
+
20
+ @column({ type: "string", foreignKey: City.province })
21
+ provinceId: string;
22
+
23
+ @column({ type: "string", foreignKey: City.parentCity, nullable: true })
24
+ parentCityId: string | null = null;
25
+
26
+ @column({ type: "string" })
27
+ country: Country;
28
+
29
+ static parentCity = new ManyToOneRelation(City, "parentCity")
30
+ static province = new ManyToOneRelation(Province, "province")
31
+ }
@@ -0,0 +1,117 @@
1
+ import { Country } from "@stamhoofd/structures";
2
+
3
+ import { City } from "./City";
4
+ import { PostalCode } from './PostalCode';
5
+ import { Province } from './Province';
6
+
7
+
8
+ describe("Model.PostalCode", () => {
9
+ let oostVlaanderen!: Province;
10
+ let gent!: City;
11
+ let mariakerke!: City;
12
+
13
+ let wetteren!: City;
14
+ let massemen!: City;
15
+
16
+ let gentZip!: PostalCode;
17
+ let mariakerkeZip!: PostalCode;
18
+
19
+ let wetterenZip!: PostalCode;
20
+ let massemenZip!: PostalCode;
21
+
22
+ beforeAll(async () => {
23
+ oostVlaanderen = new Province()
24
+ oostVlaanderen.name = "Oost-Vlaanderen"
25
+ oostVlaanderen.country = Country.Belgium
26
+ await oostVlaanderen.save()
27
+
28
+ // Create some cities
29
+ gent = new City()
30
+ gent.name = "Gent"
31
+ gent.provinceId = oostVlaanderen.id
32
+ gent.country = Country.Belgium
33
+ await gent.save()
34
+
35
+ // Create some cities
36
+ mariakerke = new City()
37
+ mariakerke.name = "Mariakerke"
38
+ mariakerke.provinceId = oostVlaanderen.id
39
+ mariakerke.parentCityId = gent.id
40
+ mariakerke.country = Country.Belgium
41
+ await mariakerke.save()
42
+
43
+ // Create some cities
44
+ wetteren = new City()
45
+ wetteren.name = "Wetteren"
46
+ wetteren.provinceId = oostVlaanderen.id
47
+ wetteren.country = Country.Belgium
48
+ await wetteren.save()
49
+
50
+ // Create some cities
51
+ massemen = new City()
52
+ massemen.name = "Massemen"
53
+ massemen.provinceId = oostVlaanderen.id
54
+ massemen.parentCityId = wetteren.id
55
+ massemen.country = Country.Belgium
56
+ await massemen.save()
57
+
58
+ // Create postal codes
59
+ gentZip = new PostalCode()
60
+ gentZip.postalCode = "9000"
61
+ gentZip.cityId = gent.id
62
+ gentZip.country = Country.Belgium
63
+ await gentZip.save()
64
+
65
+ // Create postal codes
66
+ mariakerkeZip = new PostalCode()
67
+ mariakerkeZip.postalCode = "9030"
68
+ mariakerkeZip.cityId = mariakerke.id
69
+ mariakerkeZip.country = Country.Belgium
70
+ await mariakerkeZip.save()
71
+
72
+ // Create postal codes
73
+ wetterenZip = new PostalCode()
74
+ wetterenZip.postalCode = "9230"
75
+ wetterenZip.cityId = wetteren.id
76
+ wetterenZip.country = Country.Belgium
77
+ await wetterenZip.save()
78
+
79
+ // Create postal codes
80
+ massemenZip = new PostalCode()
81
+ massemenZip.postalCode = "9230"
82
+ massemenZip.cityId = massemen.id
83
+ massemenZip.country = Country.Belgium
84
+ await massemenZip.save()
85
+ });
86
+
87
+ test("Normal flow", async () => {
88
+ const test = await PostalCode.getCity("9000", "Gent", Country.Belgium);
89
+ expect(test).toMatchObject(gent)
90
+ });
91
+
92
+ test("Entering the postal code of the parent city works", async () => {
93
+ const test = await PostalCode.getCity("9000", "Mariakerke", Country.Belgium);
94
+ expect(test).toMatchObject(gent)
95
+ });
96
+
97
+ test("Entering the postal code of a child city works", async () => {
98
+ const test = await PostalCode.getCity("9030", "Gent", Country.Belgium);
99
+ expect(test).toMatchObject(mariakerke)
100
+ });
101
+
102
+ test("Search normal", async () => {
103
+ const test = await PostalCode.getCity("9230", "Wetteren", Country.Belgium);
104
+ expect(test).toMatchObject(wetteren)
105
+
106
+ const test2 = await PostalCode.getCity("9230", "Massemen", Country.Belgium);
107
+ expect(test2).toMatchObject(massemen)
108
+ });
109
+
110
+ test("Allow typo", async () => {
111
+ const test = await PostalCode.getCity("9230", "Wettern", Country.Belgium);
112
+ expect(test).toMatchObject(wetteren)
113
+
114
+ const test2 = await PostalCode.getCity("9230", "Masemen", Country.Belgium);
115
+ expect(test2).toMatchObject(massemen)
116
+ });
117
+ });
@@ -0,0 +1,164 @@
1
+ import { column,Database,ManyToOneRelation,Model } from '@simonbackx/simple-database';
2
+ import { SimpleError } from '@simonbackx/simple-errors';
3
+ import { Country } from '@stamhoofd/structures';
4
+ import { Formatter, StringCompare } from '@stamhoofd/utility';
5
+ import { v4 as uuidv4 } from "uuid";
6
+
7
+ import { City } from './City';
8
+
9
+ export class PostalCode extends Model {
10
+ static table = "postal_codes"
11
+
12
+ @column({
13
+ primary: true, type: "string", beforeSave(value) {
14
+ return value ?? uuidv4();
15
+ }
16
+ })
17
+ id!: string;
18
+
19
+ @column({ type: "string" })
20
+ postalCode: string;
21
+
22
+ @column({ type: "string", foreignKey: PostalCode.city })
23
+ cityId: string;
24
+
25
+ @column({ type: "string" })
26
+ country: Country;
27
+
28
+ static city = new ManyToOneRelation(City, "city")
29
+
30
+ /**
31
+ * Search for a given city via it's postal code and country, collecting information about the city (id), parentCity (id) and province (id)
32
+ */
33
+ static async getCity(postalCode: string, cityName: string, country: Country): Promise<City | null> {
34
+ let query = `SELECT ${City.getDefaultSelect()}from \`${PostalCode.table}\`\n`;
35
+ query += `JOIN \`${City.table}\` ON \`${PostalCode.table}\`.\`${PostalCode.city.foreignKey}\` = \`${City.table}\`.\`${City.primary.name}\`\n`
36
+
37
+ // We do an extra join because we also need to get the other registrations of each member (only one regitration has to match the query)
38
+ query += `where \`${PostalCode.table}\`.\`postalCode\` = ? AND \`${PostalCode.table}\`.\`country\` = ?`
39
+
40
+ const [results] = await Database.select(query, [postalCode, country])
41
+
42
+ const cities = City.fromRows(results, City.table)
43
+
44
+ if (cities.length == 1) {
45
+ return cities[0]
46
+ }
47
+
48
+ // Search by city name (first exact match, then allow errors)
49
+ let bestScore = 0
50
+ let bestCity: City | null = null
51
+
52
+ for (const city of cities) {
53
+ const typo = StringCompare.typoCount(cityName, city.name)
54
+ if (typo == 0) {
55
+ return city
56
+ }
57
+
58
+ if (bestCity === null || typo < bestScore) {
59
+ bestCity = city
60
+ bestScore = typo
61
+ }
62
+ }
63
+
64
+ if (bestCity && (bestScore < 3 || StringCompare.contains(cityName, bestCity.name) || StringCompare.contains(bestCity.name, cityName))) {
65
+ return bestCity
66
+ }
67
+
68
+ bestScore = 0
69
+ bestCity = null
70
+
71
+ for (const city of cities) {
72
+ const match = StringCompare.matchCount(cityName, city.name)
73
+
74
+ if (bestCity === null || match > bestScore) {
75
+ bestCity = city
76
+ bestScore = match
77
+ }
78
+ }
79
+
80
+ if (bestCity && (bestScore > cityName.length/2 || StringCompare.contains(cityName, bestCity.name))) {
81
+ return bestCity
82
+ }
83
+
84
+ if (cities.length >= 1 && cities[0].parentCityId !== null && cities.every(c => c.parentCityId === cities[0].parentCityId)) {
85
+ // Might have put a postal code of the parent city
86
+ const parent = await City.getByID(cities[0].parentCityId)
87
+ if (parent) {
88
+ const typo = StringCompare.typoCount(cityName, parent.name)
89
+ if (typo < 4 || StringCompare.contains(cityName, parent.name)) {
90
+ if (cities.length > 1) {
91
+ throw new SimpleError({
92
+ code: "invalid_field",
93
+ message: "Invalid city. Suggestions: " + Formatter.joinLast(cities.map(c => c.name), ", ", " of ") + "?",
94
+ human: "Welke gemeente bedoel je precies? " + Formatter.joinLast(cities.map(c => c.name), ", ", " of ") + "?",
95
+ field: "city"
96
+ })
97
+ }
98
+ return cities[0] // do not return parent here, because the postal code has priority
99
+ }
100
+ }
101
+ }
102
+
103
+ // Search parent in belgium only
104
+ if (country == Country.Belgium) {
105
+ return this.getCityByParent(postalCode, cityName, country)
106
+ }
107
+
108
+ return null;
109
+ }
110
+
111
+ /**
112
+ * Search for a given city via it's postal code and country, collecting information about the city (id), parentCity (id) and province (id)
113
+ */
114
+ static async getCityByParent(postalCode: string, cityName: string, country: Country): Promise<City | null> {
115
+ let query = `SELECT ${City.getDefaultSelect()}from \`${PostalCode.table}\`\n`;
116
+ query += `JOIN \`${City.table}\` as parent ON \`${PostalCode.table}\`.\`${PostalCode.city.foreignKey}\` = \`parent\`.\`${City.primary.name}\`\n`
117
+ query += `JOIN \`${City.table}\` ON \`parent\`.\`${City.primary.name}\` = \`${City.table}\`.\`${City.parentCity.foreignKey}\`\n`
118
+
119
+ // We do an extra join because we also need to get the other registrations of each member (only one regitration has to match the query)
120
+ query += `where \`${PostalCode.table}\`.\`postalCode\` = ? AND \`${PostalCode.table}\`.\`country\` = ?`
121
+
122
+ const [results] = await Database.select(query, [postalCode, country])
123
+
124
+ const cities = City.fromRows(results, City.table)
125
+
126
+ // Search by city name (first exact match, then allow errors)
127
+ let bestScore = 0
128
+ let bestCity: City | null = null
129
+
130
+ for (const city of cities) {
131
+ const typo = StringCompare.typoCount(cityName, city.name)
132
+ if (typo == 0) {
133
+ return city
134
+ }
135
+
136
+ if (bestCity === null || typo < bestScore) {
137
+ bestCity = city
138
+ bestScore = typo
139
+ }
140
+ }
141
+
142
+ if (bestCity && (bestScore < 3 || StringCompare.contains(cityName, bestCity.name) || StringCompare.contains(bestCity.name, cityName))) {
143
+ return bestCity
144
+ }
145
+
146
+ bestScore = 0
147
+ bestCity = null
148
+
149
+ for (const city of cities) {
150
+ const match = StringCompare.matchCount(cityName, city.name)
151
+
152
+ if (bestCity === null || match > bestScore) {
153
+ bestCity = city
154
+ bestScore = match
155
+ }
156
+ }
157
+
158
+ if (bestCity && (bestScore > cityName.length/2 || StringCompare.contains(cityName, bestCity.name))) {
159
+ return bestCity
160
+ }
161
+
162
+ return null;
163
+ }
164
+ }
@@ -0,0 +1,20 @@
1
+ import { column,Model } from '@simonbackx/simple-database';
2
+ import { Country } from '@stamhoofd/structures';
3
+ import { v4 as uuidv4 } from "uuid";
4
+
5
+ export class Province extends Model {
6
+ static table = "provinces"
7
+
8
+ @column({
9
+ primary: true, type: "string", beforeSave(value) {
10
+ return value ?? uuidv4();
11
+ }
12
+ })
13
+ id!: string;
14
+
15
+ @column({ type: "string" })
16
+ name: string;
17
+
18
+ @column({ type: "string" })
19
+ country: Country;
20
+ }
@@ -0,0 +1,25 @@
1
+ import { column, ManyToOneRelation, Model } from '@simonbackx/simple-database';
2
+ import { v4 as uuidv4 } from "uuid";
3
+
4
+ import { City } from './City';
5
+
6
+ export class Street extends Model {
7
+ static table = "streets"
8
+
9
+ @column({
10
+ primary: true, type: "string", beforeSave(value) {
11
+ return value ?? uuidv4();
12
+ }
13
+ })
14
+ id!: string;
15
+
16
+ @column({ type: "string" })
17
+ name: string;
18
+
19
+ @column({ type: "string", foreignKey: Street.city })
20
+ cityId: string;
21
+
22
+ static city = new ManyToOneRelation(City, "city")
23
+
24
+
25
+ }
@@ -0,0 +1,49 @@
1
+ /* eslint-disable simple-import-sort/exports */
2
+ export {Organization} from "./Organization"
3
+ export {User} from "./User"
4
+ export {Payment} from "./Payment"
5
+ export {Registration} from "./Registration"
6
+ export {Member, RegistrationWithMember, MemberWithRegistrations} from "./Member"
7
+
8
+ export * from "./EmailVerificationCode"
9
+
10
+ export * from "./Image"
11
+ export * from "./MolliePayment"
12
+ export * from "./MollieToken"
13
+ export {Order} from "./Order"
14
+ export * from "./PasswordToken"
15
+ export * from "./PayconiqPayment"
16
+ export * from "./RegisterCode"
17
+ export * from "./STInvoice"
18
+ export * from "./STPackage"
19
+ export {STPendingInvoice} from "./STPendingInvoice"
20
+ export {Token, TokenWithUser} from "./Token"
21
+ export * from "./Webshop"
22
+ export * from "./STCredit"
23
+ export * from "./UsedRegisterCode"
24
+ export * from "./Ticket"
25
+ export * from "./EmailTemplate"
26
+ export * from "./BuckarooPayment"
27
+ export {BalanceItem} from "./BalanceItem"
28
+ export {BalanceItemPayment} from "./BalanceItemPayment"
29
+ export {Group} from "./Group"
30
+
31
+ export * from "./addresses/Street"
32
+ export * from "./addresses/City"
33
+ export * from "./addresses/PostalCode"
34
+ export * from "./addresses/Province"
35
+
36
+ export * from "./StripeAccount"
37
+ export * from "./StripePaymentIntent"
38
+ export * from "./StripeCheckoutSession"
39
+
40
+ export * from "./Document"
41
+ export * from "./DocumentTemplate"
42
+
43
+ export * from "./WebshopDiscountCode"
44
+
45
+ export * from "./Platform"
46
+ export * from "./MemberResponsibilityRecord"
47
+
48
+ export * from "./OrganizationRegistrationPeriod"
49
+ export * from "./RegistrationPeriod"