# AGENTS.md — Module/Feature Development Checklist

> Checklist saat membuat module atau fitur baru.

## ⚠️ WAJIB BACA SEBELUM KERJA

Sebelum memulai/modifikasi apapun, **WAJIB** baca file di `.ai/` folder:

```
.ai/
├── CONTEXT.md      # Project context, roles, module mapping
├── REFERENCE.md    # Database schema (tabel, relasi, enums)
└── CONVENTIONS.md  # Aturan kode (backend + frontend)
```

**Baca urutan:**
1. `CONTEXT.md` → pahami project, role, dan module
2. `REFERENCE.md` → pahami struktur data
3. `CONVENTIONS.md` → pahami cara nulis kode

**Jangan pernah skip membaca `.ai/` folder** — semua aturan ada di sana.

**Catatan Penting:**
- File `.ai/` adalah **contoh best practice & referensi**, bukan berarti semua pola di situ sudah ada di project
- Jika pola di `.ai/` belum ada di project → **ikuti pola yang sudah ada di codebase**
- Jangan buang waktu mencari file/pattern yang belum tentu ada

---

## Workflow: Trace Codebase

Sebelum mengubah/menambah fitur, **pahami dulu alur kode yang sudah ada**.

### Cara Trace:

Mulai dari file yang relevan (Route/Controller/Service), lalu **ikuti setiap pemanggilan**:

- Jika ada `use ... Service` → baca file Service
- Jika ada `use ... Model` → baca file Model
- Jika ada `use ... Trait` → baca file Trait
- Jika ada `use ... Enum` → baca file Enum
- Jika ada Form Request → baca file Form Request

### Contoh Trace:

```
ProductController
  └── panggil ProductService → baca
        └── panggil Product model → baca
              └── pakai HasFactory trait → baca
```

**Ikuti terus sampai semua pemanggilan dipahami. Jangan ubah kode tanpa memahami alur yang sudah ada.**

---

## Documentation: Catatan Session Kerja

Setiap kali bekerja pada suatu fitur, **WAJIB** buat/dokumentasi di `/docs` folder.

### Format: `/docs/{nama-fitur}.md`

Isi dokumen:
1. **Tujuan** — fitur apa yang dibuat/diubah
2. **File yang dibaca** — daftar file + ringkasan singkat
3. **Pola yang ditemukan** — struktur kode, relasi, flow
4. **Perubahan yang dilakukan** — apa saja yang diubah

### Contoh:

```markdown
# Fitur: Transfer Stok Produk

## Tujuan
Menambah fitur perpindahan stok dari gudang baik ke reject

## File yang Dibaca
- `routes/web.php` → ProductController di route `admin.manage.products`
- `app/Http/Controllers/Admin/Manage/ProductController.php` → ada method `index`, `store`, `update`
- `app/Services/Admin/Manage/ProductService.php` → panggil Product model, pakai `HasStockAdjustment` trait
- `app/Models/Product.php` → relasi `stocks()`, accessor `formatted_stock`

## Pola yang Ditemukan
- Service handle logic, Controller zero logic
- Pakai trait `HasStockAdjustment` untuk adjust stock
- Stock ada di tabel `stocks` dengan relasi ke product

## Perubahan
- Tambah method `transferStock()` di ProductService
- Tambah route `POST /products/{product}/transfer-stock`
```

### Kapan harus update?
- Saat mulai sesi baru → buat dokumen baru
- Saat lanjut sesi sebelumnya → baca dulu dokumen yang sudah ada

---

## Backend

### 1. Migration
```bash
php artisan make:migration create_{table}_table
```
- [ ] Kolom sesuai kebutuhan
- [ ] Foreign key → `$table->foreignId('user_id')->constrained()->cascadeOnDelete()`
- [ ] Custom FK → `$table->foreignId('created_by_id')->constrained('users')->restrictOnDelete()`
- [ ] Soft deletes → `$table->softDeletes()` (kecuali: Attendance, StokOpnameItem, RetailStockHistory, StockMutation)
- [ ] Timestamps → `$table->timestamps()`

### 2. Model
```bash
php artisan make:model {Model} -m
```
- [ ] `#[Guarded(['id'])]` — jangan pakai $fillable
- [ ] `#[Appends([...])]` — di atas class declaration
- [ ] `protected function casts(): array` — method syntax, bukan property
- [ ] Scopes — `#[Scope]` + `protected function name(Builder $query): void`
- [ ] Accessors — `Attribute::make(get: fn () => ...)`, NAMA BERBEDA dari kolom DB
- [ ] Relasi — WAJIB 2 ARAH di kedua model
- [ ] Select — `select(['id', 'name', ...])` + eager load relasi

**Urutan isi model:**
1. `casts()`
2. Scopes (abjad)
3. Accessors (abjad)
4. Relations (abjad)

### 3. Enum (jika perlu)
```bash
php artisan make:enum {EnumName}
```
- [ ] Pakai `HasValues` trait
- [ ] Buat `label(): string` method
- [ ] Buat scopes untuk setiap case

### 4. Service
```bash
# Manual create
app/Services/Admin/{Module}/{Model}Service.php
```
- [ ] Return type di SEMUA method
- [ ] Method wajib: `paginated()`, `getAll()`, `store()`, `update()`, `destroy()`
- [ ] Select kolom yang dibutuhkan + eager load relasi
- [ ] Gunakan traits jika perlu: `HandlesCashTransactions`, `HasStockAdjustment`, `RegistersMedia`
- [ ] Urutan method: CRUD → custom methods → private helpers (di paling bawah)

