756 lines
24 KiB
JavaScript
756 lines
24 KiB
JavaScript
let PrismaClient
|
|
|
|
try {
|
|
;({ PrismaClient } = require('@prisma/client'))
|
|
} catch {
|
|
;({ PrismaClient } = require('/app/node_modules/@prisma/client'))
|
|
}
|
|
|
|
const prisma = new PrismaClient()
|
|
const TEST_TAG = '[测试数据]'
|
|
|
|
const locationSeeds = [
|
|
{ key: 'hq', name: '总部机房', code: 'HQ01', description: `${TEST_TAG} 总部核心设备区` },
|
|
{ key: 'office', name: '行政办公室', code: 'OF01', description: `${TEST_TAG} 行政办公区` },
|
|
{ key: 'service', name: '客服办公区', code: 'CS01', description: `${TEST_TAG} 客服与运营办公区` },
|
|
{ key: 'warehouse', name: '仓储维修间', code: 'WH01', description: `${TEST_TAG} 仓储和维修测试区` }
|
|
]
|
|
|
|
const departmentNameMap = {
|
|
management: '总经理室',
|
|
opsA: '运营中心A',
|
|
service: '客服中心',
|
|
warehouse: '仓储中心',
|
|
finance: '财务部'
|
|
}
|
|
|
|
const personDeptKeywordMap = {
|
|
manager: '总经理室',
|
|
ops: '运营中心A',
|
|
service: '客服中心',
|
|
warehouse: '仓储中心',
|
|
finance: '财务'
|
|
}
|
|
|
|
const dayMs = 24 * 60 * 60 * 1000
|
|
const dateOffset = (days) => new Date(Date.now() + days * dayMs)
|
|
|
|
const normalizeShortName = (value) => {
|
|
const normalized = String(value || '').trim().toUpperCase()
|
|
return normalized.replace(/[^A-Z0-9]/g, '')
|
|
}
|
|
|
|
const buildEquipmentCode = (shortName, locationId, sequence) =>
|
|
`${normalizeShortName(shortName)}-${String(locationId).padStart(4, '0')}-${String(sequence).padStart(5, '0')}`
|
|
|
|
const calculateValues = (unitPrice, totalQuantity, remainingQuantity) => ({
|
|
total_value: Number(unitPrice) * Number(totalQuantity),
|
|
borrowed_value: Number(unitPrice) * (Number(totalQuantity) - Number(remainingQuantity)),
|
|
available_value: Number(unitPrice) * Number(remainingQuantity)
|
|
})
|
|
|
|
const ensureLocation = async (seed) => {
|
|
const existing =
|
|
(await prisma.storageLocation.findFirst({ where: { code: seed.code } })) ||
|
|
(await prisma.storageLocation.findFirst({ where: { name: seed.name } }))
|
|
|
|
if (existing) {
|
|
return prisma.storageLocation.update({
|
|
where: { id: existing.id },
|
|
data: {
|
|
name: seed.name,
|
|
code: seed.code,
|
|
status: 'active',
|
|
description: seed.description
|
|
}
|
|
})
|
|
}
|
|
|
|
return prisma.storageLocation.create({
|
|
data: {
|
|
name: seed.name,
|
|
code: seed.code,
|
|
status: 'active',
|
|
description: seed.description
|
|
}
|
|
})
|
|
}
|
|
|
|
const ensureEquipment = async (seed) => {
|
|
const values = calculateValues(seed.unit_price, seed.total_quantity, seed.remaining_quantity)
|
|
const existing = await prisma.equipment.findUnique({
|
|
where: { equipment_code: seed.equipment_code }
|
|
})
|
|
|
|
const data = {
|
|
equipment_code: seed.equipment_code,
|
|
equipment_name: seed.equipment_name,
|
|
equipment_model: seed.equipment_model,
|
|
equipment_type: seed.equipment_type,
|
|
code_generation_mode: 'manual',
|
|
status: seed.status,
|
|
total_quantity: seed.total_quantity,
|
|
remaining_quantity: seed.remaining_quantity,
|
|
unit_price: seed.unit_price,
|
|
total_value: values.total_value,
|
|
borrowed_value: values.borrowed_value,
|
|
available_value: values.available_value,
|
|
total_value_with_children: seed.total_value_with_children || values.total_value,
|
|
description: seed.description,
|
|
purchase_date: seed.purchase_date,
|
|
supplier: seed.supplier,
|
|
storage_location_id: seed.storage_location_id,
|
|
department_id: seed.department_id,
|
|
asset_type_id: seed.asset_type_id,
|
|
parent_id: seed.parent_id || null,
|
|
mount_status: seed.mount_status || 'none'
|
|
}
|
|
|
|
if (existing) {
|
|
return prisma.equipment.update({
|
|
where: { id: existing.id },
|
|
data
|
|
})
|
|
}
|
|
|
|
return prisma.equipment.create({ data })
|
|
}
|
|
|
|
const ensureBorrowRecord = async (seed) => {
|
|
const existing = await prisma.borrowRecord.findFirst({
|
|
where: {
|
|
equipment_code: seed.equipment_code,
|
|
person_id: seed.person_id,
|
|
status: seed.status,
|
|
notes: { contains: TEST_TAG }
|
|
}
|
|
})
|
|
|
|
if (existing) {
|
|
return existing
|
|
}
|
|
|
|
return prisma.borrowRecord.create({
|
|
data: seed
|
|
})
|
|
}
|
|
|
|
const ensureMaintenanceRecord = async (seed) => {
|
|
const existing = await prisma.maintenanceRecord.findFirst({
|
|
where: {
|
|
equipment_code: seed.equipment_code,
|
|
issue_description: seed.issue_description
|
|
}
|
|
})
|
|
|
|
if (existing) {
|
|
return prisma.maintenanceRecord.update({
|
|
where: { id: existing.id },
|
|
data: seed
|
|
})
|
|
}
|
|
|
|
return prisma.maintenanceRecord.create({ data: seed })
|
|
}
|
|
|
|
const ensureDisposalRecord = async (seed) => {
|
|
const existing = await prisma.disposalRecord.findFirst({
|
|
where: {
|
|
equipment_code: seed.equipment_code,
|
|
disposal_reason: seed.disposal_reason
|
|
}
|
|
})
|
|
|
|
if (existing) {
|
|
return prisma.disposalRecord.update({
|
|
where: { id: existing.id },
|
|
data: seed
|
|
})
|
|
}
|
|
|
|
return prisma.disposalRecord.create({ data: seed })
|
|
}
|
|
|
|
const ensureMountHistory = async (seed) => {
|
|
const existing = await prisma.mountHistory.findFirst({
|
|
where: {
|
|
child_id: seed.child_id,
|
|
parent_id: seed.parent_id,
|
|
operation_type: seed.operation_type,
|
|
notes: seed.notes
|
|
}
|
|
})
|
|
|
|
if (existing) {
|
|
return existing
|
|
}
|
|
|
|
return prisma.mountHistory.create({ data: seed })
|
|
}
|
|
|
|
const ensureOperationLog = async (seed) => {
|
|
const existing = await prisma.operationLog.findFirst({
|
|
where: {
|
|
operation_type: seed.operation_type,
|
|
equipment_code: seed.equipment_code || null,
|
|
operation_details: seed.operation_details
|
|
}
|
|
})
|
|
|
|
if (existing) {
|
|
return existing
|
|
}
|
|
|
|
return prisma.operationLog.create({ data: seed })
|
|
}
|
|
|
|
async function main() {
|
|
const admin = await prisma.user.findFirst({
|
|
where: { username: 'admin' },
|
|
select: { id: true, username: true, name: true }
|
|
})
|
|
|
|
if (!admin) {
|
|
throw new Error('未找到 admin 用户,无法写入测试数据')
|
|
}
|
|
|
|
const assetTypeNormalization = [
|
|
{ id: 1, name: '主机', short_name: 'PC' },
|
|
{ id: 2, name: 'cpu', short_name: 'CPU' },
|
|
{ id: 3, name: '其他外设', short_name: 'QT' },
|
|
{ id: 4, name: '内存条', short_name: 'NCT' },
|
|
{ id: 5, name: '显卡', short_name: 'XK' },
|
|
{ id: 6, name: '显示器', short_name: 'XSQ' },
|
|
{ id: 7, name: '硬盘', short_name: 'YP' },
|
|
{ id: 8, name: '笔记本', short_name: 'PC' }
|
|
]
|
|
|
|
for (const item of assetTypeNormalization) {
|
|
await prisma.assetType.update({
|
|
where: { id: item.id },
|
|
data: {
|
|
name: item.name,
|
|
short_name: item.short_name,
|
|
status: 'active'
|
|
}
|
|
})
|
|
}
|
|
|
|
const assetTypes = await prisma.assetType.findMany({
|
|
select: { id: true, name: true, short_name: true, can_be_parent: true, can_be_child: true }
|
|
})
|
|
const assetTypeMap = new Map(assetTypes.map((item) => [item.name, item]))
|
|
|
|
const requiredTypes = ['主机', 'cpu', '其他外设', '内存条', '显卡', '显示器', '硬盘', '笔记本']
|
|
for (const typeName of requiredTypes) {
|
|
if (!assetTypeMap.has(typeName)) {
|
|
throw new Error(`缺少资产类型:${typeName}`)
|
|
}
|
|
}
|
|
|
|
await prisma.assetType.updateMany({
|
|
where: { name: { in: ['主机', '笔记本'] } },
|
|
data: { can_be_parent: true }
|
|
})
|
|
await prisma.assetType.updateMany({
|
|
where: { name: { in: ['cpu', '其他外设', '内存条', '显卡', '硬盘'] } },
|
|
data: { can_be_child: true }
|
|
})
|
|
|
|
const locationMap = new Map()
|
|
for (const seed of locationSeeds) {
|
|
const location = await ensureLocation(seed)
|
|
locationMap.set(seed.key, location)
|
|
}
|
|
|
|
const departmentMap = new Map()
|
|
for (const [key, name] of Object.entries(departmentNameMap)) {
|
|
const department = await prisma.department.findFirst({
|
|
where: { status: 'active', name }
|
|
})
|
|
if (!department) {
|
|
throw new Error(`未找到启用部门:${name}`)
|
|
}
|
|
departmentMap.set(key, department)
|
|
}
|
|
|
|
const personMap = new Map()
|
|
for (const [key, keyword] of Object.entries(personDeptKeywordMap)) {
|
|
const person = await prisma.person.findFirst({
|
|
where: {
|
|
status: 'active',
|
|
department: { contains: keyword }
|
|
},
|
|
orderBy: { id: 'asc' }
|
|
})
|
|
|
|
if (!person) {
|
|
throw new Error(`未找到可用测试人员,部门关键字:${keyword}`)
|
|
}
|
|
personMap.set(key, person)
|
|
}
|
|
|
|
const siteConfigCount = await prisma.siteConfig.count()
|
|
if (siteConfigCount === 0) {
|
|
await prisma.siteConfig.create({
|
|
data: {
|
|
site_name: '简尚固定资产管理系统',
|
|
theme_color: '#2563eb',
|
|
updated_by: admin.id
|
|
}
|
|
})
|
|
}
|
|
|
|
const code = (typeName, locationKey, sequence) =>
|
|
buildEquipmentCode(
|
|
assetTypeMap.get(typeName).short_name,
|
|
locationMap.get(locationKey).id,
|
|
sequence
|
|
)
|
|
|
|
const equipmentSeeds = [
|
|
{
|
|
equipment_code: code('主机', 'hq', 1),
|
|
equipment_name: '研发部测试主机',
|
|
equipment_model: 'ThinkCentre M900',
|
|
equipment_type: '主机',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 5899,
|
|
description: `${TEST_TAG} 用于二维码打印、挂载测试的主机`,
|
|
purchase_date: new Date('2025-01-15'),
|
|
supplier: '联想授权渠道',
|
|
storage_location_id: locationMap.get('hq').id,
|
|
department_id: departmentMap.get('opsA').id,
|
|
asset_type_id: assetTypeMap.get('主机').id
|
|
},
|
|
{
|
|
equipment_code: code('主机', 'service', 1),
|
|
equipment_name: '客服前台主机',
|
|
equipment_model: 'Dell OptiPlex 7090',
|
|
equipment_type: '主机',
|
|
status: '已借出',
|
|
total_quantity: 1,
|
|
remaining_quantity: 0,
|
|
unit_price: 4680,
|
|
description: `${TEST_TAG} 当前借出状态演示`,
|
|
purchase_date: new Date('2025-02-20'),
|
|
supplier: '戴尔企业采购',
|
|
storage_location_id: locationMap.get('service').id,
|
|
department_id: departmentMap.get('service').id,
|
|
asset_type_id: assetTypeMap.get('主机').id
|
|
},
|
|
{
|
|
equipment_code: code('笔记本', 'office', 1),
|
|
equipment_name: '管理层备用笔记本',
|
|
equipment_model: 'ThinkPad T14',
|
|
equipment_type: '笔记本',
|
|
status: '已借出',
|
|
total_quantity: 1,
|
|
remaining_quantity: 0,
|
|
unit_price: 6999,
|
|
description: `${TEST_TAG} 长期借用演示`,
|
|
purchase_date: new Date('2025-03-18'),
|
|
supplier: '联想官方商城',
|
|
storage_location_id: locationMap.get('office').id,
|
|
department_id: departmentMap.get('management').id,
|
|
asset_type_id: assetTypeMap.get('笔记本').id
|
|
},
|
|
{
|
|
equipment_code: code('笔记本', 'office', 2),
|
|
equipment_name: '财务外勤笔记本',
|
|
equipment_model: 'HP ProBook 440',
|
|
equipment_type: '笔记本',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 5299,
|
|
description: `${TEST_TAG} 可借用笔记本`,
|
|
purchase_date: new Date('2024-12-01'),
|
|
supplier: '惠普商用渠道',
|
|
storage_location_id: locationMap.get('office').id,
|
|
department_id: departmentMap.get('finance').id,
|
|
asset_type_id: assetTypeMap.get('笔记本').id
|
|
},
|
|
{
|
|
equipment_code: code('显示器', 'service', 1),
|
|
equipment_name: '客服工位显示器',
|
|
equipment_model: 'AOC 24B2XH',
|
|
equipment_type: '显示器',
|
|
status: '维护中',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 899,
|
|
description: `${TEST_TAG} 维修流程演示`,
|
|
purchase_date: new Date('2024-11-06'),
|
|
supplier: 'AOC 官方旗舰店',
|
|
storage_location_id: locationMap.get('service').id,
|
|
department_id: departmentMap.get('service').id,
|
|
asset_type_id: assetTypeMap.get('显示器').id
|
|
},
|
|
{
|
|
equipment_code: code('显示器', 'office', 1),
|
|
equipment_name: '财务双屏显示器',
|
|
equipment_model: 'Dell P2422H',
|
|
equipment_type: '显示器',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 1199,
|
|
description: `${TEST_TAG} 正常在库显示器`,
|
|
purchase_date: new Date('2025-01-08'),
|
|
supplier: '戴尔企业采购',
|
|
storage_location_id: locationMap.get('office').id,
|
|
department_id: departmentMap.get('finance').id,
|
|
asset_type_id: assetTypeMap.get('显示器').id
|
|
},
|
|
{
|
|
equipment_code: code('其他外设', 'warehouse', 1),
|
|
equipment_name: '标签打印机',
|
|
equipment_model: 'Xprinter XP-H500E',
|
|
equipment_type: '其他外设',
|
|
status: '待报废',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 899,
|
|
description: `${TEST_TAG} 报废流程演示设备`,
|
|
purchase_date: new Date('2023-08-05'),
|
|
supplier: '芯烨官方店',
|
|
storage_location_id: locationMap.get('warehouse').id,
|
|
department_id: departmentMap.get('warehouse').id,
|
|
asset_type_id: assetTypeMap.get('其他外设').id
|
|
},
|
|
{
|
|
equipment_code: code('其他外设', 'office', 1),
|
|
equipment_name: '财务扫描枪',
|
|
equipment_model: 'Honeywell 1470g',
|
|
equipment_type: '其他外设',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 560,
|
|
description: `${TEST_TAG} 已完成维修历史演示`,
|
|
purchase_date: new Date('2024-06-11'),
|
|
supplier: '霍尼韦尔代理商',
|
|
storage_location_id: locationMap.get('office').id,
|
|
department_id: departmentMap.get('finance').id,
|
|
asset_type_id: assetTypeMap.get('其他外设').id
|
|
},
|
|
{
|
|
equipment_code: code('硬盘', 'warehouse', 1),
|
|
equipment_name: '淘汰机械硬盘',
|
|
equipment_model: 'Seagate 1TB HDD',
|
|
equipment_type: '硬盘',
|
|
status: '已报废',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 260,
|
|
description: `${TEST_TAG} 已完成报废演示设备`,
|
|
purchase_date: new Date('2022-02-10'),
|
|
supplier: '希捷经销商',
|
|
storage_location_id: locationMap.get('warehouse').id,
|
|
department_id: departmentMap.get('warehouse').id,
|
|
asset_type_id: assetTypeMap.get('硬盘').id
|
|
},
|
|
{
|
|
equipment_code: code('cpu', 'hq', 1),
|
|
equipment_name: '主机CPU',
|
|
equipment_model: 'Intel i5-12400',
|
|
equipment_type: 'cpu',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 1380,
|
|
description: `${TEST_TAG} 已挂载到研发部测试主机`,
|
|
purchase_date: new Date('2025-01-15'),
|
|
supplier: '英特尔代理',
|
|
storage_location_id: locationMap.get('hq').id,
|
|
department_id: departmentMap.get('opsA').id,
|
|
asset_type_id: assetTypeMap.get('cpu').id,
|
|
mount_status: 'mounted'
|
|
},
|
|
{
|
|
equipment_code: code('内存条', 'hq', 1),
|
|
equipment_name: '主机内存',
|
|
equipment_model: 'Kingston DDR4 16GB',
|
|
equipment_type: '内存条',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 320,
|
|
description: `${TEST_TAG} 已挂载到研发部测试主机`,
|
|
purchase_date: new Date('2025-01-15'),
|
|
supplier: '金士顿经销商',
|
|
storage_location_id: locationMap.get('hq').id,
|
|
department_id: departmentMap.get('opsA').id,
|
|
asset_type_id: assetTypeMap.get('内存条').id,
|
|
mount_status: 'mounted'
|
|
},
|
|
{
|
|
equipment_code: code('显卡', 'hq', 1),
|
|
equipment_name: '主机显卡',
|
|
equipment_model: 'NVIDIA T400',
|
|
equipment_type: '显卡',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 980,
|
|
description: `${TEST_TAG} 已挂载到研发部测试主机`,
|
|
purchase_date: new Date('2025-01-15'),
|
|
supplier: '英伟达代理',
|
|
storage_location_id: locationMap.get('hq').id,
|
|
department_id: departmentMap.get('opsA').id,
|
|
asset_type_id: assetTypeMap.get('显卡').id,
|
|
mount_status: 'mounted'
|
|
},
|
|
{
|
|
equipment_code: code('硬盘', 'hq', 1),
|
|
equipment_name: '主机固态硬盘',
|
|
equipment_model: 'Samsung PM9A1 1TB',
|
|
equipment_type: '硬盘',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 699,
|
|
description: `${TEST_TAG} 已挂载到研发部测试主机`,
|
|
purchase_date: new Date('2025-01-15'),
|
|
supplier: '三星渠道',
|
|
storage_location_id: locationMap.get('hq').id,
|
|
department_id: departmentMap.get('opsA').id,
|
|
asset_type_id: assetTypeMap.get('硬盘').id,
|
|
mount_status: 'mounted'
|
|
},
|
|
{
|
|
equipment_code: code('其他外设', 'service', 2),
|
|
equipment_name: '客服键鼠套装',
|
|
equipment_model: 'Logitech MK270',
|
|
equipment_type: '其他外设',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 149,
|
|
description: `${TEST_TAG} 已完成借还历史演示`,
|
|
purchase_date: new Date('2025-02-01'),
|
|
supplier: '罗技旗舰店',
|
|
storage_location_id: locationMap.get('service').id,
|
|
department_id: departmentMap.get('service').id,
|
|
asset_type_id: assetTypeMap.get('其他外设').id
|
|
},
|
|
{
|
|
equipment_code: code('其他外设', 'office', 2),
|
|
equipment_name: '会议摄像头',
|
|
equipment_model: 'Logitech C930e',
|
|
equipment_type: '其他外设',
|
|
status: '可用',
|
|
total_quantity: 1,
|
|
remaining_quantity: 1,
|
|
unit_price: 799,
|
|
description: `${TEST_TAG} 正常在库会议设备`,
|
|
purchase_date: new Date('2024-10-09'),
|
|
supplier: '罗技企业采购',
|
|
storage_location_id: locationMap.get('office').id,
|
|
department_id: departmentMap.get('management').id,
|
|
asset_type_id: assetTypeMap.get('其他外设').id
|
|
}
|
|
]
|
|
|
|
const equipmentMap = new Map()
|
|
for (const seed of equipmentSeeds) {
|
|
const equipment = await ensureEquipment(seed)
|
|
equipmentMap.set(seed.equipment_code, equipment)
|
|
}
|
|
|
|
const parentHost = equipmentMap.get(code('主机', 'hq', 1))
|
|
const mountedChildren = [
|
|
equipmentMap.get(code('cpu', 'hq', 1)),
|
|
equipmentMap.get(code('内存条', 'hq', 1)),
|
|
equipmentMap.get(code('显卡', 'hq', 1)),
|
|
equipmentMap.get(code('硬盘', 'hq', 1))
|
|
]
|
|
|
|
for (const child of mountedChildren) {
|
|
await prisma.equipment.update({
|
|
where: { id: child.id },
|
|
data: {
|
|
parent_id: parentHost.id,
|
|
mount_status: 'mounted'
|
|
}
|
|
})
|
|
|
|
await ensureMountHistory({
|
|
child_id: child.id,
|
|
parent_id: parentHost.id,
|
|
operation_type: 'mount',
|
|
operated_by: admin.id,
|
|
notes: `${TEST_TAG} 初始化挂载`
|
|
})
|
|
}
|
|
|
|
const childValue = mountedChildren.reduce((sum, item) => sum + Number(item.unit_price), 0)
|
|
await prisma.equipment.update({
|
|
where: { id: parentHost.id },
|
|
data: {
|
|
total_value_with_children: Number(parentHost.unit_price) + childValue
|
|
}
|
|
})
|
|
|
|
const borrowedHost = equipmentMap.get(code('主机', 'service', 1))
|
|
const borrowedLaptop = equipmentMap.get(code('笔记本', 'office', 1))
|
|
const historicalPeripheral = equipmentMap.get(code('其他外设', 'service', 2))
|
|
const maintenanceMonitor = equipmentMap.get(code('显示器', 'service', 1))
|
|
const disposedDisk = equipmentMap.get(code('硬盘', 'warehouse', 1))
|
|
const disposalPrinter = equipmentMap.get(code('其他外设', 'warehouse', 1))
|
|
const maintainedScanner = equipmentMap.get(code('其他外设', 'office', 1))
|
|
|
|
await ensureBorrowRecord({
|
|
equipment_id: borrowedHost.id,
|
|
equipment_code: borrowedHost.equipment_code,
|
|
person_id: personMap.get('service').id,
|
|
person_name: personMap.get('service').real_name,
|
|
person_nickname: personMap.get('service').nickname,
|
|
person_identifier: personMap.get('service').id_number,
|
|
borrow_time: dateOffset(-12),
|
|
expected_return_time: dateOffset(3),
|
|
is_long_term: false,
|
|
return_time: null,
|
|
status: '已借出',
|
|
return_condition: '正常',
|
|
notes: `${TEST_TAG} 客服工位借用中`
|
|
})
|
|
|
|
await ensureBorrowRecord({
|
|
equipment_id: borrowedLaptop.id,
|
|
equipment_code: borrowedLaptop.equipment_code,
|
|
person_id: personMap.get('manager').id,
|
|
person_name: personMap.get('manager').real_name,
|
|
person_nickname: personMap.get('manager').nickname,
|
|
person_identifier: personMap.get('manager').id_number,
|
|
borrow_time: dateOffset(-25),
|
|
expected_return_time: null,
|
|
is_long_term: true,
|
|
return_time: null,
|
|
status: '已借出',
|
|
return_condition: '正常',
|
|
notes: `${TEST_TAG} 管理层长期领用`
|
|
})
|
|
|
|
await ensureBorrowRecord({
|
|
equipment_id: historicalPeripheral.id,
|
|
equipment_code: historicalPeripheral.equipment_code,
|
|
person_id: personMap.get('ops').id,
|
|
person_name: personMap.get('ops').real_name,
|
|
person_nickname: personMap.get('ops').nickname,
|
|
person_identifier: personMap.get('ops').id_number,
|
|
borrow_time: dateOffset(-40),
|
|
expected_return_time: dateOffset(-33),
|
|
is_long_term: false,
|
|
return_time: dateOffset(-31),
|
|
status: '已归还',
|
|
return_condition: '正常',
|
|
notes: `${TEST_TAG} 已归还历史记录`
|
|
})
|
|
|
|
await ensureMaintenanceRecord({
|
|
equipment_id: maintenanceMonitor.id,
|
|
equipment_code: maintenanceMonitor.equipment_code,
|
|
issue_description: `${TEST_TAG} 屏幕闪烁,间歇性黑屏`,
|
|
repair_vendor: '常州本地维保点',
|
|
estimated_cost: 180,
|
|
actual_cost: null,
|
|
start_date: dateOffset(-2),
|
|
expected_end_date: dateOffset(5),
|
|
actual_end_date: null,
|
|
status: 'in_progress',
|
|
repair_result: null,
|
|
created_by: admin.id
|
|
})
|
|
|
|
await ensureMaintenanceRecord({
|
|
equipment_id: maintainedScanner.id,
|
|
equipment_code: maintainedScanner.equipment_code,
|
|
issue_description: `${TEST_TAG} 扫描头识别异常`,
|
|
repair_vendor: '苏州售后中心',
|
|
estimated_cost: 120,
|
|
actual_cost: 100,
|
|
start_date: dateOffset(-18),
|
|
expected_end_date: dateOffset(-12),
|
|
actual_end_date: dateOffset(-13),
|
|
status: 'completed',
|
|
repair_result: '更换扫描头后恢复正常',
|
|
created_by: admin.id
|
|
})
|
|
|
|
await ensureDisposalRecord({
|
|
equipment_id: disposalPrinter.id,
|
|
equipment_code: disposalPrinter.equipment_code,
|
|
disposal_reason: `${TEST_TAG} 主板老化,维修成本高于残值`,
|
|
disposal_method: '报废',
|
|
estimated_value: 80,
|
|
actual_value: null,
|
|
status: 'pending',
|
|
applied_by: admin.id,
|
|
applied_at: dateOffset(-1),
|
|
approved_by: null,
|
|
approved_at: null,
|
|
completed_at: null,
|
|
notes: `${TEST_TAG} 待审批报废单`
|
|
})
|
|
|
|
await ensureDisposalRecord({
|
|
equipment_id: disposedDisk.id,
|
|
equipment_code: disposedDisk.equipment_code,
|
|
disposal_reason: `${TEST_TAG} 盘体异响且坏道严重`,
|
|
disposal_method: '报废',
|
|
estimated_value: 20,
|
|
actual_value: 0,
|
|
status: 'completed',
|
|
applied_by: admin.id,
|
|
applied_at: dateOffset(-30),
|
|
approved_by: admin.id,
|
|
approved_at: dateOffset(-28),
|
|
completed_at: dateOffset(-25),
|
|
notes: `${TEST_TAG} 已完成报废处置`
|
|
})
|
|
|
|
await ensureOperationLog({
|
|
user_id: admin.id,
|
|
username: admin.username,
|
|
operation_type: '初始化测试数据',
|
|
equipment_code: null,
|
|
equipment_id: null,
|
|
operation_details: `${TEST_TAG} 写入演示资产、借用、维修、报废数据`,
|
|
ip_address: null
|
|
})
|
|
|
|
await ensureOperationLog({
|
|
user_id: admin.id,
|
|
username: admin.username,
|
|
operation_type: '初始化挂载关系',
|
|
equipment_code: parentHost.equipment_code,
|
|
equipment_id: parentHost.id,
|
|
operation_details: `${TEST_TAG} 为主机挂载 CPU/内存/显卡/硬盘`,
|
|
ip_address: null
|
|
})
|
|
|
|
const summary = {
|
|
storage_locations: await prisma.storageLocation.count(),
|
|
equipments: await prisma.equipment.count(),
|
|
borrow_records: await prisma.borrowRecord.count(),
|
|
maintenance_records: await prisma.maintenanceRecord.count(),
|
|
disposal_records: await prisma.disposalRecord.count(),
|
|
mounted_children: await prisma.equipment.count({ where: { parent_id: parentHost.id } })
|
|
}
|
|
|
|
console.log(JSON.stringify(summary, null, 2))
|
|
}
|
|
|
|
main()
|
|
.catch((error) => {
|
|
console.error(error)
|
|
process.exitCode = 1
|
|
})
|
|
.finally(async () => {
|
|
await prisma.$disconnect()
|
|
})
|