info('Starting migration: reports → reports...'); $legacyConn = DB::connection('mysql_second'); $query = $legacyConn->table('reports')->whereNull('deleted_at'); $totalCount = $query->count(); if ($totalCount === 0) { $this->warn('No reports found in legacy database.'); return; } $this->info("Found {$totalCount} legacy report record(s)."); // Pre-cache report IDs that already have proof media (skip re-importing files) $this->migratedIds = DB::table('media') ->where('model_type', Report::class) ->where('collection_name', 'reports') ->pluck('model_id') ->flip() ->all(); // Build a lookup: legacy media_orders.id → new cooperations.id // via: media_orders.name (lowercased) → cooperations.title (lowercased) $legacyOrders = $legacyConn->table('media_orders') ->whereNull('deleted_at') ->select('id', 'name') ->get() ->keyBy('id'); $cooperationMap = DB::table('cooperations') ->select('id', 'title') ->get() ->keyBy(fn ($c) => strtolower(trim($c->title))); foreach ($legacyOrders as $order) { $key = strtolower(trim($order->name)); if (isset($cooperationMap[$key])) { $this->mediaOrderToCooperation[$order->id] = $cooperationMap[$key]->id; } } $query->orderBy('id')->chunk(50, function ($chunk) { foreach ($chunk as $legacy) { $this->processReport($legacy); } }); $this->newLine(); $this->info('reports migration completed successfully!'); } /** * Process a single legacy report record. */ private function processReport(object $legacy): void { $idText = "[#{$legacy->id}]"; $this->output->write("{$idText} Processing: ".Str::limit($legacy->title ?? '', 40).'... '); try { // Resolve media_task_assignment_id // Chain: legacy.media_order → cooperation_id → task_assignment → media_task_assignment (by partner_media_id) $cooperationId = $this->mediaOrderToCooperation[$legacy->media_order] ?? null; if (! $cooperationId) { $this->output->writeln('SKIP (cooperation not found for media_order #'.$legacy->media_order.')'); return; } $taskAssignment = DB::table('task_assignments') ->where('cooperation_id', $cooperationId) ->select('id') ->first(); if (! $taskAssignment) { $this->output->writeln('SKIP (task_assignment not found for cooperation #'.$cooperationId.')'); return; } $mediaTaskAssignment = DB::table('media_task_assignment') ->where('task_assignment_id', $taskAssignment->id) ->where('partner_media_id', $legacy->media) ->select('id') ->first(); if (! $mediaTaskAssignment) { $this->output->writeln('SKIP (media_task_assignment not found for media #'.$legacy->media.')'); return; } // Insert the report DB::table('reports')->insert([ 'media_task_assignment_id' => $mediaTaskAssignment->id, 'title' => $legacy->title ?? '', 'publication_date' => $legacy->broadcast, 'link' => $legacy->link ?? '', 'description' => '', 'status' => $this->mapApprovalStatus((string) $legacy->status), 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now(), ]); $newReportId = (int) DB::getPdo()->lastInsertId(); // Migrate proof image if not already done if (! isset($this->migratedIds[$newReportId])) { $report = Report::find($newReportId); if ($report) { $this->migrateProof($report, $legacy); } } $this->output->writeln('DONE'); } catch (\Exception $e) { $this->output->writeln('FAILED: '.$e->getMessage().''); } } /** * Migrate the proof image file from S3 to the Report media library. */ private function migrateProof(Report $report, object $legacy): void { $legacyPath = trim($legacy->proof ?? ''); if (empty($legacyPath) || $legacyPath === '-' || $legacyPath === 'no-image.png') { return; } $sourcePath = 'old-data/reports/'.$legacyPath; $this->importProofFile($report, $sourcePath, $legacy); } /** * Import a single proof image to the Report media library. */ private function importProofFile(Report $report, string $sourcePath, object $legacy): void { $attempts = 0; $maxAttempts = 3; $exists = false; while ($attempts < $maxAttempts) { try { $exists = Storage::disk('s3')->exists($sourcePath); break; } catch (\Exception $e) { $attempts++; usleep(200000); } } if (! $exists) { return; } try { $report->addMediaFromDisk($sourcePath, 's3') ->withCustomProperties([ 'feature' => 'reports', 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), 'doc_type' => 'proof', ]) ->preservingOriginal() ->toMediaCollection('reports', 's3'); } catch (\Exception $e) { // Log quietly or handle error } } /** * Map legacy reports.status integer to ApprovalStatus enum value. * Legacy: 0 = menunggu, 1 = menerima, 2 = menolak */ private function mapApprovalStatus(string $legacyStatus): int { return match ($legacyStatus) { '0' => ApprovalStatus::PENDING->value, '1' => ApprovalStatus::ACCEPTED->value, '2' => ApprovalStatus::REJECTED->value, default => ApprovalStatus::PENDING->value, }; } }