@stamhoofd/backend 2.72.0 → 2.73.1
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 +1 -0
- package/package.json +10 -10
- package/src/email-recipient-loaders/orders.ts +1 -1
- package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +1 -1
- package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +7 -7
- package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +23 -3
- package/src/endpoints/global/audit-logs/GetAuditLogsEndpoint.ts +3 -3
- package/src/endpoints/global/events/GetEventsEndpoint.ts +6 -6
- package/src/endpoints/global/events/PatchEventsEndpoint.ts +36 -4
- package/src/endpoints/global/members/GetMembersEndpoint.ts +4 -4
- package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +24 -14
- package/src/endpoints/global/members/shouldCheckIfMemberIsDuplicate.ts +34 -0
- package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +11 -1
- package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +20 -12
- package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +11 -3
- package/src/endpoints/organization/dashboard/documents/GetDocumentsCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +6 -6
- package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +2 -1
- package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +5 -5
- package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts +51 -9
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersCountEndpoint.ts +1 -1
- package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +6 -6
- package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +6 -6
- package/src/excel-loaders/members.ts +8 -0
- package/src/excel-loaders/receivable-balances.ts +294 -0
- package/src/helpers/AuthenticatedStructures.ts +32 -6
- package/src/helpers/SetupStepUpdater.ts +10 -4
- package/src/helpers/xlsxAddressTransformerColumnFactory.ts +8 -0
- package/src/services/PaymentReallocationService.ts +3 -2
- package/src/services/PaymentService.ts +17 -1
- package/src/sql-filters/members.ts +20 -1
- package/src/sql-filters/organizations.ts +1 -0
- package/src/sql-filters/receivable-balances.ts +53 -1
- package/src/sql-sorters/organizations.ts +11 -0
|
@@ -38,7 +38,7 @@ export class GetDocumentsEndpoint extends Endpoint<Params, Query, Body, Response
|
|
|
38
38
|
return [false];
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
static buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
41
|
+
static async buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
42
42
|
const organization = Context.organization!;
|
|
43
43
|
|
|
44
44
|
const documentTable: string = Document.table;
|
|
@@ -46,25 +46,25 @@ export class GetDocumentsEndpoint extends Endpoint<Params, Query, Body, Response
|
|
|
46
46
|
const query = SQL
|
|
47
47
|
.select(SQL.wildcard(documentTable))
|
|
48
48
|
.from(SQL.table(documentTable))
|
|
49
|
-
.where(compileToSQLFilter({
|
|
49
|
+
.where(await compileToSQLFilter({
|
|
50
50
|
organizationId: organization.id,
|
|
51
51
|
}, filterCompilers));
|
|
52
52
|
|
|
53
53
|
if (q.filter) {
|
|
54
|
-
query.where(compileToSQLFilter(q.filter, filterCompilers));
|
|
54
|
+
query.where(await compileToSQLFilter(q.filter, filterCompilers));
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
if (q.search) {
|
|
58
58
|
const searchFilter: StamhoofdFilter | null = getDocumentSearchFilter(q.search);
|
|
59
59
|
|
|
60
60
|
if (searchFilter) {
|
|
61
|
-
query.where(compileToSQLFilter(searchFilter, filterCompilers));
|
|
61
|
+
query.where(await compileToSQLFilter(searchFilter, filterCompilers));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (q instanceof LimitedFilteredRequest) {
|
|
66
66
|
if (q.pageFilter) {
|
|
67
|
-
query.where(compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
67
|
+
query.where(await compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
q.sort = assertSort(q.sort, [{ key: 'id' }]);
|
|
@@ -76,7 +76,7 @@ export class GetDocumentsEndpoint extends Endpoint<Params, Query, Body, Response
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
static async buildData(requestQuery: LimitedFilteredRequest) {
|
|
79
|
-
const query = this.buildQuery(requestQuery);
|
|
79
|
+
const query = await this.buildQuery(requestQuery);
|
|
80
80
|
const data = await query.fetch();
|
|
81
81
|
|
|
82
82
|
const documents: Document[] = Document.fromRows(data, Document.table);
|
|
@@ -8,9 +8,9 @@ import { Formatter } from '@stamhoofd/utility';
|
|
|
8
8
|
import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
|
|
9
9
|
import { BuckarooHelper } from '../../../../helpers/BuckarooHelper';
|
|
10
10
|
import { Context } from '../../../../helpers/Context';
|
|
11
|
+
import { SetupStepUpdater } from '../../../../helpers/SetupStepUpdater';
|
|
11
12
|
import { TagHelper } from '../../../../helpers/TagHelper';
|
|
12
13
|
import { ViesHelper } from '../../../../helpers/ViesHelper';
|
|
13
|
-
import { SetupStepUpdater } from '../../../../helpers/SetupStepUpdater';
|
|
14
14
|
|
|
15
15
|
type Params = Record<string, never>;
|
|
16
16
|
type Query = undefined;
|
|
@@ -126,6 +126,7 @@ export class PatchOrganizationEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
126
126
|
organization.privateMeta.privateKey = request.body.privateMeta.privateKey ?? organization.privateMeta.privateKey;
|
|
127
127
|
organization.privateMeta.featureFlags = patchObject(organization.privateMeta.featureFlags, request.body.privateMeta.featureFlags);
|
|
128
128
|
organization.privateMeta.balanceNotificationSettings = patchObject(organization.privateMeta.balanceNotificationSettings, request.body.privateMeta.balanceNotificationSettings);
|
|
129
|
+
organization.privateMeta.recordAnswers = request.body.privateMeta.recordAnswers.applyTo(organization.privateMeta.recordAnswers);
|
|
129
130
|
|
|
130
131
|
if (request.body.privateMeta.mollieProfile !== undefined) {
|
|
131
132
|
organization.privateMeta.mollieProfile = patchObject(organization.privateMeta.mollieProfile, request.body.privateMeta.mollieProfile);
|
|
@@ -5,11 +5,11 @@ import { Payment } from '@stamhoofd/models';
|
|
|
5
5
|
import { SQL, compileToSQLFilter, compileToSQLSorter } from '@stamhoofd/sql';
|
|
6
6
|
import { CountFilteredRequest, LimitedFilteredRequest, PaginatedResponse, PaymentGeneral, StamhoofdFilter, TransferSettings, assertSort, getSortFilter } from '@stamhoofd/structures';
|
|
7
7
|
|
|
8
|
+
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
8
9
|
import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
|
|
9
10
|
import { Context } from '../../../../helpers/Context';
|
|
10
11
|
import { paymentFilterCompilers } from '../../../../sql-filters/payments';
|
|
11
12
|
import { paymentSorters } from '../../../../sql-sorters/payments';
|
|
12
|
-
import { SQLResultNamespacedRow } from '@simonbackx/simple-database';
|
|
13
13
|
|
|
14
14
|
type Params = Record<string, never>;
|
|
15
15
|
type Query = LimitedFilteredRequest;
|
|
@@ -59,11 +59,11 @@ export class GetPaymentsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
59
59
|
);
|
|
60
60
|
|
|
61
61
|
if (scopeFilter) {
|
|
62
|
-
query.where(compileToSQLFilter(scopeFilter, filterCompilers));
|
|
62
|
+
query.where(await compileToSQLFilter(scopeFilter, filterCompilers));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
if (q.filter) {
|
|
66
|
-
query.where(compileToSQLFilter(q.filter, filterCompilers));
|
|
66
|
+
query.where(await compileToSQLFilter(q.filter, filterCompilers));
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (q.search) {
|
|
@@ -142,13 +142,13 @@ export class GetPaymentsEndpoint extends Endpoint<Params, Query, Body, ResponseB
|
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
if (searchFilter) {
|
|
145
|
-
query.where(compileToSQLFilter(searchFilter, filterCompilers));
|
|
145
|
+
query.where(await compileToSQLFilter(searchFilter, filterCompilers));
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
if (q instanceof LimitedFilteredRequest) {
|
|
150
150
|
if (q.pageFilter) {
|
|
151
|
-
query.where(compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
151
|
+
query.where(await compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
q.sort = assertSort(q.sort, [{ key: 'id' }]);
|
package/src/endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { DecodedRequest, Endpoint, Request, Response } from '@simonbackx/simple-
|
|
|
3
3
|
import { SimpleError } from '@simonbackx/simple-errors';
|
|
4
4
|
import { CachedBalance } from '@stamhoofd/models';
|
|
5
5
|
import { compileToSQLFilter, compileToSQLSorter } from '@stamhoofd/sql';
|
|
6
|
-
import {
|
|
6
|
+
import { assertSort, CountFilteredRequest, DetailedReceivableBalance, getSortFilter, LimitedFilteredRequest, PaginatedResponse, ReceivableBalance as ReceivableBalanceStruct, StamhoofdFilter } from '@stamhoofd/structures';
|
|
7
7
|
|
|
8
8
|
import { AuthenticatedStructures } from '../../../../helpers/AuthenticatedStructures';
|
|
9
9
|
import { Context } from '../../../../helpers/Context';
|
|
@@ -54,23 +54,49 @@ export class GetReceivableBalancesEndpoint extends Endpoint<Params, Query, Body,
|
|
|
54
54
|
.select();
|
|
55
55
|
|
|
56
56
|
if (scopeFilter) {
|
|
57
|
-
query.where(compileToSQLFilter(scopeFilter, filterCompilers));
|
|
57
|
+
query.where(await compileToSQLFilter(scopeFilter, filterCompilers));
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
if (q.filter) {
|
|
61
|
-
query.where(compileToSQLFilter(q.filter, filterCompilers));
|
|
61
|
+
query.where(await compileToSQLFilter(q.filter, filterCompilers));
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
if (q.search) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
let searchFilter: StamhoofdFilter | null = null;
|
|
66
|
+
|
|
67
|
+
searchFilter = {
|
|
68
|
+
$or: [
|
|
69
|
+
{
|
|
70
|
+
organizations: {
|
|
71
|
+
$elemMatch: {
|
|
72
|
+
$or: [
|
|
73
|
+
{ name: { $contains: q.search } },
|
|
74
|
+
{ uri: q.search },
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
members: {
|
|
81
|
+
$elemMatch: { name: { $contains: q.search } },
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
users: {
|
|
86
|
+
$elemMatch: { name: { $contains: q.search } },
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
if (searchFilter) {
|
|
93
|
+
query.where(await compileToSQLFilter(searchFilter, filterCompilers));
|
|
94
|
+
}
|
|
69
95
|
}
|
|
70
96
|
|
|
71
97
|
if (q instanceof LimitedFilteredRequest) {
|
|
72
98
|
if (q.pageFilter) {
|
|
73
|
-
query.where(compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
99
|
+
query.where(await compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
74
100
|
}
|
|
75
101
|
|
|
76
102
|
q.sort = assertSort(q.sort, [{ key: 'id' }]);
|
|
@@ -81,7 +107,7 @@ export class GetReceivableBalancesEndpoint extends Endpoint<Params, Query, Body,
|
|
|
81
107
|
return query;
|
|
82
108
|
}
|
|
83
109
|
|
|
84
|
-
static async
|
|
110
|
+
static async buildDataHelper(requestQuery: LimitedFilteredRequest) {
|
|
85
111
|
const query = await GetReceivableBalancesEndpoint.buildQuery(requestQuery);
|
|
86
112
|
const data = await query.fetch();
|
|
87
113
|
|
|
@@ -107,12 +133,28 @@ export class GetReceivableBalancesEndpoint extends Endpoint<Params, Query, Body,
|
|
|
107
133
|
}
|
|
108
134
|
}
|
|
109
135
|
|
|
136
|
+
return { data, next };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
static async buildData(requestQuery: LimitedFilteredRequest) {
|
|
140
|
+
const { data, next } = await GetReceivableBalancesEndpoint.buildDataHelper(requestQuery);
|
|
141
|
+
|
|
110
142
|
return new PaginatedResponse<ReceivableBalanceStruct[], LimitedFilteredRequest>({
|
|
111
143
|
results: await AuthenticatedStructures.receivableBalances(data),
|
|
112
144
|
next,
|
|
113
145
|
});
|
|
114
146
|
}
|
|
115
147
|
|
|
148
|
+
static async buildDetailedData(requestQuery: LimitedFilteredRequest) {
|
|
149
|
+
const organization = Context.organization ?? await Context.setOrganizationScope();
|
|
150
|
+
const { data, next } = await GetReceivableBalancesEndpoint.buildDataHelper(requestQuery);
|
|
151
|
+
|
|
152
|
+
return new PaginatedResponse<DetailedReceivableBalance[], LimitedFilteredRequest>({
|
|
153
|
+
results: await AuthenticatedStructures.detailedReceivableBalances(organization.id, data),
|
|
154
|
+
next,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
116
158
|
async handle(request: DecodedRequest<Params, Query, Body>) {
|
|
117
159
|
await Context.setOrganizationScope();
|
|
118
160
|
await Context.authenticate();
|
|
@@ -35,7 +35,7 @@ export class GetWebshopOrdersCountEndpoint extends Endpoint<Params, Query, Body,
|
|
|
35
35
|
throw Context.auth.error();
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const query = GetWebshopOrdersEndpoint.buildQuery(request.query);
|
|
38
|
+
const query = await GetWebshopOrdersEndpoint.buildQuery(request.query);
|
|
39
39
|
|
|
40
40
|
const count = await query
|
|
41
41
|
.count();
|
|
@@ -35,7 +35,7 @@ export class GetWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
35
35
|
return [false];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
static buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
38
|
+
static async buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
39
39
|
// todo: filter userId???
|
|
40
40
|
const organization = Context.organization!;
|
|
41
41
|
|
|
@@ -44,7 +44,7 @@ export class GetWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
44
44
|
const query = SQL
|
|
45
45
|
.select(SQL.wildcard(ordersTable))
|
|
46
46
|
.from(SQL.table(ordersTable))
|
|
47
|
-
.where(compileToSQLFilter({
|
|
47
|
+
.where(await compileToSQLFilter({
|
|
48
48
|
organizationId: organization.id,
|
|
49
49
|
number: {
|
|
50
50
|
$neq: null,
|
|
@@ -52,20 +52,20 @@ export class GetWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
52
52
|
}, filterCompilers));
|
|
53
53
|
|
|
54
54
|
if (q.filter) {
|
|
55
|
-
query.where(compileToSQLFilter(q.filter, filterCompilers));
|
|
55
|
+
query.where(await compileToSQLFilter(q.filter, filterCompilers));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (q.search) {
|
|
59
59
|
const searchFilter: StamhoofdFilter | null = getOrderSearchFilter(q.search, parsePhoneNumber);
|
|
60
60
|
|
|
61
61
|
if (searchFilter) {
|
|
62
|
-
query.where(compileToSQLFilter(searchFilter, filterCompilers));
|
|
62
|
+
query.where(await compileToSQLFilter(searchFilter, filterCompilers));
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
if (q instanceof LimitedFilteredRequest) {
|
|
67
67
|
if (q.pageFilter) {
|
|
68
|
-
query.where(compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
68
|
+
query.where(await compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
q.sort = assertSort(q.sort, [{ key: 'id' }]);
|
|
@@ -77,7 +77,7 @@ export class GetWebshopOrdersEndpoint extends Endpoint<Params, Query, Body, Resp
|
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
static async buildData(requestQuery: LimitedFilteredRequest) {
|
|
80
|
-
const query = this.buildQuery(requestQuery);
|
|
80
|
+
const query = await this.buildQuery(requestQuery);
|
|
81
81
|
const data = await query.fetch();
|
|
82
82
|
|
|
83
83
|
const orders: Order[] = Order.fromRows(data, Order.table);
|
|
@@ -34,7 +34,7 @@ export class GetWebshopTicketsEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
34
34
|
return [false];
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
static buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
37
|
+
static async buildQuery(q: CountFilteredRequest | LimitedFilteredRequest) {
|
|
38
38
|
const organization = Context.organization!;
|
|
39
39
|
|
|
40
40
|
const ticketsTable: string = Ticket.table;
|
|
@@ -42,12 +42,12 @@ export class GetWebshopTicketsEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
42
42
|
const query = SQL
|
|
43
43
|
.select(SQL.wildcard(ticketsTable))
|
|
44
44
|
.from(SQL.table(ticketsTable))
|
|
45
|
-
.where(compileToSQLFilter({
|
|
45
|
+
.where(await Promise.resolve(compileToSQLFilter({
|
|
46
46
|
organizationId: organization.id,
|
|
47
|
-
}, filterCompilers));
|
|
47
|
+
}, filterCompilers)));
|
|
48
48
|
|
|
49
49
|
if (q.filter) {
|
|
50
|
-
query.where(compileToSQLFilter(q.filter, filterCompilers));
|
|
50
|
+
query.where(await Promise.resolve(compileToSQLFilter(q.filter, filterCompilers)));
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
// currently no search supported, probably not needed?
|
|
@@ -56,7 +56,7 @@ export class GetWebshopTicketsEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
56
56
|
|
|
57
57
|
if (q instanceof LimitedFilteredRequest) {
|
|
58
58
|
if (q.pageFilter) {
|
|
59
|
-
query.where(compileToSQLFilter(q.pageFilter, filterCompilers));
|
|
59
|
+
query.where(await Promise.resolve(compileToSQLFilter(q.pageFilter, filterCompilers)));
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
q.sort = assertSort(q.sort, [{ key: 'id' }]);
|
|
@@ -68,7 +68,7 @@ export class GetWebshopTicketsEndpoint extends Endpoint<Params, Query, Body, Res
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
static async buildData(requestQuery: LimitedFilteredRequest) {
|
|
71
|
-
const query = this.buildQuery(requestQuery);
|
|
71
|
+
const query = await this.buildQuery(requestQuery);
|
|
72
72
|
const data = await query.fetch();
|
|
73
73
|
|
|
74
74
|
const tickets: Ticket[] = Ticket.fromRows(data, Ticket.table);
|
|
@@ -204,6 +204,14 @@ const sheet: XlsxTransformerSheet<PlatformMember, PlatformMember> = {
|
|
|
204
204
|
};
|
|
205
205
|
},
|
|
206
206
|
},
|
|
207
|
+
{
|
|
208
|
+
id: 'nationalRegisterNumber',
|
|
209
|
+
name: 'Rijksregisternummer',
|
|
210
|
+
width: 30,
|
|
211
|
+
getValue: ({ patchedMember: object }: PlatformMember) => ({
|
|
212
|
+
value: object.details.nationalRegisterNumber?.toString() ?? '',
|
|
213
|
+
}),
|
|
214
|
+
},
|
|
207
215
|
|
|
208
216
|
...XlsxTransformerColumnHelper.creatColumnsForParents(),
|
|
209
217
|
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { XlsxBuiltInNumberFormat, XlsxTransformerColumn, XlsxTransformerConcreteColumn } from '@stamhoofd/excel-writer';
|
|
2
|
+
import { BalanceItemRelationType, BalanceItemWithPayments, DetailedReceivableBalance, ExcelExportType, getBalanceItemRelationTypeName, getBalanceItemStatusName, getBalanceItemTypeName, getReceivableBalanceTypeNameNotTranslated, PaginatedResponse, ReceivableBalance } from '@stamhoofd/structures';
|
|
3
|
+
import { Formatter } from '@stamhoofd/utility';
|
|
4
|
+
import { ExportToExcelEndpoint } from '../endpoints/global/files/ExportToExcelEndpoint';
|
|
5
|
+
import { GetReceivableBalancesEndpoint } from '../endpoints/organization/dashboard/receivable-balances/GetReceivableBalancesEndpoint';
|
|
6
|
+
|
|
7
|
+
type ReceivableBalanceWithItem = {
|
|
8
|
+
receivableBalance: DetailedReceivableBalance;
|
|
9
|
+
balanceItem: BalanceItemWithPayments;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
ExportToExcelEndpoint.loaders.set(ExcelExportType.ReceivableBalances, {
|
|
13
|
+
fetch: async (requestQuery) => {
|
|
14
|
+
const data = await GetReceivableBalancesEndpoint.buildDetailedData(requestQuery);
|
|
15
|
+
|
|
16
|
+
return new PaginatedResponse({
|
|
17
|
+
...data,
|
|
18
|
+
});
|
|
19
|
+
},
|
|
20
|
+
sheets: [
|
|
21
|
+
{
|
|
22
|
+
id: 'receivableBalances',
|
|
23
|
+
name: 'Te ontvangen bedragen',
|
|
24
|
+
columns: getGeneralColumns(),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: 'balanceItems',
|
|
28
|
+
name: 'Lijnen',
|
|
29
|
+
transform: (data: DetailedReceivableBalance): ReceivableBalanceWithItem[] => data.balanceItems.map(balanceItem => ({
|
|
30
|
+
receivableBalance: data,
|
|
31
|
+
balanceItem,
|
|
32
|
+
})),
|
|
33
|
+
columns: [
|
|
34
|
+
...getBalanceItemColumns(),
|
|
35
|
+
|
|
36
|
+
// Repeating columns need to de-transform again
|
|
37
|
+
...getGeneralColumns()
|
|
38
|
+
.map((c) => {
|
|
39
|
+
return {
|
|
40
|
+
...c,
|
|
41
|
+
id: `receivableBalance.${c.id}`,
|
|
42
|
+
getValue: (object: ReceivableBalanceWithItem) => {
|
|
43
|
+
return c.getValue(object.receivableBalance);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
}),
|
|
47
|
+
],
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
function getBalanceItemColumns(): XlsxTransformerColumn<ReceivableBalanceWithItem>[] {
|
|
53
|
+
return [
|
|
54
|
+
{
|
|
55
|
+
id: 'id',
|
|
56
|
+
name: 'ID',
|
|
57
|
+
width: 40,
|
|
58
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
59
|
+
value: object.balanceItem.id,
|
|
60
|
+
style: {
|
|
61
|
+
font: {
|
|
62
|
+
bold: true,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
id: 'type',
|
|
69
|
+
name: 'Type',
|
|
70
|
+
width: 30,
|
|
71
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
72
|
+
value: getBalanceItemTypeName(object.balanceItem.type),
|
|
73
|
+
}),
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'category',
|
|
77
|
+
name: 'Categorie',
|
|
78
|
+
width: 30,
|
|
79
|
+
getValue: (object: ReceivableBalanceWithItem) => {
|
|
80
|
+
return {
|
|
81
|
+
value: Formatter.capitalizeFirstLetter(object.balanceItem.category),
|
|
82
|
+
};
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
id: 'description',
|
|
87
|
+
name: 'Beschrijving',
|
|
88
|
+
width: 40,
|
|
89
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
90
|
+
value: object.balanceItem.description,
|
|
91
|
+
}),
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
id: 'amount',
|
|
95
|
+
name: 'Aantal',
|
|
96
|
+
width: 20,
|
|
97
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
98
|
+
value: object.balanceItem.amount,
|
|
99
|
+
style: {
|
|
100
|
+
numberFormat: {
|
|
101
|
+
id: XlsxBuiltInNumberFormat.Number,
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
}),
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: 'unitPrice',
|
|
108
|
+
name: 'Eenheidsprijs',
|
|
109
|
+
width: 20,
|
|
110
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
111
|
+
value: object.balanceItem.unitPrice / 100,
|
|
112
|
+
style: {
|
|
113
|
+
numberFormat: {
|
|
114
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
}),
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'price',
|
|
121
|
+
name: 'Prijs',
|
|
122
|
+
width: 20,
|
|
123
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
124
|
+
value: object.balanceItem.price / 100,
|
|
125
|
+
style: {
|
|
126
|
+
numberFormat: {
|
|
127
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 'pricePaid',
|
|
134
|
+
name: 'Betaald bedrag',
|
|
135
|
+
width: 20,
|
|
136
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
137
|
+
value: object.balanceItem.pricePaid / 100,
|
|
138
|
+
style: {
|
|
139
|
+
numberFormat: {
|
|
140
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
}),
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
id: 'pricePending',
|
|
147
|
+
name: 'In verwerking',
|
|
148
|
+
width: 20,
|
|
149
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
150
|
+
value: object.balanceItem.pricePending / 100,
|
|
151
|
+
style: {
|
|
152
|
+
numberFormat: {
|
|
153
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
id: 'priceOpen',
|
|
160
|
+
name: 'Openstaand bedrag',
|
|
161
|
+
width: 20,
|
|
162
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
163
|
+
value: object.balanceItem.priceOpen / 100,
|
|
164
|
+
style: {
|
|
165
|
+
numberFormat: {
|
|
166
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
}),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'createdAt',
|
|
173
|
+
name: 'Aangemaakt op',
|
|
174
|
+
width: 20,
|
|
175
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
176
|
+
value: object.balanceItem.createdAt,
|
|
177
|
+
style: {
|
|
178
|
+
numberFormat: {
|
|
179
|
+
id: XlsxBuiltInNumberFormat.DateSlash,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
}),
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 'dueAt',
|
|
186
|
+
name: 'Verschuldigd vanaf',
|
|
187
|
+
width: 20,
|
|
188
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
189
|
+
value: object.balanceItem.dueAt,
|
|
190
|
+
style: {
|
|
191
|
+
numberFormat: {
|
|
192
|
+
id: XlsxBuiltInNumberFormat.DateSlash,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
}),
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
id: 'status',
|
|
199
|
+
name: 'Status',
|
|
200
|
+
width: 20,
|
|
201
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
202
|
+
value: getBalanceItemStatusName(object.balanceItem.status),
|
|
203
|
+
}),
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
{
|
|
207
|
+
match: (id) => {
|
|
208
|
+
if (id.startsWith('relations.')) {
|
|
209
|
+
const type = id.split('.')[1] as BalanceItemRelationType;
|
|
210
|
+
if (Object.values(BalanceItemRelationType).includes(type)) {
|
|
211
|
+
return [
|
|
212
|
+
{
|
|
213
|
+
id: `relations.${type}`,
|
|
214
|
+
name: getBalanceItemRelationTypeName(type),
|
|
215
|
+
width: 35,
|
|
216
|
+
getValue: (object: ReceivableBalanceWithItem) => ({
|
|
217
|
+
value: object.balanceItem.relations.get(type)?.name || '',
|
|
218
|
+
}),
|
|
219
|
+
},
|
|
220
|
+
];
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
];
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function getGeneralColumns(): XlsxTransformerConcreteColumn<ReceivableBalance>[] {
|
|
229
|
+
return [
|
|
230
|
+
{
|
|
231
|
+
id: 'id',
|
|
232
|
+
name: 'ID schuldenaar',
|
|
233
|
+
width: 40,
|
|
234
|
+
getValue: (object: ReceivableBalance) => ({
|
|
235
|
+
value: object.id,
|
|
236
|
+
style: {
|
|
237
|
+
font: {
|
|
238
|
+
bold: true,
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
}),
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
id: 'name',
|
|
245
|
+
name: 'Schuldenaar',
|
|
246
|
+
width: 40,
|
|
247
|
+
getValue: (object: ReceivableBalance) => ({
|
|
248
|
+
value: object.object.name,
|
|
249
|
+
}),
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
id: 'uri',
|
|
253
|
+
name: 'Groepsnummer',
|
|
254
|
+
width: 16,
|
|
255
|
+
getValue: (object: ReceivableBalance) => ({
|
|
256
|
+
value: object.object.uri,
|
|
257
|
+
}),
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: 'amountOpen',
|
|
261
|
+
name: 'Openstaand bedrag',
|
|
262
|
+
width: 10,
|
|
263
|
+
getValue: (object: ReceivableBalance) => ({
|
|
264
|
+
value: object.amountOpen / 100,
|
|
265
|
+
style: {
|
|
266
|
+
numberFormat: {
|
|
267
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
268
|
+
},
|
|
269
|
+
},
|
|
270
|
+
}),
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
id: 'amountPending',
|
|
274
|
+
name: 'In verwerking',
|
|
275
|
+
width: 18,
|
|
276
|
+
getValue: (object: ReceivableBalance) => ({
|
|
277
|
+
value: object.amountPending / 100,
|
|
278
|
+
style: {
|
|
279
|
+
numberFormat: {
|
|
280
|
+
id: XlsxBuiltInNumberFormat.Currency2DecimalWithRed,
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
}),
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
id: 'objectType',
|
|
287
|
+
name: 'type',
|
|
288
|
+
width: 10,
|
|
289
|
+
getValue: (object: ReceivableBalance) => ({
|
|
290
|
+
value: getReceivableBalanceTypeNameNotTranslated(object.objectType),
|
|
291
|
+
}),
|
|
292
|
+
},
|
|
293
|
+
];
|
|
294
|
+
}
|