264 lines
6.9 KiB
JavaScript
264 lines
6.9 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Script to generate bulk test data for the webstore database
|
|
* Usage: node scripts/generate-test-data.js [options]
|
|
*
|
|
* Options:
|
|
* --products N Generate N additional products (default: 10)
|
|
* --orders N Generate N test orders (default: 5)
|
|
* --reset Delete all data before seeding (careful!)
|
|
*/
|
|
|
|
require("dotenv").config({ path: ".env" });
|
|
|
|
const { PrismaClient } = require("@prisma/client");
|
|
const bcryptjs = require("bcryptjs");
|
|
|
|
const prisma = new PrismaClient();
|
|
|
|
// Parse command line arguments
|
|
const args = process.argv.slice(2);
|
|
const options = {
|
|
productsCount: 10,
|
|
ordersCount: 5,
|
|
shouldReset: false
|
|
};
|
|
|
|
for (let i = 0; i < args.length; i++) {
|
|
if (args[i] === "--products" && args[i + 1]) {
|
|
options.productsCount = parseInt(args[i + 1], 10);
|
|
i++;
|
|
} else if (args[i] === "--orders" && args[i + 1]) {
|
|
options.ordersCount = parseInt(args[i + 1], 10);
|
|
i++;
|
|
} else if (args[i] === "--reset") {
|
|
options.shouldReset = true;
|
|
}
|
|
}
|
|
|
|
const productNames = [
|
|
"Premium Leather Boots",
|
|
"Summer Canvas Shoes",
|
|
"Minimalist Sneakers",
|
|
"Casual Loafers",
|
|
"Running Shoes Pro",
|
|
"Hiking Boots",
|
|
"Beach Sandals",
|
|
"Formal Dress Shoes",
|
|
"Winter Snow Boots",
|
|
"Slip-on Comfort Shoes",
|
|
"Designer Heels",
|
|
"Waterproof Outdoor Boots",
|
|
"Lightweight Mesh Runners",
|
|
"Classic Oxfords",
|
|
"Athletic Training Shoes"
|
|
];
|
|
|
|
const descriptions = [
|
|
"Premium quality with exceptional comfort",
|
|
"Perfect for everyday wear and activities",
|
|
"Stylish design with modern aesthetics",
|
|
"Durable materials built to last",
|
|
"Eco-friendly sustainable production",
|
|
"Handcrafted with attention to detail",
|
|
"Weather-resistant and waterproof",
|
|
"Ergonomic design for all-day comfort",
|
|
"Available in multiple colors",
|
|
"Perfect for professional environments"
|
|
];
|
|
|
|
function generateRandomPrice() {
|
|
return (Math.floor(Math.random() * 20) + 5).toString() + "990.00";
|
|
}
|
|
|
|
function generateRandomStock() {
|
|
return Math.floor(Math.random() * 50) + 5;
|
|
}
|
|
|
|
function getRandomElement(arr) {
|
|
return arr[Math.floor(Math.random() * arr.length)];
|
|
}
|
|
|
|
async function resetDatabase() {
|
|
console.log("⚠️ Resetting database...");
|
|
try {
|
|
// Delete in order of dependencies
|
|
await prisma.orderItem.deleteMany({});
|
|
await prisma.order.deleteMany({});
|
|
await prisma.product.deleteMany({});
|
|
await prisma.category.deleteMany({});
|
|
await prisma.user.deleteMany({});
|
|
console.log("✓ Database reset completed");
|
|
} catch (error) {
|
|
console.error("Error resetting database:", error.message);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
async function seedInitialData() {
|
|
console.log("Seeding initial categories...");
|
|
|
|
const categories = [
|
|
{ name: "Shoes", slug: "shoes" },
|
|
{ name: "Bags", slug: "bags" },
|
|
{ name: "Accessories", slug: "accessories" },
|
|
{ name: "Clothing", slug: "clothing" },
|
|
{ name: "Electronics", slug: "electronics" }
|
|
];
|
|
|
|
for (const category of categories) {
|
|
await prisma.category.upsert({
|
|
where: { slug: category.slug },
|
|
update: {},
|
|
create: category
|
|
});
|
|
}
|
|
|
|
console.log("✓ Categories seeded");
|
|
}
|
|
|
|
async function generateProducts(count) {
|
|
console.log(`\nGenerating ${count} additional products...`);
|
|
|
|
const categories = await prisma.category.findMany();
|
|
const generatedProducts = [];
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
const category = getRandomElement(categories);
|
|
const name = `${getRandomElement(productNames)} ${i + 1}`;
|
|
|
|
try {
|
|
const product = await prisma.product.create({
|
|
data: {
|
|
name,
|
|
description: getRandomElement(descriptions),
|
|
price: generateRandomPrice(),
|
|
stock: generateRandomStock(),
|
|
categoryId: category.id,
|
|
imageUrl: `/images/placeholder-${i + 1}.jpg`
|
|
}
|
|
});
|
|
generatedProducts.push(product);
|
|
|
|
if ((i + 1) % 5 === 0) {
|
|
process.stdout.write(`\r Progress: ${i + 1}/${count} products`);
|
|
}
|
|
} catch (error) {
|
|
if (!error.message.includes("Unique constraint failed")) {
|
|
console.error(`\nError creating product: ${error.message}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
console.log(`\r✓ Generated ${generatedProducts.length} products`);
|
|
return generatedProducts;
|
|
}
|
|
|
|
async function generateTestUsers(count = 5) {
|
|
console.log(`\nGenerating ${count} test users...`);
|
|
|
|
const users = [];
|
|
for (let i = 1; i <= count; i++) {
|
|
const email = `user${i}@test.com`;
|
|
const passwordHash = await bcryptjs.hash("password123", 10);
|
|
|
|
try {
|
|
const user = await prisma.user.upsert({
|
|
where: { email },
|
|
update: {},
|
|
create: {
|
|
name: `Test User ${i}`,
|
|
email,
|
|
passwordHash
|
|
}
|
|
});
|
|
users.push(user);
|
|
} catch (error) {
|
|
console.error(`Error creating user: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
console.log(`✓ Generated ${users.length} test users`);
|
|
return users;
|
|
}
|
|
|
|
async function generateOrders(count) {
|
|
console.log(`\nGenerating ${count} test orders...`);
|
|
|
|
const products = await prisma.product.findMany({ take: 20 });
|
|
const createdOrders = [];
|
|
|
|
for (let i = 0; i < count; i++) {
|
|
try {
|
|
const itemsCount = Math.floor(Math.random() * 3) + 1;
|
|
const items = [];
|
|
let totalPrice = 0;
|
|
|
|
for (let j = 0; j < itemsCount; j++) {
|
|
const product = getRandomElement(products);
|
|
const quantity = Math.floor(Math.random() * 3) + 1;
|
|
items.push({
|
|
productId: product.id,
|
|
quantity,
|
|
unitPrice: product.price
|
|
});
|
|
totalPrice += parseFloat(product.price) * quantity;
|
|
}
|
|
|
|
const order = await prisma.order.create({
|
|
data: {
|
|
customerName: `Customer ${i + 1}`,
|
|
customerEmail: `customer${i + 1}@example.com`,
|
|
totalPrice: totalPrice.toFixed(2),
|
|
items: {
|
|
create: items
|
|
}
|
|
},
|
|
include: {
|
|
items: true
|
|
}
|
|
});
|
|
|
|
createdOrders.push(order);
|
|
|
|
if ((i + 1) % 2 === 0) {
|
|
process.stdout.write(`\r Progress: ${i + 1}/${count} orders`);
|
|
}
|
|
} catch (error) {
|
|
console.error(`\nError creating order: ${error.message}`);
|
|
}
|
|
}
|
|
|
|
console.log(`\r✓ Generated ${createdOrders.length} orders`);
|
|
return createdOrders;
|
|
}
|
|
|
|
async function main() {
|
|
console.log("🚀 Test Data Generator for Webstore\n");
|
|
console.log("Options:");
|
|
console.log(` Products to generate: ${options.productsCount}`);
|
|
console.log(` Orders to generate: ${options.ordersCount}`);
|
|
console.log(` Reset database first: ${options.shouldReset ? "YES" : "NO"}\n`);
|
|
|
|
try {
|
|
if (options.shouldReset) {
|
|
await resetDatabase();
|
|
}
|
|
|
|
await seedInitialData();
|
|
await generateTestUsers(5);
|
|
await generateProducts(options.productsCount);
|
|
await generateOrders(options.ordersCount);
|
|
|
|
console.log("\n✨ Test data generation completed successfully!");
|
|
} catch (error) {
|
|
console.error("\n❌ Error during data generation:", error.message);
|
|
process.exit(1);
|
|
} finally {
|
|
await prisma.$disconnect();
|
|
}
|
|
}
|
|
|
|
main();
|