@stamhoofd/models 2.1.1 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +661 -0
  2. package/dist/src/factories/GroupFactory.d.ts.map +1 -1
  3. package/dist/src/factories/GroupFactory.js +1 -0
  4. package/dist/src/factories/GroupFactory.js.map +1 -1
  5. package/dist/src/factories/MemberFactory.d.ts.map +1 -1
  6. package/dist/src/factories/MemberFactory.js +0 -2
  7. package/dist/src/factories/MemberFactory.js.map +1 -1
  8. package/dist/src/factories/RegistrationFactory.d.ts.map +1 -1
  9. package/dist/src/factories/RegistrationFactory.js +2 -0
  10. package/dist/src/factories/RegistrationFactory.js.map +1 -1
  11. package/dist/src/factories/UserFactory.d.ts +1 -0
  12. package/dist/src/factories/UserFactory.d.ts.map +1 -1
  13. package/dist/src/factories/UserFactory.js +14 -4
  14. package/dist/src/factories/UserFactory.js.map +1 -1
  15. package/dist/src/helpers/GroupBuilder.d.ts.map +1 -1
  16. package/dist/src/helpers/GroupBuilder.js +25 -2
  17. package/dist/src/helpers/GroupBuilder.js.map +1 -1
  18. package/dist/src/migrations/1605262046-import-postcodes-nl.js +1 -1
  19. package/dist/src/migrations/1605262046-import-postcodes-nl.js.map +1 -1
  20. package/dist/src/migrations/1714985451-user-nullable-organization-id.sql +2 -0
  21. package/dist/src/migrations/1714985452-email-verification-code-nullable-organization-id.sql +2 -0
  22. package/dist/src/migrations/1714985453-user-organization-permissions.sql +2 -0
  23. package/dist/src/migrations/1714985454-user-organization-permissions.sql +2 -0
  24. package/dist/src/migrations/1715079362-platform.sql +6 -0
  25. package/dist/src/migrations/1715181649-registrations-organization-id.sql +2 -0
  26. package/dist/src/migrations/1715181650-registrations-organization-id-fill.sql +1 -0
  27. package/dist/src/migrations/1715181651-registrations-organization-id-drop-null.sql +2 -0
  28. package/dist/src/migrations/1716117067-members-nullable-organization-id.sql +2 -0
  29. package/dist/src/migrations/1719567581-registration-periods.sql +13 -0
  30. package/dist/src/migrations/1719567582-organization-registration-periods.sql +13 -0
  31. package/dist/src/migrations/1719567881-organization-periodId.sql +2 -0
  32. package/dist/src/migrations/1719567882-groups-periodId.sql +2 -0
  33. package/dist/src/migrations/1719567883-platform-periodId.sql +2 -0
  34. package/dist/src/migrations/1719568079-default-period.sql +2 -0
  35. package/dist/src/migrations/1719568080-set-default-period-platform.sql +1 -0
  36. package/dist/src/migrations/1719568081-set-default-period-organizations.sql +1 -0
  37. package/dist/src/migrations/1719568082-set-default-period-groups.sql +1 -0
  38. package/dist/src/migrations/1719580828-registrations-periodId.sql +2 -0
  39. package/dist/src/migrations/1719580829-set-default-period-registrations.sql +1 -0
  40. package/dist/src/migrations/1719931362-groups-default-age-group-id.sql +2 -0
  41. package/dist/src/migrations/1720080975-convert-charset.sql +87 -0
  42. package/dist/src/migrations/1720080976-responsibilities.sql +14 -0
  43. package/dist/src/migrations/1720088136-member-membership-types.sql +23 -0
  44. package/dist/src/migrations/1720088137-member-membership-types-expire-date.sql +2 -0
  45. package/dist/src/migrations/1720444931-organization-active.sql +2 -0
  46. package/dist/src/models/BalanceItem.d.ts +1 -1
  47. package/dist/src/models/BalanceItem.d.ts.map +1 -1
  48. package/dist/src/models/BalanceItem.js +15 -5
  49. package/dist/src/models/BalanceItem.js.map +1 -1
  50. package/dist/src/models/Document.d.ts.map +1 -1
  51. package/dist/src/models/Document.js +6 -2
  52. package/dist/src/models/Document.js.map +1 -1
  53. package/dist/src/models/DocumentTemplate.d.ts +3 -3
  54. package/dist/src/models/DocumentTemplate.d.ts.map +1 -1
  55. package/dist/src/models/DocumentTemplate.js +23 -24
  56. package/dist/src/models/DocumentTemplate.js.map +1 -1
  57. package/dist/src/models/EmailVerificationCode.d.ts +6 -7
  58. package/dist/src/models/EmailVerificationCode.d.ts.map +1 -1
  59. package/dist/src/models/EmailVerificationCode.js +37 -30
  60. package/dist/src/models/EmailVerificationCode.js.map +1 -1
  61. package/dist/src/models/Group.d.ts +6 -4
  62. package/dist/src/models/Group.d.ts.map +1 -1
  63. package/dist/src/models/Group.js +28 -9
  64. package/dist/src/models/Group.js.map +1 -1
  65. package/dist/src/models/Member.d.ts +10 -9
  66. package/dist/src/models/Member.d.ts.map +1 -1
  67. package/dist/src/models/Member.js +99 -15
  68. package/dist/src/models/Member.js.map +1 -1
  69. package/dist/src/models/MemberPlatformMembership.d.ts +19 -0
  70. package/dist/src/models/MemberPlatformMembership.d.ts.map +1 -0
  71. package/dist/src/models/MemberPlatformMembership.js +123 -0
  72. package/dist/src/models/MemberPlatformMembership.js.map +1 -0
  73. package/dist/src/models/Organization.d.ts +8 -6
  74. package/dist/src/models/Organization.d.ts.map +1 -1
  75. package/dist/src/models/Organization.js +38 -59
  76. package/dist/src/models/Organization.js.map +1 -1
  77. package/dist/src/models/OrganizationRegistrationPeriod.d.ts +3 -0
  78. package/dist/src/models/OrganizationRegistrationPeriod.d.ts.map +1 -1
  79. package/dist/src/models/OrganizationRegistrationPeriod.js +49 -0
  80. package/dist/src/models/OrganizationRegistrationPeriod.js.map +1 -1
  81. package/dist/src/models/PasswordToken.d.ts +1 -1
  82. package/dist/src/models/PasswordToken.d.ts.map +1 -1
  83. package/dist/src/models/PasswordToken.js +9 -10
  84. package/dist/src/models/PasswordToken.js.map +1 -1
  85. package/dist/src/models/Payment.d.ts +5 -3
  86. package/dist/src/models/Payment.d.ts.map +1 -1
  87. package/dist/src/models/Payment.js +13 -5
  88. package/dist/src/models/Payment.js.map +1 -1
  89. package/dist/src/models/Platform.d.ts +1 -0
  90. package/dist/src/models/Platform.d.ts.map +1 -1
  91. package/dist/src/models/Platform.js +3 -0
  92. package/dist/src/models/Platform.js.map +1 -1
  93. package/dist/src/models/Registration.d.ts +7 -2
  94. package/dist/src/models/Registration.d.ts.map +1 -1
  95. package/dist/src/models/Registration.js +11 -0
  96. package/dist/src/models/Registration.js.map +1 -1
  97. package/dist/src/models/STInvoice.d.ts.map +1 -1
  98. package/dist/src/models/STInvoice.js +1 -0
  99. package/dist/src/models/STInvoice.js.map +1 -1
  100. package/dist/src/models/Token.d.ts.map +1 -1
  101. package/dist/src/models/Token.js +1 -0
  102. package/dist/src/models/Token.js.map +1 -1
  103. package/dist/src/models/User.d.ts +20 -11
  104. package/dist/src/models/User.d.ts.map +1 -1
  105. package/dist/src/models/User.js +84 -26
  106. package/dist/src/models/User.js.map +1 -1
  107. package/dist/src/models/index.d.ts +5 -0
  108. package/dist/src/models/index.d.ts.map +1 -1
  109. package/dist/src/models/index.js +5 -0
  110. package/dist/src/models/index.js.map +1 -1
  111. package/package.json +3 -2
  112. package/src/migrations/1719931362-groups-default-age-group-id.sql +2 -0
  113. package/src/migrations/1720080975-convert-charset.sql +87 -0
  114. package/src/migrations/1720080976-responsibilities.sql +14 -0
  115. package/src/migrations/1720088136-member-membership-types.sql +23 -0
  116. package/src/migrations/1720088137-member-membership-types-expire-date.sql +2 -0
  117. package/src/migrations/1720444931-organization-active.sql +2 -0
  118. package/src/models/Group.ts +3 -0
  119. package/src/models/Member.ts +86 -2
  120. package/src/models/MemberPlatformMembership.ts +122 -0
  121. package/src/models/Organization.ts +4 -61
  122. package/src/models/OrganizationRegistrationPeriod.ts +60 -0
  123. package/src/models/Payment.ts +4 -4
  124. package/src/models/Platform.ts +4 -0
  125. package/src/models/Registration.ts +6 -0
  126. package/src/models/STInvoice.ts +2 -0
  127. package/src/models/index.ts +1 -0
