Files
zkxw/web-admin/src/utils/production-complete-work-order-gate.test.ts
T
2026-09-16 10:27:24 +08:00

151 lines
4.1 KiB
TypeScript

import { describe, it } from 'node:test'
import assert from 'node:assert/strict'
import {
classifyTasksForCompleteWorkOrderGate,
findTaskStepGateIssue,
needsProductionReceptionGate
} from './production-complete-work-order-gate-logic'
describe('classifyTasksForCompleteWorkOrderGate', () => {
it('no_tasks when list empty', () => {
assert.deepEqual(classifyTasksForCompleteWorkOrderGate([]), { kind: 'no_tasks' })
})
it('all_done when only completed or voided tasks remain', () => {
assert.deepEqual(
classifyTasksForCompleteWorkOrderGate([
{ id: '1', taskStatus: 'ywc' },
{ id: '2', taskStatus: 'yzf' }
]),
{ kind: 'all_done' }
)
})
it('check_incomplete returns unfinished tasks only', () => {
const decision = classifyTasksForCompleteWorkOrderGate([
{ id: '1', taskStatus: 'ywc' },
{ id: '2', taskStatus: 'dpz' },
{ id: '3', taskStatus: 'jxz' },
{ id: '4', taskStatus: 'yzf' }
])
assert.equal(decision.kind, 'check_incomplete')
if (decision.kind === 'check_incomplete') {
assert.deepEqual(
decision.incomplete.map((t) => t.id),
['2', '3']
)
}
})
})
describe('needsProductionReceptionGate', () => {
it('true for inbound cell_storage and research_donation', () => {
assert.equal(
needsProductionReceptionGate({
workOrderType: 'inbound',
receptionSource: 'cell_storage'
} as any),
true
)
assert.equal(
needsProductionReceptionGate({
workOrderType: 'inbound',
receptionSource: 'research_donation'
} as any),
true
)
// 缺省 workOrderType 视为入库
assert.equal(needsProductionReceptionGate({ receptionSource: 'cell_storage' } as any), true)
})
it('false for outbound/temporary even if receptionSource looks inbound', () => {
assert.equal(needsProductionReceptionGate({ receptionSource: 'outbound' } as any), false)
assert.equal(needsProductionReceptionGate({} as any), false)
// 扩增/传代临时工单:DB 默认 reception_source=cell_storage,且常无 sampleCode
assert.equal(
needsProductionReceptionGate({
workOrderType: 'temporary',
receptionSource: 'cell_storage',
sampleCode: ''
} as any),
false
)
assert.equal(
needsProductionReceptionGate({
workOrderType: 'outbound',
receptionSource: 'cell_storage'
} as any),
false
)
})
})
describe('findTaskStepGateIssue', () => {
it('requires assignee', () => {
const issue = findTaskStepGateIssue({
steps: [{ id: 's1', processName: '分离', assigneeUserIds: [], plannedStartTime: '2026-01-01' }]
})
assert.ok(issue)
assert.match(issue!.message, /负责人/)
assert.equal(issue!.stepId, 's1')
})
it('requires planned start time', () => {
const issue = findTaskStepGateIssue({
steps: [{ id: 's1', processName: '分离', assigneeUserIds: ['u1'], plannedStartTime: '' }]
})
assert.ok(issue)
assert.match(issue!.message, /计划开始时间/)
})
it('requires barcode on existing output rows', () => {
const issue = findTaskStepGateIssue({
steps: [
{
id: 's1',
processName: '分离',
assigneeUserIds: ['u1'],
plannedStartTime: '2026-01-01',
outputs: [{ outputName: '细胞袋', outputBarcode: '' }]
}
]
})
assert.ok(issue)
assert.match(issue!.message, /条码/)
})
it('allows empty outputs', () => {
assert.equal(
findTaskStepGateIssue({
steps: [
{
id: 's1',
processName: '分离',
assigneeUserIds: ['u1'],
plannedStartTime: '2026-01-01',
outputs: []
}
]
}),
null
)
})
it('passes when all filled', () => {
assert.equal(
findTaskStepGateIssue({
steps: [
{
id: 's1',
processName: '分离',
assigneeUserIds: ['u1'],
plannedStartTime: '2026-01-01',
outputs: [{ outputName: '细胞袋', outputBarcode: 'BC-1' }]
}
]
}),
null
)
})
})