feat(consumable): 解耦耗材日志与耗材关联并支持耗材删除后日志保留

This commit is contained in:
zhang1106
2026-02-24 11:58:31 +08:00
parent d67fdb2b17
commit b810e2cca1
4 changed files with 315 additions and 21 deletions
+97 -13
View File
@@ -70,7 +70,16 @@ router.post('/', async (req, res) => {
currentStock: consumable.currentStock,
operator: req.body.operator || req.body.operatorName || '系统',
reason: '新建耗材',
notes: req.body.description || ''
notes: req.body.description || '',
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location,
minStock: consumable.minStock,
maxStock: consumable.maxStock
}
}, { transaction });
await transaction.commit();
@@ -138,7 +147,16 @@ router.post('/import', async (req, res) => {
currentStock: consumable.currentStock,
operator,
reason: '批量导入',
notes: ''
notes: '',
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location,
minStock: consumable.minStock,
maxStock: consumable.maxStock
}
}, { transaction });
results.success++;
@@ -337,7 +355,14 @@ router.post('/quick-inout', async (req, res) => {
operator,
reason,
notes,
isEditable: false
isEditable: false,
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location
}
}, { transaction });
await transaction.commit();
@@ -432,7 +457,14 @@ router.post('/inout', async (req, res) => {
operator,
reason,
notes,
isEditable: false
isEditable: false,
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location
}
}, { transaction });
await transaction.commit();
@@ -515,7 +547,6 @@ router.post('/adjust', async (req, res) => {
const changeQuantity = newStock - previousStock;
// 系统生成的调整记录不可编辑
await ConsumableLog.create({
consumableId,
consumableName: consumable.name,
@@ -526,7 +557,14 @@ router.post('/adjust', async (req, res) => {
operator,
reason: reason || (adjustType === 'set' ? '库存调整为 ' + newStock : reason),
notes: adjustType === 'set' ? `库存从 ${previousStock} 调整为 ${newStock}` : notes,
isEditable: false
isEditable: false,
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location
}
}, { transaction });
await transaction.commit();
@@ -618,7 +656,7 @@ router.get('/logs/export', async (req, res) => {
order: [['createdAt', 'DESC']]
});
const csvHeader = 'ID,耗材ID,耗材名称,操作类型,变动数量,操作前库存,操作后库存,操作人,原因,备注,创建时间,更新时间\n';
const csvHeader = 'ID,耗材ID,耗材名称,操作类型,变动数量,操作前库存,操作后库存,操作人,原因,备注,耗材状态,分类,单位,单价,创建时间,更新时间\n';
const csvRows = logs.map(log => {
const operationTypeMap = {
'in': '入库',
@@ -629,6 +667,7 @@ router.get('/logs/export', async (req, res) => {
'adjust': '调整',
'import': '导入'
};
const snapshot = log.consumableSnapshot || {};
return [
log.id,
log.consumableId,
@@ -640,6 +679,10 @@ router.get('/logs/export', async (req, res) => {
log.operator,
log.reason || '',
log.notes || '',
log.isConsumableDeleted ? '已删除' : '正常',
snapshot.category || '',
snapshot.unit || '',
snapshot.unitPrice || '',
dayjs(log.createdAt).format('YYYY-MM-DD HH:mm:ss'),
dayjs(log.updatedAt).format('YYYY-MM-DD HH:mm:ss')
].map(v => `"${String(v).replace(/"/g, '""')}"`).join(',');
@@ -754,7 +797,14 @@ router.put('/:id', async (req, res) => {
currentStock: consumable.currentStock,
operator: req.body.operator || req.body.operatorName || '系统',
reason: '信息更新',
notes: `更新字段: ${Object.keys(req.body).join(', ')}`
notes: `更新字段: ${Object.keys(req.body).join(', ')}`,
consumableSnapshot: {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location
}
}, { transaction });
await transaction.commit();
@@ -777,17 +827,51 @@ router.delete('/:id', async (req, res) => {
const consumableId = consumable.consumableId;
const consumableName = consumable.name;
const currentStock = consumable.currentStock;
const operator = req.body.operator || req.query.operator || '系统';
const consumableSnapshot = {
category: consumable.category,
unit: consumable.unit,
unitPrice: consumable.unitPrice,
supplier: consumable.supplier,
location: consumable.location,
description: consumable.description,
minStock: consumable.minStock,
maxStock: consumable.maxStock,
status: consumable.status
};
await ConsumableLog.create({
consumableId,
consumableName,
operationType: 'delete',
quantity: -currentStock,
previousStock: currentStock,
currentStock: 0,
operator,
reason: '删除耗材',
notes: `删除耗材:${consumableName},删除时库存为 ${currentStock}`,
isEditable: false,
isConsumableDeleted: true,
consumableSnapshot
}, { transaction });
await ConsumableLog.update(
{
isConsumableDeleted: true,
consumableSnapshot
},
{
where: { consumableId },
transaction
}
);
await ConsumableRecord.destroy({
where: { consumableId },
transaction
});
await ConsumableLog.destroy({
where: { consumableId },
transaction
});
await consumable.destroy({ transaction });
await transaction.commit();