@things-factory/organization 9.1.19 → 9.2.13
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.
- package/dist-client/pages/department/department-list-page.js +1 -1
- package/dist-client/pages/department/department-list-page.js.map +1 -1
- package/dist-client/pages/employee/employee-list-page.js +0 -1
- package/dist-client/pages/employee/employee-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/employee/employee-mutation.js +1 -1
- package/dist-server/service/employee/employee-mutation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/spec/unit/approval-line.spec.ts +329 -0
- package/spec/unit/department.spec.ts +253 -0
- package/spec/unit/employee.spec.ts +271 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/organization",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.2.13",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"@operato/graphql": "^9.0.0",
|
|
34
34
|
"@operato/p13n": "^9.0.0",
|
|
35
35
|
"@operato/shell": "^9.0.0",
|
|
36
|
-
"@things-factory/auth-base": "^9.
|
|
37
|
-
"@things-factory/code-ui": "^9.
|
|
38
|
-
"@things-factory/contact": "^9.
|
|
39
|
-
"@things-factory/shell": "^9.
|
|
36
|
+
"@things-factory/auth-base": "^9.2.13",
|
|
37
|
+
"@things-factory/code-ui": "^9.2.13",
|
|
38
|
+
"@things-factory/contact": "^9.2.13",
|
|
39
|
+
"@things-factory/shell": "^9.2.13"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "d65748803a86a1fb6c9810ea4f93519c6f44f6d5"
|
|
42
42
|
}
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ApprovalLine Unit Tests
|
|
3
|
+
* 결재라인 엔티티 단위 테스트
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TestDatabase } from '../../../../test/test-database'
|
|
7
|
+
import { withTestTransaction } from '../../../../test/test-context'
|
|
8
|
+
import {
|
|
9
|
+
domainFactory,
|
|
10
|
+
userFactory,
|
|
11
|
+
roleFactory,
|
|
12
|
+
employeeFactory,
|
|
13
|
+
approvalLineFactory
|
|
14
|
+
} from '../../../../test/factories'
|
|
15
|
+
import { ApprovalLineOwnerType } from '../../../../test/entities/schemas'
|
|
16
|
+
|
|
17
|
+
describe('ApprovalLine Entity Tests', () => {
|
|
18
|
+
let testDb: TestDatabase
|
|
19
|
+
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
testDb = TestDatabase.getInstance()
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
describe('ApprovalLine 생성', () => {
|
|
25
|
+
it('ApprovalLine이 올바르게 생성되어야 한다', async () => {
|
|
26
|
+
await withTestTransaction(async (context) => {
|
|
27
|
+
const { tx, domain } = context.state
|
|
28
|
+
|
|
29
|
+
// When
|
|
30
|
+
const approvalLine = await approvalLineFactory.createWithDomain(
|
|
31
|
+
{
|
|
32
|
+
name: 'Standard Approval',
|
|
33
|
+
description: 'Standard approval process',
|
|
34
|
+
ownerType: ApprovalLineOwnerType.Common
|
|
35
|
+
},
|
|
36
|
+
domain,
|
|
37
|
+
tx
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
// Then
|
|
41
|
+
expect(approvalLine).toBeDefined()
|
|
42
|
+
expect(approvalLine.id).toBeDefined()
|
|
43
|
+
expect(approvalLine.name).toBe('Standard Approval')
|
|
44
|
+
expect(approvalLine.description).toBe('Standard approval process')
|
|
45
|
+
expect(approvalLine.ownerType).toBe(ApprovalLineOwnerType.Common)
|
|
46
|
+
expect(approvalLine.domain?.id).toBe(domain.id)
|
|
47
|
+
})
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('Employee 소유의 ApprovalLine이 생성될 수 있어야 한다', async () => {
|
|
51
|
+
await withTestTransaction(async (context) => {
|
|
52
|
+
const { tx, domain } = context.state
|
|
53
|
+
|
|
54
|
+
// Given
|
|
55
|
+
const employee = await employeeFactory.createWithDomain({}, domain, tx)
|
|
56
|
+
|
|
57
|
+
// When
|
|
58
|
+
const approvalLine = await approvalLineFactory.createForEmployee(
|
|
59
|
+
{ name: 'My Approval Line' },
|
|
60
|
+
employee,
|
|
61
|
+
tx
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
// Then
|
|
65
|
+
expect(approvalLine.ownerType).toBe(ApprovalLineOwnerType.Employee)
|
|
66
|
+
expect(approvalLine.ownerValue).toBe(employee.id)
|
|
67
|
+
expect(approvalLine.ownerEmployee?.id).toBe(employee.id)
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
describe('ApprovalLine Model (결재 단계)', () => {
|
|
73
|
+
it('Role 타입 결재 아이템이 생성되어야 한다', async () => {
|
|
74
|
+
await withTestTransaction(async (context) => {
|
|
75
|
+
const { tx, domain } = context.state
|
|
76
|
+
|
|
77
|
+
// Given
|
|
78
|
+
const role = await roleFactory.create({ name: 'Approver Role', domain }, tx)
|
|
79
|
+
|
|
80
|
+
// When
|
|
81
|
+
const item = approvalLineFactory.createRoleApprovalItem(role)
|
|
82
|
+
|
|
83
|
+
// Then
|
|
84
|
+
expect(item.type).toBe('Role')
|
|
85
|
+
expect(item.value).toBe(role.id)
|
|
86
|
+
expect(item.approver?.id).toBe(role.id)
|
|
87
|
+
expect(item.approver?.name).toBe('Approver Role')
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('Employee 타입 결재 아이템이 생성되어야 한다', async () => {
|
|
92
|
+
await withTestTransaction(async (context) => {
|
|
93
|
+
const { tx, domain } = context.state
|
|
94
|
+
|
|
95
|
+
// Given
|
|
96
|
+
const employee = await employeeFactory.createWithDomain(
|
|
97
|
+
{ name: 'Approver Employee' },
|
|
98
|
+
domain,
|
|
99
|
+
tx
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
// When
|
|
103
|
+
const item = approvalLineFactory.createEmployeeApprovalItem(employee)
|
|
104
|
+
|
|
105
|
+
// Then
|
|
106
|
+
expect(item.type).toBe('Employee')
|
|
107
|
+
expect(item.value).toBe(employee.id)
|
|
108
|
+
expect(item.approver?.id).toBe(employee.id)
|
|
109
|
+
expect(item.approver?.name).toBe('Approver Employee')
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('Supervisor 타입 결재 아이템이 생성되어야 한다', async () => {
|
|
114
|
+
// When
|
|
115
|
+
const item = approvalLineFactory.createSupervisorApprovalItem()
|
|
116
|
+
|
|
117
|
+
// Then
|
|
118
|
+
expect(item.type).toBe('Supervisor')
|
|
119
|
+
expect(item.value).toBeUndefined()
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('DepartmentManager 타입 결재 아이템이 생성되어야 한다', async () => {
|
|
123
|
+
// When
|
|
124
|
+
const item = approvalLineFactory.createDepartmentManagerApprovalItem()
|
|
125
|
+
|
|
126
|
+
// Then
|
|
127
|
+
expect(item.type).toBe('DepartmentManager')
|
|
128
|
+
expect(item.value).toBeUndefined()
|
|
129
|
+
})
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
describe('단일 레벨 결재라인', () => {
|
|
133
|
+
it('Role 기반 단일 레벨 결재라인이 생성되어야 한다', async () => {
|
|
134
|
+
await withTestTransaction(async (context) => {
|
|
135
|
+
const { tx, domain } = context.state
|
|
136
|
+
|
|
137
|
+
// Given
|
|
138
|
+
const role = await roleFactory.create({ name: 'Approver', domain }, tx)
|
|
139
|
+
|
|
140
|
+
// When
|
|
141
|
+
const approvalLine = await approvalLineFactory.createSingleRoleApprovalLine(
|
|
142
|
+
role,
|
|
143
|
+
domain,
|
|
144
|
+
tx
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
// Then
|
|
148
|
+
expect(approvalLine.model).toBeDefined()
|
|
149
|
+
expect(approvalLine.model?.length).toBe(1)
|
|
150
|
+
expect(approvalLine.model?.[0].type).toBe('Role')
|
|
151
|
+
expect(approvalLine.model?.[0].approver?.id).toBe(role.id)
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
describe('다중 레벨 결재라인', () => {
|
|
157
|
+
it('여러 단계의 결재라인이 생성되어야 한다', async () => {
|
|
158
|
+
await withTestTransaction(async (context) => {
|
|
159
|
+
const { tx, domain } = context.state
|
|
160
|
+
|
|
161
|
+
// Given
|
|
162
|
+
const teamLeadRole = await roleFactory.create({ name: 'Team Lead', domain }, tx)
|
|
163
|
+
const managerRole = await roleFactory.create({ name: 'Manager', domain }, tx)
|
|
164
|
+
const directorRole = await roleFactory.create({ name: 'Director', domain }, tx)
|
|
165
|
+
|
|
166
|
+
const items = [
|
|
167
|
+
approvalLineFactory.createRoleApprovalItem(teamLeadRole),
|
|
168
|
+
approvalLineFactory.createRoleApprovalItem(managerRole),
|
|
169
|
+
approvalLineFactory.createRoleApprovalItem(directorRole)
|
|
170
|
+
]
|
|
171
|
+
|
|
172
|
+
// When
|
|
173
|
+
const approvalLine = await approvalLineFactory.createMultiLevelApprovalLine(
|
|
174
|
+
items,
|
|
175
|
+
domain,
|
|
176
|
+
tx
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
// Then
|
|
180
|
+
expect(approvalLine.model?.length).toBe(3)
|
|
181
|
+
expect(approvalLine.model?.[0].approver?.name).toBe('Team Lead')
|
|
182
|
+
expect(approvalLine.model?.[1].approver?.name).toBe('Manager')
|
|
183
|
+
expect(approvalLine.model?.[2].approver?.name).toBe('Director')
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
it('표준 2단계 결재라인이 생성되어야 한다', async () => {
|
|
188
|
+
await withTestTransaction(async (context) => {
|
|
189
|
+
const { tx, domain } = context.state
|
|
190
|
+
|
|
191
|
+
// When
|
|
192
|
+
const { approvalLine, teamLeadRole, managerRole } =
|
|
193
|
+
await approvalLineFactory.createStandardApprovalLine(domain, tx)
|
|
194
|
+
|
|
195
|
+
// Then
|
|
196
|
+
expect(approvalLine.name).toBe('Standard 2-Level Approval')
|
|
197
|
+
expect(approvalLine.model?.length).toBe(2)
|
|
198
|
+
expect(approvalLine.model?.[0].approver?.id).toBe(teamLeadRole.id)
|
|
199
|
+
expect(approvalLine.model?.[1].approver?.id).toBe(managerRole.id)
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
it('혼합 타입 결재라인이 생성되어야 한다 (Role + Employee)', async () => {
|
|
204
|
+
await withTestTransaction(async (context) => {
|
|
205
|
+
const { tx, domain } = context.state
|
|
206
|
+
|
|
207
|
+
// Given
|
|
208
|
+
const role = await roleFactory.create({ name: 'Team Lead', domain }, tx)
|
|
209
|
+
const employee = await employeeFactory.createWithDomain(
|
|
210
|
+
{ name: 'Final Approver' },
|
|
211
|
+
domain,
|
|
212
|
+
tx
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
const items = [
|
|
216
|
+
approvalLineFactory.createRoleApprovalItem(role),
|
|
217
|
+
approvalLineFactory.createEmployeeApprovalItem(employee)
|
|
218
|
+
]
|
|
219
|
+
|
|
220
|
+
// When
|
|
221
|
+
const approvalLine = await approvalLineFactory.createMultiLevelApprovalLine(
|
|
222
|
+
items,
|
|
223
|
+
domain,
|
|
224
|
+
tx
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
// Then
|
|
228
|
+
expect(approvalLine.model?.length).toBe(2)
|
|
229
|
+
expect(approvalLine.model?.[0].type).toBe('Role')
|
|
230
|
+
expect(approvalLine.model?.[1].type).toBe('Employee')
|
|
231
|
+
})
|
|
232
|
+
})
|
|
233
|
+
|
|
234
|
+
it('동적 타입 결재라인이 생성되어야 한다 (Supervisor + DepartmentManager)', async () => {
|
|
235
|
+
await withTestTransaction(async (context) => {
|
|
236
|
+
const { tx, domain } = context.state
|
|
237
|
+
|
|
238
|
+
// Given
|
|
239
|
+
const items = [
|
|
240
|
+
approvalLineFactory.createSupervisorApprovalItem(),
|
|
241
|
+
approvalLineFactory.createDepartmentManagerApprovalItem()
|
|
242
|
+
]
|
|
243
|
+
|
|
244
|
+
// When
|
|
245
|
+
const approvalLine = await approvalLineFactory.createMultiLevelApprovalLine(
|
|
246
|
+
items,
|
|
247
|
+
domain,
|
|
248
|
+
tx
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
// Then
|
|
252
|
+
expect(approvalLine.model?.length).toBe(2)
|
|
253
|
+
expect(approvalLine.model?.[0].type).toBe('Supervisor')
|
|
254
|
+
expect(approvalLine.model?.[1].type).toBe('DepartmentManager')
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
describe('ApprovalLine 조회', () => {
|
|
260
|
+
it('Domain으로 ApprovalLine을 조회할 수 있어야 한다', async () => {
|
|
261
|
+
await withTestTransaction(async (context) => {
|
|
262
|
+
const { tx, domain } = context.state
|
|
263
|
+
|
|
264
|
+
// Given
|
|
265
|
+
await approvalLineFactory.createWithDomain({ name: 'Line A' }, domain, tx)
|
|
266
|
+
await approvalLineFactory.createWithDomain({ name: 'Line B' }, domain, tx)
|
|
267
|
+
|
|
268
|
+
// When
|
|
269
|
+
const approvalLines = await tx.getRepository('ApprovalLine').find({
|
|
270
|
+
where: { domain: { id: domain.id } }
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
// Then
|
|
274
|
+
expect(approvalLines.length).toBe(2)
|
|
275
|
+
})
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
it('Common 타입 ApprovalLine만 조회할 수 있어야 한다', async () => {
|
|
279
|
+
await withTestTransaction(async (context) => {
|
|
280
|
+
const { tx, domain } = context.state
|
|
281
|
+
|
|
282
|
+
// Given
|
|
283
|
+
await approvalLineFactory.createWithDomain(
|
|
284
|
+
{ ownerType: ApprovalLineOwnerType.Common },
|
|
285
|
+
domain,
|
|
286
|
+
tx
|
|
287
|
+
)
|
|
288
|
+
const employee = await employeeFactory.createWithDomain({}, domain, tx)
|
|
289
|
+
await approvalLineFactory.createForEmployee({}, employee, tx)
|
|
290
|
+
|
|
291
|
+
// When
|
|
292
|
+
const commonLines = await tx.getRepository('ApprovalLine').find({
|
|
293
|
+
where: {
|
|
294
|
+
domain: { id: domain.id },
|
|
295
|
+
ownerType: ApprovalLineOwnerType.Common
|
|
296
|
+
}
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
// Then
|
|
300
|
+
expect(commonLines.length).toBe(1)
|
|
301
|
+
expect(commonLines[0].ownerType).toBe(ApprovalLineOwnerType.Common)
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('특정 Employee의 ApprovalLine만 조회할 수 있어야 한다', async () => {
|
|
306
|
+
await withTestTransaction(async (context) => {
|
|
307
|
+
const { tx, domain } = context.state
|
|
308
|
+
|
|
309
|
+
// Given
|
|
310
|
+
const employee1 = await employeeFactory.createWithDomain({ name: 'Emp 1' }, domain, tx)
|
|
311
|
+
const employee2 = await employeeFactory.createWithDomain({ name: 'Emp 2' }, domain, tx)
|
|
312
|
+
|
|
313
|
+
await approvalLineFactory.createForEmployee({ name: 'Line 1' }, employee1, tx)
|
|
314
|
+
await approvalLineFactory.createForEmployee({ name: 'Line 2' }, employee2, tx)
|
|
315
|
+
|
|
316
|
+
// When
|
|
317
|
+
const employee1Lines = await tx.getRepository('ApprovalLine').find({
|
|
318
|
+
where: {
|
|
319
|
+
domain: { id: domain.id },
|
|
320
|
+
ownerEmployee: { id: employee1.id }
|
|
321
|
+
}
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
// Then
|
|
325
|
+
expect(employee1Lines.length).toBe(1)
|
|
326
|
+
})
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
})
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Department Unit Tests
|
|
3
|
+
* 부서 엔티티 단위 테스트
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { TestDatabase } from '../../../../test/test-database'
|
|
7
|
+
import { withTestTransaction } from '../../../../test/test-context'
|
|
8
|
+
import {
|
|
9
|
+
domainFactory,
|
|
10
|
+
employeeFactory,
|
|
11
|
+
departmentFactory
|
|
12
|
+
} from '../../../../test/factories'
|
|
13
|
+
|
|
14
|
+
describe('Department Entity Tests', () => {
|
|
15
|
+
let testDb: TestDatabase
|
|
16
|
+
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
testDb = TestDatabase.getInstance()
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
describe('Department 생성', () => {
|
|
22
|
+
it('Department가 올바르게 생성되어야 한다', async () => {
|
|
23
|
+
await withTestTransaction(async (context) => {
|
|
24
|
+
const { tx, domain } = context.state
|
|
25
|
+
|
|
26
|
+
// When
|
|
27
|
+
const department = await departmentFactory.createWithDomain(
|
|
28
|
+
{
|
|
29
|
+
controlNo: 'DEPT-001',
|
|
30
|
+
name: 'Engineering',
|
|
31
|
+
description: 'Engineering Department'
|
|
32
|
+
},
|
|
33
|
+
domain,
|
|
34
|
+
tx
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
// Then
|
|
38
|
+
expect(department).toBeDefined()
|
|
39
|
+
expect(department.id).toBeDefined()
|
|
40
|
+
expect(department.controlNo).toBe('DEPT-001')
|
|
41
|
+
expect(department.name).toBe('Engineering')
|
|
42
|
+
expect(department.description).toBe('Engineering Department')
|
|
43
|
+
expect(department.domain?.id).toBe(domain.id)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('controlNo는 필수 필드여야 한다', async () => {
|
|
48
|
+
await withTestTransaction(async (context) => {
|
|
49
|
+
const { tx, domain } = context.state
|
|
50
|
+
|
|
51
|
+
// When
|
|
52
|
+
const department = await departmentFactory.createWithDomain(
|
|
53
|
+
{ controlNo: 'REQUIRED-DEPT-001' },
|
|
54
|
+
domain,
|
|
55
|
+
tx
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
// Then
|
|
59
|
+
expect(department.controlNo).toBe('REQUIRED-DEPT-001')
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('active 상태가 관리되어야 한다', async () => {
|
|
64
|
+
await withTestTransaction(async (context) => {
|
|
65
|
+
const { tx, domain } = context.state
|
|
66
|
+
|
|
67
|
+
// When: active=true
|
|
68
|
+
const activeDept = await departmentFactory.createWithDomain(
|
|
69
|
+
{ active: true },
|
|
70
|
+
domain,
|
|
71
|
+
tx
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// When: active=false
|
|
75
|
+
const inactiveDept = await departmentFactory.createWithDomain(
|
|
76
|
+
{ active: false },
|
|
77
|
+
domain,
|
|
78
|
+
tx
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
// Then
|
|
82
|
+
expect(activeDept.active).toBe(true)
|
|
83
|
+
expect(inactiveDept.active).toBe(false)
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
describe('Department 계층 구조', () => {
|
|
89
|
+
it('Parent-Child 관계가 설정되어야 한다', async () => {
|
|
90
|
+
await withTestTransaction(async (context) => {
|
|
91
|
+
const { tx, domain } = context.state
|
|
92
|
+
|
|
93
|
+
// Given
|
|
94
|
+
const parent = await departmentFactory.createWithDomain(
|
|
95
|
+
{ name: 'Parent Department' },
|
|
96
|
+
domain,
|
|
97
|
+
tx
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
// When
|
|
101
|
+
const child = await departmentFactory.createChildDepartment(
|
|
102
|
+
{ name: 'Child Department' },
|
|
103
|
+
parent,
|
|
104
|
+
tx
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
// Then
|
|
108
|
+
expect(child.parent?.id).toBe(parent.id)
|
|
109
|
+
})
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
it('다단계 계층 구조가 생성되어야 한다', async () => {
|
|
113
|
+
await withTestTransaction(async (context) => {
|
|
114
|
+
const { tx, domain } = context.state
|
|
115
|
+
|
|
116
|
+
// When
|
|
117
|
+
const { root, child, grandchild } = await departmentFactory.createHierarchy(domain, tx)
|
|
118
|
+
|
|
119
|
+
// Then
|
|
120
|
+
expect(root.parent).toBeUndefined()
|
|
121
|
+
expect(child.parent?.id).toBe(root.id)
|
|
122
|
+
expect(grandchild.parent?.id).toBe(child.id)
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('같은 parent 아래 여러 child가 있을 수 있어야 한다', async () => {
|
|
127
|
+
await withTestTransaction(async (context) => {
|
|
128
|
+
const { tx, domain } = context.state
|
|
129
|
+
|
|
130
|
+
// Given
|
|
131
|
+
const parent = await departmentFactory.createWithDomain(
|
|
132
|
+
{ name: 'Parent' },
|
|
133
|
+
domain,
|
|
134
|
+
tx
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
// When
|
|
138
|
+
const child1 = await departmentFactory.createChildDepartment(
|
|
139
|
+
{ name: 'Child 1' },
|
|
140
|
+
parent,
|
|
141
|
+
tx
|
|
142
|
+
)
|
|
143
|
+
const child2 = await departmentFactory.createChildDepartment(
|
|
144
|
+
{ name: 'Child 2' },
|
|
145
|
+
parent,
|
|
146
|
+
tx
|
|
147
|
+
)
|
|
148
|
+
const child3 = await departmentFactory.createChildDepartment(
|
|
149
|
+
{ name: 'Child 3' },
|
|
150
|
+
parent,
|
|
151
|
+
tx
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
// Then
|
|
155
|
+
expect(child1.parent?.id).toBe(parent.id)
|
|
156
|
+
expect(child2.parent?.id).toBe(parent.id)
|
|
157
|
+
expect(child3.parent?.id).toBe(parent.id)
|
|
158
|
+
})
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
describe('Department-Manager 관계', () => {
|
|
163
|
+
it('Department에 Manager를 설정할 수 있어야 한다', async () => {
|
|
164
|
+
await withTestTransaction(async (context) => {
|
|
165
|
+
const { tx, domain } = context.state
|
|
166
|
+
|
|
167
|
+
// Given
|
|
168
|
+
const department = await departmentFactory.createWithDomain({}, domain, tx)
|
|
169
|
+
const manager = await employeeFactory.createManager({ department }, domain, tx)
|
|
170
|
+
|
|
171
|
+
// When
|
|
172
|
+
department.manager = manager
|
|
173
|
+
const updated = await tx.save('Department', department)
|
|
174
|
+
|
|
175
|
+
// Then
|
|
176
|
+
expect(updated.manager?.id).toBe(manager.id)
|
|
177
|
+
})
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it('Manager 없이도 Department가 존재할 수 있어야 한다', async () => {
|
|
181
|
+
await withTestTransaction(async (context) => {
|
|
182
|
+
const { tx, domain } = context.state
|
|
183
|
+
|
|
184
|
+
// When
|
|
185
|
+
const department = await departmentFactory.createWithDomain({}, domain, tx)
|
|
186
|
+
|
|
187
|
+
// Then
|
|
188
|
+
expect(department.manager).toBeUndefined()
|
|
189
|
+
})
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
describe('Department 조회', () => {
|
|
194
|
+
it('Domain으로 부서를 조회할 수 있어야 한다', async () => {
|
|
195
|
+
await withTestTransaction(async (context) => {
|
|
196
|
+
const { tx, domain } = context.state
|
|
197
|
+
|
|
198
|
+
// Given
|
|
199
|
+
await departmentFactory.createWithDomain({ name: 'Dept A' }, domain, tx)
|
|
200
|
+
await departmentFactory.createWithDomain({ name: 'Dept B' }, domain, tx)
|
|
201
|
+
await departmentFactory.createWithDomain({ name: 'Dept C' }, domain, tx)
|
|
202
|
+
|
|
203
|
+
// When
|
|
204
|
+
const departments = await tx.getRepository('Department').find({
|
|
205
|
+
where: { domain: { id: domain.id } }
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
// Then
|
|
209
|
+
expect(departments.length).toBe(3)
|
|
210
|
+
})
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
it('controlNo로 부서를 조회할 수 있어야 한다', async () => {
|
|
214
|
+
await withTestTransaction(async (context) => {
|
|
215
|
+
const { tx, domain } = context.state
|
|
216
|
+
|
|
217
|
+
// Given
|
|
218
|
+
await departmentFactory.createWithDomain(
|
|
219
|
+
{ controlNo: 'UNIQUE-DEPT-001' },
|
|
220
|
+
domain,
|
|
221
|
+
tx
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
// When
|
|
225
|
+
const department = await tx.getRepository('Department').findOne({
|
|
226
|
+
where: { domain: { id: domain.id }, controlNo: 'UNIQUE-DEPT-001' }
|
|
227
|
+
})
|
|
228
|
+
|
|
229
|
+
// Then
|
|
230
|
+
expect(department).toBeDefined()
|
|
231
|
+
expect(department?.controlNo).toBe('UNIQUE-DEPT-001')
|
|
232
|
+
})
|
|
233
|
+
})
|
|
234
|
+
})
|
|
235
|
+
|
|
236
|
+
describe('Department 속성', () => {
|
|
237
|
+
it('extension(내선번호)이 저장되어야 한다', async () => {
|
|
238
|
+
await withTestTransaction(async (context) => {
|
|
239
|
+
const { tx, domain } = context.state
|
|
240
|
+
|
|
241
|
+
// When
|
|
242
|
+
const department = await departmentFactory.createWithDomain(
|
|
243
|
+
{ extension: '1234' },
|
|
244
|
+
domain,
|
|
245
|
+
tx
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
// Then
|
|
249
|
+
expect(department.extension).toBe('1234')
|
|
250
|
+
})
|
|
251
|
+
})
|
|
252
|
+
})
|
|
253
|
+
})
|