# AI Agent Customization for Web Dolphin Japan

This document helps AI coding agents understand the codebase structure, conventions, and best practices for this Laravel 12 project.

> **Backend API-Only Project:** This is a REST API server. No frontend, no Vite, no Node.js dependencies. Pure PHP/Laravel backend development.

## Quick Start

### Essential Commands

```bash
# Initial setup (install composer deps, create .env, generate app key, migrate)
composer run setup

# Development server (runs Laravel, queue, and logs)
composer run dev

# Run tests
composer run test
```

### Tech Stack
- **Backend**: Laravel 12, PHP 8.2
- **Database**: PostgreSQL
- **Testing**: PHPUnit
- **Code Quality**: Pint (linter), Laravel Tinker (REPL)

---

## Architecture Overview

This project uses a **3-layer clean architecture** organized by feature:

```
Feature (Example: Brand)
├── Controllers/Admin/BrandController.php        # HTTP request handler
├── Http/Service/BrandService.php               # Business logic orchestrator
├── Http/Repository/BrandRepository.php         # Data access & file operations
├── Models/Brand.php                            # Eloquent model (ORM)
├── Http/Requests/BrandRequest.php              # Request validation
└── Http/Resources/BrandResource.php            # JSON response transformation
```

### Layer Responsibilities

| Layer | Purpose | Key Pattern |
|-------|---------|-------------|
| **Controller** | Parse HTTP request, delegate to service | Inject service, call methods, return response |
| **Service** | Orchestrate business logic, format response | Combine repository operations, use RespondsWithHttpStatus trait |
| **Repository** | Handle data access & file operations | Static methods with query building; interact with models |
| **Model** | Eloquent ORM mapping to database | Define relationships, casts, fillable attributes |
| **Request** | Validate incoming data | Rules in `rules()` method; `authorize()` must return true |
| **Resource** | Transform model data to JSON | Define visible fields and transformations |

---

## API Design & Response Format

### Routing Convention
- **Version**: `api/v1/*`
- **Resource grouping**: `/api/v1/{resource}/`
- **Methods**: GET (index, all), POST (add)
- **Location**: [routes/web.php](routes/web.php)

### Response Format

All API responses use the `RespondsWithHttpStatus` trait and follow this structure:

**Success (200)**
```json
{
  "code": 200,
  "hasError": false,
  "result": { /* data */ }
}
```

**Error (4xx/5xx)**
```json
{
  "code": 422,
  "hasError": true,
  "message": "Validation failed",
  "errors": { /* validation errors */ }
}
```

---

## Naming Conventions

Follow these patterns for consistency:

| Component | Pattern | Example |
|-----------|---------|---------|
| Controllers | `{Entity}Controller` in `Admin/` | `BrandController` |
| Services | `{Entity}Service` | `BrandService` |
| Repositories | `{Entity}Repository` (extend `CommonRepository`) | `BrandRepository` |
| Models | Singular, capitalized | `Brand`, `User` |
| Requests | `{Entity}Request` in `Requests/` | `BrandRequest` |
| Resources | `{Entity}Resource` in `Resources/` | `BrandResource` |
| Routes | Lowercase, plural | `/api/v1/brand/` |
| Migrations | Timestamp + `create_{table}_table` | `2026_05_03_123834_create_brands_table.php` |

---

## How to Implement a New Feature

### 1. Create the Database
- Add migration: `php artisan make:migration create_{entities}_table`
- Define schema in `database/migrations/`
- Run: `php artisan migrate`

### 2. Create the Model
- File: `app/Models/{Entity}.php`
- Extend `Illuminate\Database\Eloquent\Model`
- Define fillable attributes, relationships, casts

### 3. Create the Repository
- File: `app/Http/Repository/{Entity}Repository.php`
- Extend `CommonRepository` (base class in same directory)
- Implement data access methods using static methods
- Handle file operations with MD5 hashing

