244 lines
8.4 KiB
JavaScript
244 lines
8.4 KiB
JavaScript
const express = require('express');
|
||
const router = express.Router();
|
||
const Order = require('../models/Order');
|
||
const Vehicle = require('../models/Vehicle');
|
||
const Customer = require('../models/Customer');
|
||
const Store = require('../models/Store');
|
||
const { authMiddleware, requireRole } = require('../middleware/auth');
|
||
const { validate } = require('../middleware/validate');
|
||
const { schemas } = require('../middleware/validate');
|
||
|
||
// ─── 公开列表查询(登录即可,admin 可看全部,customer 只能看自己的) ───
|
||
router.get('/', authMiddleware, async (req, res) => {
|
||
try {
|
||
const filter = {};
|
||
if (req.query.status) filter.status = req.query.status;
|
||
// 非 admin 角色只能看自己的订单
|
||
if (req.user.role === 'customer') {
|
||
// 查找当前 rider 对应的客户手机号(需关联 Customer 表)
|
||
// 此处通过 rider id 查找(假设订单中 rider 字段关联骑手)
|
||
filter.rider = req.user.id;
|
||
} else if (req.user.role === 'store') {
|
||
// store 角色永远只能看自己门店的数据,忽略前端传的 storeId 参数
|
||
if (req.user.storeId) {
|
||
filter.storeId = req.user.storeId;
|
||
}
|
||
}
|
||
const orders = await Order.find(filter)
|
||
.populate('customer', 'name phone')
|
||
.populate('vehicle', 'model vehicleId');
|
||
res.json({ success: true, data: orders });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: '服务器内部错误' });
|
||
}
|
||
});
|
||
|
||
// 获取单个订单(登录即可,检查是否本人或 admin/store)
|
||
router.get('/:id', authMiddleware, async (req, res) => {
|
||
try {
|
||
const order = await Order.findById(req.params.id)
|
||
.populate('customer')
|
||
.populate('vehicle');
|
||
if (!order) return res.status(404).json({ success: false, message: '订单不存在' });
|
||
|
||
// 权限检查:本人骑手 或 admin/store
|
||
const isOwner = order.rider?.toString() === req.user.id;
|
||
if (req.user.role !== 'admin' && req.user.role !== 'store' && !isOwner) {
|
||
return res.status(403).json({ success: false, message: '权限不足' });
|
||
}
|
||
res.json({ success: true, data: order });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 创建订单(store 或 admin)
|
||
router.post('/', authMiddleware, requireRole('admin', 'store'), validate(schemas.order), async (req, res) => {
|
||
try {
|
||
const {
|
||
customerName, customer,
|
||
vehicleId, vehicle,
|
||
contractMonths, startDate, endDate, rentalFee, deposit, orderType
|
||
} = req.body;
|
||
|
||
const vehicleObjectId = vehicle || vehicleId;
|
||
|
||
// 解析客户
|
||
let customerObjectId = customer;
|
||
if (!customerObjectId && customerName) {
|
||
let customerDoc = await Customer.findOne({ name: customerName });
|
||
if (!customerDoc) {
|
||
customerDoc = await Customer.create({
|
||
name: customerName,
|
||
phone: '00000000000',
|
||
customerId: `CUST${Date.now()}`
|
||
});
|
||
}
|
||
customerObjectId = customerDoc._id;
|
||
}
|
||
|
||
const vehicleDoc = await Vehicle.findById(vehicleObjectId);
|
||
if (!vehicleDoc) return res.status(404).json({ success: false, message: '车辆不存在' });
|
||
if (vehicleDoc.status !== '空闲') {
|
||
return res.status(400).json({ success: false, message: '车辆不可用,当前状态:' + vehicleDoc.status });
|
||
}
|
||
|
||
const start = startDate ? new Date(startDate) : new Date();
|
||
let end = endDate ? new Date(endDate) : null;
|
||
const months = Number(contractMonths) || 0;
|
||
if (!end && months > 0) {
|
||
end = new Date(start);
|
||
end.setMonth(end.getMonth() + months);
|
||
}
|
||
|
||
const fee = Number(rentalFee) || 0;
|
||
const depositAmt = Number(deposit) || 0;
|
||
const totalAmount = fee + depositAmt;
|
||
|
||
const order = new Order({
|
||
customer: customerObjectId,
|
||
vehicle: vehicleObjectId,
|
||
startDate: start,
|
||
endDate: end || new Date(start.getTime() + 30 * 24 * 60 * 60 * 1000),
|
||
rentalFee: fee,
|
||
deposit: depositAmt,
|
||
totalAmount,
|
||
status: '进行中'
|
||
});
|
||
|
||
await order.save();
|
||
|
||
vehicleDoc.status = '在租';
|
||
vehicleDoc.isRented = true;
|
||
vehicleDoc.currentOrderId = order._id;
|
||
await vehicleDoc.save();
|
||
|
||
if (customerObjectId) {
|
||
const cust = await Customer.findById(customerObjectId);
|
||
if (cust) {
|
||
cust.totalRentals += 1;
|
||
cust.currentRentals = (cust.currentRentals || 0) + 1;
|
||
cust.totalSpent = (cust.totalSpent || 0) + totalAmount;
|
||
await cust.save();
|
||
}
|
||
}
|
||
|
||
res.status(201).json({ success: true, data: order });
|
||
} catch (error) {
|
||
res.status(400).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 更新订单(admin 或 store)
|
||
router.put('/:id', authMiddleware, requireRole('admin', 'store'), async (req, res) => {
|
||
try {
|
||
const order = await Order.findByIdAndUpdate(req.params.id, req.body, { new: true, runValidators: true });
|
||
if (!order) return res.status(404).json({ success: false, message: '订单不存在' });
|
||
res.json({ success: true, data: order });
|
||
} catch (error) {
|
||
res.status(400).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 结束订单(admin 或 store)
|
||
router.patch('/:id/complete', authMiddleware, requireRole('admin', 'store'), async (req, res) => {
|
||
try {
|
||
const order = await Order.findById(req.params.id);
|
||
if (!order) return res.status(404).json({ success: false, message: '订单不存在' });
|
||
|
||
order.status = '已完成';
|
||
order.actualEndDate = new Date();
|
||
await order.save();
|
||
|
||
const vehicle = await Vehicle.findById(order.vehicle);
|
||
if (vehicle) {
|
||
vehicle.status = '空闲';
|
||
vehicle.isRented = false;
|
||
vehicle.currentOrderId = null;
|
||
vehicle.totalRentDays += Math.ceil((new Date(order.endDate) - new Date(order.startDate)) / (1000 * 60 * 60 * 24));
|
||
await vehicle.save();
|
||
}
|
||
|
||
const customer = await Customer.findById(order.customer);
|
||
if (customer) {
|
||
customer.currentRentals -= 1;
|
||
await customer.save();
|
||
}
|
||
|
||
res.json({ success: true, data: order });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 取消订单(admin 或 store)
|
||
router.patch('/:id/cancel', authMiddleware, requireRole('admin', 'store'), async (req, res) => {
|
||
try {
|
||
const order = await Order.findById(req.params.id);
|
||
if (!order) return res.status(404).json({ success: false, message: '订单不存在' });
|
||
if (order.status === '已完成' || order.status === '已取消') {
|
||
return res.status(400).json({ success: false, message: '当前状态无法取消' });
|
||
}
|
||
|
||
order.status = '已取消';
|
||
order.actualEndDate = new Date();
|
||
await order.save();
|
||
|
||
const vehicle = await Vehicle.findById(order.vehicle);
|
||
if (vehicle) {
|
||
vehicle.status = '空闲';
|
||
vehicle.isRented = false;
|
||
vehicle.currentOrderId = null;
|
||
await vehicle.save();
|
||
}
|
||
|
||
const customer = await Customer.findById(order.customer);
|
||
if (customer) {
|
||
customer.currentRentals = Math.max((customer.currentRentals || 0) - 1, 0);
|
||
await customer.save();
|
||
}
|
||
|
||
res.json({ success: true, data: order });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 逾期订单(admin 或 store)
|
||
router.get('/status/overdue', authMiddleware, requireRole('admin', 'store'), async (req, res) => {
|
||
try {
|
||
const now = new Date();
|
||
const orders = await Order.find({
|
||
status: '进行中',
|
||
endDate: { $lt: now }
|
||
})
|
||
.populate('customer', 'name phone')
|
||
.populate('vehicle', 'model vehicleId');
|
||
|
||
for (const order of orders) {
|
||
const overdueDays = Math.ceil((now - order.endDate) / (1000 * 60 * 60 * 24));
|
||
order.overdueDays = overdueDays;
|
||
order.overdueFee = overdueDays * order.rentalFee * 0.1;
|
||
order.status = '逾期';
|
||
await order.save();
|
||
}
|
||
res.json({ success: true, data: orders });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
// 按状态筛选(admin 或 store)
|
||
router.get('/status/:status', authMiddleware, requireRole('admin', 'store'), async (req, res) => {
|
||
try {
|
||
const orders = await Order.find({ status: req.params.status })
|
||
.populate('customer', 'name phone')
|
||
.populate('vehicle', 'model vehicleId');
|
||
res.json({ success: true, data: orders });
|
||
} catch (error) {
|
||
res.status(500).json({ success: false, message: "服务器内部错误" });
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|