@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/organization",
3
- "version": "8.0.0-beta.8",
3
+ "version": "8.0.0",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -27,16 +27,16 @@
27
27
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
28
28
  },
29
29
  "dependencies": {
30
- "@operato/app": "^8.0.0-beta",
31
- "@operato/contact": "^8.0.0-beta",
32
- "@operato/data-tree": "^8.0.0-beta",
33
- "@operato/graphql": "^8.0.0-beta",
34
- "@operato/p13n": "^8.0.0-beta",
35
- "@operato/shell": "^8.0.0-beta",
36
- "@things-factory/auth-base": "^8.0.0-beta.8",
37
- "@things-factory/code-ui": "^8.0.0-beta.8",
38
- "@things-factory/contact": "^8.0.0-beta.8",
39
- "@things-factory/shell": "^8.0.0-beta.5"
30
+ "@operato/app": "^8.0.0",
31
+ "@operato/contact": "^8.0.0",
32
+ "@operato/data-tree": "^8.0.0",
33
+ "@operato/graphql": "^8.0.0",
34
+ "@operato/p13n": "^8.0.0",
35
+ "@operato/shell": "^8.0.0",
36
+ "@things-factory/auth-base": "^8.0.0",
37
+ "@things-factory/code-ui": "^8.0.0",
38
+ "@things-factory/contact": "^8.0.0",
39
+ "@things-factory/shell": "^8.0.0"
40
40
  },
41
- "gitHead": "bf5206511b2d84dfb95edc3dae7f54f6cbb9bcca"
41
+ "gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
42
42
  }
