@things-factory/accounting 8.0.0-beta.9 → 8.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/client/activities/activity-book-edit.ts +88 -0
- package/client/activities/activity-book-view.ts +88 -0
- package/client/activities/activity-expense-edit.ts +88 -0
- package/client/activities/activity-expense-view.ts +88 -0
- package/client/bootstrap.ts +10 -0
- package/client/components/accounting-category-selector.ts +136 -0
- package/client/components/accounting-category-view.ts +75 -0
- package/client/grist-editors/grist-editor-accounting-category-object.ts +83 -0
- package/client/grist-editors/grist-renderer-accounting-category-object.ts +13 -0
- package/client/index.ts +0 -0
- package/client/pages/account/account-importer.ts +97 -0
- package/client/pages/account/account-list-page.ts +364 -0
- package/client/pages/accounting-category/accounting-category-importer.ts +97 -0
- package/client/pages/accounting-category/accounting-category-list-page.ts +368 -0
- package/client/pages/accounting-category/accounting-category-tree-page.ts +338 -0
- package/client/pages/accounting-document/accounting-document-importer.ts +90 -0
- package/client/pages/accounting-document/accounting-document-list-page.ts +398 -0
- package/client/pages/financial-statement/financial-statement-importer.ts +97 -0
- package/client/pages/financial-statement/financial-statement-list-page.ts +338 -0
- package/client/pages/fiscal-month/fiscal-month-importer.ts +90 -0
- package/client/pages/fiscal-month/fiscal-month-list-page.ts +398 -0
- package/client/pages/fiscal-quarter/fiscal-quarter-importer.ts +90 -0
- package/client/pages/fiscal-quarter/fiscal-quarter-list-page.ts +398 -0
- package/client/pages/fiscal-year/fiscal-year-importer.ts +90 -0
- package/client/pages/fiscal-year/fiscal-year-list-page.ts +398 -0
- package/client/pages/income-statement/income-statement-importer.ts +97 -0
- package/client/pages/income-statement/income-statement-list-page.ts +338 -0
- package/client/pages/payment/payment-importer.ts +90 -0
- package/client/pages/payment/payment-list-page.ts +398 -0
- package/client/pages/transaction/transaction-importer.ts +97 -0
- package/client/pages/transaction/transaction-list-page.ts +338 -0
- package/client/route.ts +35 -0
- package/client/tsconfig.json +13 -0
- package/client/types/accounting-category.ts +23 -0
- package/client/types/index.ts +1 -0
- package/dist-client/pages/accounting-category/accounting-category-tree-page.js +1 -1
- package/dist-client/pages/accounting-category/accounting-category-tree-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/index.d.ts +2 -3
- package/dist-server/service/index.js +0 -5
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/payment/index.d.ts +2 -1
- package/dist-server/service/payment/payment-history.d.ts +1 -8
- package/dist-server/service/payment/payment-history.js +10 -41
- package/dist-server/service/payment/payment-history.js.map +1 -1
- package/dist-server/service/payment/payment-type.d.ts +1 -7
- package/dist-server/service/payment/payment-type.js +0 -24
- package/dist-server/service/payment/payment-type.js.map +1 -1
- package/dist-server/service/payment/payment.d.ts +0 -12
- package/dist-server/service/payment/payment.js +1 -36
- package/dist-server/service/payment/payment.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/server/activities/activity-book.ts +172 -0
- package/server/activities/activity-expense.ts +149 -0
- package/server/activities/index.ts +18 -0
- package/server/controllers/index.ts +1 -0
- package/server/controllers/summary-statements.ts +166 -0
- package/server/index.ts +6 -0
- package/server/middlewares/index.ts +3 -0
- package/server/migrations/1725200507196-seed-fiscal-entities.ts +106 -0
- package/server/migrations/1725201467183-seed-accounts.ts +339 -0
- package/server/migrations/index.ts +9 -0
- package/server/routes.ts +26 -0
- package/server/service/account/account-history.ts +117 -0
- package/server/service/account/account-mutation.ts +140 -0
- package/server/service/account/account-query.ts +51 -0
- package/server/service/account/account-type.ts +44 -0
- package/server/service/account/account.ts +97 -0
- package/server/service/account/event-subscriber.ts +17 -0
- package/server/service/account/index.ts +9 -0
- package/server/service/accounting-category/accounting-category-history.ts +129 -0
- package/server/service/accounting-category/accounting-category-mutation.ts +148 -0
- package/server/service/accounting-category/accounting-category-query.ts +74 -0
- package/server/service/accounting-category/accounting-category-type.ts +48 -0
- package/server/service/accounting-category/accounting-category.ts +100 -0
- package/server/service/accounting-category/event-subscriber.ts +20 -0
- package/server/service/accounting-category/index.ts +9 -0
- package/server/service/accounting-document/accounting-document-history.ts +123 -0
- package/server/service/accounting-document/accounting-document-mutation.ts +137 -0
- package/server/service/accounting-document/accounting-document-query.ts +48 -0
- package/server/service/accounting-document/accounting-document-type.ts +52 -0
- package/server/service/accounting-document/accounting-document.ts +93 -0
- package/server/service/accounting-document/event-subscriber.ts +17 -0
- package/server/service/accounting-document/index.ts +9 -0
- package/server/service/common-type.ts +12 -0
- package/server/service/financial-statement/event-subscriber.ts +17 -0
- package/server/service/financial-statement/financial-statement-history.ts +129 -0
- package/server/service/financial-statement/financial-statement-line-item.ts +82 -0
- package/server/service/financial-statement/financial-statement-mutation.ts +148 -0
- package/server/service/financial-statement/financial-statement-query.ts +53 -0
- package/server/service/financial-statement/financial-statement-type.ts +51 -0
- package/server/service/financial-statement/financial-statement.ts +116 -0
- package/server/service/financial-statement/index.ts +10 -0
- package/server/service/fiscal-month/fiscal-month-mutation.ts +145 -0
- package/server/service/fiscal-month/fiscal-month-query.ts +58 -0
- package/server/service/fiscal-month/fiscal-month-type.ts +66 -0
- package/server/service/fiscal-month/fiscal-month.ts +84 -0
- package/server/service/fiscal-month/index.ts +7 -0
- package/server/service/fiscal-quarter/fiscal-quarter-mutation.ts +148 -0
- package/server/service/fiscal-quarter/fiscal-quarter-query.ts +60 -0
- package/server/service/fiscal-quarter/fiscal-quarter-type.ts +60 -0
- package/server/service/fiscal-quarter/fiscal-quarter.ts +80 -0
- package/server/service/fiscal-quarter/index.ts +7 -0
- package/server/service/fiscal-year/fiscal-year-mutation.ts +145 -0
- package/server/service/fiscal-year/fiscal-year-query.ts +53 -0
- package/server/service/fiscal-year/fiscal-year-type.ts +54 -0
- package/server/service/fiscal-year/fiscal-year.ts +76 -0
- package/server/service/fiscal-year/index.ts +7 -0
- package/server/service/income-statement/event-subscriber.ts +17 -0
- package/server/service/income-statement/income-statement-history.ts +133 -0
- package/server/service/income-statement/income-statement-line-item.ts +84 -0
- package/server/service/income-statement/income-statement-mutation.ts +147 -0
- package/server/service/income-statement/income-statement-query.ts +50 -0
- package/server/service/income-statement/income-statement-type.ts +51 -0
- package/server/service/income-statement/income-statement.ts +120 -0
- package/server/service/income-statement/index.ts +10 -0
- package/server/service/index.ts +108 -0
- package/server/service/payment/event-subscriber.ts +17 -0
- package/server/service/payment/index.ts +9 -0
- package/server/service/payment/payment-history.ts +132 -0
- package/server/service/payment/payment-mutation.ts +139 -0
- package/server/service/payment/payment-query.ts +50 -0
- package/server/service/payment/payment-type.ts +64 -0
- package/server/service/payment/payment.ts +123 -0
- package/server/service/transaction/event-subscriber.ts +17 -0
- package/server/service/transaction/index.ts +9 -0
- package/server/service/transaction/transaction-history.ts +161 -0
- package/server/service/transaction/transaction-mutation.ts +146 -0
- package/server/service/transaction/transaction-query.ts +50 -0
- package/server/service/transaction/transaction-type.ts +48 -0
- package/server/service/transaction/transaction.ts +230 -0
- package/server/tsconfig.json +10 -0
- package/dist-client/pages/bank/bank-importer.d.ts +0 -23
- package/dist-client/pages/bank/bank-importer.js +0 -93
- package/dist-client/pages/bank/bank-importer.js.map +0 -1
- package/dist-client/pages/bank/bank-list-page.d.ts +0 -66
- package/dist-client/pages/bank/bank-list-page.js +0 -370
- package/dist-client/pages/bank/bank-list-page.js.map +0 -1
- package/dist-client/pages/bank-account/bank-account-importer.d.ts +0 -23
- package/dist-client/pages/bank-account/bank-account-importer.js +0 -93
- package/dist-client/pages/bank-account/bank-account-importer.js.map +0 -1
- package/dist-client/pages/bank-account/bank-account-list-page.d.ts +0 -66
- package/dist-client/pages/bank-account/bank-account-list-page.js +0 -370
- package/dist-client/pages/bank-account/bank-account-list-page.js.map +0 -1
- package/dist-client/pages/financial-institution/financial-institution-importer.d.ts +0 -23
- package/dist-client/pages/financial-institution/financial-institution-importer.js +0 -93
- package/dist-client/pages/financial-institution/financial-institution-importer.js.map +0 -1
- package/dist-client/pages/financial-institution/financial-institution-list-page.d.ts +0 -66
- package/dist-client/pages/financial-institution/financial-institution-list-page.js +0 -370
- package/dist-client/pages/financial-institution/financial-institution-list-page.js.map +0 -1
- package/dist-server/migrations/1725201567284-seed-country-codes.d.ts +0 -5
- package/dist-server/migrations/1725201567284-seed-country-codes.js +0 -248
- package/dist-server/migrations/1725201567284-seed-country-codes.js.map +0 -1
- package/dist-server/migrations/1725201667385-seed-financial-institutions.d.ts +0 -5
- package/dist-server/migrations/1725201667385-seed-financial-institutions.js +0 -348
- package/dist-server/migrations/1725201667385-seed-financial-institutions.js.map +0 -1
- package/dist-server/service/bank-account/bank-account-history.d.ts +0 -34
- package/dist-server/service/bank-account/bank-account-history.js +0 -172
- package/dist-server/service/bank-account/bank-account-history.js.map +0 -1
- package/dist-server/service/bank-account/bank-account-mutation.d.ts +0 -10
- package/dist-server/service/bank-account/bank-account-mutation.js +0 -128
- package/dist-server/service/bank-account/bank-account-mutation.js.map +0 -1
- package/dist-server/service/bank-account/bank-account-query.d.ts +0 -11
- package/dist-server/service/bank-account/bank-account-query.js +0 -79
- package/dist-server/service/bank-account/bank-account-query.js.map +0 -1
- package/dist-server/service/bank-account/bank-account-type.d.ts +0 -39
- package/dist-server/service/bank-account/bank-account-type.js +0 -153
- package/dist-server/service/bank-account/bank-account-type.js.map +0 -1
- package/dist-server/service/bank-account/bank-account.d.ts +0 -38
- package/dist-server/service/bank-account/bank-account.js +0 -164
- package/dist-server/service/bank-account/bank-account.js.map +0 -1
- package/dist-server/service/bank-account/event-subscriber.d.ts +0 -7
- package/dist-server/service/bank-account/event-subscriber.js +0 -21
- package/dist-server/service/bank-account/event-subscriber.js.map +0 -1
- package/dist-server/service/bank-account/index.d.ts +0 -7
- package/dist-server/service/bank-account/index.js +0 -12
- package/dist-server/service/bank-account/index.js.map +0 -1
- package/dist-server/service/financial-institution/financial-institution-mutation.d.ts +0 -10
- package/dist-server/service/financial-institution/financial-institution-mutation.js +0 -169
- package/dist-server/service/financial-institution/financial-institution-mutation.js.map +0 -1
- package/dist-server/service/financial-institution/financial-institution-query.d.ts +0 -12
- package/dist-server/service/financial-institution/financial-institution-query.js +0 -97
- package/dist-server/service/financial-institution/financial-institution-query.js.map +0 -1
- package/dist-server/service/financial-institution/financial-institution-type.d.ts +0 -32
- package/dist-server/service/financial-institution/financial-institution-type.js +0 -126
- package/dist-server/service/financial-institution/financial-institution-type.js.map +0 -1
- package/dist-server/service/financial-institution/financial-institution.d.ts +0 -34
- package/dist-server/service/financial-institution/financial-institution.js +0 -137
- package/dist-server/service/financial-institution/financial-institution.js.map +0 -1
- package/dist-server/service/financial-institution/index.d.ts +0 -6
- package/dist-server/service/financial-institution/index.js +0 -10
- package/dist-server/service/financial-institution/index.js.map +0 -1
- package/helps/accounting/bank-account.md +0 -160
- package/helps/accounting/bank.md +0 -160
- package/helps/accounting/financial-institution.md +0 -160
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/accounting",
|
3
|
-
"version": "8.0.0
|
3
|
+
"version": "8.0.0",
|
4
4
|
"main": "dist-server/index.js",
|
5
5
|
"browser": "dist-client/index.js",
|
6
6
|
"things-factory": true,
|
@@ -28,11 +28,11 @@
|
|
28
28
|
},
|
29
29
|
"dependencies": {
|
30
30
|
"@material/web": "^2.0.0",
|
31
|
-
"@operato/graphql": "^
|
32
|
-
"@operato/shell": "^
|
33
|
-
"@things-factory/auth-base": "^8.0.0
|
34
|
-
"@things-factory/shell": "^8.0.0
|
35
|
-
"@things-factory/worklist": "^8.0.0
|
31
|
+
"@operato/graphql": "^7.1.0",
|
32
|
+
"@operato/shell": "^7.1.0",
|
33
|
+
"@things-factory/auth-base": "^8.0.0",
|
34
|
+
"@things-factory/shell": "^8.0.0",
|
35
|
+
"@things-factory/worklist": "^8.0.0"
|
36
36
|
},
|
37
|
-
"gitHead": "
|
37
|
+
"gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
|
38
38
|
}
|
@@ -0,0 +1,172 @@
|
|
1
|
+
import {
|
2
|
+
Activity,
|
3
|
+
ActivityInstance,
|
4
|
+
ActivityInstanceStatus,
|
5
|
+
ActivityThread,
|
6
|
+
UpdateActivityInstanceStateAddendum
|
7
|
+
} from '@things-factory/worklist'
|
8
|
+
|
9
|
+
async function callback(
|
10
|
+
activityInstance: ActivityInstance,
|
11
|
+
addendum: UpdateActivityInstanceStateAddendum,
|
12
|
+
context: ResolverContext
|
13
|
+
) {
|
14
|
+
const { domain, tx } = context.state
|
15
|
+
const { input, output, state } = activityInstance
|
16
|
+
const { causedBy } = addendum || {}
|
17
|
+
|
18
|
+
if (state == ActivityInstanceStatus.Ended) {
|
19
|
+
const activity = (await tx.getRepository(Activity).findOneBy({
|
20
|
+
domain: { id: domain.id },
|
21
|
+
name: 'Book'
|
22
|
+
})) as Activity
|
23
|
+
|
24
|
+
/*
|
25
|
+
The Book activity is designed to be performed by a single assignee (thread).
|
26
|
+
Therefore, we take a sample from the output as data.
|
27
|
+
If it were an activity performed by multiple assignees (threads),
|
28
|
+
we would process the entire output as data.
|
29
|
+
*/
|
30
|
+
const assignees = Object.keys(output)
|
31
|
+
const data = assignees.length > 0 && output[assignees[0]]
|
32
|
+
|
33
|
+
if (activity) {
|
34
|
+
/*
|
35
|
+
Custom logic goes here.
|
36
|
+
Typically, this would involve recording the accounting transaction
|
37
|
+
or updating related data in the accounting system.
|
38
|
+
For example, you might:
|
39
|
+
1. Save the transaction to the database
|
40
|
+
2. Update account balances
|
41
|
+
3. Generate necessary reports or notifications
|
42
|
+
*/
|
43
|
+
} else {
|
44
|
+
console.error('Book Activity not installed.')
|
45
|
+
}
|
46
|
+
} else if (state == ActivityInstanceStatus.Aborted) {
|
47
|
+
// Implement logic for handling aborted activities here
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
export const ActivityBook = {
|
52
|
+
name: 'Book',
|
53
|
+
description: 'An activity that records income or expenses in the accounting system',
|
54
|
+
release: '1.0.0',
|
55
|
+
provider: 'hatiolab.com',
|
56
|
+
category: 'accounting',
|
57
|
+
activityType: 'user',
|
58
|
+
priority: 1,
|
59
|
+
searchKeys: [
|
60
|
+
// sample search keys
|
61
|
+
{
|
62
|
+
name: 'category',
|
63
|
+
description: 'expense category',
|
64
|
+
inputKey: 'category',
|
65
|
+
tKey: 'category'
|
66
|
+
}
|
67
|
+
],
|
68
|
+
/*
|
69
|
+
Setting an activity as startable means it can be manually initiated and assigned.
|
70
|
+
Users with the defined issuer role can start it, or all users if no issuer is defined.
|
71
|
+
The process of starting allows for manual adjustment of assignees and approval-line,
|
72
|
+
with activity settings as the default.
|
73
|
+
*/
|
74
|
+
startable: true,
|
75
|
+
/* (Unimplemented property)
|
76
|
+
startingType can be set to 'issue' or 'post'. 'post' type allows for start, assign, and end
|
77
|
+
to be done at once by a single user. Users only see draft and post stages for this activity.
|
78
|
+
All model properties should be 'in' or 'inout' in this case, as 'out' properties won't have
|
79
|
+
a chance for input. Assignees settings are meaningless in this case.
|
80
|
+
If an approval-line is set, it will still be processed through the approval process.
|
81
|
+
For 'issue' type, 'in' or 'inout' properties of the model are filled and assigned to the assignee,
|
82
|
+
so an assignee must be set.
|
83
|
+
*/
|
84
|
+
startingType: 'post',
|
85
|
+
/* (Unimplemented property)
|
86
|
+
The multiple property can be set to 'parallel' or 'sequential'. 'parallel' processes multiple
|
87
|
+
instances (threads) in parallel, while 'sequential' processes them in sequence.
|
88
|
+
If not set, it implies single instance execution, where only one assignee is allocated even if
|
89
|
+
multiple are set. In this case, the activity instance's result data (output) is directly applied
|
90
|
+
from the single thread's output.
|
91
|
+
*/
|
92
|
+
multiple: null,
|
93
|
+
model: [
|
94
|
+
{
|
95
|
+
name: 'name',
|
96
|
+
description: 'name',
|
97
|
+
tag: 'name',
|
98
|
+
hidden: false,
|
99
|
+
mandatory: true,
|
100
|
+
inout: 'in',
|
101
|
+
type: 'select',
|
102
|
+
options: {
|
103
|
+
options: ['KRW', 'USD', 'CNY']
|
104
|
+
},
|
105
|
+
unit: null,
|
106
|
+
quantifier: [1],
|
107
|
+
spec: {}
|
108
|
+
},
|
109
|
+
{
|
110
|
+
name: 'currency',
|
111
|
+
description: 'currency',
|
112
|
+
tag: 'currency',
|
113
|
+
hidden: false,
|
114
|
+
mandatory: true,
|
115
|
+
inout: 'in',
|
116
|
+
type: 'select',
|
117
|
+
options: {
|
118
|
+
options: ['KRW', 'USD', 'CNY']
|
119
|
+
},
|
120
|
+
unit: null,
|
121
|
+
quantifier: [1],
|
122
|
+
spec: {}
|
123
|
+
},
|
124
|
+
{
|
125
|
+
name: 'amount',
|
126
|
+
description: 'amount',
|
127
|
+
tag: 'amount',
|
128
|
+
hidden: false,
|
129
|
+
mandatory: true,
|
130
|
+
inout: 'in',
|
131
|
+
type: 'number',
|
132
|
+
options: {},
|
133
|
+
unit: null,
|
134
|
+
quantifier: [1],
|
135
|
+
spec: {}
|
136
|
+
},
|
137
|
+
{
|
138
|
+
name: 'category',
|
139
|
+
description: 'accounting category',
|
140
|
+
tag: 'category',
|
141
|
+
hidden: true,
|
142
|
+
mandatory: true,
|
143
|
+
inout: 'in',
|
144
|
+
type: 'string',
|
145
|
+
options: {},
|
146
|
+
unit: null,
|
147
|
+
quantifier: [1],
|
148
|
+
spec: {}
|
149
|
+
},
|
150
|
+
{
|
151
|
+
name: 'date',
|
152
|
+
description: 'issuance date',
|
153
|
+
tag: 'date',
|
154
|
+
hidden: true,
|
155
|
+
mandatory: true,
|
156
|
+
inout: 'in',
|
157
|
+
type: 'string',
|
158
|
+
options: {},
|
159
|
+
unit: null,
|
160
|
+
quantifier: [1],
|
161
|
+
spec: {}
|
162
|
+
}
|
163
|
+
],
|
164
|
+
uiType: 'generated',
|
165
|
+
uiSource: '',
|
166
|
+
viewType: 'generated',
|
167
|
+
viewSource: '',
|
168
|
+
reportType: 'custom-element',
|
169
|
+
reportSource: 'activity-book-report',
|
170
|
+
thumbnail: '/assets/images/book-activity.jpg',
|
171
|
+
callback /* Called when there is a change in the lifecycle of a task (activity-instance). */
|
172
|
+
}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
import { Activity, ActivityInstance, ActivityInstanceStatus } from '@things-factory/worklist'
|
2
|
+
|
3
|
+
async function callback(activityInstance: ActivityInstance, context: ResolverContext) {
|
4
|
+
const { domain, tx } = context.state
|
5
|
+
const { input, output, state } = activityInstance
|
6
|
+
|
7
|
+
if (state == ActivityInstanceStatus.Ended) {
|
8
|
+
const activity = (await tx.getRepository(Activity).findOneBy({
|
9
|
+
domain: { id: domain.id },
|
10
|
+
name: 'Expense'
|
11
|
+
})) as Activity
|
12
|
+
|
13
|
+
/*
|
14
|
+
expense 액티비티는 한명의 assignee(thread)만 수행하도록 한다. 따라서, output 중에서 샘플 한 개만을 data로 취한다.
|
15
|
+
만약, 여러 assignees(threads)가 수행하는 액티비티인 경우에는 output 전체를 data로 처리한다.
|
16
|
+
*/
|
17
|
+
const assignees = Object.keys(output)
|
18
|
+
const data = assignees.length > 0 && output[assignees[0]]
|
19
|
+
|
20
|
+
if (activity) {
|
21
|
+
/*
|
22
|
+
custom logic goes here.
|
23
|
+
주로,
|
24
|
+
*/
|
25
|
+
} else {
|
26
|
+
console.error('Expense Activity not installed.')
|
27
|
+
}
|
28
|
+
} else if (state == ActivityInstanceStatus.Aborted) {
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
export const ActivityExpense = {
|
33
|
+
name: 'Expense',
|
34
|
+
description: 'An activity for reporting and approving expense spending',
|
35
|
+
release: '1.0.0',
|
36
|
+
provider: 'hatiolab.com',
|
37
|
+
category: 'accounting',
|
38
|
+
activityType: 'user',
|
39
|
+
priority: 1,
|
40
|
+
searchKeys: [
|
41
|
+
// sample search keys
|
42
|
+
{
|
43
|
+
name: 'category',
|
44
|
+
description: 'expense category',
|
45
|
+
inputKey: 'category',
|
46
|
+
tKey: 'category'
|
47
|
+
}
|
48
|
+
],
|
49
|
+
/*
|
50
|
+
startable 설정된 액티비티는 수동으로 업무를 시작하여, 할당할 수 있음을 의미한다.
|
51
|
+
issuer로 정의된 역할을 갖는 사용자가 시작할 수 있으며, issuer가 정의되지 않았다면 모든 사용자가 시작할 수 있다.
|
52
|
+
업무를 시작하는 과정에서 assignees와 approval-line은 액티비티의 설정을 디폴트로 하지만 수동으로 조정할 수 있다.
|
53
|
+
*/
|
54
|
+
startable: true,
|
55
|
+
/* (미구현 속성)
|
56
|
+
startingType 설정된 액티비티는 'issue' 또는 'post' 이 될 수 있다. 'post' 타입은 혼자서 start, assign, end 까지 한번에 다하는 특성을 갖는다. 이 액티비티를 수행하는 사용자는 draft(초안)과 post(완료)단계만 인식하게 된다.
|
57
|
+
이 경우의 모델은 모두 'in' 또는 'inout'의 속성을 갖는 것이 좋다. 'out' 속성의 데이타는 입력될 기회를 갖지 못한다.
|
58
|
+
이 경우의 assignees 설정은 의미가 없다.
|
59
|
+
이 경우에도 approval-line이 설정되어 있다면, 승인 프로세스에 의해서 처리된다.
|
60
|
+
'issue' 타입인 경우에는 모델의 'in' 또는 'inout' 속성을 채워서 assignee에게 할당하는 방식이므로 assignee가 설정되어야 한다.
|
61
|
+
*/
|
62
|
+
startingType: 'post',
|
63
|
+
/* (미구현 속성)
|
64
|
+
multiple 속성은 'parallel', 'sequential' 값을 설정할 수 있다. parallel로 설정하면, 다중 인스턴스(여기서는 다중 쓰레드)로 처리하되 병렬처리되며,
|
65
|
+
sequential로 설정하면 순차적으로 다중 인스턴스가 수행된다.
|
66
|
+
설정하지 않으면, single 인스턴스로 수행된다는 의미이며, 이 경우 assignees가 여럿이 설정되어있어도 1명에게만 할당되게 된다.
|
67
|
+
이 경우에는 액티비티 인스턴스의 결과 데이타(output)도 단일 쓰레드의 output이 그대로 적용된다.
|
68
|
+
*/
|
69
|
+
multiple: null,
|
70
|
+
model: [
|
71
|
+
{
|
72
|
+
name: 'name',
|
73
|
+
description: 'name',
|
74
|
+
tag: 'name',
|
75
|
+
hidden: false,
|
76
|
+
mandatory: true,
|
77
|
+
inout: 'in',
|
78
|
+
type: 'select',
|
79
|
+
options: {
|
80
|
+
options: ['KRW', 'USD', 'CNY']
|
81
|
+
},
|
82
|
+
unit: null,
|
83
|
+
quantifier: [1],
|
84
|
+
spec: {}
|
85
|
+
},
|
86
|
+
{
|
87
|
+
name: 'currency',
|
88
|
+
description: 'currency',
|
89
|
+
tag: 'currency',
|
90
|
+
hidden: false,
|
91
|
+
mandatory: true,
|
92
|
+
inout: 'in',
|
93
|
+
type: 'select',
|
94
|
+
options: {
|
95
|
+
options: ['KRW', 'USD', 'CNY']
|
96
|
+
},
|
97
|
+
unit: null,
|
98
|
+
quantifier: [1],
|
99
|
+
spec: {}
|
100
|
+
},
|
101
|
+
{
|
102
|
+
name: 'amount',
|
103
|
+
description: 'amount',
|
104
|
+
tag: 'amount',
|
105
|
+
hidden: false,
|
106
|
+
mandatory: true,
|
107
|
+
inout: 'in',
|
108
|
+
type: 'number',
|
109
|
+
options: {},
|
110
|
+
unit: null,
|
111
|
+
quantifier: [1],
|
112
|
+
spec: {}
|
113
|
+
},
|
114
|
+
{
|
115
|
+
name: 'category',
|
116
|
+
description: 'expense category',
|
117
|
+
tag: 'category',
|
118
|
+
hidden: true,
|
119
|
+
mandatory: true,
|
120
|
+
inout: 'in',
|
121
|
+
type: 'string',
|
122
|
+
options: {},
|
123
|
+
unit: null,
|
124
|
+
quantifier: [1],
|
125
|
+
spec: {}
|
126
|
+
},
|
127
|
+
{
|
128
|
+
name: 'date',
|
129
|
+
description: 'expense spent date',
|
130
|
+
tag: 'date',
|
131
|
+
hidden: true,
|
132
|
+
mandatory: true,
|
133
|
+
inout: 'in',
|
134
|
+
type: 'string',
|
135
|
+
options: {},
|
136
|
+
unit: null,
|
137
|
+
quantifier: [1],
|
138
|
+
spec: {}
|
139
|
+
}
|
140
|
+
],
|
141
|
+
uiType: 'generated',
|
142
|
+
uiSource: '',
|
143
|
+
viewType: 'generated',
|
144
|
+
viewSource: '',
|
145
|
+
reportType: 'custom-element',
|
146
|
+
reportSource: 'activity-expense-report',
|
147
|
+
thumbnail: '/assets/images/expense-activity.jpg',
|
148
|
+
callback /* Called when there is a change in the lifecycle of a task (activity-instance). */
|
149
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { ActivityInstallations } from '@things-factory/worklist'
|
2
|
+
|
3
|
+
/* IMPORT ACTIVITY TEMPLATES */
|
4
|
+
import { ActivityExpense } from './activity-expense'
|
5
|
+
import { ActivityBook } from './activity-book'
|
6
|
+
;[
|
7
|
+
/* ACTIVITY TEMPLATES */
|
8
|
+
ActivityExpense,
|
9
|
+
ActivityBook
|
10
|
+
].forEach(template => {
|
11
|
+
ActivityInstallations.installActivityTemplate(template as any)
|
12
|
+
})
|
13
|
+
|
14
|
+
/*
|
15
|
+
Add the following line to server/index.ts so that activities can be registered when loading a module.
|
16
|
+
--
|
17
|
+
import './activities'
|
18
|
+
*/
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './summary-statements'
|
@@ -0,0 +1,166 @@
|
|
1
|
+
import { getRepository } from '@things-factory/shell'
|
2
|
+
|
3
|
+
import { FinancialStatement } from '../service/financial-statement/financial-statement'
|
4
|
+
import { IncomeStatement } from '../service/income-statement/income-statement'
|
5
|
+
import { Transaction, TransactionType } from '../service/transaction/transaction'
|
6
|
+
import { Payment, PaymentDirection } from '../service/payment/payment'
|
7
|
+
|
8
|
+
export async function calculateMonthlyStatements(year: number, month: number): Promise<void> {
|
9
|
+
const transactionRepository = getRepository(Transaction)
|
10
|
+
const paymentRepository = getRepository(Payment)
|
11
|
+
const financialStatementRepository = getRepository(FinancialStatement)
|
12
|
+
const incomeStatementRepository = getRepository(IncomeStatement)
|
13
|
+
|
14
|
+
// 재무제표 계산
|
15
|
+
const financialResult = await transactionRepository
|
16
|
+
.createQueryBuilder('transaction')
|
17
|
+
.leftJoinAndSelect('transaction.payments', 'payment')
|
18
|
+
.select([
|
19
|
+
'SUM(CASE WHEN transaction.type = :asset THEN payment.amount ELSE 0 END) AS asset',
|
20
|
+
'SUM(CASE WHEN transaction.type = :liability THEN payment.amount ELSE 0 END) AS liability',
|
21
|
+
'SUM(CASE WHEN transaction.type = :equity THEN payment.amount ELSE 0 END) AS equity'
|
22
|
+
])
|
23
|
+
.where('transaction.year = :year', { year })
|
24
|
+
.andWhere('transaction.month = :month', { month })
|
25
|
+
.andWhere('payment.direction = :incoming', { incoming: PaymentDirection.Incoming })
|
26
|
+
.setParameters({
|
27
|
+
asset: TransactionType.Asset,
|
28
|
+
liability: TransactionType.Liability,
|
29
|
+
equity: TransactionType.Equity
|
30
|
+
})
|
31
|
+
.getRawOne()
|
32
|
+
|
33
|
+
const financialStatement = new FinancialStatement()
|
34
|
+
financialStatement.year = year
|
35
|
+
financialStatement.month = month
|
36
|
+
financialStatement.asset = financialResult.asset || 0
|
37
|
+
financialStatement.liability = financialResult.liability || 0
|
38
|
+
financialStatement.equity = financialResult.equity || 0
|
39
|
+
|
40
|
+
await financialStatementRepository.save(financialStatement)
|
41
|
+
|
42
|
+
// 손익계산서 계산
|
43
|
+
const incomeResult = await transactionRepository
|
44
|
+
.createQueryBuilder('transaction')
|
45
|
+
.leftJoinAndSelect('transaction.payments', 'payment')
|
46
|
+
.select([
|
47
|
+
'SUM(CASE WHEN transaction.type = :income THEN payment.amount ELSE 0 END) AS revenue',
|
48
|
+
'SUM(CASE WHEN transaction.type = :expense THEN payment.amount ELSE 0 END) AS expense'
|
49
|
+
])
|
50
|
+
.where('transaction.year = :year', { year })
|
51
|
+
.andWhere('transaction.month = :month', { month })
|
52
|
+
.andWhere('payment.direction = :incoming', { incoming: PaymentDirection.Incoming })
|
53
|
+
.setParameters({
|
54
|
+
income: TransactionType.SalesIncome,
|
55
|
+
expense: TransactionType.PurchaseExpense
|
56
|
+
})
|
57
|
+
.getRawOne()
|
58
|
+
|
59
|
+
const incomeStatement = new IncomeStatement()
|
60
|
+
incomeStatement.year = year
|
61
|
+
incomeStatement.month = month
|
62
|
+
incomeStatement.revenue = incomeResult.revenue || 0
|
63
|
+
incomeStatement.expense = incomeResult.expense || 0
|
64
|
+
incomeStatement.netIncome = (incomeResult.revenue || 0) - (incomeResult.expense || 0)
|
65
|
+
|
66
|
+
await incomeStatementRepository.save(incomeStatement)
|
67
|
+
}
|
68
|
+
|
69
|
+
export async function calculateQuarterlyStatements(year: number, quarter: number): Promise<void> {
|
70
|
+
const financialStatementRepository = getRepository(FinancialStatement)
|
71
|
+
const incomeStatementRepository = getRepository(IncomeStatement)
|
72
|
+
|
73
|
+
const months = getMonthsInQuarter(quarter)
|
74
|
+
|
75
|
+
// 재무제표 분기 합계 계산
|
76
|
+
const financialResult = await financialStatementRepository
|
77
|
+
.createQueryBuilder('financialStatement')
|
78
|
+
.select([
|
79
|
+
'SUM(financialStatement.asset) AS asset',
|
80
|
+
'SUM(financialStatement.liability) AS liability',
|
81
|
+
'SUM(financialStatement.equity) AS equity'
|
82
|
+
])
|
83
|
+
.where('financialStatement.year = :year', { year })
|
84
|
+
.andWhere('financialStatement.month IN (:...months)', { months })
|
85
|
+
.getRawOne()
|
86
|
+
|
87
|
+
const financialStatement = new FinancialStatement()
|
88
|
+
financialStatement.year = year
|
89
|
+
financialStatement.quarter = quarter
|
90
|
+
financialStatement.asset = financialResult.asset || 0
|
91
|
+
financialStatement.liability = financialResult.liability || 0
|
92
|
+
financialStatement.equity = financialResult.equity || 0
|
93
|
+
|
94
|
+
await financialStatementRepository.save(financialStatement)
|
95
|
+
|
96
|
+
// 손익계산서 분기 합계 계산
|
97
|
+
const incomeResult = await incomeStatementRepository
|
98
|
+
.createQueryBuilder('incomeStatement')
|
99
|
+
.select(['SUM(incomeStatement.revenue) AS revenue', 'SUM(incomeStatement.expense) AS expense'])
|
100
|
+
.where('incomeStatement.year = :year', { year })
|
101
|
+
.andWhere('incomeStatement.month IN (:...months)', { months })
|
102
|
+
.getRawOne()
|
103
|
+
|
104
|
+
const incomeStatement = new IncomeStatement()
|
105
|
+
incomeStatement.year = year
|
106
|
+
incomeStatement.quarter = quarter
|
107
|
+
incomeStatement.revenue = incomeResult.revenue || 0
|
108
|
+
incomeStatement.expense = incomeResult.expense || 0
|
109
|
+
incomeStatement.netIncome = (incomeResult.revenue || 0) - (incomeResult.expense || 0)
|
110
|
+
|
111
|
+
await incomeStatementRepository.save(incomeStatement)
|
112
|
+
}
|
113
|
+
|
114
|
+
export async function calculateYearlyStatements(year: number): Promise<void> {
|
115
|
+
const financialStatementRepository = getRepository(FinancialStatement)
|
116
|
+
const incomeStatementRepository = getRepository(IncomeStatement)
|
117
|
+
|
118
|
+
// 재무제표 연간 합계 계산
|
119
|
+
const financialResult = await financialStatementRepository
|
120
|
+
.createQueryBuilder('financialStatement')
|
121
|
+
.select([
|
122
|
+
'SUM(financialStatement.asset) AS asset',
|
123
|
+
'SUM(financialStatement.liability) AS liability',
|
124
|
+
'SUM(financialStatement.equity) AS equity'
|
125
|
+
])
|
126
|
+
.where('financialStatement.year = :year', { year })
|
127
|
+
.getRawOne()
|
128
|
+
|
129
|
+
const financialStatement = new FinancialStatement()
|
130
|
+
financialStatement.year = year
|
131
|
+
financialStatement.asset = financialResult.asset || 0
|
132
|
+
financialStatement.liability = financialResult.liability || 0
|
133
|
+
financialStatement.equity = financialResult.equity || 0
|
134
|
+
|
135
|
+
await financialStatementRepository.save(financialStatement)
|
136
|
+
|
137
|
+
// 손익계산서 연간 합계 계산
|
138
|
+
const incomeResult = await incomeStatementRepository
|
139
|
+
.createQueryBuilder('incomeStatement')
|
140
|
+
.select(['SUM(incomeStatement.revenue) AS revenue', 'SUM(incomeStatement.expense) AS expense'])
|
141
|
+
.where('incomeStatement.year = :year', { year })
|
142
|
+
.getRawOne()
|
143
|
+
|
144
|
+
const incomeStatement = new IncomeStatement()
|
145
|
+
incomeStatement.year = year
|
146
|
+
incomeStatement.revenue = incomeResult.revenue || 0
|
147
|
+
incomeStatement.expense = incomeResult.expense || 0
|
148
|
+
incomeStatement.netIncome = (incomeResult.revenue || 0) - (incomeResult.expense || 0)
|
149
|
+
|
150
|
+
await incomeStatementRepository.save(incomeStatement)
|
151
|
+
}
|
152
|
+
|
153
|
+
export function getMonthsInQuarter(quarter: number): number[] {
|
154
|
+
switch (quarter) {
|
155
|
+
case 1:
|
156
|
+
return [1, 2, 3]
|
157
|
+
case 2:
|
158
|
+
return [4, 5, 6]
|
159
|
+
case 3:
|
160
|
+
return [7, 8, 9]
|
161
|
+
case 4:
|
162
|
+
return [10, 11, 12]
|
163
|
+
default:
|
164
|
+
throw new Error('Invalid quarter number')
|
165
|
+
}
|
166
|
+
}
|
package/server/index.ts
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
2
|
+
import { Domain, getRepository } from '@things-factory/shell'
|
3
|
+
import { User } from '@things-factory/auth-base'
|
4
|
+
import { FiscalYear } from '../service/fiscal-year/fiscal-year'
|
5
|
+
import { FiscalQuarter } from '../service/fiscal-quarter/fiscal-quarter'
|
6
|
+
import { FiscalMonth } from '../service/fiscal-month/fiscal-month'
|
7
|
+
import { FiscalStatus } from '../service/common-type'
|
8
|
+
|
9
|
+
export class SeedFiscalEntities1725200507196 implements MigrationInterface {
|
10
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
11
|
+
const domainRepository = getRepository(Domain)
|
12
|
+
const userRepository = getRepository(User)
|
13
|
+
const fiscalYearRepository = getRepository(FiscalYear)
|
14
|
+
const fiscalQuarterRepository = getRepository(FiscalQuarter)
|
15
|
+
const fiscalMonthRepository = getRepository(FiscalMonth)
|
16
|
+
|
17
|
+
const domain: Domain | null = await domainRepository.findOne({
|
18
|
+
where: { name: 'SYSTEM' }
|
19
|
+
})
|
20
|
+
|
21
|
+
if (!domain) {
|
22
|
+
throw new Error('SYSTEM domain not found')
|
23
|
+
}
|
24
|
+
|
25
|
+
const user = await userRepository.findOne({ where: { id: domain.owner } })
|
26
|
+
|
27
|
+
if (!user) {
|
28
|
+
throw new Error('Domain owner not found')
|
29
|
+
}
|
30
|
+
|
31
|
+
const currentYear = new Date().getFullYear()
|
32
|
+
|
33
|
+
try {
|
34
|
+
// Fiscal Year 생성
|
35
|
+
const fiscalYear = await fiscalYearRepository.save({
|
36
|
+
domain,
|
37
|
+
year: currentYear,
|
38
|
+
startDate: `${currentYear}-01-01`, // 문자열로 저장
|
39
|
+
endDate: `${currentYear}-12-31`, // 문자열로 저장
|
40
|
+
status: FiscalStatus.OPEN,
|
41
|
+
creator: user,
|
42
|
+
updater: user
|
43
|
+
})
|
44
|
+
|
45
|
+
// Fiscal Quarters 생성
|
46
|
+
for (let quarter = 1; quarter <= 4; quarter++) {
|
47
|
+
const startMonth = (quarter - 1) * 3 + 1
|
48
|
+
const endMonth = quarter * 3
|
49
|
+
|
50
|
+
const fiscalQuarter = await fiscalQuarterRepository.save({
|
51
|
+
domain,
|
52
|
+
year: currentYear,
|
53
|
+
quarter,
|
54
|
+
startDate: `${currentYear}-${String(startMonth).padStart(2, '0')}-01`, // 문자열로 저장
|
55
|
+
endDate: `${currentYear}-${String(endMonth).padStart(2, '0')}-31`, // 임시로 월의 마지막 날을 31일로 설정
|
56
|
+
status: FiscalStatus.OPEN,
|
57
|
+
creator: user,
|
58
|
+
updater: user
|
59
|
+
})
|
60
|
+
|
61
|
+
// Fiscal Months 생성
|
62
|
+
for (let month = startMonth; month <= endMonth; month++) {
|
63
|
+
const startDate = `${currentYear}-${String(month).padStart(2, '0')}-01`
|
64
|
+
const endDate = `${currentYear}-${String(month).padStart(2, '0')}-${new Date(currentYear, month, 0).getDate()}`
|
65
|
+
|
66
|
+
await fiscalMonthRepository.save({
|
67
|
+
domain,
|
68
|
+
year: currentYear,
|
69
|
+
quarter,
|
70
|
+
month,
|
71
|
+
startDate,
|
72
|
+
endDate,
|
73
|
+
status: FiscalStatus.OPEN,
|
74
|
+
creator: user,
|
75
|
+
updater: user
|
76
|
+
})
|
77
|
+
}
|
78
|
+
}
|
79
|
+
} catch (error) {
|
80
|
+
console.error('Failed to seed fiscal entities:', error)
|
81
|
+
throw error
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
86
|
+
const domainRepository = getRepository(Domain)
|
87
|
+
const fiscalYearRepository = getRepository(FiscalYear)
|
88
|
+
const fiscalQuarterRepository = getRepository(FiscalQuarter)
|
89
|
+
const fiscalMonthRepository = getRepository(FiscalMonth)
|
90
|
+
|
91
|
+
const domain: Domain | null = await domainRepository.findOne({
|
92
|
+
where: { name: 'SYSTEM' }
|
93
|
+
})
|
94
|
+
|
95
|
+
if (!domain) {
|
96
|
+
throw new Error('SYSTEM domain not found')
|
97
|
+
}
|
98
|
+
|
99
|
+
const currentYear = new Date().getFullYear()
|
100
|
+
|
101
|
+
// FiscalMonth, FiscalQuarter, FiscalYear 삭제
|
102
|
+
await fiscalMonthRepository.delete({ domain: { id: domain.id }, year: currentYear })
|
103
|
+
await fiscalQuarterRepository.delete({ domain: { id: domain.id }, year: currentYear })
|
104
|
+
await fiscalYearRepository.delete({ domain: { id: domain.id }, year: currentYear })
|
105
|
+
}
|
106
|
+
}
|