### 5. Form Request
```bash
php artisan make:request {Model}Request
```
- [ ] `authorize(): bool` → return true
- [ ] `rules(): array` → validasi sesuai kebutuhan
- [ ] `attributes(): array` → label Bahasa Indonesia
- [ ] `prepareForValidation()` → strip currency jika ada input Rupiah
- [ ] Unique ignore → `Rule::unique('table')->ignore($this->route('model')?->id)`

### 6. Controller
```bash
php artisan make:controller Admin/{Module}/{Model}Controller
```
- [ ] Constructor promotion → `public function __construct(private {Model}Service $service) {}`
- [ ] Return type di SEMUA method (`Response`)
- [ ] Zero logic — semua di service
- [ ] Flash → `Inertia::flash('toast', ['type' => 'success', 'message' => '...'])` sebelum `return back()`
- [ ] `handleAction()` untuk 2+ query
- [ ] Method order: `__construct`, `index`, `create`, `store`, `show`, `edit`, `update`, `destroy`, custom actions

### 7. Route
```php
// routes/web.php
Route::resource('{module}', {Model}Controller::class)
    ->parameters(['{module}' => '{model}']);
```
- [ ] Route group sesuai module
- [ ] Middleware `permission:{permission}` jika perlu

### 8. Permission
```php
// database/seeders/RolePermissionSeeder.php
```
- [ ] Tambah permissions: `{model}.view`, `{model}.create`, `{model}.update`, `{model}.delete`
- [ ] Assign ke role yang sesuai

---

## Frontend

### 9. Columns
```bash
resources/js/pages/admin/{module}/{model}/columns.tsx
```
- [ ] Type definition → `export type {Model} = { ... }`
- [ ] Column factory → `export function create{Model}Columns(params): ColumnDef<{Model}>[]`
- [ ] Gunakan `formatted_*` accessor dari model, bukan format di TypeScript
- [ ] Actions column → conditional on `can('{model}.update')` / `can('{model}.delete')`

### 10. Index Page
```bash
resources/js/pages/admin/{module}/{model}/index.tsx
```
- [ ] Simple CRUD → `DataTable` + `FormDialog` + `DeleteConfirmDialog`
- [ ] Complex list → `CardTable` + `FilterPopover` + `useCardTableExpand`
- [ ] Hooks: `useCan()`, `useServerTable()`
- [ ] Permission check → `can('{model}.create')` untuk tombolTambah

### 11. Create/Edit Page
```bash
resources/js/pages/admin/{module}/{model}/create.tsx
resources/js/pages/admin/{module}/{model}/edit.tsx
```
- [ ] Simple CRUD → inline `FormDialog` di index page
- [ ] Complex form → full-page `<Form>` + draft saving
- [ ] Gunakan `RupiahInput`, `NumberInput`, `FileUpload`, `Combobox` sesuai kebutuhan
- [ ] Route helpers → Ziggy (`route('admin.{module}.{model}.store')`)

### 12. Sidebar
```tsx
// resources/js/components/app-sidebar.tsx
```
- [ ] Tambah item di `masterItems` / `manageItems` / `financeItems` / `hrItems`
- [ ] Permission → `permission: '{model}.view'`
- [ ] Icon → dari `lucide-react`

---

## Testing

### 13. Manual Test
- [ ] Create — form validasi, flash message, redirect
- [ ] Read — data muncul di index, pagination, search
- [ ] Update — form terisi data lama, flash message
- [ ] Delete — konfirmasi, flash message
- [ ] Permission — user tanpa akses tidak bisa akses
- [ ] Relasi — eager load tidak N+1

---

## Update `.ai/` Files

> **WAJIB** update `.ai/` files saat ada perubahan supaya tetap updated.

### Kapan harus update?
- [ ] Tambah kolom baru → update `REFERENCE.md` (tambah kolom + type + relation)
- [ ] Tambah migration baru → update `REFERENCE.md` (tambah tabel baru)
- [ ] Tambah relasi baru → update `REFERENCE.md` (tambah relasi di 2 model)
- [ ] Tambah model baru → update `CONTEXT.md` (tambah ke Module Overview)
- [ ] Tambah role/permission baru → update `CONTEXT.md` (tambah ke Roles & Akses)
- [ ] Tambah enum baru → update `REFERENCE.md` (tambah ke tabel Enums)
- [ ] Tambah service trait baru → update `REFERENCE.md` (tambah ke Service Concerns)
- [ ] Tambah accessor baru → update `CONVENTIONS.md` jika ada pattern baru

### Checklist update `.ai/`:
```
□ REFERENCE.md — kolom/tabel/relasi/enum sudah sesuai?
□ CONTEXT.md — module mapping sudah sesuai?
□ CONVENTIONS.md — ada pattern baru yang perlu ditambah?
```

---

## Quick Reference

### File Paths
| Item | Path |
|------|------|
| Migration | `database/migrations/` |
| Model | `app/Models/` |
| Enum | `app/Enums/` |
| Service | `app/Services/Admin/{Module}/` |
| Form Request | `app/Http/Requests/Admin/{Module}/` |
| Controller | `app/Http/Controllers/Admin/{Module}/` |
| Route | `routes/web.php` |
| Permission | `database/seeders/RolePermissionSeeder.php` |
| Columns | `resources/js/pages/admin/{module}/{model}/columns.tsx` |
| Index | `resources/js/pages/admin/{module}/{model}/index.tsx` |
| Create | `resources/js/pages/admin/{module}/{model}/create.tsx` |
| Edit | `resources/js/pages/admin/{module}/{model}/edit.tsx` |
| Sidebar | `resources/js/components/app-sidebar.tsx` |

### Conventions
- Baca `.ai/CONVENTIONS.md` untuk aturan lengkap
- Baca `.ai/REFERENCE.md` untuk database schema
- Baca `.ai/CONTEXT.md` untuk project context & roles
