125 lines
3.7 KiB
PHP
125 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class SyncPoliFromJson extends Command
|
|
{
|
|
protected $signature = 'poli:sync-json {--path= : Path file JSON poli, default database/seeders/data/poli.json} {--dry-run : Cek data tanpa menulis ke database}';
|
|
|
|
protected $description = 'Update atau create data poli dari file JSON berdasarkan id tanpa truncate.';
|
|
|
|
public function handle(): int
|
|
{
|
|
$path = $this->resolvePath($this->option('path') ?: database_path('seeders/data/poli.json'));
|
|
$data = $this->readJson($path);
|
|
|
|
$updated = 0;
|
|
$created = 0;
|
|
$unchanged = 0;
|
|
|
|
DB::transaction(function () use ($data, &$updated, &$created, &$unchanged) {
|
|
foreach ($data as $row) {
|
|
$id = (int) $row['id'];
|
|
$payload = [
|
|
'poli' => $row['poli'] ?? null,
|
|
'subpoli' => $row['subpoli'] ?? null,
|
|
'subsubpoli' => $row['subsubpoli'] ?? null,
|
|
'modaliti' => $row['modaliti'] ?? null,
|
|
'kelompok' => $row['kelompok'] ?? null,
|
|
'modaliti2' => isset($row['modaliti2']) ? (string) $row['modaliti2'] : null,
|
|
'created_at' => $row['created_at'] ?? now(),
|
|
'updated_at' => $row['updated_at'] ?? now(),
|
|
];
|
|
|
|
$existing = DB::table('poli')->where('id', $id)->first();
|
|
|
|
if ($existing === null) {
|
|
$created++;
|
|
|
|
if (!$this->option('dry-run')) {
|
|
DB::table('poli')->insert(array_merge(['id' => $id], $payload));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if ($this->isSameRow($existing, $payload)) {
|
|
$unchanged++;
|
|
continue;
|
|
}
|
|
|
|
$updated++;
|
|
|
|
if (!$this->option('dry-run')) {
|
|
DB::table('poli')->where('id', $id)->update($payload);
|
|
}
|
|
}
|
|
});
|
|
|
|
$mode = $this->option('dry-run') ? 'DRY RUN' : 'DONE';
|
|
$this->info("{$mode}: {$created} created, {$updated} updated, {$unchanged} unchanged.");
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
private function resolvePath(string $path): string
|
|
{
|
|
if ($path !== '' && $path[0] === '/') {
|
|
return $path;
|
|
}
|
|
|
|
return base_path($path);
|
|
}
|
|
|
|
private function readJson(string $path): array
|
|
{
|
|
if (!is_file($path)) {
|
|
throw new \RuntimeException("File JSON poli tidak ditemukan: {$path}");
|
|
}
|
|
|
|
$json = file_get_contents($path);
|
|
|
|
if ($json === false) {
|
|
throw new \RuntimeException("Gagal membaca file JSON poli: {$path}");
|
|
}
|
|
|
|
$data = json_decode($json, true);
|
|
|
|
if (!is_array($data)) {
|
|
throw new \RuntimeException("Format JSON poli tidak valid: {$path}");
|
|
}
|
|
|
|
$ids = [];
|
|
|
|
foreach ($data as $index => $row) {
|
|
if (!is_array($row) || !isset($row['id'])) {
|
|
throw new \RuntimeException('Data poli baris '.($index + 1).' tidak memiliki id.');
|
|
}
|
|
|
|
$id = (int) $row['id'];
|
|
|
|
if (isset($ids[$id])) {
|
|
throw new \RuntimeException("Duplikasi id poli pada JSON: {$id}");
|
|
}
|
|
|
|
$ids[$id] = true;
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
private function isSameRow(object $existing, array $payload): bool
|
|
{
|
|
foreach ($payload as $key => $value) {
|
|
if ((string) ($existing->{$key} ?? '') !== (string) ($value ?? '')) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|