diff --git a/app/Services/PrizeImportService.php b/app/Services/PrizeImportService.php index 58c1008..7b305e4 100644 --- a/app/Services/PrizeImportService.php +++ b/app/Services/PrizeImportService.php @@ -20,6 +20,10 @@ class PrizeImportService $failed = 0; $errors = []; + // Jejak susunan_cabutan yang telah dikosongkan (overwrite) dalam import ini, + // supaya item yang baru dimasukkan tidak dipadam semula oleh baris seterusnya. + $cleared = []; + foreach ($rows as $i => $row) { $line = $i + 2; @@ -35,6 +39,21 @@ class PrizeImportService $kodHadiah = trim($row['kod_hadiah'] ?? ''); $batch = $kodHadiah !== '' ? $kodHadiah : 'B' . str_pad((string) ($i + 1), 4, '0', STR_PAD_LEFT); + // Overwrite data lama jika susunan_cabutan adalah nombor yang sama. + if ($drawOrder > 0 && ! isset($cleared[$drawOrder])) { + $existing = Prize::where('draw_order', $drawOrder)->get(); + + if ($existing->contains(fn (Prize $p) => $p->status === Prize::STATUS_DISAHKAN)) { + $failed++; + $errors[] = "Baris {$line}: susunan_cabutan {$drawOrder} sudah ada pemenang disahkan, tidak boleh ditulis ganti."; + continue; + } + + $duplicate += $existing->count(); + Prize::where('draw_order', $drawOrder)->delete(); + $cleared[$drawOrder] = true; + } + try { foreach ($this->expand($nama, $kuantiti) as $index => $itemName) { Prize::create([ diff --git a/resources/views/admin/prizes/import.blade.php b/resources/views/admin/prizes/import.blade.php index 46879a4..f22110c 100644 --- a/resources/views/admin/prizes/import.blade.php +++ b/resources/views/admin/prizes/import.blade.php @@ -8,7 +8,8 @@
Muat Naik Fail

Format CSV atau XLSX. Lajur: kod_hadiah, nama_hadiah, kategori, nilai_anggaran, susunan_cabutan, kuantiti. - Jika kuantiti > 1, sistem akan jana beberapa item berasingan (cth Hamper #1 … #5).

+ Jika kuantiti > 1, sistem akan jana beberapa item berasingan (cth Hamper #1 … #5). + Data lama akan ditulis ganti jika susunan_cabutan adalah nombor yang sama (kecuali yang sudah ada pemenang disahkan).

@csrf @@ -25,6 +26,7 @@
{{ $result->total_rows }}
Baris
{{ $result->success_count }}
Item Dijana
+
{{ $result->duplicate_count }}
Ditulis Ganti
{{ $result->failed_count }}
Gagal
@if($result->errors) diff --git a/tests/Feature/ImportTest.php b/tests/Feature/ImportTest.php index d81b18e..6702dce 100644 --- a/tests/Feature/ImportTest.php +++ b/tests/Feature/ImportTest.php @@ -51,4 +51,34 @@ class ImportTest extends TestCase $this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Hamper #5', 'draw_order' => 3]); $this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Motosikal', 'draw_order' => 1]); } + + public function test_prize_import_overwrites_same_susunan_cabutan(): void + { + $service = new PrizeImportService(); + $service->import([['nama_hadiah' => 'Hadiah Lama', 'kuantiti' => '2', 'susunan_cabutan' => '1']], 'lama.csv'); + + $this->assertEquals(2, Prize::where('draw_order', 1)->count()); + + $log = $service->import([['nama_hadiah' => 'Hadiah Baru', 'kuantiti' => '1', 'susunan_cabutan' => '1']], 'baru.csv'); + + $this->assertEquals(1, $log->success_count); + $this->assertEquals(2, $log->duplicate_count); + $this->assertEquals(1, Prize::where('draw_order', 1)->count()); + $this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Hadiah Baru', 'draw_order' => 1]); + $this->assertDatabaseMissing('prizes', ['nama_hadiah' => 'Hadiah Lama']); + } + + public function test_prize_import_does_not_overwrite_confirmed_winner(): void + { + $service = new PrizeImportService(); + $service->import([['nama_hadiah' => 'Hadiah Disahkan', 'kuantiti' => '1', 'susunan_cabutan' => '1']], 'lama.csv'); + Prize::where('draw_order', 1)->update(['status' => Prize::STATUS_DISAHKAN]); + + $log = $service->import([['nama_hadiah' => 'Cuba Ganti', 'kuantiti' => '1', 'susunan_cabutan' => '1']], 'baru.csv'); + + $this->assertEquals(0, $log->success_count); + $this->assertEquals(1, $log->failed_count); + $this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Hadiah Disahkan']); + $this->assertDatabaseMissing('prizes', ['nama_hadiah' => 'Cuba Ganti']); + } }