@things-factory/accounting 8.0.0-beta.9 → 8.0.2

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
@@ -0,0 +1,82 @@
1
+ import {
2
+ CreateDateColumn,
3
+ UpdateDateColumn,
4
+ DeleteDateColumn,
5
+ Entity,
6
+ Index,
7
+ Column,
8
+ RelationId,
9
+ ManyToOne,
10
+ PrimaryGeneratedColumn,
11
+ VersionColumn
12
+ } from 'typeorm'
13
+ import { ObjectType, Field, ID } from 'type-graphql'
14
+
15
+ import { Domain } from '@things-factory/shell'
16
+ import { User } from '@things-factory/auth-base'
17
+ import { Account } from '../account/account'
18
+ import { FinancialStatement } from './financial-statement'
19
+
20
+ @ObjectType({ description: 'Line item for a financial statement, representing the breakdown of financial accounts' })
21
+ @Entity()
22
+ @Index(
23
+ 'ix_financial_statement_line_item_0',
24
+ (lineItem: FinancialStatementLineItem) => [lineItem.statement, lineItem.account],
25
+ {
26
+ unique: false,
27
+ where: '"deleted_at" IS NULL'
28
+ }
29
+ )
30
+ export class FinancialStatementLineItem {
31
+ @PrimaryGeneratedColumn('uuid')
32
+ @Field(type => ID)
33
+ readonly id: string // 고유 식별자 (UUID)
34
+
35
+ @ManyToOne(type => FinancialStatement, statement => statement.lineItems)
36
+ @Field(type => FinancialStatement, { description: 'The financial statement this line item is associated with' })
37
+ statement: FinancialStatement // 연결된 재무제표
38
+
39
+ @RelationId((lineItem: FinancialStatementLineItem) => lineItem.statement)
40
+ statementId: string // 재무제표의 ID
41
+
42
+ @ManyToOne(type => Account)
43
+ @Field(type => Account, { description: 'The financial account associated with this line item' })
44
+ account: Account // 라인 아이템과 연결된 계정
45
+
46
+ @RelationId((lineItem: FinancialStatementLineItem) => lineItem.account)
47
+ accountId: string // 계정의 ID
48
+
49
+ @Column({ nullable: false })
50
+ @Field({ nullable: false, description: 'The monetary amount related to the financial account for this line item' })
51
+ amount: number // 계정에 대한 금액
52
+
53
+ @Column({ nullable: true })
54
+ @Field({ nullable: true, description: 'Optional description or notes for this line item' })
55
+ description?: string // 라인 아이템에 대한 선택적 설명 또는 메모
56
+
57
+ @CreateDateColumn()
58
+ @Field({ nullable: true, description: 'The date and time when this line item was created' })
59
+ createdAt?: Date // 라인 아이템이 생성된 날짜 및 시간
60
+
61
+ @UpdateDateColumn()
62
+ @Field({ nullable: true, description: 'The date and time when this line item was last updated' })
63
+ updatedAt?: Date // 라인 아이템이 마지막으로 업데이트된 날짜 및 시간
64
+
65
+ @DeleteDateColumn()
66
+ @Field({ nullable: true, description: 'The date and time when this line item was deleted' })
67
+ deletedAt?: Date // 라인 아이템이 삭제된 날짜 및 시간
68
+
69
+ @ManyToOne(type => User, { nullable: true })
70
+ @Field(type => User, { nullable: true, description: 'The user who created this line item' })
71
+ creator?: User // 라인 아이템을 생성한 사용자
72
+
73
+ @RelationId((lineItem: FinancialStatementLineItem) => lineItem.creator)
74
+ creatorId?: string // 생성자의 ID
75
+
76
+ @ManyToOne(type => User, { nullable: true })
77
+ @Field(type => User, { nullable: true, description: 'The user who last updated this line item' })
78
+ updater?: User // 라인 아이템을 마지막으로 업데이트한 사용자
79
+
80
+ @RelationId((lineItem: FinancialStatementLineItem) => lineItem.updater)
81
+ updaterId?: string // 업데이트한 사용자의 ID
82
+ }
@@ -0,0 +1,148 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+
4
+ import { getRepository } from '@things-factory/shell'
5
+
6
+ import { FinancialStatement } from './financial-statement'
7
+ import { NewFinancialStatement, FinancialStatementPatch } from './financial-statement-type'
8
+
9
+ @Resolver(FinancialStatement)
10
+ export class FinancialStatementMutation {
11
+ @Directive('@transaction')
12
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
13
+ @Mutation(returns => FinancialStatement, { description: 'To create new FinancialStatement' })
14
+ async createFinancialStatement(
15
+ @Arg('financialStatement') financialStatement: NewFinancialStatement,
16
+ @Ctx() context: ResolverContext
17
+ ): Promise<FinancialStatement> {
18
+ const { domain, user, tx } = context.state
19
+
20
+ const result = await getRepository(FinancialStatement, tx).save({
21
+ ...financialStatement,
22
+ domain,
23
+ creator: user,
24
+ updater: user
25
+ })
26
+
27
+ return result
28
+ }
29
+
30
+ @Directive('@transaction')
31
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
32
+ @Mutation(returns => FinancialStatement, { description: 'To modify FinancialStatement information' })
33
+ async updateFinancialStatement(
34
+ @Arg('id') id: string,
35
+ @Arg('patch') patch: FinancialStatementPatch,
36
+ @Ctx() context: ResolverContext
37
+ ): Promise<FinancialStatement> {
38
+ const { domain, user, tx } = context.state
39
+
40
+ const repository = getRepository(FinancialStatement, tx)
41
+ const financialStatement = await repository.findOne({
42
+ where: { domain: { id: domain.id }, id }
43
+ })
44
+
45
+ const result = await repository.save({
46
+ ...financialStatement,
47
+ ...patch,
48
+ updater: user
49
+ })
50
+
51
+ return result
52
+ }
53
+
54
+ @Directive('@transaction')
55
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
56
+ @Mutation(returns => [FinancialStatement], { description: "To modify multiple FinancialStatements' information" })
57
+ async updateMultipleFinancialStatement(
58
+ @Arg('patches', type => [FinancialStatementPatch]) patches: FinancialStatementPatch[],
59
+ @Ctx() context: ResolverContext
60
+ ): Promise<FinancialStatement[]> {
61
+ const { domain, user, tx } = context.state
62
+
63
+ let results = []
64
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
65
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
66
+ const financialStatementRepo = getRepository(FinancialStatement, tx)
67
+
68
+ if (_createRecords.length > 0) {
69
+ for (let i = 0; i < _createRecords.length; i++) {
70
+ const newRecord = _createRecords[i]
71
+
72
+ const result = await financialStatementRepo.save({
73
+ ...newRecord,
74
+ domain,
75
+ creator: user,
76
+ updater: user
77
+ })
78
+
79
+ results.push({ ...result, cuFlag: '+' })
80
+ }
81
+ }
82
+
83
+ if (_updateRecords.length > 0) {
84
+ for (let i = 0; i < _updateRecords.length; i++) {
85
+ const updateRecord = _updateRecords[i]
86
+ const financialStatement = await financialStatementRepo.findOneBy({ id: updateRecord.id })
87
+
88
+ const result = await financialStatementRepo.save({
89
+ ...financialStatement,
90
+ ...updateRecord,
91
+ updater: user
92
+ })
93
+
94
+ results.push({ ...result, cuFlag: 'M' })
95
+ }
96
+ }
97
+
98
+ return results
99
+ }
100
+
101
+ @Directive('@transaction')
102
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
103
+ @Mutation(returns => Boolean, { description: 'To delete FinancialStatement' })
104
+ async deleteFinancialStatement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
105
+ const { domain, tx } = context.state
106
+
107
+ await getRepository(FinancialStatement, tx).delete({ domain: { id: domain.id }, id })
108
+
109
+ return true
110
+ }
111
+
112
+ @Directive('@transaction')
113
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
114
+ @Mutation(returns => Boolean, { description: 'To delete multiple FinancialStatements' })
115
+ async deleteFinancialStatements(
116
+ @Arg('ids', type => [String]) ids: string[],
117
+ @Ctx() context: ResolverContext
118
+ ): Promise<boolean> {
119
+ const { domain, tx } = context.state
120
+
121
+ await getRepository(FinancialStatement, tx).delete({
122
+ domain: { id: domain.id },
123
+ id: In(ids)
124
+ })
125
+
126
+ return true
127
+ }
128
+
129
+ @Directive('@transaction')
130
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
131
+ @Mutation(returns => Boolean, { description: 'To import multiple FinancialStatements' })
132
+ async importFinancialStatements(
133
+ @Arg('financialStatements', type => [FinancialStatementPatch]) financialStatements: FinancialStatementPatch[],
134
+ @Ctx() context: ResolverContext
135
+ ): Promise<boolean> {
136
+ const { domain, tx } = context.state
137
+
138
+ await Promise.all(
139
+ financialStatements.map(async (financialStatement: FinancialStatementPatch) => {
140
+ const createdFinancialStatement: FinancialStatement = await tx
141
+ .getRepository(FinancialStatement)
142
+ .save({ domain, ...financialStatement })
143
+ })
144
+ )
145
+
146
+ return true
147
+ }
148
+ }
@@ -0,0 +1,53 @@
1
+ import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
+ import { User } from '@things-factory/auth-base'
4
+ import { FinancialStatement } from './financial-statement'
5
+ import { FinancialStatementList } from './financial-statement-type'
6
+
7
+ @Resolver(FinancialStatement)
8
+ export class FinancialStatementQuery {
9
+ @Directive('@privilege(category: "accounting", privilege: "query")')
10
+ @Query(returns => FinancialStatement!, { nullable: true, description: 'To fetch a FinancialStatement' })
11
+ async financialStatement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<FinancialStatement> {
12
+ const { domain } = context.state
13
+
14
+ return await getRepository(FinancialStatement).findOne({
15
+ where: { domain: { id: domain.id }, id }
16
+ })
17
+ }
18
+
19
+ @Directive('@privilege(category: "accounting", privilege: "query")')
20
+ @Query(returns => FinancialStatementList, { description: 'To fetch multiple FinancialStatements' })
21
+ async financialStatements(
22
+ @Args() params: ListParam,
23
+ @Ctx() context: ResolverContext
24
+ ): Promise<FinancialStatementList> {
25
+ const { domain } = context.state
26
+
27
+ const queryBuilder = getQueryBuilderFromListParams({
28
+ domain,
29
+ params,
30
+ repository: await getRepository(FinancialStatement),
31
+ searchables: ['name', 'description']
32
+ })
33
+
34
+ const [items, total] = await queryBuilder.getManyAndCount()
35
+
36
+ return { items, total }
37
+ }
38
+
39
+ @FieldResolver(type => Domain)
40
+ async domain(@Root() financialStatement: FinancialStatement): Promise<Domain> {
41
+ return await getRepository(Domain).findOneBy({ id: financialStatement.domainId })
42
+ }
43
+
44
+ @FieldResolver(type => User)
45
+ async updater(@Root() financialStatement: FinancialStatement): Promise<User> {
46
+ return await getRepository(User).findOneBy({ id: financialStatement.updaterId })
47
+ }
48
+
49
+ @FieldResolver(type => User)
50
+ async creator(@Root() financialStatement: FinancialStatement): Promise<User> {
51
+ return await getRepository(User).findOneBy({ id: financialStatement.creatorId })
52
+ }
53
+ }
@@ -0,0 +1,51 @@
1
+ import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
2
+
3
+ import { FinancialStatement, FinancialStatementStatus } from './financial-statement'
4
+
5
+ @InputType()
6
+ export class NewFinancialStatement {
7
+ @Field()
8
+ name: string
9
+
10
+ @Field({ nullable: true })
11
+ description?: string
12
+
13
+ @Field(type => FinancialStatementStatus, { nullable: true })
14
+ state?: FinancialStatementStatus
15
+
16
+ @Field({ nullable: true })
17
+ active?: boolean
18
+
19
+ @Field({ nullable: true })
20
+ params?: string
21
+ }
22
+
23
+ @InputType()
24
+ export class FinancialStatementPatch {
25
+ @Field(type => ID, { nullable: true })
26
+ id?: string
27
+
28
+ @Field({ nullable: true })
29
+ name?: string
30
+
31
+ @Field({ nullable: true })
32
+ description?: string
33
+
34
+ @Field(type => FinancialStatementStatus, { nullable: true })
35
+ state?: FinancialStatementStatus
36
+
37
+ @Field({ nullable: true })
38
+ active?: boolean
39
+
40
+ @Field({ nullable: true })
41
+ cuFlag?: string
42
+ }
43
+
44
+ @ObjectType()
45
+ export class FinancialStatementList {
46
+ @Field(type => [FinancialStatement])
47
+ items: FinancialStatement[]
48
+
49
+ @Field(type => Int)
50
+ total: number
51
+ }
@@ -0,0 +1,116 @@
1
+ import {
2
+ CreateDateColumn,
3
+ UpdateDateColumn,
4
+ DeleteDateColumn,
5
+ Entity,
6
+ Index,
7
+ Column,
8
+ RelationId,
9
+ ManyToOne,
10
+ OneToMany,
11
+ PrimaryGeneratedColumn,
12
+ VersionColumn
13
+ } from 'typeorm'
14
+ import { ObjectType, Field, ID, registerEnumType } from 'type-graphql'
15
+
16
+ import { Domain } from '@things-factory/shell'
17
+ import { User } from '@things-factory/auth-base'
18
+
19
+ import { FinancialStatementLineItem } from './financial-statement-line-item'
20
+
21
+ export enum FinancialStatementStatus {
22
+ STATUS_A = 'STATUS_A',
23
+ STATUS_B = 'STATUS_B'
24
+ }
25
+
26
+ registerEnumType(FinancialStatementStatus, {
27
+ name: 'FinancialStatementStatus',
28
+ description: 'State enumeration of a financial statement' // 재무제표 상태 열거형
29
+ })
30
+
31
+ // 재무제표 (Financial Statement)
32
+ @Entity()
33
+ @Index(
34
+ 'ix_financial_statement_0',
35
+ (financialStatement: FinancialStatement) => [
36
+ financialStatement.domain,
37
+ financialStatement.year,
38
+ financialStatement.quarter,
39
+ financialStatement.month
40
+ ],
41
+ {
42
+ unique: true,
43
+ where: '"deleted_at" IS NULL' // 삭제되지 않은 경우에만 유니크
44
+ }
45
+ )
46
+ @ObjectType({ description: 'Entity for FinancialStatement, representing the financial position of an entity' }) // 엔티티 설명 추가
47
+ export class FinancialStatement {
48
+ @PrimaryGeneratedColumn('uuid')
49
+ @Field(type => ID, { description: 'Unique identifier for the financial statement' })
50
+ readonly id: string // 고유 식별자 (UUID)
51
+
52
+ @VersionColumn()
53
+ @Field({ nullable: true, description: 'Version number for optimistic locking' })
54
+ version?: number = 1 // 낙관적 잠금을 위한 버전 관리 필드
55
+
56
+ @ManyToOne(type => Domain)
57
+ @Field({ nullable: true, description: 'The domain to which this financial statement belongs' })
58
+ domain?: Domain // 이 재무제표가 속한 도메인
59
+
60
+ @RelationId((financialStatement: FinancialStatement) => financialStatement.domain)
61
+ domainId?: string // 도메인의 ID
62
+
63
+ @Column({ nullable: true })
64
+ @Field({ nullable: true, description: 'Fiscal year of the financial statement' })
65
+ year?: number // 회계 연도
66
+
67
+ @Column({ nullable: true })
68
+ @Field({ nullable: true, description: 'Fiscal quarter of the financial statement' })
69
+ quarter?: number // 회계 분기
70
+
71
+ @Column({ nullable: true })
72
+ @Field({ nullable: true, description: 'Fiscal month of the financial statement' })
73
+ month?: number // 회계 월
74
+
75
+ @Column({ nullable: true })
76
+ @Field({ nullable: true, description: 'Total assets recorded in the financial statement' })
77
+ asset?: number // 재무제표에 기록된 총자산
78
+
79
+ @Column({ nullable: true })
80
+ @Field({ nullable: true, description: 'Total liabilities recorded in the financial statement' })
81
+ liability?: number // 재무제표에 기록된 총부채
82
+
83
+ @Column({ nullable: true })
84
+ @Field({ nullable: true, description: 'Total equity recorded in the financial statement' })
85
+ equity?: number // 재무제표에 기록된 총자본
86
+
87
+ @OneToMany(type => FinancialStatementLineItem, lineItem => lineItem.statement)
88
+ @Field(type => [FinancialStatementLineItem], { nullable: true })
89
+ lineItems?: FinancialStatementLineItem[] // 계정별 브레이크다운
90
+
91
+ @CreateDateColumn()
92
+ @Field({ nullable: true, description: 'The date and time when the financial statement was created' })
93
+ createdAt?: Date // 재무제표가 생성된 날짜 및 시간
94
+
95
+ @UpdateDateColumn()
96
+ @Field({ nullable: true, description: 'The date and time when the financial statement was last updated' })
97
+ updatedAt?: Date // 재무제표가 마지막으로 업데이트된 날짜 및 시간
98
+
99
+ @DeleteDateColumn()
100
+ @Field({ nullable: true, description: 'The date and time when the financial statement was deleted' })
101
+ deletedAt?: Date // 재무제표가 삭제된 날짜 및 시간
102
+
103
+ @ManyToOne(type => User, { nullable: true })
104
+ @Field(type => User, { nullable: true, description: 'The user who created the financial statement' })
105
+ creator?: User // 재무제표를 생성한 사용자
106
+
107
+ @RelationId((financialStatement: FinancialStatement) => financialStatement.creator)
108
+ creatorId?: string // 재무제표를 생성한 사용자의 ID
109
+
110
+ @ManyToOne(type => User, { nullable: true })
111
+ @Field(type => User, { nullable: true, description: 'The user who last updated the financial statement' })
112
+ updater?: User // 재무제표를 마지막으로 업데이트한 사용자
113
+
114
+ @RelationId((financialStatement: FinancialStatement) => financialStatement.updater)
115
+ updaterId?: string // 재무제표를 업데이트한 사용자의 ID
116
+ }
@@ -0,0 +1,10 @@
1
+ import { FinancialStatement } from './financial-statement'
2
+ import { FinancialStatementLineItem } from './financial-statement-line-item'
3
+ import { FinancialStatementHistory } from './financial-statement-history'
4
+ import { FinancialStatementQuery } from './financial-statement-query'
5
+ import { FinancialStatementMutation } from './financial-statement-mutation'
6
+ import { FinancialStatementHistoryEntitySubscriber } from './event-subscriber'
7
+
8
+ export const entities = [FinancialStatement, FinancialStatementLineItem, FinancialStatementHistory]
9
+ export const resolvers = [FinancialStatementQuery, FinancialStatementMutation]
10
+ export const subscribers = [FinancialStatementHistoryEntitySubscriber]
@@ -0,0 +1,145 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+ import { getRepository } from '@things-factory/shell'
4
+
5
+ import { FiscalMonth } from './fiscal-month'
6
+ import { NewFiscalMonth, FiscalMonthPatch } from './fiscal-month-type'
7
+
8
+ @Resolver(FiscalMonth)
9
+ export class FiscalMonthMutation {
10
+ @Directive('@transaction')
11
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
12
+ @Mutation(returns => FiscalMonth, { description: 'To create new FiscalMonth' })
13
+ async createFiscalMonth(
14
+ @Arg('fiscalMonth') fiscalMonth: NewFiscalMonth,
15
+ @Ctx() context: ResolverContext
16
+ ): Promise<FiscalMonth> {
17
+ const { domain, user, tx } = context.state
18
+
19
+ const result = await getRepository(FiscalMonth, tx).save({
20
+ ...fiscalMonth,
21
+ domain,
22
+ creator: user,
23
+ updater: user
24
+ })
25
+
26
+ return result
27
+ }
28
+
29
+ @Directive('@transaction')
30
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
31
+ @Mutation(returns => FiscalMonth, { description: 'To modify FiscalMonth information' })
32
+ async updateFiscalMonth(
33
+ @Arg('id') id: string,
34
+ @Arg('patch') patch: FiscalMonthPatch,
35
+ @Ctx() context: ResolverContext
36
+ ): Promise<FiscalMonth> {
37
+ const { domain, user, tx } = context.state
38
+
39
+ const repository = getRepository(FiscalMonth, tx)
40
+ const fiscalMonth = await repository.findOne({
41
+ where: { domain: { id: domain.id }, id }
42
+ })
43
+
44
+ const result = await repository.save({
45
+ ...fiscalMonth,
46
+ ...patch,
47
+ updater: user
48
+ })
49
+
50
+ return result
51
+ }
52
+
53
+ @Directive('@transaction')
54
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
55
+ @Mutation(returns => [FiscalMonth], { description: "To modify multiple FiscalMonths' information" })
56
+ async updateMultipleFiscalMonth(
57
+ @Arg('patches', type => [FiscalMonthPatch]) patches: FiscalMonthPatch[],
58
+ @Ctx() context: ResolverContext
59
+ ): Promise<FiscalMonth[]> {
60
+ const { domain, user, tx } = context.state
61
+
62
+ let results = []
63
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
64
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
65
+ const fiscalMonthRepo = getRepository(FiscalMonth, tx)
66
+
67
+ if (_createRecords.length > 0) {
68
+ for (let i = 0; i < _createRecords.length; i++) {
69
+ const newRecord = _createRecords[i]
70
+
71
+ const result = await fiscalMonthRepo.save({
72
+ ...newRecord,
73
+ domain,
74
+ creator: user,
75
+ updater: user
76
+ })
77
+
78
+ results.push({ ...result, cuFlag: '+' })
79
+ }
80
+ }
81
+
82
+ if (_updateRecords.length > 0) {
83
+ for (let i = 0; i < _updateRecords.length; i++) {
84
+ const updateRecord = _updateRecords[i]
85
+ const fiscalMonth = await fiscalMonthRepo.findOneBy({ id: updateRecord.id })
86
+
87
+ const result = await fiscalMonthRepo.save({
88
+ ...fiscalMonth,
89
+ ...updateRecord,
90
+ updater: user
91
+ })
92
+
93
+ results.push({ ...result, cuFlag: 'M' })
94
+ }
95
+ }
96
+
97
+ return results
98
+ }
99
+
100
+ @Directive('@transaction')
101
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
102
+ @Mutation(returns => Boolean, { description: 'To delete FiscalMonth' })
103
+ async deleteFiscalMonth(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
104
+ const { domain, tx } = context.state
105
+
106
+ await getRepository(FiscalMonth, tx).delete({ domain: { id: domain.id }, id })
107
+
108
+ return true
109
+ }
110
+
111
+ @Directive('@transaction')
112
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
113
+ @Mutation(returns => Boolean, { description: 'To delete multiple FiscalMonths' })
114
+ async deleteFiscalMonths(
115
+ @Arg('ids', type => [String]) ids: string[],
116
+ @Ctx() context: ResolverContext
117
+ ): Promise<boolean> {
118
+ const { domain, tx } = context.state
119
+
120
+ await getRepository(FiscalMonth, tx).delete({
121
+ domain: { id: domain.id },
122
+ id: In(ids)
123
+ })
124
+
125
+ return true
126
+ }
127
+
128
+ @Directive('@transaction')
129
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
130
+ @Mutation(returns => Boolean, { description: 'To import multiple FiscalMonths' })
131
+ async importFiscalMonths(
132
+ @Arg('fiscalMonths', type => [FiscalMonthPatch]) fiscalMonths: FiscalMonthPatch[],
133
+ @Ctx() context: ResolverContext
134
+ ): Promise<boolean> {
135
+ const { domain, tx } = context.state
136
+
137
+ await Promise.all(
138
+ fiscalMonths.map(async (fiscalMonth: FiscalMonthPatch) => {
139
+ const createdFiscalMonth: FiscalMonth = await getRepository(FiscalMonth, tx).save({ domain, ...fiscalMonth })
140
+ })
141
+ )
142
+
143
+ return true
144
+ }
145
+ }
@@ -0,0 +1,58 @@
1
+ import { Directive, Resolver, Query, FieldResolver, Root, Args, Arg, Ctx } from 'type-graphql'
2
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
+ import { User } from '@things-factory/auth-base'
4
+ import { FiscalMonth } from './fiscal-month'
5
+ import { FiscalMonthList } from './fiscal-month-type'
6
+
7
+ @Resolver(FiscalMonth)
8
+ export class FiscalMonthQuery {
9
+ @Directive('@privilege(category: "accounting", privilege: "query")')
10
+ @Query(returns => FiscalMonth!, { nullable: true, description: 'To fetch a FiscalMonth by year, quarter, and month' })
11
+ async fiscalMonth(
12
+ @Arg('year') year: number,
13
+ @Arg('quarter') quarter: number,
14
+ @Arg('month') month: number,
15
+ @Ctx() context: ResolverContext
16
+ ): Promise<FiscalMonth | undefined> {
17
+ const { domain } = context.state
18
+
19
+ return await getRepository(FiscalMonth).findOne({
20
+ where: { domain: { id: domain.id }, year, quarter, month }
21
+ })
22
+ }
23
+
24
+ @Directive('@privilege(category: "accounting", privilege: "query")')
25
+ @Query(returns => FiscalMonthList, { description: 'To fetch multiple FiscalMonths' })
26
+ async fiscalMonths(
27
+ @Args(type => ListParam) params: ListParam,
28
+ @Ctx() context: ResolverContext
29
+ ): Promise<FiscalMonthList> {
30
+ const { domain } = context.state
31
+
32
+ const queryBuilder = getQueryBuilderFromListParams({
33
+ domain,
34
+ params,
35
+ repository: await getRepository(FiscalMonth),
36
+ searchables: []
37
+ })
38
+
39
+ const [items, total] = await queryBuilder.getManyAndCount()
40
+
41
+ return { items, total }
42
+ }
43
+
44
+ @FieldResolver(type => Domain)
45
+ async domain(@Root() fiscalMonth: FiscalMonth): Promise<Domain> {
46
+ return fiscalMonth.domainId && (await getRepository(Domain).findOneBy({ id: fiscalMonth.domainId }))
47
+ }
48
+
49
+ @FieldResolver(type => User)
50
+ async updater(@Root() fiscalMonth: FiscalMonth): Promise<User> {
51
+ return fiscalMonth.updaterId && (await getRepository(User).findOneBy({ id: fiscalMonth.updaterId }))
52
+ }
53
+
54
+ @FieldResolver(type => User)
55
+ async creator(@Root() fiscalMonth: FiscalMonth): Promise<User> {
56
+ return fiscalMonth.creatorId && (await getRepository(User).findOneBy({ id: fiscalMonth.creatorId }))
57
+ }
58
+ }