@things-factory/dataset 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/tsconfig.tsbuildinfo +1 -1
- package/dist-server/activities/activity-data-review.js +5 -2
- package/dist-server/activities/activity-data-review.js.map +1 -1
- package/dist-server/activities/activity-ooc-review.js +4 -1
- package/dist-server/activities/activity-ooc-review.js.map +1 -1
- package/dist-server/controllers/create-data-ooc.js +2 -1
- package/dist-server/controllers/create-data-ooc.js.map +1 -1
- package/dist-server/controllers/create-data-sample.js +2 -2
- package/dist-server/controllers/create-data-sample.js.map +1 -1
- package/dist-server/controllers/issue-data-collection-task.js +9 -5
- package/dist-server/controllers/issue-data-collection-task.js.map +1 -1
- package/dist-server/controllers/issue-ooc-resolve.js +11 -6
- package/dist-server/controllers/issue-ooc-resolve.js.map +1 -1
- package/dist-server/controllers/issue-ooc-review.js +9 -6
- package/dist-server/controllers/issue-ooc-review.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -13
- package/spec/integration/debug.spec.ts +42 -0
- package/spec/integration/ooc-lifecycle.spec.ts +484 -0
- package/spec/integration/ooc-workflow.spec.ts +276 -0
- package/spec/integration/simple.spec.ts +62 -0
- package/spec/unit/controllers/activity-callbacks.spec.ts +609 -0
- package/spec/unit/controllers/create-data-ooc.spec.ts +310 -0
- package/spec/unit/controllers/issue-ooc-resolve.spec.ts +431 -0
- package/spec/unit/controllers/issue-ooc-review.spec.ts +288 -0
- package/spec/unit/data-use-case.spec.ts +150 -0
- package/spec/unit/ooc-state-transition.spec.ts +233 -0
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* issue-ooc-resolve Controller Unit Tests
|
|
3
|
+
* OOC Resolve Activity 발행 컨트롤러 테스트
|
|
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
|
+
dataSetFactory,
|
|
13
|
+
dataOocFactory,
|
|
14
|
+
activityFactory,
|
|
15
|
+
activityInstanceFactory
|
|
16
|
+
} from '../../../../../test/factories'
|
|
17
|
+
import { DataOocStatus, ActivityInstanceStatus } from '../../../../../test/entities/schemas'
|
|
18
|
+
|
|
19
|
+
describe('issue-ooc-resolve Controller', () => {
|
|
20
|
+
let testDb: TestDatabase
|
|
21
|
+
|
|
22
|
+
beforeAll(async () => {
|
|
23
|
+
testDb = TestDatabase.getInstance()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
describe('OOC Resolve Activity 발행 조건', () => {
|
|
27
|
+
it('Activity가 존재하고 resolverRole이 있으면 Resolve Instance가 생성되어야 한다', async () => {
|
|
28
|
+
await withTestTransaction(async (context) => {
|
|
29
|
+
const { tx, domain } = context.state
|
|
30
|
+
|
|
31
|
+
// Given: OOC Resolve Activity와 resolverRole이 있는 DataSet
|
|
32
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
33
|
+
const resolverRole = await roleFactory.create({ name: 'Resolver', domain }, tx)
|
|
34
|
+
const dataSet = await dataSetFactory.createWithDomain(
|
|
35
|
+
{ resolverRole },
|
|
36
|
+
domain,
|
|
37
|
+
tx
|
|
38
|
+
)
|
|
39
|
+
const dataOoc = await dataOocFactory.createWithDataSetAndSample(
|
|
40
|
+
{
|
|
41
|
+
state: DataOocStatus.REVIEWED,
|
|
42
|
+
correctiveInstruction: 'Temperature 조절 필요'
|
|
43
|
+
},
|
|
44
|
+
dataSet,
|
|
45
|
+
undefined,
|
|
46
|
+
tx
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
// When: issueOocResolve 로직 시뮬레이션
|
|
50
|
+
const activityInstance = await activityInstanceFactory.createWithActivity(
|
|
51
|
+
{
|
|
52
|
+
name: `[OOC 조치] ${dataSet.name}`,
|
|
53
|
+
description: dataSet.description,
|
|
54
|
+
state: ActivityInstanceStatus.Issued,
|
|
55
|
+
dueAt: new Date(Date.now() + resolveActivity.standardTime * 1000),
|
|
56
|
+
input: {
|
|
57
|
+
dataOocId: dataOoc.id,
|
|
58
|
+
instruction: dataOoc.correctiveInstruction
|
|
59
|
+
},
|
|
60
|
+
assigneeRole: resolverRole,
|
|
61
|
+
threadsMin: 1,
|
|
62
|
+
threadsMax: 1,
|
|
63
|
+
approvalLine: dataSet.outlierApprovalLine || []
|
|
64
|
+
},
|
|
65
|
+
resolveActivity,
|
|
66
|
+
domain,
|
|
67
|
+
tx
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
// Then
|
|
71
|
+
expect(activityInstance).toBeDefined()
|
|
72
|
+
expect(activityInstance.name).toBe(`[OOC 조치] ${dataSet.name}`)
|
|
73
|
+
expect(activityInstance.input?.dataOocId).toBe(dataOoc.id)
|
|
74
|
+
expect(activityInstance.input?.instruction).toBe('Temperature 조절 필요')
|
|
75
|
+
expect(activityInstance.assigneeRole?.id).toBe(resolverRole.id)
|
|
76
|
+
expect(activityInstance.activity?.id).toBe(resolveActivity.id)
|
|
77
|
+
})
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
it('resolverRole이 없으면 Resolve Activity가 발행되지 않아야 한다', async () => {
|
|
81
|
+
await withTestTransaction(async (context) => {
|
|
82
|
+
const { tx, domain } = context.state
|
|
83
|
+
|
|
84
|
+
// Given: resolverRole이 없는 DataSet
|
|
85
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
86
|
+
const dataSet = await dataSetFactory.createWithDomain(
|
|
87
|
+
{ resolverRole: undefined, resolverRoleId: undefined },
|
|
88
|
+
domain,
|
|
89
|
+
tx
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
// When & Then: resolverRole 체크
|
|
93
|
+
const resolverRoleId = dataSet.resolverRoleId
|
|
94
|
+
expect(resolverRoleId).toBeFalsy()
|
|
95
|
+
|
|
96
|
+
// issueOocResolve 로직에서는 이 경우 console.error만 출력하고 리턴
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('OOC Resolve Activity가 설치되지 않으면 Resolve가 발행되지 않아야 한다', async () => {
|
|
101
|
+
await withTestTransaction(async (context) => {
|
|
102
|
+
const { tx, domain } = context.state
|
|
103
|
+
|
|
104
|
+
// Given: OOC Resolve Activity가 없는 상태
|
|
105
|
+
const { dataSet, resolverRole } = await dataSetFactory.createWithRoles({}, domain, tx)
|
|
106
|
+
|
|
107
|
+
// When: Activity 조회
|
|
108
|
+
const activity = await tx
|
|
109
|
+
.getRepository('Activity')
|
|
110
|
+
.findOne({ where: { domain: { id: domain.id }, name: 'OOC Resolve' } })
|
|
111
|
+
|
|
112
|
+
// Then: Activity가 없음
|
|
113
|
+
expect(activity).toBeNull()
|
|
114
|
+
// issueOocResolve 로직에서는 이 경우 console.error만 출력하고 리턴
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
describe('OOC Resolve Instance 속성', () => {
|
|
120
|
+
it('input에 dataOocId와 instruction이 포함되어야 한다', async () => {
|
|
121
|
+
await withTestTransaction(async (context) => {
|
|
122
|
+
const { tx, domain } = context.state
|
|
123
|
+
|
|
124
|
+
// Given
|
|
125
|
+
const { dataSet, resolverRole } = await dataSetFactory.createWithRoles({}, domain, tx)
|
|
126
|
+
const dataOoc = await dataOocFactory.createWithDataSetAndSample(
|
|
127
|
+
{
|
|
128
|
+
state: DataOocStatus.REVIEWED,
|
|
129
|
+
correctiveInstruction: 'Temperature를 20-80 범위로 조절하세요'
|
|
130
|
+
},
|
|
131
|
+
dataSet,
|
|
132
|
+
undefined,
|
|
133
|
+
tx
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
// When: issueOocResolve 입력 구성
|
|
137
|
+
const input = {
|
|
138
|
+
dataOocId: dataOoc.id,
|
|
139
|
+
instruction: dataOoc.correctiveInstruction
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Then
|
|
143
|
+
expect(input.dataOocId).toBe(dataOoc.id)
|
|
144
|
+
expect(input.instruction).toBe('Temperature를 20-80 범위로 조절하세요')
|
|
145
|
+
})
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('dueAt은 현재시간 + standardTime으로 계산되어야 한다 (Review와 다름)', async () => {
|
|
149
|
+
await withTestTransaction(async (context) => {
|
|
150
|
+
const { tx, domain } = context.state
|
|
151
|
+
|
|
152
|
+
// Given
|
|
153
|
+
const standardTime = 72 * 60 * 60 // 72시간
|
|
154
|
+
const resolveActivity = await activityFactory.createWithDomain(
|
|
155
|
+
{
|
|
156
|
+
name: 'OOC Resolve',
|
|
157
|
+
standardTime
|
|
158
|
+
},
|
|
159
|
+
domain,
|
|
160
|
+
tx
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
// When: dueAt 계산 (현재 시간 기준)
|
|
164
|
+
const now = Date.now()
|
|
165
|
+
const expectedDueAt = new Date(now + standardTime * 1000)
|
|
166
|
+
|
|
167
|
+
// Then: dueAt이 현재시간 + standardTime
|
|
168
|
+
// Review는 collectedAt 기준, Resolve는 현재시간 기준
|
|
169
|
+
expect(expectedDueAt.getTime()).toBeGreaterThan(now)
|
|
170
|
+
expect(expectedDueAt.getTime() - now).toBe(standardTime * 1000)
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
describe('outlierApprovalLine 적용', () => {
|
|
176
|
+
it('DataSet의 outlierApprovalLine이 Resolve Instance에 적용되어야 한다', async () => {
|
|
177
|
+
await withTestTransaction(async (context) => {
|
|
178
|
+
const { tx, domain } = context.state
|
|
179
|
+
|
|
180
|
+
// Given: outlierApprovalLine이 설정된 DataSet
|
|
181
|
+
const approverRole = await roleFactory.create({ name: 'Approver', domain }, tx)
|
|
182
|
+
const outlierApprovalLine = [
|
|
183
|
+
{
|
|
184
|
+
type: 'Role',
|
|
185
|
+
value: approverRole.id,
|
|
186
|
+
approver: { id: approverRole.id, name: approverRole.name }
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
const resolverRole = await roleFactory.create({ name: 'Resolver', domain }, tx)
|
|
191
|
+
const dataSet = await dataSetFactory.createWithDomain(
|
|
192
|
+
{
|
|
193
|
+
resolverRole,
|
|
194
|
+
outlierApprovalLine
|
|
195
|
+
},
|
|
196
|
+
domain,
|
|
197
|
+
tx
|
|
198
|
+
)
|
|
199
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
200
|
+
|
|
201
|
+
// When: Resolve Instance 생성
|
|
202
|
+
const activityInstance = await activityInstanceFactory.createWithActivity(
|
|
203
|
+
{
|
|
204
|
+
state: ActivityInstanceStatus.Issued,
|
|
205
|
+
assigneeRole: resolverRole,
|
|
206
|
+
approvalLine: dataSet.outlierApprovalLine
|
|
207
|
+
},
|
|
208
|
+
resolveActivity,
|
|
209
|
+
domain,
|
|
210
|
+
tx
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
// Then
|
|
214
|
+
expect(activityInstance.approvalLine).toBeDefined()
|
|
215
|
+
expect(activityInstance.approvalLine?.length).toBe(1)
|
|
216
|
+
expect(activityInstance.approvalLine?.[0].type).toBe('Role')
|
|
217
|
+
expect(activityInstance.approvalLine?.[0].approver?.id).toBe(approverRole.id)
|
|
218
|
+
})
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('outlierApprovalLine이 없으면 빈 배열 또는 undefined로 설정되어야 한다', async () => {
|
|
222
|
+
await withTestTransaction(async (context) => {
|
|
223
|
+
const { tx, domain } = context.state
|
|
224
|
+
|
|
225
|
+
// Given: outlierApprovalLine이 없는 DataSet
|
|
226
|
+
const { dataSet, resolverRole } = await dataSetFactory.createWithRoles(
|
|
227
|
+
{ outlierApprovalLine: undefined },
|
|
228
|
+
domain,
|
|
229
|
+
tx
|
|
230
|
+
)
|
|
231
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
232
|
+
|
|
233
|
+
// When: Resolve Instance 생성
|
|
234
|
+
const activityInstance = await activityInstanceFactory.createWithActivity(
|
|
235
|
+
{
|
|
236
|
+
state: ActivityInstanceStatus.Issued,
|
|
237
|
+
assigneeRole: resolverRole,
|
|
238
|
+
approvalLine: dataSet.outlierApprovalLine || []
|
|
239
|
+
},
|
|
240
|
+
resolveActivity,
|
|
241
|
+
domain,
|
|
242
|
+
tx
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
// Then
|
|
246
|
+
expect(activityInstance.approvalLine).toEqual([])
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('다중 레벨 결재라인이 올바르게 적용되어야 한다', async () => {
|
|
251
|
+
await withTestTransaction(async (context) => {
|
|
252
|
+
const { tx, domain } = context.state
|
|
253
|
+
|
|
254
|
+
// Given: 2단계 결재라인
|
|
255
|
+
const approverRole1 = await roleFactory.create({ name: 'Team Lead', domain }, tx)
|
|
256
|
+
const approverRole2 = await roleFactory.create({ name: 'Manager', domain }, tx)
|
|
257
|
+
const outlierApprovalLine = [
|
|
258
|
+
{ type: 'Role', value: approverRole1.id, approver: { id: approverRole1.id, name: approverRole1.name } },
|
|
259
|
+
{ type: 'Role', value: approverRole2.id, approver: { id: approverRole2.id, name: approverRole2.name } }
|
|
260
|
+
]
|
|
261
|
+
|
|
262
|
+
const resolverRole = await roleFactory.create({ name: 'Resolver', domain }, tx)
|
|
263
|
+
const dataSet = await dataSetFactory.createWithDomain(
|
|
264
|
+
{
|
|
265
|
+
resolverRole,
|
|
266
|
+
outlierApprovalLine
|
|
267
|
+
},
|
|
268
|
+
domain,
|
|
269
|
+
tx
|
|
270
|
+
)
|
|
271
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
272
|
+
|
|
273
|
+
// When
|
|
274
|
+
const activityInstance = await activityInstanceFactory.createWithActivity(
|
|
275
|
+
{
|
|
276
|
+
state: ActivityInstanceStatus.Issued,
|
|
277
|
+
assigneeRole: resolverRole,
|
|
278
|
+
approvalLine: dataSet.outlierApprovalLine
|
|
279
|
+
},
|
|
280
|
+
resolveActivity,
|
|
281
|
+
domain,
|
|
282
|
+
tx
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
// Then
|
|
286
|
+
expect(activityInstance.approvalLine?.length).toBe(2)
|
|
287
|
+
expect(activityInstance.approvalLine?.[0].approver?.id).toBe(approverRole1.id)
|
|
288
|
+
expect(activityInstance.approvalLine?.[1].approver?.id).toBe(approverRole2.id)
|
|
289
|
+
})
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('Employee 타입 결재라인도 지원되어야 한다', async () => {
|
|
293
|
+
await withTestTransaction(async (context) => {
|
|
294
|
+
const { tx, domain } = context.state
|
|
295
|
+
|
|
296
|
+
// Given: Employee 타입 결재라인
|
|
297
|
+
const approverUser = await userFactory.create({ name: 'Approver User' }, tx)
|
|
298
|
+
const outlierApprovalLine = [
|
|
299
|
+
{
|
|
300
|
+
type: 'Employee',
|
|
301
|
+
value: approverUser.id,
|
|
302
|
+
approver: { id: approverUser.id, name: approverUser.name }
|
|
303
|
+
}
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
const resolverRole = await roleFactory.create({ name: 'Resolver', domain }, tx)
|
|
307
|
+
const dataSet = await dataSetFactory.createWithDomain(
|
|
308
|
+
{
|
|
309
|
+
resolverRole,
|
|
310
|
+
outlierApprovalLine
|
|
311
|
+
},
|
|
312
|
+
domain,
|
|
313
|
+
tx
|
|
314
|
+
)
|
|
315
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
316
|
+
|
|
317
|
+
// When
|
|
318
|
+
const activityInstance = await activityInstanceFactory.createWithActivity(
|
|
319
|
+
{
|
|
320
|
+
state: ActivityInstanceStatus.Issued,
|
|
321
|
+
assigneeRole: resolverRole,
|
|
322
|
+
approvalLine: dataSet.outlierApprovalLine
|
|
323
|
+
},
|
|
324
|
+
resolveActivity,
|
|
325
|
+
domain,
|
|
326
|
+
tx
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
// Then
|
|
330
|
+
expect(activityInstance.approvalLine?.[0].type).toBe('Employee')
|
|
331
|
+
expect(activityInstance.approvalLine?.[0].approver?.id).toBe(approverUser.id)
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
describe('DataOoc과 ResolveActivityInstance 연결', () => {
|
|
337
|
+
it('DataOoc의 resolveActivityInstance 필드에 생성된 Instance가 저장되어야 한다', async () => {
|
|
338
|
+
await withTestTransaction(async (context) => {
|
|
339
|
+
const { tx, domain } = context.state
|
|
340
|
+
|
|
341
|
+
// Given
|
|
342
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
343
|
+
const { dataSet, resolverRole } = await dataSetFactory.createWithRoles({}, domain, tx)
|
|
344
|
+
let dataOoc = await dataOocFactory.createWithDataSetAndSample(
|
|
345
|
+
{
|
|
346
|
+
state: DataOocStatus.REVIEWED,
|
|
347
|
+
correctiveInstruction: 'Fix temperature'
|
|
348
|
+
},
|
|
349
|
+
dataSet,
|
|
350
|
+
undefined,
|
|
351
|
+
tx
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
// When: Resolve Instance 생성 및 DataOoc에 연결
|
|
355
|
+
const resolveInstance = await activityInstanceFactory.createWithActivity(
|
|
356
|
+
{
|
|
357
|
+
name: `[OOC 조치] ${dataSet.name}`,
|
|
358
|
+
state: ActivityInstanceStatus.Issued,
|
|
359
|
+
input: {
|
|
360
|
+
dataOocId: dataOoc.id,
|
|
361
|
+
instruction: dataOoc.correctiveInstruction
|
|
362
|
+
},
|
|
363
|
+
assigneeRole: resolverRole
|
|
364
|
+
},
|
|
365
|
+
resolveActivity,
|
|
366
|
+
domain,
|
|
367
|
+
tx
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
dataOoc.resolveActivityInstance = resolveInstance
|
|
371
|
+
dataOoc = await tx.save('DataOoc', dataOoc)
|
|
372
|
+
|
|
373
|
+
// Then
|
|
374
|
+
expect(dataOoc.resolveActivityInstance).toBeDefined()
|
|
375
|
+
expect(dataOoc.resolveActivityInstance?.id).toBe(resolveInstance.id)
|
|
376
|
+
})
|
|
377
|
+
})
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
describe('Review → Resolve 연계', () => {
|
|
381
|
+
it('Review 완료 후 Resolve가 자동으로 발행되는 플로우 테스트', async () => {
|
|
382
|
+
await withTestTransaction(async (context) => {
|
|
383
|
+
const { tx, domain, user } = context.state
|
|
384
|
+
|
|
385
|
+
// Given: Review 완료 상태의 DataOoc
|
|
386
|
+
const reviewActivity = await activityFactory.createOocReviewActivity(domain, tx)
|
|
387
|
+
const resolveActivity = await activityFactory.createOocResolveActivity(domain, tx)
|
|
388
|
+
const { dataSet, supervisoryRole, resolverRole } = await dataSetFactory.createWithRoles({}, domain, tx)
|
|
389
|
+
|
|
390
|
+
let dataOoc = await dataOocFactory.createWithDataSetAndSample(
|
|
391
|
+
{ state: DataOocStatus.ISSUED },
|
|
392
|
+
dataSet,
|
|
393
|
+
undefined,
|
|
394
|
+
tx
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
// Review 완료 시뮬레이션
|
|
398
|
+
dataOoc.state = DataOocStatus.REVIEWED
|
|
399
|
+
dataOoc.reviewedAt = new Date()
|
|
400
|
+
dataOoc.reviewer = user
|
|
401
|
+
dataOoc.correctiveInstruction = 'Temperature 조절 필요'
|
|
402
|
+
dataOoc = await tx.save('DataOoc', dataOoc)
|
|
403
|
+
|
|
404
|
+
// When: Resolve Activity 발행 (activity-ooc-review callback에서 호출됨)
|
|
405
|
+
const resolveInstance = await activityInstanceFactory.createWithActivity(
|
|
406
|
+
{
|
|
407
|
+
name: `[OOC 조치] ${dataSet.name}`,
|
|
408
|
+
state: ActivityInstanceStatus.Issued,
|
|
409
|
+
input: {
|
|
410
|
+
dataOocId: dataOoc.id,
|
|
411
|
+
instruction: dataOoc.correctiveInstruction
|
|
412
|
+
},
|
|
413
|
+
assigneeRole: resolverRole,
|
|
414
|
+
approvalLine: dataSet.outlierApprovalLine || []
|
|
415
|
+
},
|
|
416
|
+
resolveActivity,
|
|
417
|
+
domain,
|
|
418
|
+
tx
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
dataOoc.resolveActivityInstance = resolveInstance
|
|
422
|
+
dataOoc = await tx.save('DataOoc', dataOoc)
|
|
423
|
+
|
|
424
|
+
// Then: Review 완료 후 Resolve가 발행됨
|
|
425
|
+
expect(dataOoc.state).toBe(DataOocStatus.REVIEWED)
|
|
426
|
+
expect(dataOoc.resolveActivityInstance).toBeDefined()
|
|
427
|
+
expect(dataOoc.resolveActivityInstance?.input?.instruction).toBe('Temperature 조절 필요')
|
|
428
|
+
})
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
})
|