migrationService = $migrationService; } /** * Show the migration interface */ public function index() { $m1Stores = $this->migrationService->getMagento1Stores(); $m2Stores = $this->migrationService->getMagento2Stores(); $connectionTest = $this->migrationService->testConnections(); $m1Categories = $this->migrationService->getMagento1Categories(); $m2Categories = $this->migrationService->getMagento2Categories(); $m2CategoriesNotInM1 = $this->migrationService->getM2CategoriesNotInM1(); $m1Attributes = $this->migrationService->getMagento1Attributes(); $m2Attributes = $this->migrationService->getMagento2Attributes(); $m1AttributesMissingInM2 = $this->migrationService->getM1AttributesMissingInM2(); $m1AttributeGroups = $this->migrationService->getMagento1AttributeGroups(); $m2AttributeGroups = $this->migrationService->getMagento2AttributeGroups(); $m1AttributeGroupsMissingInM2 = $this->migrationService->getM1AttributeGroupsMissingInM2(); $m1Products = $this->migrationService->getMagento1Products(); $m2Products = $this->migrationService->getMagento2Products(); $m1ProductsNotInM2 = $this->migrationService->getM1ProductsNotInM2(); $m2ProductsNotInM1 = $this->migrationService->getM2ProductsNotInM1(); return view('migration.index', [ 'm1Stores' => $m1Stores, 'm2Stores' => $m2Stores, 'connectionTest' => $connectionTest, 'm1CategoriesCount' => $m1Categories->count(), 'm2CategoriesCount' => $m2Categories->count(), 'm2CategoriesNotInM1' => $m2CategoriesNotInM1, 'm1Attributes' => $m1Attributes, 'm2Attributes' => $m2Attributes, 'm1AttributesMissingInM2' => $m1AttributesMissingInM2, 'm1AttributeGroups' => $m1AttributeGroups, 'm2AttributeGroups' => $m2AttributeGroups, 'm1AttributeGroupsMissingInM2' => $m1AttributeGroupsMissingInM2, 'm1Products' => $m1Products, 'm2Products' => $m2Products, 'm1ProductsNotInM2' => $m1ProductsNotInM2, 'm2ProductsNotInM1' => $m2ProductsNotInM1, ]); } /** * Test database connections */ public function testConnections() { $results = $this->migrationService->testConnections(); return response()->json([ 'success' => $results['magento1'] && $results['magento2'], 'results' => $results, ]); } /** * Get Magento 1 categories preview */ public function getMagento1Categories() { $categories = $this->migrationService->getMagento1Categories(); return response()->json([ 'success' => true, 'count' => $categories->count(), 'categories' => $categories->take(50)->map(function($cat) { return [ 'id' => $cat->entity_id, 'name' => $cat->name ?? 'N/A', 'level' => $cat->level, 'parent_id' => $cat->parent_id, 'is_active' => $cat->is_active ?? 0, ]; }), ]); } /** * Get Magento 1 category tree */ public function getMagento1CategoryTree() { try { $categories = $this->migrationService->getMagento1Categories(); $tree = $this->migrationService->buildCategoryTreeHierarchy($categories, 'm1'); return response()->json([ 'success' => true, 'tree' => $tree, ]); } catch (\Exception $e) { Log::error('Error fetching M1 category tree: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Failed to fetch category tree: ' . $e->getMessage(), ], 500); } } /** * Get Magento 1 category tree with products */ public function getMagento1CategoryTreeWithProducts() { try { $tree = $this->migrationService->getMagento1CategoryTreeWithProducts(); return response()->json([ 'success' => true, 'tree' => $tree ]); } catch (\Exception $e) { Log::error('Error fetching M1 category tree with products: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Failed to load category tree with products: ' . $e->getMessage(), 'tree' => [] ], 500); } } /** * Get Magento 2 category tree with products */ public function getMagento2CategoryTreeWithProducts() { try { $tree = $this->migrationService->getMagento2CategoryTreeWithProducts(); return response()->json([ 'success' => true, 'tree' => $tree ]); } catch (\Exception $e) { Log::error('Error fetching M2 category tree with products: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Failed to load category tree with products: ' . $e->getMessage(), 'tree' => [] ], 500); } } /** * Get Magento 2 category tree */ public function getMagento2CategoryTree() { try { $categories = $this->migrationService->getMagento2Categories(); $tree = $this->migrationService->buildCategoryTreeHierarchy($categories, 'm2'); return response()->json([ 'success' => true, 'tree' => $tree, ]); } catch (\Exception $e) { Log::error('Error fetching M2 category tree: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Failed to fetch category tree: ' . $e->getMessage(), ], 500); } } /** * Get M2 categories not in M1 (for AJAX refresh) */ public function getM2CategoriesNotInM1() { try { $categories = $this->migrationService->getM2CategoriesNotInM1(); return response()->json([ 'success' => true, 'categories' => $categories->map(function($category) { return [ 'entity_id' => $category->entity_id, 'name' => $category->name ?? 'Unnamed Category', 'level' => $category->level ?? 'N/A', 'is_active' => $category->is_active ?? 0, 'root_category_name' => $category->root_category_name ?? 'N/A', 'root_category_id' => $category->root_category_id ?? null, 'path' => $category->path ?? 'N/A', ]; }), 'count' => $categories->count(), ]); } catch (\Exception $e) { Log::error('Error fetching M2 categories not in M1: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Failed to fetch categories: ' . $e->getMessage(), ], 500); } } /** * Delete a category */ public function deleteCategory(Request $request, $categoryId) { $request->validate([ 'source' => 'nullable|in:m1,m2', ]); try { $source = $request->input('source', 'm2'); $result = $this->migrationService->deleteCategory($categoryId, $source); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Category deletion error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Deletion failed: ' . $e->getMessage(), ], 500); } } /** * Rename a Magento 2 category */ public function renameCategory(Request $request, $categoryId) { $request->validate([ 'name' => 'required|string|max:255', 'store_id' => 'nullable|integer', ]); try { $newName = $request->input('name'); $storeId = $request->input('store_id', 0); $result = $this->migrationService->renameCategory($categoryId, $newName, $storeId); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Category rename error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Rename failed: ' . $e->getMessage(), ], 500); } } /** * Migrate an attribute from Magento 1 to Magento 2 */ public function migrateAttribute(Request $request, $attributeId) { try { $result = $this->migrationService->migrateAttribute($attributeId); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Attribute migration error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Migration failed: ' . $e->getMessage(), ], 500); } } /** * Migrate an attribute group from Magento 1 to Magento 2 */ public function migrateAttributeGroup(Request $request, $groupId, $setId) { try { $result = $this->migrationService->migrateAttributeGroup($groupId, $setId); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Attribute group migration error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Migration failed: ' . $e->getMessage(), ], 500); } } /** * Migrate all products from Magento 1 to Magento 2 */ public function migrateProducts(Request $request) { try { $dryRun = $request->input('dry_run', false); $result = $this->migrationService->migrateProducts($dryRun); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Product migration error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Migration failed: ' . $e->getMessage(), 'added' => 0, 'updated' => 0, 'errors' => 0, 'log' => [], 'missing_attributes' => [] ], 500); } } /** * Delete a single product from Magento 2 */ public function deleteM2Product(Request $request, $productId) { try { $result = $this->migrationService->deleteM2Product($productId); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Delete M2 product error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Deletion failed: ' . $e->getMessage() ], 500); } } /** * Sync product category assignments from M1 to M2 */ public function syncProductCategories(Request $request) { try { $result = $this->migrationService->syncProductCategories(); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Sync product categories error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Sync failed: ' . $e->getMessage(), 'updated' => 0, 'skipped' => 0, 'errors' => 0, 'log' => [] ], 500); } } /** * Delete all products in Magento 2 that have entity_id greater than max M1 product ID */ public function deleteM2ProductsAboveM1Max(Request $request) { try { $result = $this->migrationService->deleteM2ProductsAboveM1Max(); return response()->json($result, $result['success'] ? 200 : 400); } catch (\Exception $e) { Log::error('Delete M2 products error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Deletion failed: ' . $e->getMessage(), 'deleted' => 0 ], 500); } } /** * Execute the migration */ public function migrate(Request $request) { $request->validate([ 'store_mapping' => 'required|array', 'store_mapping.*' => 'required|integer', ]); try { $storeMapping = $request->input('store_mapping'); // Convert array format: ['m1_store_id' => 'm2_store_id'] $mapping = []; foreach ($storeMapping as $m1StoreId => $m2StoreId) { $mapping[(int)$m1StoreId] = (int)$m2StoreId; } $result = $this->migrationService->migrateCategories($mapping); return response()->json($result); } catch (\Exception $e) { Log::error('Migration error: ' . $e->getMessage()); return response()->json([ 'success' => false, 'message' => 'Migration failed: ' . $e->getMessage(), ], 500); } } }