e-scooter-rental-system/seed-full-data.js

270 lines
16 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.

/**
* 完整测试数据填充脚本
* 用法: node seed-full-data.js
*/
const mongoose = require('mongoose');
const MONGO_URI = 'mongodb://localhost:27017/e-scooter-rental';
// 加载所有模型
const Store = require('./server/models/Store');
const Vehicle = require('./server/models/Vehicle');
const Customer = require('./server/models/Customer');
const Order = require('./server/models/Order');
const Payment = require('./server/models/Payment');
const Complaint = require('./server/models/Complaint');
const Application = require('./server/models/Application');
const Dispute = require('./server/models/Dispute');
const COLLECTIONS = [Store, Vehicle, Customer, Order, Payment, Complaint, Application, Dispute];
async function clearAll() {
console.log('🗑️ 清空所有集合...');
for (const Model of COLLECTIONS) {
await Model.deleteMany({});
}
console.log(' 所有集合已清空\n');
}
async function seedStores() {
console.log('📍 插入门店数据...');
const stores = [
{ storeId: 'STORE001', name: '朝阳区总店', address: '北京市朝阳区建国路88号', phone: '010-12345678', manager: '王店长', status: '营业中', approvalStatus: '已通过' },
{ storeId: 'STORE002', name: '海淀区中关村店', address: '北京市海淀区中关村大街12号', phone: '010-23456789', manager: '李店长', status: '营业中', approvalStatus: '已通过' },
{ storeId: 'STORE003', name: '西城区金融街店', address: '北京市西城区金融大街28号', phone: '010-34567890', manager: '赵店长', status: '营业中', approvalStatus: '已通过' },
{ storeId: 'STORE004', name: '东城区王府井店', address: '北京市东城区王府井大街66号', phone: '010-45678901', manager: '孙店长', status: '装修中', approvalStatus: '已通过' },
{ storeId: 'STORE005', name: '丰台区南站店', address: '北京市丰台区南站西路88号', phone: '010-56789012', manager: '周店长', status: '营业中', approvalStatus: '已通过' },
];
const result = await Store.insertMany(stores);
console.log(` 插入 ${result.length} 条门店记录`);
return result;
}
async function seedVehicles(stores) {
console.log('🚗 插入车辆数据...');
const storeIds = stores.map(s => s.storeId);
const vehicles = [
{ vehicleId: 'VEH0001', storeId: storeIds[0], frameNumber: 'FN0001', plateNumber: '京A12345', brand: '雅迪', vehicleType: 'DT3', color: '黑色', batteryType: '锂电池', batteryCapacity: 48, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2023-06-15'), purchasePrice: 3999, purchaseSupplier: '雅迪集团' },
{ vehicleId: 'VEH0002', storeId: storeIds[0], frameNumber: 'FN0002', plateNumber: '京A12346', brand: '爱玛', vehicleType: 'TDN3', color: '白色', batteryType: '铅酸电池', batteryCapacity: 60, batteryStatus: '正常', status: '在租', isRented: true, purchaseDate: new Date('2023-07-20'), purchasePrice: 3599, purchaseSupplier: '爱玛科技' },
{ vehicleId: 'VEH0003', storeId: storeIds[1], frameNumber: 'FN0003', plateNumber: '京B23456', brand: '台铃', vehicleType: 'TL5', color: '银色', batteryType: '锂电池', batteryCapacity: 48, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2023-08-10'), purchasePrice: 4200, purchaseSupplier: '台铃集团' },
{ vehicleId: 'VEH0004', storeId: storeIds[1], frameNumber: 'FN0004', plateNumber: '京B23457', brand: '小牛', vehicleType: 'MQi2', color: '红色', batteryType: '锂电池', batteryCapacity: 48, batteryStatus: '老化', status: '维修中', isRented: false, purchaseDate: new Date('2023-09-01'), purchasePrice: 4999, purchaseSupplier: '小牛电动' },
{ vehicleId: 'VEH0005', storeId: storeIds[2], frameNumber: 'FN0005', plateNumber: '京C34567', brand: '雅迪', vehicleType: 'DT5', color: '蓝色', batteryType: '锂电池', batteryCapacity: 52, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2023-10-15'), purchasePrice: 4299, purchaseSupplier: '雅迪集团' },
{ vehicleId: 'VEH0006', storeId: storeIds[2], frameNumber: 'FN0006', plateNumber: '京C34568', brand: '绿源', vehicleType: 'LY6', color: '绿色', batteryType: '铅酸电池', batteryCapacity: 60, batteryStatus: '正常', status: '在租', isRented: true, purchaseDate: new Date('2023-11-01'), purchasePrice: 3699, purchaseSupplier: '绿源电动车' },
{ vehicleId: 'VEH0007', storeId: storeIds[3], frameNumber: 'FN0007', plateNumber: '京D45678', brand: '爱玛', vehicleType: 'TDN5', color: '黑色', batteryType: '锂电池', batteryCapacity: 48, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2024-01-10'), purchasePrice: 3899, purchaseSupplier: '爱玛科技' },
{ vehicleId: 'VEH0008', storeId: storeIds[3], frameNumber: 'FN0008', plateNumber: '京D45679', brand: '台铃', vehicleType: 'TL3', color: '白色', batteryType: '铅酸电池', batteryCapacity: 60, batteryStatus: '待更换', status: '待回收', isRented: false, purchaseDate: new Date('2023-05-20'), purchasePrice: 3299, purchaseSupplier: '台铃集团' },
{ vehicleId: 'VEH0009', storeId: storeIds[4], frameNumber: 'FN0009', plateNumber: '京E56789', brand: '小牛', vehicleType: 'MQi3', color: '灰色', batteryType: '锂电池', batteryCapacity: 52, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2024-02-15'), purchasePrice: 5199, purchaseSupplier: '小牛电动' },
{ vehicleId: 'VEH0010', storeId: storeIds[4], frameNumber: 'FN0010', plateNumber: '京E56790', brand: '雅迪', vehicleType: 'DT3', color: '红色', batteryType: '锂电池', batteryCapacity: 48, batteryStatus: '正常', status: '空闲', isRented: false, purchaseDate: new Date('2024-03-01'), purchasePrice: 3999, purchaseSupplier: '雅迪集团' },
];
const result = await Vehicle.insertMany(vehicles);
console.log(` 插入 ${result.length} 条车辆记录`);
return result;
}
async function seedCustomers() {
console.log('👤 插入客户数据...');
const customers = [
{ customerId: 'CUST001', name: '张三', phone: '13800138001', idCard: '110101199001011234', address: '北京市朝阳区', email: 'zhangsan@email.com', creditScore: 95, creditLevel: '优秀', accountStatus: '正常' },
{ customerId: 'CUST002', name: '李四', phone: '13800138002', idCard: '110102199203122345', address: '北京市海淀区', email: 'lisi@email.com', creditScore: 88, creditLevel: '良好', accountStatus: '正常' },
{ customerId: 'CUST003', name: '王五', phone: '13800138003', idCard: '110105198805051234', address: '北京市西城区', email: 'wangwu@email.com', creditScore: 92, creditLevel: '优秀', accountStatus: '正常' },
{ customerId: 'CUST004', name: '赵六', phone: '13800138004', idCard: '110106199107081234', address: '北京市东城区', email: 'zhaoliu@email.com', creditScore: 75, creditLevel: '一般', accountStatus: '正常' },
{ customerId: 'CUST005', name: '孙七', phone: '13800138005', idCard: '110107199306151234', address: '北京市丰台区', email: 'sunqi@email.com', creditScore: 80, creditLevel: '良好', accountStatus: '正常' },
{ customerId: 'CUST006', name: '周八', phone: '13800138006', idCard: '110108199501201234', address: '北京市朝阳区', email: 'zhouba@email.com', creditScore: 90, creditLevel: '优秀', accountStatus: '正常' },
{ customerId: 'CUST007', name: '吴九', phone: '13800138007', idCard: '110109198912301234', address: '北京市海淀区', email: 'wujiu@email.com', creditScore: 60, creditLevel: '较差', accountStatus: '冻结' },
{ customerId: 'CUST008', name: '郑十', phone: '13800138008', idCard: '110111199708101234', address: '北京市通州区', email: 'zhengshi@email.com', creditScore: 85, creditLevel: '良好', accountStatus: '正常' },
];
const result = await Customer.insertMany(customers);
console.log(` 插入 ${result.length} 条客户记录`);
return result;
}
async function seedOrders(customers, vehicles, stores) {
console.log('📋 插入订单数据...');
// Order 使用 customer 和 vehicle 的 ObjectId
// 注意: insertMany 不会触发 pre-save hook需要手动生成 orderNumber
const ordersData = [
{
orderNumber: 'ORD202603200001',
customer: customers[0]._id,
vehicle: vehicles[1]._id, // VEH0002 在租
startDate: new Date('2026-03-20'),
endDate: new Date('2026-03-27'),
status: '进行中',
rentalFee: 50,
deposit: 200,
totalAmount: 550,
paidAmount: 200,
paymentMethod: '微信',
},
{
orderNumber: 'ORD202603180002',
customer: customers[1]._id,
vehicle: vehicles[5]._id, // VEH0006 在租
startDate: new Date('2026-03-18'),
endDate: new Date('2026-03-28'),
status: '进行中',
rentalFee: 45,
deposit: 200,
totalAmount: 650,
paidAmount: 200,
paymentMethod: '支付宝',
},
{
orderNumber: 'ORD202603100002',
customer: customers[2]._id,
vehicle: vehicles[0]._id, // VEH0001 已完成
startDate: new Date('2026-03-10'),
endDate: new Date('2026-03-15'),
actualEndDate: new Date('2026-03-15'),
status: '已完成',
rentalFee: 50,
deposit: 200,
totalAmount: 450,
paidAmount: 450,
paymentMethod: '微信',
},
{
orderNumber: 'ORD202603050003',
customer: customers[3]._id,
vehicle: vehicles[2]._id,
startDate: new Date('2026-03-05'),
endDate: new Date('2026-03-10'),
actualEndDate: new Date('2026-03-12'), // 逾期2天
status: '逾期',
rentalFee: 50,
deposit: 200,
totalAmount: 600,
paidAmount: 200,
paymentMethod: '银行卡',
overdueDays: 2,
overdueFee: 50,
},
{
orderNumber: 'ORD202603010004',
customer: customers[4]._id,
vehicle: vehicles[6]._id,
startDate: new Date('2026-03-01'),
endDate: new Date('2026-03-03'),
actualEndDate: new Date('2026-03-03'),
status: '已完成',
rentalFee: 40,
deposit: 200,
totalAmount: 280,
paidAmount: 280,
paymentMethod: '现金',
},
];
const result = await Order.insertMany(ordersData);
console.log(` 插入 ${result.length} 条订单记录`);
return result;
}
async function seedPayments(orders) {
console.log('💰 插入财务数据...');
const payments = [
{ paymentId: 'PAY001', type: '收入', party: '张三', amount: 200, method: '微信', category: '其他', remark: '租车押金收取', createdAt: new Date('2026-03-20') },
{ paymentId: 'PAY002', type: '收入', party: '张三', amount: 550, method: '微信', category: '租金收入', remark: '租车7天租金', createdAt: new Date('2026-03-27') },
{ paymentId: 'PAY003', type: '收入', party: '李四', amount: 200, method: '支付宝', category: '其他', remark: '租车押金收取', createdAt: new Date('2026-03-18') },
{ paymentId: 'PAY004', type: '收入', party: '王五', amount: 450, method: '微信', category: '租金收入', remark: '租车5天完成', createdAt: new Date('2026-03-15') },
{ paymentId: 'PAY005', type: '支出', party: '张客户', amount: 200, method: '微信', category: '押金退还', remark: '王五订单押金退还', createdAt: new Date('2026-03-15') },
{ paymentId: 'PAY006', type: '支出', party: '维修员老李', amount: 300, method: '现金', category: '工资', remark: '3月维修工费', createdAt: new Date('2026-03-20') },
{ paymentId: 'PAY007', type: '支出', party: '房东王先生', amount: 5000, method: '银行卡', category: '房租', remark: '3月门店房租', createdAt: new Date('2026-03-01') },
{ paymentId: 'PAY008', type: '收入', party: '赵六', amount: 200, method: '银行卡', category: '其他', remark: '租车押金收取', createdAt: new Date('2026-03-05') },
];
const result = await Payment.insertMany(payments);
console.log(` 插入 ${result.length} 条财务记录`);
return result;
}
async function seedComplaints(customers, orders) {
console.log('📝 插入投诉数据...');
const complaints = [
{ complaintId: 'COMP001', customer: customers[0]._id, order: orders[0]._id, type: '车辆问题', content: '电动车刹车不灵,骑行存在安全隐患', status: '处理中', handler: '王店长' },
{ complaintId: 'COMP002', customer: customers[1]._id, order: orders[1]._id, type: '服务态度', content: '门店工作人员态度恶劣', status: '待处理', handler: '李店长' },
{ complaintId: 'COMP003', customer: customers[3]._id, order: orders[3]._id, type: '费用问题', content: '认为逾期费用计算不合理', status: '已解决', handler: '赵店长', response: '已减免逾期费用50元' },
];
const result = await Complaint.insertMany(complaints);
console.log(` 插入 ${result.length} 条投诉记录`);
return result;
}
async function seedApplications(stores) {
console.log('📄 插入申请数据...');
const applications = [
{ appId: 'APP001', store: stores[0]._id, storeName: '朝阳区总店', type: '促销活动', title: '五一假期租车优惠活动', content: '申请在五一假期期间推出租车8折优惠活动', status: '待审批' },
{ appId: 'APP002', store: stores[1]._id, storeName: '海淀区中关村店', type: '设备申请', title: '新增10辆电动车', content: '申请采购10辆雅迪DT3型号电动车用于扩充库存', status: '已通过', handler: '总部审批员' },
{ appId: 'APP003', store: stores[3]._id, storeName: '东城区王府井店', type: '注册申请', title: '门店重装开业申请', content: '门店装修完成,申请重新开业', status: '已拒绝', rejectReason: '消防验收未通过' },
];
const result = await Application.insertMany(applications);
console.log(` 插入 ${result.length} 条申请记录`);
return result;
}
async function seedDisputes(stores) {
console.log('⚖️ 插入争议数据...');
const disputes = [
{
disputeId: 'DIS001',
storeA: stores[0]._id,
storeAName: '朝阳区总店',
storeB: stores[1]._id,
storeBName: '海淀区中关村店',
type: '区域纠纷',
title: '客户跨区还车纠纷',
content: '客户在A店租车后跨区还至B店产生区域管理归属争议',
status: '待处理',
},
{
disputeId: 'DIS002',
storeA: stores[2]._id,
storeAName: '西城区金融街店',
storeB: stores[4]._id,
storeBName: '丰台区南站店',
type: '费用纠纷',
title: '订单费用分成争议',
content: '跨店订单的费用收入分成存在分歧',
status: '处理中',
handler: '总部调解员',
},
];
const result = await Dispute.insertMany(disputes);
console.log(` 插入 ${result.length} 条争议记录`);
return result;
}
async function main() {
try {
console.log('🚀 连接 MongoDB...\n');
await mongoose.connect(MONGO_URI);
console.log(` 已连接: ${MONGO_URI}\n`);
await clearAll();
const stores = await seedStores();
const vehicles = await seedVehicles(stores);
const customers = await seedCustomers();
const orders = await seedOrders(customers, vehicles, stores);
await seedPayments(orders);
await seedComplaints(customers, orders);
await seedApplications(stores);
await seedDisputes(stores);
console.log('\n✅ 数据填充完成!\n');
console.log('📊 各集合数据条数:');
for (const Model of COLLECTIONS) {
const count = await Model.countDocuments();
console.log(` ${Model.modelName}: ${count}`);
}
console.log('\n🕐 关闭连接...\n');
await mongoose.disconnect();
console.log('👋 完成!');
} catch (err) {
console.error('❌ 错误:', err.message);
await mongoose.disconnect();
process.exit(1);
}
}
main();