# CLAUDE.md — Elshrkawy Base

## What This Project Is

A Laravel 12 API starter kit used as the foundation for new projects. It ships ready with: JWT auth, hierarchical RBAC, 6-gateway payment module, wallet system, 124 settings, push notifications, full AR/EN localization, and a Livewire 3 admin dashboard (separate `modules/Dashboard` module) built on Flux UI + Tailwind v4.

---

## Commands

```bash
# Setup
composer install && cp .env.example .env
php artisan key:generate && php artisan jwt:secret
php artisan migrate

# Development
composer dev          # server + queue + logs + vite concurrently

# Testing
php artisan test                         # run all tests
php artisan test --filter ClassName      # run specific class
php artisan test --coverage              # with coverage report

# Code generation
php artisan make:crud City               # scaffold full admin CRUD
php artisan make:crud City --parent=Country --with-tests --with-factory
php artisan make:user-type Delivery user --auth-type=phone
php artisan make:user-type Manager dashboard --auth-type=email

# Utilities
php artisan clear:permission-cache       # clear Redis permission cache
php artisan generate:postman-collection  # regenerate Postman JSON
php artisan find:translations            # find missing translation keys
php artisan fcm:test                     # test Firebase push notification
```

---

## Route Prefixes

| Prefix | Purpose | Auth |
|--------|---------|------|
| `/api/v1/general/*` | Public + optional-auth endpoints | none / optional |
| `/api/v1/admin/*` | Admin JSON API | `auth:api + admin + active + permission` |
| `/api/v1/payment/*` | Payment, wallet, webhooks | mixed |
| `/admin/*` | Livewire dashboard (HTML) — `modules/Dashboard` | `web` session + `User::canAccessDashboard()` |
| `GET /api/v1/general/health` | Health check — DB + Cache status | none |

All routes need `Accept-Language: ar` or `Accept-Language: en` header (SetLocale middleware).

---

## Architecture

```
HTTP Request
  → Middleware (SetLocale → auth:api → admin → active → permission)
  → Controller
  → Service
  → Model / Cache
  → JSON response via json() helper
```

**Key conventions:**
- Controllers are thin — all logic lives in Services
- Dashboard controllers extend `DashboardBaseController` for CRUD
- Services extend `DashboardCRUDService` and override `eagerLoad()`, `applyGlobalScopes()`
- All API responses use `json($data, $message, $status, $httpCode)` helper
- Translatable models store translations in `{model}_translations` tables

---

## Critical Files

| File | Purpose |
|------|---------|
| `bootstrap/app.php` | Route groups, middleware aliases, exception handler |
| `bootstrap/providers.php` | Service providers (add new ones here) |
| `config/user_types.php` | User type definitions + auth type + profile resource |
| `config/payment.php` | All gateway credentials + wallet config |
| `app/Helpers/Helpers.php` | Global helpers: `json()`, `settings()`, `generateOtp()`, `throttle()` |
| `app/Traits/HasPermission.php` | Permission checking methods on User model |
| `app/Services/Permission/PermissionCacheService.php` | Redis permission caching (1hr TTL) |
| `app/Services/Dashboard/DashboardCRUDService.php` | Base class for all dashboard services (JSON API) |
| `modules/Payment/src/PaymentServiceProvider.php` | Registers payment routes + PaymentService |
| `modules/Dashboard/src/DashboardServiceProvider.php` | Dashboard module bootstrap (routes, middleware aliases, Livewire components, sidebar registry) |
| `modules/Dashboard/src/Concerns/AuthorizesResource.php` | Trait used by every Livewire resource component for permission checks |
| `modules/Dashboard/README.md` | How to add Livewire resources, locales, permissions, custom screens |

---

## Adding a New CRUD Resource

1. Create the migration and run `php artisan migrate`
2. Run `php artisan make:crud {Name} --with-tests --with-factory`
3. Add permissions to the seeder/admin panel
4. Register routes (the command does this automatically in `routes/api/dashboard/admin.php`)

---

## Adding a New User Type