@@ -0,0 +1,87 @@
1
+ set foreign_key_checks=0;
2
+ ALTER TABLE `_members_users` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
3
+ ALTER TABLE `_members_users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
4
+ ALTER TABLE `balance_item_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
5
+ ALTER TABLE `balance_item_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
6
+ ALTER TABLE `balance_items` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
7
+ ALTER TABLE `balance_items` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
8
+ ALTER TABLE `buckaroo_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
9
+ ALTER TABLE `buckaroo_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
10
+ ALTER TABLE `cities` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
11
+ ALTER TABLE `cities` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
12
+ ALTER TABLE `document_templates` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
13
+ ALTER TABLE `document_templates` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
14
+ ALTER TABLE `documents` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
15
+ ALTER TABLE `documents` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
16
+ ALTER TABLE `email_addresses` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
17
+ ALTER TABLE `email_addresses` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
18
+ ALTER TABLE `email_templates` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
19
+ ALTER TABLE `email_templates` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
20
+ ALTER TABLE `email_verification_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
21
+ ALTER TABLE `email_verification_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
22
+ ALTER TABLE `groups` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
23
+ ALTER TABLE `groups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
24
+ ALTER TABLE `images` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
25
+ ALTER TABLE `images` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
26
+ ALTER TABLE `members` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
27
+ ALTER TABLE `members` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
28
+ ALTER TABLE `migrations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
29
+ ALTER TABLE `migrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
30
+ ALTER TABLE `mollie_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
31
+ ALTER TABLE `mollie_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
32
+ ALTER TABLE `mollie_tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
33
+ ALTER TABLE `mollie_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
34
+ ALTER TABLE `organization_registration_periods` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
35
+ ALTER TABLE `organization_registration_periods` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
36
+ ALTER TABLE `organizations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
37
+ ALTER TABLE `organizations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
38
+ ALTER TABLE `password_tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
39
+ ALTER TABLE `password_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
40
+ ALTER TABLE `payconiq_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
41
+ ALTER TABLE `payconiq_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
42
+ ALTER TABLE `payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
43
+ ALTER TABLE `payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
44
+ ALTER TABLE `platform` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
45
+ ALTER TABLE `platform` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
46
+ ALTER TABLE `postal_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
47
+ ALTER TABLE `postal_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
48
+ ALTER TABLE `provinces` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
49
+ ALTER TABLE `provinces` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
50
+ ALTER TABLE `register_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
51
+ ALTER TABLE `register_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
52
+ ALTER TABLE `registration_periods` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
53
+ ALTER TABLE `registration_periods` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
54
+ ALTER TABLE `registrations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
55
+ ALTER TABLE `registrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
56
+ ALTER TABLE `stamhoofd_credits` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
57
+ ALTER TABLE `stamhoofd_credits` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
58
+ ALTER TABLE `stamhoofd_invoices` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
59
+ ALTER TABLE `stamhoofd_invoices` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
60
+ ALTER TABLE `stamhoofd_packages` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
61
+ ALTER TABLE `stamhoofd_packages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
62
+ ALTER TABLE `stamhoofd_pending_invoices` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
63
+ ALTER TABLE `stamhoofd_pending_invoices` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
64
+ ALTER TABLE `streets` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
65
+ ALTER TABLE `streets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
66
+ ALTER TABLE `stripe_accounts` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
67
+ ALTER TABLE `stripe_accounts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
68
+ ALTER TABLE `stripe_checkout_sessions` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
69
+ ALTER TABLE `stripe_checkout_sessions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
70
+ ALTER TABLE `stripe_payment_intents` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
71
+ ALTER TABLE `stripe_payment_intents` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
72
+ ALTER TABLE `tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
73
+ ALTER TABLE `tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
74
+ ALTER TABLE `used_register_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
75
+ ALTER TABLE `used_register_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
76
+ ALTER TABLE `users` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
77
+ ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
78
+ ALTER TABLE `webshop_discount_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
79
+ ALTER TABLE `webshop_discount_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
80
+ ALTER TABLE `webshop_orders` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
81
+ ALTER TABLE `webshop_orders` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
82
+ ALTER TABLE `webshop_tickets` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
83
+ ALTER TABLE `webshop_tickets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
84
+ ALTER TABLE `webshops` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
85
+ ALTER TABLE `webshops` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
86
+ ALTER DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
87
+ set foreign_key_checks=1;
@@ -0,0 +1,14 @@
1
+ CREATE TABLE `member_responsibility_records` (
2
+ `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '',
3
+ `memberId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
4
+ `organizationId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
5
+ `responsibilityId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
6
+ `startDate` datetime NOT NULL,
7
+ `endDate` datetime DEFAULT NULL,
8
+ PRIMARY KEY (`id`),
9
+ KEY `responsibilityId` (`responsibilityId`) USING BTREE,
10
+ KEY `memberId,organizationId` (`memberId`,`organizationId`) USING BTREE,
11
+ KEY `organizationId` (`organizationId`),
12
+ CONSTRAINT `member_responsibility_records_ibfk_1` FOREIGN KEY (`memberId`) REFERENCES `members` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
13
+ CONSTRAINT `member_responsibility_records_ibfk_2` FOREIGN KEY (`organizationId`) REFERENCES `organizations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
14
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
@@ -0,0 +1,23 @@
1
+ CREATE TABLE `member_platform_memberships` (
2
+ `id` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL DEFAULT '',
3
+ `memberId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
4
+ `membershipTypeId` varchar(36) NOT NULL,
5
+ `organizationId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
6
+ `periodId` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
7
+ `startDate` datetime NOT NULL,
8
+ `endDate` datetime NOT NULL,
9
+ `invoiceItemDetailId` varchar(36) DEFAULT '',
10
+ `invoiceId` varchar(36) DEFAULT '',
11
+ `price` int NOT NULL DEFAULT '0',
12
+ `createdAt` datetime NOT NULL,
13
+ `updatedAt` datetime NOT NULL,
14
+ PRIMARY KEY (`id`),
15
+ KEY `memberId` (`memberId`),
16
+ KEY `organizationId` (`organizationId`),
17
+ KEY `periodId` (`periodId`),
18
+ KEY `invoiceId` (`invoiceId`),
19
+ CONSTRAINT `member_platform_memberships_ibfk_1` FOREIGN KEY (`memberId`) REFERENCES `members` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
20
+ CONSTRAINT `member_platform_memberships_ibfk_2` FOREIGN KEY (`organizationId`) REFERENCES `organizations` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
21
+ CONSTRAINT `member_platform_memberships_ibfk_3` FOREIGN KEY (`periodId`) REFERENCES `registration_periods` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
22
+ CONSTRAINT `member_platform_memberships_ibfk_4` FOREIGN KEY (`invoiceId`) REFERENCES `stamhoofd_invoices` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
23
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `member_platform_memberships`
2
+ ADD COLUMN `expireDate` datetime NULL AFTER `endDate`;
@@ -0,0 +1,2 @@
1
+ ALTER TABLE `organizations`
2
+ ADD COLUMN `active` tinyint(1) NOT NULL DEFAULT '1';
@@ -42,6 +42,9 @@ export class Group extends Model {
42
42
  @column({ type: "string" })
43
43
  periodId: string;
44
44
 
45
+ @column({ type: "string", nullable: true })
46
+ defaultAgeGroupId: string | null = null
47
+
45
48
  /**
46
49
  * Every time a new registration period starts, this number increases. This is used to mark all older registrations as 'out of date' automatically
47
50
  */
@@ -1,10 +1,11 @@
1
1
  import { column, Database, ManyToManyRelation, ManyToOneRelation, Model, OneToManyRelation } from '@simonbackx/simple-database';
2
2
  import { SQL } from "@stamhoofd/sql";
3
3
  import { Member as MemberStruct, MemberDetails, MemberWithRegistrationsBlob, RegistrationWithMember as RegistrationWithMemberStruct, User as UserStruct } from '@stamhoofd/structures';
4
- import { Formatter } from '@stamhoofd/utility';
4
+ import { Formatter, Sorter } from '@stamhoofd/utility';
5
5
  import { v4 as uuidv4 } from "uuid";
6
6
 
7
- import { Group, Payment, Registration, User } from './';
7
+ import { Group, MemberPlatformMembership, Payment, Platform, Registration, User } from './';
8
+ import { QueueHandler } from '@stamhoofd/queues';
8
9
  export type MemberWithRegistrations = Member & {
9
10
  users: User[],
10
11
  registrations: (Registration & {group: Group})[]
@@ -383,4 +384,87 @@ export class Member extends Model {
383
384
  member: MemberStruct.create(registration.member),
384
385
  })
385
386
  }
387
+
388
+ async updateMemberships(this: MemberWithRegistrations) {
389
+ console.log('Updating memberships for member: ' + this.id)
390
+ return await QueueHandler.schedule('updateMemberships-' + this.id, async () => {
391
+ const platform = await Platform.getShared()
392
+ const registrations = this.registrations.filter(r => r.group.periodId == platform.periodId && !r.waitingList && r.registeredAt && !r.deactivatedAt)
393
+
394
+ const defaultMemberships = registrations.flatMap(r => {
395
+ if (!r.group.defaultAgeGroupId) {
396
+ return []
397
+ }
398
+ const defaultAgeGroup = platform.config.defaultAgeGroups.find(g => g.id == r.group.defaultAgeGroupId)
399
+ if (!defaultAgeGroup || !defaultAgeGroup.defaultMembershipTypeId) {
400
+ return []
401
+ }
402
+
403
+ const defaultMembership = platform.config.membershipTypes.find(m => m.id == defaultAgeGroup.defaultMembershipTypeId)
404
+ if (!defaultMembership) {
405
+ return []
406
+ }
407
+
408
+ return [{
409
+ registration: r,
410
+ membership: defaultMembership,
411
+ }]
412
+ })
413
+ // Get active memberships for this member
414
+ const memberships = await MemberPlatformMembership.where({memberId: this.id, periodId: platform.periodId })
415
+ const now = new Date()
416
+ const activeMemberships = memberships.filter(m => m.startDate <= now && m.endDate >= now)
417
+
418
+ if (defaultMemberships.length == 0) {
419
+ // Stop all active memberships
420
+ for (const membership of activeMemberships) {
421
+ if (!membership.invoiceId && !membership.invoiceItemDetailId) {
422
+ console.log('Removing membership because no longer registered member and not yet invoiced for: ' + this.id + ' - membership ' + membership.id)
423
+ await membership.delete()
424
+ }
425
+ }
426
+
427
+ console.log('Skipping automatic membership for: ' + this.id, ' - no default memberships found')
428
+ return
429
+ }
430
+
431
+
432
+ if (activeMemberships.length) {
433
+ // Skip automatic additions
434
+ console.log('Skipping automatic membership for: ' + this.id, ' - already has active memberships')
435
+ return
436
+ }
437
+
438
+ // Add the cheapest available membership
439
+ const cheapestMembership = defaultMemberships.sort(({membership: a, registration: ar}, {membership: b, registration: br}) => {
440
+ const diff = a.getPrice(platform.periodId, now)!.price - b.getPrice(platform.periodId, now)!.price
441
+ if (diff == 0) {
442
+ return Sorter.byDateValue(br.createdAt, ar.createdAt)
443
+ }
444
+ return diff
445
+ })[0]
446
+ if (!cheapestMembership) {
447
+ throw new Error("No membership found")
448
+ }
449
+
450
+ const periodConfig = cheapestMembership.membership.periods.get(platform.periodId)
451
+ if (!periodConfig) {
452
+ throw new Error("Period config not found")
453
+ }
454
+
455
+ console.log('Creating automatic membership for: ' + this.id + ' - membership type ' + cheapestMembership.membership.id)
456
+ const membership = new MemberPlatformMembership();
457
+ membership.memberId = this.id
458
+ membership.membershipTypeId = cheapestMembership.membership.id
459
+ membership.organizationId = cheapestMembership.registration.organizationId
460
+ membership.periodId = platform.periodId
461
+
462
+ membership.startDate = periodConfig.startDate
463
+ membership.endDate = periodConfig.endDate
464
+ membership.expireDate = periodConfig.expireDate
465
+
466
+ await membership.calculatePrice()
467
+ await membership.save()
468
+ });
469
+ }
386
470
  }
