@things-factory/organization 8.0.0-beta.8 → 8.0.0

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 (94) hide show
  1. package/client/bootstrap.ts +23 -0
  2. package/client/component/approval-line-brief.ts +119 -0
  3. package/client/component/approval-line-items-editor-popup.ts +91 -0
  4. package/client/component/approval-line-items-editor.ts +325 -0
  5. package/client/component/approval-line-selector.ts +235 -0
  6. package/client/component/approval-line-templates-manager.ts +229 -0
  7. package/client/component/approval-line-view.ts +122 -0
  8. package/client/component/assignees-editor-popup.ts +79 -0
  9. package/client/component/assignees-editor.ts +217 -0
  10. package/client/component/assignees-view.ts +55 -0
  11. package/client/component/department-selector.ts +151 -0
  12. package/client/component/department-view.ts +107 -0
  13. package/client/component/index.ts +16 -0
  14. package/client/component/recipients-editor-popup.ts +79 -0
  15. package/client/component/recipients-editor.ts +212 -0
  16. package/client/component/recipients-view.ts +55 -0
  17. package/client/grist-editor/grist-editor-approval-line.ts +70 -0
  18. package/client/grist-editor/grist-editor-assignees.ts +69 -0
  19. package/client/grist-editor/grist-editor-department-object.ts +78 -0
  20. package/client/grist-editor/grist-editor-recipients.ts +69 -0
  21. package/client/grist-editor/grist-renderer-approval-line.ts +13 -0
  22. package/client/grist-editor/grist-renderer-assignees.ts +13 -0
  23. package/client/grist-editor/grist-renderer-department-object.ts +13 -0
  24. package/client/grist-editor/grist-renderer-recipients.ts +13 -0
  25. package/client/index.ts +2 -0
  26. package/client/pages/approval-line/common-approval-line-templates-page.ts +382 -0
  27. package/client/pages/approval-line/my-approval-line-templates-page.ts +385 -0
  28. package/client/pages/department/department-importer.ts +87 -0
  29. package/client/pages/department/department-list-page.ts +450 -0
  30. package/client/pages/department/department-tree-page.ts +379 -0
  31. package/client/pages/employee/employee-importer.ts +87 -0
  32. package/client/pages/employee/employee-list-page.ts +772 -0
  33. package/client/pages/employee/employees-by-department.ts +519 -0
  34. package/client/route.ts +27 -0
  35. package/client/tsconfig.json +13 -0
  36. package/client/types/approval-line.ts +52 -0
  37. package/client/types/contact.ts +51 -0
  38. package/client/types/department.ts +29 -0
  39. package/client/types/employee.ts +50 -0
  40. package/client/types/index.ts +5 -0
  41. package/client/types/org-member.ts +27 -0
  42. package/dist-client/bootstrap.js +1 -8
  43. package/dist-client/bootstrap.js.map +1 -1
  44. package/dist-client/pages/employee/employee-list-page.js +3 -3
  45. package/dist-client/pages/employee/employee-list-page.js.map +1 -1
  46. package/dist-client/pages/employee/employees-by-department.js +2 -2
  47. package/dist-client/pages/employee/employees-by-department.js.map +1 -1
  48. package/dist-client/tsconfig.tsbuildinfo +1 -1
  49. package/dist-server/service/employee/employee-history.d.ts +2 -6
  50. package/dist-server/service/employee/employee-history.js +3 -23
  51. package/dist-server/service/employee/employee-history.js.map +1 -1
  52. package/dist-server/service/employee/employee-query.js +1 -1
  53. package/dist-server/service/employee/employee-query.js.map +1 -1
  54. package/dist-server/service/employee/employee-type.d.ts +5 -13
  55. package/dist-server/service/employee/employee-type.js +7 -39
  56. package/dist-server/service/employee/employee-type.js.map +1 -1
  57. package/dist-server/service/employee/employee.d.ts +2 -6
  58. package/dist-server/service/employee/employee.js +3 -23
  59. package/dist-server/service/employee/employee.js.map +1 -1
  60. package/dist-server/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +12 -12
  62. package/server/controllers/register-employee-as-system-user.ts +136 -0
  63. package/server/index.ts +3 -0
  64. package/server/migrations/1723861013111-seed-organization-codes.ts +127 -0
  65. package/server/migrations/index.ts +9 -0
  66. package/server/routes.ts +26 -0
  67. package/server/service/approval-line/approval-line-item.ts +42 -0
  68. package/server/service/approval-line/approval-line-mutation.ts +394 -0
  69. package/server/service/approval-line/approval-line-query.ts +208 -0
  70. package/server/service/approval-line/approval-line-type.ts +63 -0
  71. package/server/service/approval-line/approval-line.ts +123 -0
  72. package/server/service/approval-line/index.ts +7 -0
  73. package/server/service/department/department-history.ts +141 -0
  74. package/server/service/department/department-mutation.ts +231 -0
  75. package/server/service/department/department-query.ts +131 -0
  76. package/server/service/department/department-type.ts +74 -0
  77. package/server/service/department/department.ts +116 -0
  78. package/server/service/department/event-subscriber.ts +17 -0
  79. package/server/service/department/index.ts +9 -0
  80. package/server/service/employee/employee-history.ts +173 -0
  81. package/server/service/employee/employee-mutation.ts +386 -0
  82. package/server/service/employee/employee-query.ts +172 -0
  83. package/server/service/employee/employee-type.ts +176 -0
  84. package/server/service/employee/employee.ts +177 -0
  85. package/server/service/employee/event-subscriber.ts +17 -0
  86. package/server/service/employee/index.ts +9 -0
  87. package/server/service/index.ts +39 -0
  88. package/server/tsconfig.json +10 -0
  89. package/dist-client/filters-form/filter-department-object.d.ts +0 -3
  90. package/dist-client/filters-form/filter-department-object.js +0 -8
  91. package/dist-client/filters-form/filter-department-object.js.map +0 -1
  92. package/dist-client/filters-form/ox-filter-department-object.d.ts +0 -15
  93. package/dist-client/filters-form/ox-filter-department-object.js +0 -130
  94. package/dist-client/filters-form/ox-filter-department-object.js.map +0 -1
