@stamhoofd/backend 2.58.0 → 2.59.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.
- package/index.ts +6 -1
- package/package.json +12 -12
- package/src/audit-logs/EventLogger.ts +30 -0
- package/src/audit-logs/GroupLogger.ts +95 -0
- package/src/audit-logs/MemberLogger.ts +24 -0
- package/src/audit-logs/MemberPlatformMembershipLogger.ts +57 -0
- package/src/audit-logs/MemberResponsibilityRecordLogger.ts +69 -0
- package/src/audit-logs/ModelLogger.ts +218 -0
- package/src/audit-logs/OrderLogger.ts +57 -0
- package/src/audit-logs/OrganizationLogger.ts +26 -0
- package/src/audit-logs/OrganizationRegistrationPeriodLogger.ts +77 -0
- package/src/audit-logs/PaymentLogger.ts +43 -0
- package/src/audit-logs/PlatformLogger.ts +13 -0
- package/src/audit-logs/RegistrationLogger.ts +53 -0
- package/src/audit-logs/RegistrationPeriodLogger.ts +21 -0
- package/src/audit-logs/StripeAccountLogger.ts +47 -0
- package/src/audit-logs/WebshopLogger.ts +35 -0
- package/src/crons.ts +2 -1
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +12 -24
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +4 -18
- package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +5 -13
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +3 -11
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +0 -15
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +5 -2
- package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +0 -19
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +1 -12
- package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +18 -33
- package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +0 -6
- package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +0 -6
- package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +5 -14
- package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +7 -4
- package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +8 -2
- package/src/helpers/AuthenticatedStructures.ts +16 -1
- package/src/helpers/Context.ts +8 -2
- package/src/helpers/MemberUserSyncer.ts +45 -40
- package/src/helpers/PeriodHelper.ts +3 -4
- package/src/helpers/TagHelper.ts +23 -20
- package/src/seeds/1722344162-update-membership.ts +2 -2
- package/src/seeds/1726572303-schedule-stock-updates.ts +2 -1
- package/src/services/AuditLogService.ts +83 -295
- package/src/services/BalanceItemPaymentService.ts +1 -1
- package/src/services/BalanceItemService.ts +14 -5
- package/src/services/MemberNumberService.ts +120 -0
- package/src/services/PaymentService.ts +199 -193
- package/src/services/PlatformMembershipService.ts +284 -0
- package/src/services/RegistrationService.ts +76 -27
- package/src/services/explainPatch.ts +110 -41
- package/src/helpers/MembershipHelper.ts +0 -54
|
@@ -22,8 +22,8 @@ function createStringChangeHandler(key: string) {
|
|
|
22
22
|
return [
|
|
23
23
|
AuditLogPatchItem.create({
|
|
24
24
|
key: getAutoEncoderKey(key),
|
|
25
|
-
oldValue: getAutoEncoderValue(oldValue) || getAutoEncoderName(oldValue) || undefined,
|
|
26
|
-
value: getAutoEncoderValue(value) || getAutoEncoderName(value) || undefined,
|
|
25
|
+
oldValue: getAutoEncoderValue(oldValue, key) || getAutoEncoderName(oldValue) || undefined,
|
|
26
|
+
value: getAutoEncoderValue(value, key) || getAutoEncoderName(value) || undefined,
|
|
27
27
|
}).autoType(),
|
|
28
28
|
];
|
|
29
29
|
};
|
|
@@ -58,12 +58,11 @@ function createIntegerChangeHandler(key: string) {
|
|
|
58
58
|
return [];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
const formatter: (typeof Formatter.price | typeof Formatter.integer) = key.toLowerCase().includes('price') ? Formatter.price.bind(Formatter) : Formatter.integer.bind(Formatter);
|
|
62
61
|
return [
|
|
63
62
|
AuditLogPatchItem.create({
|
|
64
63
|
key: getAutoEncoderKey(key),
|
|
65
|
-
oldValue: oldValue !== null ?
|
|
66
|
-
value: value !== null ?
|
|
64
|
+
oldValue: oldValue !== null ? (getAutoEncoderValue(oldValue, key) || undefined) : undefined,
|
|
65
|
+
value: value !== null ? (getAutoEncoderValue(value, key) || undefined) : undefined,
|
|
67
66
|
}).autoType(),
|
|
68
67
|
];
|
|
69
68
|
};
|
|
@@ -85,7 +84,7 @@ function createDateChangeHandler(key: string) {
|
|
|
85
84
|
let dno = oldValue ? Formatter.dateNumber(oldValue, true) : undefined;
|
|
86
85
|
let dn = value ? Formatter.dateNumber(value, true) : undefined;
|
|
87
86
|
|
|
88
|
-
if (dno && dn && (dno === dn || (Formatter.time(oldValue!) !== Formatter.time(value!)))) {
|
|
87
|
+
if (dno && dn && (dno === dn || (Formatter.time(oldValue!) !== Formatter.time(value!))) && key !== 'birthDay') {
|
|
89
88
|
// Add time
|
|
90
89
|
dno += ' ' + Formatter.time(oldValue!);
|
|
91
90
|
dn += ' ' + Formatter.time(value!);
|
|
@@ -157,7 +156,7 @@ function getAutoEncoderName(autoEncoder: unknown): AuditLogReplacement | null {
|
|
|
157
156
|
}
|
|
158
157
|
return null;
|
|
159
158
|
}
|
|
160
|
-
function getAutoEncoderPutValue(autoEncoder: unknown): AuditLogReplacement | null {
|
|
159
|
+
function getAutoEncoderPutValue(autoEncoder: unknown, key?: string): AuditLogReplacement | null {
|
|
161
160
|
if (typeof autoEncoder === 'object' && autoEncoder !== null && 'getPutValue' in autoEncoder && typeof autoEncoder.getPutValue === 'function') {
|
|
162
161
|
const name = autoEncoder.getPutValue();
|
|
163
162
|
if (typeof name === 'string') {
|
|
@@ -167,14 +166,18 @@ function getAutoEncoderPutValue(autoEncoder: unknown): AuditLogReplacement | nul
|
|
|
167
166
|
return name;
|
|
168
167
|
}
|
|
169
168
|
}
|
|
170
|
-
return getAutoEncoderValue(autoEncoder);
|
|
169
|
+
return getAutoEncoderValue(autoEncoder, key);
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
function getAutoEncoderValue(autoEncoder: unknown): AuditLogReplacement | null {
|
|
172
|
+
function getAutoEncoderValue(autoEncoder: unknown, key?: string): AuditLogReplacement | null {
|
|
174
173
|
if (typeof autoEncoder === 'string') {
|
|
175
174
|
if (isUuid(autoEncoder)) {
|
|
176
175
|
return AuditLogReplacement.uuid(autoEncoder);
|
|
177
176
|
}
|
|
177
|
+
if (key && key === 'status') {
|
|
178
|
+
// Will be an enum
|
|
179
|
+
return AuditLogReplacement.key(autoEncoder);
|
|
180
|
+
}
|
|
178
181
|
return AuditLogReplacement.string(autoEncoder);
|
|
179
182
|
}
|
|
180
183
|
|
|
@@ -187,6 +190,9 @@ function getAutoEncoderValue(autoEncoder: unknown): AuditLogReplacement | null {
|
|
|
187
190
|
}
|
|
188
191
|
|
|
189
192
|
if (typeof autoEncoder === 'number') {
|
|
193
|
+
if (key && (key.toLowerCase().includes('price') || key.toLowerCase().includes('fee'))) {
|
|
194
|
+
return AuditLogReplacement.string(Formatter.price(autoEncoder));
|
|
195
|
+
}
|
|
190
196
|
return AuditLogReplacement.string(Formatter.integer(autoEncoder));
|
|
191
197
|
}
|
|
192
198
|
|
|
@@ -246,6 +252,10 @@ function findOriginalById(id: unknown, oldArray: unknown[]): unknown | null {
|
|
|
246
252
|
return id ? oldArray.find(v => getId(v) === id) : null;
|
|
247
253
|
}
|
|
248
254
|
|
|
255
|
+
function findOriginalIndexById(id: unknown, oldArray: unknown[]): number {
|
|
256
|
+
return id ? oldArray.findIndex(v => getId(v) === id) : -1;
|
|
257
|
+
}
|
|
258
|
+
|
|
249
259
|
function getId(object: unknown): string | number | null {
|
|
250
260
|
const id = getOptionalId(object);
|
|
251
261
|
if (typeof id !== 'string' && typeof id !== 'number') {
|
|
@@ -262,6 +272,10 @@ function findOriginal(put: unknown, oldArray: unknown[]): unknown | null {
|
|
|
262
272
|
return findOriginalById(getId(put), oldArray);
|
|
263
273
|
}
|
|
264
274
|
|
|
275
|
+
function findIndex(put: unknown, oldArray: unknown[]): number {
|
|
276
|
+
return findOriginalIndexById(getId(put), oldArray);
|
|
277
|
+
}
|
|
278
|
+
|
|
265
279
|
function processPut(key: string, put: unknown, original: unknown | null, createdIdSet?: Set<string>): AuditLogPatchItem[] {
|
|
266
280
|
const items: AuditLogPatchItem[] = [];
|
|
267
281
|
const keySingular = getKeySingular(key);
|
|
@@ -269,10 +283,11 @@ function processPut(key: string, put: unknown, original: unknown | null, created
|
|
|
269
283
|
|
|
270
284
|
// Added a new parent
|
|
271
285
|
if (!original) {
|
|
286
|
+
const n = getAutoEncoderName(put);
|
|
272
287
|
items.push(
|
|
273
288
|
AuditLogPatchItem.create({
|
|
274
|
-
key: AuditLogReplacement.key(keySingular).append(
|
|
275
|
-
value: v || undefined,
|
|
289
|
+
key: AuditLogReplacement.key(keySingular).append(n),
|
|
290
|
+
value: (n?.toString() !== v?.toString()) ? (v || undefined) : undefined,
|
|
276
291
|
type: AuditLogPatchItemType.Added,
|
|
277
292
|
}),
|
|
278
293
|
);
|
|
@@ -345,10 +360,10 @@ function processPatch(key: string, patch: unknown, original: unknown | null): Au
|
|
|
345
360
|
ov = null;
|
|
346
361
|
v = null;
|
|
347
362
|
|
|
348
|
-
if (l.length === 0) {
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
}
|
|
363
|
+
// if (l.length === 0) {
|
|
364
|
+
// Probably no change
|
|
365
|
+
return [];
|
|
366
|
+
// }
|
|
352
367
|
}
|
|
353
368
|
|
|
354
369
|
// Simplify changes by providing one change instead of for all keys
|
|
@@ -380,15 +395,16 @@ function processDelete(key: string, deletedItem: unknown, createdIdSet?: Set<str
|
|
|
380
395
|
}
|
|
381
396
|
|
|
382
397
|
const v = getAutoEncoderPutValue(deletedItem);
|
|
398
|
+
const n = getAutoEncoderName(deletedItem);
|
|
383
399
|
|
|
384
400
|
const keySingular = getKeySingular(key);
|
|
385
|
-
const k = AuditLogReplacement.key(keySingular).append(
|
|
401
|
+
const k = AuditLogReplacement.key(keySingular).append(n);
|
|
386
402
|
|
|
387
403
|
return [
|
|
388
404
|
AuditLogPatchItem.create({
|
|
389
405
|
key: k,
|
|
390
406
|
type: AuditLogPatchItemType.Removed,
|
|
391
|
-
oldValue: v
|
|
407
|
+
oldValue: (n?.toString() !== v?.toString()) ? (v || undefined) : undefined,
|
|
392
408
|
}),
|
|
393
409
|
];
|
|
394
410
|
}
|
|
@@ -404,16 +420,25 @@ function createArrayChangeHandler(key: string) {
|
|
|
404
420
|
if (!isPatchableArray(value)) {
|
|
405
421
|
if (Array.isArray(value)) {
|
|
406
422
|
// Search for puts
|
|
407
|
-
|
|
408
|
-
|
|
423
|
+
let orderChanged = false;
|
|
424
|
+
let added = 0;
|
|
425
|
+
for (const [index, newItem] of value.entries()) {
|
|
426
|
+
const originalIndex = findIndex(newItem, oldValue);
|
|
409
427
|
|
|
410
|
-
if (
|
|
428
|
+
if (originalIndex === -1) {
|
|
411
429
|
// Has been added
|
|
412
|
-
items.push(...processPut(key, newItem,
|
|
430
|
+
items.push(...processPut(key, newItem, null));
|
|
431
|
+
added++;
|
|
413
432
|
}
|
|
414
433
|
else {
|
|
415
434
|
// Has been overwritten
|
|
435
|
+
const original = oldValue[originalIndex];
|
|
416
436
|
items.push(...processPatch(key, newItem, original));
|
|
437
|
+
|
|
438
|
+
if ((index - added) !== originalIndex) {
|
|
439
|
+
// Order has changed
|
|
440
|
+
orderChanged = true;
|
|
441
|
+
}
|
|
417
442
|
}
|
|
418
443
|
}
|
|
419
444
|
|
|
@@ -423,8 +448,20 @@ function createArrayChangeHandler(key: string) {
|
|
|
423
448
|
if (!newItem) {
|
|
424
449
|
// Has been deleted
|
|
425
450
|
items.push(...processDelete(key, original));
|
|
451
|
+
|
|
452
|
+
orderChanged = false; // ignore order changed as delete will have set it to true
|
|
426
453
|
}
|
|
427
454
|
}
|
|
455
|
+
|
|
456
|
+
if (orderChanged) {
|
|
457
|
+
// Check if order has changed
|
|
458
|
+
items.push(
|
|
459
|
+
AuditLogPatchItem.create({
|
|
460
|
+
key: getAutoEncoderKey(key),
|
|
461
|
+
type: AuditLogPatchItemType.Reordered,
|
|
462
|
+
}),
|
|
463
|
+
);
|
|
464
|
+
}
|
|
428
465
|
}
|
|
429
466
|
// Not supported
|
|
430
467
|
return items;
|
|
@@ -524,10 +561,10 @@ function createMapChangeHandler(key?: string) {
|
|
|
524
561
|
ov = null;
|
|
525
562
|
nv = null;
|
|
526
563
|
|
|
527
|
-
if (c.length === 0) {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
}
|
|
564
|
+
// if (c.length === 0) {
|
|
565
|
+
// Probably no change
|
|
566
|
+
continue;
|
|
567
|
+
// }
|
|
531
568
|
}
|
|
532
569
|
|
|
533
570
|
// Simplify change
|
|
@@ -587,32 +624,32 @@ function createMapChangeHandler(key?: string) {
|
|
|
587
624
|
};
|
|
588
625
|
}
|
|
589
626
|
|
|
590
|
-
function createUnknownChangeHandler(key: string) {
|
|
627
|
+
export function createUnknownChangeHandler(key: string) {
|
|
591
628
|
return (oldValue: unknown, value: unknown) => {
|
|
592
|
-
if (
|
|
629
|
+
if (oldValue === value) {
|
|
593
630
|
return [];
|
|
594
631
|
}
|
|
595
632
|
|
|
596
|
-
if (oldValue
|
|
597
|
-
return
|
|
633
|
+
if ((Array.isArray(oldValue) || Array.isArray(value)) && (!oldValue || Array.isArray(oldValue)) && (Array.isArray(value) || !value)) {
|
|
634
|
+
return createArrayChangeHandler(key)(oldValue, value);
|
|
598
635
|
}
|
|
599
636
|
|
|
600
|
-
if (!oldValue && getAutoEncoderValue(value)) {
|
|
637
|
+
if (!oldValue && oldValue !== 0 && getAutoEncoderValue(value, key)) {
|
|
601
638
|
// Simplify addition
|
|
602
639
|
return [
|
|
603
640
|
AuditLogPatchItem.create({
|
|
604
641
|
key: getAutoEncoderKey(key),
|
|
605
|
-
value: getAutoEncoderPutValue(value) || undefined,
|
|
642
|
+
value: getAutoEncoderPutValue(value, key) || undefined,
|
|
606
643
|
type: AuditLogPatchItemType.Added,
|
|
607
644
|
}),
|
|
608
645
|
];
|
|
609
646
|
}
|
|
610
647
|
|
|
611
|
-
if (oldValue && value === null) {
|
|
648
|
+
if ((oldValue || oldValue === 0) && (value === null || value === undefined)) {
|
|
612
649
|
return [
|
|
613
650
|
AuditLogPatchItem.create({
|
|
614
651
|
key: getAutoEncoderKey(key),
|
|
615
|
-
oldValue: getAutoEncoderPutValue(oldValue) || undefined,
|
|
652
|
+
oldValue: getAutoEncoderPutValue(oldValue, key) || undefined,
|
|
616
653
|
type: AuditLogPatchItemType.Removed,
|
|
617
654
|
}),
|
|
618
655
|
];
|
|
@@ -623,10 +660,10 @@ function createUnknownChangeHandler(key: string) {
|
|
|
623
660
|
return i;
|
|
624
661
|
});
|
|
625
662
|
|
|
626
|
-
let v = getAutoEncoderValue(value);
|
|
627
|
-
let ov = getAutoEncoderValue(oldValue);
|
|
663
|
+
let v = getAutoEncoderValue(value, key);
|
|
664
|
+
let ov = getAutoEncoderValue(oldValue, key);
|
|
628
665
|
|
|
629
|
-
if (oldValue && value && getAutoEncoderValue(value) && items.length === 0 && value instanceof AutoEncoder && value.isPatch()) {
|
|
666
|
+
if (oldValue !== undefined && oldValue !== null && value !== undefined && value !== null && getAutoEncoderValue(value, key) && items.length === 0 && value instanceof AutoEncoder && value.isPatch()) {
|
|
630
667
|
return [
|
|
631
668
|
AuditLogPatchItem.create({
|
|
632
669
|
key: getAutoEncoderKey(key),
|
|
@@ -643,10 +680,10 @@ function createUnknownChangeHandler(key: string) {
|
|
|
643
680
|
v = null;
|
|
644
681
|
ov = null;
|
|
645
682
|
|
|
646
|
-
if (items.length === 0) {
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
}
|
|
683
|
+
// if (items.length === 0) {
|
|
684
|
+
// Probably no change
|
|
685
|
+
return [];
|
|
686
|
+
// }
|
|
650
687
|
}
|
|
651
688
|
|
|
652
689
|
return [
|
|
@@ -694,7 +731,39 @@ function getExplainerForField(field: Field<any>) {
|
|
|
694
731
|
}
|
|
695
732
|
|
|
696
733
|
if (field.decoder instanceof ArrayDecoder) {
|
|
697
|
-
|
|
734
|
+
const handler = createArrayChangeHandler(field.property);
|
|
735
|
+
|
|
736
|
+
if (field.decoder.decoder instanceof EnumDecoder) {
|
|
737
|
+
// Map values to keys
|
|
738
|
+
return (oldValue: unknown, value: unknown) => {
|
|
739
|
+
const items = handler(oldValue, value);
|
|
740
|
+
|
|
741
|
+
for (const item of items) {
|
|
742
|
+
if (item.oldValue && !item.oldValue.type) {
|
|
743
|
+
item.oldValue.type = AuditLogReplacementType.Key;
|
|
744
|
+
}
|
|
745
|
+
if (item.value && !item.value.type) {
|
|
746
|
+
item.value.type = AuditLogReplacementType.Key;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
// If item.key is an array that ends with a 'value', also change it
|
|
750
|
+
if (item.key.type === AuditLogReplacementType.Array) {
|
|
751
|
+
const lastKeyItem = item.key.values[item.key.values.length - 1];
|
|
752
|
+
if (!lastKeyItem.type) {
|
|
753
|
+
lastKeyItem.type = AuditLogReplacementType.Key;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
if (!item.key.type) {
|
|
758
|
+
item.key.type = AuditLogReplacementType.Key;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
return items;
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
return handler;
|
|
698
767
|
}
|
|
699
768
|
|
|
700
769
|
if (field.decoder instanceof MapDecoder) {
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { logger } from '@simonbackx/simple-logging';
|
|
2
|
-
import { Member } from '@stamhoofd/models';
|
|
3
|
-
import { QueueHandler } from '@stamhoofd/queues';
|
|
4
|
-
|
|
5
|
-
export class MembershipHelper {
|
|
6
|
-
static async updateAll() {
|
|
7
|
-
console.log('Scheduling updateAllMemberships');
|
|
8
|
-
|
|
9
|
-
let c = 0;
|
|
10
|
-
let id: string = '';
|
|
11
|
-
const tag = 'updateAllMemberships';
|
|
12
|
-
const batch = 100;
|
|
13
|
-
|
|
14
|
-
QueueHandler.cancel(tag);
|
|
15
|
-
|
|
16
|
-
await QueueHandler.schedule(tag, async () => {
|
|
17
|
-
console.log('Starting updateAllMemberships');
|
|
18
|
-
await logger.setContext({ tags: ['silent-seed', 'seed'] }, async () => {
|
|
19
|
-
while (true) {
|
|
20
|
-
const rawMembers = await Member.where({
|
|
21
|
-
id: {
|
|
22
|
-
value: id,
|
|
23
|
-
sign: '>',
|
|
24
|
-
},
|
|
25
|
-
}, { limit: batch, sort: ['id'] });
|
|
26
|
-
|
|
27
|
-
if (rawMembers.length === 0) {
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const promises: Promise<any>[] = [];
|
|
32
|
-
|
|
33
|
-
for (const member of rawMembers) {
|
|
34
|
-
promises.push((async () => {
|
|
35
|
-
await Member.updateMembershipsForId(member.id, true);
|
|
36
|
-
c++;
|
|
37
|
-
|
|
38
|
-
if (c % 10000 === 0) {
|
|
39
|
-
process.stdout.write(c + ' members updated\n');
|
|
40
|
-
}
|
|
41
|
-
})());
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await Promise.all(promises);
|
|
45
|
-
id = rawMembers[rawMembers.length - 1].id;
|
|
46
|
-
|
|
47
|
-
if (rawMembers.length < batch) {
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|