@@ -0,0 +1,122 @@
1
+
2
+ import { column, Model } from "@simonbackx/simple-database";
3
+ import { v4 as uuidv4 } from "uuid";
4
+ import { Platform } from "./Platform";
5
+ import { PlatformMembershipTypeBehaviour } from "@stamhoofd/structures";
6
+ import { SimpleError } from "@simonbackx/simple-errors";
7
+ import { Formatter } from "@stamhoofd/utility";
8
+
9
+ export class MemberPlatformMembership extends Model {
10
+ static table = "member_platform_memberships";
11
+
12
+ // Columns
13
+ @column({
14
+ primary: true, type: "string", beforeSave(value) {
15
+ return value ?? uuidv4();
16
+ }
17
+ })
18
+ id!: string;
19
+
20
+ @column({ type: "string" })
21
+ memberId: string;
22
+
23
+ @column({ type: "string" })
24
+ membershipTypeId: string;
25
+
26
+ @column({ type: "string" })
27
+ organizationId: string;
28
+
29
+ @column({ type: "string" })
30
+ periodId: string;
31
+
32
+ @column({ type: "date" })
33
+ startDate: Date;
34
+
35
+ @column({ type: "date" })
36
+ endDate: Date;
37
+
38
+ @column({ type: "date", nullable: true})
39
+ expireDate: Date | null = null;
40
+
41
+ @column({ type: "string", nullable: true })
42
+ invoiceItemDetailId: string | null = null;
43
+
44
+ @column({ type: "string", nullable: true })
45
+ invoiceId: string | null = null;
46
+
47
+ @column({ type: "integer" })
48
+ price = 0;
49
+
50
+ @column({
51
+ type: "datetime", beforeSave(old?: any) {
52
+ if (old !== undefined) {
53
+ return old;
54
+ }
55
+ const date = new Date()
56
+ date.setMilliseconds(0)
57
+ return date
58
+ }
59
+ })
60
+ createdAt: Date
61
+
62
+ @column({
63
+ type: "datetime", beforeSave() {
64
+ const date = new Date()
65
+ date.setMilliseconds(0)
66
+ return date
67
+ },
68
+ skipUpdate: true
69
+ })
70
+ updatedAt: Date
71
+
72
+
73
+ async calculatePrice() {
74
+ if (this.invoiceId || this.invoiceItemDetailId) {
75
+ return;
76
+ }
77
+
78
+ const platform = await Platform.getShared();
79
+ const membershipType = platform.config.membershipTypes.find(m => m.id == this.membershipTypeId);
80
+
81
+ if (!membershipType) {
82
+ throw new SimpleError({
83
+ code: 'invalid_membership_type',
84
+ message: 'Uknown membership type',
85
+ human: 'Deze aansluiting is niet (meer) beschikbaar'
86
+ })
87
+ }
88
+
89
+ const periodConfig = membershipType.periods.get(this.periodId)
90
+
91
+ if (!periodConfig) {
92
+ throw new SimpleError({
93
+ code: 'period_unavailable',
94
+ message: 'Membership not available for this period',
95
+ human: 'Deze aansluiting is nog niet beschikbaar voor dit werkjaar'
96
+ })
97
+ }
98
+
99
+ const priceConfig = periodConfig.getPriceForDate(membershipType.behaviour === PlatformMembershipTypeBehaviour.Days ? this.startDate : (this.createdAt ?? new Date()));
100
+
101
+
102
+ if (membershipType.behaviour === PlatformMembershipTypeBehaviour.Days) {
103
+ // Make sure time is equal between start and end date
104
+ let startBrussels = Formatter.luxon(this.startDate);
105
+ let endBrussels = Formatter.luxon(this.endDate);
106
+ startBrussels = startBrussels.set({hour: 0, minute: 0, second: 0, millisecond: 0});
107
+ endBrussels = endBrussels.set({hour: 23, minute: 59, second: 59, millisecond: 0});
108
+ this.startDate = startBrussels.toJSDate();
109
+ this.endDate = endBrussels.toJSDate();
110
+
111
+ this.expireDate = null
112
+
113
+ const days = Math.round((this.endDate.getTime() - this.startDate.getTime()) / (1000 * 60 * 60 * 24));
114
+ this.price = priceConfig.pricePerDay * days + priceConfig.price;
115
+ } else {
116
+ this.price = priceConfig.price;
117
+ this.startDate = periodConfig.startDate;
118
+ this.endDate = periodConfig.endDate;
119
+ this.expireDate = periodConfig.expireDate;
120
+ }
121
+ }
122
+ }
@@ -3,8 +3,7 @@ import { DecodedRequest } from '@simonbackx/simple-endpoints';
3
3
  import { SimpleError } from '@simonbackx/simple-errors';
