'date', 'expired_at' => 'date', 'qty' => 'float', // Mendukung dosis desimal (misal 2.5 ml) 'created_at' => 'datetime', ]; } /** * Logic Otomatisasi & Integritas Data */ protected static function booted() { static::saving(function ($medicine) { $name = strtolower($medicine->nama_obat); // 1. OTOMATISASI KATEGORI BERDASARKAN KEYWORDS $categories = \App\Models\Category::all(); $matched = false; foreach ($categories as $cat) { $keywords = explode(',', strtolower($cat->keywords)); foreach ($keywords as $keyword) { if (str_contains($name, trim($keyword))) { $medicine->category_id = $cat->id; $medicine->kategori = $cat->name; $matched = true; break 2; } } } if (!$matched) { $medicine->kategori = $medicine->kategori ?: 'Umum'; } // 2. SINKRONISASI TANGGAL EXPIRED (Double Guard) // Jika expired_at kosong tapi expired_date ada, samakan. Begitu juga sebaliknya. if ($medicine->expired_date && !$medicine->expired_at) { $medicine->expired_at = $medicine->expired_date; } elseif ($medicine->expired_at && !$medicine->expired_date) { $medicine->expired_date = $medicine->expired_at; } }); } /** * Accessor: Mempermudah pemanggilan foto produk dengan fallback image. */ public function getFotoUrlAttribute(): string { if ($this->foto_produk && Storage::disk('public')->exists($this->foto_produk)) { return asset('storage/' . $this->foto_produk); } return 'https://ui-avatars.com/api/?name=' . urlencode($this->nama_obat) . '&background=f1f5f9&color=64748b'; } /** * Accessor: Cek Status Expired secara instan. * Bisa digunakan di Blade: @if($medicine->is_expired) ... @endif */ public function getIsExpiredAttribute(): bool { return $this->expired_at ? $this->expired_at->isPast() : false; } /** * Relasi ke Kategori Obat. */ public function category(): BelongsTo { return $this->belongsTo(Category::class, 'category_id'); } /** * Relasi ke riwayat pengobatan kucing. */ public function treatments(): HasMany { return $this->hasMany(Treatment::class, 'medicine_id'); } /** * Melihat riwayat penggunaan obat ini di berbagai rekam medis */ public function treatmentDetails() { return $this->hasMany(TreatmentDetail::class); } }