overwrite hadiah

This commit is contained in:
Saufi
2026-06-26 18:43:09 +08:00
parent 4075717506
commit 1c8d2ef8ff
3 changed files with 52 additions and 1 deletions

View File

@@ -20,6 +20,10 @@ class PrizeImportService
$failed = 0; $failed = 0;
$errors = []; $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) { foreach ($rows as $i => $row) {
$line = $i + 2; $line = $i + 2;
@@ -35,6 +39,21 @@ class PrizeImportService
$kodHadiah = trim($row['kod_hadiah'] ?? ''); $kodHadiah = trim($row['kod_hadiah'] ?? '');
$batch = $kodHadiah !== '' ? $kodHadiah : 'B' . str_pad((string) ($i + 1), 4, '0', STR_PAD_LEFT); $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 { try {
foreach ($this->expand($nama, $kuantiti) as $index => $itemName) { foreach ($this->expand($nama, $kuantiti) as $index => $itemName) {
Prize::create([ Prize::create([

View File

@@ -8,7 +8,8 @@
<div class="card"><div class="card-body"> <div class="card"><div class="card-body">
<h5 class="fw-bold"><i class="bi bi-upload text-teal"></i> Muat Naik Fail</h5> <h5 class="fw-bold"><i class="bi bi-upload text-teal"></i> Muat Naik Fail</h5>
<p class="text-muted small">Format CSV atau XLSX. Lajur: <code>kod_hadiah, nama_hadiah, kategori, nilai_anggaran, susunan_cabutan, kuantiti</code>. <p class="text-muted small">Format CSV atau XLSX. Lajur: <code>kod_hadiah, nama_hadiah, kategori, nilai_anggaran, susunan_cabutan, kuantiti</code>.
Jika <b>kuantiti &gt; 1</b>, sistem akan jana beberapa item berasingan (cth Hamper #1 … #5).</p> Jika <b>kuantiti &gt; 1</b>, sistem akan jana beberapa item berasingan (cth Hamper #1 … #5).
Data lama akan <b>ditulis ganti</b> jika <code>susunan_cabutan</code> adalah nombor yang sama (kecuali yang sudah ada pemenang disahkan).</p>
<form method="POST" action="{{ route('admin.prizes.import.store') }}" enctype="multipart/form-data"> <form method="POST" action="{{ route('admin.prizes.import.store') }}" enctype="multipart/form-data">
@csrf @csrf
<input type="file" name="file" class="form-control mb-2 @error('file') is-invalid @enderror" accept=".csv,.xlsx,.xls" required> <input type="file" name="file" class="form-control mb-2 @error('file') is-invalid @enderror" accept=".csv,.xlsx,.xls" required>
@@ -25,6 +26,7 @@
<div class="row text-center g-2 my-2"> <div class="row text-center g-2 my-2">
<div class="col"><div class="stat-card bg-teal py-2"><div class="value fs-4">{{ $result->total_rows }}</div><div class="label">Baris</div></div></div> <div class="col"><div class="stat-card bg-teal py-2"><div class="value fs-4">{{ $result->total_rows }}</div><div class="label">Baris</div></div></div>
<div class="col"><div class="stat-card bg-green py-2"><div class="value fs-4">{{ $result->success_count }}</div><div class="label">Item Dijana</div></div></div> <div class="col"><div class="stat-card bg-green py-2"><div class="value fs-4">{{ $result->success_count }}</div><div class="label">Item Dijana</div></div></div>
<div class="col"><div class="stat-card bg-gold py-2"><div class="value fs-4">{{ $result->duplicate_count }}</div><div class="label">Ditulis Ganti</div></div></div>
<div class="col"><div class="stat-card bg-red py-2"><div class="value fs-4">{{ $result->failed_count }}</div><div class="label">Gagal</div></div></div> <div class="col"><div class="stat-card bg-red py-2"><div class="value fs-4">{{ $result->failed_count }}</div><div class="label">Gagal</div></div></div>
</div> </div>
@if($result->errors) @if($result->errors)

View File

@@ -51,4 +51,34 @@ class ImportTest extends TestCase
$this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Hamper #5', 'draw_order' => 3]); $this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Hamper #5', 'draw_order' => 3]);
$this->assertDatabaseHas('prizes', ['nama_hadiah' => 'Motosikal', 'draw_order' => 1]); $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']);
}
} }