### 4. Create the Service
- File: `app/Http/Service/{Entity}Service.php`
- Use `RespondsWithHttpStatus` trait
- Inject repository, orchestrate business logic
- Format responses with consistent structure

### 5. Create the Request
- File: `app/Http/Requests/{Entity}Request.php`
- Define validation rules in `rules()` method
- Ensure `authorize()` returns `true`
- Use appropriate validators (unique, max, image, etc.)

### 6. Create the Resource
- File: `app/Http/Resources/{Entity}Resource.php`
- Extend `JsonResource`
- Define visible fields in `toArray()` method

### 7. Create the Controller
- File: `app/Http/Controllers/Admin/{Entity}Controller.php`
- Inject service in constructor
- Implement action methods that call service methods

### 8. Add Routes
- File: [routes/web.php](routes/web.php)
- Use `Route::group()` with prefix
- Follow versioning pattern: `api/v1/{resource}`

---

## Pagination

Use the `PaginationTrait` for list endpoints:

```php
use App\Traits\PaginationTrait;

public function index() {
    $perPage = config('constant.pagination_records'); // Uses config
    $data = Brand::paginate($perPage);
    return $this->sendResponse($data, 'Brands retrieved successfully');
}
```

---

## File Uploads

The `BrandRepository` demonstrates file handling:

```php
// Files are stored in FILE_PATH directory
// MD5 hashing is used for file names
// Directory permissions are set to 777
```

Set `FILE_PATH` in `.env` and ensure the directory exists and is writable.

---

## Key Files to Reference

| Purpose | File | Notes |
|---------|------|-------|
| HTTP response trait | [app/Traits/RespondsWithHttpStatus.php](app/Traits/RespondsWithHttpStatus.php) | Used by all services |
| Pagination trait | [app/Traits/PaginationTrait.php](app/Traits/PaginationTrait.php) | Used for list endpoints |
| Brand example (full pattern) | [app/Http/Controllers/Admin/BrandController.php](app/Http/Controllers/Admin/BrandController.php) | Reference implementation |
| Database config | [config/database.php](config/database.php) | Connection settings |


---

## Known Issues & Gotchas

### Static Repository Methods
- **Current**: Repository methods are static (non-standard for Laravel)
- **Recommendation**: Consider refactoring to instance methods for dependency injection
- **Note**: Existing code works as-is; maintain consistency when extending

### Legacy Route Syntax
- **Current**: Routes use string-based controller refs: `'BrandController@index'`
- **Modern**: Should use array syntax: `[BrandController::class, 'index']`
- **Status**: Both work; maintain consistency with existing patterns

### Folder Nesting
- **Note**: Request and Resource folders have extra nesting: `Requests/Requests/` and `Resources/Resources/`
- **Maintain**: Keep this structure for new files

---

- **Unit**: Test individual components in isolation

Run tests with:
```bash
composer run test
```

---

## Development Workflow

1. **Create new feature**: Follow "How to Implement a New Feature" section
2. **Add routes**: Use existing patterns in web.php
3. **Test**: Run `composer run test` and verify manually
4. **Deploy**: Follow [DEPLOYMENT.md](DEPLOYMENT.md)

---

## Useful Resources

- Laravel Documentation: https://laravel.com/docs/12
- Eloquent ORM: https://laravel.com/docs/12/eloquent
- Validation Rules: https://laravel.com/docs/12/validation#available-validation-rules
- PostgreSQL Documentation: https://www.postgresql.org/docs/

---

## Questions for AI Agents

When implementing features, AI agents should consider:

1. **Does this follow the 3-layer pattern?** (Controller → Service → Repository)
2. **Is the response format consistent?** (RespondsWithHttpStatus trait)
3. **Are validation rules complete?** (BrandRequest pattern)
4. **Is authorization implemented?** (authorize() returns true)
5. **Is pagination handled?** (PaginationTrait for lists)
6. **Are naming conventions followed?** (See table above)
7. **Is the file upload logic correct?** (MD5 hashing, permissions)

