@stamhoofd/backend 2.120.6 → 2.121.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 (61) hide show
  1. package/package.json +12 -12
  2. package/src/audit-logs/RegistrationInvitationLogger.ts +46 -0
  3. package/src/audit-logs/init.ts +2 -0
  4. package/src/crons/index.ts +2 -0
  5. package/src/crons/invoices.ts +166 -0
  6. package/src/crons/mollie-chargebacks.ts +87 -0
  7. package/src/crons.ts +47 -10
  8. package/src/email-recipient-loaders/payments.ts +84 -41
  9. package/src/endpoints/global/groups/GetGroupsCountEndpoint.ts +51 -0
  10. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +22 -3
  11. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +4 -0
  12. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsCountEndpoint.ts +45 -0
  13. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.test.ts +495 -0
  14. package/src/endpoints/global/registration-invitations/GetRegistrationInvitationsEndpoint.ts +216 -0
  15. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.test.ts +405 -0
  16. package/src/endpoints/global/registration-invitations/PatchRegistrationInvitationsEndpoint.ts +168 -0
  17. package/src/endpoints/organization/dashboard/balance-items/PatchBalanceItemsEndpoint.ts +15 -0
  18. package/src/endpoints/{global → organization/dashboard}/billing/DeactivatePackageEndpoint.ts +3 -4
  19. package/src/endpoints/organization/dashboard/billing/DeleteOrganizationMandateEndpoint.ts +62 -0
  20. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceCollectionEndpoint.ts +56 -0
  21. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedPayableBalanceEndpoint.ts +42 -19
  22. package/src/endpoints/organization/dashboard/billing/GetOrganizationMandatesEndpoint.ts +64 -0
  23. package/src/endpoints/organization/dashboard/billing/GetPackagesEndpoint.ts +11 -3
  24. package/src/endpoints/organization/dashboard/billing/OrganizationCheckoutEndpoint.ts +308 -0
  25. package/src/endpoints/organization/dashboard/billing/PatchOrganizationMandatesEndpoint.ts +94 -0
  26. package/src/endpoints/organization/dashboard/invoices/GetInvoicesEndpoint.ts +7 -0
  27. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +5 -4
  28. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +7 -2
  29. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +17 -8
  30. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +3 -3
  31. package/src/endpoints/organization/dashboard/receivable-balances/ChargeReceivableBalancesEndpoint.ts +127 -0
  32. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +13 -4
  33. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +7 -1
  34. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +1 -1
  35. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +13 -11
  36. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +14 -19
  37. package/src/helpers/AdminPermissionChecker.ts +11 -3
  38. package/src/helpers/AuthenticatedStructures.ts +94 -6
  39. package/src/helpers/FinancialSupportHelper.ts +21 -0
  40. package/src/helpers/RecordAnswerHelper.test.ts +746 -0
  41. package/src/helpers/RecordAnswerHelper.ts +116 -0
  42. package/src/helpers/StripeHelper.ts +2 -3
  43. package/src/helpers/ViesHelper.ts +7 -3
  44. package/src/seeds/1750090030-records-configuration.ts +68 -3
  45. package/src/seeds/1752848561-groups-registration-periods.ts +26 -2
  46. package/src/seeds/1779121239-default-invoice-email-template.sql +3 -0
  47. package/src/services/BalanceItemService.ts +12 -16
  48. package/src/services/InvoiceService.ts +372 -72
  49. package/src/services/MollieService.ts +537 -0
  50. package/src/services/PaymentMandateService.ts +214 -0
  51. package/src/services/PaymentService.ts +578 -222
  52. package/src/services/PlatformMembershipService.ts +1 -1
  53. package/src/services/RegistrationService.ts +66 -5
  54. package/src/services/STPackageService.ts +0 -7
  55. package/src/services/data/invoice.hbs.html +686 -0
  56. package/src/sql-filters/groups.ts +11 -1
  57. package/src/sql-filters/payments.ts +5 -0
  58. package/src/sql-filters/registration-invitations.ts +90 -0
  59. package/src/sql-sorters/registration-invitations.ts +36 -0
  60. package/vitest.config.js +1 -0
  61. package/src/endpoints/global/billing/ActivatePackagesEndpoint.ts +0 -216
@@ -175,7 +175,7 @@ export class PlatformMembershipService {
175
175
  }
176
176
  const types = platform.config.membershipTypes.filter(m => m.behaviour === PlatformMembershipTypeBehaviour.Period).map(m => m.id);
