@stamhoofd/backend 2.14.0 → 2.16.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 (31) hide show
  1. package/.env.template.json +2 -1
  2. package/index.ts +15 -1
  3. package/package.json +14 -12
  4. package/src/email-recipient-loaders/members.ts +61 -0
  5. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +1 -1
  6. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +5 -183
  7. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +163 -0
  8. package/src/endpoints/global/files/GetFileCache.ts +69 -0
  9. package/src/endpoints/global/files/UploadFile.ts +4 -1
  10. package/src/endpoints/global/files/UploadImage.ts +14 -2
  11. package/src/endpoints/global/members/GetMembersEndpoint.ts +12 -299
  12. package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +22 -2
  13. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +6 -134
  14. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +5 -3
  15. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +5 -3
  16. package/src/excel-loaders/members.ts +101 -0
  17. package/src/excel-loaders/payments.ts +539 -0
  18. package/src/helpers/AdminPermissionChecker.ts +0 -3
  19. package/src/helpers/AuthenticatedStructures.ts +2 -0
  20. package/src/helpers/FileCache.ts +158 -0
  21. package/src/helpers/fetchToAsyncIterator.ts +34 -0
  22. package/src/sql-filters/balance-item-payments.ts +13 -0
  23. package/src/sql-filters/members.ts +179 -0
  24. package/src/sql-filters/organizations.ts +115 -0
  25. package/src/sql-filters/payments.ts +78 -0
  26. package/src/sql-filters/registrations.ts +24 -0
  27. package/src/sql-sorters/members.ts +46 -0
  28. package/src/sql-sorters/organizations.ts +71 -0
  29. package/src/sql-sorters/payments.ts +50 -0
  30. package/tsconfig.json +3 -4
  31. package/src/endpoints/organization/dashboard/payments/legacy/GetPaymentsEndpoint.ts +0 -170
@@ -0,0 +1,71 @@
1
+ import { Organization } from "@stamhoofd/models"
2
+ import { SQL, SQLOrderBy, SQLOrderByDirection, SQLSortDefinitions } from "@stamhoofd/sql"
3
+
4
+ export const organizationSorters: SQLSortDefinitions<Organization> = {
5
+ 'id': {
6
+ getValue(a) {
7
+ return a.id
8
+ },
9
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
10
+ return new SQLOrderBy({
11
+ column: SQL.column('id'),
12
+ direction
13
+ })
14
+ }
15
+ },
16
+ 'name': {
17
+ getValue(a) {
18
+ return a.name
19
+ },
20
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
21
+ return new SQLOrderBy({
22
+ column: SQL.column('name'),
23
+ direction
24
+ })
25
+ }
26
+ },
27
+ 'uri': {
28
+ getValue(a) {
29
+ return a.uri
30
+ },
31
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
32
+ return new SQLOrderBy({
33
+ column: SQL.column('uri'),
34
+ direction
35
+ })
36
+ }
37
+ },
38
+ 'type': {
39
+ getValue(a) {
40
+ return a.meta.type
41
+ },
42
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
43
+ return new SQLOrderBy({
44
+ column: SQL.jsonValue(SQL.column('meta'), '$.value.type'),
45
+ direction
46
+ })
47
+ }
48
+ },
49
+ 'city': {
50
+ getValue(a) {
51
+ return a.address.city
52
+ },
53
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
54
+ return new SQLOrderBy({
55
+ column: SQL.jsonValue(SQL.column('address'), '$.value.city'),
56
+ direction
57
+ })
58
+ }
59
+ },
60
+ 'country': {
61
+ getValue(a) {
62
+ return a.address.country
63
+ },
64
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
65
+ return new SQLOrderBy({
66
+ column: SQL.jsonValue(SQL.column('address'), '$.value.country'),
67
+ direction
68
+ })
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,50 @@
1
+ import { Payment } from "@stamhoofd/models"
2
+ import { SQL, SQLOrderBy, SQLOrderByDirection, SQLSortDefinitions } from "@stamhoofd/sql"
3
+ import { Formatter } from "@stamhoofd/utility"
4
+
5
+ export const paymentSorters: SQLSortDefinitions<Payment> = {
6
+ 'id': {
7
+ getValue(a) {
8
+ return a.id
9
+ },
10
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
11
+ return new SQLOrderBy({
12
+ column: SQL.column('id'),
13
+ direction
14
+ })
15
+ }
16
+ },
17
+ 'createdAt': {
18
+ getValue(a) {
19
+ return Formatter.dateTimeIso(a.createdAt, 'UTC')
20
+ },
21
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
22
+ return new SQLOrderBy({
23
+ column: SQL.column('createdAt'),
24
+ direction
25
+ })
26
+ }
27
+ },
28
+ 'paidAt': {
29
+ getValue(a) {
30
+ return a.paidAt !== null ? Formatter.dateTimeIso(a.paidAt, 'UTC') : null
31
+ },
32
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
33
+ return new SQLOrderBy({
34
+ column: SQL.column('paidAt'),
35
+ direction
36
+ })
37
+ }
38
+ },
39
+ 'price': {
40
+ getValue(a) {
41
+ return a.price
42
+ },
43
+ toSQL: (direction: SQLOrderByDirection): SQLOrderBy => {
44
+ return new SQLOrderBy({
45
+ column: SQL.column('price'),
46
+ direction
47
+ })
48
+ }
49
+ }
50
+ }
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es2019", // needs to be es2019 to support optional chaining. Node.js doesn't support optional chaining yet, so we need the transpiling
3
+ "target": "es2022", // needs to be es2019 to support optional chaining. Node.js doesn't support optional chaining yet, so we need the transpiling
4
4
  "module": "commonjs",