4
4
  import { I18n } from "@stamhoofd/backend-i18n";
5
5
  import { Email, EmailInterfaceRecipient } from "@stamhoofd/email";
6
- import { OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Address, Country, DNSRecordStatus, EmailTemplateType, Organization as OrganizationStruct, OrganizationEmail, OrganizationMetaData, OrganizationPrivateMetaData, OrganizationRecordsConfiguration, PaymentMethod, PaymentProvider, PrivatePaymentConfiguration, Recipient, Replacement, STPackageType, TransferSettings } from "@stamhoofd/structures";
7
- import { Formatter } from "@stamhoofd/utility";
6
+ import { Address, Country, DNSRecordStatus, EmailTemplateType, OrganizationEmail, OrganizationMetaData, OrganizationPrivateMetaData, OrganizationRecordsConfiguration, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, PrivatePaymentConfiguration, Recipient, Replacement, STPackageType, TransferSettings } from "@stamhoofd/structures";
8
7
  import { AWSError } from 'aws-sdk';
9
8
  import SES from 'aws-sdk/clients/sesv2';
10
9
  import { PromiseResult } from 'aws-sdk/lib/request';
@@ -95,6 +94,9 @@ export class Organization extends Model {
95
94
  })
96
95
  updatedAt: Date
97
96
 
