235 lines
12 KiB
PHP
235 lines
12 KiB
PHP
@extends('layouts.app')
|
|
|
|
@section('content')
|
|
<!-- Product Migration Section -->
|
|
<div class="section">
|
|
<h2>🚀 Product Migration</h2>
|
|
<div class="info-box" style="margin-bottom: 20px;">
|
|
<h3 style="margin-bottom: 10px; color: #1976D2; font-size: 1.1em;">What happens when you click "Start Product Migration"?</h3>
|
|
<p style="margin: 5px 0; color: #1976D2;">The product migration process will:</p>
|
|
<ul style="margin: 10px 0 0 20px; color: #1976D2; line-height: 1.8;">
|
|
<li><strong>Create new products:</strong> If a product with the same SKU doesn't exist in Magento 2, it will be created with all its attributes</li>
|
|
<li><strong>Update existing products:</strong> If a product with the same SKU already exists in Magento 2, it will be updated with the latest data from Magento 1</li>
|
|
<li><strong>Migrate product attributes:</strong> All product attributes including SKU, name, description, price, weight, status, visibility, and tax class will be migrated</li>
|
|
<li><strong>Assign to categories:</strong> Products will be assigned to the corresponding categories in Magento 2</li>
|
|
<li><strong>Generate logs:</strong> Detailed migration logs showing which products were added, updated, or encountered errors</li>
|
|
</ul>
|
|
<p style="margin: 10px 0 0 0; color: #d32f2f; font-weight: 600;">⚠️ <strong>Warning:</strong> This will modify your Magento 2 database. Make sure you have a backup before proceeding.</p>
|
|
</div>
|
|
|
|
<div style="margin-top: 20px; display: flex; gap: 15px; flex-wrap: wrap;">
|
|
<button id="dryRunProductMigrationBtn" class="btn btn-secondary" onclick="startProductMigration(true)">
|
|
Run Dry Run (Check for Errors)
|
|
</button>
|
|
<button id="startProductMigrationBtn" class="btn btn-primary" onclick="startProductMigration(false)">
|
|
Start Product Migration
|
|
</button>
|
|
<button id="deleteProductsAboveM1MaxBtn" class="btn btn-danger" onclick="deleteProductsAboveM1Max()">
|
|
Delete M2 Products Above M1 Max ID
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Missing Attributes Section -->
|
|
<div class="section" id="missingAttributesSection" style="margin-top: 30px; display: none;">
|
|
<h2>⚠️ Missing Attributes</h2>
|
|
<p style="margin-bottom: 15px; color: #666;">The following attributes exist in Magento 1 but are missing in Magento 2. These need to be created before migration:</p>
|
|
<div style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 20px; max-height: 400px; overflow-y: auto;">
|
|
<table class="products-table" id="missingAttributesTable">
|
|
<thead>
|
|
<tr>
|
|
<th>Attribute Code</th>
|
|
<th>Label</th>
|
|
<th>Backend Type</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="missingAttributesTableBody">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Migration Logs Section -->
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>📋 Product Migration Logs</h2>
|
|
<p style="margin-bottom: 15px; color: #666;">Detailed logs showing which products were added, updated, or encountered errors during migration:</p>
|
|
<div class="log-container" id="productMigrationLogContainer" style="display: block;">
|
|
<div id="productMigrationLogContent">
|
|
<div class="log-entry" style="color: #999; font-style: italic;">
|
|
No product migration logs yet. Click "Run Dry Run" or "Start Product Migration" to begin.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Product Statistics -->
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>📊 Product Statistics</h2>
|
|
<div class="stats">
|
|
<div class="stat-card">
|
|
<div class="number">{{ $m1Products->count() }}</div>
|
|
<div class="label">Magento 1 Products</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="number">{{ $m2Products->count() }}</div>
|
|
<div class="label">Magento 2 Products</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="number">{{ $m1ProductsNotInM2->count() }}</div>
|
|
<div class="label">M1 Products Not in M2</div>
|
|
</div>
|
|
<div class="stat-card">
|
|
<div class="number">{{ $m2ProductsNotInM1->count() }}</div>
|
|
<div class="label">M2 Products Not in M1</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Products Not in M2 Section -->
|
|
@if($m1ProductsNotInM2->count() > 0)
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>⚠️ Magento 1 Products Not in Magento 2</h2>
|
|
<p>These products exist in Magento 1 but are missing in Magento 2:</p>
|
|
<div style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 20px; max-height: 400px; overflow-y: auto; margin-top: 15px;">
|
|
<table class="products-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>SKU</th>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Status</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($m1ProductsNotInM2->take(50) as $product)
|
|
<tr>
|
|
<td>{{ $product->entity_id }}</td>
|
|
<td>{{ $product->sku ?? 'N/A' }}</td>
|
|
<td>{{ $product->name ?? 'Unnamed Product' }}</td>
|
|
<td>{{ $product->type_id ?? 'N/A' }}</td>
|
|
<td>
|
|
@if(($product->status ?? 0) == 1)
|
|
<span style="color: #28a745;">Enabled</span>
|
|
@else
|
|
<span style="color: #dc3545;">Disabled</span>
|
|
@endif
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
@if($m1ProductsNotInM2->count() > 50)
|
|
<p style="margin-top: 15px; color: #666;">Showing first 50 of {{ $m1ProductsNotInM2->count() }} products.</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Products Not in M1 Section -->
|
|
@if($m2ProductsNotInM1->count() > 0)
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>⚠️ Magento 2 Products Not in Magento 1</h2>
|
|
<p>These products exist in Magento 2 but are missing in Magento 1:</p>
|
|
<div style="background: white; border: 1px solid #ddd; border-radius: 6px; padding: 20px; max-height: 400px; overflow-y: auto; margin-top: 15px;">
|
|
<table class="products-table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>SKU</th>
|
|
<th>Name</th>
|
|
<th>Type</th>
|
|
<th>Status</th>
|
|
<th>Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach($m2ProductsNotInM1->take(50) as $product)
|
|
<tr>
|
|
<td>{{ $product->entity_id }}</td>
|
|
<td>{{ $product->sku ?? 'N/A' }}</td>
|
|
<td>{{ $product->name ?? 'Unnamed Product' }}</td>
|
|
<td>{{ $product->type_id ?? 'N/A' }}</td>
|
|
<td>
|
|
@if(($product->status ?? 0) == 1)
|
|
<span style="color: #28a745;">Enabled</span>
|
|
@else
|
|
<span style="color: #dc3545;">Disabled</span>
|
|
@endif
|
|
</td>
|
|
<td>
|
|
<button
|
|
class="btn btn-danger"
|
|
onclick="deleteM2Product({{ $product->entity_id }}, '{{ addslashes($product->name ?? 'Unnamed Product') }}', '{{ addslashes($product->sku ?? 'N/A') }}')"
|
|
style="padding: 6px 12px; font-size: 0.85em;">
|
|
Delete
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
@endforeach
|
|
</tbody>
|
|
</table>
|
|
@if($m2ProductsNotInM1->count() > 50)
|
|
<p style="margin-top: 15px; color: #666;">Showing first 50 of {{ $m2ProductsNotInM1->count() }} products.</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
<!-- Sync Product Categories Section -->
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>🔄 Sync Product Categories</h2>
|
|
<p>Sync product category assignments from Magento 1 to Magento 2:</p>
|
|
<button id="syncProductCategoriesBtn" class="btn btn-primary" onclick="syncProductCategories()" style="margin-top: 15px;">
|
|
Sync Product Categories
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Category Tree with Products Section -->
|
|
<div class="section" style="margin-top: 30px;">
|
|
<h2>🌳 Category Tree with Products</h2>
|
|
<p>View all categories with their associated products in a tree structure</p>
|
|
|
|
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-top: 20px;">
|
|
<!-- Magento 1 Tree with Products -->
|
|
<div>
|
|
<h3 style="margin-bottom: 15px; color: #667eea;">Magento 1 Categories</h3>
|
|
<button onclick="loadM1CategoryTreeWithProducts()" style="padding: 10px 20px; font-size: 1em; background: #667eea; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; margin-bottom: 15px;">
|
|
Load M1 Category Tree with Products
|
|
</button>
|
|
<div class="tree-container" id="m1-category-products-tree-container">
|
|
<div class="tree-loading">Click the button above to load categories with products</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Magento 2 Tree with Products -->
|
|
<div>
|
|
<h3 style="margin-bottom: 15px; color: #764ba2;">Magento 2 Categories</h3>
|
|
<button onclick="loadM2CategoryTreeWithProducts()" style="padding: 10px 20px; font-size: 1em; background: #764ba2; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: 600; margin-bottom: 15px;">
|
|
Load M2 Category Tree with Products
|
|
</button>
|
|
<div class="tree-container" id="m2-category-products-tree-container">
|
|
<div class="tree-loading">Click the button above to load categories with products</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endsection
|
|
|
|
{{-- CSS is loaded globally via app.css --}}
|
|
|
|
@push('scripts')
|
|
@vite(['resources/js/products.js'])
|
|
<script>
|
|
window.productRoutes = {
|
|
migrateProducts: '{{ route("products.migrate-products") }}',
|
|
deleteProduct: '{{ route("products.delete-product", ["productId" => ":id"]) }}',
|
|
deleteProductsAboveM1Max: '{{ route("products.delete-products-above-m1-max") }}',
|
|
syncProductCategories: '{{ route("products.sync-product-categories") }}',
|
|
magento1CategoryTreeWithProducts: '{{ route("categories.magento1-category-tree-with-products") }}',
|
|
magento2CategoryTreeWithProducts: '{{ route("categories.magento2-category-tree-with-products") }}'
|
|
};
|
|
</script>
|
|
@endpush
|
|
|