@things-factory/accounting 10.1.154 → 10.1.156
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-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/activities/activity-expenditure.d.ts +186 -0
- package/dist-server/activities/activity-expenditure.js +122 -0
- package/dist-server/activities/activity-expenditure.js.map +1 -0
- package/dist-server/activities/expenditure-activity-names.d.ts +4 -0
- package/dist-server/activities/expenditure-activity-names.js +13 -0
- package/dist-server/activities/expenditure-activity-names.js.map +1 -0
- package/dist-server/activities/index.d.ts +2 -1
- package/dist-server/activities/index.js +19 -12
- package/dist-server/activities/index.js.map +1 -1
- package/dist-server/index.d.ts +1 -0
- package/dist-server/index.js +1 -0
- package/dist-server/index.js.map +1 -1
- package/dist-server/service/account/account-match.d.ts +5 -3
- package/dist-server/service/account/account-match.js +7 -3
- package/dist-server/service/account/account-match.js.map +1 -1
- package/dist-server/service/bank-statement/bank-import.js +9 -3
- package/dist-server/service/bank-statement/bank-import.js.map +1 -1
- package/dist-server/service/bank-statement/bank-source.js +2 -1
- package/dist-server/service/bank-statement/bank-source.js.map +1 -1
- package/dist-server/service/counterparty-account/counterparty-account-query.d.ts +6 -0
- package/dist-server/service/counterparty-account/counterparty-account-query.js +48 -0
- package/dist-server/service/counterparty-account/counterparty-account-query.js.map +1 -0
- package/dist-server/service/counterparty-account/counterparty-account-rules.d.ts +46 -0
- package/dist-server/service/counterparty-account/counterparty-account-rules.js +76 -0
- package/dist-server/service/counterparty-account/counterparty-account-rules.js.map +1 -0
- package/dist-server/service/counterparty-account/counterparty-account-service.d.ts +22 -0
- package/dist-server/service/counterparty-account/counterparty-account-service.js +66 -0
- package/dist-server/service/counterparty-account/counterparty-account-service.js.map +1 -0
- package/dist-server/service/counterparty-account/counterparty-account-type.d.ts +9 -0
- package/dist-server/service/counterparty-account/counterparty-account-type.js +40 -0
- package/dist-server/service/counterparty-account/counterparty-account-type.js.map +1 -0
- package/dist-server/service/counterparty-account/index.d.ts +4 -0
- package/dist-server/service/counterparty-account/index.js +8 -0
- package/dist-server/service/counterparty-account/index.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-payment-state.d.ts +52 -0
- package/dist-server/service/expenditure-request/expenditure-payment-state.js +100 -0
- package/dist-server/service/expenditure-request/expenditure-payment-state.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-item.d.ts +41 -0
- package/dist-server/service/expenditure-request/expenditure-request-item.js +149 -0
- package/dist-server/service/expenditure-request/expenditure-request-item.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-mutation.d.ts +18 -0
- package/dist-server/service/expenditure-request/expenditure-request-mutation.js +140 -0
- package/dist-server/service/expenditure-request/expenditure-request-mutation.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-query.d.ts +46 -0
- package/dist-server/service/expenditure-request/expenditure-request-query.js +365 -0
- package/dist-server/service/expenditure-request/expenditure-request-query.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-rules.d.ts +128 -0
- package/dist-server/service/expenditure-request/expenditure-request-rules.js +183 -0
- package/dist-server/service/expenditure-request/expenditure-request-rules.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-service.d.ts +92 -0
- package/dist-server/service/expenditure-request/expenditure-request-service.js +488 -0
- package/dist-server/service/expenditure-request/expenditure-request-service.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request-type.d.ts +85 -0
- package/dist-server/service/expenditure-request/expenditure-request-type.js +312 -0
- package/dist-server/service/expenditure-request/expenditure-request-type.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-request.d.ts +67 -0
- package/dist-server/service/expenditure-request/expenditure-request.js +228 -0
- package/dist-server/service/expenditure-request/expenditure-request.js.map +1 -0
- package/dist-server/service/expenditure-request/expenditure-target.d.ts +1 -0
- package/dist-server/service/expenditure-request/expenditure-target.js +55 -0
- package/dist-server/service/expenditure-request/expenditure-target.js.map +1 -0
- package/dist-server/service/expenditure-request/index.d.ts +8 -0
- package/dist-server/service/expenditure-request/index.js +12 -0
- package/dist-server/service/expenditure-request/index.js.map +1 -0
- package/dist-server/service/index.d.ts +9 -2
- package/dist-server/service/index.js +18 -3
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -9
- package/translations/en.json +58 -1
- package/translations/es.json +17 -1
- package/translations/ja.json +17 -1
- package/translations/ko.json +58 -1
- package/translations/ms.json +17 -1
- package/translations/zh.json +17 -1
- package/dist-client/activities/activity-expense-edit.d.ts +0 -14
- package/dist-client/activities/activity-expense-edit.js +0 -85
- package/dist-client/activities/activity-expense-edit.js.map +0 -1
- package/dist-client/activities/activity-expense-view.d.ts +0 -14
- package/dist-client/activities/activity-expense-view.js +0 -85
- package/dist-client/activities/activity-expense-view.js.map +0 -1
- package/dist-server/activities/activity-expense.d.ts +0 -58
- package/dist-server/activities/activity-expense.js +0 -150
- package/dist-server/activities/activity-expense.js.map +0 -1
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExpenditureRequestItemQuery = exports.ExpenditureRequestQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const typeorm_1 = require("typeorm");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const auth_base_1 = require("@things-factory/auth-base");
|
|
9
|
+
const attachment_base_1 = require("@things-factory/attachment-base");
|
|
10
|
+
const biz_base_1 = require("@things-factory/biz-base");
|
|
11
|
+
const organization_1 = require("@things-factory/organization");
|
|
12
|
+
const tax_invoice_1 = require("@things-factory/tax-invoice");
|
|
13
|
+
const account_1 = require("../account/account");
|
|
14
|
+
const expenditure_request_1 = require("./expenditure-request");
|
|
15
|
+
const expenditure_request_item_1 = require("./expenditure-request-item");
|
|
16
|
+
const expenditure_payment_state_1 = require("./expenditure-payment-state");
|
|
17
|
+
const expenditure_request_rules_1 = require("./expenditure-request-rules");
|
|
18
|
+
const expenditure_request_service_1 = require("./expenditure-request-service");
|
|
19
|
+
const expenditure_request_type_1 = require("./expenditure-request-type");
|
|
20
|
+
const byId = async (entity, id, withDeleted = false) => id ? (await (0, shell_1.getRepository)(entity).findOne({ where: { id }, withDeleted })) : null;
|
|
21
|
+
async function summaryOf(domain, year, month, requesterId) {
|
|
22
|
+
const period = month ? `${year}-${String(month).padStart(2, '0')}` : `${year}-%`;
|
|
23
|
+
const requests = await (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).find({
|
|
24
|
+
where: {
|
|
25
|
+
domain: { id: domain.id },
|
|
26
|
+
kind: expenditure_request_1.ExpenditureKind.REIMBURSEMENT,
|
|
27
|
+
month: month ? period : (0, typeorm_1.Like)(period),
|
|
28
|
+
...(requesterId ? { requester: { id: requesterId } } : {})
|
|
29
|
+
},
|
|
30
|
+
relations: ['requester', 'items', 'items.account']
|
|
31
|
+
});
|
|
32
|
+
const shaped = requests.map(one => ({
|
|
33
|
+
month: one.month,
|
|
34
|
+
requesterId: one.requesterId ?? one.requester?.id,
|
|
35
|
+
requesterName: one.requester?.name ?? null,
|
|
36
|
+
status: one.status,
|
|
37
|
+
/* Summed by 계정과목; a line not yet filed counts under the category written on it. */
|
|
38
|
+
items: (one.items ?? []).filter(item => !item.deletedAt).map(item => ({ ...item, category: item.account?.name ?? item.category }))
|
|
39
|
+
}));
|
|
40
|
+
const rows = (0, expenditure_request_rules_1.monthlySummary)(shaped);
|
|
41
|
+
const approved = requests.filter(one => one.status === expenditure_request_1.ExpenditureRequestStatus.APPROVED);
|
|
42
|
+
approved.forEach(one => (one.items = (one.items ?? []).filter(item => !item.deletedAt)));
|
|
43
|
+
const states = await (0, expenditure_payment_state_1.paymentStatesOf)((0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).manager, domain, approved);
|
|
44
|
+
return {
|
|
45
|
+
rows,
|
|
46
|
+
statuses: Object.entries((0, expenditure_request_rules_1.statusCounts)(shaped)).map(([status, count]) => ({ status, count })),
|
|
47
|
+
approvedTotal: rows.reduce((sum, one) => sum + one.total, 0),
|
|
48
|
+
unpaid: [...states.values()].reduce((sum, one) => sum + one.outstanding, 0)
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
let ExpenditureRequestQuery = class ExpenditureRequestQuery {
|
|
52
|
+
/** The caller's own requests - what an employee sees. */
|
|
53
|
+
async myExpenditureRequests(params, context) {
|
|
54
|
+
const { domain, user } = context.state;
|
|
55
|
+
const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({ domain, params, repository: (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest), searchables: ['title', 'notes'], alias: 'request' });
|
|
56
|
+
queryBuilder.andWhere('request.requester = :requester', { requester: user.id });
|
|
57
|
+
queryBuilder.addOrderBy('request.createdAt', 'DESC');
|
|
58
|
+
const [items, total] = await queryBuilder.getManyAndCount();
|
|
59
|
+
return { items, total };
|
|
60
|
+
}
|
|
61
|
+
/** One of the caller's own requests, with its lines. */
|
|
62
|
+
async myExpenditureRequest(id, context) {
|
|
63
|
+
const { domain, user } = context.state;
|
|
64
|
+
return await (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).findOne({ where: { id, domain: { id: domain.id }, requester: { id: user.id } } });
|
|
65
|
+
}
|
|
66
|
+
/** Every request of the domain - what finance sees. */
|
|
67
|
+
async expenditureRequests(params, context) {
|
|
68
|
+
const { domain } = context.state;
|
|
69
|
+
const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({ domain, params, repository: (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest), searchables: ['title', 'notes'], alias: 'request' });
|
|
70
|
+
queryBuilder.addOrderBy('request.createdAt', 'DESC');
|
|
71
|
+
const [items, total] = await queryBuilder.getManyAndCount();
|
|
72
|
+
return { items, total };
|
|
73
|
+
}
|
|
74
|
+
async expenditureRequest(id, context) {
|
|
75
|
+
return await (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).findOne({ where: { id, domain: { id: context.state.domain.id } } });
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The payment queue (지급 대기) - approved requests still to pay, by the day they are to be paid, and the paid ones
|
|
79
|
+
* whose bank line no statement has matched yet.
|
|
80
|
+
*/
|
|
81
|
+
async expenditureQueue(context) {
|
|
82
|
+
const { domain } = context.state;
|
|
83
|
+
const manager = (0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).manager;
|
|
84
|
+
const { requests, states } = await (0, expenditure_request_service_1.approvedWithStates)(manager, domain);
|
|
85
|
+
const rows = [];
|
|
86
|
+
for (const request of requests) {
|
|
87
|
+
const payment = states.get(request.id);
|
|
88
|
+
if (payment.state === expenditure_payment_state_1.ExpenditurePaymentState.NOTHING_TO_PAY)
|
|
89
|
+
continue;
|
|
90
|
+
rows.push({
|
|
91
|
+
request,
|
|
92
|
+
payment,
|
|
93
|
+
payeeName: (request.kind === expenditure_request_1.ExpenditureKind.VENDOR ? request.counterparty?.name : request.requester?.name) ?? undefined,
|
|
94
|
+
payeeAccountDrift: payment.outstanding > 0 ? await (0, expenditure_request_service_1.driftOf)(manager, request) : undefined
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
const due = (row) => row.request.dueDate ?? '9999-12-31';
|
|
98
|
+
const waiting = rows
|
|
99
|
+
.filter(row => row.payment.outstanding > 0)
|
|
100
|
+
.sort((a, b) => due(a).localeCompare(due(b)) || String(a.request.decidedAt ?? '').localeCompare(String(b.request.decidedAt ?? '')));
|
|
101
|
+
const unreconciled = rows.filter(row => row.payment.outstanding <= 0 && !row.payment.reconciled);
|
|
102
|
+
return { waiting, unreconciled };
|
|
103
|
+
}
|
|
104
|
+
async expenditureSummary(year, month, context) {
|
|
105
|
+
return await summaryOf(context.state.domain, year, month || undefined);
|
|
106
|
+
}
|
|
107
|
+
async myExpenditureSummary(year, month, context) {
|
|
108
|
+
return await summaryOf(context.state.domain, year, month || undefined, context.state.user.id);
|
|
109
|
+
}
|
|
110
|
+
/** How far it is paid - read from its payments (ADR-0135 §2-4). */
|
|
111
|
+
async payment(request) {
|
|
112
|
+
if (request.status !== expenditure_request_1.ExpenditureRequestStatus.APPROVED)
|
|
113
|
+
return null;
|
|
114
|
+
const items = await (0, shell_1.getRepository)(expenditure_request_item_1.ExpenditureRequestItem).find({ where: { request: { id: request.id } } });
|
|
115
|
+
const states = await (0, expenditure_payment_state_1.paymentStatesOf)((0, shell_1.getRepository)(expenditure_request_1.ExpenditureRequest).manager, { id: request.domainId }, [{ id: request.id, items }]);
|
|
116
|
+
return states.get(request.id) ?? null;
|
|
117
|
+
}
|
|
118
|
+
async items(request) {
|
|
119
|
+
if (request.items)
|
|
120
|
+
return request.items.filter(item => !item.deletedAt);
|
|
121
|
+
return await (0, shell_1.getRepository)(expenditure_request_item_1.ExpenditureRequestItem).find({ where: { request: { id: request.id } }, order: { spentDate: 'ASC', createdAt: 'ASC' } });
|
|
122
|
+
}
|
|
123
|
+
async requester(request) {
|
|
124
|
+
return request.requester ?? (await byId(auth_base_1.User, request.requesterId));
|
|
125
|
+
}
|
|
126
|
+
async department(request) {
|
|
127
|
+
return request.department ?? (await byId(organization_1.Department, request.departmentId));
|
|
128
|
+
}
|
|
129
|
+
async counterparty(request) {
|
|
130
|
+
return request.counterparty ?? (await byId(biz_base_1.Counterparty, request.counterpartyId, true));
|
|
131
|
+
}
|
|
132
|
+
async payeeAccount(request) {
|
|
133
|
+
return request.payeeAccount ?? (await byId(biz_base_1.CounterpartyBankAccount, request.payeeAccountId, true));
|
|
134
|
+
}
|
|
135
|
+
async decidedBy(request) {
|
|
136
|
+
return request.decidedBy ?? (await byId(auth_base_1.User, request.decidedById));
|
|
137
|
+
}
|
|
138
|
+
async domain(request) {
|
|
139
|
+
return await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: request.domainId });
|
|
140
|
+
}
|
|
141
|
+
async creator(request) {
|
|
142
|
+
return await byId(auth_base_1.User, request.creatorId);
|
|
143
|
+
}
|
|
144
|
+
async updater(request) {
|
|
145
|
+
return await byId(auth_base_1.User, request.updaterId);
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
exports.ExpenditureRequestQuery = ExpenditureRequestQuery;
|
|
149
|
+
tslib_1.__decorate([
|
|
150
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting-self", privilege: "query", domainOwnerGranted: true)'),
|
|
151
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_type_1.ExpenditureRequestList, { description: "The caller's own expenditure requests" }),
|
|
152
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
153
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
154
|
+
tslib_1.__metadata("design:type", Function),
|
|
155
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
156
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
157
|
+
], ExpenditureRequestQuery.prototype, "myExpenditureRequests", null);
|
|
158
|
+
tslib_1.__decorate([
|
|
159
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting-self", privilege: "query", domainOwnerGranted: true)'),
|
|
160
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_1.ExpenditureRequest, { nullable: true, description: "One of the caller's own expenditure requests" }),
|
|
161
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
162
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
163
|
+
tslib_1.__metadata("design:type", Function),
|
|
164
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
165
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
166
|
+
], ExpenditureRequestQuery.prototype, "myExpenditureRequest", null);
|
|
167
|
+
tslib_1.__decorate([
|
|
168
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "query", domainOwnerGranted: true)'),
|
|
169
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_type_1.ExpenditureRequestList, { description: 'Every expenditure request of the domain' }),
|
|
170
|
+
tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
|
|
171
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
172
|
+
tslib_1.__metadata("design:type", Function),
|
|
173
|
+
tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
|
|
174
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
175
|
+
], ExpenditureRequestQuery.prototype, "expenditureRequests", null);
|
|
176
|
+
tslib_1.__decorate([
|
|
177
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "query", domainOwnerGranted: true)'),
|
|
178
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_1.ExpenditureRequest, { nullable: true, description: 'One expenditure request of the domain' }),
|
|
179
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
180
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
181
|
+
tslib_1.__metadata("design:type", Function),
|
|
182
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
183
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
184
|
+
], ExpenditureRequestQuery.prototype, "expenditureRequest", null);
|
|
185
|
+
tslib_1.__decorate([
|
|
186
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "query", domainOwnerGranted: true)'),
|
|
187
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_type_1.ExpenditureQueue, { description: 'Approved requests still to pay, and paid ones not yet matched to the bank' }),
|
|
188
|
+
tslib_1.__param(0, (0, type_graphql_1.Ctx)()),
|
|
189
|
+
tslib_1.__metadata("design:type", Function),
|
|
190
|
+
tslib_1.__metadata("design:paramtypes", [Object]),
|
|
191
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
192
|
+
], ExpenditureRequestQuery.prototype, "expenditureQueue", null);
|
|
193
|
+
tslib_1.__decorate([
|
|
194
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting", privilege: "query", domainOwnerGranted: true)'),
|
|
195
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_type_1.ExpenditureSummary, { description: 'Approved reimbursements per month, requester and category, with requests per status' }),
|
|
196
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('year', type => type_graphql_1.Int)),
|
|
197
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('month', type => type_graphql_1.Int, { nullable: true })),
|
|
198
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
199
|
+
tslib_1.__metadata("design:type", Function),
|
|
200
|
+
tslib_1.__metadata("design:paramtypes", [Number, Number, Object]),
|
|
201
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
202
|
+
], ExpenditureRequestQuery.prototype, "expenditureSummary", null);
|
|
203
|
+
tslib_1.__decorate([
|
|
204
|
+
(0, type_graphql_1.Directive)('@privilege(category: "accounting-self", privilege: "query", domainOwnerGranted: true)'),
|
|
205
|
+
(0, type_graphql_1.Query)(returns => expenditure_request_type_1.ExpenditureSummary, { description: "The caller's own monthly summary of reimbursements" }),
|
|
206
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('year', type => type_graphql_1.Int)),
|
|
207
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('month', type => type_graphql_1.Int, { nullable: true })),
|
|
208
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
209
|
+
tslib_1.__metadata("design:type", Function),
|
|
210
|
+
tslib_1.__metadata("design:paramtypes", [Number, Number, Object]),
|
|
211
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
212
|
+
], ExpenditureRequestQuery.prototype, "myExpenditureSummary", null);
|
|
213
|
+
tslib_1.__decorate([
|
|
214
|
+
(0, type_graphql_1.FieldResolver)(type => expenditure_request_type_1.ExpenditurePayment, { nullable: true }),
|
|
215
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
216
|
+
tslib_1.__metadata("design:type", Function),
|
|
217
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
218
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
219
|
+
], ExpenditureRequestQuery.prototype, "payment", null);
|
|
220
|
+
tslib_1.__decorate([
|
|
221
|
+
(0, type_graphql_1.FieldResolver)(type => [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
222
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
223
|
+
tslib_1.__metadata("design:type", Function),
|
|
224
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
225
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
226
|
+
], ExpenditureRequestQuery.prototype, "items", null);
|
|
227
|
+
tslib_1.__decorate([
|
|
228
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
229
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
230
|
+
tslib_1.__metadata("design:type", Function),
|
|
231
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
232
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
233
|
+
], ExpenditureRequestQuery.prototype, "requester", null);
|
|
234
|
+
tslib_1.__decorate([
|
|
235
|
+
(0, type_graphql_1.FieldResolver)(type => organization_1.Department, { nullable: true }),
|
|
236
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
237
|
+
tslib_1.__metadata("design:type", Function),
|
|
238
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
239
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
240
|
+
], ExpenditureRequestQuery.prototype, "department", null);
|
|
241
|
+
tslib_1.__decorate([
|
|
242
|
+
(0, type_graphql_1.FieldResolver)(type => biz_base_1.Counterparty, { nullable: true }),
|
|
243
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
244
|
+
tslib_1.__metadata("design:type", Function),
|
|
245
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
246
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
247
|
+
], ExpenditureRequestQuery.prototype, "counterparty", null);
|
|
248
|
+
tslib_1.__decorate([
|
|
249
|
+
(0, type_graphql_1.FieldResolver)(type => biz_base_1.CounterpartyBankAccount, { nullable: true }),
|
|
250
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
251
|
+
tslib_1.__metadata("design:type", Function),
|
|
252
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
253
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
254
|
+
], ExpenditureRequestQuery.prototype, "payeeAccount", null);
|
|
255
|
+
tslib_1.__decorate([
|
|
256
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
257
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
258
|
+
tslib_1.__metadata("design:type", Function),
|
|
259
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
260
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
261
|
+
], ExpenditureRequestQuery.prototype, "decidedBy", null);
|
|
262
|
+
tslib_1.__decorate([
|
|
263
|
+
(0, type_graphql_1.FieldResolver)(type => shell_1.Domain),
|
|
264
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
265
|
+
tslib_1.__metadata("design:type", Function),
|
|
266
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
267
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
268
|
+
], ExpenditureRequestQuery.prototype, "domain", null);
|
|
269
|
+
tslib_1.__decorate([
|
|
270
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
271
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
272
|
+
tslib_1.__metadata("design:type", Function),
|
|
273
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
274
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
275
|
+
], ExpenditureRequestQuery.prototype, "creator", null);
|
|
276
|
+
tslib_1.__decorate([
|
|
277
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
278
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
279
|
+
tslib_1.__metadata("design:type", Function),
|
|
280
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_1.ExpenditureRequest]),
|
|
281
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
282
|
+
], ExpenditureRequestQuery.prototype, "updater", null);
|
|
283
|
+
exports.ExpenditureRequestQuery = ExpenditureRequestQuery = tslib_1.__decorate([
|
|
284
|
+
(0, type_graphql_1.UseMiddleware)(shell_1.SpeakRefusals),
|
|
285
|
+
(0, type_graphql_1.Resolver)(expenditure_request_1.ExpenditureRequest)
|
|
286
|
+
], ExpenditureRequestQuery);
|
|
287
|
+
let ExpenditureRequestItemQuery = class ExpenditureRequestItemQuery {
|
|
288
|
+
async request(item) {
|
|
289
|
+
return item.request ?? (await byId(expenditure_request_1.ExpenditureRequest, item.requestId));
|
|
290
|
+
}
|
|
291
|
+
async account(item) {
|
|
292
|
+
return item.account ?? (await byId(account_1.Account, item.accountId));
|
|
293
|
+
}
|
|
294
|
+
async taxInvoice(item) {
|
|
295
|
+
return item.taxInvoice ?? (await byId(tax_invoice_1.TaxInvoice, item.taxInvoiceId, true));
|
|
296
|
+
}
|
|
297
|
+
/** Where the receipt is, or null - so an approver can see what was spent. */
|
|
298
|
+
async receiptUrl(item) {
|
|
299
|
+
const attachment = await (0, shell_1.getRepository)(attachment_base_1.Attachment).findOne({ where: { refType: expenditure_request_service_1.RECEIPT_REF_TYPE, refBy: item.id }, order: { createdAt: 'DESC' } });
|
|
300
|
+
return attachment?.fullpath ?? null;
|
|
301
|
+
}
|
|
302
|
+
async domain(item) {
|
|
303
|
+
return await (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: item.domainId });
|
|
304
|
+
}
|
|
305
|
+
async creator(item) {
|
|
306
|
+
return await byId(auth_base_1.User, item.creatorId);
|
|
307
|
+
}
|
|
308
|
+
async updater(item) {
|
|
309
|
+
return await byId(auth_base_1.User, item.updaterId);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
exports.ExpenditureRequestItemQuery = ExpenditureRequestItemQuery;
|
|
313
|
+
tslib_1.__decorate([
|
|
314
|
+
(0, type_graphql_1.FieldResolver)(type => expenditure_request_1.ExpenditureRequest, { nullable: true }),
|
|
315
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
316
|
+
tslib_1.__metadata("design:type", Function),
|
|
317
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
318
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
319
|
+
], ExpenditureRequestItemQuery.prototype, "request", null);
|
|
320
|
+
tslib_1.__decorate([
|
|
321
|
+
(0, type_graphql_1.FieldResolver)(type => account_1.Account, { nullable: true }),
|
|
322
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
323
|
+
tslib_1.__metadata("design:type", Function),
|
|
324
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
325
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
326
|
+
], ExpenditureRequestItemQuery.prototype, "account", null);
|
|
327
|
+
tslib_1.__decorate([
|
|
328
|
+
(0, type_graphql_1.FieldResolver)(type => tax_invoice_1.TaxInvoice, { nullable: true }),
|
|
329
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
330
|
+
tslib_1.__metadata("design:type", Function),
|
|
331
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
332
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
333
|
+
], ExpenditureRequestItemQuery.prototype, "taxInvoice", null);
|
|
334
|
+
tslib_1.__decorate([
|
|
335
|
+
(0, type_graphql_1.FieldResolver)(type => String, { nullable: true }),
|
|
336
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
337
|
+
tslib_1.__metadata("design:type", Function),
|
|
338
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
339
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
340
|
+
], ExpenditureRequestItemQuery.prototype, "receiptUrl", null);
|
|
341
|
+
tslib_1.__decorate([
|
|
342
|
+
(0, type_graphql_1.FieldResolver)(type => shell_1.Domain),
|
|
343
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
344
|
+
tslib_1.__metadata("design:type", Function),
|
|
345
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
346
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
347
|
+
], ExpenditureRequestItemQuery.prototype, "domain", null);
|
|
348
|
+
tslib_1.__decorate([
|
|
349
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
350
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
351
|
+
tslib_1.__metadata("design:type", Function),
|
|
352
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
353
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
354
|
+
], ExpenditureRequestItemQuery.prototype, "creator", null);
|
|
355
|
+
tslib_1.__decorate([
|
|
356
|
+
(0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
|
|
357
|
+
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
358
|
+
tslib_1.__metadata("design:type", Function),
|
|
359
|
+
tslib_1.__metadata("design:paramtypes", [expenditure_request_item_1.ExpenditureRequestItem]),
|
|
360
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
361
|
+
], ExpenditureRequestItemQuery.prototype, "updater", null);
|
|
362
|
+
exports.ExpenditureRequestItemQuery = ExpenditureRequestItemQuery = tslib_1.__decorate([
|
|
363
|
+
(0, type_graphql_1.Resolver)(expenditure_request_item_1.ExpenditureRequestItem)
|
|
364
|
+
], ExpenditureRequestItemQuery);
|
|
365
|
+
//# sourceMappingURL=expenditure-request-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expenditure-request-query.js","sourceRoot":"","sources":["../../../server/service/expenditure-request/expenditure-request-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Int, Query, Resolver, Root, UseMiddleware } from 'type-graphql'\nimport { Like } from 'typeorm'\n\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, SpeakRefusals } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { Attachment } from '@things-factory/attachment-base'\nimport { Counterparty, CounterpartyBankAccount } from '@things-factory/biz-base'\nimport { Department } from '@things-factory/organization'\nimport { TaxInvoice } from '@things-factory/tax-invoice'\n\nimport { Account } from '../account/account'\nimport { ExpenditureKind, ExpenditureRequest, ExpenditureRequestStatus } from './expenditure-request'\nimport { ExpenditureRequestItem } from './expenditure-request-item'\nimport { paymentStatesOf, ExpenditurePaymentState } from './expenditure-payment-state'\nimport { monthlySummary, statusCounts, type RequestStatus } from './expenditure-request-rules'\nimport { approvedWithStates, driftOf, RECEIPT_REF_TYPE } from './expenditure-request-service'\nimport { ExpenditurePayment, ExpenditureQueue, ExpenditureQueueRow, ExpenditureRequestList, ExpenditureSummary } from './expenditure-request-type'\n\nconst byId = async <T>(entity: new () => T, id: string | null | undefined, withDeleted = false): Promise<T | null> =>\n id ? ((await getRepository(entity).findOne({ where: { id } as any, withDeleted })) as T | null) : null\n\nasync function summaryOf(domain: { id: string }, year: number, month: number | undefined, requesterId?: string): Promise<ExpenditureSummary> {\n const period = month ? `${year}-${String(month).padStart(2, '0')}` : `${year}-%`\n const requests = await getRepository(ExpenditureRequest).find({\n where: {\n domain: { id: domain.id },\n kind: ExpenditureKind.REIMBURSEMENT,\n month: month ? period : Like(period),\n ...(requesterId ? { requester: { id: requesterId } } : {})\n } as any,\n relations: ['requester', 'items', 'items.account']\n })\n const shaped = requests.map(one => ({\n month: one.month,\n requesterId: one.requesterId ?? one.requester?.id,\n requesterName: one.requester?.name ?? null,\n status: one.status as RequestStatus,\n /* Summed by 계정과목; a line not yet filed counts under the category written on it. */\n items: (one.items ?? []).filter(item => !item.deletedAt).map(item => ({ ...item, category: item.account?.name ?? item.category }))\n }))\n\n const rows = monthlySummary(shaped)\n const approved = requests.filter(one => one.status === ExpenditureRequestStatus.APPROVED)\n approved.forEach(one => (one.items = (one.items ?? []).filter(item => !item.deletedAt)))\n const states = await paymentStatesOf(getRepository(ExpenditureRequest).manager, domain, approved as any)\n\n return {\n rows,\n statuses: Object.entries(statusCounts(shaped)).map(([status, count]) => ({ status, count })),\n approvedTotal: rows.reduce((sum, one) => sum + one.total, 0),\n unpaid: [...states.values()].reduce((sum, one) => sum + one.outstanding, 0)\n }\n}\n\n@UseMiddleware(SpeakRefusals)\n@Resolver(ExpenditureRequest)\nexport class ExpenditureRequestQuery {\n /** The caller's own requests - what an employee sees. */\n @Directive('@privilege(category: \"accounting-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureRequestList, { description: \"The caller's own expenditure requests\" })\n async myExpenditureRequests(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ExpenditureRequestList> {\n const { domain, user } = context.state\n const queryBuilder = getQueryBuilderFromListParams({ domain, params, repository: getRepository(ExpenditureRequest), searchables: ['title', 'notes'], alias: 'request' })\n queryBuilder.andWhere('request.requester = :requester', { requester: user.id })\n queryBuilder.addOrderBy('request.createdAt', 'DESC')\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n /** One of the caller's own requests, with its lines. */\n @Directive('@privilege(category: \"accounting-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureRequest, { nullable: true, description: \"One of the caller's own expenditure requests\" })\n async myExpenditureRequest(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ExpenditureRequest | null> {\n const { domain, user } = context.state\n return await getRepository(ExpenditureRequest).findOne({ where: { id, domain: { id: domain.id }, requester: { id: user.id } } as any })\n }\n\n /** Every request of the domain - what finance sees. */\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureRequestList, { description: 'Every expenditure request of the domain' })\n async expenditureRequests(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ExpenditureRequestList> {\n const { domain } = context.state\n const queryBuilder = getQueryBuilderFromListParams({ domain, params, repository: getRepository(ExpenditureRequest), searchables: ['title', 'notes'], alias: 'request' })\n queryBuilder.addOrderBy('request.createdAt', 'DESC')\n const [items, total] = await queryBuilder.getManyAndCount()\n return { items, total }\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureRequest, { nullable: true, description: 'One expenditure request of the domain' })\n async expenditureRequest(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ExpenditureRequest | null> {\n return await getRepository(ExpenditureRequest).findOne({ where: { id, domain: { id: context.state.domain.id } } as any })\n }\n\n /**\n * The payment queue (지급 대기) - approved requests still to pay, by the day they are to be paid, and the paid ones\n * whose bank line no statement has matched yet.\n */\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureQueue, { description: 'Approved requests still to pay, and paid ones not yet matched to the bank' })\n async expenditureQueue(@Ctx() context: ResolverContext): Promise<ExpenditureQueue> {\n const { domain } = context.state\n const manager = getRepository(ExpenditureRequest).manager\n const { requests, states } = await approvedWithStates(manager, domain)\n\n const rows: ExpenditureQueueRow[] = []\n for (const request of requests) {\n const payment = states.get(request.id)!\n if (payment.state === ExpenditurePaymentState.NOTHING_TO_PAY) continue\n rows.push({\n request,\n payment,\n payeeName: (request.kind === ExpenditureKind.VENDOR ? request.counterparty?.name : request.requester?.name) ?? undefined,\n payeeAccountDrift: payment.outstanding > 0 ? await driftOf(manager, request) : undefined\n })\n }\n const due = (row: ExpenditureQueueRow) => row.request.dueDate ?? '9999-12-31'\n const waiting = rows\n .filter(row => row.payment.outstanding > 0)\n .sort((a, b) => due(a).localeCompare(due(b)) || String(a.request.decidedAt ?? '').localeCompare(String(b.request.decidedAt ?? '')))\n const unreconciled = rows.filter(row => row.payment.outstanding <= 0 && !row.payment.reconciled)\n return { waiting, unreconciled }\n }\n\n @Directive('@privilege(category: \"accounting\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureSummary, { description: 'Approved reimbursements per month, requester and category, with requests per status' })\n async expenditureSummary(\n @Arg('year', type => Int) year: number,\n @Arg('month', type => Int, { nullable: true }) month: number,\n @Ctx() context: ResolverContext\n ): Promise<ExpenditureSummary> {\n return await summaryOf(context.state.domain, year, month || undefined)\n }\n\n @Directive('@privilege(category: \"accounting-self\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ExpenditureSummary, { description: \"The caller's own monthly summary of reimbursements\" })\n async myExpenditureSummary(\n @Arg('year', type => Int) year: number,\n @Arg('month', type => Int, { nullable: true }) month: number,\n @Ctx() context: ResolverContext\n ): Promise<ExpenditureSummary> {\n return await summaryOf(context.state.domain, year, month || undefined, context.state.user.id)\n }\n\n /** How far it is paid - read from its payments (ADR-0135 §2-4). */\n @FieldResolver(type => ExpenditurePayment, { nullable: true })\n async payment(@Root() request: ExpenditureRequest): Promise<ExpenditurePayment | null> {\n if (request.status !== ExpenditureRequestStatus.APPROVED) return null\n const items = await getRepository(ExpenditureRequestItem).find({ where: { request: { id: request.id } } as any })\n const states = await paymentStatesOf(getRepository(ExpenditureRequest).manager, { id: request.domainId! }, [{ id: request.id, items }])\n return states.get(request.id) ?? null\n }\n\n @FieldResolver(type => [ExpenditureRequestItem])\n async items(@Root() request: ExpenditureRequest): Promise<ExpenditureRequestItem[]> {\n if (request.items) return request.items.filter(item => !item.deletedAt)\n return await getRepository(ExpenditureRequestItem).find({ where: { request: { id: request.id } } as any, order: { spentDate: 'ASC', createdAt: 'ASC' } as any })\n }\n\n @FieldResolver(type => User, { nullable: true })\n async requester(@Root() request: ExpenditureRequest): Promise<User | null> {\n return request.requester ?? (await byId(User, request.requesterId))\n }\n\n @FieldResolver(type => Department, { nullable: true })\n async department(@Root() request: ExpenditureRequest): Promise<Department | null> {\n return request.department ?? (await byId(Department, request.departmentId))\n }\n\n @FieldResolver(type => Counterparty, { nullable: true })\n async counterparty(@Root() request: ExpenditureRequest): Promise<Counterparty | null> {\n return request.counterparty ?? (await byId(Counterparty, request.counterpartyId, true))\n }\n\n @FieldResolver(type => CounterpartyBankAccount, { nullable: true })\n async payeeAccount(@Root() request: ExpenditureRequest): Promise<CounterpartyBankAccount | null> {\n return request.payeeAccount ?? (await byId(CounterpartyBankAccount, request.payeeAccountId, true))\n }\n\n @FieldResolver(type => User, { nullable: true })\n async decidedBy(@Root() request: ExpenditureRequest): Promise<User | null> {\n return request.decidedBy ?? (await byId(User, request.decidedById))\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() request: ExpenditureRequest): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: request.domainId })\n }\n\n @FieldResolver(type => User, { nullable: true })\n async creator(@Root() request: ExpenditureRequest): Promise<User | null> {\n return await byId(User, request.creatorId)\n }\n\n @FieldResolver(type => User, { nullable: true })\n async updater(@Root() request: ExpenditureRequest): Promise<User | null> {\n return await byId(User, request.updaterId)\n }\n}\n\n@Resolver(ExpenditureRequestItem)\nexport class ExpenditureRequestItemQuery {\n @FieldResolver(type => ExpenditureRequest, { nullable: true })\n async request(@Root() item: ExpenditureRequestItem): Promise<ExpenditureRequest | null> {\n return item.request ?? (await byId(ExpenditureRequest, item.requestId))\n }\n\n @FieldResolver(type => Account, { nullable: true })\n async account(@Root() item: ExpenditureRequestItem): Promise<Account | null> {\n return item.account ?? (await byId(Account, item.accountId))\n }\n\n @FieldResolver(type => TaxInvoice, { nullable: true })\n async taxInvoice(@Root() item: ExpenditureRequestItem): Promise<TaxInvoice | null> {\n return item.taxInvoice ?? (await byId(TaxInvoice, item.taxInvoiceId, true))\n }\n\n /** Where the receipt is, or null - so an approver can see what was spent. */\n @FieldResolver(type => String, { nullable: true })\n async receiptUrl(@Root() item: ExpenditureRequestItem): Promise<string | null> {\n const attachment = await getRepository(Attachment).findOne({ where: { refType: RECEIPT_REF_TYPE, refBy: item.id }, order: { createdAt: 'DESC' } as any })\n return attachment?.fullpath ?? null\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() item: ExpenditureRequestItem): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: item.domainId })\n }\n\n @FieldResolver(type => User, { nullable: true })\n async creator(@Root() item: ExpenditureRequestItem): Promise<User | null> {\n return await byId(User, item.creatorId)\n }\n\n @FieldResolver(type => User, { nullable: true })\n async updater(@Root() item: ExpenditureRequestItem): Promise<User | null> {\n return await byId(User, item.updaterId)\n }\n}\n"]}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The rules of an expenditure request (ADR-0135) - who may change it when, what it pays, what a decision means, and
|
|
3
|
+
* the monthly summary.
|
|
4
|
+
*
|
|
5
|
+
* ── The life of a request ──────────────────────────────────────────────────────────────────────
|
|
6
|
+
* DRAFT ──submit──▶ SUBMITTED ──approved──▶ APPROVED ──bank lines pay it──▶ (paid, then reconciled)
|
|
7
|
+
* ▲ │ │
|
|
8
|
+
* │ │ └─rejected──▶ REJECTED ──edit & submit again──▶ SUBMITTED
|
|
9
|
+
* └────withdraw──────┘ (WITHDRAWN, editable again)
|
|
10
|
+
*
|
|
11
|
+
* Only the requester edits, and only while nobody is judging it (DRAFT, REJECTED, WITHDRAWN). What approvers saw is
|
|
12
|
+
* what is paid: once submitted the lines and the payee's account are frozen.
|
|
13
|
+
*
|
|
14
|
+
* Paid and reconciled are not states stored here; they are read from the payments (§`paymentStateFrom`).
|
|
15
|
+
*
|
|
16
|
+
* Pure.
|
|
17
|
+
*/
|
|
18
|
+
import { Refusal } from '@things-factory/shell';
|
|
19
|
+
export type RequestStatus = 'DRAFT' | 'SUBMITTED' | 'APPROVED' | 'REJECTED' | 'WITHDRAWN';
|
|
20
|
+
export type RequestKind = 'VENDOR' | 'REIMBURSEMENT';
|
|
21
|
+
export declare const EDITABLE: readonly RequestStatus[];
|
|
22
|
+
export interface RequestLine {
|
|
23
|
+
amount: number;
|
|
24
|
+
vatAmount?: number | null;
|
|
25
|
+
paymentMethod?: string | null;
|
|
26
|
+
category?: string | null;
|
|
27
|
+
accountId?: string | null;
|
|
28
|
+
spentDate?: string | null;
|
|
29
|
+
taxInvoiceId?: string | null;
|
|
30
|
+
}
|
|
31
|
+
/** A day as people write it - 2026-09-03, 2026.9.3, 2026/9/3 - in YYYY-MM-DD, or undefined when it is not one. */
|
|
32
|
+
export declare function dayOf(value: unknown): string | undefined;
|
|
33
|
+
/** A month as YYYY-MM, or undefined. */
|
|
34
|
+
export declare const monthOf: (value: unknown) => string | undefined;
|
|
35
|
+
export declare function canEdit(status: RequestStatus): boolean;
|
|
36
|
+
/** A line the company pays - everything but what the corporate card already paid. */
|
|
37
|
+
export declare const isPayable: (line: Pick<RequestLine, "paymentMethod">) => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* What a request totals, and what of it the company is to pay. **The one place this is decided** - the request's
|
|
40
|
+
* stored totals, the payment queue and every reader take it from here.
|
|
41
|
+
*/
|
|
42
|
+
export declare function totalsOf(lines: readonly RequestLine[]): {
|
|
43
|
+
total: number;
|
|
44
|
+
payable: number;
|
|
45
|
+
count: number;
|
|
46
|
+
};
|
|
47
|
+
export interface SubmittedHead {
|
|
48
|
+
kind: RequestKind;
|
|
49
|
+
status: RequestStatus;
|
|
50
|
+
month?: string | null;
|
|
51
|
+
dueDate?: string | null;
|
|
52
|
+
counterpartyId?: string | null;
|
|
53
|
+
payeeAccountId?: string | null;
|
|
54
|
+
}
|
|
55
|
+
/** Why a request cannot be submitted, or undefined when it can. */
|
|
56
|
+
export declare function submitRefusal(head: SubmittedHead, lines: readonly RequestLine[]): Refusal | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* What an approval outcome does to the request.
|
|
59
|
+
*
|
|
60
|
+
* worklist calls the activity's callback on every state change, and more than once for the same one. A decision lands
|
|
61
|
+
* only on the request **still waiting on that very instance** - once it has moved on (decided, or withdrawn and
|
|
62
|
+
* submitted again as a new instance) a late call changes nothing.
|
|
63
|
+
*/
|
|
64
|
+
export declare function decisionOf(instance: {
|
|
65
|
+
id: string;
|
|
66
|
+
state: string;
|
|
67
|
+
}, causedBy: readonly {
|
|
68
|
+
state?: string;
|
|
69
|
+
}[], request: {
|
|
70
|
+
status: RequestStatus;
|
|
71
|
+
activityInstanceId?: string | null;
|
|
72
|
+
}): 'APPROVED' | 'REJECTED' | 'WITHDRAWN' | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Which reimbursement a line added on the go joins - **the requester's editable one of that month.**
|
|
75
|
+
*
|
|
76
|
+
* The phone flow has no "request" step: a person snaps a receipt, types the amount and is done. The line goes to the
|
|
77
|
+
* month's draft; with none, to one sent back (rejected or withdrawn) so it can go up again with the rest; with none of
|
|
78
|
+
* those either, a new draft is started (undefined here). A request already with approvers or decided is never added
|
|
79
|
+
* to - what they saw stays what it was.
|
|
80
|
+
*/
|
|
81
|
+
export declare function requestForLine(requests: readonly {
|
|
82
|
+
id: string;
|
|
83
|
+
status: RequestStatus;
|
|
84
|
+
month?: string | null;
|
|
85
|
+
updatedAt?: Date | string | null;
|
|
86
|
+
}[], month: string): string | undefined;
|
|
87
|
+
/**
|
|
88
|
+
* Whether the account approvers saw is still the one on file - `gone` when the counterparty's account was deleted
|
|
89
|
+
* (deleting a counterparty deletes its accounts), `changed` when its number or holder is no longer what was written at
|
|
90
|
+
* submission, or the account was moved to another counterparty. Finance is told before paying.
|
|
91
|
+
*/
|
|
92
|
+
export declare function payeeAccountDrift(approved: {
|
|
93
|
+
counterpartyId?: string | null;
|
|
94
|
+
payeeAccountNumber?: string | null;
|
|
95
|
+
payeeHolderName?: string | null;
|
|
96
|
+
}, current: {
|
|
97
|
+
counterpartyId?: string | null;
|
|
98
|
+
accountNumber?: string | null;
|
|
99
|
+
holderName?: string | null;
|
|
100
|
+
deletedAt?: Date | string | null;
|
|
101
|
+
} | null | undefined, keyOf: (value: unknown) => string): 'gone' | 'changed' | undefined;
|
|
102
|
+
export interface SummaryRequest {
|
|
103
|
+
month?: string | null;
|
|
104
|
+
requesterId: string;
|
|
105
|
+
requesterName?: string | null;
|
|
106
|
+
status: RequestStatus;
|
|
107
|
+
items: RequestLine[];
|
|
108
|
+
}
|
|
109
|
+
export interface MonthSummaryRow {
|
|
110
|
+
month: string;
|
|
111
|
+
requesterId: string;
|
|
112
|
+
requesterName: string | null;
|
|
113
|
+
category: string;
|
|
114
|
+
total: number;
|
|
115
|
+
payable: number;
|
|
116
|
+
count: number;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The monthly summary - per month, requester and category.
|
|
120
|
+
*
|
|
121
|
+
* Only approved requests count; a draft or a rejected one is not spending the company agreed to. The caller shows the
|
|
122
|
+
* others as counts by status.
|
|
123
|
+
*/
|
|
124
|
+
export declare function monthlySummary(requests: readonly SummaryRequest[]): MonthSummaryRow[];
|
|
125
|
+
/** Requests per status - so drafts and pending ones are seen, not summed. */
|
|
126
|
+
export declare function statusCounts(requests: readonly {
|
|
127
|
+
status: RequestStatus;
|
|
128
|
+
}[]): Record<RequestStatus, number>;
|