@@ -0,0 +1,136 @@
1
+ import { getRepository } from '@things-factory/shell'
2
+ import { Employee } from '../service/employee/employee'
3
+ import { registerContactAsSystemUser } from '@things-factory/contact'
4
+ import { Role, User } from '@things-factory/auth-base'
5
+ import { EmployeePatch } from 'service/employee/employee-type'
6
+
7
+ export async function registerEmployeeAsSystemUser(employeeId: string, context: ResolverContext) {
8
+ const { domain, tx } = context.state
9
+
10
+ const employeeRepository = getRepository(Employee, tx)
11
+
12
+ const employee = await employeeRepository.findOne({
13
+ where: {
14
+ id: employeeId,
15
+ domain: { id: domain.id }
16
+ },
17
+ relations: ['contact', 'user']
18
+ })
19
+
20
+ if (employee.user) {
21
+ throw new Error(context.t('error.employee-already-registered'))
22
+ }
23
+
24
+ if (!employee.contact) {
25
+ throw new Error(context.t('error.contact-information-required'))
26
+ }
27
+
28
+ const systemUser = await registerContactAsSystemUser(
29
+ {
30
+ contactId: employee.contact.id,
31
+ roleName: employee.active ? employee.jobResponsibility : ''
32
+ },
33
+ context
34
+ )
35
+
36
+ employee.user = systemUser
37
+
38
+ await employeeRepository.save(employee)
39
+
40
+ return systemUser
41
+ }
42
+
43
+ export async function onUpdateEmployeeAsSystemUser(patch: EmployeePatch, context: ResolverContext) {
44
+ const { domain, user, tx } = context.state
45
+ const { id, jobResponsibility } = patch
46
+
47
+ const employeeRepository = getRepository(Employee, tx)
48
+
49
+ const employee = await employeeRepository.findOne({
50
+ where: {
51
+ id,
52
+ domain: { id: domain.id }
53
+ },
54
+ relations: ['contact', 'user']
55
+ })
56
+
57
+ if (!employee.user) {
58
+ return
59
+ }
60
+
61
+ const { jobResponsibility: lastJobResponsibility } = employee
62
+
63
+ if ('jobResponsibility' in patch && lastJobResponsibility !== jobResponsibility) {
64
+ const userRepository = getRepository(User, tx)
65
+
66
+ const systemUser = await userRepository.findOne({
67
+ where: { id: employee.user.id },
68
+ relations: ['domains', 'roles']
69
+ })
70
+
71
+ const { roles } = systemUser
72
+ let newRoles = [...roles]
73
+
74
+ if (lastJobResponsibility) {
75
+ const lastRole = await getRepository(Role, tx).findOne({
76
+ where: { name: lastJobResponsibility, domain: { id: domain.id } }
77
+ })
78
+
79
+ if (lastRole) {
80
+ newRoles = roles.filter(role => role.id !== lastRole.id)
81
+ }
82
+ }
83
+
84
+ const newRole = await getRepository(Role, tx).findOne({
85
+ where: { name: jobResponsibility, domain: { id: domain.id } }
86
+ })
87
+
88
+ if (newRole && !roles.find(role => role.id === newRole.id)) {
89
+ newRoles = [...newRoles, newRole]
90
+ }
91
+
92
+ systemUser.roles = newRoles
93
+ systemUser.updater = user
94
+
95
+ await userRepository.save(systemUser)
96
+ }
97
+ }
98
+
99
+ export async function onDeleteEmployeeAsSystemUser(employeeId: string, context: ResolverContext) {
100
+ const { domain, user, tx } = context.state
101
+
102
+ const employeeRepository = getRepository(Employee, tx)
103
+
104
+ const employee = await employeeRepository.findOne({
105
+ where: {
106
+ id: employeeId,
107
+ domain: { id: domain.id }
108
+ },
109
+ relations: ['user']
110
+ })
111
+
112
+ if (!employee.user) {
113
+ return
114
+ }
115
+
116
+ const { jobResponsibility } = employee
117
+
118
+ if (jobResponsibility) {
119
+ const userRepository = getRepository(User, tx)
120
+
121
+ const systemUser = await userRepository.findOne({
122
+ where: { id: employee.user.id },
123
+ relations: ['domains', 'roles']
124
+ })
125
+
126
+ const lastRole = await getRepository(Role, tx).findOne({
127
+ where: { name: jobResponsibility, domain: { id: domain.id } }
128
+ })
129
+
130
+ if (lastRole) {
131
+ systemUser.roles = systemUser.roles.filter(role => role.id !== lastRole.id)
132
+ systemUser.updater = user
133
+ await userRepository.save(systemUser)
134
+ }
135
+ }
136
+ }
@@ -0,0 +1,3 @@
1
+ export * from './service'
2
+
3
+ import './routes'
@@ -0,0 +1,127 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm'
2
+
3
+ import { logger } from '@things-factory/env'
4
+ import { Domain, getRepository } from '@things-factory/shell'
5
+ import { User } from '@things-factory/auth-base'
6
+ import { CommonCode, CommonCodeDetail } from '@things-factory/code-base'
7
+
8
+ const SEED_COMMON_CODES = [
9
+ {
10
+ name: 'EMPLOYEE_TYPE',
11
+ description: '직원 유형',
12
+ details: [
13
+ {
14
+ name: 'FULLTIME',
15
+ description: '풀타임 정규직',
16
+ labels: null,
17
+ rank: 1
18
+ },
19
+ {
20
+ name: 'PARTTIME',
21
+ description: '파트타임 정규직',
22
+ labels: null,
23
+ rank: 2
24
+ },
25
+ {
26
+ name: 'TEMPORARY',
27
+ description: '임시직',
28
+ labels: null,
29
+ rank: 3
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ name: 'JOB_POSITION',
35
+ description: '직급',
36
+ details: [
37
+ // {
38
+ // name: '임원',
39
+ // description: '임원',
40
+ // labels: null,
41
+ // rank: 1
42
+ // },
43
+ // {
44
+ // name: '직원',
45
+ // description: '직원',
46
+ // labels: null,
47
+ // rank: 2
48
+ // }
49
+ ]
50
+ },
51
+ {
52
+ name: 'JOB_RESPONSIBILITY',
53
+ description: '직책',
54
+ details: [
55
+ // {
56
+ // name: '상담사',
57
+ // description: '상담사',
58
+ // labels: null,
59
+ // rank: 1
60
+ // },
61
+ // {
62
+ // name: '매니저',
63
+ // description: '매니저',
64
+ // labels: null,
65
+ // rank: 2
66
+ // }
67
+ ]
68
+ }
69
+ ]
70
+
71
+ export class SeedOrganizationCodes1723861013111 implements MigrationInterface {
72
+ public async up(queryRunner: QueryRunner): Promise<void> {
73
+ const commonCodeRepository = getRepository(CommonCode)
74
+ const commonCodeDetailRepository = getRepository(CommonCodeDetail)
75
+ const domainRepository = getRepository(Domain)
76
+ const userRepository = getRepository(User)
77
+
78
+ const domain: Domain = await domainRepository.findOne({
79
+ where: { name: 'SYSTEM' }
80
+ })
81
+ const user = await userRepository.findOne({ where: { id: domain.owner } })
82
+
83
+ try {
84
+ for (let i = 0; i < SEED_COMMON_CODES.length; i++) {
85
+ const { name, description, details } = SEED_COMMON_CODES[i]
86
+
87
+ const commonCode = await commonCodeRepository.save({
88
+ domain,
89
+ name,
90
+ description,
91
+ creator: user,
92
+ updater: user
93
+ })
94
+
95
+ for (const commonCodeDetail of details) {
96
+ const { name, description, labels, rank } = commonCodeDetail
97
+
98
+ await commonCodeDetailRepository.save({
99
+ domain,
100
+ commonCode,
101
+ name,
102
+ description,
103
+ labels,
104
+ rank
105
+ })
106
+ }
107
+ }
108
+ } catch (e) {
109
+ logger.error(e)
110
+ }
111
+ }
112
+
113
+ public async down(queryRunner: QueryRunner): Promise<void> {
114
+ const domainRepository = getRepository(Domain)
115
+
116
+ const domain: Domain = await domainRepository.findOne({
117
+ where: { name: 'SYSTEM' }
118
+ })
119
+
120
+ const repository = getRepository(CommonCode)
121
+
122
+ SEED_COMMON_CODES.reverse().forEach(async commonCode => {
123
+ let record = await repository.findOne({ where: { name: commonCode.name, domain: { id: domain.id } } })
124
+ record && (await repository.remove(record))
125
+ })
126
+ }
127
+ }
@@ -0,0 +1,9 @@
1
+ const glob = require('glob')
2
+ const path = require('path')
3
+
4
+ export var migrations = []
5
+
6
+ glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
7
+ if (file.indexOf('index.js') !== -1) return
8
+ migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
9
+ })
@@ -0,0 +1,26 @@
1
+ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
2
+ /*
3
+ * can add global public routes to application (auth not required, tenancy not required)
4
+ *
5
+ * ex) routes.get('/path', async(context, next) => {})
6
+ * ex) routes.post('/path', async(context, next) => {})
7
+ */
8
+ })
9
+
10
+ process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
11
+ /*
12
+ * can add global private routes to application (auth required, tenancy not required)
13
+ */
14
+ })
15
+
16
+ process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
17
+ /*
18
+ * can add domain public routes to application (auth not required, tenancy required)
19
+ */
20
+ })
21
+
22
+ process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
23
+ /*
24
+ * can add domain private routes to application (auth required, tenancy required)
25
+ */
26
+ })
@@ -0,0 +1,42 @@
1
+ import { ObjectType, Field, ID, registerEnumType } from 'type-graphql'
2
+
3
+ export enum OrgMemberTargetType {
4
+ Employee = 'Employee',
5
+ Department = 'Department',
6
+ Role = 'Role',
7
+ Myself = 'Myself',
8
+ MyDepartment = 'MyDepartment',
9
+ MySupervisor = 'MySupervisor'
10
+ }
11
+
12
+ registerEnumType(OrgMemberTargetType, {
13
+ name: 'OrgMemberTargetType',
14
+ description: 'type enumeration of a approval line item'
15
+ })
16
+
17
+ @ObjectType()
18
+ export class OrgMemberTarget {
19
+ @Field(() => ID, { description: 'Field id' })
20
+ id?: string
21
+
22
+ @Field({ nullable: true, description: 'Field name' })
23
+ name?: string
24
+
25
+ @Field({ nullable: true, description: 'Field description' })
26
+ description?: string
27
+
28
+ @Field({ nullable: true })
29
+ controlNo?: string
30
+ }
31
+
32
+ @ObjectType({ description: 'Entity for approval line item' })
33
+ export class ApprovalLineItem {
34
+ @Field({ nullable: true })
35
+ type?: OrgMemberTargetType
36
+
37
+ @Field(type => String, { nullable: true })
38
+ value?: string
39
+
40
+ @Field(type => OrgMemberTarget, { nullable: true })
41
+ approver?: OrgMemberTarget
42
+ }