190 lines
7.8 KiB
TypeScript
190 lines
7.8 KiB
TypeScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
|
|
import prisma from '../../utils/prisma'
|
|
import { getDashboardStats, getValueStatistics } from '../statisticsController'
|
|
|
|
test('首页统计应排除已报废库存、完整覆盖在册状态并使用上海自然日', async () => {
|
|
const originalAssetTypeFindMany = prisma.assetType.findMany
|
|
const originalEquipmentGroupBy = prisma.equipment.groupBy
|
|
const originalEquipmentFindMany = prisma.equipment.findMany
|
|
const originalEquipmentAggregate = prisma.equipment.aggregate
|
|
const originalEquipmentCount = prisma.equipment.count
|
|
const originalBorrowRecordFindMany = prisma.borrowRecord.findMany
|
|
const borrowRanges: any[] = []
|
|
|
|
;(prisma.assetType.findMany as any) = async () => [{ name: '内存条' }]
|
|
;(prisma.equipment.groupBy as any) = async (args: any) => {
|
|
if (args.by.length === 1 && args.by[0] === 'status') {
|
|
return [
|
|
{ status: '可用', _sum: { total_quantity: 1122, remaining_quantity: 1122, total_value: 424805, borrowed_value: 0, available_value: 424805 } },
|
|
{ status: '已借出', _sum: { total_quantity: 4507, remaining_quantity: 0, total_value: 2848258.44, borrowed_value: 2848258.44, available_value: 0 } },
|
|
{ status: '待报废', _sum: { total_quantity: 1, remaining_quantity: 1, total_value: 0, borrowed_value: 0, available_value: 0 } },
|
|
{ status: '已丢失', _sum: { total_quantity: 3, remaining_quantity: 0, total_value: 300, borrowed_value: 0, available_value: 0 } },
|
|
{ status: '已报废', _sum: { total_quantity: 127, remaining_quantity: 127, total_value: 83257, borrowed_value: 0, available_value: 0 } }
|
|
]
|
|
}
|
|
if (args.by.includes('status')) {
|
|
return [
|
|
{ equipment_type: '显示器', status: '可用', _sum: { total_quantity: 10, remaining_quantity: 10 } },
|
|
{ equipment_type: '显示器', status: '待报废', _sum: { total_quantity: 1, remaining_quantity: 1 } },
|
|
{ equipment_type: '仅丢失资产类型', status: '已丢失', _sum: { total_quantity: 3, remaining_quantity: 0 } }
|
|
]
|
|
}
|
|
return [{ equipment_type: '显示器', _sum: { remaining_quantity: 8 } }]
|
|
}
|
|
;(prisma.equipment.findMany as any) = async () => [
|
|
{
|
|
status: '可用',
|
|
total_value: 424805,
|
|
borrowed_value: 0,
|
|
available_value: 424805,
|
|
total_value_with_children: 0
|
|
},
|
|
{
|
|
status: '已借出',
|
|
total_value: 2848998.44,
|
|
borrowed_value: 2848998.44,
|
|
available_value: 0,
|
|
total_value_with_children: 0
|
|
}
|
|
]
|
|
;(prisma.equipment.aggregate as any) = async (args: any) => {
|
|
assert.deepEqual(args.where.status.notIn, ['已报废', '已丢失'])
|
|
return { _count: { id: 2057 }, _sum: { total_quantity: 2057 } }
|
|
}
|
|
;(prisma.equipment.count as any) = async () => 3
|
|
;(prisma.borrowRecord.findMany as any) = async (args: any) => {
|
|
borrowRanges.push(args.where.borrow_time || args.where.return_time)
|
|
if (args.where.return_time) {
|
|
assert.deepEqual(args.where.return_condition, { not: '丢失' })
|
|
}
|
|
return args.where.borrow_time
|
|
? [{ children_snapshot: '[{"unit_price":20}]', equipment: { unit_price: 100 } }]
|
|
: []
|
|
}
|
|
|
|
const state = { status: 200, body: null as any }
|
|
const response = {
|
|
status(code: number) {
|
|
state.status = code
|
|
return this
|
|
},
|
|
json(body: any) {
|
|
state.body = body
|
|
return this
|
|
}
|
|
}
|
|
|
|
try {
|
|
await getDashboardStats({} as any, response as any)
|
|
|
|
assert.equal(state.status, 200)
|
|
assert.equal(state.body.data.total_equipment, 5630)
|
|
assert.equal(state.body.data.root_asset_records, 2057)
|
|
assert.equal(state.body.data.accessory_equipment, 3573)
|
|
assert.equal(state.body.data.available_equipment, 1122)
|
|
assert.equal(state.body.data.borrowed_equipment, 4507)
|
|
assert.equal(state.body.data.pending_disposal_equipment, 1)
|
|
assert.equal(state.body.data.disposed_equipment, 127)
|
|
assert.equal(state.body.data.lost_equipment, 3)
|
|
assert.equal(state.body.data.other_equipment, 0)
|
|
const lostOnlyType = state.body.data.inventory_by_type.find((row: any) => row.equipment_type === '仅丢失资产类型')
|
|
assert.equal(lostOnlyType.total_quantity, 0)
|
|
assert.equal(lostOnlyType.lost_quantity, 3)
|
|
assert.equal(lostOnlyType.other_quantity, 0)
|
|
assert.equal(state.body.data.borrowed_without_active_record, 3)
|
|
assert.equal(state.body.data.today_borrow, 1)
|
|
assert.equal(state.body.data.today_return, 0)
|
|
assert.equal(state.body.data.today_borrow_value, 120)
|
|
assert.equal(state.body.data.business_timezone, 'Asia/Shanghai')
|
|
assert.equal(state.body.data.inventory_scope, 'current_excluding_disposed_and_lost')
|
|
assert.equal(state.body.data.value_scope, 'book_value_excluding_disposed_including_lost')
|
|
assert.equal(state.body.data.total_value, 3273363.44)
|
|
assert.equal(state.body.data.borrowed_value, 2848258.44)
|
|
assert.equal(
|
|
state.body.data.available_equipment +
|
|
state.body.data.borrowed_equipment +
|
|
state.body.data.maintenance_equipment +
|
|
state.body.data.pending_disposal_equipment +
|
|
state.body.data.damaged_equipment +
|
|
state.body.data.other_equipment,
|
|
state.body.data.total_equipment
|
|
)
|
|
assert.ok(Math.abs(state.body.data.usage_rate - 80.06750755018653) < 0.000001)
|
|
assert.ok(Math.abs(state.body.data.value_usage_rate - 87.021180377732) < 0.000001)
|
|
assert.equal(borrowRanges.length, 2)
|
|
for (const range of borrowRanges) {
|
|
assert.equal(range.gte.getUTCHours(), 16)
|
|
assert.equal(range.lt.getTime() - range.gte.getTime(), 24 * 60 * 60 * 1000)
|
|
}
|
|
} finally {
|
|
;(prisma.assetType.findMany as any) = originalAssetTypeFindMany
|
|
;(prisma.equipment.groupBy as any) = originalEquipmentGroupBy
|
|
;(prisma.equipment.findMany as any) = originalEquipmentFindMany
|
|
;(prisma.equipment.aggregate as any) = originalEquipmentAggregate
|
|
;(prisma.equipment.count as any) = originalEquipmentCount
|
|
;(prisma.borrowRecord.findMany as any) = originalBorrowRecordFindMany
|
|
}
|
|
})
|
|
|
|
test('价值统计应按当前资产本体汇总并忽略已报废和过期组合金额缓存', async () => {
|
|
const originalEquipmentFindMany = prisma.equipment.findMany
|
|
let capturedWhere: any
|
|
;(prisma.equipment.findMany as any) = async (args: any) => {
|
|
capturedWhere = args.where
|
|
return [
|
|
{
|
|
equipment_name: '显示器',
|
|
equipment_type: '显示器',
|
|
unit_price: 1500,
|
|
total_quantity: 1,
|
|
total_value: 1500,
|
|
borrowed_value: 1500,
|
|
available_value: 0,
|
|
total_value_with_children: 2240,
|
|
status: '已借出'
|
|
},
|
|
{
|
|
equipment_name: '扩展坞',
|
|
equipment_type: '扩展坞',
|
|
unit_price: 740,
|
|
total_quantity: 1,
|
|
total_value: 740,
|
|
borrowed_value: 0,
|
|
available_value: 740,
|
|
total_value_with_children: 0,
|
|
status: '可用'
|
|
}
|
|
]
|
|
}
|
|
|
|
const state = { status: 200, body: null as any }
|
|
const response = {
|
|
status(code: number) {
|
|
state.status = code
|
|
return this
|
|
},
|
|
json(body: any) {
|
|
state.body = body
|
|
return this
|
|
}
|
|
}
|
|
|
|
try {
|
|
await getValueStatistics({ query: { start_date: '2026-07-17', end_date: '2026-07-17' } } as any, response as any)
|
|
|
|
assert.equal(capturedWhere.status.not, '已报废')
|
|
assert.equal(capturedWhere.created_at.gte.toISOString(), '2026-07-16T16:00:00.000Z')
|
|
assert.equal(capturedWhere.created_at.lt.toISOString(), '2026-07-17T16:00:00.000Z')
|
|
assert.equal(state.body.data.total_value, 2240)
|
|
assert.equal(state.body.data.borrowed_value, 1500)
|
|
assert.equal(state.body.data.available_value, 740)
|
|
assert.equal(state.body.data.value_by_type.length, 2)
|
|
assert.equal(state.body.data.top_equipment[0].item_value, 1500)
|
|
assert.equal(state.body.data.top_equipment[0].stock_total_value, 1500)
|
|
} finally {
|
|
;(prisma.equipment.findMany as any) = originalEquipmentFindMany
|
|
}
|
|
})
|