e-scooter-rental-system/server/routes/orders.js

252 lines
7.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const express = require('express');
const router = express.Router();
const Order = require('../models/Order');
const Vehicle = require('../models/Vehicle');
const Customer = require('../models/Customer');
// 获取所有订单
router.get('/', async (req, res) => {
try {
const orders = await Order.find()
.populate('customer', 'name phone')
.populate('vehicle', 'model vehicleId');
res.json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 获取单个订单
router.get('/:id', 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: '订单不存在' });
}
res.json({ success: true, data: order });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 创建订单(支持门店端新客创建订单)
router.post('/', async (req, res) => {
try {
const {
customerName, customer, // customerName=新客姓名字符串customer=已有客户ID
vehicleId, vehicle, // vehicleId=前端字段名vehicle=后端字段名
contractMonths, startDate, endDate, rentalFee, deposit, orderType
} = req.body;
// 解析车辆 ID兼容前端 vehicleId 字段名)
const vehicleObjectId = vehicle || vehicleId;
// 解析客户优先用已有客户ID否则用姓名查找或创建新客户
let customerObjectId = customer;
if (!customerObjectId && customerName) {
// 查找同名客户
let customerDoc = await Customer.findOne({ name: customerName });
if (!customerDoc) {
// 创建新客户phone 必填,设为默认值)
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 });
}
// 日期处理startDate/endDate 或根据 contractMonths 计算
const start = startDate ? new Date(startDate) : new Date();
let end = endDate ? new Date(endDate) : null;
let months = Number(contractMonths) || 0;
if (!end && months > 0) {
end = new Date(start);
end.setMonth(end.getMonth() + months);
}
// 租金计算:使用传入的 rentalFee若未传则为 0
let 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: error.message });
}
});
// 更新订单
router.put('/:id', 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: error.message });
}
});
// 结束订单
router.patch('/:id/complete', 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: error.message });
}
});
// 取消订单
router.patch('/:id/cancel', 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: error.message });
}
});
// 获取逾期订单
router.get('/status/overdue', 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; // 10% 滞纳金
order.status = '逾期';
await order.save();
}
res.json({ success: true, data: orders });
} catch (error) {
res.status(500).json({ success: false, message: error.message });
}
});
// 按状态筛选订单
router.get('/status/:status', 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: error.message });
}
});
module.exports = router;