ifixkart-backend/Backend/generate_mock_migration.py

345 lines
17 KiB
Python

import os
import zipfile
import openpyxl
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
def create_mock_png():
# 67-byte 1x1 transparent PNG file binary
return (
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01'
b'\x08\x06\x00\x00\x00\x1f\x15c4\x00\x00\x00\rIDATx\x9cc`\x00\x01\x00'
b'\x00\xff\xff\x03\x00\x00\x06\x00\x05\x57\xbf\xab\xcc\x00\x00\x00\x00'
b'IEND\xaeB`\x82'
)
def main():
print("Starting generation of mock migration catalog dataset...")
# Create target directories
output_dir = "migration_data"
temp_media_dir = "temp_media_folders"
os.makedirs(output_dir, exist_ok=True)
os.makedirs(temp_media_dir, exist_ok=True)
# 1. NEW CATEGORIES DEFINITION
# Final 10 categories mapping
categories_info = {
# Category Name: (Parent Category, Is Parent Feature)
"Laptop Accessories": ("", "no"),
"Laptop Batteries": ("Laptop Accessories", "no"),
"Laptop Keyboards": ("Laptop Accessories", "no"),
"Laptop Screen Protectors": ("Laptop Accessories", "no"),
"Tablets & iPads": ("", "yes"),
"Gaming Accessories": ("", "yes"),
"Refurbished Phones": ("", "yes"),
"Power Banks": ("", "no"),
"USB Cables & Adapters": ("", "no"),
"Wireless Chargers": ("", "no"),
}
# 2. BRANDS & PRODUCTS DEFINTION
# 4 Brands with multiple device types: lenovo, hp, dell, realme
brands_data = {
"Lenovo": {
"device_types": ["laptop", "tablet", "mobile"],
"products": [
# (Name, Device Type, Series, Model, Base Price, Category)
("Lenovo ThinkPad X1 Carbon", "laptop", "ThinkPad Series", "ThinkPad X1 Carbon Gen 11", 125000, "Laptop Accessories"),
("Lenovo IdeaPad Slim 5", "laptop", "IdeaPad Series", "IdeaPad Slim 5 14IRL8", 65000, "Laptop Accessories"),
("Lenovo Legion Pro 7i", "laptop", "Legion Series", "Legion Pro 7i Gen 8", 185000, "Laptop Accessories"),
("Lenovo Yoga Book 9i", "laptop", "Yoga Series", "Yoga Book 9i Dual Screen", 220000, "Laptop Accessories"),
("Lenovo Tab P12 Pro", "tablet", "Tab P Series", "Lenovo Tab P12 Pro Wi-Fi", 45000, "Tablets & iPads"),
("Lenovo Tab M10 Plus", "tablet", "Tab M Series", "Lenovo Tab M10 Plus Gen 3", 18000, "Tablets & iPads"),
("Lenovo Tab K11", "tablet", "Tab K Series", "Lenovo Tab K11 Pro LTE", 22000, "Tablets & iPads"),
("Lenovo Legion Phone Duel 2", "mobile", "Legion Phone Series", "Legion Phone Duel 2 5G", 55000, "Refurbished Phones"),
("Lenovo K15 Note", "mobile", "K-Series", "Lenovo K15 Note 4G", 12000, "Refurbished Phones"),
("Lenovo Vibe K6", "mobile", "Vibe Series", "Lenovo Vibe K6 Power", 9000, "Refurbished Phones")
]
},
"HP": {
"device_types": ["laptop", "tablet"],
"products": [
("HP Pavilion 15", "laptop", "Pavilion Series", "HP Pavilion 15-eg3000", 58000, "Laptop Accessories"),
("HP Envy x360", "laptop", "Envy Series", "HP Envy x360 15-fe0000", 82000, "Laptop Accessories"),
("HP Spectre x360", "laptop", "Spectre Series", "HP Spectre x360 14-ef0000", 145000, "Laptop Accessories"),
("HP Omen 16", "laptop", "Omen Series", "HP Omen 16-wf0000", 120000, "Laptop Accessories"),
("HP EliteBook 840", "laptop", "EliteBook Series", "HP EliteBook 840 G10", 105000, "Laptop Accessories"),
("HP Chromebook 14", "laptop", "Chromebook Series", "HP Chromebook 14a-na0000", 25000, "Laptop Accessories"),
("HP Elite x2 G8", "tablet", "Elite x2 Series", "HP Elite x2 G8 Tablet", 95000, "Tablets & iPads"),
("HP Pro Slate 12", "tablet", "Pro Slate Series", "HP Pro Slate 12 WiFi", 35000, "Tablets & iPads"),
("HP Envy x2 Tablet", "tablet", "Envy x2 Series", "HP Envy x2 12-g000", 65000, "Tablets & iPads"),
("HP Pro x2 612", "tablet", "Pro x2 Series", "HP Pro x2 612 G2", 48000, "Tablets & iPads")
]
},
"Dell": {
"device_types": ["laptop", "tablet"],
"products": [
("Dell Inspiron 15", "laptop", "Inspiron Series", "Dell Inspiron 15 3530", 52000, "Laptop Accessories"),
("Dell XPS 13 Plus", "laptop", "XPS Series", "Dell XPS 13 Plus 9320", 165000, "Laptop Accessories"),
("Dell Latitude 5440", "laptop", "Latitude Series", "Dell Latitude 5440 Business", 90000, "Laptop Accessories"),
("Dell Precision 5570", "laptop", "Precision Series", "Dell Precision 5570 Mobile Workstation", 210000, "Laptop Accessories"),
("Dell Vostro 3520", "laptop", "Vostro Series", "Dell Vostro 3520 15.6", 42000, "Laptop Accessories"),
("Dell Alienware m16", "laptop", "Alienware Series", "Alienware m16 R1 Gaming", 240000, "Laptop Accessories"),
("Dell Venue 11 Pro", "tablet", "Venue Series", "Dell Venue 11 Pro 7140", 30000, "Tablets & iPads"),
("Dell Latitude 7220 Rugged", "tablet", "Latitude Tablet Series", "Dell Latitude 7220 Rugged Extreme", 150000, "Tablets & iPads"),
("Dell XPS 12 Tablet", "tablet", "XPS Tablet Series", "Dell XPS 12 9250 2-in-1", 70000, "Tablets & iPads"),
("Dell Venue 8 Pro", "tablet", "Venue Series", "Dell Venue 8 Pro 5855", 15000, "Tablets & iPads")
]
},
"Realme": {
"device_types": ["mobile", "tablet"],
"products": [
("Realme GT 6", "mobile", "GT Series", "Realme GT 6 5G", 42000, "Refurbished Phones"),
("Realme Narzo 70 Pro", "mobile", "Narzo Series", "Realme Narzo 70 Pro 5G", 22000, "Refurbished Phones"),
("Realme C65", "mobile", "C Series", "Realme C65 5G", 11000, "Refurbished Phones"),
("Realme 12 Pro Plus", "mobile", "12 Pro Series", "Realme 12 Pro+ 5G", 32000, "Refurbished Phones"),
("Realme GT Neo 6", "mobile", "GT Series", "Realme GT Neo 6 SE", 29000, "Refurbished Phones"),
("Realme Narzo N53", "mobile", "Narzo Series", "Realme Narzo N53 4G", 9500, "Refurbished Phones"),
("Realme Pad 2", "tablet", "Pad Series", "Realme Pad 2 LTE", 20000, "Tablets & iPads"),
("Realme Pad Mini", "tablet", "Pad Mini Series", "Realme Pad Mini WiFi", 12000, "Tablets & iPads"),
("Realme Pad Slim", "tablet", "Pad Series", "Realme Pad Slim LTE", 16000, "Tablets & iPads"),
("Realme Pad Air", "tablet", "Pad Air Series", "Realme Pad Air WiFi", 18000, "Tablets & iPads")
]
}
}
# 10 Miscellaneous Category-Specific Products
category_products = [
# (Name, Brand, Device Type, Series, Model, Base Price, Category)
("Lenovo Power Bank 20000mAh", "Lenovo", "mobile", "Vibe Series", "PB-20K", 1800, "Power Banks"),
("Realme Power Bank 2", "Realme", "mobile", "C Series", "Realme PB2 10K", 1200, "Power Banks"),
("HP USB-C Fast Cable", "HP", "laptop", "Pavilion Series", "HP-CABLE-3A", 650, "USB Cables & Adapters"),
("Dell Braided USB-C Cable", "Dell", "laptop", "Inspiron Series", "Dell-BRD-5A", 850, "USB Cables & Adapters"),
("Realme Air Wireless Charger", "Realme", "mobile", "GT Series", "Realme WLS-15W", 1999, "Wireless Chargers"),
("Lenovo Smart Wireless Pad", "Lenovo", "mobile", "Edge Series", "Lenovo WLS-20W", 2499, "Wireless Chargers"),
("HP Replacement Battery Envy", "HP", "laptop", "Enens", "HP-BAT-ENVY", 4500, "Laptop Batteries"),
("Dell Replacement Battery XPS", "Dell", "laptop", "XPS Series", "Dell-BAT-XPS13", 5500, "Laptop Batteries"),
("Lenovo Stylus Pen Tab", "Lenovo", "tablet", "Tab P Series", "Lenovo Active Pen 3", 3500, "Tablets & iPads"),
("Realme Pencil Pro", "Realme", "tablet", "Pad Series", "Realme Pencil 2", 2999, "Tablets & iPads")
]
# Assemble all 50 products list
all_products = []
# 40 Brand-linked products
for brand_name, brand_meta in brands_data.items():
for p in brand_meta["products"]:
all_products.append({
"name": p[0],
"brand": brand_name,
"device_type": p[1],
"device_series": p[2],
"device_model": p[3],
"price": p[4],
"category": p[5]
})
# 10 Category-specific products
for p in category_products:
all_products.append({
"name": p[0],
"brand": p[1],
"device_type": p[2],
"device_series": p[3],
"device_model": p[4],
"price": p[5],
"category": p[6]
})
# Prepare Image ZIP package list
media_keys_to_zip = []
# 3. CONSTRUCT 200 ROWS FOR EXCEL
excel_rows = []
# Attribute variants setup
color_variants = ["Midnight Black", "Arctic White", "Slate Grey", "Ocean Blue"]
storage_variants = ["8GB/128GB", "12GB/256GB", "16GB/512GB", "16GB/1TB"]
pack_variants = ["Single Pack", "2-Pack Bundle", "3-Pack Value", "Family 5-Pack"]
for prod_idx, p in enumerate(all_products):
# Media key matching directory name in ZIP
media_key = f"{p['brand']}-{p['device_model'].replace(' ', '-').replace('/', '-')}".replace('+', '-Plus')
media_keys_to_zip.append(media_key)
# Product type flag
is_accessory = p["category"] in ("Power Banks", "USB Cables & Adapters", "Wireless Chargers", "Laptop Batteries")
# Build 4 variants for each product
for var_idx in range(4):
# Price multipliers: Arctic White = +0%, Grey = +5%, Ocean Blue = +10%, Black = +12%
# Storage multipliers: 128GB = 1.0, 256GB = 1.15, 512GB = 1.30, 1TB = 1.50
price_multiplier = 1.0
variant_name = p["name"]
sku_suffix = ""
# Attributes mapping
attr_color = color_variants[var_idx]
attr_storage = ""
attr_pack = ""
if is_accessory:
# Accessories vary by Pack Size
attr_pack = pack_variants[var_idx]
price_multiplier = [1.0, 1.8, 2.5, 3.8][var_idx]
sku_suffix = f"-PK{var_idx+1}"
variant_name = f"{p['name']} ({attr_color} - {attr_pack})"
else:
# Electronics vary by Storage/RAM
attr_storage = storage_variants[var_idx]
price_multiplier = [1.0, 1.15, 1.30, 1.55][var_idx]
sku_suffix = f"-{attr_storage.replace('/', '-')}"
variant_name = f"{p['name']} ({attr_color} - {attr_storage})"
# Final price calculations
final_price = round(p["price"] * price_multiplier, 2)
# Generate clean SKU
brand_code = p["brand"][:3].upper()
model_code = "".join([w[0] for w in p["device_model"].split() if w]).upper()[:6]
color_code = attr_color.split()[-1][:3].upper()
sku = f"{brand_code}-{model_code}-{color_code}{sku_suffix}"
# Category details
p_cat = p["category"]
parent_cat_info = categories_info.get(p_cat, ("", "no"))
parent_category = parent_cat_info[0]
is_parent_feature = parent_cat_info[1]
# Generate barcode (EAN-13 style)
barcode = f"890{prod_idx:04d}{var_idx:02d}{final_price:04.0f}"[:13]
# Generate descriptions
description = (
f"Premium {p['brand']} {p['device_model']} in elegant {attr_color}. "
f"Features cutting-edge specifications, original brand warranty, and genuine parts compatibility."
)
if attr_pack:
description += f" Packed as convenience {attr_pack}."
# Construct row dictionary
row_data = {
"sku": sku,
"name": variant_name,
"parent_name": p["name"],
"price": final_price,
"stock": 10 + (prod_idx * 3 + var_idx * 5) % 150, # dynamic inventory stock levels
"brand": p["brand"],
"category": p_cat,
"parent_category": parent_category,
"is_parent_feature": is_parent_feature,
"device_series": p["device_series"],
"device_model": p["device_model"],
"device_type": p["device_type"],
"media_key": media_key,
"barcode": barcode,
"description": description,
"Color Attribute": attr_color,
}
# Set dynamic attributes based on type
if attr_storage:
row_data["Storage Attribute"] = attr_storage
row_data["RAM Attribute"] = attr_storage.split("/")[0]
if attr_pack:
row_data["Pack Attribute"] = attr_pack
excel_rows.append(row_data)
# 4. WRITE EXCEL SHEET USING OPENPYXL
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "Unified Catalog Catalog"
# Define Header list based on union of keys
headers = [
"sku", "name", "parent_name", "price", "stock", "brand", "category",
"parent_category", "is_parent_feature", "device_series", "device_model",
"device_type", "media_key", "barcode", "description", "Color Attribute",
"Storage Attribute", "RAM Attribute", "Pack Attribute"
]
# Style definitions
font_header = Font(name="Segoe UI", size=11, bold=True, color="FFFFFF")
font_data = Font(name="Segoe UI", size=10, color="000000")
fill_header = PatternFill(start_color="1F2C5C", end_color="1F2C5C", fill_type="solid") # Dark navy matching dashboard theme
fill_zebra = PatternFill(start_color="F9FAFB", end_color="F9FAFB", fill_type="solid")
thin_border = Border(
left=Side(style='thin', color='E9EDF4'),
right=Side(style='thin', color='E9EDF4'),
top=Side(style='thin', color='E9EDF4'),
bottom=Side(style='thin', color='E9EDF4')
)
# Write Headers
for col_idx, h in enumerate(headers, 1):
cell = ws.cell(row=1, column=col_idx, value=h)
cell.font = font_header
cell.fill = fill_header
cell.alignment = Alignment(horizontal="left", vertical="center")
cell.border = thin_border
# Write Rows
for row_idx, r_dict in enumerate(excel_rows, 2):
is_zebra = (row_idx % 2 == 0)
for col_idx, h in enumerate(headers, 1):
val = r_dict.get(h, "")
cell = ws.cell(row=row_idx, column=col_idx, value=val)
cell.font = font_data
cell.border = thin_border
if is_zebra:
cell.fill = fill_zebra
# Formatting and Alignment
if h in ("price", "stock"):
cell.alignment = Alignment(horizontal="right", vertical="center")
if h == "price":
cell.number_format = '₹#,##0.00'
else:
cell.number_format = '#,##0'
else:
cell.alignment = Alignment(horizontal="left", vertical="center")
# Set row heights
ws.row_dimensions[1].height = 28
for r in range(2, len(excel_rows) + 2):
ws.row_dimensions[r].height = 20
# Auto fit column widths
for col in ws.columns:
max_len = max(len(str(cell.value or '')) for cell in col)
col_letter = openpyxl.utils.get_column_letter(col[0].column)
ws.column_dimensions[col_letter].width = max(max_len + 3, 12)
# Save workbook
excel_path = os.path.join(output_dir, "catalog_import.xlsx")
wb.save(excel_path)
print(f"Created Excel import sheet at: {excel_path} (200 rows, 19 columns)")
# 5. CREATE IMAGES AND ZIP ARCHIVE
png_data = create_mock_png()
zip_path = os.path.join(output_dir, "media_images.zip")
print("Packing media images ZIP (4 mock JPEGs per product)...")
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
for m_key in media_keys_to_zip:
# We add front, back, side, box images for each product key
for img_name in ["front.jpg", "back.jpg", "side.jpg", "box.jpg"]:
# File path in ZIP: e.g. "Lenovo-ThinkPad-X1-Carbon/front.jpg"
zip_filename = f"{m_key}/{img_name}"
# Write the 1x1 PNG data under JPEG extensions directly (browsers render valid PNGs with JPG extensions anyway)
zipf.writestr(zip_filename, png_data)
print(f"Created Media ZIP package at: {zip_path} (50 folders, 200 files)")
# Cleanup temporary folders if any
if os.path.exists(temp_media_dir):
import shutil
shutil.rmtree(temp_media_dir)
print("Successfully generated all mock migration catalog data!")
if __name__ == "__main__":
main()