@@ -0,0 +1,394 @@
1
+ import { Resolver, Mutation, Arg, Ctx, Directive } from 'type-graphql'
2
+ import { In } from 'typeorm'
3
+
4
+ import { getRepository } from '@things-factory/shell'
5
+ import { Employee } from '../employee/employee'
6
+ import { ApprovalLine, ApprovalLineOwnerType } from './approval-line'
7
+ import { ApprovalLineItem, OrgMemberTargetType } from './approval-line-item'
8
+ import { NewApprovalLine, ApprovalLinePatch } from './approval-line-type'
9
+
10
+ async function getOwnerValue(
11
+ approvalLine: ApprovalLine | NewApprovalLine | ApprovalLinePatch,
12
+ patch: NewApprovalLine | ApprovalLinePatch,
13
+ context: ResolverContext
14
+ ) {
15
+ if (!('owner' in patch || 'ownerType' in patch)) {
16
+ /* owner 또는 ownerType 하나도 언급되지 않았다면, 업데이트하지 않는다. */
17
+ return
18
+ }
19
+
20
+ const { domain, tx } = context.state
21
+ const { ownerType, owner } = patch
22
+
23
+ if (!ownerType || !owner) {
24
+ /* ownerType이 클리어되거나, owner가 지정되지 않았다면, 클리어시킨다. */
25
+ return null
26
+ }
27
+
28
+ var ownerObject
29
+
30
+ switch (ownerType || approvalLine.ownerType) {
31
+ case ApprovalLineOwnerType.Employee:
32
+ ownerObject = await getRepository(Employee, tx).findOneBy({ domain: { id: domain.id }, id: owner.id })
33
+ break
34
+ default:
35
+ }
36
+
37
+ return ownerObject?.id || null
38
+ }
39
+
40
+ function getModelValue(patch: NewApprovalLine | ApprovalLinePatch): ApprovalLineItem[] {
41
+ if (!('model' in patch)) {
42
+ /* model이 언급되지 않았다면, 업데이트하지 않는다. */
43
+ return
44
+ }
45
+
46
+ const { model } = patch
47
+
48
+ if (!model || !(model instanceof Array)) {
49
+ /* model의 값이 없거나 배열이 아니라면, 클리어시킨다. */
50
+ return null
51
+ }
52
+
53
+ return model
54
+ .map(m => {
55
+ return {
56
+ type: m.type,
57
+ approver: m.approver
58
+ } as ApprovalLineItem
59
+ })
60
+ .filter(m => m.type)
61
+ .filter(m => {
62
+ switch (m.type) {
63
+ case OrgMemberTargetType.Employee:
64
+ case OrgMemberTargetType.Department:
65
+ case OrgMemberTargetType.Role:
66
+ return !!m.approver?.id
67
+ default:
68
+ return true
69
+ }
70
+ })
71
+ }
72
+
73
+ @Resolver(ApprovalLine)
74
+ export class ApprovalLineMutation {
75
+ @Directive('@transaction')
76
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
77
+ @Mutation(returns => ApprovalLine, { description: 'To create new ApprovalLine' })
78
+ async createApprovalLine(
79
+ @Arg('approvalLine') approvalLine: NewApprovalLine,
80
+ @Ctx() context: ResolverContext
81
+ ): Promise<ApprovalLine> {
82
+ const { domain, user, tx } = context.state
83
+
84
+ const result = await getRepository(ApprovalLine, tx).save({
85
+ ...approvalLine,
86
+ ownerValue: await getOwnerValue(approvalLine, approvalLine, context),
87
+ model: getModelValue(approvalLine),
88
+ domain,
89
+ creator: user,
90
+ updater: user
91
+ })
92
+
93
+ return result
94
+ }
95
+
96
+ @Directive('@transaction')
97
+ @Mutation(returns => ApprovalLine, { description: 'To create new ApprovalLine for current user' })
98
+ async createMyApprovalLine(
99
+ @Arg('approvalLine') approvalLine: NewApprovalLine,
100
+ @Ctx() context: ResolverContext
101
+ ): Promise<ApprovalLine> {
102
+ const { domain, user, tx } = context.state
103
+ const employee = await getRepository(Employee, tx).findOneBy({
104
+ domain: { id: domain.id },
105
+ user: { id: user.id }
106
+ })
107
+
108
+ if (!employee) {
109
+ throw new Error('There is no employee object associated with the user.')
110
+ }
111
+
112
+ const result = await getRepository(ApprovalLine, tx).save({
113
+ ...approvalLine,
114
+ ownerType: ApprovalLineOwnerType.Employee,
115
+ ownerValue: employee.id,
116
+ model: getModelValue(approvalLine),
117
+ domain,
118
+ creator: user,
119
+ updater: user
120
+ })
121
+
122
+ return result
123
+ }
124
+
125
+ @Directive('@transaction')
126
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
127
+ @Mutation(returns => ApprovalLine, { description: 'To modify ApprovalLine information' })
128
+ async updateApprovalLine(
129
+ @Arg('id') id: string,
130
+ @Arg('patch') patch: ApprovalLinePatch,
131
+ @Ctx() context: ResolverContext
132
+ ): Promise<ApprovalLine> {
133
+ const { domain, user, tx } = context.state
134
+
135
+ const repository = getRepository(ApprovalLine, tx)
136
+ const approvalLine = await repository.findOne({
137
+ where: { domain: { id: domain.id }, id }
138
+ })
139
+
140
+ const result = await repository.save({
141
+ ...approvalLine,
142
+ ...patch,
143
+ ownerValue: await getOwnerValue(approvalLine, patch, context),
144
+ model: getModelValue(patch),
145
+ updater: user
146
+ })
147
+
148
+ return result
149
+ }
150
+
151
+ @Directive('@transaction')
152
+ @Mutation(returns => ApprovalLine, { description: 'To modify ApprovalLine information for current user' })
153
+ async updateMyApprovalLine(
154
+ @Arg('id') id: string,
155
+ @Arg('patch') patch: ApprovalLinePatch,
156
+ @Ctx() context: ResolverContext
157
+ ): Promise<ApprovalLine> {
158
+ const { domain, user, tx } = context.state
159
+ const employee = await getRepository(Employee, tx).findOneBy({
160
+ domain: { id: domain.id },
161
+ user: { id: user.id }
162
+ })
163
+
164
+ const repository = getRepository(ApprovalLine, tx)
165
+ const approvalLine = await repository.findOne({
166
+ where: { domain: { id: domain.id }, id }
167
+ })
168
+
169
+ const result = await repository.save({
170
+ ...approvalLine,
171
+ ...patch,
172
+ ownerType: ApprovalLineOwnerType.Employee,
173
+ ownerValue: employee.id,
174
+ model: getModelValue(patch),
175
+ updater: user
176
+ })
177
+
178
+ return result
179
+ }
180
+
181
+ @Directive('@transaction')
182
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
183
+ @Mutation(returns => [ApprovalLine], { description: "To modify multiple ApprovalLines' information" })
184
+ async updateMultipleApprovalLine(
185
+ @Arg('patches', type => [ApprovalLinePatch]) patches: ApprovalLinePatch[],
186
+ @Ctx() context: ResolverContext
187
+ ): Promise<ApprovalLine[]> {
188
+ const { domain, user, tx } = context.state
189
+
190
+ let results = []
191
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
192
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
193
+ const approvalLineRepo = getRepository(ApprovalLine, tx)
194
+
195
+ if (_createRecords.length > 0) {
196
+ for (let i = 0; i < _createRecords.length; i++) {
197
+ const newRecord = _createRecords[i]
198
+
199
+ const result = await approvalLineRepo.save({
200
+ ...newRecord,
201
+ ownerValue: await getOwnerValue(newRecord, newRecord, context),
202
+ model: getModelValue(newRecord),
203
+ domain,
204
+ creator: user,
205
+ updater: user
206
+ })
207
+
208
+ results.push({ ...result, cuFlag: '+' })
209
+ }
210
+ }
211
+
212
+ if (_updateRecords.length > 0) {
213
+ for (let i = 0; i < _updateRecords.length; i++) {
214
+ const updateRecord = _updateRecords[i]
215
+ const approvalLine = await approvalLineRepo.findOneBy({ id: updateRecord.id })
216
+
217
+ const result = await approvalLineRepo.save({
218
+ ...approvalLine,
219
+ ...updateRecord,
220
+ ownerValue: await getOwnerValue(approvalLine, updateRecord, context),
221
+ model: getModelValue(updateRecord),
222
+ updater: user
223
+ })
224
+
225
+ results.push({ ...result, cuFlag: 'M' })
226
+ }
227
+ }
228
+
229
+ return results
230
+ }
231
+
232
+ @Directive('@transaction')
233
+ @Mutation(returns => [ApprovalLine], {
234
+ description: "To modify multiple ApprovalLines' information for current user"
235
+ })
236
+ async updateMultipleMyApprovalLine(
237
+ @Arg('patches', type => [ApprovalLinePatch]) patches: ApprovalLinePatch[],
238
+ @Ctx() context: ResolverContext
239
+ ): Promise<ApprovalLine[]> {
240
+ const { domain, user, tx } = context.state
241
+
242
+ const employee = await getRepository(Employee, tx).findOneBy({
243
+ domain: { id: domain.id },
244
+ user: { id: user.id }
245
+ })
246
+
247
+ if (!employee) {
248
+ throw new Error('There is no employee object associated with the user.')
249
+ }
250
+
251
+ let results = []
252
+ const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
253
+ const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')
254
+ const approvalLineRepo = getRepository(ApprovalLine, tx)
255
+
256
+ if (_createRecords.length > 0) {
257
+ for (let i = 0; i < _createRecords.length; i++) {
258
+ const newRecord = _createRecords[i]
259
+
260
+ const result = await approvalLineRepo.save({
261
+ ...newRecord,
262
+ ownerType: ApprovalLineOwnerType.Employee,
263
+ ownerValue: employee.id,
264
+ model: getModelValue(newRecord),
265
+ domain,
266
+ creator: user,
267
+ updater: user
268
+ })
269
+
270
+ results.push({ ...result, cuFlag: '+' })
271
+ }
272
+ }
273
+
274
+ if (_updateRecords.length > 0) {
275
+ for (let i = 0; i < _updateRecords.length; i++) {
276
+ const updateRecord = _updateRecords[i]
277
+ const approvalLine = await approvalLineRepo.findOneBy({ id: updateRecord.id })
278
+
279
+ const result = await approvalLineRepo.save({
280
+ ...approvalLine,
281
+ ...updateRecord,
282
+ ownerType: ApprovalLineOwnerType.Employee,
283
+ ownerValue: employee.id,
284
+ model: getModelValue(updateRecord),
285
+ updater: user
286
+ })
287
+
288
+ results.push({ ...result, cuFlag: 'M' })
289
+ }
290
+ }
291
+
292
+ return results
293
+ }
294
+
295
+ @Directive('@transaction')
296
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
297
+ @Mutation(returns => Boolean, { description: 'To delete ApprovalLine' })
298
+ async deleteApprovalLine(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
299
+ const { domain, tx } = context.state
300
+
301
+ await getRepository(ApprovalLine, tx).delete({ domain: { id: domain.id }, id })
302
+
303
+ return true
304
+ }
305
+
306
+ @Directive('@transaction')
307
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
308
+ @Mutation(returns => Boolean, { description: 'To delete multiple ApprovalLines' })
309
+ async deleteApprovalLines(
310
+ @Arg('ids', type => [String]) ids: string[],
311
+ @Ctx() context: ResolverContext
312
+ ): Promise<boolean> {
313
+ const { domain, tx } = context.state
314
+
315
+ await getRepository(ApprovalLine, tx).delete({
316
+ domain: { id: domain.id },
317
+ id: In(ids)
318
+ })
319
+
320
+ return true
321
+ }
322
+
323
+ @Directive('@transaction')
324
+ @Mutation(returns => Boolean, { description: 'To delete ApprovalLine for current user' })
325
+ async deleteMyApprovalLine(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
326
+ const { domain, user, tx } = context.state
327
+
328
+ const employee = await getRepository(Employee, tx).findOneBy({
329
+ domain: { id: domain.id },
330
+ user: { id: user.id }
331
+ })
332
+
333
+ if (!employee) {
334
+ throw new Error('There is no employee object associated with the user.')
335
+ }
336
+
337
+ await getRepository(ApprovalLine, tx).delete({
338
+ id,
339
+ domain: { id: domain.id },
340
+ ownerType: ApprovalLineOwnerType.Employee,
341
+ ownerValue: employee.id
342
+ })
343
+
344
+ return true
345
+ }
346
+
347
+ @Directive('@transaction')
348
+ @Mutation(returns => Boolean, { description: 'To delete multiple ApprovalLines for current user' })
349
+ async deleteMyApprovalLines(
350
+ @Arg('ids', type => [String]) ids: string[],
351
+ @Ctx() context: ResolverContext
352
+ ): Promise<boolean> {
353
+ const { domain, user, tx } = context.state
354
+
355
+ const employee = await getRepository(Employee, tx).findOneBy({
356
+ domain: { id: domain.id },
357
+ user: { id: user.id }
358
+ })
359
+
360
+ if (!employee) {
361
+ throw new Error('There is no employee object associated with the user.')
362
+ }
363
+
364
+ await getRepository(ApprovalLine, tx).delete({
365
+ domain: { id: domain.id },
366
+ ownerType: ApprovalLineOwnerType.Employee,
367
+ ownerValue: employee.id,
368
+ id: In(ids)
369
+ })
370
+
371
+ return true
372
+ }
373
+
374
+ @Directive('@transaction')
375
+ @Directive('@privilege(category: "organization", privilege: "mutation", domainOwnerGranted: true)')
376
+ @Mutation(returns => Boolean, { description: 'To import multiple ApprovalLines' })
377
+ async importApprovalLines(
378
+ @Arg('approvalLines', type => [ApprovalLinePatch]) approvalLines: ApprovalLinePatch[],
379
+ @Ctx() context: ResolverContext
380
+ ): Promise<boolean> {
381
+ const { domain, tx } = context.state
382
+
383
+ await Promise.all(
384
+ approvalLines.map(async (approvalLine: ApprovalLinePatch) => {
385
+ const createdApprovalLine: ApprovalLine = await getRepository(ApprovalLine, tx).save({
386
+ domain,
387
+ ...approvalLine
388
+ })
389
+ })
390
+ )
391
+
392
+ return true
393
+ }
394
+ }
@@ -0,0 +1,208 @@
1
+ import { Directive, Resolver, Query, FieldResolver, Root, Args, Arg, Ctx } from 'type-graphql'
2
+ import { Brackets, In } from 'typeorm'
3
+ import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
4
+ import { Role, User } from '@things-factory/auth-base'
5
+ import { ApprovalLineItem, OrgMemberTargetType } from './approval-line-item'
6
+ import { ApprovalLine, ApprovalLineOwner, ApprovalLineOwnerType } from './approval-line'
7
+ import { ApprovalLineList } from './approval-line-type'
8
+ import { Employee } from '../employee/employee'
9
+ import { Department } from '../department/department'
10
+
11
+ async function getOwnerValue(approvalLine: ApprovalLine, context: ResolverContext) {
12
+ const { domain } = context.state
13
+ const { ownerType, ownerValue } = approvalLine
14
+
15
+ if (!ownerType || !ownerValue) {
16
+ /* ownerType이 클리어되거나, owner가 지정되지 않았다면, 클리어시킨다. */
17
+ return null
18
+ }
19
+
20
+ var ownerObject
21
+
22
+ switch (ownerType) {
23
+ case ApprovalLineOwnerType.Employee:
24
+ ownerObject = await getRepository(Employee).findOneBy({ domain: { id: domain.id }, id: ownerValue })
25
+ break
26
+ default:
27
+ return null
28
+ }
29
+
30
+ return ownerObject
31
+ }
32
+
33
+ async function getModel(approvalLine: ApprovalLine, context: ResolverContext): Promise<ApprovalLineItem[]> {
34
+ const { domain } = context.state
35
+ const { model } = approvalLine
36
+
37
+ if (!model || !(model instanceof Array)) {
38
+ return null
39
+ }
40
+
41
+ var approvalLineItemList = []
42
+
43
+ for (let item of model) {
44
+ /* deprecated "value", use approver */
45
+ var { type, value, approver } = item
46
+ var id = approver?.id || value
47
+ approver = null
48
+
49
+ switch (type) {
50
+ case OrgMemberTargetType.Employee:
51
+ approver = id && (await getRepository(Employee).findOneBy({ domain: { id: domain.id }, id }))
52
+ break
53
+ case OrgMemberTargetType.Department:
54
+ approver = id && (await getRepository(Department).findOneBy({ domain: { id: domain.id }, id }))
55
+ break
56
+ case OrgMemberTargetType.Role:
57
+ approver = id && (await getRepository(Role).findOneBy({ domain: { id: domain.id }, id }))
58
+ break
59
+ case OrgMemberTargetType.Myself:
60
+ case OrgMemberTargetType.MyDepartment:
61
+ case OrgMemberTargetType.MySupervisor:
62
+ break
63
+ default:
64
+ continue
65
+ }
66
+
67
+ approvalLineItemList.push({ type, approver })
68
+ }
69
+
70
+ return approvalLineItemList
71
+ }
72
+
73
+ @Resolver(ApprovalLine)
74
+ export class ApprovalLineQuery {
75
+ @Query(returns => ApprovalLine!, { nullable: true, description: 'To fetch a approval line' })
76
+ async approvalLine(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ApprovalLine> {
77
+ const { domain } = context.state
78
+
79
+ return await getRepository(ApprovalLine).findOne({
80
+ where: { domain: { id: domain.id }, id }
81
+ })
82
+ }
83
+
84
+ @Directive('@privilege(category: "organization", privilege: "query", domainOwnerGranted: true)')
85
+ @Query(returns => ApprovalLineList, { description: 'To fetch multiple approval lines' })
86
+ async approvalLines(
87
+ @Args(type => ListParam) params: ListParam,
88
+ @Ctx() context: ResolverContext
89
+ ): Promise<ApprovalLineList> {
90
+ const { domain } = context.state
91
+
92
+ const queryBuilder = getQueryBuilderFromListParams({
93
+ domain,
94
+ params,
95
+ repository: await getRepository(ApprovalLine),
96
+ searchables: ['name', 'description']
97
+ })
98
+
99
+ const [items, total] = await queryBuilder.getManyAndCount()
100
+
101
+ return { items, total }
102
+ }
103
+
104
+ @Query(returns => ApprovalLineList, { description: 'To fetch referable approval lines for the user' })
105
+ async approvalLineReferences(
106
+ @Args(type => ListParam) params: ListParam,
107
+ @Ctx() context: ResolverContext
108
+ ): Promise<ApprovalLineList> {
109
+ const { domain, user } = context.state
110
+ const employees = await getRepository(Employee).findBy({
111
+ domain: { id: domain.id },
112
+ user: { id: user.id }
113
+ })
114
+
115
+ const queryBuilder = getQueryBuilderFromListParams({
116
+ domain,
117
+ params,
118
+ repository: await getRepository(ApprovalLine),
119
+ searchables: ['name', 'description']
120
+ }).andWhere(
121
+ employees.length > 0
122
+ ? new Brackets(qb => {
123
+ qb.where({ ownerType: 'Common' })
124
+ qb.orWhere({
125
+ ownerType: 'Employee',
126
+ ownerValue: In(employees.map(employee => employee.id))
127
+ })
128
+ })
129
+ : { ownerType: 'Common' }
130
+ )
131
+
132
+ const [items, total] = await queryBuilder.getManyAndCount()
133
+
134
+ return { items, total }
135
+ }
136
+
137
+ @Query(returns => ApprovalLineList, { description: 'To fetch approval lines only for to the user' })
138
+ async myApprovalLines(
139
+ @Args(type => ListParam) params: ListParam,
140
+ @Ctx() context: ResolverContext
141
+ ): Promise<ApprovalLineList> {
142
+ const { domain, user } = context.state
143
+ const employees = await getRepository(Employee).findBy({
144
+ domain: { id: domain.id },
145
+ user: { id: user.id }
146
+ })
147
+
148
+ const queryBuilder = getQueryBuilderFromListParams({
149
+ domain,
150
+ params,
151
+ repository: await getRepository(ApprovalLine),
152
+ searchables: ['name', 'description']
153
+ }).andWhere({
154
+ ownerType: 'Employee',
155
+ ownerValue: In(employees.map(employee => employee.id))
156
+ })
157
+
158
+ const [items, total] = await queryBuilder.getManyAndCount()
159
+
160
+ return { items, total }
161
+ }
162
+
163
+ @Query(returns => ApprovalLineList, { description: 'To fetch common approval lines' })
164
+ async commonApprovalLines(
165
+ @Args(type => ListParam) params: ListParam,
166
+ @Ctx() context: ResolverContext
167
+ ): Promise<ApprovalLineList> {
168
+ const { domain, user } = context.state
169
+
170
+ const queryBuilder = getQueryBuilderFromListParams({
171
+ domain,
172
+ params,
173
+ repository: await getRepository(ApprovalLine),
174
+ searchables: ['name', 'description']
175
+ }).andWhere({
176
+ ownerType: 'Common'
177
+ })
178
+
179
+ const [items, total] = await queryBuilder.getManyAndCount()
180
+
181
+ return { items, total }
182
+ }
183
+
184
+ @FieldResolver(type => [ApprovalLineItem])
185
+ async model(@Root() approvalLine: ApprovalLine, @Ctx() context: ResolverContext): Promise<ApprovalLineItem[]> {
186
+ return await getModel(approvalLine, context)
187
+ }
188
+
189
+ @FieldResolver(type => ApprovalLineOwner)
190
+ async owner(@Root() approvalLine: ApprovalLine, @Ctx() context: ResolverContext): Promise<ApprovalLineOwner> {
191
+ return await getOwnerValue(approvalLine, context)
192
+ }
193
+
194
+ @FieldResolver(type => Domain)
195
+ async domain(@Root() approvalLine: ApprovalLine): Promise<Domain> {
196
+ return await getRepository(Domain).findOneBy({ id: approvalLine.domainId })
197
+ }
198
+
199
+ @FieldResolver(type => User)
200
+ async updater(@Root() approvalLine: ApprovalLine): Promise<User> {
201
+ return await getRepository(User).findOneBy({ id: approvalLine.updaterId })
202
+ }
203
+
204
+ @FieldResolver(type => User)
205
+ async creator(@Root() approvalLine: ApprovalLine): Promise<User> {
206
+ return await getRepository(User).findOneBy({ id: approvalLine.creatorId })
207
+ }
208
+ }
@@ -0,0 +1,63 @@
1
+ import { ObjectType, Field, InputType, Int, ID } from 'type-graphql'
2
+
3
+ import { ObjectRef, ScalarObject } from '@things-factory/shell'
4
+
5
+ import { ApprovalLine, ApprovalLineOwnerType } from './approval-line'
6
+ import { ApprovalLineItem } from './approval-line-item'
7
+
8
+ @InputType()
9
+ export class ObjectRefApprovalLineOwnerType extends ObjectRef {
10
+ @Field({ nullable: true })
11
+ controlNo?: string
12
+ }
13
+
14
+ @InputType()
15
+ export class NewApprovalLine {
16
+ @Field()
17
+ name: string
18
+
19
+ @Field({ nullable: true })
20
+ description?: string
21
+
22
+ @Field(type => ApprovalLineOwnerType)
23
+ ownerType: ApprovalLineOwnerType
24
+
25
+ @Field(type => ObjectRefApprovalLineOwnerType)
26
+ owner: ObjectRefApprovalLineOwnerType
27
+
28
+ @Field(type => ScalarObject, { nullable: true })
29
+ model?: ApprovalLineItem[]
30
+ }
31
+
32
+ @InputType()
33
+ export class ApprovalLinePatch {
34
+ @Field(type => ID, { nullable: true })
35
+ id?: string
36
+
37
+ @Field({ nullable: true })
38
+ name?: string
39
+
40
+ @Field({ nullable: true })
41
+ description?: string
42
+
43
+ @Field(type => ApprovalLineOwnerType, { nullable: true })
44
+ ownerType?: ApprovalLineOwnerType
45
+
46
+ @Field(type => ObjectRefApprovalLineOwnerType, { nullable: true })
47
+ owner?: ObjectRefApprovalLineOwnerType
48
+
49
+ @Field(type => ScalarObject, { nullable: true })
50
+ model?: ApprovalLineItem[]
51
+
52
+ @Field({ nullable: true })
53
+ cuFlag?: string
54
+ }
55
+
56
+ @ObjectType()
57
+ export class ApprovalLineList {
58
+ @Field(type => [ApprovalLine])
59
+ items: ApprovalLine[]
60
+
61
+ @Field(type => Int)
62
+ total: number
63
+ }