97
+ @column({type: 'boolean'})
98
+ active = true;
99
+
98
100
  /**
99
101
  * Return default locale confiruation
100
102
  */
@@ -299,65 +301,6 @@ export class Organization extends Model {
299
301
  return struct
300
302
  }
301
303
 
302
- async cleanCategories(groups: {id: string}[]) {
303
- const reachable = new Map<string, boolean>()
304
- const queue = [this.meta.rootCategoryId]
305
- reachable.set(this.meta.rootCategoryId, true)
306
- let shouldSave = false;
307
-
308
- const usedGroupIds = new Set<string>()
309
-
310
- while (queue.length > 0) {
311
- const id = queue.shift()
312
- if (!id) {
313
- break
314
- }
315
-
316
- const category = this.meta.categories.find(c => c.id === id)
317
- if (!category) {
318
- continue
319
- }
320
-
321
- for (const i of category.categoryIds) {
322
- if (!reachable.get(i)) {
323
- reachable.set(i, true)
324
- queue.push(i)
325
- }
326
- }
327
-
328
- // Remove groupIds that no longer exist or are in a different category already
329
- let filtered = category.groupIds.filter(id => !!groups.find(g => g.id === id) && !usedGroupIds.has(id))
330
-
331
- // Remove duplicate groups
332
- filtered = Formatter.uniqueArray(filtered)
333
-
334
- if (filtered.length !== category.groupIds.length) {
335
- shouldSave = true;
336
- console.log("Deleted "+ (category.groupIds.length - filtered.length) +" group ids from category " + category.id + ", in organization "+this.id)
337
- category.groupIds = filtered
338
- }
339
-
340
- for (const groupId of category.groupIds) {
341
- usedGroupIds.add(groupId)
342
- }
343
- }
344
-
345
- const reachableCategoryIds = [...reachable.keys()]
346
-
347
- // Delete all categories that are not reachable anymore
348
- const beforeCount = this.meta.categories.length;
349
- this.meta.categories = this.meta.categories.filter(c => reachableCategoryIds.includes(c.id))
350
-
351
- if (this.meta.categories.length !== beforeCount) {
352
- console.log("Deleted "+ (beforeCount - this.meta.categories.length) +" categories from organization "+this.id)
353
- await this.save()
354
- } else {
355
- if (shouldSave) {
356
- await this.save()
357
- }
358
- }
359
- }
360
-
361
304
  async updateDNSRecords() {
362
305
  const organization = this;
363
306
 
@@ -2,6 +2,7 @@ import { column, Model } from '@simonbackx/simple-database';
2
2
  import { Group as GroupStruct, OrganizationRegistrationPeriodSettings, OrganizationRegistrationPeriod as OrganizationRegistrationPeriodStruct } from '@stamhoofd/structures';
3
3
  import { v4 as uuidv4 } from "uuid";
4
4
  import { Group, RegistrationPeriod } from '.';
5
+ import { Formatter } from '@stamhoofd/utility';
5
6
 
6
7
  export class OrganizationRegistrationPeriod extends Model {
7
8
  static table = "organization_registration_periods";
@@ -51,4 +52,63 @@ export class OrganizationRegistrationPeriod extends Model {
51
52
  groups: groups.map(g => g.getStructure()).sort(GroupStruct.defaultSort)
52
53
  })
53
54
  }
