Files
cabutan-bertuah-koipb/app/Services/PrizeImportService.php
2026-06-26 18:43:09 +08:00

112 lines
3.7 KiB
PHP

<?php
namespace App\Services;
use App\Models\ImportLog;
use App\Models\Prize;
class PrizeImportService
{
/**
* Import baris hadiah. Jika kuantiti > 1, generate beberapa item berasingan
* (cth Hamper #1 .. Hamper #5).
*
* @param array<int, array<string, string>> $rows
*/
public function import(array $rows, string $filename, ?int $userId = null): ImportLog
{
$success = 0;
$duplicate = 0;
$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;
$nama = trim($row['nama_hadiah'] ?? '');
if ($nama === '') {
$failed++;
$errors[] = "Baris {$line}: nama_hadiah wajib diisi.";
continue;
}
$kuantiti = max(1, (int) ($row['kuantiti'] ?? 1));
$drawOrder = (int) ($row['susunan_cabutan'] ?? ($row['draw_order'] ?? 0));
$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([
'kod_hadiah' => $kodHadiah ?: null,
'nama_hadiah' => $itemName,
'kategori' => trim($row['kategori'] ?? '') ?: null,
'nilai_anggaran' => $this->parseDecimal($row['nilai_anggaran'] ?? ''),
'draw_order' => $drawOrder,
'item_index' => $index,
'batch_kod' => $batch,
'status' => Prize::STATUS_BELUM,
]);
$success++;
}
} catch (\Throwable $e) {
$failed++;
$errors[] = "Baris {$line}: {$e->getMessage()}";
}
}
return ImportLog::create([
'type' => 'prizes',
'filename' => $filename,
'total_rows' => count($rows),
'success_count' => $success,
'duplicate_count' => $duplicate,
'failed_count' => $failed,
'errors' => $errors ?: null,
'imported_by' => $userId,
]);
}
/**
* @return array<int, string> diindeks dari 1
*/
public function expand(string $nama, int $kuantiti): array
{
if ($kuantiti <= 1) {
return [1 => $nama];
}
$items = [];
for ($n = 1; $n <= $kuantiti; $n++) {
$items[$n] = "{$nama} #{$n}";
}
return $items;
}
private function parseDecimal(string $value): ?float
{
$value = trim(str_replace([',', 'RM', 'rm'], '', $value));
return $value === '' ? null : (float) $value;
}
}