Day 13 โ CRUD Master Data: Asset โ
Fase: 2 โ Mini Project Asset Management | Minggu: 3 | Hari: Rabu
๐ฏ Tujuan Hari Ini โ
Tim menyelesaikan modul CRUD Asset secara lengkap, termasuk dropdown kategori di form dan penampilan kode aset unik.
๐ Task Wajib โ
1. Buat Model Asset โ
bash
php artisan make:model AssetIsi app/Models/Asset.php:
php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Asset extends Model
{
protected $fillable = [
'category_id', 'name', 'code', 'description', 'stock', 'condition'
];
// Relasi: 1 aset milik 1 kategori
public function category()
{
return $this->belongsTo(Category::class);
}
// Relasi: 1 aset punya banyak loan (akan dipakai di week 4)
public function loans()
{
return $this->hasMany(Loan::class);
}
}2. Buat Controller โ
bash
php artisan make:controller AssetController --resourceIsi AssetController.php:
php
<?php
namespace App\Http\Controllers;
use App\Models\Asset;
use App\Models\Category;
use Illuminate\Http\Request;
class AssetController extends Controller
{
public function index()
{
$assets = Asset::with('category')->orderBy('name')->paginate(10);
return view('assets.index', compact('assets'));
}
public function create()
{
$categories = Category::orderBy('name')->get();
return view('assets.create', compact('categories'));
}
public function store(Request $request)
{
$request->validate([
'category_id' => 'required|exists:categories,id',
'name' => 'required|min:2|max:150',
'code' => 'required|max:50|unique:assets,code',
'description' => 'nullable|max:500',
'stock' => 'required|integer|min:0',
'condition' => 'required|in:baik,rusak,perbaikan',
]);
Asset::create($request->only([
'category_id', 'name', 'code', 'description', 'stock', 'condition'
]));
return redirect()->route('assets.index')
->with('success', "Aset '{$request->name}' berhasil ditambahkan!");
}
public function show(Asset $asset)
{
$asset->load('category', 'loans');
return view('assets.show', compact('asset'));
}
public function edit(Asset $asset)
{
$categories = Category::orderBy('name')->get();
return view('assets.edit', compact('asset', 'categories'));
}
public function update(Request $request, Asset $asset)
{
$request->validate([
'category_id' => 'required|exists:categories,id',
'name' => 'required|min:2|max:150',
'code' => "required|max:50|unique:assets,code,{$asset->id}",
'description' => 'nullable|max:500',
'stock' => 'required|integer|min:0',
'condition' => 'required|in:baik,rusak,perbaikan',
]);
$asset->update($request->only([
'category_id', 'name', 'code', 'description', 'stock', 'condition'
]));
return redirect()->route('assets.index')
->with('success', "Aset '{$asset->name}' berhasil diperbarui!");
}
public function destroy(Asset $asset)
{
$nama = $asset->name;
$asset->delete();
return redirect()->route('assets.index')
->with('success', "Aset '{$nama}' berhasil dihapus!");
}
}3. Daftarkan Route Asset โ
Di routes/web.php:
php
use App\Http\Controllers\AssetController;
Route::resource('assets', AssetController::class);4. Buat Views Asset โ
resources/views/assets/index.blade.php:
html
@extends('layouts.app')
@section('title', 'Daftar Aset')
@section('content')
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:20px;">
<div>
<h1>๐๏ธ Daftar Aset</h1>
<p style="color:#666;">Total: {{ $assets->total() }} aset</p>
</div>
<a href="{{ route('assets.create') }}" class="btn-primary">+ Tambah Aset</a>
</div>
@include('partials.alert')
<div style="background:white; border-radius:10px; overflow:hidden; box-shadow:0 2px 8px rgba(0,0,0,0.07);">
<table style="width:100%; border-collapse:collapse;">
<thead>
<tr style="background:#1a1a2e; color:white;">
<th style="padding:14px 16px; text-align:left;">Kode</th>
<th style="padding:14px 16px; text-align:left;">Nama Aset</th>
<th style="padding:14px 16px; text-align:left;">Kategori</th>
<th style="padding:14px 16px; text-align:center;">Stock</th>
<th style="padding:14px 16px; text-align:center;">Kondisi</th>
<th style="padding:14px 16px; text-align:center;">Aksi</th>
</tr>
</thead>
<tbody>
@forelse($assets as $asset)
<tr style="border-bottom:1px solid #f0f0f0;">
<td style="padding:14px 16px; font-family:monospace; font-weight:bold; color:#4f46e5;">
{{ $asset->code }}
</td>
<td style="padding:14px 16px;">{{ $asset->name }}</td>
<td style="padding:14px 16px; color:#666;">{{ $asset->category->name }}</td>
<td style="padding:14px 16px; text-align:center;">
<span style="font-weight:bold; color:{{ $asset->stock > 0 ? '#155724' : '#721c24' }};">
{{ $asset->stock }}
</span>
</td>
<td style="padding:14px 16px; text-align:center;">
@php
$condColor = ['baik' => '#d4edda', 'rusak' => '#f8d7da', 'perbaikan' => '#fff3cd'];
$condText = ['baik' => '#155724', 'rusak' => '#721c24', 'perbaikan' => '#856404'];
@endphp
<span style="background:{{ $condColor[$asset->condition] }}; color:{{ $condText[$asset->condition] }};
padding:4px 10px; border-radius:20px; font-size:12px;">
{{ ucfirst($asset->condition) }}
</span>
</td>
<td style="padding:14px 16px; text-align:center;">
<a href="{{ route('assets.show', $asset->id) }}" style="color:#6c757d; margin:0 4px;">Detail</a>
<a href="{{ route('assets.edit', $asset->id) }}" style="color:#0066cc; margin:0 4px;">Edit</a>
<form action="{{ route('assets.destroy', $asset->id) }}" method="POST" style="display:inline;"
onsubmit="return confirm('Hapus aset {{ $asset->name }}?')">
@csrf @method('DELETE')
<button type="submit" style="border:none; background:none; color:#dc3545; cursor:pointer;">Hapus</button>
</form>
</td>
</tr>
@empty
<tr>
<td colspan="6" style="text-align:center; padding:40px; color:#999;">
Belum ada aset. <a href="{{ route('assets.create') }}">Tambahkan sekarang.</a>
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div style="margin-top:20px;">
{{ $assets->links() }}
</div>
@endsectionresources/views/assets/create.blade.php โ pastikan dropdown kategori mengambil dari variabel $categories:
html
<select name="category_id" ...>
<option value="">-- Pilih Kategori --</option>
@foreach($categories as $cat)
<option value="{{ $cat->id }}" {{ old('category_id') == $cat->id ? 'selected' : '' }}>
{{ $cat->name }}
</option>
@endforeach
</select>5. Tambahkan Data Aset Dummy via Seeder โ
bash
php artisan make:seeder AssetSeederphp
use App\Models\Asset;
use App\Models\Category;
public function run(): void
{
$elektronik = Category::where('name', 'Elektronik')->first();
$furniture = Category::where('name', 'Furniture')->first();
Asset::insert([
['category_id' => $elektronik->id, 'name' => 'Laptop Dell Inspiron', 'code' => 'EL-001', 'stock' => 5, 'condition' => 'baik', 'created_at' => now(), 'updated_at' => now()],
['category_id' => $elektronik->id, 'name' => 'Proyektor Epson', 'code' => 'EL-002', 'stock' => 2, 'condition' => 'baik', 'created_at' => now(), 'updated_at' => now()],
['category_id' => $furniture->id, 'name' => 'Meja Rapat', 'code' => 'FU-001', 'stock' => 8, 'condition' => 'baik', 'created_at' => now(), 'updated_at' => now()],
]);
}bash
php artisan db:seed --class=AssetSeeder๐ Laporan ke Mentor โ
๐ LAPORAN HARIAN โ Day 13
Nama : [Nama Lengkap]
Role : [Role Kamu]
โ
Yang saya kerjakan hari ini:
- [ ] Model Asset dengan relasi belongsTo Category selesai
- [ ] AssetController lengkap dengan validasi
- [ ] Halaman index dengan pagination berjalan
- [ ] Form create dengan dropdown kategori dari DB
- [ ] Seeder untuk data dummy aset berhasil dijalankan
๐ธ Screenshot Wajib:
1. Halaman /assets dengan tabel data aset + kondisi berwarna
2. Form tambah aset dengan dropdown kategori yang terisi
3. Pagination (jika ada > 10 data)
๐งช QA Test Result:
| Test Case | Pass/Fail |
|-----------|-----------|
| Tambah aset tanpa kategori | |
| Tambah aset dengan kode duplikat | |
| Edit aset: ganti kategori | |
| Hapus aset | |
โ Kendala:
[Tulis jika ada]Catatan Mentor
Ingatkan peserta tentang validasi exists:categories,id di field category_id. Ini memastikan user tidak bisa manipulasi ID kategori dengan cara inject ID yang tidak ada di database (keamanan dasar).