feat: Introduce data migration commands for various core entities including company, location, theme, and other

This commit is contained in:
Yoga Pangestu 2026-02-04 14:04:21 +07:00
parent d2c7bce033
commit 30f0a09c84
13 changed files with 1315 additions and 0 deletions

View File

@ -0,0 +1,62 @@
<?php
namespace App\Console\Commands;
use App\Enums\AnnouncementType;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MigrateAnnouncementCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:announcement';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate announcement data from legacy news table where category = 1';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting announcement migration...');
$legacyConn = DB::connection('mysql_second');
// Get legacy news with category 1 (Announcements)
$legacyAnnouncements = $legacyConn->table('news')
->where('category', '1')
->get();
if ($legacyAnnouncements->isEmpty()) {
$this->warn('No announcements found with category 1.');
return;
}
$this->withProgressBar($legacyAnnouncements, function ($legacy) {
DB::table('announcements')->updateOrInsert(
['id' => $legacy->id],
[
'title' => $legacy->title,
'content' => $legacy->content,
'type' => AnnouncementType::PUBLIC->value,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Announcement migration completed successfully!');
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MigrateClassificationCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:classification';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate classification data from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting classification migration...');
$legacyConn = DB::connection('mysql_second');
$newConn = DB::connection('mysql');
// Migrate Classifications
$this->info('Migrating classifications...');
$legacyClassifications = $legacyConn->table('classifications')->get();
$this->withProgressBar($legacyClassifications, function ($legacy) {
DB::table('classifications')->updateOrInsert(
['id' => $legacy->id],
[
'name' => $legacy->name,
'is_active' => $legacy->status == '1' ? IsActive::ACTIVE->value : IsActive::INACTIVE->value,
'sort_order' => $legacy->enhancer ?? 0,
'created_at' => $legacy->created_at,
'updated_at' => $legacy->updated_at,
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
// Migrate Sub Classifications
$this->info('Migrating sub classifications...');
$legacySubClassifications = $legacyConn->table('sub_classifications')->get();
$this->withProgressBar($legacySubClassifications, function ($legacy) {
DB::table('sub_classifications')->updateOrInsert(
['id' => $legacy->id],
[
'classification_id' => $legacy->classification,
'name' => $legacy->name,
'is_active' => $legacy->status == '1' ? IsActive::ACTIVE->value : IsActive::INACTIVE->value,
'sort_order' => $legacy->enhancer ?? 0,
'created_at' => $legacy->created_at,
'updated_at' => $legacy->updated_at,
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Migration completed successfully!');
}
}

View File

@ -0,0 +1,183 @@
<?php
namespace App\Console\Commands;
use App\Enums\MediaClassification;
use App\Enums\MediaType;
use App\Enums\VerificationStatus;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateCompanyCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:company';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate companies, partner media, and verification requests from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting company migration...');
$legacyConn = DB::connection('mysql_second');
$legacyCompanies = $legacyConn->table('companies')->get();
if ($legacyCompanies->isEmpty()) {
$this->warn('No companies found in legacy database.');
return;
}
$this->withProgressBar($legacyCompanies, function ($legacy) use ($legacyConn) {
// Find user in NEW database. Legcy enhancer is the user_id.
$user = DB::table('users')->where('id', $legacy->enhancer)->first();
// If not found by ID, try by email (sometimes IDs change during user migration if not careful)
if (! $user) {
$user = DB::table('users')->where('email', $legacy->email)->first();
}
if (! $user) {
// If user still not found, we skip this company for now as it's orphaned
return;
}
// 1. Migrate Company
DB::table('companies')->updateOrInsert(
['id' => $legacy->id],
[
'user_id' => $user->id,
'name' => $legacy->name,
'email' => $legacy->email,
'address' => $legacy->address,
'director_name' => $legacy->director,
'director_nik' => $legacy->nick_director,
'deed_incorporation' => str()->limit($legacy->deed_of_establishment, 150, ''),
'trade_license' => str()->limit($legacy->trade_license, 150, ''),
'tax_id_number' => str()->limit($legacy->tax_id_number, 150, ''),
'taxable_enterprise' => str()->limit($legacy->taxable_enterprise, 150, ''),
'annual_tax_return' => str()->limit($legacy->annual_tax_statement, 150, ''),
'domicile_certificate' => str()->limit($legacy->domicile, 150, ''),
'profile' => str()->limit($legacy->profile ?? '-', 150, ''),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
// 2. Migrate Verification Request
$status = $this->mapVerificationStatus($legacy->status_edit);
DB::table('verification_requests')->updateOrInsert(
['company_id' => $legacy->id],
[
'submitted_by' => $user->id,
'status' => $status,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
]
);
// 3. Migrate Partner Media (from legacy 'media' table matching company ID)
$legacyMediaList = $legacyConn->table('media')->where('company', $legacy->id)->get();
foreach ($legacyMediaList as $legacyMedia) {
DB::table('partner_media')->updateOrInsert(
['id' => $legacyMedia->id],
[
'company_id' => $legacy->id,
'name' => $legacyMedia->name,
'address' => $legacyMedia->address,
'link' => $this->extractMediaLink($legacyMedia->link),
'type' => $this->mapMediaType($legacyMedia->type),
'classification' => $this->mapMediaClassification($legacyMedia->classification),
'journalism_organization' => $legacyMedia->organization,
'press_council_certificate' => $legacyMedia->certificate,
'created_at' => $legacyMedia->created_at ?? now(),
'updated_at' => $legacyMedia->updated_at ?? now(),
'deleted_at' => $legacyMedia->deleted_at,
]
);
}
});
$this->newLine();
$this->info('Company migration completed successfully!');
}
private function mapVerificationStatus($legacyStatus): int
{
return match ((string) $legacyStatus) {
'1', '3' => VerificationStatus::APPROVED->value,
'2' => VerificationStatus::REJECTED->value,
default => VerificationStatus::PENDING->value,
};
}
private function mapMediaType($legacyType): int
{
return match (strtolower($legacyType ?? '')) {
'online' => MediaType::ONLINE->value,
'cetak' => MediaType::PRINT->value,
'radio' => MediaType::RADIO->value,
'televisi' => MediaType::TELEVISION->value,
default => MediaType::ONLINE->value,
};
}
private function mapMediaClassification($legacyClass): int
{
return match (strtolower($legacyClass ?? '')) {
'lokal' => MediaClassification::LOCAL->value,
'regional' => MediaClassification::REGIONAL->value,
'nasional' => MediaClassification::NATIONAL->value,
default => MediaClassification::LOCAL->value,
};
}
private function extractMediaLink(?string $link): ?string
{
if (empty($link)) {
return null;
}
// Find all URLs (starts with http or https)
preg_match_all('/(https?:\/\/[^\s]+)/i', $link, $matches);
// If no URL found, return the original string truncated
if (empty($matches[0])) {
return Str::limit($link, 50, '');
}
// Try to find the main media website URL
foreach ($matches[0] as $url) {
$url = rtrim($url, ','); // clean trailing comma if any
// Skip common non-media-website URLs if there's an alternative
if (count($matches[0]) > 1 && (
str_contains($url, 'google.') ||
str_contains($url, 'drive.') ||
str_contains($url, 'share.') ||
str_contains($url, 'bit.ly')
)) {
continue;
}
return Str::limit($url, 50, '');
}
// Fallback to the first URL found
return Str::limit($matches[0][0], 50, '');
}
}

View File

@ -0,0 +1,116 @@
<?php
namespace App\Console\Commands;
use App\Enums\ContentType;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateContentRecapCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:content-recap';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate content recap data from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting content recap migration...');
$legacyConn = DB::connection('mysql_second');
// 1. Migrate Classifications first
$this->info('Migrating classifications for content recap...');
$legacyRecapClasses = $legacyConn->table('content_recap_classifications')->get();
$classMapping = [];
foreach ($legacyRecapClasses as $legacyClass) {
// Check by name to avoid duplicates in classifications table
$existing = DB::table('classifications')->where('name', $legacyClass->name)->first();
if ($existing) {
$classMapping[$legacyClass->id] = $existing->id;
} else {
$newId = DB::table('classifications')->insertGetId([
'name' => $legacyClass->name,
'is_active' => IsActive::ACTIVE->value,
'sort_order' => 0,
'created_at' => $legacyClass->created_at ?? now(),
'updated_at' => $legacyClass->updated_at ?? now(),
'deleted_at' => $legacyClass->deleted_at,
]);
$classMapping[$legacyClass->id] = $newId;
}
}
// 2. Migrate Content Recaps
$this->info('Migrating content recaps...');
$legacyRecaps = $legacyConn->table('content_recap')->get();
if ($legacyRecaps->isEmpty()) {
$this->warn('No content recaps found in legacy database.');
return;
}
$this->withProgressBar($legacyRecaps, function ($legacy) use ($classMapping) {
$classificationId = $classMapping[$legacy->classification_id] ?? null;
// Fallback for classification if not found in master table mapping
if (! $classificationId && $legacy->classification) {
$classificationId = DB::table('classifications')
->where('name', $legacy->classification)
->value('id');
}
// If still no classification, skip or use a default one?
// The table requires classification_id so we must have one.
if (! $classificationId) {
return; // Skip if no classification
}
DB::table('content_recaps')->updateOrInsert(
['id' => $legacy->id],
[
'classification_id' => $classificationId,
'title' => $legacy->title,
'link' => Str::limit($legacy->link, 50, ''),
'posting_date' => $legacy->posting_date === '0000-00-00' ? now()->toDateString() : $legacy->posting_date,
'type' => $this->mapContentType($legacy->content_type),
'channel' => Str::limit($legacy->channel, 20, ''),
'social_media' => Str::limit($legacy->social_media ?? '-', 50, ''),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Content recap migration completed successfully!');
}
private function mapContentType(?string $legacyType): string
{
return match (strtolower($legacyType ?? '')) {
'foto' => ContentType::FOTO->value,
'grafis' => ContentType::GRAPHIC->value,
'audio video' => ContentType::VIDEO->value,
default => ContentType::FOTO->value,
};
}
}

View File

@ -0,0 +1,239 @@
<?php
namespace App\Console\Commands;
use App\Enums\ApprovalStatus;
use App\Enums\CooperationStatus;
use Illuminate\Console\Command;
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';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting comprehensive cooperation and report migration...');
$legacyConn = DB::connection('mysql_second');
$offset = 10000;
// 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;
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,
]
);
// 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(),
]
);
// 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;
}
$mediaStatus = isset($statuses[$index]) ? trim($statuses[$index]) : '1';
$approval = $this->mapApprovalStatus($mediaStatus);
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()]
);
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->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;
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,
]
);
// 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(),
]
);
// Pivot Media
if ($legacy->media) {
$mediaIds = explode(',', $legacy->media);
foreach ($mediaIds as $mediaId) {
$mediaId = trim($mediaId);
if (empty($mediaId)) {
continue;
}
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()]
);
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()]
);
}
}
});
$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')
->join('companies', 'partner_media.company_id', '=', 'companies.id')
->where('companies.user_id', $legacy->enhancer)
->select('partner_media.id')
->first();
if (! $media) {
return;
}
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();
// 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' => Str::limit($legacy->title, 200),
'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!');
}
private function mapApprovalStatus($legacy): int
{
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
default => ApprovalStatus::PENDING->value,
};
}
private function mapReportStatus($legacy): int
{
return match ((string) $legacy) {
'1' => ApprovalStatus::ACCEPTED->value,
'2' => ApprovalStatus::REJECTED->value,
default => ApprovalStatus::PENDING->value,
};
}
}

