389 lines
10 KiB
Python
389 lines
10 KiB
Python
import random
|
|
import uuid
|
|
from datetime import datetime, timedelta
|
|
|
|
from faker import Faker
|
|
from werkzeug.security import generate_password_hash
|
|
|
|
from app import create_app, db
|
|
from models import (
|
|
Cart,
|
|
CartItem,
|
|
Category,
|
|
CategoryEnum,
|
|
Order,
|
|
OrderItem,
|
|
Product,
|
|
ProductImage,
|
|
ProductLike,
|
|
Review,
|
|
User,
|
|
)
|
|
|
|
def create_seed_data():
|
|
"""Create dummy data for testing"""
|
|
fake = Faker()
|
|
|
|
print("🌱 Starting database seeding...")
|
|
|
|
|
|
print("👤 Checking/Creating admin user...")
|
|
admin = User.query.filter_by(email="admin@wearwell.com").first()
|
|
if not admin:
|
|
admin = User(
|
|
email="admin@wearwell.com",
|
|
password_hash=generate_password_hash("admin123"),
|
|
is_admin=True,
|
|
)
|
|
db.session.add(admin)
|
|
print("✅ Created admin user")
|
|
else:
|
|
print("⚠️ Admin user already exists, skipping...")
|
|
|
|
print("👥 Creating regular users...")
|
|
users = [admin] if admin else []
|
|
|
|
existing_users = User.query.count()
|
|
users_to_create = max(
|
|
0, 11 - existing_users
|
|
)
|
|
|
|
for i in range(users_to_create):
|
|
email = f"user{i + 1}@example.com"
|
|
|
|
|
|
if not User.query.filter_by(email=email).first():
|
|
user = User(
|
|
email=email,
|
|
password_hash=generate_password_hash(f"password{i + 1}"),
|
|
is_admin=False,
|
|
)
|
|
db.session.add(user)
|
|
users.append(user)
|
|
|
|
db.session.commit()
|
|
|
|
print("🏷️ Creating categories...")
|
|
categories = []
|
|
|
|
for cat_name in CategoryEnum.ALL:
|
|
category = Category.query.filter_by(name=cat_name).first()
|
|
if not category:
|
|
category = Category(name=cat_name)
|
|
db.session.add(category)
|
|
categories.append(category)
|
|
|
|
db.session.commit()
|
|
|
|
print("👕 Creating products...")
|
|
|
|
existing_products_count = Product.query.count()
|
|
products_to_create = max(0, 50 - existing_products_count)
|
|
|
|
if products_to_create > 0:
|
|
clothing_brands = [
|
|
"Nike",
|
|
"Adidas",
|
|
"Levi's",
|
|
"H&M",
|
|
"Zara",
|
|
"Uniqlo",
|
|
"Gap",
|
|
"Puma",
|
|
"Under Armour",
|
|
"Calvin Klein",
|
|
]
|
|
colors = [
|
|
"Black",
|
|
"White",
|
|
"Blue",
|
|
"Red",
|
|
"Green",
|
|
"Gray",
|
|
"Navy",
|
|
"Brown",
|
|
"Beige",
|
|
"Maroon",
|
|
]
|
|
materials = [
|
|
"Cotton",
|
|
"Polyester",
|
|
"Denim",
|
|
"Wool",
|
|
"Linen",
|
|
"Silk",
|
|
"Leather",
|
|
"Nylon",
|
|
"Rayon",
|
|
"Spandex",
|
|
]
|
|
product_types = [
|
|
"T-Shirt",
|
|
"Shirt",
|
|
"Jeans",
|
|
"Pants",
|
|
"Jacket",
|
|
"Hoodie",
|
|
"Sweater",
|
|
"Shorts",
|
|
"Dress",
|
|
]
|
|
|
|
existing_products = Product.query.all()
|
|
products = existing_products.copy()
|
|
|
|
existing_skus = {p.sku for p in existing_products if p.sku}
|
|
new_skus = set()
|
|
|
|
for i in range(products_to_create):
|
|
while True:
|
|
sku = f"SKU-{uuid.uuid4().hex[:8].upper()}"
|
|
if sku not in existing_skus and sku not in new_skus:
|
|
new_skus.add(sku)
|
|
break
|
|
|
|
category = random.choice(categories)
|
|
price = round(random.uniform(15, 150), 2)
|
|
stock = random.randint(0, 100)
|
|
|
|
product = Product(
|
|
name=f"{random.choice(product_types)} - {fake.word().title()}",
|
|
description=fake.paragraph(nb_sentences=3),
|
|
price=price,
|
|
stock=stock,
|
|
color=random.choice(colors),
|
|
size=random.choice(["XS", "S", "M", "L", "XL", "XXL"]),
|
|
material=random.choice(materials),
|
|
company=random.choice(clothing_brands),
|
|
sku=sku,
|
|
weight=round(random.uniform(0.1, 2.0), 2),
|
|
dimensions=f"{
|
|
random.randint(
|
|
30,
|
|
60)}x{
|
|
random.randint(
|
|
20,
|
|
40)}x{
|
|
random.randint(
|
|
2,
|
|
10)} cm",
|
|
category_id=category.id,
|
|
)
|
|
db.session.add(product)
|
|
products.append(product)
|
|
|
|
db.session.commit()
|
|
print(f"✅ Created {products_to_create} new products")
|
|
else:
|
|
products = Product.query.all()
|
|
print(f"⚠️ Already have {existing_products_count} products, skipping...")
|
|
|
|
print("🖼️ Creating product images...")
|
|
new_products = [p for p in products if not p.images]
|
|
|
|
for product in new_products:
|
|
num_images = random.randint(1, 4)
|
|
for j in range(num_images):
|
|
image = ProductImage(
|
|
product_id=product.id,
|
|
filename=f"product_{product.id}_img_{j + 1}.jpg",
|
|
is_primary=(j == 0),
|
|
display_order=j,
|
|
)
|
|
db.session.add(image)
|
|
|
|
db.session.commit()
|
|
|
|
existing_reviews = Review.query.count()
|
|
if existing_reviews < 100:
|
|
print("⭐ Creating reviews...")
|
|
products_without_reviews = [p for p in products if not p.reviews]
|
|
products_to_review = random.sample(
|
|
products_without_reviews, min(30, len(products_without_reviews))
|
|
)
|
|
|
|
for product in products_to_review:
|
|
num_reviews = random.randint(1, 8)
|
|
for _ in range(num_reviews):
|
|
user = random.choice(users[1:]) if len(users) > 1 else users[0]
|
|
review = Review(
|
|
product_id=product.id,
|
|
user_id=user.id,
|
|
rating=random.randint(1, 5),
|
|
title=fake.sentence(),
|
|
comment=fake.paragraph(),
|
|
is_verified_purchase=random.choice([True, False]),
|
|
created_at=fake.date_time_between(
|
|
start_date="-1y", end_date="now"),
|
|
)
|
|
db.session.add(review)
|
|
|
|
db.session.commit()
|
|
print(f"✅ Created {Review.query.count() - existing_reviews} new reviews")
|
|
else:
|
|
print(f"⚠️ Already have {existing_reviews} reviews, skipping...")
|
|
|
|
print("🛒 Creating carts...")
|
|
users_without_carts = [u for u in users if not u.cart]
|
|
|
|
for user in users_without_carts[:5]:
|
|
cart = Cart(user_id=user.id)
|
|
db.session.add(cart)
|
|
db.session.flush()
|
|
|
|
num_items = random.randint(1, 5)
|
|
for _ in range(num_items):
|
|
product = random.choice(products)
|
|
cart_item = CartItem(
|
|
cart_id=cart.id,
|
|
product_id=product.id,
|
|
quantity=random.randint(1, 3),
|
|
selected_size=product.size,
|
|
selected_color=product.color,
|
|
)
|
|
db.session.add(cart_item)
|
|
|
|
db.session.commit()
|
|
|
|
existing_orders = Order.query.count()
|
|
if existing_orders < 15:
|
|
print("📦 Creating orders...")
|
|
order_statuses = ["pending", "processing",
|
|
"shipped", "delivered", "cancelled"]
|
|
|
|
orders_to_create = 15 - existing_orders
|
|
for i in range(orders_to_create):
|
|
user = random.choice(users)
|
|
order = Order(
|
|
user_id=user.id,
|
|
status=random.choice(order_statuses),
|
|
created_at=fake.date_time_between(start_date="-6m", end_date="now"),
|
|
)
|
|
db.session.add(order)
|
|
db.session.flush()
|
|
|
|
num_items = random.randint(1, 5)
|
|
|
|
for _ in range(num_items):
|
|
product = random.choice(products)
|
|
quantity = random.randint(1, 3)
|
|
price = product.price
|
|
|
|
order_item = OrderItem(
|
|
order_id=order.id,
|
|
product_id=product.id,
|
|
quantity=quantity,
|
|
price_at_purchase=price,
|
|
selected_size=product.size,
|
|
selected_color=product.color,
|
|
)
|
|
db.session.add(order_item)
|
|
|
|
db.session.commit()
|
|
print(f"✅ Created {orders_to_create} new orders")
|
|
else:
|
|
print(f"⚠️ Already have {existing_orders} orders, skipping...")
|
|
|
|
print("❤️ Creating product likes...")
|
|
existing_likes = ProductLike.query.count()
|
|
|
|
if existing_likes < 50:
|
|
products_to_like = random.sample(products, min(20, len(products)))
|
|
likes_created = 0
|
|
|
|
for product in products_to_like:
|
|
|
|
available_users = [u for u in users if u.id != 1]
|
|
num_users_to_like = min(random.randint(3, 10), len(available_users))
|
|
users_to_like = random.sample(available_users, num_users_to_like)
|
|
|
|
for user in users_to_like:
|
|
|
|
existing_like = ProductLike.query.filter_by(
|
|
product_id=product.id, user_id=user.id
|
|
).first()
|
|
|
|
if not existing_like:
|
|
like = ProductLike(
|
|
product_id=product.id,
|
|
user_id=user.id,
|
|
is_like=random.choice([True, False]),
|
|
created_at=fake.date_time_between(
|
|
start_date="-3m", end_date="now"
|
|
),
|
|
)
|
|
db.session.add(like)
|
|
likes_created += 1
|
|
|
|
db.session.commit()
|
|
print(f"✅ Created {likes_created} new likes")
|
|
else:
|
|
print(f"⚠️ Already have {existing_likes} likes, skipping...")
|
|
|
|
print("\n" + "=" * 50)
|
|
print("✅ DATABASE SEEDING COMPLETED SUCCESSFULLY!")
|
|
print("=" * 50)
|
|
print(f"\n📊 FINAL COUNTS:")
|
|
print(f" 👥 Users: {User.query.count()}")
|
|
print(f" 🏷️ Categories: {Category.query.count()}")
|
|
print(f" 👕 Products: {Product.query.count()}")
|
|
print(f" 🖼️ Product Images: {ProductImage.query.count()}")
|
|
print(f" ⭐ Reviews: {Review.query.count()}")
|
|
print(f" 🛒 Carts: {Cart.query.count()}")
|
|
print(f" 📦 Orders: {Order.query.count()}")
|
|
print(f" ❤️ Likes: {ProductLike.query.count()}")
|
|
|
|
print("\n🔑 LOGIN CREDENTIALS:")
|
|
print(" 👑 Admin:")
|
|
print(" Email: admin@wearwell.com")
|
|
print(" Password: admin123")
|
|
print("\n 👤 Test Users (10 available):")
|
|
print(" Email: user1@example.com")
|
|
print(" Password: password1")
|
|
print(" Email: user2@example.com")
|
|
print(" Password: password2")
|
|
print(" ... and 8 more users (user3@example.com to user10@example.com)")
|
|
|
|
print("\n💡 TIPS:")
|
|
print(" • Run this script multiple times to add more data")
|
|
print(" • Data won't duplicate (checks for existing records)")
|
|
print(" • To start fresh, clear your database first")
|
|
|
|
|
|
def clear_and_seed():
|
|
"""Clear all data and seed fresh"""
|
|
print("⚠️ WARNING: This will delete ALL data from the database!")
|
|
response = input("Are you sure? Type 'YES' to continue: ")
|
|
|
|
if response != "YES":
|
|
print("❌ Operation cancelled")
|
|
return
|
|
|
|
print("🗑️ Clearing database...")
|
|
|
|
ProductLike.query.delete()
|
|
OrderItem.query.delete()
|
|
Order.query.delete()
|
|
CartItem.query.delete()
|
|
Cart.query.delete()
|
|
Review.query.delete()
|
|
ProductImage.query.delete()
|
|
Product.query.delete()
|
|
Category.query.delete()
|
|
User.query.delete()
|
|
|
|
db.session.commit()
|
|
print("✅ Database cleared!")
|
|
|
|
create_seed_data()
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
app = create_app()
|
|
with app.app_context():
|
|
if len(sys.argv) > 1 and sys.argv[1] == "--fresh":
|
|
clear_and_seed()
|
|
else:
|
|
create_seed_data()
|