```bash
php artisan make:user-type {Name} {user|dashboard} --auth-type={email|phone}
```

This generates: auth controller, password controller, profile controller, middleware, resource, and routes. It also updates `config/user_types.php`, `UserTypeEnum`, and `bootstrap/app.php`.

---

## Permission System

Permissions are strings like `countries.index`, `roles.store`, `admins.destroy`.

```php
// Check permission
$user->hasPermission('countries.index')
$user->hasAnyPermission(['countries.index', 'countries.store'])

// Grant/deny directly (overrides role)
$user->grantPermission($permissionId, $expiresAt = null)
$user->denyPermission($permissionId)

// Super admin bypasses all permission checks
$user->is_super = true
```

Permissions are cached in Redis for 1 hour. Clear with:
```bash
php artisan clear:permission-cache
```

---

## Payment Module

Gateway contract: `Modules\Payment\Contracts\PaymentGatewayInterface`

```php
$paymentService = app(PaymentService::class);

// Initiate
$result = $paymentService->initiate($userId, 'hyperpay', 100.00, [
    'payment_type' => 'VISA',
    'customer_name' => 'John',
]);

// Verify
$transaction = $paymentService->verify($transactionUuid);

// Refund
$transaction = $paymentService->refund($transactionUuid);
```

Supported gateways: `hyperpay`, `myfatoorah`, `moyasar`, `tabby`, `tamara`, `wallet`

Switch between test/live: `PAYMENT_MODE=test|live` in `.env`

---

## Settings

```php
// Read a setting
settings('app_name')
setting(SettingKeyEnum::AppName)

// Write
set_setting(SettingKeyEnum::AppName, 'My App')

// Cache cleared automatically on save; manual clear:
Setting::clearSettingsCache()
```

---

## Environment Variables — Key Ones

| Variable | Effect |
|----------|--------|
| `APP_ENV=local` | OTP always returns `1111`, Telescope enabled |
| `APP_DEBUG=true` | Shows stack traces, debug headers on Gzip |
| `TELESCOPE_ENABLED=false` | Disables Telescope entirely |
| `TELESCOPE_ALLOWED_EMAILS` | Comma-separated emails that can view Telescope |
| `PAYMENT_MODE=test\|live` | Switches all gateways between test/live credentials |
| `PAYMENT_CURRENCY=SAR` | Default currency for all transactions |
| `CACHE_STORE=redis` | Use Redis for caching (required for permission caching) |
| `QUEUE_CONNECTION=redis` | Use Redis for queues (recommended) |

---

## Testing

Tests run against SQLite `:memory:` — no MySQL needed for CI.

```bash
php artisan test                  # all 76 tests
php artisan test --filter Payment # only payment tests
php artisan test --coverage --min=70
```

**Factories available:** User (admin/client/superAdmin/inactive/banned), Role, Permission, Country, City, Coupon, Transaction

**TestCase helpers:**
```php
$this->actingAsSuperAdmin()    # super admin bypasses permission checks
$this->actingAsAdmin()         # admin with no permissions
$this->actingAsClient()        # client user
$this->givePermission($user, 'countries.index')
```

---

## What NOT to Do

- **Don't** put business logic in controllers — put it in Services
- **Don't** call `Permission::all()` or `Role::all()` in request paths — use cached service
- **Don't** use `APP_DEBUG=true` to check OTP bypass — use `APP_ENV=local`
- **Don't** skip the `eagerLoad()` method in new services — causes N+1 queries
- **Don't** add routes directly to `bootstrap/app.php` — add to route files in `routes/api/`
- **Don't** modify migrations that have already been deployed — create new ones
- **Don't** hardcode credentials — use `.env` + `config()`

---

## Conventions

| Item | Convention |
|------|-----------|
| Response format | `json($data, $message, $status, $code)` |
| Route names | `{resource}.{action}` — e.g. `countries.index` |
| Permission names | Match route names exactly |
| Service method | `index`, `show`, `create`, `update`, `destroy` |
| Translation format | `ar.name`, `en.name` in request payloads |
| OTP | 6 digits in production, `1111` in local/testing |
