@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.
Files changed (196) hide show
  1. package/client/activities/activity-book-edit.ts +88 -0
  2. package/client/activities/activity-book-view.ts +88 -0
  3. package/client/activities/activity-expense-edit.ts +88 -0
  4. package/client/activities/activity-expense-view.ts +88 -0
  5. package/client/bootstrap.ts +10 -0
  6. package/client/components/accounting-category-selector.ts +136 -0
  7. package/client/components/accounting-category-view.ts +75 -0
  8. package/client/grist-editors/grist-editor-accounting-category-object.ts +83 -0
  9. package/client/grist-editors/grist-renderer-accounting-category-object.ts +13 -0
  10. package/client/index.ts +0 -0
  11. package/client/pages/account/account-importer.ts +97 -0
  12. package/client/pages/account/account-list-page.ts +364 -0
  13. package/client/pages/accounting-category/accounting-category-importer.ts +97 -0
  14. package/client/pages/accounting-category/accounting-category-list-page.ts +368 -0
  15. package/client/pages/accounting-category/accounting-category-tree-page.ts +338 -0
  16. package/client/pages/accounting-document/accounting-document-importer.ts +90 -0
  17. package/client/pages/accounting-document/accounting-document-list-page.ts +398 -0
  18. package/client/pages/financial-statement/financial-statement-importer.ts +97 -0
  19. package/client/pages/financial-statement/financial-statement-list-page.ts +338 -0
  20. package/client/pages/fiscal-month/fiscal-month-importer.ts +90 -0
  21. package/client/pages/fiscal-month/fiscal-month-list-page.ts +398 -0
  22. package/client/pages/fiscal-quarter/fiscal-quarter-importer.ts +90 -0
  23. package/client/pages/fiscal-quarter/fiscal-quarter-list-page.ts +398 -0
  24. package/client/pages/fiscal-year/fiscal-year-importer.ts +90 -0
  25. package/client/pages/fiscal-year/fiscal-year-list-page.ts +398 -0
  26. package/client/pages/income-statement/income-statement-importer.ts +97 -0
  27. package/client/pages/income-statement/income-statement-list-page.ts +338 -0
  28. package/client/pages/payment/payment-importer.ts +90 -0
  29. package/client/pages/payment/payment-list-page.ts +398 -0
  30. package/client/pages/transaction/transaction-importer.ts +97 -0
  31. package/client/pages/transaction/transaction-list-page.ts +338 -0
  32. package/client/route.ts +35 -0
  33. package/client/tsconfig.json +13 -0
  34. package/client/types/accounting-category.ts +23 -0
  35. package/client/types/index.ts +1 -0
  36. package/dist-client/pages/accounting-category/accounting-category-tree-page.js +1 -1
  37. package/dist-client/pages/accounting-category/accounting-category-tree-page.js.map +1 -1
  38. package/dist-client/tsconfig.tsbuildinfo +1 -1
  39. package/dist-server/service/index.d.ts +2 -3
  40. package/dist-server/service/index.js +0 -5
  41. package/dist-server/service/index.js.map +1 -1
  42. package/dist-server/service/payment/index.d.ts +2 -1
  43. package/dist-server/service/payment/payment-history.d.ts +1 -8
  44. package/dist-server/service/payment/payment-history.js +10 -41
  45. package/dist-server/service/payment/payment-history.js.map +1 -1
  46. package/dist-server/service/payment/payment-type.d.ts +1 -7
  47. package/dist-server/service/payment/payment-type.js +0 -24
  48. package/dist-server/service/payment/payment-type.js.map +1 -1
  49. package/dist-server/service/payment/payment.d.ts +0 -12
  50. package/dist-server/service/payment/payment.js +1 -36
  51. package/dist-server/service/payment/payment.js.map +1 -1
  52. package/dist-server/tsconfig.tsbuildinfo +1 -1
  53. package/package.json +7 -7
  54. package/server/activities/activity-book.ts +172 -0
  55. package/server/activities/activity-expense.ts +149 -0
  56. package/server/activities/index.ts +18 -0
  57. package/server/controllers/index.ts +1 -0
  58. package/server/controllers/summary-statements.ts +166 -0
  59. package/server/index.ts +6 -0
  60. package/server/middlewares/index.ts +3 -0
  61. package/server/migrations/1725200507196-seed-fiscal-entities.ts +106 -0
  62. package/server/migrations/1725201467183-seed-accounts.ts +339 -0
  63. package/server/migrations/index.ts +9 -0
  64. package/server/routes.ts +26 -0
  65. package/server/service/account/account-history.ts +117 -0
  66. package/server/service/account/account-mutation.ts +140 -0
  67. package/server/service/account/account-query.ts +51 -0
  68. package/server/service/account/account-type.ts +44 -0
  69. package/server/service/account/account.ts +97 -0
  70. package/server/service/account/event-subscriber.ts +17 -0
  71. package/server/service/account/index.ts +9 -0
  72. package/server/service/accounting-category/accounting-category-history.ts +129 -0
  73. package/server/service/accounting-category/accounting-category-mutation.ts +148 -0
  74. package/server/service/accounting-category/accounting-category-query.ts +74 -0
  75. package/server/service/accounting-category/accounting-category-type.ts +48 -0
  76. package/server/service/accounting-category/accounting-category.ts +100 -0
  77. package/server/service/accounting-category/event-subscriber.ts +20 -0
  78. package/server/service/accounting-category/index.ts +9 -0
  79. package/server/service/accounting-document/accounting-document-history.ts +123 -0
  80. package/server/service/accounting-document/accounting-document-mutation.ts +137 -0
  81. package/server/service/accounting-document/accounting-document-query.ts +48 -0
  82. package/server/service/accounting-document/accounting-document-type.ts +52 -0
  83. package/server/service/accounting-document/accounting-document.ts +93 -0
  84. package/server/service/accounting-document/event-subscriber.ts +17 -0
  85. package/server/service/accounting-document/index.ts +9 -0
  86. package/server/service/common-type.ts +12 -0
  87. package/server/service/financial-statement/event-subscriber.ts +17 -0
  88. package/server/service/financial-statement/financial-statement-history.ts +129 -0
  89. package/server/service/financial-statement/financial-statement-line-item.ts +82 -0
  90. package/server/service/financial-statement/financial-statement-mutation.ts +148 -0
  91. package/server/service/financial-statement/financial-statement-query.ts +53 -0
  92. package/server/service/financial-statement/financial-statement-type.ts +51 -0
  93. package/server/service/financial-statement/financial-statement.ts +116 -0
  94. package/server/service/financial-statement/index.ts +10 -0
  95. package/server/service/fiscal-month/fiscal-month-mutation.ts +145 -0
  96. package/server/service/fiscal-month/fiscal-month-query.ts +58 -0
  97. package/server/service/fiscal-month/fiscal-month-type.ts +66 -0
  98. package/server/service/fiscal-month/fiscal-month.ts +84 -0
  99. package/server/service/fiscal-month/index.ts +7 -0
  100. package/server/service/fiscal-quarter/fiscal-quarter-mutation.ts +148 -0
  101. package/server/service/fiscal-quarter/fiscal-quarter-query.ts +60 -0
  102. package/server/service/fiscal-quarter/fiscal-quarter-type.ts +60 -0
  103. package/server/service/fiscal-quarter/fiscal-quarter.ts +80 -0
  104. package/server/service/fiscal-quarter/index.ts +7 -0
  105. package/server/service/fiscal-year/fiscal-year-mutation.ts +145 -0
  106. package/server/service/fiscal-year/fiscal-year-query.ts +53 -0
  107. package/server/service/fiscal-year/fiscal-year-type.ts +54 -0
  108. package/server/service/fiscal-year/fiscal-year.ts +76 -0
  109. package/server/service/fiscal-year/index.ts +7 -0
  110. package/server/service/income-statement/event-subscriber.ts +17 -0
  111. package/server/service/income-statement/income-statement-history.ts +133 -0
  112. package/server/service/income-statement/income-statement-line-item.ts +84 -0
  113. package/server/service/income-statement/income-statement-mutation.ts +147 -0
  114. package/server/service/income-statement/income-statement-query.ts +50 -0
  115. package/server/service/income-statement/income-statement-type.ts +51 -0
  116. package/server/service/income-statement/income-statement.ts +120 -0
  117. package/server/service/income-statement/index.ts +10 -0
  118. package/server/service/index.ts +108 -0
  119. package/server/service/payment/event-subscriber.ts +17 -0
  120. package/server/service/payment/index.ts +9 -0
  121. package/server/service/payment/payment-history.ts +132 -0
  122. package/server/service/payment/payment-mutation.ts +139 -0
  123. package/server/service/payment/payment-query.ts +50 -0
  124. package/server/service/payment/payment-type.ts +64 -0
  125. package/server/service/payment/payment.ts +123 -0
  126. package/server/service/transaction/event-subscriber.ts +17 -0
  127. package/server/service/transaction/index.ts +9 -0
  128. package/server/service/transaction/transaction-history.ts +161 -0
  129. package/server/service/transaction/transaction-mutation.ts +146 -0
  130. package/server/service/transaction/transaction-query.ts +50 -0
  131. package/server/service/transaction/transaction-type.ts +48 -0
  132. package/server/service/transaction/transaction.ts +230 -0
  133. package/server/tsconfig.json +10 -0
  134. package/dist-client/pages/bank/bank-importer.d.ts +0 -23
  135. package/dist-client/pages/bank/bank-importer.js +0 -93
  136. package/dist-client/pages/bank/bank-importer.js.map +0 -1
  137. package/dist-client/pages/bank/bank-list-page.d.ts +0 -66
  138. package/dist-client/pages/bank/bank-list-page.js +0 -370
  139. package/dist-client/pages/bank/bank-list-page.js.map +0 -1
  140. package/dist-client/pages/bank-account/bank-account-importer.d.ts +0 -23
  141. package/dist-client/pages/bank-account/bank-account-importer.js +0 -93
  142. package/dist-client/pages/bank-account/bank-account-importer.js.map +0 -1
  143. package/dist-client/pages/bank-account/bank-account-list-page.d.ts +0 -66
  144. package/dist-client/pages/bank-account/bank-account-list-page.js +0 -370
  145. package/dist-client/pages/bank-account/bank-account-list-page.js.map +0 -1
  146. package/dist-client/pages/financial-institution/financial-institution-importer.d.ts +0 -23
  147. package/dist-client/pages/financial-institution/financial-institution-importer.js +0 -93
  148. package/dist-client/pages/financial-institution/financial-institution-importer.js.map +0 -1
  149. package/dist-client/pages/financial-institution/financial-institution-list-page.d.ts +0 -66
  150. package/dist-client/pages/financial-institution/financial-institution-list-page.js +0 -370
  151. package/dist-client/pages/financial-institution/financial-institution-list-page.js.map +0 -1
  152. package/dist-server/migrations/1725201567284-seed-country-codes.d.ts +0 -5
  153. package/dist-server/migrations/1725201567284-seed-country-codes.js +0 -248
  154. package/dist-server/migrations/1725201567284-seed-country-codes.js.map +0 -1
  155. package/dist-server/migrations/1725201667385-seed-financial-institutions.d.ts +0 -5
  156. package/dist-server/migrations/1725201667385-seed-financial-institutions.js +0 -348
  157. package/dist-server/migrations/1725201667385-seed-financial-institutions.js.map +0 -1
  158. package/dist-server/service/bank-account/bank-account-history.d.ts +0 -34
  159. package/dist-server/service/bank-account/bank-account-history.js +0 -172
  160. package/dist-server/service/bank-account/bank-account-history.js.map +0 -1
  161. package/dist-server/service/bank-account/bank-account-mutation.d.ts +0 -10
  162. package/dist-server/service/bank-account/bank-account-mutation.js +0 -128
  163. package/dist-server/service/bank-account/bank-account-mutation.js.map +0 -1
  164. package/dist-server/service/bank-account/bank-account-query.d.ts +0 -11
  165. package/dist-server/service/bank-account/bank-account-query.js +0 -79
  166. package/dist-server/service/bank-account/bank-account-query.js.map +0 -1
  167. package/dist-server/service/bank-account/bank-account-type.d.ts +0 -39
  168. package/dist-server/service/bank-account/bank-account-type.js +0 -153
  169. package/dist-server/service/bank-account/bank-account-type.js.map +0 -1
  170. package/dist-server/service/bank-account/bank-account.d.ts +0 -38
  171. package/dist-server/service/bank-account/bank-account.js +0 -164
  172. package/dist-server/service/bank-account/bank-account.js.map +0 -1
  173. package/dist-server/service/bank-account/event-subscriber.d.ts +0 -7
  174. package/dist-server/service/bank-account/event-subscriber.js +0 -21
  175. package/dist-server/service/bank-account/event-subscriber.js.map +0 -1
  176. package/dist-server/service/bank-account/index.d.ts +0 -7
  177. package/dist-server/service/bank-account/index.js +0 -12
  178. package/dist-server/service/bank-account/index.js.map +0 -1
  179. package/dist-server/service/financial-institution/financial-institution-mutation.d.ts +0 -10
  180. package/dist-server/service/financial-institution/financial-institution-mutation.js +0 -169
  181. package/dist-server/service/financial-institution/financial-institution-mutation.js.map +0 -1
  182. package/dist-server/service/financial-institution/financial-institution-query.d.ts +0 -12
  183. package/dist-server/service/financial-institution/financial-institution-query.js +0 -97
  184. package/dist-server/service/financial-institution/financial-institution-query.js.map +0 -1
  185. package/dist-server/service/financial-institution/financial-institution-type.d.ts +0 -32
  186. package/dist-server/service/financial-institution/financial-institution-type.js +0 -126
  187. package/dist-server/service/financial-institution/financial-institution-type.js.map +0 -1
  188. package/dist-server/service/financial-institution/financial-institution.d.ts +0 -34
  189. package/dist-server/service/financial-institution/financial-institution.js +0 -137
  190. package/dist-server/service/financial-institution/financial-institution.js.map +0 -1
  191. package/dist-server/service/financial-institution/index.d.ts +0 -6
  192. package/dist-server/service/financial-institution/index.js +0 -10
  193. package/dist-server/service/financial-institution/index.js.map +0 -1
  194. package/helps/accounting/bank-account.md +0 -160
  195. package/helps/accounting/bank.md +0 -160
  196. 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-beta.9",
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": "^8.0.0-beta",
32
- "@operato/shell": "^8.0.0-beta",
33
- "@things-factory/auth-base": "^8.0.0-beta.9",
34
- "@things-factory/shell": "^8.0.0-beta.9",
35
- "@things-factory/worklist": "^8.0.0-beta.9"
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": "86b1dfa26292926a2d5447fdc23bfa5a9e983245"
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
+ }
@@ -0,0 +1,6 @@
1
+ export * from './controllers'
2
+ export * from './migrations'
3
+ export * from './middlewares'
4
+ export * from './service'
5
+
6
+ import './routes'
@@ -0,0 +1,3 @@
1
+ export function initMiddlewares(app) {
2
+ /* can add middlewares into app */
3
+ }
@@ -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
+ }