@stamhoofd/backend 2.80.1 → 2.81.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/index.ts CHANGED
@@ -111,10 +111,7 @@ const start = async () => {
111
111
  console.log('Loading loaders...');
112
112
 
113
113
  // Register Excel loaders
114
- await import('./src/excel-loaders/members');
115
- await import('./src/excel-loaders/payments');
116
- await import('./src/excel-loaders/organizations');
117
- await import('./src/excel-loaders/receivable-balances');
114
+ await import('./src/excel-loaders');
118
115
 
119
116
  // Register Email Recipient loaders
120
117
  await import('./src/email-recipient-loaders/members');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stamhoofd/backend",
3
- "version": "2.80.1",
3
+ "version": "2.81.0",
4
4
  "main": "./dist/index.js",
5
5
  "exports": {
6
6
  ".": {
@@ -38,14 +38,14 @@
38
38
  "@simonbackx/simple-encoding": "2.22.0",
39
39
  "@simonbackx/simple-endpoints": "1.19.1",
40
40
  "@simonbackx/simple-logging": "^1.0.1",
41
- "@stamhoofd/backend-i18n": "2.80.1",
42
- "@stamhoofd/backend-middleware": "2.80.1",
43
- "@stamhoofd/email": "2.80.1",
44
- "@stamhoofd/models": "2.80.1",
45
- "@stamhoofd/queues": "2.80.1",
46
- "@stamhoofd/sql": "2.80.1",
47
- "@stamhoofd/structures": "2.80.1",
48
- "@stamhoofd/utility": "2.80.1",
41
+ "@stamhoofd/backend-i18n": "2.81.0",
42
+ "@stamhoofd/backend-middleware": "2.81.0",
43
+ "@stamhoofd/email": "2.81.0",
44
+ "@stamhoofd/models": "2.81.0",
45
+ "@stamhoofd/queues": "2.81.0",
46
+ "@stamhoofd/sql": "2.81.0",
47
+ "@stamhoofd/structures": "2.81.0",
48
+ "@stamhoofd/utility": "2.81.0",
49
49
  "archiver": "^7.0.1",
50
50
  "aws-sdk": "^2.885.0",
51
51
  "axios": "1.6.8",
@@ -65,5 +65,5 @@
65
65
  "publishConfig": {
66
66
  "access": "public"
67
67
  },
68
- "gitHead": "37793d55487f7e8792d7b97df20750f8bd5be9a3"
68
+ "gitHead": "5a0faf4813aeb5c3d7216536278acb65ba2361e0"
69
69
  }
@@ -0,0 +1,133 @@
1
+ import { XlsxBuiltInNumberFormat, XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
+ import { EventNotification, EventNotificationStatus, EventNotificationStatusHelper, ExcelExportType, LimitedFilteredRequest, Platform as PlatformStruct } from '@stamhoofd/structures';
3
+ import { Formatter } from '@stamhoofd/utility';
4
+ import { GetEventNotificationsEndpoint } from '../endpoints/global/events/GetEventNotificationsEndpoint';
5
+ import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint';
6
+ import { XlsxTransformerColumnHelper } from '../helpers/XlsxTransformerColumnHelper';
7
+
8
+ // Assign to a typed variable to assure we have correct type checking in place
9
+ const sheet: XlsxTransformerSheet<EventNotification, EventNotification> = {
10
+ id: 'event-notifications',
11
+ name: 'Meldingen',
12
+ columns: [
13
+ {
14
+ id: 'id',
15
+ name: 'ID',
16
+ width: 40,
17
+ getValue: (notification: EventNotification) => ({
18
+ value: notification.id,
19
+ }),
20
+ },
21
+ {
22
+ id: 'name',
23
+ name: 'Naam activiteit',
24
+ width: 40,
25
+ getValue: (notification: EventNotification) => ({
26
+ value: notification.events.map(e => e.name).join(', '),
27
+ }),
28
+ },
29
+ {
30
+ id: 'organization.name',
31
+ name: 'Groep',
32
+ width: 40,
33
+ getValue: (notification: EventNotification) => ({
34
+ value: notification.organization.name,
35
+ }),
36
+ },
37
+ {
38
+ id: 'organization.uri',
39
+ name: 'Groepsnummer',
40
+ width: 30,
41
+ getValue: (notification: EventNotification) => ({
42
+ value: notification.organization.uri,
43
+ }),
44
+ },
45
+ {
46
+ id: 'status',
47
+ name: 'Status',
48
+ width: 30,
49
+ getValue: (notification: EventNotification) => ({
50
+ value: Formatter.capitalizeFirstLetter(EventNotificationStatusHelper.getName(notification.status)),
51
+ }),
52
+ },
53
+ {
54
+ id: 'feedbackText',
55
+ name: 'Opmerkingen',
56
+ width: 80,
57
+ getValue: (notification: EventNotification) => ({
58
+ value: notification.status !== EventNotificationStatus.Accepted ? notification.feedbackText : null,
59
+ style: {
60
+ alignment: {
61
+ wrapText: true,
62
+ },
63
+ },
64
+ }),
65
+ },
66
+ {
67
+ id: 'startDate',
68
+ name: 'Startdatum',
69
+ width: 20,
70
+ getValue: (notification: EventNotification) => ({
71
+ value: notification.startDate,
72
+ style: {
73
+ numberFormat: {
74
+ id: XlsxBuiltInNumberFormat.DateSlash,
75
+ },
76
+ },
77
+ }),
78
+ },
79
+ {
80
+ id: 'endDate',
81
+ name: 'Einddatum',
82
+ width: 20,
83
+ getValue: (notification: EventNotification) => ({
84
+ value: notification.endDate,
85
+ style: {
86
+ numberFormat: {
87
+ id: XlsxBuiltInNumberFormat.DateSlash,
88
+ },
89
+ },
90
+ }),
91
+ },
92
+ {
93
+ id: 'submittedAt',
94
+ name: 'Ingediend op',
95
+ width: 20,
96
+ getValue: (notification: EventNotification) => ({
97
+ value: notification.submittedAt,
98
+ style: {
99
+ numberFormat: {
100
+ id: XlsxBuiltInNumberFormat.DateSlash,
101
+ },
102
+ },
103
+ }),
104
+ },
105
+ {
106
+ id: 'submittedBy',
107
+ name: 'Ingediend door',
108
+ width: 40,
109
+ getValue: (notification: EventNotification) => ({
110
+ value: notification.submittedBy?.name ?? '',
111
+ }),
112
+ },
113
+
114
+ // Dynamic records
115
+ XlsxTransformerColumnHelper.createRecordAnswersColumns({
116
+ matchId: 'recordAnswers',
117
+ getRecordAnswers: (notification: EventNotification) => notification.recordAnswers,
118
+ getRecordCategories: () => {
119
+ const platform = PlatformStruct.shared;
120
+ return platform.config.eventNotificationTypes.flatMap(r => r.recordCategories);
121
+ },
122
+ }),
123
+ ],
124
+ };
125
+
126
+ ExportToExcelEndpoint.loaders.set(ExcelExportType.EventNotifications, {
127
+ fetch: async (query: LimitedFilteredRequest) => {
128
+ return await GetEventNotificationsEndpoint.buildData(query);
129
+ },
130
+ sheets: [
131
+ sheet,
132
+ ],
133
+ });
@@ -0,0 +1,5 @@
1
+ import './members';
2
+ import './payments';
3
+ import './organizations';
4
+ import './receivable-balances';
5
+ import './event-notifications';
@@ -6,7 +6,7 @@ import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEn
6
6
  import { GetMembersEndpoint } from '../endpoints/global/members/GetMembersEndpoint';
7
7
  import { AuthenticatedStructures } from '../helpers/AuthenticatedStructures';
8
8
  import { Context } from '../helpers/Context';
9
- import { XlsxTransformerColumnHelper } from '../helpers/xlsxAddressTransformerColumnFactory';
9
+ import { XlsxTransformerColumnHelper } from '../helpers/XlsxTransformerColumnHelper';
10
10
 
11
11
  // Assign to a typed variable to assure we have correct type checking in place
12
12
  const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
@@ -16,7 +16,7 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
16
16
  {
17
17
  id: 'id',
18
18
  name: 'ID',
19
- width: 20,
19
+ width: 40,
20
20
  getValue: ({ patchedMember: object }: PlatformMember) => ({
21
21
  value: object.id,
22
22
  }),
@@ -89,7 +89,7 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
89
89
  {
90
90
  id: 'email',
91
91
  name: 'E-mailadres',
92
- width: 20,
92
+ width: 40,
93
93
  getValue: ({ patchedMember: object }: PlatformMember) => ({
94
94
  value: object.details.email,
95
95
  }),
@@ -247,42 +247,19 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
247
247
  },
248
248
 
249
249
  // Dynamic records
250
- {
251
- match(id) {
252
- if (id.startsWith('recordAnswers.')) {
253
- const platform = PlatformStruct.shared;
254
- const organization = Context.organization;
255
-
256
- const recordSettings = [
257
- ...(organization?.meta.recordsConfiguration.recordCategories.flatMap(category => category.getAllRecords()) ?? []),
258
- ...platform.config.recordsConfiguration.recordCategories.flatMap(category => category.getAllRecords()),
259
- ];
260
-
261
- const recordSettingId = id.split('.')[1];
262
- console.log('recordSettingId', recordSettingId);
263
- const recordSetting = recordSettings.find(r => r.id === recordSettingId);
264
-
265
- if (!recordSetting) {
266
- // Will throw a proper error itself
267
- console.log('recordSetting not found', recordSettings);
268
- return;
269
- }
270
-
271
- const columns = recordSetting.excelColumns;
272
-
273
- return columns.map((columnName, index) => {
274
- return {
275
- id: `recordAnswers.${recordSettingId}.${index}`,
276
- name: columnName,
277
- width: 20,
278
- getValue: ({ patchedMember: object }: PlatformMember) => ({
279
- value: object.details.recordAnswers.get(recordSettingId)?.excelValues[index]?.value ?? '',
280
- }),
281
- };
282
- });
283
- }
250
+ XlsxTransformerColumnHelper.createRecordAnswersColumns({
251
+ matchId: 'recordAnswers',
252
+ getRecordAnswers: ({ patchedMember: object }: PlatformMember) => object.details.recordAnswers,
253
+ getRecordCategories: () => {
254
+ const platform = PlatformStruct.shared;
255
+ const organization = Context.organization;
256
+
257
+ return [
258
+ ...(organization?.meta.recordsConfiguration.recordCategories ?? []),
259
+ ...platform.config.recordsConfiguration.recordCategories,
260
+ ];
284
261
  },
285
- },
262
+ }),
286
263
 
287
264
  // Registration records
288
265
  {
@@ -2,7 +2,7 @@ import { XlsxTransformerSheet } from '@stamhoofd/excel-writer';
2
2
  import { Platform as PlatformStruct, ExcelExportType, LimitedFilteredRequest, Organization as OrganizationStruct, MemberResponsibilityRecord as MemberResponsibilityRecordStruct, PaginatedResponse, MemberWithRegistrationsBlob, Premise } from '@stamhoofd/structures';
3
3
  import { GetOrganizationsEndpoint } from '../endpoints/admin/organizations/GetOrganizationsEndpoint';
4
4
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint';
5
- import { XlsxTransformerColumnHelper } from '../helpers/xlsxAddressTransformerColumnFactory';
5
+ import { XlsxTransformerColumnHelper } from '../helpers/XlsxTransformerColumnHelper';
6
6
  import { Group, Member, MemberResponsibilityRecord } from '@stamhoofd/models';
7
7
  import { Formatter, Sorter } from '@stamhoofd/utility';
8
8
  import { ArrayDecoder, field } from '@simonbackx/simple-encoding';
@@ -33,7 +33,7 @@ const sheet: XlsxTransformerSheet<Object, Object> = {
33
33
  {
34
34
  id: 'id',
35
35
  name: 'ID',
36
- width: 35,
36
+ width: 40,
37
37
  getValue: (object: Object) => ({
38
38
  value: object.id,
39
39
  }),
@@ -5,7 +5,7 @@ import { BalanceItemPaymentDetailed, BalanceItemRelationType, ExcelExportType, g
5
5
  import { Formatter } from '@stamhoofd/utility';
6
6
  import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint';
7
7
  import { GetPaymentsEndpoint } from '../endpoints/organization/dashboard/payments/GetPaymentsEndpoint';
8
- import { XlsxTransformerColumnHelper } from '../helpers/xlsxAddressTransformerColumnFactory';
8
+ import { XlsxTransformerColumnHelper } from '../helpers/XlsxTransformerColumnHelper';
9
9
 
10
10
  type PaymentWithItem = {
11
11
  payment: PaymentGeneral;
@@ -475,7 +475,7 @@ function getPayingOrganizationColumns(): XlsxTransformerColumn<PaymentGeneral>[]
475
475
  {
476
476
  id: 'payingOrganization.id',
477
477
  name: 'ID betalende groep',
478
- width: 30,
478
+ width: 40,
479
479
  getValue: (object: PaymentGeneralWithStripeAccount) => {
480
480
  return {
481
481
  value: object.payingOrganization?.id || '',
@@ -1,5 +1,5 @@
1
1
  import { XlsxTransformerColumn } from '@stamhoofd/excel-writer';
2
- import { Address, CountryHelper, Parent, ParentTypeHelper, PlatformMember } from '@stamhoofd/structures';
2
+ import { Address, CountryHelper, Parent, ParentTypeHelper, PlatformMember, RecordAnswer, RecordCategory, RecordSettings, RecordType } from '@stamhoofd/structures';
3
3
 
4
4
  export class XlsxTransformerColumnHelper {
5
5
  static formatBoolean(value: boolean | undefined | null): string {
@@ -115,7 +115,8 @@ export class XlsxTransformerColumnHelper {
115
115
  {
116
116
  id: getId('street'),
117
117
  name: `Straat`,
118
- width: 30,
118
+ defaultCategory: 'Adres', // Ignore this name
119
+ width: 40,
119
120
  getValue: (object: T) => {
120
121
  const address = getAddress(object);
121
122
  return {
@@ -126,6 +127,7 @@ export class XlsxTransformerColumnHelper {
126
127
  {
127
128
  id: getId('number'),
128
129
  name: 'Nummer',
130
+ defaultCategory: 'Adres', // Ignore this name
129
131
  width: 20,
130
132
  getValue: (object: T) => {
131
133
  const address = getAddress(object);
@@ -137,6 +139,7 @@ export class XlsxTransformerColumnHelper {
137
139
  {
138
140
  id: getId('postalCode'),
139
141
  name: 'Postcode',
142
+ defaultCategory: 'Adres', // Ignore this name
140
143
  width: 20,
141
144
  getValue: (object: T) => {
142
145
  const address = getAddress(object);
@@ -148,6 +151,7 @@ export class XlsxTransformerColumnHelper {
148
151
  {
149
152
  id: getId('city'),
150
153
  name: 'Stad',
154
+ defaultCategory: 'Adres', // Ignore this name
151
155
  width: 20,
152
156
  getValue: (object: T) => {
153
157
  const address = getAddress(object);
@@ -159,6 +163,7 @@ export class XlsxTransformerColumnHelper {
159
163
  {
160
164
  id: getId('country'),
161
165
  name: 'Land',
166
+ defaultCategory: 'Adres', // Ignore this name
162
167
  width: 20,
163
168
  getValue: (object: T) => {
164
169
  const address = getAddress(object);
@@ -173,4 +178,65 @@ export class XlsxTransformerColumnHelper {
173
178
  },
174
179
  };
175
180
  }
181
+
182
+ static createRecordAnswersColumns<T>({ matchId, getRecordCategories, getRecordAnswers }: { matchId: string; getRecordCategories: () => RecordCategory[]; getRecordAnswers: (object: T) => Map<string, RecordAnswer> }): XlsxTransformerColumn<T> {
183
+ return {
184
+ match(id) {
185
+ if (id.startsWith(matchId + '.')) {
186
+ const recordCategories = getRecordCategories();
187
+ const flattenedCategories = RecordCategory.flattenCategoriesWith(recordCategories, r => r.excelColumns.length > 0);
188
+
189
+ let recordCategory: RecordCategory | undefined;
190
+ let recordSetting: RecordSettings | undefined;
191
+ const recordSettingId = id.split('.')[1];
192
+
193
+ for (const category of flattenedCategories) {
194
+ const recordSettings = category.getAllRecords();
195
+ const rr = recordSettings.find(r => r.id === recordSettingId);
196
+
197
+ if (rr) {
198
+ recordSetting = rr;
199
+ recordCategory = category;
200
+ break;
201
+ }
202
+ }
203
+
204
+ if (!recordSetting || !recordCategory) {
205
+ // Will throw a proper error itself
206
+ console.log('recordSetting not found');
207
+ return;
208
+ }
209
+
210
+ const columns = recordSetting.excelColumns;
211
+
212
+ return columns.map(({ name, width, defaultCategory }, index) => {
213
+ return {
214
+ id: `${matchId}.${recordSettingId}.${index}`,
215
+ name,
216
+ width: width ?? 20,
217
+ defaultCategory,
218
+ category: recordCategory.name,
219
+ getValue: (object: T) => {
220
+ const answers = getRecordAnswers(object);
221
+ const b = (answers.get(recordSettingId)?.excelValues[index] ?? {
222
+ value: '',
223
+ });
224
+
225
+ return {
226
+ ...b,
227
+ style: {
228
+ ...b.style,
229
+ alignment: {
230
+ ...b.style?.alignment,
231
+ wrapText: recordSetting.type === RecordType.Textarea,
232
+ },
233
+ },
234
+ };
235
+ },
236
+ };
237
+ });
238
+ }
239
+ },
240
+ };
241
+ }
176
242
  }