Files
nxxmdata/government-backend/routes/warehouse.js

390 lines
8.4 KiB
JavaScript
Raw Normal View History

2025-09-17 18:04:28 +08:00
const express = require('express');
const router = express.Router();
2025-09-24 17:49:32 +08:00
const Material = require('../models/Material');
const WarehouseTransaction = require('../models/WarehouseTransaction');
const { Op } = require('sequelize');
2025-09-17 18:04:28 +08:00
2025-09-24 17:49:32 +08:00
// 仓库物资列表(支持分页、搜索和筛选)
router.get('/', async (req, res) => {
try {
const {
keyword = '',
category = '',
status = '',
page = 1,
pageSize = 10
} = req.query;
const where = {};
// 搜索条件
if (keyword) {
where[Op.or] = [
{ code: { [Op.like]: `%${keyword}%` } },
{ name: { [Op.like]: `%${keyword}%` } }
];
}
// 类别筛选
if (category) {
where.category = category;
}
// 状态筛选
if (status) {
where.status = status;
}
const offset = (parseInt(page) - 1) * parseInt(pageSize);
const limit = parseInt(pageSize);
const { count, rows } = await Material.findAndCountAll({
where,
offset,
limit,
order: [['update_time', 'DESC']]
});
res.json({
code: 200,
data: rows,
total: count,
page: parseInt(page),
pageSize: limit,
totalPages: Math.ceil(count / limit)
});
} catch (error) {
res.status(500).json({
code: 500,
message: '获取物资列表失败',
error: error.message
});
}
});
// 获取单个物资详情
router.get('/:id', async (req, res) => {
try {
const { id } = req.params;
const material = await Material.findByPk(id);
if (!material) {
return res.status(404).json({
code: 404,
message: '物资不存在'
});
}
res.json({
code: 200,
data: material
});
} catch (error) {
res.status(500).json({
code: 500,
message: '获取物资详情失败',
error: error.message
});
}
});
// 创建新物资
router.post('/', async (req, res) => {
try {
const { code, name, category, unit, stockQuantity, warningQuantity, supplier, remark } = req.body;
// 检查物资编号是否已存在
const existingMaterial = await Material.findOne({ where: { code } });
if (existingMaterial) {
return res.status(400).json({
code: 400,
message: '物资编号已存在'
});
}
const material = await Material.create({
code,
name,
category,
unit,
stockQuantity,
warningQuantity,
supplier,
remark
});
res.json({
code: 200,
message: '创建物资成功',
data: material
});
} catch (error) {
res.status(500).json({
code: 500,
message: '创建物资失败',
error: error.message
});
}
});
// 更新物资信息
router.put('/:id', async (req, res) => {
try {
const { id } = req.params;
const { code, name, category, unit, stockQuantity, warningQuantity, supplier, remark } = req.body;
const material = await Material.findByPk(id);
if (!material) {
return res.status(404).json({
code: 404,
message: '物资不存在'
});
}
// 检查物资编号是否已存在(排除当前物资)
if (code && code !== material.code) {
const existingMaterial = await Material.findOne({ where: { code } });
if (existingMaterial) {
return res.status(400).json({
code: 400,
message: '物资编号已存在'
});
}
}
await material.update({
code,
name,
category,
unit,
stockQuantity,
warningQuantity,
supplier,
remark
});
res.json({
code: 200,
message: '更新物资成功',
data: material
});
} catch (error) {
res.status(500).json({
code: 500,
message: '更新物资失败',
error: error.message
});
}
});
// 删除物资
router.delete('/:id', async (req, res) => {
try {
const { id } = req.params;
const material = await Material.findByPk(id);
if (!material) {
return res.status(404).json({
code: 404,
message: '物资不存在'
});
}
await material.destroy();
res.json({
code: 200,
message: '删除物资成功'
});
} catch (error) {
res.status(500).json({
code: 500,
message: '删除物资失败',
error: error.message
});
}
});
// 物资入库
router.post('/in', async (req, res) => {
try {
const { materialId, quantity, operator, remark } = req.body;
// 开始事务
const transaction = await Material.sequelize.transaction();
try {
// 查找物资
const material = await Material.findByPk(materialId, { transaction });
if (!material) {
await transaction.rollback();
return res.status(404).json({
code: 404,
message: '物资不存在'
});
}
// 更新库存
material.stockQuantity += parseInt(quantity);
await material.save({ transaction });
// 记录入库记录
await WarehouseTransaction.create({
materialId,
type: 'in',
quantity,
operator,
remark
}, { transaction });
// 提交事务
await transaction.commit();
res.json({
code: 200,
message: '入库成功',
data: {
materialId,
quantity,
newStock: material.stockQuantity
}
});
} catch (err) {
// 回滚事务
await transaction.rollback();
throw err;
}
} catch (error) {
res.status(500).json({
code: 500,
message: '入库失败',
error: error.message
});
}
});
// 物资出库
router.post('/out', async (req, res) => {
try {
const { materialId, quantity, operator, remark } = req.body;
// 开始事务
const transaction = await Material.sequelize.transaction();
try {
// 查找物资
const material = await Material.findByPk(materialId, { transaction });
if (!material) {
await transaction.rollback();
return res.status(404).json({
code: 404,
message: '物资不存在'
});
}
// 检查库存是否足够
if (material.stockQuantity < parseInt(quantity)) {
await transaction.rollback();
return res.status(400).json({
code: 400,
message: '库存不足'
});
}
// 更新库存
material.stockQuantity -= parseInt(quantity);
await material.save({ transaction });
// 记录出库记录
await WarehouseTransaction.create({
materialId,
type: 'out',
quantity,
operator,
remark
}, { transaction });
// 提交事务
await transaction.commit();
res.json({
code: 200,
message: '出库成功',
data: {
materialId,
quantity,
newStock: material.stockQuantity
}
});
} catch (err) {
// 回滚事务
await transaction.rollback();
throw err;
}
} catch (error) {
res.status(500).json({
code: 500,
message: '出库失败',
error: error.message
});
}
});
// 获取库存统计信息
router.get('/stats', async (req, res) => {
try {
// 统计总类别数
const totalCategories = await Material.count({
distinct: true,
col: 'category'
});
// 统计库存总量
const totalQuantityResult = await Material.sum('stockQuantity');
const totalQuantity = totalQuantityResult || 0;
// 统计低库存物资数
const lowStockCount = await Material.count({
where: {
status: 'low'
}
});
// 统计缺货物资数
const outOfStockCount = await Material.count({
where: {
status: 'out'
}
});
// 统计各类别物资数量
const categoryStats = await Material.findAll({
attributes: [
'category',
[Material.sequelize.fn('COUNT', Material.sequelize.col('id')), 'count'],
[Material.sequelize.fn('SUM', Material.sequelize.col('stockQuantity')), 'totalQuantity']
],
group: ['category'],
raw: true
});
res.json({
code: 200,
data: {
totalCategories,
totalQuantity,
lowStockCount,
outOfStockCount,
categoryStats
}
});
} catch (error) {
res.status(500).json({
code: 500,
message: '获取统计信息失败',
error: error.message
});
}
2025-09-17 18:04:28 +08:00
});
module.exports = router;