refactor: modularize legacy cooperation migration logic and implement grouping by name to handle duplicates
This commit is contained in:
parent
27a4ade00b
commit
5b0588a367
@ -5,235 +5,316 @@
|
||||
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;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class MigrateCooperationCommand extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'migrate:cooperation';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Migrate cooperation data, proposals, and orders from legacy database';
|
||||
protected $description = 'Migrate cooperation data from legacy database';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
* Map: legacy media_cooperation id => new cooperation_id
|
||||
* Dipakai untuk lookup saat migrate proposals
|
||||
*/
|
||||
public function handle()
|
||||
private array $legacyCoopMap = [];
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
$this->info('Starting comprehensive cooperation and report migration...');
|
||||
$this->migrateMediaOrders();
|
||||
$this->migrateMediaCooperation();
|
||||
$this->migrateProposals();
|
||||
$this->migrateReports();
|
||||
}
|
||||
|
||||
$legacyConn = DB::connection('mysql_second');
|
||||
$offset = 10000;
|
||||
private function migrateMediaOrders(): void
|
||||
{
|
||||
$this->info('Migrating media_orders → cooperations...');
|
||||
|
||||
// 1. Migrate media_orders -> cooperations & task_assignments
|
||||
$this->info('Migrating media_orders...');
|
||||
$legacyOrders = $legacyConn->table('media_orders')->get();
|
||||
$this->withProgressBar($legacyOrders, function ($legacy) {
|
||||
$status = $legacy->deleted_at ? CooperationStatus::COMPLETED->value : CooperationStatus::ASSIGNMENT->value;
|
||||
$groups = DB::connection('mysql_second')
|
||||
->table('media_orders')
|
||||
->whereNull('deleted_at')
|
||||
->orderBy('id')
|
||||
->get()
|
||||
->groupBy(fn ($item) => strtolower(trim($item->name)));
|
||||
|
||||
DB::table('cooperations')->updateOrInsert(
|
||||
['id' => $legacy->id],
|
||||
[
|
||||
'title' => Str::limit($legacy->name, 200),
|
||||
'initial_submission_date' => $legacy->begin,
|
||||
'final_submission_date' => $legacy->end,
|
||||
'description' => $legacy->description ?? '-',
|
||||
'status' => $status,
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
'deleted_at' => $legacy->deleted_at,
|
||||
]
|
||||
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'),
|
||||
);
|
||||
|
||||
// Task Assignment
|
||||
DB::table('task_assignments')->updateOrInsert(
|
||||
['id' => $legacy->id],
|
||||
[
|
||||
'cooperation_id' => $legacy->id,
|
||||
'start_date' => $legacy->begin,
|
||||
'end_date' => $legacy->end,
|
||||
'task_description' => $legacy->description ?? '-',
|
||||
'report_amount' => $legacy->amount_report ?? 1,
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
]
|
||||
$this->insertCooperationMedia(
|
||||
group: $group,
|
||||
cooperationId: $cooperationId,
|
||||
approvalStatus: ApprovalStatus::ACCEPTED->value,
|
||||
);
|
||||
|
||||
// Pivot Media
|
||||
if ($legacy->media) {
|
||||
$mediaIds = explode(',', $legacy->media);
|
||||
$statuses = explode(',', $legacy->status);
|
||||
foreach ($mediaIds as $index => $mediaId) {
|
||||
$mediaId = trim($mediaId);
|
||||
if (empty($mediaId)) {
|
||||
continue;
|
||||
}
|
||||
$startDate = Carbon::parse($group->max('end'))->addDay();
|
||||
$endDate = $startDate->copy()->addDays(7);
|
||||
|
||||
$mediaStatus = isset($statuses[$index]) ? trim($statuses[$index]) : '1';
|
||||
$approval = $this->mapApprovalStatus($mediaStatus);
|
||||
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(),
|
||||
]);
|
||||
|
||||
DB::table('cooperation_media')->updateOrInsert(
|
||||
['cooperation_id' => $legacy->id, 'partner_media_id' => $mediaId],
|
||||
['status' => $approval, 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now()]
|
||||
);
|
||||
$taskAssignmentId = (int) DB::getPdo()->lastInsertId();
|
||||
|
||||
DB::table('media_task_assignment')->updateOrInsert(
|
||||
['task_assignment_id' => $legacy->id, 'partner_media_id' => $mediaId],
|
||||
['status' => $approval, 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now()]
|
||||
);
|
||||
}
|
||||
$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->newLine();
|
||||
|
||||
// 2. Migrate media_cooperation -> cooperations & task_assignments
|
||||
$this->info('Migrating media_cooperation...');
|
||||
$legacyCoops = $legacyConn->table('media_cooperation')->get();
|
||||
$this->withProgressBar($legacyCoops, function ($legacy) use ($offset) {
|
||||
$newId = $legacy->id + $offset;
|
||||
$status = $legacy->deleted_at ? CooperationStatus::COMPLETED->value : CooperationStatus::PENDING->value;
|
||||
$this->info("Merged {$group->count()} rows → {$first->name}");
|
||||
}
|
||||
|
||||
DB::table('cooperations')->updateOrInsert(
|
||||
['id' => $newId],
|
||||
[
|
||||
'title' => Str::limit($legacy->name, 200),
|
||||
'initial_submission_date' => $legacy->begin,
|
||||
'final_submission_date' => $legacy->end,
|
||||
'description' => $legacy->description ?? '-',
|
||||
'status' => $status,
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
'deleted_at' => $legacy->deleted_at,
|
||||
]
|
||||
);
|
||||
$this->info('media_cooperation migration done.');
|
||||
}
|
||||
|
||||
// Task Assignment
|
||||
DB::table('task_assignments')->updateOrInsert(
|
||||
['id' => $newId],
|
||||
[
|
||||
'cooperation_id' => $newId,
|
||||
'start_date' => $legacy->begin,
|
||||
'end_date' => $legacy->end,
|
||||
'task_description' => $legacy->description ?? '-',
|
||||
'report_amount' => 1,
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
]
|
||||
);
|
||||
private function migrateProposals(): void
|
||||
{
|
||||
$this->info('Migrating propose_media_cooperation → cooperation_proposals...');
|
||||
|
||||
// Pivot Media
|
||||
if ($legacy->media) {
|
||||
$mediaIds = explode(',', $legacy->media);
|
||||
foreach ($mediaIds as $mediaId) {
|
||||
$mediaId = trim($mediaId);
|
||||
if (empty($mediaId)) {
|
||||
continue;
|
||||
}
|
||||
$proposals = DB::connection('mysql_second')
|
||||
->table('propose_media_cooperation')
|
||||
->whereNull('deleted_at')
|
||||
->get();
|
||||
|
||||
DB::table('cooperation_media')->updateOrInsert(
|
||||
['cooperation_id' => $newId, 'partner_media_id' => $mediaId],
|
||||
['status' => ApprovalStatus::PENDING->value, 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now()]
|
||||
);
|
||||
foreach ($proposals as $proposal) {
|
||||
$cooperationId = $this->legacyCoopMap[$proposal->media_cooperation_id] ?? null;
|
||||
|
||||
DB::table('media_task_assignment')->updateOrInsert(
|
||||
['task_assignment_id' => $newId, 'partner_media_id' => $mediaId],
|
||||
['status' => ApprovalStatus::PENDING->value, 'created_at' => $legacy->created_at ?? now(), 'updated_at' => $legacy->updated_at ?? now()]
|
||||
);
|
||||
}
|
||||
if (! $cooperationId) {
|
||||
$this->warn("cooperation not found for proposal {$proposal->id} (media_cooperation_id: {$proposal->media_cooperation_id})");
|
||||
|
||||
continue;
|
||||
}
|
||||
});
|
||||
$this->newLine();
|
||||
|
||||
// 3. Migrate proposals
|
||||
$this->info('Migrating proposals...');
|
||||
$legacyProposals = $legacyConn->table('propose_media_cooperation')->get();
|
||||
$this->withProgressBar($legacyProposals, function ($legacy) use ($offset) {
|
||||
$media = DB::table('partner_media')
|
||||
$partnerMediaId = DB::table('partner_media')
|
||||
->join('companies', 'partner_media.company_id', '=', 'companies.id')
|
||||
->where('companies.user_id', $legacy->enhancer)
|
||||
->select('partner_media.id')
|
||||
->first();
|
||||
->where('companies.user_id', $proposal->enhancer)
|
||||
->value('partner_media.id');
|
||||
|
||||
if (! $media) {
|
||||
return;
|
||||
if (! $partnerMediaId) {
|
||||
$this->warn("partner_media not found for proposal {$proposal->id} (enhancer/user_id: {$proposal->enhancer})");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('cooperation_proposals')->updateOrInsert(
|
||||
['id' => $legacy->id],
|
||||
[
|
||||
'cooperation_id' => $legacy->media_cooperation_id + $offset,
|
||||
'partner_media_id' => $media->id,
|
||||
'description' => $legacy->rejection_reason ?? '-',
|
||||
'e_catalog' => Str::limit($legacy->e_catalog, 200),
|
||||
'status' => $this->mapApprovalStatus($legacy->status),
|
||||
'submitted_at' => $legacy->created_at ?? now(),
|
||||
'responded_at' => $legacy->updated_at,
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
]
|
||||
);
|
||||
});
|
||||
$this->newLine();
|
||||
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(),
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. Migrate reports
|
||||
$this->info('Migrating reports...');
|
||||
$legacyReports = $legacyConn->table('reports')->get();
|
||||
$this->withProgressBar($legacyReports, function ($legacy) {
|
||||
// Find media_task_assignment_id
|
||||
// We assume media_order in reports refers to media_orders table primarily
|
||||
$assignment = DB::table('media_task_assignment')
|
||||
->where('task_assignment_id', $legacy->media_order)
|
||||
->where('partner_media_id', $legacy->media)
|
||||
->first();
|
||||
|
||||
if (! $assignment) {
|
||||
return;
|
||||
}
|
||||
|
||||
DB::table('reports')->updateOrInsert(
|
||||
['id' => $legacy->id],
|
||||
[
|
||||
'media_task_assignment_id' => $assignment->id,
|
||||
'title' => $legacy->title,
|
||||
'publication_date' => $legacy->broadcast ?? $legacy->created_at ?? now(),
|
||||
'link' => Str::limit($legacy->link, 50),
|
||||
'description' => 'Legacy Proof: '.($legacy->proof ?? '-'),
|
||||
'status' => $this->mapReportStatus($legacy->status),
|
||||
'created_at' => $legacy->created_at ?? now(),
|
||||
'updated_at' => $legacy->updated_at ?? now(),
|
||||
'deleted_at' => $legacy->deleted_at,
|
||||
]
|
||||
);
|
||||
});
|
||||
$this->newLine();
|
||||
|
||||
$this->info('Cooperation and report migration completed!');
|
||||
$this->info('proposals migration done.');
|
||||
}
|
||||
|
||||
private function mapApprovalStatus($legacy): int
|
||||
// =========================================================
|
||||
// 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 ((string) $legacy) {
|
||||
'1', '4' => ApprovalStatus::ACCEPTED->value,
|
||||
'2', '0' => ApprovalStatus::REJECTED->value, // Assume 0 is rejected/inactive in some contexts, but let's see
|
||||
return match ($legacy) {
|
||||
'accepted' => ApprovalStatus::ACCEPTED->value,
|
||||
'rejected' => ApprovalStatus::REJECTED->value,
|
||||
default => ApprovalStatus::PENDING->value,
|
||||
};
|
||||
}
|
||||
|
||||
private function mapReportStatus($legacy): int
|
||||
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
|
||||
{
|
||||
return match ((string) $legacy) {
|
||||
'1' => ApprovalStatus::ACCEPTED->value,
|
||||
'2' => ApprovalStatus::REJECTED->value,
|
||||
default => ApprovalStatus::PENDING->value,
|
||||
};
|
||||
$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.');
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user