55
+
56
+ async cleanCategories(groups: {id: string}[]) {
57
+ const reachable = new Map<string, boolean>()
58
+ const queue = [this.settings.rootCategoryId]
59
+ reachable.set(this.settings.rootCategoryId, true)
60
+ let shouldSave = false;
61
+
62
+ const usedGroupIds = new Set<string>()
63
+
64
+ while (queue.length > 0) {
65
+ const id = queue.shift()
66
+ if (!id) {
67
+ break
68
+ }
69
+
70
+ const category = this.settings.categories.find(c => c.id === id)
71
+ if (!category) {
72
+ continue
73
+ }
74
+
75
+ for (const i of category.categoryIds) {
76
+ if (!reachable.get(i)) {
77
+ reachable.set(i, true)
78
+ queue.push(i)
79
+ }
80
+ }
81
+
82
+ // Remove groupIds that no longer exist or are in a different category already
83
+ let filtered = category.groupIds.filter(id => !!groups.find(g => g.id === id) && !usedGroupIds.has(id))
84
+
85
+ // Remove duplicate groups
86
+ filtered = Formatter.uniqueArray(filtered)
87
+
88
+ if (filtered.length !== category.groupIds.length) {
89
+ shouldSave = true;
90
+ console.log("Deleted "+ (category.groupIds.length - filtered.length) +" group ids from category " + category.id + ", in organization period "+this.id)
91
+ category.groupIds = filtered
92
+ }
93
+
94
+ for (const groupId of category.groupIds) {
95
+ usedGroupIds.add(groupId)
96
+ }
97
+ }
98
+
99
+ const reachableCategoryIds = [...reachable.keys()]
100
+
101
+ // Delete all categories that are not reachable anymore
102
+ const beforeCount = this.settings.categories.length;
103
+ this.settings.categories = this.settings.categories.filter(c => reachableCategoryIds.includes(c.id))
104
+
105
+ if (this.settings.categories.length !== beforeCount) {
106
+ console.log("Deleted "+ (beforeCount - this.settings.categories.length) +" categories from organizaton period "+this.id)
107
+ await this.save()
108
+ } else {
109
+ if (shouldSave) {
110
+ await this.save()
111
+ }
112
+ }
113
+ }
54
114
  }
