Mark-Lasfar
Fix Vercel deployment configuration
9acc8a2
// backend/scripts/seed.js
require('dotenv').config();
const mongoose = require('mongoose');
const bcrypt = require('bcryptjs');
// โœ… ุงุณุชูˆุฑุฏ ุงู„ู…ูˆุฏูŠู„ุงุช ู…ู† server.js
const { User, Product, Customer, Coupon, ShippingRate } = require('../server');
if (!process.env.MONGODB_URI) {
console.error('โŒ MONGODB_URI is not defined');
process.exit(1);
}
const MONGODB_URI = process.env.MONGODB_URI;
// ุงู„ู…ู†ุชุฌุงุช (ุจุฏูˆู† slug - ู‡ู†ุถูŠูู‡ ููŠ ุงู„ูƒูˆุฏ)
const products = [
{
name: "ุณุฌุงุฏ ุตูˆู ูุงุฎุฑ - ุจูŠุฌ",
slug: "ุณุฌุงุฏ-ุตูˆู-ูุงุฎุฑ-ุจูŠุฌ",
category: "carpet",
subcategory: "wool",
material: "ุตูˆู ุทุจูŠุนูŠ 100%",
size: "200x300 ุณู…",
color: "ุจูŠุฌ ูุงุชุญ",
price: 2500,
oldPrice: 3500,
quantity: 50,
imageUrl: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR47nEBR3-0a8nroyXdIhqcI_BJ-LPINhAPDw&s",
description: "ุณุฌุงุฏ ุตูˆู ุทุจูŠุนูŠ ูุงุฎุฑ ู…ุตู†ูˆุน ูŠุฏูˆูŠุงู‹",
features: ["ุตูˆู ุทุจูŠุนูŠ 100%", "ู…ู‚ุงูˆู… ู„ู„ุจู‚ุน", "ุณู‡ู„ ุงู„ุชู†ุธูŠู"],
tags: ["ุณุฌุงุฏ", "ุตูˆู", "ูุงุฎุฑ", "ุจูŠุฌ"],
isFeatured: true,
isNew: true,
discount: 28,
inStock: true,
rating: 4.8,
reviewCount: 15
},
{
name: "ุณุฌุงุฏ ุญุฑูŠุฑ - ุฑู…ุงุฏูŠ ุบุงู…ู‚",
slug: "ุณุฌุงุฏ-ุญุฑูŠุฑ-ุฑู…ุงุฏูŠ-ุบุงู…ู‚",
category: "carpet",
subcategory: "silk",
material: "ุญุฑูŠุฑ ุทุจูŠุนูŠ",
size: "160x230 ุณู…",
color: "ุฑู…ุงุฏูŠ ุบุงู…ู‚",
price: 4500,
oldPrice: 6000,
quantity: 30,
imageUrl: "https://cdn.arabsstock.com/uploads/images/336092/saudi-design-for-colorful-authentic-thumbnail-336092.webp",
description: "ุณุฌุงุฏ ุญุฑูŠุฑ ูุงุฎุฑ ุจุชุตู…ูŠู… ุนุตุฑูŠ",
features: ["ุญุฑูŠุฑ ุทุจูŠุนูŠ", "ุชุตู…ูŠู… ุนุตุฑูŠ", "ู„ู…ุนุฉ ุทุจูŠุนูŠุฉ"],
tags: ["ุณุฌุงุฏ", "ุญุฑูŠุฑ", "ุฑู…ุงุฏูŠ", "ูุงุฎุฑ"],
isFeatured: true,
isNew: false,
discount: 25,
inStock: true,
rating: 4.9,
reviewCount: 23
},
{
name: "ู…ูˆูƒูŠุช ู‚ุทูŠูุฉ - ุจูŠุฌ ูุงุชุญ",
slug: "ู…ูˆูƒูŠุช-ู‚ุทูŠูุฉ-ุจูŠุฌ-ูุงุชุญ",
category: "carpet",
subcategory: "velvet",
material: "ู‚ุทูŠูุฉ",
size: "250x350 ุณู…",
color: "ุจูŠุฌ ูุงุชุญ",
price: 1800,
oldPrice: 2200,
quantity: 100,
imageUrl: "https://cdn.arabsstock.com/uploads/images/255073/the-popular-saudi-heritage-of-thumbnail-255073.webp",
description: "ู…ูˆูƒูŠุช ู‚ุทูŠูุฉ ู†ุงุนู… ุฌุฏุงู‹",
features: ["ู‚ุทูŠูุฉ ุนุงู„ูŠุฉ ุงู„ุฌูˆุฏุฉ", "ู†ุงุนู… ุฌุฏุงู‹", "ู…ุถุงุฏ ู„ู„ุญุณุงุณูŠุฉ"],
tags: ["ู…ูˆูƒูŠุช", "ู‚ุทูŠูุฉ", "ุจูŠุฌ", "ุบุฑูุฉ ู†ูˆู…"],
isFeatured: false,
isNew: true,
discount: 18,
inStock: true,
rating: 4.5,
reviewCount: 8
},
{
name: "ุณุฌุงุฏ ุนุฑุจูŠ ุชู‚ู„ูŠุฏูŠ - ุฃุญู…ุฑ",
slug: "ุณุฌุงุฏ-ุนุฑุจูŠ-ุชู‚ู„ูŠุฏูŠ-ุฃุญู…ุฑ",
category: "carpet",
subcategory: "traditional",
material: "ุตูˆู + ู‚ุทู†",
size: "300x400 ุณู…",
color: "ุฃุญู…ุฑ",
price: 5800,
oldPrice: 7500,
quantity: 15,
imageUrl: "https://cdn.arabsstock.com/uploads/images/255057/traditional-handicraft-heritage-art-popular-thumbnail-255057.webp",
description: "ุณุฌุงุฏ ุนุฑุจูŠ ุชู‚ู„ูŠุฏูŠ ู…ุตู†ูˆุน ูŠุฏูˆูŠุงู‹",
features: ["ุตู†ุงุนุฉ ูŠุฏูˆูŠุฉ", "ู†ู‚ูˆุด ุฃุซุฑูŠุฉ", "ุฃู„ูˆุงู† ุทุจูŠุนูŠุฉ"],
tags: ["ุณุฌุงุฏ", "ุนุฑุจูŠ", "ุชู‚ู„ูŠุฏูŠ", "ุฃุญู…ุฑ"],
isFeatured: true,
isNew: false,
discount: 22,
inStock: true,
rating: 4.7,
reviewCount: 12
},
{
name: "ู‚ู…ุงุด ุณุชุงุฆุฑ - ูƒุชุงู†ูŠ ุจูŠุฌ",
slug: "ู‚ู…ุงุด-ุณุชุงุฆุฑ-ูƒุชุงู†ูŠ-ุจูŠุฌ",
category: "textile",
subcategory: "linen",
material: "ูƒุชุงู† ุทุจูŠุนูŠ",
size: "140 ุณู… ุนุฑุถ",
color: "ุจูŠุฌ ุทุจูŠุนูŠ",
price: 350,
oldPrice: 500,
quantity: 200,
imageUrl: "https://cdn.arabsstock.com/uploads/images/255046/the-popular-saudi-heritage-of-preview-255046.jpg",
description: "ู‚ู…ุงุด ุณุชุงุฆุฑ ูƒุชุงู†ูŠ ุทุจูŠุนูŠ",
features: ["ูƒุชุงู† ุทุจูŠุนูŠ", "ู‚ุงุจู„ ู„ู„ุชู†ูุณ", "ู…ุถุงุฏ ู„ู„ุจูƒุชูŠุฑูŠุง"],
tags: ["ู‚ู…ุงุด", "ุณุชุงุฆุฑ", "ูƒุชุงู†", "ุจูŠุฌ"],
isFeatured: false,
isNew: true,
discount: 30,
inStock: true,
rating: 4.6,
reviewCount: 7
},
{
name: "ู‚ู…ุงุด ุชู†ุฌูŠุฏ - ู…ุฎู…ู„ ุฃุฒุฑู‚",
slug: "ู‚ู…ุงุด-ุชู†ุฌูŠุฏ-ู…ุฎู…ู„-ุฃุฒุฑู‚",
category: "textile",
subcategory: "velvet",
material: "ู…ุฎู…ู„",
size: "150 ุณู… ุนุฑุถ",
color: "ุฃุฒุฑู‚ ุฏุงูƒู†",
price: 450,
oldPrice: 650,
quantity: 150,
imageUrl: "https://cdn.arabsstock.com/uploads/images/255050/popular-designs-for-colorful-authentic-preview-255050.jpg",
description: "ู‚ู…ุงุด ุชู†ุฌูŠุฏ ู…ุฎู…ู„ ูุงุฎุฑ",
features: ["ู…ุฎู…ู„ ุนุงู„ูŠ ุงู„ุฌูˆุฏุฉ", "ู„ู…ุนุฉ ุทุจูŠุนูŠุฉ", "ู…ู‚ุงูˆู… ู„ู„ุงู‡ุชุฑุงุก"],
tags: ["ู‚ู…ุงุด", "ุชู†ุฌูŠุฏ", "ู…ุฎู…ู„", "ุฃุฒุฑู‚"],
isFeatured: true,
isNew: false,
discount: 30,
inStock: true,
rating: 4.8,
reviewCount: 11
},
{
name: "ุณุฌุงุฏ ุตูˆู - ุจูŠุฌ ุบุงู…ู‚",
slug: "ุณุฌุงุฏ-ุตูˆู-ุจูŠุฌ-ุบุงู…ู‚",
category: "carpet",
subcategory: "wool",
material: "ุตูˆู ุทุจูŠุนูŠ",
size: "180x270 ุณู…",
color: "ุจูŠุฌ ุบุงู…ู‚",
price: 2200,
oldPrice: 3000,
quantity: 40,
imageUrl: "https://cdn.arabsstock.com/uploads/images/255042/traditional-handicraft-heritage-art-popular-designs-colorful.jpg",
description: "ุณุฌุงุฏ ุตูˆู ุทุจูŠุนูŠ ุจุชุตู…ูŠู… ูƒู„ุงุณูŠูƒูŠ",
features: ["ุตูˆู ุทุจูŠุนูŠ", "ุชุตู…ูŠู… ูƒู„ุงุณูŠูƒูŠ", "ู…ุชูŠู†"],
tags: ["ุณุฌุงุฏ", "ุตูˆู", "ูƒู„ุงุณูŠูƒูŠ", "ุจูŠุฌ"],
isFeatured: false,
isNew: false,
discount: 26,
inStock: true,
rating: 4.4,
reviewCount: 9
},
{
name: "ู‚ู…ุงุด ุชู†ุฌูŠุฏ - ู‚ุทูŠูุฉ ูˆุฑุฏูŠ",
slug: "ู‚ู…ุงุด-ุชู†ุฌูŠุฏ-ู‚ุทูŠูุฉ-ูˆุฑุฏูŠ",
category: "textile",
subcategory: "velvet",
material: "ู‚ุทูŠูุฉ",
size: "140 ุณู… ุนุฑุถ",
color: "ูˆุฑุฏูŠ ูุงุชุญ",
price: 380,
oldPrice: 550,
quantity: 120,
imageUrl: "https://cdn.arabsstock.com/uploads/images/336062/traditional-craft-art-saudi-design-authentic-colorful-arabic.jpg",
description: "ู‚ู…ุงุด ุชู†ุฌูŠุฏ ู‚ุทูŠูุฉ ู†ุงุนู…",
features: ["ู‚ุทูŠูุฉ ู†ุงุนู…ุฉ", "ุฃู„ูˆุงู† ุนุตุฑูŠุฉ", "ู…ู‚ุงูˆู… ู„ู„ุจู‚ุน"],
tags: ["ู‚ู…ุงุด", "ุชู†ุฌูŠุฏ", "ู‚ุทูŠูุฉ", "ูˆุฑุฏูŠ"],
isFeatured: false,
isNew: true,
discount: 30,
inStock: true,
rating: 4.7,
reviewCount: 6
}
];
// ุงู„ุนู…ู„ุงุก (30 ุนู…ูŠู„)
const customers = [];
const firstNames = ['ุฃุญู…ุฏ', 'ู…ุญู…ุฏ', 'ุนู„ูŠ', 'ุญุณู†', 'ุญุณูŠู†', 'ู…ุญู…ูˆุฏ', 'ุฅุจุฑุงู‡ูŠู…', 'ูŠูˆุณู', 'ุนู…ุฑ', 'ุฎุงู„ุฏ', 'ู…ุตุทูู‰', 'ุนุจุฏุงู„ู„ู‡', 'ูƒุฑูŠู…', 'ุทุงุฑู‚', 'ุณุงู…ูŠ'];
const lastNames = ['ุญุณู†', 'ุนู„ูŠ', 'ู…ุญู…ูˆุฏ', 'ุฅุจุฑุงู‡ูŠู…', 'ูŠูˆุณู', 'ุนู…ุฑ', 'ุฎุงู„ุฏ', 'ู…ุตุทูู‰', 'ุนุจุฏุงู„ู„ู‡', 'ูƒุฑูŠู…', 'ุทุงุฑู‚', 'ุณุงู…ูŠ', 'ูุงุฑูˆู‚', 'ู…ู…ุฏูˆุญ', 'ุนุงุทู'];
const cities = ['Cairo', 'Alexandria', 'Giza', 'Mansoura', 'Tanta', 'Port Said', 'Suez', 'Luxor', 'Aswan', 'Ismailia'];
for (let i = 0; i < 30; i++) {
const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
customers.push({
name: `${firstName} ${lastName}`,
phone: `010${Math.floor(Math.random() * 90000000) + 10000000}`,
address: `${Math.floor(Math.random() * 200) + 1} ุดุงุฑุน ${firstName}ุŒ ${cities[Math.floor(Math.random() * cities.length)]}`,
email: `${firstName}.${lastName}${Math.floor(Math.random() * 1000)}@example.com`,
registeredAt: new Date(Date.now() - Math.random() * 365 * 24 * 60 * 60 * 1000)
});
}
// ูƒูˆุจูˆู†ุงุช ุฎุตู…
const coupons = [
{ code: 'WELCOME10', discountType: 'percentage', discountValue: 10, minOrderAmount: 200, maxDiscount: 500, validFrom: new Date(), validTo: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000), usageLimit: 100, isActive: true },
{ code: 'SAVE20', discountType: 'percentage', discountValue: 20, minOrderAmount: 500, maxDiscount: 1000, validFrom: new Date(), validTo: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000), usageLimit: 50, isActive: true },
{ code: 'FLAT100', discountType: 'fixed', discountValue: 100, minOrderAmount: 1000, maxDiscount: 100, validFrom: new Date(), validTo: new Date(Date.now() + 90 * 24 * 60 * 60 * 1000), usageLimit: 30, isActive: true },
{ code: 'FREESHIP', discountType: 'percentage', discountValue: 0, minOrderAmount: 1000, maxDiscount: 0, validFrom: new Date(), validTo: new Date(Date.now() + 60 * 24 * 60 * 60 * 1000), usageLimit: 200, isActive: true },
{ code: 'SUMMER25', discountType: 'percentage', discountValue: 25, minOrderAmount: 800, maxDiscount: 1500, validFrom: new Date(), validTo: new Date(Date.now() + 120 * 24 * 60 * 60 * 1000), usageLimit: 40, isActive: true }
];
// ุฃุณุนุงุฑ ุงู„ุดุญู†
const shippingRates = [
{ city: 'Cairo', cost: 50, estimatedDays: 2 },
{ city: 'Alexandria', cost: 60, estimatedDays: 3 },
{ city: 'Giza', cost: 50, estimatedDays: 2 },
{ city: 'Mansoura', cost: 55, estimatedDays: 3 },
{ city: 'Tanta', cost: 55, estimatedDays: 3 },
{ city: 'Port Said', cost: 65, estimatedDays: 4 },
{ city: 'Suez', cost: 65, estimatedDays: 4 },
{ city: 'Luxor', cost: 80, estimatedDays: 5 },
{ city: 'Aswan', cost: 85, estimatedDays: 5 },
{ city: 'Ismailia', cost: 60, estimatedDays: 3 },
{ city: 'Other', cost: 100, estimatedDays: 7 }
];
async function seedDatabase() {
try {
console.log('๐Ÿ”Œ Connecting to MongoDB...');
await mongoose.connect(MONGODB_URI);
console.log('โœ… Connected to MongoDB');
console.log('๐Ÿ—‘๏ธ Clearing existing data...');
await Product.deleteMany({});
await Customer.deleteMany({});
await Coupon.deleteMany({});
await ShippingRate.deleteMany({});
await User.deleteMany({});
console.log('โœ… Cleared old data');
console.log('๐Ÿ‘‘ Creating admin user...');
const hashedPassword = await bcrypt.hash('admin123', 10);
await User.create({
username: 'admin',
email: 'admin@naseej.com',
password: hashedPassword,
role: 'admin',
phone: '01000000000'
});
console.log('โœ… Admin created (admin@naseej.com / admin123)');
console.log('๐Ÿ‘ฅ Creating customers...');
const createdCustomers = [];
for (const customer of customers) {
const hashedUserPassword = await bcrypt.hash('customer123', 10);
const user = await User.create({
username: customer.email.split('@')[0],
email: customer.email,
password: hashedUserPassword,
role: 'customer',
phone: customer.phone
});
const newCustomer = await Customer.create({
...customer,
userId: user._id
});
createdCustomers.push(newCustomer);
}
console.log(`โœ… ${createdCustomers.length} customers created`);
console.log('๐Ÿ“ฆ Creating products...');
const createdProducts = await Product.insertMany(products); // โœ… ุฃุณู‡ู„ ุจูƒุชูŠุฑ!
console.log(`โœ… ${createdProducts.length} products created`);
console.log('๐ŸŽซ Creating coupons...');
const createdCoupons = await Coupon.insertMany(coupons);
console.log(`โœ… ${createdCoupons.length} coupons created`);
console.log('๐Ÿšš Creating shipping rates...');
const createdShippingRates = await ShippingRate.insertMany(shippingRates);
console.log(`โœ… ${createdShippingRates.length} shipping rates created`);
console.log('\n๐ŸŽ‰ Seeding completed successfully!');
console.log('====================================');
console.log(` - Admin: admin@naseej.com / admin123`);
console.log(` - Customers: ${createdCustomers.length} (password: customer123)`);
console.log(` - Products: ${createdProducts.length}`);
console.log(` - Coupons: ${createdCoupons.length}`);
console.log(` - Shipping Rates: ${createdShippingRates.length}`);
console.log('====================================');
} catch (error) {
console.error('โŒ Seeding error:', error);
} finally {
await mongoose.disconnect();
console.log('๐Ÿ”Œ Disconnected from MongoDB');
}
}
seedDatabase();