@stamhoofd/models 2.120.6 → 2.122.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/dist/factories/GroupFactory.d.ts.map +1 -1
- package/dist/factories/GroupFactory.js +1 -1
- package/dist/factories/GroupFactory.js.map +1 -1
- package/dist/factories/OrganizationFactory.d.ts +2 -1
- package/dist/factories/OrganizationFactory.d.ts.map +1 -1
- package/dist/factories/OrganizationFactory.js +9 -1
- package/dist/factories/OrganizationFactory.js.map +1 -1
- package/dist/factories/RegistrationInvitationFactory.d.ts +15 -0
- package/dist/factories/RegistrationInvitationFactory.d.ts.map +1 -0
- package/dist/factories/RegistrationInvitationFactory.js +18 -0
- package/dist/factories/RegistrationInvitationFactory.js.map +1 -0
- package/dist/factories/STPackageFactory.js.map +1 -1
- package/dist/factories/UserFactory.d.ts.map +1 -1
- package/dist/factories/UserFactory.js +2 -2
- package/dist/factories/UserFactory.js.map +1 -1
- package/dist/factories/index.d.ts +1 -0
- package/dist/factories/index.d.ts.map +1 -1
- package/dist/factories/index.js +1 -0
- package/dist/factories/index.js.map +1 -1
- package/dist/helpers/EmailBuilder.d.ts.map +1 -1
- package/dist/helpers/EmailBuilder.js +8 -8
- package/dist/helpers/EmailBuilder.js.map +1 -1
- package/dist/helpers/Handlebars.d.ts.map +1 -1
- package/dist/helpers/Handlebars.js +10 -1
- package/dist/helpers/Handlebars.js.map +1 -1
- package/dist/helpers/InvoiceCounter.d.ts +24 -0
- package/dist/helpers/InvoiceCounter.d.ts.map +1 -0
- package/dist/helpers/InvoiceCounter.js +133 -0
- package/dist/helpers/InvoiceCounter.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/migrations/1605262045-import-postcodes.d.ts.map +1 -1
- package/dist/migrations/1605262045-import-postcodes.js +58 -24
- package/dist/migrations/1605262045-import-postcodes.js.map +1 -1
- package/dist/migrations/1605262046-import-postcodes-nl.d.ts.map +1 -1
- package/dist/migrations/1605262046-import-postcodes-nl.js +54 -17
- package/dist/migrations/1605262046-import-postcodes-nl.js.map +1 -1
- package/dist/migrations/1719567881-organization-periodId.sql +2 -0
- package/dist/migrations/1719567882-groups-periodId.sql +2 -0
- package/dist/migrations/1720080975-convert-charset.d.ts +4 -0
- package/dist/migrations/1720080975-convert-charset.d.ts.map +1 -0
- package/dist/migrations/1720080975-convert-charset.js +26 -0
- package/dist/migrations/1720080975-convert-charset.js.map +1 -0
- package/dist/migrations/1720080976-convert-charset-leads.d.ts.map +1 -1
- package/dist/migrations/1720080976-convert-charset-leads.js +11 -10
- package/dist/migrations/1720080976-convert-charset-leads.js.map +1 -1
- package/dist/migrations/1721400546-users-memberId.sql +2 -0
- package/dist/migrations/1722269236-group-waitinglist-id.sql +2 -1
- package/dist/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
- package/dist/migrations/1722525787-depending-balance-item.sql +2 -0
- package/dist/migrations/1722963554-registration-group-price-and-options.sql +1 -1
- package/dist/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
- package/dist/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
- package/dist/migrations/1733317910-paying-organization-id-fk.sql +2 -0
- package/dist/migrations/1733504881-negative-invoice-id.sql +6 -0
- package/dist/migrations/1733994455-balance-item-status-open.d.ts +4 -0
- package/dist/migrations/1733994455-balance-item-status-open.d.ts.map +1 -0
- package/dist/migrations/1733994455-balance-item-status-open.js +28 -0
- package/dist/migrations/1733994455-balance-item-status-open.js.map +1 -0
- package/dist/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
- package/dist/migrations/1763216320-bigint-balance-items.sql +5 -0
- package/dist/migrations/1763216320-bigint-orders.sql +2 -0
- package/dist/migrations/1763216320-bigint-payments.sql +2 -0
- package/dist/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
- package/dist/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
- package/dist/migrations/1769087809-payments-invoice-id.sql +2 -0
- package/dist/migrations/1772033555-balance-item-package-id.sql +2 -0
- package/dist/migrations/1776873089-create-registration-invitations-table.sql +13 -0
- package/dist/migrations/1778657958-payments-create-mandate.sql +2 -0
- package/dist/migrations/1778657959-payments-mandate-id.sql +2 -0
- package/dist/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
- package/dist/migrations/1778950642-price-invoiced.sql +2 -0
- package/dist/migrations/1779443446-transfer-fees.sql +3 -0
- package/dist/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
- package/dist/migrations/1779968328-payments-admin-user-id.sql +5 -0
- package/dist/migrations/1779970611-payments-refunded-amount.sql +2 -0
- package/dist/migrations/1779972640-balance-items-failed-at.sql +2 -0
- package/dist/migrations/1780328285-document-template-locked.sql +2 -0
- package/dist/migrations/1780328286-document-locked.sql +2 -0
- package/dist/migrations/1780412083-documents-set-locked.d.ts +4 -0
- package/dist/migrations/1780412083-documents-set-locked.d.ts.map +1 -0
- package/dist/migrations/1780412083-documents-set-locked.js +14 -0
- package/dist/migrations/1780412083-documents-set-locked.js.map +1 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.d.ts +4 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.d.ts.map +1 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.js +44 -0
- package/dist/migrations/1780928401-v1-groups-migration-data.js.map +1 -0
- package/dist/models/BalanceItem.d.ts +14 -1
- package/dist/models/BalanceItem.d.ts.map +1 -1
- package/dist/models/BalanceItem.js +91 -41
- package/dist/models/BalanceItem.js.map +1 -1
- package/dist/models/CachedBalance.d.ts +6 -1
- package/dist/models/CachedBalance.d.ts.map +1 -1
- package/dist/models/CachedBalance.js +3 -2
- package/dist/models/CachedBalance.js.map +1 -1
- package/dist/models/Document.d.ts +4 -0
- package/dist/models/Document.d.ts.map +1 -1
- package/dist/models/Document.js +26 -3
- package/dist/models/Document.js.map +1 -1
- package/dist/models/DocumentTemplate.d.ts +4 -0
- package/dist/models/DocumentTemplate.d.ts.map +1 -1
- package/dist/models/DocumentTemplate.js +37 -1
- package/dist/models/DocumentTemplate.js.map +1 -1
- package/dist/models/Email.d.ts.map +1 -1
- package/dist/models/Email.js +1 -1
- package/dist/models/Email.js.map +1 -1
- package/dist/models/EmailVerificationCode.d.ts.map +1 -1
- package/dist/models/EmailVerificationCode.js +3 -13
- package/dist/models/EmailVerificationCode.js.map +1 -1
- package/dist/models/Event.d.ts +2 -1
- package/dist/models/Event.d.ts.map +1 -1
- package/dist/models/Event.js +3 -0
- package/dist/models/Event.js.map +1 -1
- package/dist/models/EventNotification.d.ts.map +1 -1
- package/dist/models/EventNotification.js +5 -5
- package/dist/models/EventNotification.js.map +1 -1
- package/dist/models/Group.d.ts +4 -0
- package/dist/models/Group.d.ts.map +1 -1
- package/dist/models/Group.js +17 -0
- package/dist/models/Group.js.map +1 -1
- package/dist/models/Invoice.d.ts +1 -0
- package/dist/models/Invoice.d.ts.map +1 -1
- package/dist/models/Invoice.js +8 -8
- package/dist/models/Invoice.js.map +1 -1
- package/dist/models/MemberPlatformMembership.d.ts.map +1 -1
- package/dist/models/MemberPlatformMembership.js +9 -0
- package/dist/models/MemberPlatformMembership.js.map +1 -1
- package/dist/models/MollieToken.d.ts +4 -8
- package/dist/models/MollieToken.d.ts.map +1 -1
- package/dist/models/MollieToken.js +37 -90
- package/dist/models/MollieToken.js.map +1 -1
- package/dist/models/Order.d.ts.map +1 -1
- package/dist/models/Order.js +1 -0
- package/dist/models/Order.js.map +1 -1
- package/dist/models/Organization.d.ts +30 -23
- package/dist/models/Organization.d.ts.map +1 -1
- package/dist/models/Organization.js +113 -61
- package/dist/models/Organization.js.map +1 -1
- package/dist/models/PasswordToken.d.ts +5 -1
- package/dist/models/PasswordToken.d.ts.map +1 -1
- package/dist/models/PasswordToken.js +18 -17
- package/dist/models/PasswordToken.js.map +1 -1
- package/dist/models/Payment.d.ts +35 -3
- package/dist/models/Payment.d.ts.map +1 -1
- package/dist/models/Payment.js +66 -3
- package/dist/models/Payment.js.map +1 -1
- package/dist/models/Registration.d.ts +1 -0
- package/dist/models/Registration.d.ts.map +1 -1
- package/dist/models/Registration.js +4 -3
- package/dist/models/Registration.js.map +1 -1
- package/dist/models/RegistrationInvitation.d.ts +14 -0
- package/dist/models/RegistrationInvitation.d.ts.map +1 -0
- package/dist/models/RegistrationInvitation.js +45 -0
- package/dist/models/RegistrationInvitation.js.map +1 -0
- package/dist/models/STCredit.d.ts +4 -0
- package/dist/models/STCredit.d.ts.map +1 -1
- package/dist/models/STCredit.js +28 -0
- package/dist/models/STCredit.js.map +1 -1
- package/dist/models/STInvoice.d.ts +7 -1
- package/dist/models/STInvoice.d.ts.map +1 -1
- package/dist/models/STInvoice.js +9 -0
- package/dist/models/STInvoice.js.map +1 -1
- package/dist/models/STPackage.d.ts +4 -0
- package/dist/models/STPackage.d.ts.map +1 -1
- package/dist/models/STPackage.js +12 -1
- package/dist/models/STPackage.js.map +1 -1
- package/dist/models/UsedRegisterCode.d.ts +9 -0
- package/dist/models/UsedRegisterCode.d.ts.map +1 -1
- package/dist/models/UsedRegisterCode.js +31 -0
- package/dist/models/UsedRegisterCode.js.map +1 -1
- package/dist/models/User.d.ts +1 -1
- package/dist/models/User.d.ts.map +1 -1
- package/dist/models/User.js +1 -1
- package/dist/models/User.js.map +1 -1
- package/dist/models/_relations.js +25 -0
- package/dist/models/_relations.js.map +1 -1
- package/dist/models/addresses/City.d.ts +4 -4
- package/dist/models/addresses/City.d.ts.map +1 -1
- package/dist/models/addresses/City.js +6 -6
- package/dist/models/addresses/City.js.map +1 -1
- package/dist/models/addresses/PostalCode.d.ts +2 -2
- package/dist/models/addresses/PostalCode.d.ts.map +1 -1
- package/dist/models/addresses/PostalCode.js +4 -3
- package/dist/models/addresses/PostalCode.js.map +1 -1
- package/dist/models/addresses/Street.d.ts +3 -3
- package/dist/models/addresses/Street.d.ts.map +1 -1
- package/dist/models/addresses/Street.js +4 -4
- package/dist/models/addresses/Street.js.map +1 -1
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.d.ts.map +1 -1
- package/dist/models/index.js +2 -0
- package/dist/models/index.js.map +1 -1
- package/dist/models/v1GroupMigrationData.d.ts +22 -0
- package/dist/models/v1GroupMigrationData.d.ts.map +1 -0
- package/dist/models/v1GroupMigrationData.js +48 -0
- package/dist/models/v1GroupMigrationData.js.map +1 -0
- package/package.json +41 -13
- package/src/factories/GroupFactory.ts +4 -6
- package/src/factories/OrganizationFactory.ts +12 -4
- package/src/factories/RegistrationInvitationFactory.ts +24 -0
- package/src/factories/STPackageFactory.ts +2 -2
- package/src/factories/UserFactory.ts +4 -5
- package/src/factories/index.ts +1 -0
- package/src/helpers/EmailBuilder.ts +19 -28
- package/src/helpers/Handlebars.ts +10 -1
- package/src/helpers/InvoiceCounter.test.ts +220 -0
- package/src/helpers/InvoiceCounter.ts +162 -0
- package/src/index.ts +0 -1
- package/src/migrations/1605262045-import-postcodes.ts +62 -25
- package/src/migrations/1605262046-import-postcodes-nl.ts +58 -17
- package/src/migrations/1719567881-organization-periodId.sql +2 -0
- package/src/migrations/1719567882-groups-periodId.sql +2 -0
- package/src/migrations/1720080975-convert-charset.ts +34 -0
- package/src/migrations/1720080976-convert-charset-leads.ts +16 -13
- package/src/migrations/1721400546-users-memberId.sql +2 -0
- package/src/migrations/1722269236-group-waitinglist-id.sql +2 -1
- package/src/migrations/1722525785-balance-item-paying-organization-id.sql +2 -0
- package/src/migrations/1722525787-depending-balance-item.sql +2 -0
- package/src/migrations/1722963554-registration-group-price-and-options.sql +1 -1
- package/src/migrations/1723652797-payments-paying-organization-id-fk.sql +2 -0
- package/src/migrations/1733317908-added-missing-organization-fk-on-registrations.sql +2 -0
- package/src/migrations/1733317910-paying-organization-id-fk.sql +2 -0
- package/src/migrations/1733504881-negative-invoice-id.sql +6 -0
- package/src/migrations/1733994455-balance-item-status-open.ts +30 -0
- package/src/migrations/1763216320-bigint-balance-item-payments.sql +2 -0
- package/src/migrations/1763216320-bigint-balance-items.sql +5 -0
- package/src/migrations/1763216320-bigint-orders.sql +2 -0
- package/src/migrations/1763216320-bigint-payments.sql +2 -0
- package/src/migrations/1763216332-bigint-balance-item-price-total.sql +2 -0
- package/src/migrations/1769087808-corrected-invoice-user-agent.sql +2 -0
- package/src/migrations/1769087809-payments-invoice-id.sql +2 -0
- package/src/migrations/1772033555-balance-item-package-id.sql +2 -0
- package/src/migrations/1776873089-create-registration-invitations-table.sql +13 -0
- package/src/migrations/1778657958-payments-create-mandate.sql +2 -0
- package/src/migrations/1778657959-payments-mandate-id.sql +2 -0
- package/src/migrations/1778796615-payments-reversing-payment-id.sql +5 -0
- package/src/migrations/1778950642-price-invoiced.sql +2 -0
- package/src/migrations/1779443446-transfer-fees.sql +3 -0
- package/src/migrations/1779709174-used-register-code-balance-item-id.sql +5 -0
- package/src/migrations/1779968328-payments-admin-user-id.sql +5 -0
- package/src/migrations/1779970611-payments-refunded-amount.sql +2 -0
- package/src/migrations/1779972640-balance-items-failed-at.sql +2 -0
- package/src/migrations/1780328285-document-template-locked.sql +2 -0
- package/src/migrations/1780328286-document-locked.sql +2 -0
- package/src/migrations/1780412083-documents-set-locked.ts +18 -0
- package/src/migrations/1780928401-v1-groups-migration-data.ts +50 -0
- package/src/models/BalanceItem.ts +98 -43
- package/src/models/CachedBalance.test.ts +46 -46
- package/src/models/CachedBalance.ts +7 -7
- package/src/models/Document.ts +34 -13
- package/src/models/DocumentTemplate.ts +56 -17
- package/src/models/Email.test.ts +3 -3
- package/src/models/Email.ts +28 -49
- package/src/models/EmailVerificationCode.ts +8 -22
- package/src/models/Event.ts +6 -4
- package/src/models/EventNotification.ts +6 -6
- package/src/models/Group.ts +24 -3
- package/src/models/Invoice.ts +10 -9
- package/src/models/MemberPlatformMembership.test.ts +70 -0
- package/src/models/MemberPlatformMembership.ts +16 -12
- package/src/models/MollieToken.ts +42 -102
- package/src/models/Order.ts +14 -26
- package/src/models/Organization.ts +143 -86
- package/src/models/PasswordToken.ts +21 -21
- package/src/models/Payment.ts +61 -4
- package/src/models/Registration.ts +6 -5
- package/src/models/RegistrationInvitation.ts +40 -0
- package/src/models/STCredit.ts +32 -0
- package/src/models/STInvoice.ts +11 -5
- package/src/models/STPackage.ts +19 -14
- package/src/models/UsedRegisterCode.ts +34 -0
- package/src/models/User.ts +6 -7
- package/src/models/_relations.ts +29 -0
- package/src/models/addresses/City.ts +8 -6
- package/src/models/addresses/PostalCode.test.ts +1 -0
- package/src/models/addresses/PostalCode.ts +5 -3
- package/src/models/addresses/Street.ts +6 -4
- package/src/models/index.ts +3 -0
- package/src/models/v1GroupMigrationData.ts +43 -0
- package/dist/helpers/MemberMerger.d.ts +0 -14
- package/dist/helpers/MemberMerger.d.ts.map +0 -1
- package/dist/helpers/MemberMerger.js +0 -364
- package/dist/helpers/MemberMerger.js.map +0 -1
- package/dist/migrations/1720080975-convert-charset.sql +0 -85
- package/dist/migrations/1723202126-member-number-index.sql +0 -2
- package/dist/models/OneTimeToken.d.ts +0 -38
- package/dist/models/OneTimeToken.d.ts.map +0 -1
- package/dist/models/OneTimeToken.js +0 -125
- package/dist/models/OneTimeToken.js.map +0 -1
- package/src/helpers/MemberMerger.test.ts +0 -782
- package/src/helpers/MemberMerger.ts +0 -577
- package/src/migrations/1720080975-convert-charset.sql +0 -85
- package/src/migrations/1723202126-member-number-index.sql +0 -2
- package/src/models/OneTimeToken.ts +0 -133
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { column } from '@simonbackx/simple-database';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PlainObject } from '@simonbackx/simple-encoding';
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
4
|
import { QueryableModel } from '@stamhoofd/sql';
|
|
5
|
-
import { MollieOnboarding, MollieProfile, MollieStatus } from '@stamhoofd/structures';
|
|
6
5
|
import type { IncomingMessage } from 'http';
|
|
7
6
|
import https from 'https';
|
|
8
7
|
|
|
@@ -12,9 +11,17 @@ function sleep(ms: number) {
|
|
|
12
11
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
13
12
|
}
|
|
14
13
|
|
|
14
|
+
export class MollieError extends Error {
|
|
15
|
+
body: PlainObject
|
|
16
|
+
}
|
|
17
|
+
|
|
15
18
|
export class MollieToken extends QueryableModel {
|
|
16
19
|
static table = 'mollie_tokens';
|
|
17
20
|
|
|
21
|
+
get id() {
|
|
22
|
+
return this.organizationId
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
@column({ primary: true, type: 'string' })
|
|
19
26
|
organizationId!: string;
|
|
20
27
|
|
|
@@ -184,7 +191,9 @@ export class MollieToken extends QueryableModel {
|
|
|
184
191
|
|
|
185
192
|
if (response.statusCode < 200 || response.statusCode >= 300) {
|
|
186
193
|
console.error(body);
|
|
187
|
-
|
|
194
|
+
const e = new MollieError(response.statusCode + ' ' + response.statusMessage);
|
|
195
|
+
e.body = json;
|
|
196
|
+
reject(e);
|
|
188
197
|
return;
|
|
189
198
|
}
|
|
190
199
|
|
|
@@ -223,23 +232,38 @@ export class MollieToken extends QueryableModel {
|
|
|
223
232
|
* Refresh the token itself, without generating a new token. Everyone who had the token has a new token now
|
|
224
233
|
*/
|
|
225
234
|
async refresh(): Promise<void> {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
235
|
+
try {
|
|
236
|
+
const data = await MollieToken.request('POST', '/oauth2/tokens', {
|
|
237
|
+
grant_type: 'refresh_token',
|
|
238
|
+
refresh_token: this.refreshToken,
|
|
239
|
+
}, 'urlencoded');
|
|
230
240
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
+
if (data && data.access_token && data.refresh_token) {
|
|
242
|
+
// Delete token if exisitng
|
|
243
|
+
this.refreshToken = data.refresh_token;
|
|
244
|
+
this.accessToken = data.access_token;
|
|
245
|
+
this.expiresOn = new Date(new Date().getTime() + 3600 * 1000 - 60 * 1000);
|
|
246
|
+
await this.save();
|
|
247
|
+
|
|
248
|
+
// Update shared tokens if this object was fetched directly
|
|
249
|
+
MollieToken.knownTokens.set(this.organizationId, this);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
throw new SimpleError({ code: '', message: 'Something went wrong in the response' });
|
|
253
|
+
} catch (e) {
|
|
254
|
+
if (e instanceof MollieError) {
|
|
255
|
+
if (e.body && typeof e.body === 'object' && 'error' in e.body && e.body.error === 'invalid_grant') {
|
|
256
|
+
// Refresh token not valid.
|
|
257
|
+
console.error('Deleting Mollie Token because invalid refresh token')
|
|
258
|
+
await this.delete()
|
|
259
|
+
|
|
260
|
+
// Still throw
|
|
261
|
+
throw e;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
throw e;
|
|
241
265
|
}
|
|
242
|
-
|
|
266
|
+
|
|
243
267
|
}
|
|
244
268
|
|
|
245
269
|
/**
|
|
@@ -279,97 +303,13 @@ export class MollieToken extends QueryableModel {
|
|
|
279
303
|
|
|
280
304
|
this.knownTokens.set(organization.id, token);
|
|
281
305
|
|
|
282
|
-
organization.privateMeta.mollieOnboarding = await token.getOnboardingStatus();
|
|
283
|
-
await token.setup(organization);
|
|
284
|
-
|
|
285
|
-
await organization.save();
|
|
286
306
|
return token;
|
|
287
307
|
}
|
|
288
308
|
throw new SimpleError({ code: '', message: 'Something went wrong in the response' });
|
|
289
309
|
}
|
|
290
310
|
|
|
291
|
-
async getOnboardingStatus() {
|
|
292
|
-
try {
|
|
293
|
-
const response = await this.authRequest('GET', '/v2/onboarding/me');
|
|
294
|
-
return MollieOnboarding.create({
|
|
295
|
-
canReceivePayments: !!response.canReceivePayments,
|
|
296
|
-
canReceiveSettlements: !!response.canReceiveSettlements,
|
|
297
|
-
status: response.status === 'needs-data' ? MollieStatus.NeedsData : (response.status === 'in-review' ? MollieStatus.InReview : (MollieStatus.Completed)),
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
catch (e) {
|
|
301
|
-
console.error('Error when requesting Mollie onboarding status:');
|
|
302
|
-
console.error(e);
|
|
303
|
-
return null;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
async getProfiles(): Promise<MollieProfile[]> {
|
|
308
|
-
try {
|
|
309
|
-
const response = await this.authRequest('GET', '/v2/profiles?limit=250');
|
|
310
|
-
const profiles = response._embedded.profiles as PartialWithoutMethods<MollieProfile>[];
|
|
311
|
-
return profiles.map(p => MollieProfile.create(p));
|
|
312
|
-
}
|
|
313
|
-
catch (e) {
|
|
314
|
-
console.error('Failed to parse mollie profiles', e);
|
|
315
|
-
return [];
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
async getProfileId(website?: string): Promise<string | null> {
|
|
320
|
-
const response = await this.authRequest('GET', '/v2/profiles?limit=250');
|
|
321
|
-
const profiles = response._embedded.profiles;
|
|
322
|
-
|
|
323
|
-
// Search profile with Stamhoofd as name
|
|
324
|
-
if (website) {
|
|
325
|
-
for (const profile of profiles) {
|
|
326
|
-
if (profile.website.toLowerCase().includes(website)) {
|
|
327
|
-
return profile.id;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
// Search profile with Stamhoofd as name
|
|
333
|
-
for (const profile of profiles) {
|
|
334
|
-
if (profile.name.toLowerCase().includes('stamhoofd')) {
|
|
335
|
-
return profile.id;
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
return response._embedded.profiles[0]?.id ?? null;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
311
|
async getOnboardingLink() {
|
|
343
312
|
const response = await this.authRequest('GET', '/v2/onboarding/me');
|
|
344
313
|
return response._links.dashboard.href ?? '';
|
|
345
314
|
}
|
|
346
|
-
|
|
347
|
-
/**
|
|
348
|
-
* Set initial onboarding values + enable bancontact
|
|
349
|
-
*/
|
|
350
|
-
async setup(organization: Organization) {
|
|
351
|
-
// Submit onboarding data
|
|
352
|
-
|
|
353
|
-
if (organization.privateMeta.mollieOnboarding && organization.privateMeta.mollieOnboarding.status == MollieStatus.NeedsData) {
|
|
354
|
-
await this.authRequest('POST', '/v2/onboarding/me', {
|
|
355
|
-
organization: {
|
|
356
|
-
name: organization.name,
|
|
357
|
-
address: {
|
|
358
|
-
streetAndNumber: organization.address.street + ' ' + organization.address.number,
|
|
359
|
-
postalCode: organization.address.postalCode,
|
|
360
|
-
city: organization.address.city,
|
|
361
|
-
country: organization.address.country,
|
|
362
|
-
},
|
|
363
|
-
|
|
364
|
-
vatRegulation: 'shifted',
|
|
365
|
-
},
|
|
366
|
-
profile: {
|
|
367
|
-
name: organization.name + ' - Stamhoofd',
|
|
368
|
-
// url: "https://"+organization.getHost(),
|
|
369
|
-
description: $t(`%x1`),
|
|
370
|
-
categoryCode: 8398,
|
|
371
|
-
},
|
|
372
|
-
});
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
315
|
}
|
package/src/models/Order.ts
CHANGED
|
@@ -286,8 +286,7 @@ export class Order extends QueryableModel {
|
|
|
286
286
|
if (webshop) {
|
|
287
287
|
await this.setRelation(Order.webshop, webshop).updateTickets();
|
|
288
288
|
}
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
289
|
+
} else {
|
|
291
290
|
this.markUpdated();
|
|
292
291
|
await this.save();
|
|
293
292
|
}
|
|
@@ -427,8 +426,7 @@ export class Order extends QueryableModel {
|
|
|
427
426
|
// Remove any reserved stock
|
|
428
427
|
const updated = Order.updateTimeSlotStock(timeSlot, this.data, false);
|
|
429
428
|
changed = changed || updated;
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
429
|
+
} else {
|
|
432
430
|
this.data.reservedOrder = false;
|
|
433
431
|
this.data.reservedPersons = 0;
|
|
434
432
|
changed = true;
|
|
@@ -442,8 +440,7 @@ export class Order extends QueryableModel {
|
|
|
442
440
|
if (timeSlot) {
|
|
443
441
|
const updated = Order.updateTimeSlotStock(timeSlot, this.data, add);
|
|
444
442
|
changed = changed || updated;
|
|
445
|
-
}
|
|
446
|
-
else {
|
|
443
|
+
} else {
|
|
447
444
|
console.error('Missing timeslot ' + s.id + ' in webshop ' + this.webshopId);
|
|
448
445
|
}
|
|
449
446
|
}
|
|
@@ -456,6 +453,7 @@ export class Order extends QueryableModel {
|
|
|
456
453
|
if (previousData !== null) {
|
|
457
454
|
// Already removed
|
|
458
455
|
item.reservedSeats = [];
|
|
456
|
+
// eslint-disable-next-line no-useless-assignment
|
|
459
457
|
changed = true;
|
|
460
458
|
}
|
|
461
459
|
|
|
@@ -491,8 +489,7 @@ export class Order extends QueryableModel {
|
|
|
491
489
|
code.reserved = false;
|
|
492
490
|
discountCodeUsageMap.set(code.id, (discountCodeUsageMap.get(code.id) ?? 0) - 1);
|
|
493
491
|
changed = true;
|
|
494
|
-
}
|
|
495
|
-
else if (!code.reserved && add) {
|
|
492
|
+
} else if (!code.reserved && add) {
|
|
496
493
|
code.reserved = true;
|
|
497
494
|
discountCodeUsageMap.set(code.id, (discountCodeUsageMap.get(code.id) ?? 0) + 1);
|
|
498
495
|
changed = true;
|
|
@@ -599,8 +596,7 @@ export class Order extends QueryableModel {
|
|
|
599
596
|
ticketMap.set(item.product.id, offset + item.amount);
|
|
600
597
|
}
|
|
601
598
|
}
|
|
602
|
-
}
|
|
603
|
-
else {
|
|
599
|
+
} else {
|
|
604
600
|
// Create a shared ticket for the whole order
|
|
605
601
|
const ticket = new Ticket();
|
|
606
602
|
ticket.orderId = this.id;
|
|
@@ -752,8 +748,7 @@ export class Order extends QueryableModel {
|
|
|
752
748
|
// Needs to happen before validation, because we can include the tickets in the validation that way
|
|
753
749
|
if (this.validAt === null) {
|
|
754
750
|
await this.setRelation(Order.webshop, webshop).markValid(payment, tickets);
|
|
755
|
-
}
|
|
756
|
-
else {
|
|
751
|
+
} else {
|
|
757
752
|
this.markUpdated();
|
|
758
753
|
await this.save();
|
|
759
754
|
|
|
@@ -764,8 +759,7 @@ export class Order extends QueryableModel {
|
|
|
764
759
|
if (this.data.customer.email.length > 0) {
|
|
765
760
|
if (didCreateTickets) {
|
|
766
761
|
await this.setRelation(Order.webshop, webshop).sendTickets();
|
|
767
|
-
}
|
|
768
|
-
else {
|
|
762
|
+
} else {
|
|
769
763
|
if (payment && payment.method === PaymentMethod.Transfer) {
|
|
770
764
|
await this.setRelation(Order.webshop, webshop).sendPaidMail();
|
|
771
765
|
}
|
|
@@ -976,40 +970,34 @@ export class Order extends QueryableModel {
|
|
|
976
970
|
await this.sendEmailTemplate({
|
|
977
971
|
type: EmailTemplateType.TicketsConfirmationPOS,
|
|
978
972
|
});
|
|
979
|
-
}
|
|
980
|
-
else {
|
|
973
|
+
} else {
|
|
981
974
|
await this.sendEmailTemplate({
|
|
982
975
|
type: EmailTemplateType.TicketsConfirmation,
|
|
983
976
|
});
|
|
984
977
|
}
|
|
985
|
-
}
|
|
986
|
-
else {
|
|
978
|
+
} else {
|
|
987
979
|
if (this.webshop.meta.ticketType === WebshopTicketType.None) {
|
|
988
980
|
if (payment && payment.method === PaymentMethod.Transfer) {
|
|
989
981
|
// Also send a copy
|
|
990
982
|
await this.sendEmailTemplate({
|
|
991
983
|
type: EmailTemplateType.OrderConfirmationTransfer,
|
|
992
984
|
});
|
|
993
|
-
}
|
|
994
|
-
else if (payment && payment.method === PaymentMethod.PointOfSale) {
|
|
985
|
+
} else if (payment && payment.method === PaymentMethod.PointOfSale) {
|
|
995
986
|
await this.sendEmailTemplate({
|
|
996
987
|
type: EmailTemplateType.OrderConfirmationPOS,
|
|
997
988
|
});
|
|
998
|
-
}
|
|
999
|
-
else {
|
|
989
|
+
} else {
|
|
1000
990
|
// Also send a copy
|
|
1001
991
|
await this.sendEmailTemplate({
|
|
1002
992
|
type: EmailTemplateType.OrderConfirmationOnline,
|
|
1003
993
|
});
|
|
1004
994
|
}
|
|
1005
|
-
}
|
|
1006
|
-
else {
|
|
995
|
+
} else {
|
|
1007
996
|
if (payment && payment.method === PaymentMethod.Transfer) {
|
|
1008
997
|
await this.sendEmailTemplate({
|
|
1009
998
|
type: EmailTemplateType.TicketsConfirmationTransfer,
|
|
1010
999
|
});
|
|
1011
|
-
}
|
|
1012
|
-
else {
|
|
1000
|
+
} else {
|
|
1013
1001
|
console.error('Unexpected missing tickets for order where tickets are expected');
|
|
1014
1002
|
}
|
|
1015
1003
|
}
|
|
@@ -6,17 +6,21 @@ import { I18n } from '@stamhoofd/backend-i18n/I18n';
|
|
|
6
6
|
import type { EmailInterfaceRecipient } from '@stamhoofd/email';
|
|
7
7
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
8
8
|
import { QueryableModel, SQL } from '@stamhoofd/sql';
|
|
9
|
-
import type { OrganizationEmail, PrivatePaymentConfiguration } from '@stamhoofd/structures';
|
|
10
|
-
import { Address, appToUri, DNSRecordStatus, EmailTemplateType, OrganizationMetaData, OrganizationPrivateMetaData, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, Recipient, Replacement, STPackageType, TransferSettings } from '@stamhoofd/structures';
|
|
11
|
-
import {
|
|
9
|
+
import type { AppType, OrganizationEmail, PrivatePaymentConfiguration } from '@stamhoofd/structures';
|
|
10
|
+
import { AccessRight, Address, appToUri, Company, DNSRecordStatus, EmailTemplateType, getAppHost, GroupType, OrganizationMetaData, OrganizationPrivateMetaData, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, Recipient, Replacement, STPackageType, TransferSettings } from '@stamhoofd/structures';
|
|
11
|
+
import type { PaymentMandate } from '@stamhoofd/structures/PaymentMandate.js';
|
|
12
|
+
import { Country } from '@stamhoofd/types/Country';
|
|
13
|
+
import { Language } from '@stamhoofd/types/Language';
|
|
14
|
+
import { Formatter, Sorter } from '@stamhoofd/utility';
|
|
12
15
|
import { v4 as uuidv4 } from 'uuid';
|
|
13
16
|
import { validateDNSRecords } from '../helpers/DNSValidator.js';
|
|
14
17
|
import { OrganizationServerMetaData } from '../structures/OrganizationServerMetaData.js';
|
|
15
18
|
import { Group } from './Group.js';
|
|
16
19
|
import { OrganizationRegistrationPeriod } from './OrganizationRegistrationPeriod.js';
|
|
20
|
+
import { Registration } from './Registration.js';
|
|
17
21
|
import { StripeAccount } from './StripeAccount.js';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
22
|
+
import { Token } from './Token.js';
|
|
23
|
+
import type { User } from './User.js';
|
|
20
24
|
|
|
21
25
|
export class Organization extends QueryableModel {
|
|
22
26
|
static table = 'organizations';
|
|
@@ -209,53 +213,12 @@ export class Organization extends QueryableModel {
|
|
|
209
213
|
return organization;
|
|
210
214
|
}
|
|
211
215
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
*/
|
|
215
|
-
getRegistrationHost(i18n?: { language: Language; locale: string }): string {
|
|
216
|
-
if (this.registerDomain) {
|
|
217
|
-
let d = this.registerDomain;
|
|
218
|
-
|
|
219
|
-
if (i18n && i18n.language !== this.i18n.language) {
|
|
220
|
-
d += '/' + i18n.language;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return d;
|
|
224
|
-
}
|
|
225
|
-
return this.getDefaultRegistrationHost(i18n);
|
|
216
|
+
getDashboardHost(i18n?: { language: Language; locale: string }): string {
|
|
217
|
+
return getAppHost('dashboard', this, true, i18n);
|
|
226
218
|
}
|
|
227
219
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
return STAMHOOFD.domains.dashboard + '/' + (i18n?.locale ?? this.i18n.locale) + '/' + appToUri('registration') + '/' + this.uri;
|
|
231
|
-
}
|
|
232
|
-
let defaultDomain = STAMHOOFD.domains.registration[this.address.country] ?? STAMHOOFD.domains.registration[''];
|
|
233
|
-
|
|
234
|
-
if (i18n && i18n.language !== this.i18n.language) {
|
|
235
|
-
defaultDomain += '/' + i18n.language;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
return this.uri + '.' + defaultDomain;
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
get registerUrl() {
|
|
242
|
-
return 'https://' + this.getRegistrationHost();
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* @deprecated
|
|
247
|
-
* use getRegistrationHost
|
|
248
|
-
*/
|
|
249
|
-
getHost(i18n?: I18n): string {
|
|
250
|
-
return this.getRegistrationHost(i18n);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* @deprecated
|
|
255
|
-
* Use getDefaultRegistrationHost
|
|
256
|
-
*/
|
|
257
|
-
getDefaultHost(i18n?: I18n): string {
|
|
258
|
-
return this.getDefaultRegistrationHost(i18n);
|
|
220
|
+
get registerUrl(): string {
|
|
221
|
+
return 'https://' + getAppHost('registration', this, false);
|
|
259
222
|
}
|
|
260
223
|
|
|
261
224
|
get marketingDomain(): string {
|
|
@@ -297,8 +260,7 @@ export class Organization extends QueryableModel {
|
|
|
297
260
|
await created.save();
|
|
298
261
|
return created;
|
|
299
262
|
});
|
|
300
|
-
}
|
|
301
|
-
else {
|
|
263
|
+
} else {
|
|
302
264
|
oPeriod = oPeriods[0];
|
|
303
265
|
}
|
|
304
266
|
|
|
@@ -361,8 +323,7 @@ export class Organization extends QueryableModel {
|
|
|
361
323
|
|
|
362
324
|
console.log('Did set register domain for ' + this.id + ' to ' + organization.registerDomain);
|
|
363
325
|
}
|
|
364
|
-
}
|
|
365
|
-
else {
|
|
326
|
+
} else {
|
|
366
327
|
// Clear register domain
|
|
367
328
|
if (organization.registerDomain) {
|
|
368
329
|
// We need to clear it, to prevent sending e-mails with invalid links
|
|
@@ -400,8 +361,7 @@ export class Organization extends QueryableModel {
|
|
|
400
361
|
type: EmailTemplateType.OrganizationStableDNS,
|
|
401
362
|
bcc: true,
|
|
402
363
|
});
|
|
403
|
-
}
|
|
404
|
-
else if (!wasActive && this.privateMeta.mailDomainActive && (!didSendDomainSetupMail || didSendWarning) && !organization.serverMeta.isDNSUnstable) {
|
|
364
|
+
} else if (!wasActive && this.privateMeta.mailDomainActive && (!didSendDomainSetupMail || didSendWarning) && !organization.serverMeta.isDNSUnstable) {
|
|
405
365
|
organization.serverMeta.didSendDomainSetupMail = true;
|
|
406
366
|
await organization.save();
|
|
407
367
|
|
|
@@ -409,15 +369,13 @@ export class Organization extends QueryableModel {
|
|
|
409
369
|
await this.sendEmailTemplate({
|
|
410
370
|
type: EmailTemplateType.OrganizationDNSSetupComplete,
|
|
411
371
|
});
|
|
412
|
-
}
|
|
413
|
-
else {
|
|
372
|
+
} else {
|
|
414
373
|
await this.sendEmailTemplate({
|
|
415
374
|
type: EmailTemplateType.OrganizationValidDNS,
|
|
416
375
|
});
|
|
417
376
|
}
|
|
418
377
|
}
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
378
|
+
} else {
|
|
421
379
|
// DNS settings gone broken
|
|
422
380
|
if (organization.privateMeta.mailDomain) {
|
|
423
381
|
organization.privateMeta.pendingMailDomain = organization.privateMeta.pendingMailDomain ?? organization.privateMeta.mailDomain;
|
|
@@ -442,8 +400,7 @@ export class Organization extends QueryableModel {
|
|
|
442
400
|
type: EmailTemplateType.OrganizationUnstableDNS,
|
|
443
401
|
bcc: true,
|
|
444
402
|
});
|
|
445
|
-
}
|
|
446
|
-
else if (!organization.serverMeta.isDNSUnstable && organization.serverMeta.didSendDomainSetupMail && organization.serverMeta.DNSRecordWarningCount == 0) {
|
|
403
|
+
} else if (!organization.serverMeta.isDNSUnstable && organization.serverMeta.didSendDomainSetupMail && organization.serverMeta.DNSRecordWarningCount == 0) {
|
|
447
404
|
organization.serverMeta.DNSRecordWarningCount += 1;
|
|
448
405
|
await organization.save();
|
|
449
406
|
|
|
@@ -494,6 +451,10 @@ export class Organization extends QueryableModel {
|
|
|
494
451
|
token: 'mailDomain',
|
|
495
452
|
value: this.privateMeta.mailDomain ?? this.privateMeta.pendingMailDomain ?? '',
|
|
496
453
|
}),
|
|
454
|
+
Replacement.create({
|
|
455
|
+
token: 'organizationName',
|
|
456
|
+
value: this.name,
|
|
457
|
+
}),
|
|
497
458
|
],
|
|
498
459
|
unsubscribeType: 'marketing',
|
|
499
460
|
fromStamhoofd: true,
|
|
@@ -541,8 +502,7 @@ export class Organization extends QueryableModel {
|
|
|
541
502
|
|
|
542
503
|
await client.send(deleteCmd);
|
|
543
504
|
console.log('Deleted AWS mail idenitiy @' + this.id + ' for ' + this.privateMeta.mailDomain);
|
|
544
|
-
}
|
|
545
|
-
catch (e) {
|
|
505
|
+
} catch (e) {
|
|
546
506
|
console.error('Could not delete AWS email identitiy @' + this.id + ' for ' + this.privateMeta.mailDomain);
|
|
547
507
|
console.error(e);
|
|
548
508
|
}
|
|
@@ -609,8 +569,7 @@ export class Organization extends QueryableModel {
|
|
|
609
569
|
// Recreate it immediately
|
|
610
570
|
exists = false;
|
|
611
571
|
}
|
|
612
|
-
}
|
|
613
|
-
catch (e) {
|
|
572
|
+
} catch (e) {
|
|
614
573
|
console.error(e);
|
|
615
574
|
}
|
|
616
575
|
|
|
@@ -854,6 +813,17 @@ export class Organization extends QueryableModel {
|
|
|
854
813
|
return admins.filter(a => a.permissions && a.permissions.forOrganization(this)?.hasFullAccess());
|
|
855
814
|
}
|
|
856
815
|
|
|
816
|
+
/**
|
|
817
|
+
* These email addresess are private
|
|
818
|
+
*/
|
|
819
|
+
async getFinanceAdmins() {
|
|
820
|
+
const admins = await this.getAdmins();
|
|
821
|
+
const filtered = admins.filter(a => a.permissions && (a.permissions.forOrganization(this)?.hasFullAccess() || a.permissions.forOrganization(this)?.hasAccessRight(AccessRight.OrganizationFinanceDirector)));
|
|
822
|
+
|
|
823
|
+
// Only full access
|
|
824
|
+
return filtered;
|
|
825
|
+
}
|
|
826
|
+
|
|
857
827
|
/**
|
|
858
828
|
* These email addresess are private
|
|
859
829
|
*/
|
|
@@ -873,32 +843,90 @@ export class Organization extends QueryableModel {
|
|
|
873
843
|
return filtered.flatMap(f => f.getEmailTo());
|
|
874
844
|
}
|
|
875
845
|
|
|
846
|
+
adminsToRecipients(admins: User[]) {
|
|
847
|
+
return admins.flatMap((f) => {
|
|
848
|
+
return Recipient.create({
|
|
849
|
+
firstName: f.firstName,
|
|
850
|
+
lastName: f.lastName,
|
|
851
|
+
email: f.email,
|
|
852
|
+
replacements: [],
|
|
853
|
+
});
|
|
854
|
+
});
|
|
855
|
+
}
|
|
856
|
+
|
|
876
857
|
/**
|
|
877
858
|
* These email addresess are private
|
|
878
859
|
*/
|
|
879
860
|
async getAdminRecipients(): Promise<Recipient[]> {
|
|
880
|
-
|
|
861
|
+
const filtered = await this.getFullAdmins();
|
|
862
|
+
return this.adminsToRecipients(filtered);
|
|
863
|
+
}
|
|
881
864
|
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
865
|
+
/**
|
|
866
|
+
* These email addresess are private
|
|
867
|
+
*/
|
|
868
|
+
async getFinanceAdminRecipients(): Promise<Recipient[]> {
|
|
869
|
+
const filtered = await this.getFullAdmins();
|
|
870
|
+
return this.adminsToRecipients(filtered);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/**
|
|
874
|
+
* These email addresess are private
|
|
875
|
+
*/
|
|
876
|
+
async getInvoicingToEmails() {
|
|
877
|
+
// Circular reference fix
|
|
878
|
+
const filtered = await this.getFinanceAdmins();
|
|
879
|
+
|
|
880
|
+
if (filtered.length > 0) {
|
|
881
|
+
return filtered.flatMap(f => f.getEmailTo()).map((recipient) => {
|
|
882
|
+
if (!recipient.name) {
|
|
883
|
+
return recipient.email;
|
|
884
|
+
}
|
|
885
|
+
const cleanedName = Formatter.emailSenderName(recipient.name);
|
|
886
|
+
if (cleanedName.length < 2) {
|
|
887
|
+
return recipient.email;
|
|
888
|
+
}
|
|
889
|
+
return '"' + cleanedName + '" <' + recipient.email + '>';
|
|
890
|
+
}).join(', ');
|
|
887
891
|
}
|
|
888
892
|
|
|
889
|
-
return
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
893
|
+
return undefined;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* Returns one email for invoices. since in ubl we can only add one address.
|
|
898
|
+
* We choose the oldest user that was active in the last 3 months (otherwise the oldest user if noone was active)
|
|
899
|
+
*/
|
|
900
|
+
async getInvoicingToEmail(): Promise<string | undefined> {
|
|
901
|
+
// Circular reference fix
|
|
902
|
+
const admins = await this.getAdmins();
|
|
903
|
+
|
|
904
|
+
const tokens = await Token.select().where('userId', admins.map(a => a.id)).fetch();
|
|
905
|
+
|
|
906
|
+
// Sort by admins that were active in the last 3 months, then creation date
|
|
907
|
+
const cutoffDate = new Date(Date.now() - 1000 * 60 * 60 * 24 * 31 * 3);
|
|
908
|
+
admins.sort((a, b) => {
|
|
909
|
+
const aTokens = tokens.filter(t => t.userId === a.id);
|
|
910
|
+
const bTokens = tokens.filter(t => t.userId === b.id);
|
|
911
|
+
const aActive = !!aTokens.find(t => t.updatedAt > cutoffDate);
|
|
912
|
+
const bActive = !!bTokens.find(t => t.updatedAt > cutoffDate);
|
|
913
|
+
return Sorter.stack(
|
|
914
|
+
Sorter.byBooleanValue(aActive, bActive),
|
|
915
|
+
Sorter.byDateValue(b.createdAt, a.createdAt),
|
|
916
|
+
);
|
|
901
917
|
});
|
|
918
|
+
|
|
919
|
+
const filtered = admins.filter(a => a.verified && a.permissions && !a.email.endsWith('@stamhoofd.be') && (a.permissions.forOrganization(this)?.hasFullAccess() || a.permissions.forOrganization(this)?.hasAccessRight(AccessRight.OrganizationFinanceDirector)));
|
|
920
|
+
|
|
921
|
+
if (filtered.length > 0) {
|
|
922
|
+
return filtered.map(f => f.email)[0];
|
|
923
|
+
}
|
|
924
|
+
const filtered2 = admins.filter(a => a.verified && a.permissions && (a.permissions.forOrganization(this)?.hasFullAccess() || a.permissions.forOrganization(this)?.hasAccessRight(AccessRight.OrganizationFinanceDirector)));
|
|
925
|
+
|
|
926
|
+
if (filtered2.length > 0) {
|
|
927
|
+
return filtered2.map(f => f.email)[0];
|
|
928
|
+
}
|
|
929
|
+
return undefined;
|
|
902
930
|
}
|
|
903
931
|
|
|
904
932
|
/**
|
|
@@ -913,10 +941,17 @@ export class Organization extends QueryableModel {
|
|
|
913
941
|
};
|
|
914
942
|
}
|
|
915
943
|
|
|
916
|
-
async getPaymentProviderFor(method: PaymentMethod, config: PrivatePaymentConfiguration): Promise<{
|
|
944
|
+
async getPaymentProviderFor(method: PaymentMethod, mandate: PaymentMandate | null, config: PrivatePaymentConfiguration): Promise<{
|
|
917
945
|
provider: PaymentProvider | null;
|
|
918
946
|
stripeAccount: StripeAccount | null;
|
|
919
947
|
}> {
|
|
948
|
+
if (mandate) {
|
|
949
|
+
return {
|
|
950
|
+
provider: mandate.provider,
|
|
951
|
+
stripeAccount: null,
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
|
|
920
955
|
let stripeAccount = (config.stripeAccountId ? (await StripeAccount.getByID(config.stripeAccountId)) : null) ?? null;
|
|
921
956
|
if (stripeAccount && stripeAccount.organizationId !== this.id) {
|
|
922
957
|
console.warn('Stripe account ' + stripeAccount.id + ' is not linked to organization ' + this.id);
|
|
@@ -984,7 +1019,7 @@ export class Organization extends QueryableModel {
|
|
|
984
1019
|
return 0;
|
|
985
1020
|
}
|
|
986
1021
|
|
|
987
|
-
return await
|
|
1022
|
+
return await Registration.select()
|
|
988
1023
|
.join(
|
|
989
1024
|
SQL.join(Group.table)
|
|
990
1025
|
.where(SQL.column('id'), SQL.parentColumn('groupId')),
|
|
@@ -993,8 +1028,30 @@ export class Organization extends QueryableModel {
|
|
|
993
1028
|
.where('deactivatedAt', null)
|
|
994
1029
|
.where('registeredAt', '!=', null)
|
|
995
1030
|
.where(SQL.column(Group.table, 'deletedAt'), null)
|
|
1031
|
+
.where(SQL.column(Group.table, 'type'), '!=', GroupType.WaitingList)
|
|
996
1032
|
.count(
|
|
997
1033
|
SQL.distinct(SQL.column('memberId')),
|
|
998
1034
|
);
|
|
999
1035
|
}
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* Assures at least one company at all times
|
|
1039
|
+
*/
|
|
1040
|
+
get defaultCompanies() {
|
|
1041
|
+
const b = this.meta.companies.length
|
|
1042
|
+
? this.meta.companies
|
|
1043
|
+
: [
|
|
1044
|
+
Company.create({
|
|
1045
|
+
name: this.name,
|
|
1046
|
+
address: this.address,
|
|
1047
|
+
}),
|
|
1048
|
+
];
|
|
1049
|
+
|
|
1050
|
+
// Missing address -> use organization address
|
|
1051
|
+
if (!b[0].address) {
|
|
1052
|
+
b[0].address = this.address;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
return b;
|
|
1056
|
+
}
|
|
1000
1057
|
}
|