5
5
  "jsx": "preserve",
6
6
  "importHelpers": true,
@@ -14,8 +14,7 @@
14
14
  "declarationMap": true,
15
15
  "outDir": "dist",
16
16
  "lib": [
17
- "es2019",
18
- "ES2021.String",
17
+ "es2022",
19
18
  "DOM" // axios fix
20
19
  ],
21
20
  "types": [
@@ -39,4 +38,4 @@
39
38
  "ts-node": {
40
39
  "files": true
41
40
  }
42
- }
41
+ }
@@ -1,170 +0,0 @@
1
- import { AutoEncoder, DateDecoder, EnumDecoder, field, IntegerDecoder, StringDecoder } from "@simonbackx/simple-encoding";
2
- import { DecodedRequest, Endpoint, Request, Response } from "@simonbackx/simple-endpoints";
3
- import { Organization, Payment } from "@stamhoofd/models";
4
- import { PaymentGeneral, PaymentMethod, PaymentProvider, PaymentStatus } from "@stamhoofd/structures";
5
-
6
- import { StringArrayDecoder } from "../../../../../decoders/StringArrayDecoder";
7
- import { AuthenticatedStructures } from "../../../../../helpers/AuthenticatedStructures";
8
- import { Context } from "../../../../../helpers/Context";
9
- import { StringNullableDecoder } from "../../../../../decoders/StringNullableDecoder";
10
-
11
- type Params = Record<string, never>;
12
- type Body = undefined
13
- type ResponseBody = PaymentGeneral[]
14
-
15
-
16
- class Query extends AutoEncoder {
17
- /**
18
- * Usage in combination with paidSince is special!
19
- */
20
- @field({ decoder: StringDecoder, optional: true })
21
- afterId?: string
22
-
23
- /**
24
- * Return all payments that were paid after (and including) this date.
25
- * Only returns orders **equal** to this date if afterId is not provided or if the id of those payments is also higher.
26
- */
27
- @field({ decoder: DateDecoder, optional: true })
28
- paidSince?: Date
29
-
30
- @field({ decoder: DateDecoder, optional: true })
31
- paidBefore?: Date
32
-
33
- @field({ decoder: IntegerDecoder, optional: true })
34
- limit?: number
35
-
36
- @field({ decoder: new StringArrayDecoder(new EnumDecoder(PaymentMethod)), optional: true })
37
- methods?: PaymentMethod[]
38
-
39
- @field({ decoder: new StringArrayDecoder(new StringNullableDecoder(new EnumDecoder(PaymentProvider))), optional: true })
40
- providers?: (PaymentProvider|null)[]
41
- }
42
-
43
- export class GetPaymentsEndpoint extends Endpoint<Params, Query, Body, ResponseBody> {
44
- protected queryDecoder = Query;
45
-
46
- protected doesMatch(request: Request): [true, Params] | [false] {
47
- if (request.method != "GET") {
48
- return [false];
49
- }
50
-
51
- const params = Endpoint.parseParameters(request.url, "/organization/payments", {});
52
-
53
- if (params) {
54
- return [true, params as Params];
55
- }
56
- return [false];
57
- }
58
-
59
- async handle(request: DecodedRequest<Params, Query, Body>) {
60
- const organization = await Context.setOrganizationScope();
61
- await Context.authenticate()
62
-
63
- if (!await Context.auth.canManagePayments(organization.id)) {
64
- throw Context.auth.error()
65
- }
66
-
67
- return new Response(
68
- (await this.getPayments(organization, request.query))
69
- );
70
- }
71
-
72
- async getPayments(organization: Organization, query: Query) {
73
- const paidSince = query.paidSince ?? new Date(Date.now() - (24 * 60 * 60 * 1000 * 7 ))
74
- paidSince.setMilliseconds(0)
75
- const payments: Payment[] = []
76
-
77
- if (query.afterId) {
78
- // First return all payments with id > afterId and paidAt == paidSince
79
- payments.push(...await Payment.where({
80
- organizationId: organization.id,
81
- paidAt: {
82
- sign: '=',
83
- value: paidSince
84
- },
85
- id: {
86
- sign: '>',
87
- value: query.afterId ?? ""
88
- },
89
- method: {
90
- sign: 'IN',
91
- value: query.methods ?? [PaymentMethod.Transfer]
92
- },
93
- provider: {
94
- sign: 'IN',
95
- value: query.providers ?? [null]
96
- }
97
- }, {
98
- limit: query.limit ?? undefined,
99
- sort: [{
100
- column: "id",
101
- direction: "ASC"
102
- }]
103
- }));
104
- }
105
-
106
- payments.push(...await Payment.where({
107
- organizationId: organization.id,
108
- paidAt: query.paidBefore ? [{
109
- sign: query.afterId ? '>' : '>=',
110
- value: paidSince
111
- }, {
112
- sign: '<=',
113
- value: query.paidBefore
114
- }] : {
115
- sign: query.afterId ? '>' : '>=',
116
- value: paidSince
117
- },
118
- method: {
119
- sign: 'IN',
120
- value: query.methods ?? [PaymentMethod.Transfer]
121
- },
122
- provider: {
123
- sign: 'IN',
124
- value: query.providers ?? [null]
125
- }
126
- }, {
127
- limit: query.limit ? (query.limit - payments.length) : undefined,
128
- sort: [{
129
- column: "paidAt",
130
- direction: "ASC"
131
- },
132
- {
133
- column: "id",
134
- direction: "ASC"
135
- }]
136
- }));
137
-
138
-
139
- if (!query.paidSince && !query.methods && !query.providers) {
140
- // Default behaviour is to return all not-paid transfer payments that are not yet paid
141
-
142
- payments.push(...
143
- await Payment.where({
144
- organizationId: organization.id,
145
- paidAt: null,
146
- method: PaymentMethod.Transfer,
147
- status: {
148
- sign: '!=',
149
- value: PaymentStatus.Failed
150
- }
151
- })
152
- );
153
-
154
- payments.push(...
155
- await Payment.where({
156
- organizationId: organization.id,
157
- paidAt: null,
158
- updatedAt: {
159
- sign: '>',
160
- value: new Date(Date.now() - (24 * 60 * 60 * 1000 * 7 ))
161
- },
162
- method: PaymentMethod.Transfer,
163
- status: PaymentStatus.Failed
164
- })
165
- );
166
- }
167
-
168
- return await AuthenticatedStructures.paymentsGeneral(payments, true)
169
- }
170
- }