@@ -144,17 +144,17 @@ export class Payment extends Model {
144
144
  const registration = balanceItem?.registrationId && registrations.find(r => r.id === balanceItem.registrationId)
145
145
  const member = balanceItem?.memberId ? members.find(r => r.id === balanceItem.memberId) : undefined
146
146
  const order = balanceItem?.orderId && orders.find(r => r.id === balanceItem.orderId)
147
- const group = registration && groups.find(g => g.id === registration.groupId)
147
+ const group = registration ? groups.find(g => g.id === registration.groupId) : null
148
148
 
149
- if (!group) {
150
- throw new Error("Group not found")
149
+ if (registration && !group) {
150
+ throw new Error("Group "+registration.groupId+" not found")
151
151
  }
152
152
 
153
153
  return BalanceItemPaymentDetailed.create({
154
154
  ...item,
155
155
  balanceItem: BalanceItemDetailed.create({
156
156
  ...balanceItem,
157
- registration: registration ? registration.setRelation(Registration.group, group).getStructure() : null,
157
+ registration: registration ? registration.setRelation(Registration.group, group!).getStructure() : null,
158
158
  member: member ? MemberStruct.create(member) : null,
159
159
  order: order ? OrderStruct.create({...order, payment: null}) : null
160
160
  })
@@ -69,6 +69,10 @@ export class Platform extends Model {
69
69
  });
70
70
  }
71
71
 
72
+ static clearCache() {
73
+ this.sharedStruct = null;
74
+ }
75
+
72
76
  async save() {
73
77
  Platform.sharedStruct = null
74
78
  return await super.save()
@@ -167,8 +167,14 @@ export class Registration extends Model {
167
167
  await this.save();
168
168
  return false;
169
169
  }
170
+
171
+ if (this.waitingList && this.canRegister) {
172
+ this.waitingList = false
173
+ }
174
+
170
175
  this.reservedUntil = null
171
176
  this.registeredAt = new Date()
177
+ this.canRegister = false
172
178
  await this.save();
173
179
 
174
180
  await this.sendEmailTemplate({
@@ -305,6 +305,8 @@ export class STInvoice extends Model {
305
305
  await code.reward()
306
306
  }
307
307
  }
308
+
309
+ // todo: link member_membership items to this newly created invoice
308
310
  }
309
311
 
310
312
  async assignNextNumber() {
@@ -47,3 +47,4 @@ export * from "./MemberResponsibilityRecord"
47
47
 
48
48
  export * from "./OrganizationRegistrationPeriod"
49
49
  export * from "./RegistrationPeriod"
50
+ export * from "./MemberPlatformMembership"