177
177
  if (types.length === 0) {
178
- if (!silent) {
178
+ if (!silent && STAMHOOFD.environment !== 'test') {
179
179
  console.warn('No membership types found for memberships');
180
180
  }
181
181
  return;
@@ -1,12 +1,12 @@
1
1
  import { ManyToOneRelation } from '@simonbackx/simple-database';
2
- import { BalanceItem, Document, Group, Member, Organization, Registration, sendEmailTemplate } from '@stamhoofd/models';
3
- import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, Recipient, Replacement, StockReservation, TranslatedString, Version } from '@stamhoofd/structures';
2
+ import { encodeObject } from '@simonbackx/simple-encoding';
3
+ import { BalanceItem, Document, Group, Member, Organization, Registration, RegistrationInvitation, sendEmailTemplate } from '@stamhoofd/models';
4
+ import { QueueHandler } from '@stamhoofd/queues';
5
+ import { AppliedRegistrationDiscount, AuditLogSource, BalanceItemRelationType, BalanceItemStatus, BalanceItemType, EmailTemplateType, GroupType, Recipient, Replacement, StockReservation, Version } from '@stamhoofd/structures';
6
+ import { Formatter } from '@stamhoofd/utility';
4
7
  import { AuditLogService } from './AuditLogService.js';
5
8
  import { GroupService } from './GroupService.js';
6
9
  import { PlatformMembershipService } from './PlatformMembershipService.js';
7
- import { QueueHandler } from '@stamhoofd/queues';
8
- import { Formatter } from '@stamhoofd/utility';
9
- import { encodeObject } from '@simonbackx/simple-encoding';
10
10
 
11
11
  export const RegistrationService = {
12
12
  /**
@@ -55,6 +55,8 @@ export const RegistrationService = {
55
55
  await registration.save();
56
56
  RegistrationService.scheduleStockUpdate(registration.id);
57
57
 
58
+ await this.handleWaitingListRegistrationAndInvitation(registration);
59
+
58
60
  await PlatformMembershipService.updateMembershipsForId(registration.memberId);
59
61
 
60
62
  if (registration.sendConfirmationEmail) {
@@ -76,6 +78,65 @@ export const RegistrationService = {
76
78
  return true;
77
79
  },
78
80
 
81
+ /**
82
+ * Delete all the invitations for the group and member linked to the registration.
83
+ * Will not throw if it fails.
84
+ * @param registration
85
+ */
86
+ async handleWaitingListRegistrationAndInvitation(registration: Registration): Promise<void> {
87
+ const group = await Group.getByID(registration.groupId);
88
+
89
+ if (!group || group.type === GroupType.WaitingList) {
90
+ // skip if waiting list (waiting lists cannot have invitations)
91
+ return;
92
+ }
93
+
94
+ // get invitation for this group and member (can only be 1)
95
+ const invitation = await RegistrationInvitation.select()
96
+ .where('groupId', registration.groupId)
97
+ .andWhere('memberId', registration.memberId)
98
+ .first(false);
99
+
100
+ const waitingListIds = new Set<string>();
101
+
102
+ if (group.waitingListId) {
103
+ // we should check if the member is on the waiting list of this group
104
+ waitingListIds.add(group.waitingListId);
105
+ }
106
+
107
+ if (invitation) {
108
+ // delete the invitation
109
+ try {
110
+ await invitation.delete();
111
+ } catch (e) {
112
+ // an error should not stop other logic (impact of an error is low)
113
+ console.error(e);
114
+ }
115
+ }
116
+
117
+ // unsubscribe from waiting list
118
+ if (group.waitingListId) {
119
+ try {
120
+ // get the registration for the waiting list (should only be 1)
121
+ const waitingListRegistration = await Registration.select()
122
+ .where('groupId', group.waitingListId)
123
+ .where('memberId', registration.memberId)
124
+ .where('deactivatedAt', null)
125
+ .whereNot('registeredAt', null)
126
+ .first(false);
127
+
128
+ if (waitingListRegistration) {
129
+ // unsubscribe for waiting list (waiting lists cannot have a price -> balance items should not be updated)
130
+ await RegistrationService.deactivate(waitingListRegistration);
131
+ await GroupService.updateOccupancy(group.waitingListId);
132
+ }
133
+ } catch (e) {
134
+ // an error should not stop other logic (impact of an error is low)
135
+ console.error(e);
136
+ }
137
+ }
138
+ },
139
+
79
140
  async getRecipients(registration: Registration, organization: Organization, group: Group) {
80
141
  const member = await Member.getByIdWithUsers(registration.memberId);
81
142
 
@@ -192,13 +192,6 @@ export class STPackageService {
192
192
  item.createdAt = now;
193
193
  item.status = BalanceItemStatus.Hidden;
194
194
 
195
- if (customer && customer.company && customer.company.address) {
196
- // Reverse charged vat applicable?
197
- if (customer.company.address.country !== Country.Belgium) {
198
- item.VATExcempt = VATExcemptReason.IntraCommunity;
199
- }
200
- }
201
-
202
195
  return item;
203
196
  }
204
197