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 { $fileName = basename($sourcePath); $legacyDir = dirname($sourcePath); DB::table('media')->insert([ 'model_type' => Report::class, 'model_id' => $report->id, 'uuid' => (string) Str::uuid(), 'collection_name' => 'reports', 'name' => pathinfo($fileName, PATHINFO_FILENAME), 'file_name' => $fileName, 'mime_type' => $this->guessMime($fileName), 'disk' => 's3', 'conversions_disk' => 's3', 'size' => 0, 'manipulations' => '[]', 'custom_properties' => json_encode([ 'feature' => 'reports', 'date' => Carbon::parse($legacy->created_at ?? now())->toDateString(), 'doc_type' => 'proof', 'legacy_dir' => $legacyDir, ]), 'generated_conversions' => '[]', 'responsive_images' => '[]', 'order_column' => 1, 'created_at' => now(), 'updated_at' => now(), ]); } private function guessMime(string $fileName): string { return match (strtolower(pathinfo($fileName, PATHINFO_EXTENSION))) { 'pdf' => 'application/pdf', 'jpg', 'jpeg' => 'image/jpeg', 'png' => 'image/png', 'doc' => 'application/msword', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', default => 'application/octet-stream', }; } /** * 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, }; } }