simedkom/app/Console/Commands/MigrateCooperationCommand.php

321 lines
11 KiB
PHP

<?php
namespace App\Console\Commands;
use App\Enums\ApprovalStatus;
use App\Enums\CooperationStatus;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
class MigrateCooperationCommand extends Command
{
protected $signature = 'migrate:cooperation';
protected $description = 'Migrate cooperation data from legacy database';
/**
* Map: legacy media_cooperation id => new cooperation_id
* Dipakai untuk lookup saat migrate proposals
*/
private array $legacyCoopMap = [];
public function handle(): void
{
$this->migrateMediaOrders();
$this->migrateMediaCooperation();
$this->migrateProposals();
$this->migrateReports();
}
private function migrateMediaOrders(): void
{
$this->info('Migrating media_orders → cooperations...');
$groups = DB::connection('mysql_second')
->table('media_orders')
->whereNull('deleted_at')
->orderBy('id')
->get()
->groupBy(fn ($item) => strtolower(trim($item->name)));
foreach ($groups as $group) {
$first = $group->first();
$cooperationId = $this->insertCooperation(
name: $first->name,
description: $first->description,
initialDate: $group->min('begin'),
finalDate: $group->max('end'),
status: CooperationStatus::COMPLETED->value,
completedAt: $group->max('end'),
);
$this->insertCooperationMedia(
group: $group,
cooperationId: $cooperationId,
approvalStatus: ApprovalStatus::ACCEPTED->value,
);
$startDate = Carbon::parse($group->max('end'))->addDay();
$endDate = $startDate->copy()->addDays(7);
DB::table('task_assignments')->insert([
'cooperation_id' => $cooperationId,
'start_date' => $startDate->toDateString(),
'end_date' => $endDate->toDateString(),
'task_description' => $first->description ?? '',
'report_amount' => $group->sum('amount_report') ?: 1,
'created_at' => now(),
'updated_at' => now(),
]);
$taskAssignmentId = (int) DB::getPdo()->lastInsertId();
$this->insertMediaTaskAssignment(
cooperationId: $cooperationId,
taskAssignmentId: $taskAssignmentId,
approvalStatus: ApprovalStatus::ACCEPTED->value,
);
$this->info("Merged {$group->count()} rows → {$first->name}");
}
$this->info('media_orders migration done.');
}
private function migrateMediaCooperation(): void
{
$this->info('Migrating media_cooperation → cooperations...');
$groups = DB::connection('mysql_second')
->table('media_cooperation')
->whereNull('deleted_at')
->orderBy('id')
->get()
->groupBy(fn ($item) => strtolower(trim($item->name)));
foreach ($groups as $group) {
$first = $group->first();
$cooperationId = $this->insertCooperation(
name: $first->name,
description: $first->description,
initialDate: $group->min('begin'),
finalDate: $group->max('end'),
status: CooperationStatus::PENDING->value,
completedAt: null,
);
$this->insertCooperationMedia(
group: $group,
cooperationId: $cooperationId,
approvalStatus: ApprovalStatus::PENDING->value,
);
$startDate = Carbon::parse($group->max('end'))->addDay();
$endDate = $startDate->copy()->addDays(7);
DB::table('task_assignments')->insert([
'cooperation_id' => $cooperationId,
'start_date' => $startDate->toDateString(),
'end_date' => $endDate->toDateString(),
'task_description' => $first->description ?? '',
'report_amount' => 1,
'created_at' => now(),
'updated_at' => now(),
]);
$taskAssignmentId = (int) DB::getPdo()->lastInsertId();
$this->insertMediaTaskAssignment(
cooperationId: $cooperationId,
taskAssignmentId: $taskAssignmentId,
approvalStatus: ApprovalStatus::PENDING->value,
);
// Simpan mapping legacy id → new cooperation_id untuk dipakai saat migrate proposals
foreach ($group as $item) {
$this->legacyCoopMap[$item->id] = $cooperationId;
}
$this->info("Merged {$group->count()} rows → {$first->name}");
}
$this->info('media_cooperation migration done.');
}
private function migrateProposals(): void
{
$this->info('Migrating propose_media_cooperation → cooperation_proposals...');
$proposals = DB::connection('mysql_second')
->table('propose_media_cooperation')
->whereNull('deleted_at')
->get();
foreach ($proposals as $proposal) {
$cooperationId = $this->legacyCoopMap[$proposal->media_cooperation_id] ?? null;
if (! $cooperationId) {
$this->warn("cooperation not found for proposal {$proposal->id} (media_cooperation_id: {$proposal->media_cooperation_id})");
continue;
}
$partnerMediaId = DB::table('partner_media')
->join('companies', 'partner_media.company_id', '=', 'companies.id')
->where('companies.user_id', $proposal->enhancer)
->value('partner_media.id');
if (! $partnerMediaId) {
$this->warn("partner_media not found for proposal {$proposal->id} (enhancer/user_id: {$proposal->enhancer})");
continue;
}
DB::table('cooperation_proposals')->insert([
'cooperation_id' => $cooperationId,
'partner_media_id' => $partnerMediaId,
'description' => null,
'e_catalog' => null,
'status' => $this->mapApprovalStatus($proposal->status),
'submitted_at' => $proposal->created_at ?? now(),
'responded_at' => $proposal->updated_at,
'created_at' => $proposal->created_at ?? now(),
'updated_at' => $proposal->updated_at ?? now(),
]);
}
$this->info('proposals migration done.');
}
// =========================================================
// Helper Methods
// =========================================================
private function insertCooperation(
string $name,
?string $description,
string $initialDate,
string $finalDate,
string $status,
?string $completedAt,
): int {
DB::table('cooperations')->insert([
'title' => $name,
'initial_submission_date' => $initialDate,
'final_submission_date' => $finalDate,
'description' => $description ?? '',
'payment_amount' => null,
'payment_date' => null,
'completed_at' => $completedAt,
'status' => $status,
'created_at' => now(),
'updated_at' => now(),
]);
return (int) DB::getPdo()->lastInsertId();
}
private function insertCooperationMedia(
Collection $group,
int $cooperationId,
string $approvalStatus,
): void {
$validMediaIds = DB::table('partner_media')->pluck('id')->toArray();
$mediaIds = collect();
foreach ($group as $item) {
if (! $item->media) {
continue;
}
$mediaIds = $mediaIds->merge(explode(',', $item->media));
}
$mediaIds
->map(fn ($id) => (int) $id)
->filter(fn ($id) => in_array($id, $validMediaIds))
->unique()
->each(function ($mediaId) use ($cooperationId, $approvalStatus) {
DB::table('cooperation_media')->insert([
'cooperation_id' => $cooperationId,
'partner_media_id' => $mediaId,
'status' => $approvalStatus,
'created_at' => now(),
'updated_at' => now(),
]);
});
}
private function mapApprovalStatus(string $legacy): string
{
return match ($legacy) {
'accepted' => ApprovalStatus::ACCEPTED->value,
'rejected' => ApprovalStatus::REJECTED->value,
default => ApprovalStatus::PENDING->value,
};
}
private function insertMediaTaskAssignment(
int $cooperationId,
int $taskAssignmentId,
string $approvalStatus,
): void {
$mediaIds = DB::table('cooperation_media')
->where('cooperation_id', $cooperationId)
->pluck('partner_media_id');
foreach ($mediaIds as $partnerMediaId) {
DB::table('media_task_assignment')->insert([
'task_assignment_id' => $taskAssignmentId,
'partner_media_id' => $partnerMediaId,
'status' => $approvalStatus,
'created_at' => now(),
'updated_at' => now(),
]);
}
}
private function migrateReports(): void
{
$this->info('Migrating reports → reports...');
$legacyReports = DB::connection('mysql_second')
->table('reports')
->whereNull('deleted_at')
->get();
foreach ($legacyReports as $legacy) {
// Cari media_task_assignment berdasarkan partner_media_id
// dan task_assignment yang berelasi ke cooperation dengan tanggal yang sesuai
$mediaTaskAssignment = DB::table('media_task_assignment')
->join('task_assignments', 'media_task_assignment.task_assignment_id', '=', 'task_assignments.id')
->where('media_task_assignment.partner_media_id', $legacy->media)
->whereDate('task_assignments.start_date', '<=', $legacy->broadcast)
->whereDate('task_assignments.end_date', '>=', $legacy->broadcast)
->select('media_task_assignment.id')
->first();
if (! $mediaTaskAssignment) {
$this->warn("media_task_assignment not found for report {$legacy->id}");
continue;
}
DB::table('reports')->insert([
'media_task_assignment_id' => $mediaTaskAssignment->id,
'title' => $legacy->title,
'publication_date' => $legacy->broadcast,
'link' => $legacy->link,
'description' => $legacy->proof ?? '',
'status' => $this->mapApprovalStatus($legacy->status),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
]);
}
$this->info('reports migration done.');
}
}