@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,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 { FiscalYear } from './fiscal-year'
5
+ import { FiscalYearList } from './fiscal-year-type'
6
+
7
+ @Resolver(FiscalYear)
8
+ export class FiscalYearQuery {
9
+ @Directive('@privilege(category: "accounting", privilege: "query")')
10
+ @Query(returns => FiscalYear!, { nullable: true, description: 'To fetch a FiscalYear by year' })
11
+ async fiscalYear(@Arg('year') year: number, @Ctx() context: ResolverContext): Promise<FiscalYear | undefined> {
12
+ const { domain } = context.state
13
+
14
+ return await getRepository(FiscalYear).findOne({
15
+ where: { domain: { id: domain.id }, year }
16
+ })
17
+ }
18
+
19
+ @Directive('@privilege(category: "accounting", privilege: "query")')
20
+ @Query(returns => FiscalYearList, { description: 'To fetch multiple FiscalYears' })
21
+ async fiscalYears(
22
+ @Args(type => ListParam) params: ListParam,
23
+ @Ctx() context: ResolverContext
24
+ ): Promise<FiscalYearList> {
25
+ const { domain } = context.state
26
+
27
+ const queryBuilder = getQueryBuilderFromListParams({
28
+ domain,
29
+ params,
30
+ repository: await getRepository(FiscalYear),
31
+ searchables: []
32
+ })
33
+
34
+ const [items, total] = await queryBuilder.getManyAndCount()
35
+
36
+ return { items, total }
37
+ }
38
+
39
+ @FieldResolver(type => Domain)
40
+ async domain(@Root() fiscalYear: FiscalYear): Promise<Domain> {
41
+ return fiscalYear.domainId && (await getRepository(Domain).findOneBy({ id: fiscalYear.domainId }))
42
+ }
43
+
44
+ @FieldResolver(type => User)
45
+ async updater(@Root() fiscalYear: FiscalYear): Promise<User> {
46
+ return fiscalYear.updaterId && (await getRepository(User).findOneBy({ id: fiscalYear.updaterId }))
47
+ }
48
+
49
+ @FieldResolver(type => User)
50
+ async creator(@Root() fiscalYear: FiscalYear): Promise<User> {
51
+ return fiscalYear.creatorId && (await getRepository(User).findOneBy({ id: fiscalYear.creatorId }))
52
+ }
53
+ }
@@ -0,0 +1,54 @@
1
+ import { InputType, ObjectType, Field, ID, Int } from 'type-graphql'
2
+ import { FiscalYear } from './fiscal-year'
3
+ import { FiscalStatus } from '../common-type'
4
+
5
+ @InputType()
6
+ export class NewFiscalYear {
7
+ @Field(type => Int)
8
+ year: number // 회계연도 (예: 2023)
9
+
10
+ @Field(type => String, { description: 'The start date of the fiscal month in YYYY-MM-DD format' })
11
+ startDate: string // 월의 시작일
12
+
13
+ @Field(type => String, { description: 'The end date of the fiscal month in YYYY-MM-DD format' })
14
+ endDate: string // 월의 종료일
15
+
16
+ @Field(type => FiscalStatus, { nullable: true })
17
+ status?: FiscalStatus // 회계연도의 상태 (OPEN, CLOSED, FINALIZED)
18
+
19
+ @Field({ nullable: true })
20
+ notes?: string // 회계연도에 대한 설명이나 주석
21
+ }
22
+
23
+ @InputType()
24
+ export class FiscalYearPatch {
25
+ @Field(type => ID, { nullable: true })
26
+ id?: string
27
+
28
+ @Field(type => Int, { nullable: true })
29
+ year?: number // 회계연도 (예: 2023)
30
+
31
+ @Field(type => String, { description: 'The start date of the fiscal month in YYYY-MM-DD format' })
32
+ startDate: string // 월의 시작일
33
+
34
+ @Field(type => String, { description: 'The end date of the fiscal month in YYYY-MM-DD format' })
35
+ endDate: string // 월의 종료일
36
+
37
+ @Field(type => FiscalStatus, { nullable: true })
38
+ status?: FiscalStatus // 회계연도의 상태 (OPEN, CLOSED, FINALIZED)
39
+
40
+ @Field({ nullable: true })
41
+ notes?: string // 회계연도에 대한 설명이나 주석
42
+
43
+ @Field({ nullable: true })
44
+ cuFlag?: string // Create/Update Flag
45
+ }
46
+
47
+ @ObjectType()
48
+ export class FiscalYearList {
49
+ @Field(type => [FiscalYear])
50
+ items: FiscalYear[]
51
+
52
+ @Field(type => Int)
53
+ total: number
54
+ }
@@ -0,0 +1,76 @@
1
+ import {
2
+ CreateDateColumn,
3
+ DeleteDateColumn,
4
+ UpdateDateColumn,
5
+ Entity,
6
+ Index,
7
+ Column,
8
+ ManyToOne,
9
+ RelationId,
10
+ PrimaryGeneratedColumn
11
+ } from 'typeorm'
12
+ import { ObjectType, Field, Int, ID } from 'type-graphql'
13
+ import { Domain } from '@things-factory/shell'
14
+ import { User } from '@things-factory/auth-base'
15
+ import { FiscalStatus } from '../common-type'
16
+
17
+ @ObjectType({ description: 'Entity representing a fiscal year' })
18
+ @Entity()
19
+ export class FiscalYear {
20
+ @PrimaryGeneratedColumn('uuid')
21
+ @Field(type => ID)
22
+ readonly id: string
23
+
24
+ @ManyToOne(type => Domain)
25
+ @Field({ nullable: true })
26
+ domain?: Domain
27
+
28
+ @RelationId((fiscalYear: FiscalYear) => fiscalYear.domain)
29
+ domainId?: string
30
+
31
+ @Column()
32
+ @Field(type => Int, { description: 'The fiscal year (e.g., 2023)' })
33
+ year: number // 회계연도 (예: 2023)
34
+
35
+ @Column()
36
+ @Field(type => String, { description: 'The start date of the fiscal year in YYYY-MM-DD format' })
37
+ startDate: string // 회계연도 시작일
38
+
39
+ @Column()
40
+ @Field(type => String, { description: 'The end date of the fiscal year in YYYY-MM-DD format' })
41
+ endDate: string // 회계연도 종료일
42
+
43
+ @Column({ default: FiscalStatus.OPEN })
44
+ @Field(type => FiscalStatus, { description: 'The status of the fiscal year (OPEN, CLOSED, FINALIZED)' })
45
+ status: FiscalStatus // 회계연도의 상태 (OPEN, CLOSED, FINALIZED)
46
+
47
+ @Column({ nullable: true })
48
+ @Field({ nullable: true, description: 'Notes or comments about the fiscal year' })
49
+ notes?: string // 회계연도에 대한 설명이나 주석
50
+
51
+ @CreateDateColumn()
52
+ @Field({ nullable: true })
53
+ createdAt?: Date
54
+
55
+ @UpdateDateColumn()
56
+ @Field({ nullable: true })
57
+ updatedAt?: Date
58
+
59
+ @DeleteDateColumn()
60
+ @Field({ nullable: true })
61
+ deletedAt?: Date
62
+
63
+ @ManyToOne(type => User, { nullable: true })
64
+ @Field(type => User, { nullable: true })
65
+ creator?: User
66
+
67
+ @RelationId((fiscalYear: FiscalYear) => fiscalYear.creator)
68
+ creatorId?: string
69
+
70
+ @ManyToOne(type => User, { nullable: true })
71
+ @Field(type => User, { nullable: true })
72
+ updater?: User
73
+
74
+ @RelationId((fiscalYear: FiscalYear) => fiscalYear.updater)
75
+ updaterId?: string
76
+ }
@@ -0,0 +1,7 @@
1
+ import { FiscalYear } from './fiscal-year'
2
+ import { FiscalYearQuery } from './fiscal-year-query'
3
+ import { FiscalYearMutation } from './fiscal-year-mutation'
4
+
5
+ export const entities = [FiscalYear]
6
+ export const resolvers = [FiscalYearQuery, FiscalYearMutation]
7
+ export const subscribers = []
@@ -0,0 +1,17 @@
1
+ import { EventSubscriber } from 'typeorm'
2
+
3
+ import { HistoryEntitySubscriber } from '@operato/typeorm-history'
4
+
5
+ import { IncomeStatement } from './income-statement'
6
+ import { IncomeStatementHistory } from './income-statement-history'
7
+
8
+ @EventSubscriber()
9
+ export class IncomeStatementHistoryEntitySubscriber extends HistoryEntitySubscriber<IncomeStatement, IncomeStatementHistory> {
10
+ public get entity() {
11
+ return IncomeStatement
12
+ }
13
+
14
+ public get historyEntity() {
15
+ return IncomeStatementHistory
16
+ }
17
+ }
@@ -0,0 +1,133 @@
1
+ import { Field, ID, ObjectType } from 'type-graphql'
2
+ import { Column, Entity, Index, ManyToOne, OneToMany, PrimaryGeneratedColumn, RelationId } from 'typeorm'
3
+
4
+ import {
5
+ HistoryActionColumn,
6
+ HistoryActionType,
7
+ HistoryEntityInterface,
8
+ HistoryOriginalIdColumn
9
+ } from '@operato/typeorm-history'
10
+ import { Role, User } from '@things-factory/auth-base'
11
+ import { config } from '@things-factory/env'
12
+ import { Domain } from '@things-factory/shell'
13
+
14
+ import { IncomeStatement, IncomeStatementStatus } from './income-statement'
15
+ import { IncomeStatementLineItem } from './income-statement-line-item'
16
+
17
+ const ORMCONFIG = config.get('ormconfig', {})
18
+ const DATABASE_TYPE = ORMCONFIG.type
19
+
20
+ @Entity()
21
+ @Index(
22
+ 'ix_income-statement_history_0',
23
+ (incomeStatementHistory: IncomeStatementHistory) => [
24
+ incomeStatementHistory.originalId,
25
+ incomeStatementHistory.version
26
+ ],
27
+ { unique: true }
28
+ )
29
+ @Index(
30
+ 'ix_income-statement_history_1',
31
+ (incomeStatementHistory: IncomeStatementHistory) => [
32
+ incomeStatementHistory.domain,
33
+ incomeStatementHistory.originalId,
34
+ incomeStatementHistory.version
35
+ ],
36
+ { unique: true }
37
+ )
38
+ @ObjectType({ description: 'History Entity of IncomeStatement' })
39
+ export class IncomeStatementHistory implements HistoryEntityInterface<IncomeStatement> {
40
+ @PrimaryGeneratedColumn('uuid')
41
+ @Field(type => ID)
42
+ readonly id: string
43
+
44
+ @Column({ nullable: true, default: 1 })
45
+ @Field({ nullable: true })
46
+ version?: number = 1
47
+
48
+ @ManyToOne(type => Domain)
49
+ @Field({ nullable: true })
50
+ domain?: Domain
51
+
52
+ @RelationId((incomeStatementHistory: IncomeStatementHistory) => incomeStatementHistory.domain)
53
+ domainId?: string
54
+
55
+ @Column({ nullable: true })
56
+ @Field({ nullable: true, description: 'Fiscal year of the income statement' })
57
+ year?: number // 회계 연도
58
+
59
+ @Column({ nullable: true })
60
+ @Field({ nullable: true, description: 'Fiscal quarter of the income statement' })
61
+ quarter?: number // 회계 분기
62
+
63
+ @Column({ nullable: true })
64
+ @Field({ nullable: true, description: 'Fiscal month of the income statement' })
65
+ month?: number // 회계 월
66
+
67
+ @Column({ nullable: true })
68
+ @Field({ nullable: true, description: 'Total revenue recorded in the income statement' })
69
+ revenue?: number // 손익계산서에 기록된 총수익
70
+
71
+ @Column({ nullable: true })
72
+ @Field({ nullable: true, description: 'Total expenses recorded in the income statement' })
73
+ expense?: number // 손익계산서에 기록된 총비용
74
+
75
+ @Column({ nullable: true })
76
+ @Field({ nullable: true, description: 'Net income calculated as revenue minus expenses' })
77
+ netIncome?: number // 총수익에서 총비용을 뺀 순이익
78
+
79
+ @Column({ nullable: true })
80
+ @Field({ nullable: true, description: 'Indicates whether this income statement is active' })
81
+ active?: boolean // 이 손익계산서가 활성 상태인지 여부
82
+
83
+ @OneToMany(type => IncomeStatementLineItem, lineItem => lineItem.statement)
84
+ @Field(type => [IncomeStatementLineItem], { nullable: true })
85
+ lineItems?: IncomeStatementLineItem[] // 계정별 브레이크다운
86
+
87
+ @Column({ nullable: true })
88
+ @Field({ nullable: true })
89
+ createdAt?: Date
90
+
91
+ @Column({ nullable: true })
92
+ @Field({ nullable: true })
93
+ updatedAt?: Date
94
+
95
+ @Column({ nullable: true })
96
+ @Field({ nullable: true })
97
+ deletedAt?: Date
98
+
99
+ @ManyToOne(type => User, { nullable: true })
100
+ @Field({ nullable: true })
101
+ creator?: User
102
+
103
+ @RelationId((incomeStatementHistory: IncomeStatementHistory) => incomeStatementHistory.creator)
104
+ creatorId?: string
105
+
106
+ @ManyToOne(type => User, { nullable: true })
107
+ @Field({ nullable: true })
108
+ updater?: User
109
+
110
+ @RelationId((incomeStatementHistory: IncomeStatementHistory) => incomeStatementHistory.updater)
111
+ updaterId?: string
112
+
113
+ @HistoryOriginalIdColumn()
114
+ public originalId!: string
115
+
116
+ @HistoryActionColumn({
117
+ nullable: false,
118
+ type:
119
+ DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
120
+ ? 'enum'
121
+ : DATABASE_TYPE == 'oracle'
122
+ ? 'varchar2'
123
+ : DATABASE_TYPE == 'mssql'
124
+ ? 'nvarchar'
125
+ : 'varchar',
126
+ enum:
127
+ DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'
128
+ ? HistoryActionType
129
+ : undefined,
130
+ length: DATABASE_TYPE == 'postgres' || DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb' ? undefined : 10
131
+ })
132
+ public action!: HistoryActionType
133
+ }
@@ -0,0 +1,84 @@
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 { IncomeStatement } from './income-statement'
19
+
20
+ @ObjectType({
21
+ description: 'Line item for an income statement, representing a detailed breakdown of financial accounts'
22
+ })
23
+ @Entity()
24
+ @Index(
25
+ 'ix_income_statement_line_item_0',
26
+ (lineItem: IncomeStatementLineItem) => [lineItem.statement, lineItem.account],
27
+ {
28
+ unique: false,
29
+ where: '"deleted_at" IS NULL'
30
+ }
31
+ )
32
+ export class IncomeStatementLineItem {
33
+ @PrimaryGeneratedColumn('uuid')
34
+ @Field(type => ID)
35
+ readonly id: string
36
+
37
+ @ManyToOne(type => IncomeStatement, statement => statement.lineItems)
38
+ @Field(type => IncomeStatement, { description: 'The income statement this line item belongs to' })
39
+ statement: IncomeStatement // 해당 라인 아이템이 속한 손익계산서
40
+
41
+ @RelationId((lineItem: IncomeStatementLineItem) => lineItem.statement)
42
+ statementId: string // 손익계산서의 ID
43
+
44
+ @ManyToOne(type => Account)
45
+ @Field(type => Account, { description: 'The financial account associated with this line item' })
46
+ account: Account // 라인 아이템에 연결된 계정
47
+
48
+ @RelationId((lineItem: IncomeStatementLineItem) => lineItem.account)
49
+ accountId: string // 계정의 ID
50
+
51
+ @Column({ nullable: false })
52
+ @Field({ nullable: false, description: 'The monetary amount associated with this account for the income statement' })
53
+ amount: number // 계정과 관련된 금액
54
+
55
+ @Column({ nullable: true })
56
+ @Field({ nullable: true, description: 'Optional description or notes about this line item' })
57
+ description?: string // 라인 아이템에 대한 선택적 설명 또는 메모
58
+
59
+ @CreateDateColumn()
60
+ @Field({ nullable: true, description: 'The date and time when this line item was created' })
61
+ createdAt?: Date // 라인 아이템이 생성된 날짜 및 시간
62
+
63
+ @UpdateDateColumn()
64
+ @Field({ nullable: true, description: 'The date and time when this line item was last updated' })
65
+ updatedAt?: Date // 라인 아이템이 마지막으로 업데이트된 날짜 및 시간
66
+
67
+ @DeleteDateColumn()
68
+ @Field({ nullable: true, description: 'The date and time when this line item was deleted' })
69
+ deletedAt?: Date // 라인 아이템이 삭제된 날짜 및 시간
70
+
71
+ @ManyToOne(type => User, { nullable: true })
72
+ @Field(type => User, { nullable: true, description: 'The user who created this line item' })
73
+ creator?: User // 라인 아이템을 생성한 사용자
74
+
75
+ @RelationId((lineItem: IncomeStatementLineItem) => lineItem.creator)
76
+ creatorId?: string // 생성자의 ID
77
+
78
+ @ManyToOne(type => User, { nullable: true })
79
+ @Field(type => User, { nullable: true, description: 'The user who last updated this line item' })
80
+ updater?: User // 라인 아이템을 마지막으로 업데이트한 사용자
81
+
82
+ @RelationId((lineItem: IncomeStatementLineItem) => lineItem.updater)
83
+ updaterId?: string // 업데이트한 사용자의 ID
84
+ }
@@ -0,0 +1,147 @@
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 { IncomeStatement } from './income-statement'
6
+ import { NewIncomeStatement, IncomeStatementPatch } from './income-statement-type'
7
+
8
+ @Resolver(IncomeStatement)
9
+ export class IncomeStatementMutation {
10
+ @Directive('@transaction')
11
+ @Directive('@privilege(category: "accounting", privilege: "mutation")')
12
+ @Mutation(returns => IncomeStatement, { description: 'To create new IncomeStatement' })
13
+ async createIncomeStatement(
14
+ @Arg('incomeStatement') incomeStatement: NewIncomeStatement,
15
+ @Ctx() context: ResolverContext
16
+ ): Promise<IncomeStatement> {
17
+ const { domain, user, tx } = context.state
18
+
19
+ const result = await getRepository(IncomeStatement, tx).save({
20
+ ...incomeStatement,
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 => IncomeStatement, { description: 'To modify IncomeStatement information' })
32
+ async updateIncomeStatement(
33
+ @Arg('id') id: string,
34
+ @Arg('patch') patch: IncomeStatementPatch,
35
+ @Ctx() context: ResolverContext
36
+ ): Promise<IncomeStatement> {
37
+ const { domain, user, tx } = context.state
38
+
39
+ const repository = getRepository(IncomeStatement, tx)
40
+ const incomeStatement = await repository.findOne({
41
+ where: { domain: { id: domain.id }, id }
42
+ })
43
+
44
+ const result = await repository.save({
45
+ ...incomeStatement,
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 => [IncomeStatement], { description: "To modify multiple IncomeStatements' information" })
56
+ async updateMultipleIncomeStatement(
57
+ @Arg('patches', type => [IncomeStatementPatch]) patches: IncomeStatementPatch[],
58
+ @Ctx() context: ResolverContext
59
+ ): Promise<IncomeStatement[]> {
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 incomeStatementRepo = getRepository(IncomeStatement, 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 incomeStatementRepo.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 incomeStatement = await incomeStatementRepo.findOneBy({ id: updateRecord.id })
86
+
87
+ const result = await incomeStatementRepo.save({
88
+ ...incomeStatement,
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 IncomeStatement' })
103
+ async deleteIncomeStatement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
104
+ const { domain, tx } = context.state
105
+
106
+ await getRepository(IncomeStatement, 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 IncomeStatements' })
114
+ async deleteIncomeStatements(
115
+ @Arg('ids', type => [String]) ids: string[],
116
+ @Ctx() context: ResolverContext
117
+ ): Promise<boolean> {
118
+ const { domain, tx } = context.state
119
+
120
+ await getRepository(IncomeStatement, 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 IncomeStatements' })
131
+ async importIncomeStatements(
132
+ @Arg('incomeStatements', type => [IncomeStatementPatch]) incomeStatements: IncomeStatementPatch[],
133
+ @Ctx() context: ResolverContext
134
+ ): Promise<boolean> {
135
+ const { domain, tx } = context.state
136
+
137
+ await Promise.all(
138
+ incomeStatements.map(async (incomeStatement: IncomeStatementPatch) => {
139
+ const createdIncomeStatement: IncomeStatement = await tx
140
+ .getRepository(IncomeStatement)
141
+ .save({ domain, ...incomeStatement })
142
+ })
143
+ )
144
+
145
+ return true
146
+ }
147
+ }
@@ -0,0 +1,50 @@
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 { IncomeStatement } from './income-statement'
5
+ import { IncomeStatementList } from './income-statement-type'
6
+
7
+ @Resolver(IncomeStatement)
8
+ export class IncomeStatementQuery {
9
+ @Directive('@privilege(category: "accounting", privilege: "query")')
10
+ @Query(returns => IncomeStatement!, { nullable: true, description: 'To fetch a IncomeStatement' })
11
+ async incomeStatement(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<IncomeStatement> {
12
+ const { domain } = context.state
13
+
14
+ return await getRepository(IncomeStatement).findOne({
15
+ where: { domain: { id: domain.id }, id }
16
+ })
17
+ }
18
+
19
+ @Directive('@privilege(category: "accounting", privilege: "query")')
20
+ @Query(returns => IncomeStatementList, { description: 'To fetch multiple IncomeStatements' })
21
+ async incomeStatements(@Args() params: ListParam, @Ctx() context: ResolverContext): Promise<IncomeStatementList> {
22
+ const { domain } = context.state
23
+
24
+ const queryBuilder = getQueryBuilderFromListParams({
25
+ domain,
26
+ params,
27
+ repository: await getRepository(IncomeStatement),
28
+ searchables: ['name', 'description']
29
+ })
30
+
31
+ const [items, total] = await queryBuilder.getManyAndCount()
32
+
33
+ return { items, total }
34
+ }
35
+
36
+ @FieldResolver(type => Domain)
37
+ async domain(@Root() incomeStatement: IncomeStatement): Promise<Domain> {
38
+ return await getRepository(Domain).findOneBy({ id: incomeStatement.domainId })
39
+ }
40
+
41
+ @FieldResolver(type => User)
42
+ async updater(@Root() incomeStatement: IncomeStatement): Promise<User> {
43
+ return await getRepository(User).findOneBy({ id: incomeStatement.updaterId })
44
+ }
45
+
46
+ @FieldResolver(type => User)
47
+ async creator(@Root() incomeStatement: IncomeStatement): Promise<User> {
48
+ return await getRepository(User).findOneBy({ id: incomeStatement.creatorId })
49
+ }
50
+ }
@@ -0,0 +1,51 @@
1
+ import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'
2
+
3
+ import { IncomeStatement, IncomeStatementStatus } from './income-statement'
4
+
5
+ @InputType()
6
+ export class NewIncomeStatement {
7
+ @Field()
8
+ name: string
9
+
10
+ @Field({ nullable: true })
11
+ description?: string
12
+
13
+ @Field(type => IncomeStatementStatus, { nullable: true })
14
+ state?: IncomeStatementStatus
15
+
16
+ @Field({ nullable: true })
17
+ active?: boolean
18
+
19
+ @Field({ nullable: true })
20
+ params?: string
21
+ }
22
+
23
+ @InputType()
24
+ export class IncomeStatementPatch {
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 => IncomeStatementStatus, { nullable: true })
35
+ state?: IncomeStatementStatus
36
+
37
+ @Field({ nullable: true })
38
+ active?: boolean
39
+
40
+ @Field({ nullable: true })
41
+ cuFlag?: string
42
+ }
43
+
44
+ @ObjectType()
45
+ export class IncomeStatementList {
46
+ @Field(type => [IncomeStatement])
47
+ items: IncomeStatement[]
48
+
49
+ @Field(type => Int)
50
+ total: number
51
+ }