@stamhoofd/models 2.91.0 → 2.93.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 (47) hide show
  1. package/dist/src/factories/RegistrationPeriodFactory.d.ts +2 -1
  2. package/dist/src/factories/RegistrationPeriodFactory.d.ts.map +1 -1
  3. package/dist/src/factories/RegistrationPeriodFactory.js +2 -1
  4. package/dist/src/factories/RegistrationPeriodFactory.js.map +1 -1
  5. package/dist/src/helpers/EmailBuilder.d.ts +1 -2
  6. package/dist/src/helpers/EmailBuilder.d.ts.map +1 -1
  7. package/dist/src/helpers/EmailBuilder.js +7 -21
  8. package/dist/src/helpers/EmailBuilder.js.map +1 -1
  9. package/dist/src/helpers/MemberMerger.d.ts.map +1 -1
  10. package/dist/src/helpers/MemberMerger.js +6 -0
  11. package/dist/src/helpers/MemberMerger.js.map +1 -1
  12. package/dist/src/migrations/1755529026-email-sender-id.sql +2 -0
  13. package/dist/src/migrations/1755789797-email-counts-errors.sql +7 -0
  14. package/dist/src/migrations/1755789798-email-recipient-errors.sql +2 -0
  15. package/dist/src/migrations/1756115313-email-recipient-ids-and-errors.sql +10 -0
  16. package/dist/src/migrations/1756115314-email-recipient-email-optional.sql +2 -0
  17. package/dist/src/migrations/1756115315-email-recipients-count.sql +3 -0
  18. package/dist/src/migrations/1756115316-email-cached-counts.sql +4 -0
  19. package/dist/src/models/Email.d.ts +63 -2
  20. package/dist/src/models/Email.d.ts.map +1 -1
  21. package/dist/src/models/Email.js +559 -194
  22. package/dist/src/models/Email.js.map +1 -1
  23. package/dist/src/models/Email.test.js +151 -43
  24. package/dist/src/models/Email.test.js.map +1 -1
  25. package/dist/src/models/EmailRecipient.d.ts +31 -1
  26. package/dist/src/models/EmailRecipient.d.ts.map +1 -1
  27. package/dist/src/models/EmailRecipient.js +53 -2
  28. package/dist/src/models/EmailRecipient.js.map +1 -1
  29. package/dist/src/models/WebshopUitpasNumber.d.ts +2 -1
  30. package/dist/src/models/WebshopUitpasNumber.d.ts.map +1 -1
  31. package/dist/src/models/WebshopUitpasNumber.js +20 -3
  32. package/dist/src/models/WebshopUitpasNumber.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/factories/RegistrationPeriodFactory.ts +3 -2
  35. package/src/helpers/EmailBuilder.ts +9 -24
  36. package/src/helpers/MemberMerger.ts +7 -0
  37. package/src/migrations/1755529026-email-sender-id.sql +2 -0
  38. package/src/migrations/1755789797-email-counts-errors.sql +7 -0
  39. package/src/migrations/1755789798-email-recipient-errors.sql +2 -0
  40. package/src/migrations/1756115313-email-recipient-ids-and-errors.sql +10 -0
  41. package/src/migrations/1756115314-email-recipient-email-optional.sql +2 -0
  42. package/src/migrations/1756115315-email-recipients-count.sql +3 -0
  43. package/src/migrations/1756115316-email-cached-counts.sql +4 -0
  44. package/src/models/Email.test.ts +165 -44
  45. package/src/models/Email.ts +639 -207
  46. package/src/models/EmailRecipient.ts +46 -2
  47. package/src/models/WebshopUitpasNumber.ts +23 -3
@@ -4,6 +4,7 @@ import { v4 as uuidv4 } from 'uuid';
4
4
 
5
5
  import { ArrayDecoder } from '@simonbackx/simple-encoding';
6
6
  import { QueryableModel } from '@stamhoofd/sql';
7
+ import { SimpleErrors } from '@simonbackx/simple-errors';
7
8
 
8
9
  export class EmailRecipient extends QueryableModel {
9
10
  static table = 'email_recipients';
@@ -38,15 +39,58 @@ export class EmailRecipient extends QueryableModel {
38
39
  @column({ type: 'string', nullable: true })
39
40
  lastName: string | null = null;
40
41
 
41
- @column({ type: 'string' })
42
- email: string;
42
+ @column({ type: 'string', nullable: true })
43
+ email: string | null = null;
43
44
 
44
45
  @column({ type: 'json', decoder: new ArrayDecoder(Replacement) })
45
46
  replacements: Replacement[] = [];
46
47
 
48
+ /**
49
+ * @deprecated
50
+ * Legacy field
51
+ */
47
52
  @column({ type: 'string', nullable: true })
48
53
  failErrorMessage: string | null = null;
49
54
 
55
+ @column({ type: 'json', nullable: true, decoder: SimpleErrors })
56
+ failError: SimpleErrors | null = null;
57
+
58
+ @column({ type: 'string', nullable: true })
59
+ organizationId: string | null = null;
60
+
61
+ /**
62
+ * When set, the member will be ablse to see this message in the member portal.
63
+ */
64
+ @column({ type: 'string', nullable: true })
65
+ memberId: string | null = null;
66
+
67
+ /**
68
+ * When set, the user will be able to see this message in the member portal.
69
+ */
70
+ @column({ type: 'string', nullable: true })
71
+ userId: string | null = null;
72
+
73
+ /**
74
+ * Set when the email was send, but we received a hard bounce for this specific email
75
+ * Contains the full output we received in the bounce
76
+ */
77
+ @column({ type: 'string', nullable: true })
78
+ hardBounceError: string | null = null;
79
+
80
+ /**
81
+ * Set when the email was send, but we received a soft bounce for this specific email
82
+ * Contains the full output we received in the bounce
83
+ */
84
+ @column({ type: 'string', nullable: true })
85
+ softBounceError: string | null = null;
86
+
87
+ /**
88
+ * Set when the email was send, but was marked as spam.
89
+ * The error message contains any relevant info we received from our provider. E.g. type of spam (virus, fraud, abuse...)
90
+ */
91
+ @column({ type: 'string', nullable: true })
92
+ spamComplaintError: string | null = null;
93
+
50
94
  @column({ type: 'integer' })
51
95
  failCount = 0;
52
96
 
@@ -54,8 +54,28 @@ export class WebshopUitpasNumber extends QueryableModel {
54
54
  @column({ type: 'integer', nullable: true })
55
55
  reducedPriceUitpas: number | null = null;
56
56
 
57
- static async areUitpasNumbersUsed(webshopId: string, productId: string, uitpasNumbers: string[]): Promise<boolean> {
58
- const hasBeenUsed = !!(await WebshopUitpasNumber.select().where('webshopId', webshopId).andWhere('productId', productId).andWhere('uitpasNumber', uitpasNumbers).first(false));
59
- return hasBeenUsed;
57
+ static async areUitpasNumbersUsed(webshopId: string, productId: string, uitpasNumbers: string[], uitpasEventUrl?: string, existingOrderId?: string): Promise<boolean> {
58
+ let query = WebshopUitpasNumber
59
+ .select()
60
+ .where('webshopId', webshopId)
61
+ .andWhere('uitpasNumber', uitpasNumbers);
62
+
63
+ if (uitpasEventUrl) {
64
+ query = query.andWhere(SQL.where('productId', productId).or('uitpasEventUrl', uitpasEventUrl));
65
+ }
66
+ else {
67
+ query = query.andWhere('productId', productId);
68
+ }
69
+
70
+ if (existingOrderId !== undefined) {
71
+ query = query.andWhereNot('orderId', existingOrderId);
72
+ }
73
+
74
+ return !!await query.first(false); ;
75
+ }
76
+
77
+ static async areThereRegisteredTicketSales(webshopId: string): Promise<boolean> {
78
+ const query = WebshopUitpasNumber.select().where('webshopId', webshopId).andWhereNot('ticketSaleId', null);
79
+ return !!await query.first(false);
60
80
  }
61
81
  }