@stamhoofd/models 2.121.0 → 2.122.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 (241) hide show
  1. package/dist/factories/GroupFactory.d.ts.map +1 -1
  2. package/dist/factories/GroupFactory.js +1 -1
  3. package/dist/factories/GroupFactory.js.map +1 -1
  4. package/dist/factories/OrganizationFactory.d.ts +2 -1
  5. package/dist/factories/OrganizationFactory.d.ts.map +1 -1
  6. package/dist/factories/OrganizationFactory.js +9 -1
  7. package/dist/factories/OrganizationFactory.js.map +1 -1
  8. package/dist/factories/STPackageFactory.js.map +1 -1
  9. package/dist/factories/UserFactory.d.ts.map +1 -1
  10. package/dist/factories/UserFactory.js +2 -2
  11. package/dist/factories/UserFactory.js.map +1 -1
  12. package/dist/helpers/EmailBuilder.d.ts.map +1 -1
  13. package/dist/helpers/EmailBuilder.js +8 -8
  14. package/dist/helpers/EmailBuilder.js.map +1 -1
  15. package/dist/helpers/Handlebars.d.ts.map +1 -1
  16. package/dist/helpers/Handlebars.js +7 -1
  17. package/dist/helpers/Handlebars.js.map +1 -1
  18. package/dist/index.d.ts +0 -1
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +0 -1
  21. package/dist/index.js.map +1 -1
  22. package/dist/migrations/1605262045-import-postcodes.d.ts.map +1 -1
  23. package/dist/migrations/1605262045-import-postcodes.js +58 -24
  24. package/dist/migrations/1605262045-import-postcodes.js.map +1 -1
  25. package/dist/migrations/1605262046-import-postcodes-nl.d.ts.map +1 -1
  26. package/dist/migrations/1605262046-import-postcodes-nl.js +54 -17
  27. package/dist/migrations/1605262046-import-postcodes-nl.js.map +1 -1
  28. package/dist/migrations/1719567881-organization-periodId.sql +2 -0
  29. package/dist/migrations/1719567882-groups-periodId.sql +2 -0
  30. package/dist/migrations/1720080975-convert-charset.d.ts +4 -0
  31. package/dist/migrations/1720080975-convert-charset.d.ts.map +1 -0
  32. package/dist/migrations/1720080975-convert-charset.js +26 -0
  33. package/dist/migrations/1720080975-convert-charset.js.map +1 -0
  34. package/dist/migrations/1720080976-convert-charset-leads.d.ts.map +1 -1
  35. package/dist/migrations/1720080976-convert-charset-leads.js +11 -10
  36. package/dist/migrations/1720080976-convert-charset-leads.js.map +1 -1
  37. package/dist/migrations/1721400546-users-memberId.sql +2 -0
  38. package/dist/migrations/1722269236-group-waitinglist-id.sql +2 -1
  39. package/dist/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
  40. package/dist/migrations/1722525787-depending-balance-item.sql +2 -0
  41. package/dist/migrations/1722963554-registration-group-price-and-options.sql +1 -1
  42. package/dist/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
  43. package/dist/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
  44. package/dist/migrations/1733317910-paying-organization-id-fk.sql +2 -0
  45. package/dist/migrations/1733504881-negative-invoice-id.sql +6 -0
  46. package/dist/migrations/1733994455-balance-item-status-open.d.ts +4 -0
  47. package/dist/migrations/1733994455-balance-item-status-open.d.ts.map +1 -0
  48. package/dist/migrations/1733994455-balance-item-status-open.js +28 -0
  49. package/dist/migrations/1733994455-balance-item-status-open.js.map +1 -0
  50. package/dist/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
  51. package/dist/migrations/1769087809-payments-invoice-id.sql +2 -0
  52. package/dist/migrations/1772033555-balance-item-package-id.sql +2 -0
  53. package/dist/migrations/1778796615-payments-reversing-payment-id.sql +2 -0
  54. package/dist/migrations/1779443446-transfer-fees.sql +3 -0
  55. package/dist/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
  56. package/dist/migrations/1779968328-payments-admin-user-id.sql +5 -0
  57. package/dist/migrations/1779970611-payments-refunded-amount.sql +2 -0
  58. package/dist/migrations/1779972640-balance-items-failed-at.sql +2 -0
  59. package/dist/migrations/1780328285-document-template-locked.sql +2 -0
  60. package/dist/migrations/1780328286-document-locked.sql +2 -0
  61. package/dist/migrations/1780412083-documents-set-locked.d.ts +4 -0
  62. package/dist/migrations/1780412083-documents-set-locked.d.ts.map +1 -0
  63. package/dist/migrations/1780412083-documents-set-locked.js +14 -0
  64. package/dist/migrations/1780412083-documents-set-locked.js.map +1 -0
  65. package/dist/migrations/1780928401-v1-groups-migration-data.d.ts +4 -0
  66. package/dist/migrations/1780928401-v1-groups-migration-data.d.ts.map +1 -0
  67. package/dist/migrations/1780928401-v1-groups-migration-data.js +44 -0
  68. package/dist/migrations/1780928401-v1-groups-migration-data.js.map +1 -0
  69. package/dist/models/BalanceItem.d.ts +7 -2
  70. package/dist/models/BalanceItem.d.ts.map +1 -1
  71. package/dist/models/BalanceItem.js +41 -38
  72. package/dist/models/BalanceItem.js.map +1 -1
  73. package/dist/models/CachedBalance.d.ts +6 -1
  74. package/dist/models/CachedBalance.d.ts.map +1 -1
  75. package/dist/models/CachedBalance.js +3 -2
  76. package/dist/models/CachedBalance.js.map +1 -1
  77. package/dist/models/Document.d.ts +4 -0
  78. package/dist/models/Document.d.ts.map +1 -1
  79. package/dist/models/Document.js +26 -3
  80. package/dist/models/Document.js.map +1 -1
  81. package/dist/models/DocumentTemplate.d.ts +4 -0
  82. package/dist/models/DocumentTemplate.d.ts.map +1 -1
  83. package/dist/models/DocumentTemplate.js +37 -1
  84. package/dist/models/DocumentTemplate.js.map +1 -1
  85. package/dist/models/Email.d.ts.map +1 -1
  86. package/dist/models/Email.js +1 -1
  87. package/dist/models/Email.js.map +1 -1
  88. package/dist/models/EmailVerificationCode.d.ts.map +1 -1
  89. package/dist/models/EmailVerificationCode.js +3 -13
  90. package/dist/models/EmailVerificationCode.js.map +1 -1
  91. package/dist/models/Event.d.ts +2 -1
  92. package/dist/models/Event.d.ts.map +1 -1
  93. package/dist/models/Event.js +3 -0
  94. package/dist/models/Event.js.map +1 -1
  95. package/dist/models/EventNotification.d.ts.map +1 -1
  96. package/dist/models/EventNotification.js +5 -5
  97. package/dist/models/EventNotification.js.map +1 -1
  98. package/dist/models/Invoice.d.ts +1 -0
  99. package/dist/models/Invoice.d.ts.map +1 -1
  100. package/dist/models/Invoice.js +8 -0
  101. package/dist/models/Invoice.js.map +1 -1
  102. package/dist/models/MemberPlatformMembership.d.ts.map +1 -1
  103. package/dist/models/MemberPlatformMembership.js +9 -0
  104. package/dist/models/MemberPlatformMembership.js.map +1 -1
  105. package/dist/models/Order.d.ts.map +1 -1
  106. package/dist/models/Order.js +1 -0
  107. package/dist/models/Order.js.map +1 -1
  108. package/dist/models/Organization.d.ts +23 -25
  109. package/dist/models/Organization.d.ts.map +1 -1
  110. package/dist/models/Organization.js +92 -64
  111. package/dist/models/Organization.js.map +1 -1
  112. package/dist/models/PasswordToken.d.ts +5 -1
  113. package/dist/models/PasswordToken.d.ts.map +1 -1
  114. package/dist/models/PasswordToken.js +18 -17
  115. package/dist/models/PasswordToken.js.map +1 -1
  116. package/dist/models/Payment.d.ts +21 -2
  117. package/dist/models/Payment.d.ts.map +1 -1
  118. package/dist/models/Payment.js +43 -2
  119. package/dist/models/Payment.js.map +1 -1
  120. package/dist/models/Registration.d.ts.map +1 -1
  121. package/dist/models/Registration.js +3 -3
  122. package/dist/models/Registration.js.map +1 -1
  123. package/dist/models/STCredit.d.ts +4 -0
  124. package/dist/models/STCredit.d.ts.map +1 -1
  125. package/dist/models/STCredit.js +28 -0
  126. package/dist/models/STCredit.js.map +1 -1
  127. package/dist/models/STInvoice.d.ts +7 -1
  128. package/dist/models/STInvoice.d.ts.map +1 -1
  129. package/dist/models/STInvoice.js +9 -0
  130. package/dist/models/STInvoice.js.map +1 -1
  131. package/dist/models/STPackage.d.ts +4 -0
  132. package/dist/models/STPackage.d.ts.map +1 -1
  133. package/dist/models/STPackage.js +12 -1
  134. package/dist/models/STPackage.js.map +1 -1
  135. package/dist/models/UsedRegisterCode.d.ts +9 -0
  136. package/dist/models/UsedRegisterCode.d.ts.map +1 -1
  137. package/dist/models/UsedRegisterCode.js +31 -0
  138. package/dist/models/UsedRegisterCode.js.map +1 -1
  139. package/dist/models/_relations.js +25 -0
  140. package/dist/models/_relations.js.map +1 -1
  141. package/dist/models/addresses/City.d.ts +4 -4
  142. package/dist/models/addresses/City.d.ts.map +1 -1
  143. package/dist/models/addresses/City.js +6 -6
  144. package/dist/models/addresses/City.js.map +1 -1
  145. package/dist/models/addresses/PostalCode.d.ts +2 -2
  146. package/dist/models/addresses/PostalCode.d.ts.map +1 -1
  147. package/dist/models/addresses/PostalCode.js +4 -3
  148. package/dist/models/addresses/PostalCode.js.map +1 -1
  149. package/dist/models/addresses/Street.d.ts +3 -3
  150. package/dist/models/addresses/Street.d.ts.map +1 -1
  151. package/dist/models/addresses/Street.js +4 -4
  152. package/dist/models/addresses/Street.js.map +1 -1
  153. package/dist/models/index.d.ts +1 -0
  154. package/dist/models/index.d.ts.map +1 -1
  155. package/dist/models/index.js +1 -0
  156. package/dist/models/index.js.map +1 -1
  157. package/dist/models/v1GroupMigrationData.d.ts +22 -0
  158. package/dist/models/v1GroupMigrationData.d.ts.map +1 -0
  159. package/dist/models/v1GroupMigrationData.js +48 -0
  160. package/dist/models/v1GroupMigrationData.js.map +1 -0
  161. package/package.json +32 -13
  162. package/src/factories/GroupFactory.ts +4 -6
  163. package/src/factories/OrganizationFactory.ts +12 -4
  164. package/src/factories/STPackageFactory.ts +2 -2
  165. package/src/factories/UserFactory.ts +4 -5
  166. package/src/helpers/EmailBuilder.ts +19 -28
  167. package/src/helpers/Handlebars.ts +6 -1
  168. package/src/index.ts +0 -1
  169. package/src/migrations/1605262045-import-postcodes.ts +62 -25
  170. package/src/migrations/1605262046-import-postcodes-nl.ts +58 -17
  171. package/src/migrations/1719567881-organization-periodId.sql +2 -0
  172. package/src/migrations/1719567882-groups-periodId.sql +2 -0
  173. package/src/migrations/1720080975-convert-charset.ts +34 -0
  174. package/src/migrations/1720080976-convert-charset-leads.ts +16 -13
  175. package/src/migrations/1721400546-users-memberId.sql +2 -0
  176. package/src/migrations/1722269236-group-waitinglist-id.sql +2 -1
  177. package/src/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
  178. package/src/migrations/1722525787-depending-balance-item.sql +2 -0
  179. package/src/migrations/1722963554-registration-group-price-and-options.sql +1 -1
  180. package/src/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
  181. package/src/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
  182. package/src/migrations/1733317910-paying-organization-id-fk.sql +2 -0
  183. package/src/migrations/1733504881-negative-invoice-id.sql +6 -0
  184. package/src/migrations/1733994455-balance-item-status-open.ts +30 -0
  185. package/src/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
  186. package/src/migrations/1769087809-payments-invoice-id.sql +2 -0
  187. package/src/migrations/1772033555-balance-item-package-id.sql +2 -0
  188. package/src/migrations/1778796615-payments-reversing-payment-id.sql +2 -0
  189. package/src/migrations/1779443446-transfer-fees.sql +3 -0
  190. package/src/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
  191. package/src/migrations/1779968328-payments-admin-user-id.sql +5 -0
  192. package/src/migrations/1779970611-payments-refunded-amount.sql +2 -0
  193. package/src/migrations/1779972640-balance-items-failed-at.sql +2 -0
  194. package/src/migrations/1780328285-document-template-locked.sql +2 -0
  195. package/src/migrations/1780328286-document-locked.sql +2 -0
  196. package/src/migrations/1780412083-documents-set-locked.ts +18 -0
  197. package/src/migrations/1780928401-v1-groups-migration-data.ts +50 -0
  198. package/src/models/BalanceItem.ts +44 -43
  199. package/src/models/CachedBalance.test.ts +46 -46
  200. package/src/models/CachedBalance.ts +7 -7
  201. package/src/models/Document.ts +34 -13
  202. package/src/models/DocumentTemplate.ts +56 -17
  203. package/src/models/Email.test.ts +3 -3
  204. package/src/models/Email.ts +28 -49
  205. package/src/models/EmailVerificationCode.ts +8 -22
  206. package/src/models/Event.ts +6 -4
  207. package/src/models/EventNotification.ts +6 -6
  208. package/src/models/Invoice.ts +9 -0
  209. package/src/models/MemberPlatformMembership.test.ts +70 -0
  210. package/src/models/MemberPlatformMembership.ts +16 -12
  211. package/src/models/Order.ts +14 -26
  212. package/src/models/Organization.ts +122 -93
  213. package/src/models/PasswordToken.ts +21 -21
  214. package/src/models/Payment.ts +42 -4
  215. package/src/models/Registration.ts +3 -3
  216. package/src/models/STCredit.ts +32 -0
  217. package/src/models/STInvoice.ts +11 -5
  218. package/src/models/STPackage.ts +19 -14
  219. package/src/models/UsedRegisterCode.ts +34 -0
  220. package/src/models/_relations.ts +29 -0
  221. package/src/models/addresses/City.ts +8 -6
  222. package/src/models/addresses/PostalCode.test.ts +1 -0
  223. package/src/models/addresses/PostalCode.ts +5 -3
  224. package/src/models/addresses/Street.ts +6 -4
  225. package/src/models/index.ts +2 -0
  226. package/src/models/v1GroupMigrationData.ts +43 -0
  227. package/dist/helpers/MemberMerger.d.ts +0 -14
  228. package/dist/helpers/MemberMerger.d.ts.map +0 -1
  229. package/dist/helpers/MemberMerger.js +0 -364
  230. package/dist/helpers/MemberMerger.js.map +0 -1
  231. package/dist/migrations/1720080975-convert-charset.sql +0 -85
  232. package/dist/migrations/1723202126-member-number-index.sql +0 -2
  233. package/dist/models/OneTimeToken.d.ts +0 -38
  234. package/dist/models/OneTimeToken.d.ts.map +0 -1
  235. package/dist/models/OneTimeToken.js +0 -125
  236. package/dist/models/OneTimeToken.js.map +0 -1
  237. package/src/helpers/MemberMerger.test.ts +0 -782
  238. package/src/helpers/MemberMerger.ts +0 -577
  239. package/src/migrations/1720080975-convert-charset.sql +0 -85
  240. package/src/migrations/1723202126-member-number-index.sql +0 -2
  241. package/src/models/OneTimeToken.ts +0 -133
