# Product Migration Documentation (Magento to Shopify)

This document outlines the detailed process of migrating products from Magento to Shopify using the `migrate:products` artisan command.

## 1. Command Overview
**Command:** `php artisan migrate:products {--limit=} {--chunk=100} {--store=0} {--type=} {--ids=}`

- **Purpose:** Fetches products from Magento, transforms them according to Shopify's requirements, and creates/updates them in Shopify via the GraphQL API.
- **Queueing:** Each product is processed individually via the `ProcessProductMigration` background job for better performance and error handling.

---

## 2. Data Sourcing (Magento)
Data is fetched from the Magento database using the `MagentoProductRepository`.

### A. Base Product Details
| Magento Table | Data Points Fetched | Usage in Migration |
| :--- | :--- | :--- |
| `catalog_product_entity` | `entity_id`, `sku`, `type_id`, `attribute_set_id` | Core identification and filtering. |
| `eav_attribute_set` | `attribute_set_name` | Mapped to Shopify's `productType`. |

### B. Dynamic Attributes (EAV System)
Attributes are fetched from `catalog_product_entity_varchar`, `text`, `decimal`, `int`, and `datetime`. The system follows a "Green List" defined in `shopify_metafield_definitions.json`.

| Magento Attribute Code | Shopify Metafield Key | Description |
| :--- | :--- | :--- |
| `name` / `pname` | `title` (Core) | Product Title |
| `description` | `descriptionHtml` (Core) | Product Body |
| `url_key` | `handle` (Core) | Slug/Link |
| `status` | `status` (Core) | 1 (Enabled) -> ACTIVE / 2 (Disabled) -> DRAFT |
| `price` | `variants.price` | Original Price |
| `special_price` | `variants.price` | Buying price (Original moves to `compareAtPrice`) |
| `weight` | `variants.weight` | Product Weight |
| `brands` | `custom.brands` | Brand Name |
| `short_description` | `custom.short_description` | Short summary |
| `color` | `custom.color` | Product Color |
| `fabric` / `pfabric` | `custom.fabric` | Fabric Type |
| `fit` | `custom.fit` | Product Fit (e.g. Slim, Regular) |
| `collar` / `pcollar` | `custom.collar` | Collar Style |
| `cuff` | `custom.cuff` | Mapped as **Sleeves** in Shopify |
| `vname` | `custom.vname` | Variant/Visual Name |
| `size` / `psize` | `custom.size` | Size Attribute |
| `material` / `pmaterial` | `custom.pmaterial` | Material Composition |
| `pattern` / `ppatterns` | `custom.patterns` | Design Pattern |
| `occasion` | `custom.occasion` | Mapped as **Type** in Metafields |
| `video_link` | `custom.video_link` | Video URL (Sanitized) |
| `relation` | `custom.related_skus` | Related Product SKUs (JSON) |
| `cross_sell` | `custom.cross_sell_skus`| Cross-sell Product SKUs (JSON) |
| `up_sell` | `custom.upsell_skus` | Upsell Product SKUs (JSON) |

### C. Media & Gallery
| Magento Source | Logic | Shopify Destination |
| :--- | :--- | :--- |
| `catalog_product_entity_media_gallery` | Fetches all image files related to the product ID. | `media` (Images) |
| `catalog_product_entity_varchar` | Fetches `image`, `small_image`, `thumbnail` roles. | Assigned as primary images in Shopify. |
| Custom Attribute `video_link` | Raw video URL from Magento. | `metafields` (custom.video_link) |

### D. Stock & Categories
| Magento Source | Data Points | Shopify Destination |
| :--- | :--- | :--- |
| `cataloginventory_stock_item` | `qty`, `is_in_stock` | `variants.inventoryItem` |
| `catalog_category_product` | Category names (joined with `catalog_category_entity_varchar`) | `tags` and `metafields` |

---

## 3. Data Transformation (Shopify)
The `ProductTransformer` handles the mapping of Magento data to the Shopify GraphQL payload.

### A. Core Product Mapping
- **Title:** Uses `pname` if available, otherwise `name`, falling back to `sku`.
- **Status:** Maps 'Yes'/'Enabled' to `ACTIVE`; 'No'/'Disabled' to `DRAFT`.
- **Product Type:** Derived from Magento's `attribute_set_name` (e.g., "Shirt", "Tie").
- **Tags:** Automatically generated including:
    - `SKU: [magento_sku]`
    - `Category: [category_name]`
    - `Type: [product_type]`
    - All mapped custom attributes (e.g., `Material: Silk`).

### B. Variant Mapping
- **Single Variant:** Currently, the migration assumes a single variant per simple product.
- **Options:** Only `Size` is used as a variant option.
- **Price:** If `special_price` is lower than `price`, the `price` becomes `compareAtPrice` and `special_price` becomes the active `price`.
- **Free Size Logic:** If a product belongs to categories like "Tie", "Cufflink", or "Mask" and has no size, it is automatically assigned "Free Size".

### C. Metafields (Custom Attributes)
Metadata is synced based on definitions in `shopify_metafield_definitions.json`.
- **SEO:** `meta_title` -> `global.title_tag`, `meta_description` -> `global.description_tag`.
- **Links:** Related, Cross-sell, and Upsell products are converted from Magento IDs to a JSON list of SKUs.

---

## 4. Migration Workflow (The Process)

### Step 1: Query & Dispatch
The command queries `catalog_product_entity` for simple products and dispatches `ProcessProductMigration` jobs in chunks.

### Step 2: Mapping Verification
Before reaching out to Shopify, the job checks the `product_mappings` table:
- If `sync_status` is `migrated` and a `shopify_product_id` exists, it proceeds to **Update**.
- Otherwise, it proceeds to **Create**.

### Step 3: API Execution
- **Create:** Calls `productCreate` GraphQL mutation with titles, descriptions, status, tags, and media.
- **Update:** Calls `productUpdate` GraphQL mutation. (Note: Media is typically handled during creation).
- **Handle Collision:** If Shopify returns "Handle already in use", the script attempts to find the existing product by handle or appends `-v2` to create a unique handle.

### Step 4: Record Completion
The `product_mappings` table is updated with:
- `shopify_product_id`
- `shopify_variant_id`
- `shopify_handle`
- `sync_status` ('migrated' or 'failed')
- `magento_data` (The full raw payload for debugging)

---

## 5. Technical Structure
- **Command:** `App\Console\Commands\MigrateProducts`
- **Job:** `App\Jobs\ProcessProductMigration`
- **Repository:** `App\Services\MagentoProductRepository` (Fetches Magento data)
- **Transformer:** `App\Services\ProductTransformer` (Converts to Shopify Format)
- **Service:** `App\Services\ShopifyService` (Handles API Communication)
- **Mapping Model:** `App\Models\ProductMapping` (Tracks database sync state)
