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()