270 lines
16 KiB
JavaScript
270 lines
16 KiB
JavaScript
/**
|
||
* 完整测试数据填充脚本
|
||
* 用法: 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();
|