View File

@ -0,0 +1,57 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateDepartmentCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:department';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate department data from legacy agencies table';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting department migration...');
$legacyConn = DB::connection('mysql_second');
// Migrate Departments (Agencies)
$this->info('Migrating departments...');
$legacyAgencies = $legacyConn->table('agencies')->get();
$this->withProgressBar($legacyAgencies, function ($legacy) {
DB::table('departments')->updateOrInsert(
['id' => $legacy->id],
[
'name' => $legacy->name,
'alias' => Str::limit($legacy->name, 20, ''),
'is_active' => IsActive::ACTIVE->value,
'sort_order' => 0,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Migration completed successfully!');
}
}

View File

@ -0,0 +1,76 @@
<?php
namespace App\Console\Commands;
use App\Enums\IssueSentiment;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MigrateIssueManagementCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:issue-management';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate issue management data from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting issue management migration...');
$legacyConn = DB::connection('mysql_second');
// Get legacy issue management
$legacyIssues = $legacyConn->table('issue_management')->get();
if ($legacyIssues->isEmpty()) {
$this->warn('No issue management records found in legacy database.');
return;
}
$this->withProgressBar($legacyIssues, function ($legacy) {
DB::table('issue_management')->updateOrInsert(
['id' => $legacy->id],
[
'media_monitoring_id' => $legacy->media_monitoring,
'location_id' => $legacy->locus,
'sub_location_id' => $legacy->sub_locus,
'classification_id' => $legacy->classification,
'sub_classification_id' => $legacy->sub_classification,
'issue' => $this->mapSentiment($legacy->issue),
'response' => $this->mapSentiment($legacy->response),
'description' => $legacy->description ?? '-',
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Issue management migration completed successfully!');
}
private function mapSentiment(string $legacyValue): string
{
return match (strtolower($legacyValue)) {
'positif' => IssueSentiment::POSITIVE->value,
'negatif' => IssueSentiment::NEGATIVE->value,
'netral' => IssueSentiment::NEUTRAL->value,
'krisis' => IssueSentiment::CRISIS->value,
default => IssueSentiment::NEUTRAL->value,
};
}
}

View File

@ -0,0 +1,70 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateJournalistCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:journalist';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate journalists from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting journalist migration...');
$legacyConn = DB::connection('mysql_second');
$legacyJournalists = $legacyConn->table('journalists')->get();
if ($legacyJournalists->isEmpty()) {
$this->warn('No journalists found in legacy database.');
return;
}
$this->withProgressBar($legacyJournalists, function ($legacy) {
// Find corresponding partner media (outlet) in the NEW database
// legacy 'media' column is the partner_media_id
$partnerMedia = DB::table('partner_media')->where('id', $legacy->media)->first();
if (! $partnerMedia) {
// If partner media doesn't exist, we skip as it's required
return;
}
DB::table('journalists')->updateOrInsert(
['id' => $legacy->id],
[
'partner_media_id' => $partnerMedia->id,
'name' => Str::limit($legacy->name, 100),
'email' => Str::limit($legacy->email, 254),
'phone_number' => Str::limit($legacy->phone, 20),
'press_card' => Str::limit($legacy->press_card, 100),
'ukw_certificate' => Str::limit($legacy->certificate, 100),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Journalist migration completed successfully!');
}
}

View File

@ -0,0 +1,75 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MigrateLocationCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:location';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate location data from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting location migration...');
$legacyConn = DB::connection('mysql_second');
// Migrate Locations (Locuses)
$this->info('Migrating locations...');
$legacyLocations = $legacyConn->table('locuses')->get();
$this->withProgressBar($legacyLocations, function ($legacy) {
DB::table('locations')->updateOrInsert(
['id' => $legacy->id],
[
'name' => $legacy->name,
'is_active' => $legacy->status == '1' ? IsActive::ACTIVE->value : IsActive::INACTIVE->value,
'sort_order' => $legacy->enhancer ?? 0,
'created_at' => $legacy->created_at,
'updated_at' => $legacy->updated_at,
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
// Migrate Sub Locations (Sub Locuses)
$this->info('Migrating sub locations...');
$legacySubLocations = $legacyConn->table('sub_locuses')->get();
$this->withProgressBar($legacySubLocations, function ($legacy) {
DB::table('sub_locations')->updateOrInsert(
['id' => $legacy->id],
[
'location_id' => $legacy->locus,
'name' => $legacy->name,
'is_active' => $legacy->status == '1' ? IsActive::ACTIVE->value : IsActive::INACTIVE->value,
'sort_order' => $legacy->enhancer ?? 0,
'created_at' => $legacy->created_at,
'updated_at' => $legacy->updated_at,
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Migration completed successfully!');
}
}

View File

@ -0,0 +1,100 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateMediaMonitoringCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:media-monitoring';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate media monitoring data from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting media monitoring migration...');
$legacyConn = DB::connection('mysql_second');
// Get legacy monitorings
$legacyMonitorings = $legacyConn->table('media_monitorings')->get();
if ($legacyMonitorings->isEmpty()) {
$this->warn('No media monitorings found in legacy database.');
return;
}
$this->withProgressBar($legacyMonitorings, function ($legacy) {
// Main record
DB::table('media_monitorings')->updateOrInsert(
['id' => $legacy->id],
[
'code' => Str::limit($legacy->code, 10, ''),
'media_name' => Str::limit($legacy->media_name, 50, ''),
'title' => $legacy->title,
'channel' => Str::limit($legacy->channel, 20, ''),
'writter' => Str::limit($legacy->writter, 50, ''),
'link' => $legacy->link,
'news_page' => Str::limit($legacy->news_page, 20, ''),
'quote' => $legacy->quote,
'content' => $legacy->content,
'influencer' => Str::limit($legacy->influencer, 50, ''),
'keyword' => Str::limit($legacy->keyword, 100, ''),
'release_date' => $legacy->release_date,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
// Handle Theme (Insert into themes table if not exists)
$themeName = trim($legacy->theme);
if (! empty($themeName)) {
$themeName = Str::limit($themeName, 50, '');
// Ensure theme exists in master table
DB::table('themes')->updateOrInsert(
['name' => $themeName],
[
'is_active' => IsActive::ACTIVE->value,
'sort_order' => 0,
'created_at' => now(),
'updated_at' => now(),
]
);
$themeId = DB::table('themes')->where('name', $themeName)->value('id');
// Link to pivot table
if ($themeId) {
DB::table('media_monitoring_theme')->updateOrInsert(
[
'media_monitoring_id' => $legacy->id,
'theme_id' => $themeId,
]
);
}
}
});
$this->newLine();
$this->info('Media monitoring migration completed successfully!');
}
}

View File

@ -0,0 +1,85 @@
<?php
namespace App\Console\Commands;
use App\Enums\NewsStatus;
use App\Models\News;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
class MigrateNewsCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:news';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate news data from legacy table where category = 1';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting news migration...');
$legacyConn = DB::connection('mysql_second');
// Get legacy news with category 1
$legacyNews = $legacyConn->table('news')
->where('category', '0')
->get();
if ($legacyNews->isEmpty()) {
$this->warn('No news found with category 1.');
return;
}
// Get a default author ID (prefer Developer or Admin)
$defaultAuthorId = DB::table('users')->first()?->id ?? 1;
$this->withProgressBar($legacyNews, function ($legacy) use ($defaultAuthorId) {
// Use updateOrInsert for the basic record
DB::table('news')->updateOrInsert(
['id' => $legacy->id],
[
'author_id' => $defaultAuthorId,
'title' => $legacy->title,
'slug' => Str::slug($legacy->title).'-'.$legacy->id,
'content' => $legacy->content,
'excerpt' => Str::limit(strip_tags($legacy->content), 160),
'link' => $legacy->link ? Str::limit($legacy->link, 50, '') : null,
'views' => 0,
'status' => NewsStatus::PUBLISHED->value,
'published_at' => $legacy->created_at,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
// Handle Tags using the Model (if tag exists in legacy)
if (! empty($legacy->tag)) {
$news = News::find($legacy->id);
if ($news) {
// split by comma or other delimiter if multiple tags,
// legacy 'tag' column is varchar(20), likely a single tag or comma separated
$tags = array_map('trim', explode(',', $legacy->tag));
$news->syncTags($tags);
}
}
});
$this->newLine();
$this->info('News migration completed successfully!');
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class MigrateThemeCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:theme';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate theme data from legacy proof_airing_themes table';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting theme migration...');
$legacyConn = DB::connection('mysql_second');
// Get legacy themes
$legacyThemes = $legacyConn->table('proof_airing_themes')->get();
if ($legacyThemes->isEmpty()) {
$this->warn('No themes found in legacy database.');
return;
}
$this->withProgressBar($legacyThemes, function ($legacy) {
DB::table('themes')->updateOrInsert(
['id' => $legacy->id],
[
'name' => $legacy->name,
'is_active' => IsActive::ACTIVE->value,
'sort_order' => 0,
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
'deleted_at' => $legacy->deleted_at,
]
);
});
$this->newLine();
$this->info('Theme migration completed successfully!');
}
}

View File

@ -0,0 +1,116 @@
<?php
namespace App\Console\Commands;
use App\Enums\IsActive;
use App\Enums\RoleEnum;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class MigrateUserCommand extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'migrate:user';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Migrate users from legacy database';
/**
* Execute the console command.
*/
public function handle()
{
$this->info('Starting user migration...');
$legacyConn = DB::connection('mysql_second');
$legacyUsers = $legacyConn->table('users')->get();
if ($legacyUsers->isEmpty()) {
$this->warn('No users found in legacy database.');
return;
}
$this->withProgressBar($legacyUsers, function ($legacy) {
// Skip if user already exists with same email, but ensure role is synced if needed
$user = User::where('email', $legacy->email)->first();
if (! $user) {
$username = $this->generateUniqueUsername($legacy->name, $legacy->email);
// Using DB facade directly to insert ensures the legacy password hash
// is NOT double-hashed by the model's "hashed" cast.
$userId = DB::table('users')->insertGetId([
'name' => Str::limit($legacy->name, 100),
'email' => $legacy->email,
'username' => $username,
'password' => $legacy->password, // Preserving legacy hash
'is_active' => $legacy->status == '1' ? IsActive::ACTIVE->value : IsActive::INACTIVE->value,
'email_verified_at' => now(),
'created_at' => $legacy->created_at ?? now(),
'updated_at' => $legacy->updated_at ?? now(),
]);
$user = User::find($userId);
}
// Map and Assign Role
$roleName = $this->mapRole($legacy->role);
if ($roleName && $user) {
$user->syncRoles([$roleName]);
}
});
$this->newLine();
$this->info('User migration completed successfully!');
}
private function generateUniqueUsername($name, $email)
{
// Try name first
$base = Str::limit(Str::slug($name, ''), 10, '');
if (empty($base)) {
$base = Str::limit(explode('@', $email)[0], 10, '');
}
$username = $base;
$counter = 1;
// Ensure unique within 10 chars
while (User::where('username', $username)->exists()) {
$suffix = (string) $counter;
$maxBaseLength = 10 - strlen($suffix);
$username = substr($base, 0, $maxBaseLength).$suffix;
$counter++;
if ($counter > 999) {
break;
} // Safety
}
return $username;
}
private function mapRole($legacyRole): ?string
{
return match ((int) $legacyRole) {
1 => RoleEnum::ADMINISTRATOR->value,
2 => RoleEnum::ADMIN_MONITORING->value,
3 => RoleEnum::PERUSAHAAN->value,
4 => RoleEnum::ADMIN_KONTEN->value,
5 => RoleEnum::ADMIN_KEUANGAN->value,
default => null,
};
}
}