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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }