Files

111 lines
4.7 KiB
PHP
Raw Permalink Normal View History

2026-06-01 15:01:03 +07:00
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
class MigrateOldExpenseData extends Command
{
// Perintah yang akan dieksekusi di terminal
protected $signature = 'expense:migrate-old';
protected $description = 'Migrasi data transaksional paling update dari expense-old ke database expense (v2.0) secara aman';
public function handle()
{
$this->info('Memulai Proses Sinkronisasi: Memindahkan data update dari [expense-old] ke [expense]...');
// Daftar tabel yang akan disinkronkan (Nama tabel diasumsikan sama pada kedua versi)
$tablesToMigrate = [
'form_up_country' => 'form_up_country',
'form_vehicle_running_cost' => 'form_vehicle_running_cost',
'form_entertainment_presentation' => 'form_entertainment_presentation',
'form_meeting_seminar' => 'form_meeting_seminar',
'form_others' => 'form_others',
];
foreach ($tablesToMigrate as $oldTable => $newTable) {
$this->comment("--------------------------------------------------");
$this->comment("Memproses Tabel Target: {$newTable}");
// 1. Validasi eksistensi tabel di database tujuan (expense)
if (!Schema::hasTable($newTable)) {
$this->error("Tabel [{$newTable}] tidak ditemukan di database 'expense'. Melewati tabel ini.");
continue;
}
// 2. Ambil list kolom lengkap yang ada di database tujuan (expense)
$destinationColumns = Schema::getColumnListing($newTable);
// 3. Ambil data transaksional paling update dari database lama (expense-old)
$oldData = DB::connection('mysql_lama')->table($oldTable)->get();
$insertedCount = 0;
$skippedCount = 0;
foreach ($oldData as $row) {
// 4. PROTEKSI ANTI-OVERWRITE: Cek apakah data sudah ada di database 'expense'
$isExists = DB::table($newTable)
->where('expense_number', $row->expense_number)
->exists();
if (!$isExists) {
$insertData = [];
// 5. MAPPING DATA SECARA DINAMIS
foreach ($destinationColumns as $column) {
// KUNCI PENYEMPURNAAN: Jangan bawa ID lama agar tidak tabrakan dengan Auto-Increment di DB baru
if ($column === 'id') {
continue;
}
// Jika kolom dari database baru tersedia di data 'expense-old', ambil nilainya
if (property_exists($row, $column) && !is_null($row->$column)) {
$insertData[$column] = $row->$column;
} else {
// Jika kolom baru versi 2.0 tidak ada di database lama / bernilai NULL, isi dengan nilai default aman
$insertData[$column] = $this->getDefaultValueForColumn($newTable, $column);
}
}
// 6. Jalankan amunisi Insert ke database utama (expense)
DB::table($newTable)->insert($insertData);
$insertedCount++;
} else {
$skippedCount++;
}
}
$this->info("Tabel [{$newTable}] Selesai: Masuk {$insertedCount} data baru. Diabaikan (Sudah ada) {$skippedCount} data.");
}
$this->info('==================================================');
$this->info('Sukses! Seluruh data dari [expense-old] telah bermigrasi ke [expense] dengan aman.');
}
/**
* Fallback Nilai Default untuk Kolom Baru Struktur Aplikasi 2.0
*/
private function getDefaultValueForColumn($tableName, $columnName)
{
// POINT 1: Solusi otomatisasi penanganan cabang_id yang NULL pada tabel entertainment
if ($tableName === 'form_entertainment_presentation' && $columnName === 'cabang_id') {
return 1; // Ganti angka 1 dengan ID Cabang default existing Anda
}
// Pengondisian khusus untuk kolom-kolom baru krusial di versi 2.0 Anda
if ($columnName === 'account_number') {
return '-';
}
if ($columnName === 'approved_total') {
return 0;
}
if ($columnName === 'approved_at' || $columnName === 'approved2_at' || $columnName === 'final_approved_at') {
return null;
}
// Nilai bawaan jika tidak masuk kategori spesifik di atas
return null;
}
}