dstpabuaran.com/AGENTS.md
Yoga Pangestu 0023309a8f Refactor services to improve role checks and streamline data retrieval
- Updated CustomerService to simplify getAll method.
- Refactored ProductService to utilize HasRoleChecks trait and improved role verification logic.
- Enhanced ProductVariantService with new methods for fetching data for restocking and transactions.
- Cleaned up RawMaterialService by removing unused methods and improving data retrieval.
- Adjusted SupplierService to streamline getAll method.
- Refactored RoleService to use Spatie's Role model and improved role filtering logic.
- Updated NotificationService to handle role labels more effectively.
- Improved StockMutationService by removing redundant paginated method.
- Cleaned up various frontend components to directly accept necessary props instead of nested data objects.
- Updated tests to reflect changes in service method names and ensure proper notification handling.
2026-08-09 11:33:25 +07:00

9.5 KiB

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:

# 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

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

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)

php artisan make:enum {EnumName}
  • Pakai HasValues trait
  • Buat label(): string method
  • Buat scopes untuk setiap case

4. Service

# 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

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

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

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

8. Permission

// database/seeders/RolePermissionSeeder.php
  • Tambah permissions: {model}.view, {model}.create, {model}.update, {model}.delete
  • Assign ke role yang sesuai

Frontend

9. Columns

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

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

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

// 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