Files
zkxw/web-admin/src/utils/qc-company-task-group.test.ts
T
2026-09-03 17:12:38 +08:00

183 lines
5.8 KiB
TypeScript

import { describe, it } from 'node:test'
import assert from 'node:assert/strict'
import {
buildTaskListDisplayItems,
pickSharedRemarkAndAttachments,
companyGroupProgress,
uniqueAssigneeNames,
sortThirdPartyTasksByCompany,
allThirdPartyCardSubtitle,
thirdPartyCompanyDisplayName,
countDistinctThirdPartyCompanies
} from './qc-company-task-group'
type TestQcTask = {
id: string
taskType: string
taskNo?: string
itemCode?: string
itemName?: string
taskStatus?: string
workOrderId?: string
companyId?: string
companyName?: string
remark?: string
thirdPartyAttachments?: string
updateTime?: string
assigneeUserNames?: string
attachmentFiles?: Array<{ fileUrl: string; fileName?: string; fileType?: string }>
}
function task(partial: Partial<TestQcTask> & Pick<TestQcTask, 'id' | 'taskType'>): TestQcTask {
return {
taskNo: 'T1',
itemCode: 'I',
itemName: 'Item',
taskStatus: 'dzx',
workOrderId: 'wo1',
...partial
}
}
describe('buildTaskListDisplayItems', () => {
it('keeps lab tasks as single cards and merges all third-party into one card', () => {
const tasks = [
task({ id: 'l1', taskType: 'sysz', itemName: '无菌' }),
task({
id: 't1',
taskType: 'dsfjc',
companyId: 'c1',
companyName: '金域',
itemName: '乙肝'
}),
task({
id: 't2',
taskType: 'dsfjc',
companyId: 'c1',
companyName: '金域',
itemName: '丙肝'
}),
task({
id: 't3',
taskType: 'dsfjc',
companyId: 'c2',
companyName: '迪安',
itemName: 'HIV'
}),
task({ id: 't0', taskType: 'dsfjc', companyId: '', companyName: '', itemName: '孤儿' })
]
const items = buildTaskListDisplayItems(tasks)
assert.equal(items.length, 2)
assert.equal(items[0].kind, 'lab')
assert.equal(items[0].kind === 'lab' && items[0].task.id, 'l1')
assert.equal(items[1].kind, 'all-third')
if (items[1].kind === 'all-third') {
assert.equal(items[1].tasks.length, 4)
assert.deepEqual(
items[1].tasks.map((t) => t.id),
['t1', 't2', 't3', 't0']
)
}
})
it('merges orphan third-party into all-third card', () => {
const tasks = [
task({ id: 't0', taskType: 'dsfjc', companyId: '', companyName: '', itemName: '孤儿' })
]
const items = buildTaskListDisplayItems(tasks)
assert.equal(items.length, 1)
assert.equal(items[0].kind, 'all-third')
if (items[0].kind === 'all-third') {
assert.equal(items[0].tasks[0].id, 't0')
}
})
})
describe('sortThirdPartyTasksByCompany', () => {
it('groups by company first-seen order and puts orphans last', () => {
const sorted = sortThirdPartyTasksByCompany([
task({ id: 'a1', taskType: 'dsfjc', companyId: 'c2', companyName: '迪安' }),
task({ id: 'o1', taskType: 'dsfjc', companyId: '' }),
task({ id: 'b1', taskType: 'dsfjc', companyId: 'c1', companyName: '金域' }),
task({ id: 'a2', taskType: 'dsfjc', companyId: 'c2', companyName: '迪安' }),
task({ id: 'b2', taskType: 'dsfjc', companyId: 'c1', companyName: '金域' })
])
assert.deepEqual(
sorted.map((t) => t.id),
['a1', 'a2', 'b1', 'b2', 'o1']
)
})
})
describe('allThirdPartyCardSubtitle / company helpers', () => {
it('counts distinct companies excluding unassigned', () => {
const tasks = [
task({ id: '1', taskType: 'dsfjc', companyId: 'c1', companyName: '金域' }),
task({ id: '2', taskType: 'dsfjc', companyId: 'c1', companyName: '金域' }),
task({ id: '3', taskType: 'dsfjc', companyId: 'c2', companyName: '迪安' }),
task({ id: '4', taskType: 'dsfjc', companyId: '' })
]
assert.equal(countDistinctThirdPartyCompanies(tasks), 2)
assert.equal(allThirdPartyCardSubtitle(tasks), '第三方 · 4 个检测项目 · 2 家公司')
assert.equal(
allThirdPartyCardSubtitle([task({ id: '4', taskType: 'dsfjc', companyId: '' })]),
'第三方 · 1 个检测项目'
)
assert.equal(thirdPartyCompanyDisplayName({ companyId: '', companyName: '' }), '未归属公司')
assert.equal(
thirdPartyCompanyDisplayName({ companyId: 'c1', companyName: '金域' }),
'金域'
)
})
})
describe('companyGroupProgress', () => {
it('counts ywc vs total', () => {
const p = companyGroupProgress([
task({ id: 'a', taskType: 'dsfjc', taskStatus: 'ywc' }),
task({ id: 'b', taskType: 'dsfjc', taskStatus: 'dzx' })
])
assert.deepEqual(p, { completed: 1, total: 2 })
})
})
describe('pickSharedRemarkAndAttachments', () => {
it('picks latest non-empty remark and attachments by updateTime', () => {
const picked = pickSharedRemarkAndAttachments([
task({
id: 'a',
taskType: 'dsfjc',
remark: '旧备注',
thirdPartyAttachments: 'http://a.pdf',
updateTime: '2026-08-01 10:00:00',
attachmentFiles: [{ fileUrl: 'http://a.pdf', fileName: 'a.pdf' }]
}),
task({
id: 'b',
taskType: 'dsfjc',
remark: '新备注',
thirdPartyAttachments: '',
updateTime: '2026-08-28 12:00:00',
attachmentFiles: []
})
])
assert.equal(picked.remark, '新备注')
assert.equal(picked.thirdPartyAttachments, 'http://a.pdf')
assert.equal(picked.attachmentFiles?.length, 1)
})
})
describe('uniqueAssigneeNames', () => {
it('dedupes assignee names split by comma or顿号', () => {
const names = uniqueAssigneeNames([
task({ id: 'a', taskType: 'dsfjc', assigneeUserNames: '张三,李四' }),
task({ id: 'b', taskType: 'dsfjc', assigneeUserNames: '李四、王五' })
])
assert.equal(names, '张三、李四、王五')
})
it('returns em dash when no assignees', () => {
assert.equal(uniqueAssigneeNames([task({ id: 'a', taskType: 'dsfjc' })]), '—')
})
})