@stamhoofd/models 2.83.4 → 2.84.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/src/factories/BalanceItemFactory.d.ts +3 -1
- package/dist/src/factories/BalanceItemFactory.d.ts.map +1 -1
- package/dist/src/factories/BalanceItemFactory.js +6 -0
- package/dist/src/factories/BalanceItemFactory.js.map +1 -1
- package/dist/src/factories/DocumentTemplateFactory.d.ts +15 -0
- package/dist/src/factories/DocumentTemplateFactory.d.ts.map +1 -0
- package/dist/src/factories/DocumentTemplateFactory.js +125 -0
- package/dist/src/factories/DocumentTemplateFactory.js.map +1 -0
- package/dist/src/factories/EventFactory.d.ts +2 -0
- package/dist/src/factories/EventFactory.d.ts.map +1 -1
- package/dist/src/factories/EventFactory.js +5 -0
- package/dist/src/factories/EventFactory.js.map +1 -1
- package/dist/src/factories/GroupFactory.d.ts +7 -2
- package/dist/src/factories/GroupFactory.d.ts.map +1 -1
- package/dist/src/factories/GroupFactory.js +30 -5
- package/dist/src/factories/GroupFactory.js.map +1 -1
- package/dist/src/factories/MemberFactory.d.ts.map +1 -1
- package/dist/src/factories/MemberFactory.js +3 -1
- package/dist/src/factories/MemberFactory.js.map +1 -1
- package/dist/src/factories/RegistrationFactory.d.ts +3 -1
- package/dist/src/factories/RegistrationFactory.d.ts.map +1 -1
- package/dist/src/factories/RegistrationFactory.js +2 -0
- package/dist/src/factories/RegistrationFactory.js.map +1 -1
- package/dist/src/factories/UserFactory.js +1 -1
- package/dist/src/factories/UserFactory.js.map +1 -1
- package/dist/src/factories/index.d.ts +1 -0
- package/dist/src/factories/index.d.ts.map +1 -1
- package/dist/src/factories/index.js +1 -0
- package/dist/src/factories/index.js.map +1 -1
- package/dist/src/helpers/EmailBuilder.d.ts.map +1 -1
- package/dist/src/helpers/EmailBuilder.js +3 -1
- package/dist/src/helpers/EmailBuilder.js.map +1 -1
- package/dist/src/migrations/1747913433-registration-discounts.sql +2 -0
- package/dist/src/migrations/1747996262-balance-items-paid-at.sql +2 -0
- package/dist/src/migrations/1747996263-balance-items-paid-at-fill.sql +1 -0
- package/dist/src/models/BalanceItem.d.ts +9 -8
- package/dist/src/models/BalanceItem.d.ts.map +1 -1
- package/dist/src/models/BalanceItem.js +36 -42
- package/dist/src/models/BalanceItem.js.map +1 -1
- package/dist/src/models/CachedBalance.d.ts.map +1 -1
- package/dist/src/models/CachedBalance.js +3 -0
- package/dist/src/models/CachedBalance.js.map +1 -1
- package/dist/src/models/Document.d.ts.map +1 -1
- package/dist/src/models/Document.js +9 -1
- package/dist/src/models/Document.js.map +1 -1
- package/dist/src/models/Email.d.ts.map +1 -1
- package/dist/src/models/Email.js +10 -3
- package/dist/src/models/Email.js.map +1 -1
- package/dist/src/models/Email.test.js +40 -40
- package/dist/src/models/Email.test.js.map +1 -1
- package/dist/src/models/Group.d.ts +1 -1
- package/dist/src/models/Group.d.ts.map +1 -1
- package/dist/src/models/Group.js +9 -4
- package/dist/src/models/Group.js.map +1 -1
- package/dist/src/models/Image.d.ts +3 -0
- package/dist/src/models/Image.d.ts.map +1 -1
- package/dist/src/models/Image.js +28 -17
- package/dist/src/models/Image.js.map +1 -1
- package/dist/src/models/Member.d.ts +3 -3
- package/dist/src/models/Member.d.ts.map +1 -1
- package/dist/src/models/Member.js +2 -2
- package/dist/src/models/Member.js.map +1 -1
- package/dist/src/models/MemberPlatformMembership.js +1 -1
- package/dist/src/models/MemberPlatformMembership.js.map +1 -1
- package/dist/src/models/Organization.d.ts.map +1 -1
- package/dist/src/models/Organization.js +26 -24
- package/dist/src/models/Organization.js.map +1 -1
- package/dist/src/models/PayconiqPayment.d.ts.map +1 -1
- package/dist/src/models/PayconiqPayment.js +6 -1
- package/dist/src/models/PayconiqPayment.js.map +1 -1
- package/dist/src/models/Platform.d.ts.map +1 -1
- package/dist/src/models/Platform.js +5 -3
- package/dist/src/models/Platform.js.map +1 -1
- package/dist/src/models/Registration.d.ts +11 -1
- package/dist/src/models/Registration.d.ts.map +1 -1
- package/dist/src/models/Registration.js +14 -1
- package/dist/src/models/Registration.js.map +1 -1
- package/dist/src/models/User.d.ts.map +1 -1
- package/dist/src/models/User.js +1 -1
- package/dist/src/models/User.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/factories/BalanceItemFactory.ts +7 -1
- package/src/factories/DocumentTemplateFactory.ts +130 -0
- package/src/factories/EventFactory.ts +7 -0
- package/src/factories/GroupFactory.ts +35 -8
- package/src/factories/MemberFactory.ts +3 -1
- package/src/factories/RegistrationFactory.ts +9 -2
- package/src/factories/UserFactory.ts +1 -1
- package/src/factories/index.ts +1 -0
- package/src/helpers/EmailBuilder.ts +3 -1
- package/src/migrations/1747913433-registration-discounts.sql +2 -0
- package/src/migrations/1747996262-balance-items-paid-at.sql +2 -0
- package/src/migrations/1747996263-balance-items-paid-at-fill.sql +1 -0
- package/src/models/BalanceItem.ts +39 -54
- package/src/models/CachedBalance.ts +4 -0
- package/src/models/Document.ts +9 -1
- package/src/models/Email.test.ts +40 -40
- package/src/models/Email.ts +12 -4
- package/src/models/Group.ts +12 -4
- package/src/models/Image.ts +32 -18
- package/src/models/Member.ts +3 -3
- package/src/models/MemberPlatformMembership.ts +1 -1
- package/src/models/Organization.ts +35 -27
- package/src/models/PayconiqPayment.ts +7 -1
- package/src/models/Platform.ts +6 -3
- package/src/models/Registration.ts +14 -2
- package/src/models/User.ts +2 -2
|
@@ -4,9 +4,9 @@ import { I18n } from '@stamhoofd/backend-i18n';
|
|
|
4
4
|
import { EmailInterfaceRecipient } from '@stamhoofd/email';
|
|
5
5
|
import { QueryableModel } from '@stamhoofd/sql';
|
|
6
6
|
import { Address, Country, DNSRecordStatus, EmailTemplateType, Language, OrganizationEmail, OrganizationMetaData, OrganizationPrivateMetaData, Organization as OrganizationStruct, PaymentMethod, PaymentProvider, PrivatePaymentConfiguration, Recipient, Replacement, STPackageType, TransferSettings } from '@stamhoofd/structures';
|
|
7
|
-
|
|
8
|
-
import
|
|
9
|
-
|
|
7
|
+
|
|
8
|
+
import { CreateEmailIdentityCommand, DeleteEmailIdentityCommand, GetEmailIdentityCommand, GetEmailIdentityCommandOutput, PutEmailIdentityFeedbackAttributesCommand, PutEmailIdentityMailFromAttributesCommand, SESv2Client } from '@aws-sdk/client-sesv2';
|
|
9
|
+
|
|
10
10
|
import { v4 as uuidv4 } from 'uuid';
|
|
11
11
|
|
|
12
12
|
import { QueueHandler } from '@stamhoofd/queues';
|
|
@@ -480,28 +480,27 @@ export class Organization extends QueryableModel {
|
|
|
480
480
|
return;
|
|
481
481
|
}
|
|
482
482
|
|
|
483
|
-
const
|
|
483
|
+
const client = new SESv2Client({});
|
|
484
484
|
|
|
485
485
|
// Check if mail identitiy already exists..
|
|
486
|
-
let exists = false;
|
|
487
|
-
let existing: PromiseResult<SES.GetEmailIdentityResponse, AWSError> | undefined = undefined;
|
|
488
486
|
try {
|
|
489
|
-
|
|
487
|
+
const cmd = new GetEmailIdentityCommand({
|
|
490
488
|
EmailIdentity: mailDomain,
|
|
491
|
-
})
|
|
492
|
-
|
|
489
|
+
});
|
|
490
|
+
const result = await client.send(cmd);
|
|
493
491
|
|
|
494
|
-
|
|
495
|
-
if (existing.VerifiedForSendingStatus === true) {
|
|
492
|
+
if (result.VerifiedForSendingStatus === true) {
|
|
496
493
|
console.log('Cant delete AWS mail idenitiy @' + this.id + ' for ' + mailDomain + ': already validated and might be in use by other organizations');
|
|
497
494
|
return;
|
|
498
495
|
}
|
|
499
496
|
|
|
500
|
-
console.log('Deleting AWS mail
|
|
497
|
+
console.log('Deleting AWS mail identity @' + this.id + ' for ' + mailDomain);
|
|
501
498
|
|
|
502
|
-
|
|
499
|
+
const deleteCmd = new DeleteEmailIdentityCommand({
|
|
503
500
|
EmailIdentity: mailDomain,
|
|
504
|
-
})
|
|
501
|
+
});
|
|
502
|
+
|
|
503
|
+
await client.send(deleteCmd);
|
|
505
504
|
console.log('Deleted AWS mail idenitiy @' + this.id + ' for ' + this.privateMeta.mailDomain);
|
|
506
505
|
}
|
|
507
506
|
catch (e) {
|
|
@@ -531,16 +530,18 @@ export class Organization extends QueryableModel {
|
|
|
531
530
|
return;
|
|
532
531
|
}
|
|
533
532
|
|
|
534
|
-
const
|
|
533
|
+
const client = new SESv2Client({});
|
|
535
534
|
const expectedConfigurationSetName = Formatter.slug(STAMHOOFD.platformName + '-domains');
|
|
536
535
|
|
|
537
536
|
// Check if mail identitiy already exists..
|
|
538
537
|
let exists = false;
|
|
539
|
-
let existing:
|
|
538
|
+
let existing: GetEmailIdentityCommandOutput | undefined = undefined;
|
|
540
539
|
try {
|
|
541
|
-
|
|
540
|
+
const cmd = new GetEmailIdentityCommand({
|
|
542
541
|
EmailIdentity: this.privateMeta.mailDomain,
|
|
543
|
-
})
|
|
542
|
+
});
|
|
543
|
+
|
|
544
|
+
existing = await client.send(cmd);
|
|
544
545
|
exists = true;
|
|
545
546
|
|
|
546
547
|
console.log('AWS mail idenitiy exists already: just checking the verification status in AWS @' + this.id);
|
|
@@ -560,9 +561,11 @@ export class Organization extends QueryableModel {
|
|
|
560
561
|
|
|
561
562
|
if (existing.VerifiedForSendingStatus !== true && existing.DkimAttributes?.Status === 'FAILED') {
|
|
562
563
|
console.error('AWS failed to verify DKIM records. Triggering a forced recheck @' + this.id);
|
|
563
|
-
|
|
564
|
+
|
|
565
|
+
const deleteCmd = new DeleteEmailIdentityCommand({
|
|
564
566
|
EmailIdentity: this.privateMeta.mailDomain,
|
|
565
|
-
})
|
|
567
|
+
});
|
|
568
|
+
await client.send(deleteCmd);
|
|
566
569
|
|
|
567
570
|
// Recreate it immediately
|
|
568
571
|
exists = false;
|
|
@@ -575,7 +578,7 @@ export class Organization extends QueryableModel {
|
|
|
575
578
|
if (!exists) {
|
|
576
579
|
console.log('Creating email identity in AWS SES...');
|
|
577
580
|
|
|
578
|
-
const
|
|
581
|
+
const cmd = new CreateEmailIdentityCommand({
|
|
579
582
|
EmailIdentity: this.privateMeta.mailDomain,
|
|
580
583
|
ConfigurationSetName: expectedConfigurationSetName,
|
|
581
584
|
DkimSigningAttributes: {
|
|
@@ -592,27 +595,32 @@ export class Organization extends QueryableModel {
|
|
|
592
595
|
Value: STAMHOOFD.environment ?? 'Unknown',
|
|
593
596
|
},
|
|
594
597
|
],
|
|
598
|
+
});
|
|
595
599
|
|
|
596
|
-
|
|
600
|
+
const result = await client.send(cmd);
|
|
597
601
|
this.privateMeta.mailDomainActive = result.VerifiedForSendingStatus ?? false;
|
|
598
602
|
|
|
599
603
|
// Disable email forwarding of bounces and complaints
|
|
600
604
|
// We handle this now with the configuration set
|
|
601
|
-
|
|
605
|
+
const putFeedbackCmd = new PutEmailIdentityFeedbackAttributesCommand({
|
|
602
606
|
EmailIdentity: this.privateMeta.mailDomain,
|
|
603
607
|
EmailForwardingEnabled: false,
|
|
604
|
-
})
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
await client.send(putFeedbackCmd);
|
|
605
611
|
}
|
|
606
612
|
|
|
607
613
|
if (this.privateMeta.mailFromDomain && (!exists || (existing && (!existing.MailFromAttributes || existing.MailFromAttributes.MailFromDomain !== this.privateMeta.mailFromDomain)))) {
|
|
608
614
|
// Also set a from domain, to fix SPF
|
|
609
615
|
console.log('Setting mail from domain: ' + this.privateMeta.mailFromDomain + ' for ' + this.id);
|
|
610
|
-
|
|
616
|
+
|
|
617
|
+
const cmd = new PutEmailIdentityMailFromAttributesCommand({
|
|
611
618
|
EmailIdentity: this.privateMeta.mailDomain,
|
|
612
619
|
BehaviorOnMxFailure: 'USE_DEFAULT_VALUE',
|
|
613
620
|
MailFromDomain: this.privateMeta.mailFromDomain,
|
|
614
|
-
};
|
|
615
|
-
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
await client.send(cmd);
|
|
616
624
|
}
|
|
617
625
|
}
|
|
618
626
|
|
|
@@ -161,7 +161,13 @@ export class PayconiqPayment extends QueryableModel {
|
|
|
161
161
|
private static request(method: string, path: string, data = {}, auth: string | null = null, testMode: boolean): Promise<any> {
|
|
162
162
|
return new Promise((resolve, reject) => {
|
|
163
163
|
const jsonData = JSON.stringify(data);
|
|
164
|
-
|
|
164
|
+
|
|
165
|
+
// Payconiq switches to Wero on 2025-09-21
|
|
166
|
+
const isWero = Date.now() > new Date('2025-09-21T02:00:00+02:00').getTime();
|
|
167
|
+
let hostname = !testMode ? 'api.payconiq.com' : 'api.ext.payconiq.com';
|
|
168
|
+
if (isWero) {
|
|
169
|
+
hostname = !testMode ? 'merchant.api.bancontact.net' : 'merchant.api.preprod.bancontact.net';
|
|
170
|
+
}
|
|
165
171
|
const base = 'https://' + hostname;
|
|
166
172
|
|
|
167
173
|
// Log all communication
|
package/src/models/Platform.ts
CHANGED
|
@@ -89,6 +89,11 @@ export class Platform extends QueryableModel {
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
static async getShared(): Promise<Readonly<Platform> & { save: never }> {
|
|
92
|
+
if (this.shared) {
|
|
93
|
+
// Skip queue if possible (performance optimization)
|
|
94
|
+
return this.shared as any;
|
|
95
|
+
}
|
|
96
|
+
|
|
92
97
|
return QueueHandler.schedule('Platform.getShared', async () => {
|
|
93
98
|
if (this.shared) {
|
|
94
99
|
return this.shared;
|
|
@@ -141,9 +146,7 @@ export class Platform extends QueryableModel {
|
|
|
141
146
|
this.sharedStruct = null;
|
|
142
147
|
this.sharedPrivateStruct = null;
|
|
143
148
|
});
|
|
144
|
-
|
|
145
|
-
this.shared = null;
|
|
146
|
-
});
|
|
149
|
+
this.shared = null;
|
|
147
150
|
}
|
|
148
151
|
|
|
149
152
|
async save() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { column, Database, ManyToOneRelation } from '@simonbackx/simple-database';
|
|
2
|
-
import { EmailTemplateType, GroupPrice, PaymentMethod, PaymentMethodHelper, Recipient, RecordAnswer, RecordAnswerDecoder, RegisterItemOption, Registration as RegistrationStructure, Replacement, StockReservation } from '@stamhoofd/structures';
|
|
2
|
+
import { AppliedRegistrationDiscount, EmailTemplateType, GroupPrice, PaymentMethod, PaymentMethodHelper, Recipient, RecordAnswer, RecordAnswerDecoder, RegisterItemOption, Registration as RegistrationStructure, Replacement, StockReservation } from '@stamhoofd/structures';
|
|
3
3
|
import { Formatter } from '@stamhoofd/utility';
|
|
4
4
|
import { v4 as uuidv4 } from 'uuid';
|
|
5
5
|
|
|
@@ -130,9 +130,21 @@ export class Registration extends QueryableModel {
|
|
|
130
130
|
/**
|
|
131
131
|
* Set to null if no reservations are made, to help faster querying
|
|
132
132
|
*/
|
|
133
|
-
@column({ type: 'json', decoder: new ArrayDecoder(StockReservation)
|
|
133
|
+
@column({ type: 'json', decoder: new ArrayDecoder(StockReservation) })
|
|
134
134
|
stockReservations: StockReservation[] = [];
|
|
135
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Cached value for calculation of discounts of other registrations (based on the single-source-of-truth stored in balance items)
|
|
138
|
+
*
|
|
139
|
+
* Discounts that were applied to this registration.
|
|
140
|
+
* Note that these discounts are saved in separate balance items and
|
|
141
|
+
* are not included in the price.
|
|
142
|
+
*
|
|
143
|
+
* Reason is that discounts can change after you've been registered
|
|
144
|
+
*/
|
|
145
|
+
@column({ type: 'json', decoder: new MapDecoder(StringDecoder, AppliedRegistrationDiscount) })
|
|
146
|
+
discounts = new Map<string, AppliedRegistrationDiscount>();
|
|
147
|
+
|
|
136
148
|
static group: ManyToOneRelation<'group', import('./Group').Group>;
|
|
137
149
|
|
|
138
150
|
getStructure(this: Registration & { group: import('./Group').Group }) {
|
package/src/models/User.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { column, Database, ManyToOneRelation } from '@simonbackx/simple-database';
|
|
2
2
|
import { EmailInterfaceRecipient } from '@stamhoofd/email';
|
|
3
|
-
import { QueryableModel, SQL,
|
|
3
|
+
import { QueryableModel, SQL, SQLJSONNull } from '@stamhoofd/sql';
|
|
4
4
|
import { LoginProviderType, NewUser, Permissions, Recipient, Replacement, UserMeta, UserPermissions, User as UserStruct } from '@stamhoofd/structures';
|
|
5
5
|
import argon2 from 'argon2';
|
|
6
6
|
import { v4 as uuidv4 } from 'uuid';
|
|
@@ -125,7 +125,7 @@ export class User extends QueryableModel {
|
|
|
125
125
|
.where(
|
|
126
126
|
SQL.jsonValue(SQL.column('permissions'), '$.value.globalPermissions'),
|
|
127
127
|
'!=',
|
|
128
|
-
|
|
128
|
+
SQLJSONNull,
|
|
129
129
|
)
|
|
130
130
|
.where('id', '!=', '1');
|
|
131
131
|
|