@@ -1,577 +0,0 @@
1
- import { QueryableModel, SQL } from '@stamhoofd/sql';
2
- import type {
3
- Address,
4
- BooleanStatus,
5
- MemberDetails,
6
- Parent,
7
- RecordAnswer,
8
- UitpasNumberDetails} from '@stamhoofd/structures';
9
- import {
10
- Gender,
11
- ParentType
12
- } from '@stamhoofd/structures';
13
- import { Formatter } from '@stamhoofd/utility';
14
- import {
15
- BalanceItem,
16
- Document,
17
- Member,
18
- MemberPlatformMembership,
19
- MemberResponsibilityRecord,
20
- MergedMember,
21
- Registration,
22
- User,
23
- } from '../models/index.js';
24
-
25
- export async function mergeMultipleMembers(members: Member[]) {
26
- const { base, others } = selectBaseMember(members);
27
-
28
- if (!base.existsInDatabase) {
29
- throw Error('Base member does not exist in database');
30
- }
31
-
32
- for (const other of others) {
33
- await mergeTwoMembers(base, other);
34
- }
35
- }
36
-
37
- export async function findEqualMembers({
38
- firstName,
39
- lastName,
40
- birthDay,
41
- }: {
42
- firstName: string;
43
- lastName: string;
44
- birthDay: string;
45
- }): Promise<Member[]> {
46
- return await Member.where({
47
- firstName,
48
- lastName,
49
- birthDay,
50
- });
51
- }
52
-
53
- export async function mergeTwoMembers(base: Member, other: Member): Promise<void> {
54
- console.log('Merging two member', base.id, other.id, base.details.name, other.details.name);
55
-
56
- if (base.id === other.id) {
57
- throw new Error('Cannot merge the same member');
58
- }
59
-
60
- if (!base.existsInDatabase) {
61
- throw new Error('Cannot merge to base member that does not exist in database');
62
- }
63
-
64
- mergeMemberDetails(base, other);
65
-
66
- if (other.existsInDatabase) {
67
- await mergeRegistrations(base, other);
68
- await mergeUsers(base, other);
69
- await mergeResponsibilities(base, other);
70
- await mergeBalanceItems(base, other);
71
- await mergeDocuments(base, other);
72
- await mergeMemberPlatformMemberships(base, other);
73
- }
74
-
75
- // Force review of all details
76
- base.details.reviewTimes.clearAll();
77
- base.details.cleanData();
78
-
79
- if (other.existsInDatabase && other.details.memberNumber && other.details.memberNumber === base.details.memberNumber) {
80
- // Clear member number first, because that will cause duplicate member number mysql errors
81
- other.details.memberNumber = null;
82
- await other.save();
83
- }
84
-
85
- await base.save();
86
-
87
- if (other.existsInDatabase) {
88
- console.log('Deleting duplicate member', other.id, other.details.name);
89
-
90
- // store other member in merged_member table
91
- const mergedMember = MergedMember.fromMember(other, base.id);
92
- await mergedMember.save();
93
-
94
- await other.delete();
95
- }
96
- }
97
-
98
- async function mergeRegistrations(base: Member, other: Member) {
99
- await mergeModels(base, other, Registration);
100
- }
101
-
102
- async function mergeUsers(base: Member, other: Member) {
103
- await mergeModels(base, other, User);
104
- }
105
-
106
- async function mergeResponsibilities(base: Member, other: Member) {
107
- async function getResponsibilities(memberId: string) {
108
- const rows = await SQL.select()
109
- .from(SQL.table(MemberResponsibilityRecord.table))
110
- .where(SQL.column('memberId'), memberId)
111
- .fetch();
112
-
113
- return MemberResponsibilityRecord.fromRows(
114
- rows,
115
- MemberResponsibilityRecord.table,
116
- );
117
- }
118
-
119
- const otherResponsibilities = await getResponsibilities(other.id);
120
- const baseResponsibilities = await getResponsibilities(base.id);
121
-
122
- // Delete duplicate responsibilities where endDate is null -> keep responsibility with oldest start date
123
- for (const otherResponsibility of otherResponsibilities) {
124
- // check if equal responsibilities exist
125
- const otherResponsibilitiesWithoutCurrent
126
- = otherResponsibilities.filter(
127
- o => o.id !== otherResponsibility.id,
128
- );
129
- const equalResponsibilities = baseResponsibilities
130
- .concat(otherResponsibilitiesWithoutCurrent)
131
- .filter((baseResponsibility) => {
132
- return (
133
- baseResponsibility.responsibilityId
134
- === otherResponsibility.responsibilityId
135
- && baseResponsibility.organizationId
136
- === otherResponsibility.organizationId
137
- && baseResponsibility.groupId
138
- === otherResponsibility.groupId
139
- && baseResponsibility.endDate === null
140
- && otherResponsibility.endDate === null
141
- );
142
- });
143
-
144
- if (equalResponsibilities.length > 0) {
145
- const allEqualResponsibilities = [
146
- ...equalResponsibilities,
147
- otherResponsibility,
148
- ]
149
- // sort on startDate
150
- .sort((a, b) => a.startDate.getTime() - b.startDate.getTime());
151
-
152
- const responsibilityWithOldestStartDate
153
- = allEqualResponsibilities[0];
154
-
155
- const responsibilitiesToDelete = allEqualResponsibilities.slice(
156
- 1,
157
- undefined,
158
- );
159
-
160
- for (const responsibilityToDelete of responsibilitiesToDelete) {
161
- const baseIndex = baseResponsibilities.indexOf(
162
- responsibilityToDelete,
163
- );
164
- if (baseIndex !== -1) baseResponsibilities.splice(baseIndex, 1);
165
- else {
166
- const otherIndex = otherResponsibilities.indexOf(
167
- responsibilityToDelete,
168
- );
169
- if (otherIndex !== -1)
170
- otherResponsibilities.splice(otherIndex, 1);
171
- }
172
-
173
- if (responsibilityToDelete.existsInDatabase) {
174
- await responsibilityToDelete.delete();
175
- }
176
- }
177
-
178
- if (responsibilityWithOldestStartDate.memberId !== base.id) {
179
- responsibilityWithOldestStartDate.memberId = base.id;
180
- await responsibilityWithOldestStartDate.save();
181
- }
182
- }
183
- else {
184
- otherResponsibility.memberId = base.id;
185
- await otherResponsibility.save();
186
- }
187
- }
188
- }
189
-
190
- async function mergeBalanceItems(base: Member, other: Member) {
191
- await mergeModels(base, other, BalanceItem);
192
- }
193
-
194
- async function mergeDocuments(base: Member, other: Member) {
195
- await mergeModels(base, other, Document);
196
- }
197
-
198
- async function mergeMemberPlatformMemberships(base: Member, other: Member) {
199
- await mergeModels(base, other, MemberPlatformMembership);
200
- }
201
-
202
- class ModelWithMemberId extends QueryableModel {
203
- memberId: string | null;
204
- }
205
-
206
- async function mergeModels<M extends typeof ModelWithMemberId>(
207
- base: Member,
208
- other: Member,
209
- model: M,
210
- ) {
211
- const baseId = base.id;
212
- const otherModels = await model.where({
213
- memberId: other.id,
214
- });
215
-
216
- for (const otherModel of otherModels) {
217
- otherModel.memberId = baseId;
218
- await otherModel.save();
219
- }
220
- }
221
-
222
- export function mergeMemberDetails(base: Member, other: Member): void {
223
- const baseDetails = base.details;
224
- const otherDetails = other.details;
225
- baseDetails.cleanData();
226
- otherDetails.cleanData();
227
-
228
- // string details
229
- mergeStringIfBaseNotSet(baseDetails, otherDetails, 'firstName');
230
- mergeStringIfBaseNotSet(baseDetails, otherDetails, 'lastName');
231
-
232
- mergeStringIfBaseNotSet(baseDetails, otherDetails, 'memberNumber');
233
-
234
- // uitpas number
235
- mergeUitpasNumberDetails(baseDetails, otherDetails, baseDetails);
236
-
237
- // email
238
- mergeEmail(baseDetails, otherDetails);
239
-
240
- // phone
241
- mergePhone(baseDetails, otherDetails, baseDetails);
242
-
243
- // gender
244
- if (otherDetails.gender !== Gender.Other) {
245
- baseDetails.gender = otherDetails.gender;
246
- }
247
-
248
- // notes
249
- mergeNotes(baseDetails, otherDetails);
250
-
251
- // date
252
- merge(baseDetails, otherDetails, 'birthDay');
253
-
254
- // boolean status
255
- mergeBooleanStatusIfBaseNotSet(
256
- baseDetails,
257
- otherDetails,
258
- 'requiresFinancialSupport',
259
- );
260
-
261
- mergeBooleanStatusIfBaseNotSet(
262
- baseDetails,
263
- otherDetails,
264
- 'dataPermissions',
265
- );
266
-
267
- // address
268
- mergeAddress(baseDetails, otherDetails, baseDetails);
269
-
270
- // parents
271
- mergeParents(baseDetails, otherDetails);
272
-
273
- // emergency contacts
274
- baseDetails.emergencyContacts = baseDetails.emergencyContacts.concat(
275
- // add contacts that are not yet in the list
276
- otherDetails.emergencyContacts.filter(
277
- otherContact =>
278
- !baseDetails.emergencyContacts.some(baseContact =>
279
- baseContact.isEqual(otherContact),
280
- ),
281
- ),
282
- );
283
-
284
- // review times
285
- // todo: is this correct?
286
- baseDetails.reviewTimes.merge(otherDetails.reviewTimes);
287
-
288
- // answers
289
- mergeAnswers(baseDetails, otherDetails);
290
-
291
- // unverified data
292
- baseDetails.unverifiedEmails = Formatter.uniqueArray(
293
- baseDetails.unverifiedEmails.concat(
294
- otherDetails.unverifiedEmails.filter(
295
- email => !isNullOrEmpty(email),
296
- ),
297
- ),
298
- );
299
- baseDetails.unverifiedPhones = Formatter.uniqueArray(
300
- baseDetails.unverifiedPhones.concat(
301
- otherDetails.unverifiedPhones.filter(
302
- phone => !isNullOrEmpty(phone),
303
- ),
304
- ),
305
- );
306
-
307
- // unverified addresses
308
- for (const address of otherDetails.unverifiedAddresses) {
309
- if (!baseDetails.unverifiedAddresses.some(a => a.id === address.id)) {
310
- baseDetails.unverifiedAddresses.push(address);
311
- }
312
- }
313
-
314
- // Ids
315
- baseDetails.oldIds = Formatter.uniqueArray([...baseDetails.oldIds, ...otherDetails.oldIds]).filter(b => b !== base.id);
316
-
317
- if (other.id) {
318
- baseDetails.oldIds = Formatter.uniqueArray([...baseDetails.oldIds, other.id]);
319
- }
320
- }
321
-
322
- export function selectBaseMember(members: Member[]): {
323
- base: Member;
324
- others: Member[];
325
- } {
326
- if (members.length < 2) {
327
- throw Error('Members array length is less than 2.');
328
- }
329
- const sorted = members.sort(
330
- (m1, m2) => (m2.existsInDatabase ? 0 : m2.createdAt.getTime()) - (m1.existsInDatabase ? 0 : m1.createdAt.getTime()),
331
- );
332
-
333
- return { base: sorted[0], others: sorted.slice(1, undefined) };
334
- }
335
-
336
- function mergeAnswers(base: MemberDetails, other: MemberDetails) {
337
- const newAnswers: Map<string, RecordAnswer> = new Map(base.recordAnswers);
338
- for (const otherAnswer of other.recordAnswers.values()) {
339
- const otherId = otherAnswer.settings.id;
340
- const baseAnswer = newAnswers.get(otherId);
341
-
342
- if (!baseAnswer) {
343
- newAnswers.set(otherId, otherAnswer);
344
- }
345
- else if (otherAnswer.date >= baseAnswer.date) {
346
- newAnswers.set(otherId, otherAnswer);
347
- }
348
- else {
349
- // keep existing, this one is more up-to-date, don't add the other answer
350
- }
351
- }
352
- base.recordAnswers = newAnswers;
353
- }
354
-
355
- function mergeNotes(base: MemberDetails, other: MemberDetails) {
356
- if (base.notes && other.notes && base.notes !== other.notes) {
357
- base.notes = `${base.notes}\n${other.notes}`;
358
- }
359
- else if (other.notes) {
360
- base.notes = other.notes;
361
- return;
362
- }
363
- }
364
-
365
- function mergeParents(base: MemberDetails, other: MemberDetails) {
366
- const baseParents = base.parents;
367
- const otherParents = other.parents;
368
- const parentsToAdd: Parent[] = [];
369
-
370
- for (const otherParent of otherParents) {
371
- // equal if same first and last name
372
- const equalBaseParent = baseParents.find(
373
- baseParent =>
374
- hasEqualStringValue(baseParent, otherParent, 'firstName')
375
- && hasEqualStringValue(baseParent, otherParent, 'lastName'),
376
- );
377
-
378
- if (!equalBaseParent) {
379
- parentsToAdd.push(otherParent);
380
- continue;
381
- }
382
-
383
- mergeParent(equalBaseParent, otherParent, base);
384
- }
385
-
386
- base.parents = baseParents.concat(parentsToAdd);
387
- }
388
-
389
- function mergeParent(base: Parent, other: Parent, baseDetails: MemberDetails) {
390
- if (other.type !== ParentType.Other) {
391
- base.type = other.type;
392
- }
393
- mergeString(base, other, 'firstName');
394
- mergeString(base, other, 'lastName');
395
- // add other emails to alternative emails
396
- mergeEmail(base, other);
397
- mergePhone(base, other, baseDetails);
398
- mergeAddress(base, other, baseDetails);
399
- }
400
-
401
- function mergeEmail(
402
- base: { email: string | null; alternativeEmails: string[] },
403
- other: { email: string | null; alternativeEmails: string[] },
404
- ) {
405
- const allEmails = Formatter.uniqueArray(
406
- [other.email, ...other.alternativeEmails, base.email, ...base.alternativeEmails]
407
- .filter(f => f !== null)
408
- .filter(f => !isNullOrEmpty(f)),
409
- );
410
- base.email = allEmails.shift() ?? null;
411
- base.alternativeEmails = allEmails;
412
- }
413
-
414
- function mergePhone(
415
- base: { phone: string | null | undefined },
416
- other: { phone: string | null | undefined },
417
- baseDetails: MemberDetails,
418
- ) {
419
- const originalPhone = base.phone;
420
- const isPhoneMerged = mergeString(base, other, 'phone');
421
- if (isPhoneMerged && !isNullOrEmpty(originalPhone)) {
422
- if (
423
- !baseDetails.unverifiedPhones.some(phone => phone === originalPhone)
424
- ) {
425
- baseDetails.unverifiedPhones.push(originalPhone!);
426
- }
427
- }
428
- }
429
-
430
- function mergeAddress(
431
- base: { address: Address | null | undefined },
432
- other: { address: Address | null | undefined },
433
- baseDetails: MemberDetails,
434
- ) {
435
- const baseAddress = base.address;
436
- const otherAddress = other.address;
437
-
438
- if (!otherAddress) {
439
- return;
440
- }
441
-
442
- base.address = otherAddress;
443
-
444
- if (baseAddress && baseAddress.id !== otherAddress.id) {
445
- // add base address to unverified addresses
446
- if (
447
- !baseDetails.unverifiedAddresses.some(
448
- address => address.id === baseAddress.id,
449
- )
450
- ) {
451
- baseDetails.unverifiedAddresses.push(baseAddress);
452
- }
453
- }
454
- }
455
-
456
- function mergeUitpasNumberDetails(base: { uitpasNumberDetails: UitpasNumberDetails | null }, other: { uitpasNumberDetails: UitpasNumberDetails | null }, baseDetails: MemberDetails) {
457
- const baseUitpasNumberDetails = base.uitpasNumberDetails;
458
- const otherUitpasNumberDetails = other.uitpasNumberDetails;
459
-
460
- if (!otherUitpasNumberDetails) {
461
- return;
462
- }
463
-
464
- if ((baseUitpasNumberDetails?.socialTariff?.updatedAt.getTime() ?? 0) >= (otherUitpasNumberDetails.socialTariff?.updatedAt.getTime() ?? 0)) {
465
- return;
466
- }
467
-
468
- baseDetails.uitpasNumberDetails = otherUitpasNumberDetails;
469
- }
470
-
471
- function mergeString<T, K extends keyof T>(
472
- base: T,
473
- other: T,
474
- key: K & (T[K] extends string | null | undefined ? K : never),
475
- ): boolean {
476
- const otherValue = other[key] as string | null | undefined;
477
- if (isNullOrEmpty(otherValue)) {
478
- return false;
479
- }
480
-
481
- (base[key] as string | null | undefined) = otherValue;
482
-
483
- return true;
484
- }
485
-
486
- function mergeStringIfBaseNotSet<T, K extends keyof T>(
487
- base: T,
488
- other: T,
489
- key: K & (T[K] extends string | null | undefined ? K : never),
490
- ): boolean {
491
- const otherValue = other[key] as string | null | undefined;
492
- if (isNullOrEmpty(otherValue)) {
493
- return false;
494
- }
495
-
496
- if (!isNullOrEmpty(base[key] as string | null | undefined)) {
497
- return false;
498
- }
499
-
500
- (base[key] as string | null | undefined) = otherValue;
501
-
502
- return true;
503
- }
504
-
505
- function merge<T, K extends keyof T>(
506
- base: T,
507
- other: T,
508
- key: K &
509
- (T[K] extends number | Date | boolean | null | undefined ? K : never),
510
- ): boolean {
511
- const otherValue = other[key] as number | Date | boolean | null | undefined;
512
- if (otherValue === null || otherValue === undefined) return false;
513
- (base[key] as number | Date | boolean | null | undefined) = otherValue;
514
- return true;
515
- }
516
-
517
- function mergeBooleanStatusIfBaseNotSet<T, K extends keyof T>(
518
- base: T,
519
- other: T,
520
- key: K & (T[K] extends BooleanStatus | null | undefined ? K : never),
521
- ): boolean {
522
- const otherValue = other[key] as BooleanStatus | null | undefined;
523
- if (otherValue === null || otherValue === undefined) return false;
524
-
525
- const baseValue = base[key] as BooleanStatus | null | undefined;
526
- if (baseValue === undefined || baseValue === null) {
527
- (base[key] as BooleanStatus | null | undefined) = otherValue;
528
- return true;
529
- }
530
-
531
- if (baseValue.date < otherValue.date) {
532
- (base[key] as BooleanStatus | null | undefined) = otherValue;
533
- return true;
534
- }
535
-
536
- return false;
537
- }
538
-
539
- /**
540
- * Returns true if the values of the key for a and b
541
- * are not null or undefined
542
- * and both are equal.
543
- * @param a
544
- * @param b
545
- * @param key
546
- * @returns
547
- */
548
- function hasEqualStringValue<T, K extends keyof T>(
549
- a: T,
550
- b: T,
551
- key: K & (T[K] extends string | null | undefined ? K : never),
552
- ) {
553
- return hasValueAndIsEqual(
554
- a[key] as string | null | undefined,
555
- b[key] as string | null | undefined,
556
- );
557
- }
558
-
559
- function hasValueAndIsEqual(
560
- a: string | null | undefined,
561
- b: string | null | undefined,
562
- ): boolean {
563
- if (isNullOrEmpty(a) || isNullOrEmpty(b)) return false;
564
- return isStringEqual(a as string, b as string);
565
- }
566
-
567
- function isStringEqual(a: string, b: string): boolean {
568
- return toLowerTrim(a) === toLowerTrim(b);
569
- }
570
-
571
- function toLowerTrim(name: string) {
572
- return name.toLowerCase().trim();
573
- }
574
-
575
- function isNullOrEmpty(value: string | null | undefined) {
576
- return value === null || value === undefined || value.trim() === '';
577
- }
@@ -1,85 +0,0 @@
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_templates` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
17
- ALTER TABLE `email_templates` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
18
- ALTER TABLE `email_verification_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
19
- ALTER TABLE `email_verification_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
20
- ALTER TABLE `groups` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
21
- ALTER TABLE `groups` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
22
- ALTER TABLE `images` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
23
- ALTER TABLE `images` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
24
- ALTER TABLE `members` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
25
- ALTER TABLE `members` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
26
- ALTER TABLE `migrations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
27
- ALTER TABLE `migrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
28
- ALTER TABLE `mollie_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
29
- ALTER TABLE `mollie_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
30
- ALTER TABLE `mollie_tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
31
- ALTER TABLE `mollie_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
32
- ALTER TABLE `organization_registration_periods` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
33
- ALTER TABLE `organization_registration_periods` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
34
- ALTER TABLE `organizations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
35
- ALTER TABLE `organizations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
36
- ALTER TABLE `password_tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
37
- ALTER TABLE `password_tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
38
- ALTER TABLE `payconiq_payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
39
- ALTER TABLE `payconiq_payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
40
- ALTER TABLE `payments` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
41
- ALTER TABLE `payments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
42
- ALTER TABLE `platform` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
43
- ALTER TABLE `platform` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
44
- ALTER TABLE `postal_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
45
- ALTER TABLE `postal_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
46
- ALTER TABLE `provinces` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
47
- ALTER TABLE `provinces` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
48
- ALTER TABLE `register_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
49
- ALTER TABLE `register_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
50
- ALTER TABLE `registration_periods` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
51
- ALTER TABLE `registration_periods` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
52
- ALTER TABLE `registrations` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
53
- ALTER TABLE `registrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
54
- ALTER TABLE `stamhoofd_credits` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
55
- ALTER TABLE `stamhoofd_credits` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
56
- ALTER TABLE `stamhoofd_invoices` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
57
- ALTER TABLE `stamhoofd_invoices` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
58
- ALTER TABLE `stamhoofd_packages` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
59
- ALTER TABLE `stamhoofd_packages` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
60
- ALTER TABLE `stamhoofd_pending_invoices` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
61
- ALTER TABLE `stamhoofd_pending_invoices` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
62
- ALTER TABLE `streets` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
63
- ALTER TABLE `streets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
64
- ALTER TABLE `stripe_accounts` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
65
- ALTER TABLE `stripe_accounts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
66
- ALTER TABLE `stripe_checkout_sessions` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
67
- ALTER TABLE `stripe_checkout_sessions` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
68
- ALTER TABLE `stripe_payment_intents` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
69
- ALTER TABLE `stripe_payment_intents` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
70
- ALTER TABLE `tokens` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
71
- ALTER TABLE `tokens` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
72
- ALTER TABLE `used_register_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
73
- ALTER TABLE `used_register_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
74
- ALTER TABLE `users` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
75
- ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
76
- ALTER TABLE `webshop_discount_codes` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
77
- ALTER TABLE `webshop_discount_codes` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
78
- ALTER TABLE `webshop_orders` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
79
- ALTER TABLE `webshop_orders` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
80
- ALTER TABLE `webshop_tickets` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
81
- ALTER TABLE `webshop_tickets` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
82
- ALTER TABLE `webshops` CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
83
- ALTER TABLE `webshops` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
84
- ALTER DATABASE CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
85
- set foreign_key_checks=1;
@@ -1,2 +0,0 @@
1
- ALTER TABLE `members`
2
- ADD UNIQUE INDEX `memberNumber` (`memberNumber`) USING BTREE;