# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

**El Captain** — White-label sports/social club ERP. Forked from the نادي النادي system, rebranded for generic distribution. Built on a **custom PHP 8.2+ framework** (NOT Laravel, NOT Symfony). Arabic-first, RTL, multi-branch. All views are in Arabic. The framework is hand-built with plain PDO, custom autoloader, custom template engine, and modular MVC architecture.

This is the **demo instance** — deployed at demo.elcaptain.com for prospective clients to try.

### Branding
- Club name is dynamic: `config('app.name_ar')` / `config('app.name_en')` — set via env vars
- BrandingService reads overrides from `system_config` table (group: branding)
- Never hardcode "نادي النادي" or "THE CLUB" — always use config() or BrandingService

## Commands

```bash
php cli.php migrate              # Run pending database migrations
php cli.php migrate:rollback     # Undo last batch
php cli.php migrate:status       # Show migration status
php cli.php seed                 # Run pending seeds
php cli.php seed:run <Name>      # Run specific seed
php cli.php cron                 # Run cron jobs
```

No composer, no npm, no build step. The app uses a custom PSR-4-style autoloader (`App\Core\Autoloader`). No test framework is configured.

## Architecture

### Entry Points
- **Web**: `public/index.php` — boots App singleton, dispatches router, sends response
- **CLI**: `cli.php` — minimal bootstrap (no sessions/routing), handles migrate/seed/cron

### App Boot Sequence
`App::getInstance()->boot()`: timezone (Africa/Cairo) -> .env -> config files -> DB connect -> session start -> load `system_config` table overrides -> execute all `app/Modules/*/bootstrap.php` (sorted) -> init router -> load all `app/Modules/*/Routes.php`

### Module Structure
Each module lives in `app/Modules/{Name}/` with:
- `bootstrap.php` — registers permissions via `PermissionRegistry`, sidebar menu via `MenuRegistry`, event listeners via `EventBus::listen()`
- `Routes.php` — returns array of `[METHOD, PATH, HANDLER, MIDDLEWARE_ARRAY, PERMISSION]`
- `Controllers/`, `Models/`, `Services/`, `Views/`

### Routing
Route format: `['GET', '/members/{id:\d+}', 'Members\Controllers\MemberController@show', ['auth'], 'member.view']`

Handler string resolves to `App\Modules\{handler}`. Controller method receives `(Request $request, ...$routeParams)` and returns `Response`.

Middleware names map to classes: `auth` -> AuthMiddleware, `csrf` -> CSRFMiddleware, `permission` -> PermissionMiddleware.

### Database Layer
`App\Core\Database` wraps PDO directly. Key methods:
- `select($sql, $params)` / `selectOne($sql, $params)` — prepared statements
- `insert($table, $data)` / `update($table, $data, $where, $params)` / `delete($table, $where, $params)`
- `query($sql, $params)` returns PDOStatement; `raw($sql)` executes without params

**No ORM relations.** Relationships are loaded via manual SQL joins or separate queries.

**IMPORTANT**: MySQL `SHOW TABLES LIKE ?` does NOT work with prepared statement placeholders. Use `information_schema.tables` query or hardcoded string instead.

### Model Layer
`App\Core\Model` provides: `$table`, `$fillable`, `$timestamps`, `$softDelete` (uses `is_archived` column). Static methods: `find()`, `findOrFail()`, `create()`, `query()` (returns QueryBuilder). Instance methods: `save()`, `update()`, `archive()`. Models emit events via EventBus: `{singular}.created`, `{singular}.updated`, `{singular}.archived`.

### QueryBuilder
`Model::query()->where('status','=','active')->orderBy('name','ASC')->get()`. Supports `where`, `whereIn`, `whereNull`, `join`, `leftJoin`, `groupBy`, `having`, `limit`, `offset`, `paginate`. Soft delete filtering is automatic (`withoutArchived()` by default).

### Template Engine
Plain PHP templates with layout/section support. View path uses dot notation: `'Members.Views.show'` -> `app/Modules/Members/Views/show.php`. Layout files: `'Layout.main'` -> `app/Shared/Layout/main.php`.

In views: `$__template->layout('Layout.main')`, `$__template->section('content')` / `$__template->endSection()`, `$__template->yield('content')`, `$__template->include('path', $data)`.

### EventBus
`EventBus::listen('event.name', $callback, $priority)` / `EventBus::dispatch('event.name', $data)`. Used heavily for cross-module integration (e.g., Accounting listens to payment/sale/fine events to auto-post journal entries).

### Flash Messages
`$session->flash('_alerts', [['type' => 'success', 'message' => '...']])`. Response helpers: `->withSuccess()`, `->withError()`, `->withWarning()`.

### Authorization
Routes specify a permission string. `Controller::authorize($permission)` throws RuntimeException(403) if denied. Employee permissions come from `role_permissions` + `employee_permissions` tables. Super admin check: query `employee_roles` joined with `roles` where `role_code = 'super_admin'`.

## Key Conventions

### Migration Naming
`database/migrations/Phase_NN_NNN_description.php` — returns `['up' => $sql, 'down' => $sql]` or a closure receiving `Database`. Multiple SQL statements in `up` are split by `;\n` (semicolon + newline).

### Seed Naming
`database/seeds/Phase_NN_NNN_description.php` — returns closure receiving `Database`. Tracked in `seeds` table; won't re-run unless forced.

### Permission Keys
Format: `module.action` (e.g., `member.view`, `accounting.journal.create`). Registered in each module's `bootstrap.php` via `PermissionRegistry::register()`.

### Global Helpers
`e()` for HTML escaping, `money()` for currency formatting, `csrf_field()` for form tokens, `old()` for repopulating forms after validation failure, `arabic_date()` for localized dates, `now()` / `today()` for current datetime/date.

### Controller Patterns
- `$this->view('Module.Views.path', $data)` to render
- `$this->json($data)` for API responses
- `$this->redirect('/path')` for redirects
- `$this->validate($_POST, $rules)` validates and flashes errors on failure
- `$this->authorize('permission.key')` checks permission

### Response Chaining
`return $this->redirect('/path')->withSuccess('message')` — flash + redirect in one call.

### Database Config
Connection params from `config/database.php` which reads from `.env`: `DB_HOST`, `DB_PORT`, `DB_NAME`, `DB_USER`, `DB_PASS`. Constructor: `new Database(string $host, int $port, string $dbName, string $user, string $pass, string $charset)`.

## Common Pitfalls

- **CLI context**: `App::getInstance()->db()` is null in CLI. Seeds receive `Database` as parameter; use `App::getInstance()->setDb($db)` if services need the App singleton.
- **Table existence checks**: Never use `SHOW TABLES LIKE ?` with params. Use `SELECT 1 FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = ?`.
- **Column names vary by table**: Not all tables have `is_archived` — check the migration before assuming. `fines` has no `is_archived` or `imposed_date` (use `created_at`). `hr_payroll_runs` uses `paid_at` not `payment_date`. `installment_plans` has no `is_archived`.
- **`declare(strict_types=1)`**: Used in all PHP files. Type mismatches (e.g., passing array to string param) cause fatal errors.
- **ExceptionHandler**: Respects exception code for HTTP status (401, 403, 404 return proper pages; everything else is 500).

---

# MODULE ARCHITECTURE MAP SYSTEM (MANDATORY)

This instruction overrides all implementation workflows.

Before modifying, creating, refactoring, deleting, or analyzing any module, you MUST first locate and read that module's Architecture Map.

Architecture Maps are not documentation.

Architecture Maps are not notes.

Architecture Maps are not reports.

Architecture Maps are a mandatory knowledge system and source of truth used to maintain continuity across AI sessions and human developers.

Every development task must begin and end with the Architecture Map.

---

## REQUIRED WORKFLOW FOR EVERY TASK

Whenever a request affects a module:

### Step 1: Locate Architecture Map

Search for the module's Architecture Map at `docs/architecture-maps/{ModuleName}.md`.

If an Architecture Map exists:

* Read it completely.
* Use it as the starting context.
* Validate it against the current codebase.
* Update it with any new discoveries before making changes.

If an Architecture Map does NOT exist:

STOP.

Do not implement the requested change.

Do not start coding.

Do not make assumptions.

Instead, create the Architecture Map first using the Architecture Discovery Process described below.

Only after the initial Architecture Map exists may implementation begin.

---

## ARCHITECTURE MAPS ARE REQUIRED

No module is allowed to exist without an Architecture Map.

No feature is allowed to be modified without consulting its Architecture Map.

No task is considered complete until the Architecture Map has been updated.

Failure to update the Architecture Map means the task is incomplete.

---

## ARCHITECTURE DISCOVERY PROCESS

When creating a new Architecture Map:

You must build it incrementally.

Never attempt to understand the entire module in a single pass.

Instead:

1. Scan the module structure.
2. Identify major components.
3. Document findings.
4. Continue deeper analysis.
5. Append findings to the Architecture Map.
6. Refine existing entries.
7. Repeat until sufficient understanding exists.

The Architecture Map is a living document that grows over time.

It must never be regenerated from scratch.

It must be continuously improved and expanded.

---

## DATABASE TRUTH RULE

Migration files are NOT the source of truth.

Migration files may be outdated, incomplete, or inaccurate.

Whenever database structure matters:

* Connect directly to the database.
* Inspect actual tables.
* Inspect actual columns.
* Inspect actual relationships.
* Inspect actual indexes.
* Inspect actual constraints.
* Inspect actual views.
* Inspect actual triggers.
* Inspect actual procedures.

The live database is the source of truth.

If migrations conflict with the live database, trust the database.

Document actual database structure inside the Architecture Map.

---

## MANDATORY UPDATE RULE

Every code change must trigger an Architecture Map update.

After making changes:

1. Re-analyze affected components.
2. Identify new dependencies.
3. Identify changed dependencies.
4. Identify new workflows.
5. Identify changed workflows.
6. Update diagrams, flows, relationships, and references.
7. Save all findings into the Architecture Map.

This is mandatory.

There are no exceptions.

---

## ARCHITECTURE MAP PURPOSE

The Architecture Map exists to become the module's permanent knowledge graph.

Its purpose is to allow future AI sessions and human developers to:

* Understand the module quickly.
* Avoid re-discovering architecture.
* Avoid editing dead code.
* Avoid breaking live functionality.
* Avoid duplicating logic.
* Understand dependencies.
* Predict side effects.
* Implement changes safely.
* Reduce context usage and token consumption.
* Maintain continuity between development sessions.

The Architecture Map should eventually contain enough information that a developer or AI can understand how the module works before reading large portions of the codebase.

---

## REQUIRED CONTENT

Each Architecture Map must continuously document:

* Module purpose
* System responsibilities
* File structure
* Entry points
* Controllers
* Services
* Repositories
* Jobs
* Events
* Listeners
* Middleware
* API endpoints
* Database schema (from live DB, not migrations)
* Relationships
* Business rules
* User workflows
* Data flows
* State flows
* Permission model
* External integrations
* Internal integrations
* Dependency graphs
* Risk areas
* Legacy code
* Dead code
* Technical debt
* Change impact analysis

Most importantly:

Document relationships between systems, not just the systems themselves.

The Architecture Map must explain how everything connects.

---

## ENFORCEMENT

Before any task begins:

Verify Architecture Map exists at `docs/architecture-maps/{ModuleName}.md`.

If missing:

Create it first.

Before any task completes:

Update Architecture Map.

If Architecture Map is not updated:

The task is not complete.

Architecture Maps are mandatory project infrastructure and must be maintained with the same importance as production code.

---

# CROSS-MODULE DEPENDENCY GRAPH SYSTEM (MANDATORY)

Module Architecture Maps explain how a module works internally.

They do NOT fully explain how modules interact with each other.

To prevent incomplete implementations, missed cascading changes, broken workflows, hidden regressions, and cross-module inconsistencies, the system must maintain a second knowledge layer called the Cross-Module Dependency Graph.

This graph is a mandatory project artifact stored at `docs/architecture-maps/DEPENDENCY-GRAPH.md`.

It must be consulted before any implementation begins and updated after every implementation is completed.

---

## PURPOSE

The purpose of the Dependency Graph is to answer questions such as:

* If this field changes, what else breaks?
* If this workflow changes, what downstream systems are affected?
* If this API changes, who consumes it?
* If this table changes, what reports depend on it?
* If this permission changes, what modules are affected?
* If this event changes, what listeners will stop working?
* If this status changes, which automations fail?
* If this business rule changes, which workflows become invalid?

The Dependency Graph exists specifically to identify cascading changes.

---

## REQUIRED WORKFLOW

Before implementing any request:

Step 1: Read the affected Module Architecture Maps.

Step 2: Read the Cross-Module Dependency Graph.

Step 3: Identify all directly affected modules.

Step 4: Identify all indirectly affected modules.

Step 5: Build an Impact Analysis.

Step 6: Only then begin implementation.

No implementation should begin until dependency analysis has been completed.

---

## IF THE DEPENDENCY GRAPH DOES NOT EXIST

If the Dependency Graph does not exist:

STOP.

Do not begin implementation.

Create the Dependency Graph first.

Then continue with implementation.

---

## IMPACT ANALYSIS IS MANDATORY

For every requested change, produce an internal impact analysis identifying:

* **Direct Impact** — Files and systems being modified.
* **Upstream Dependencies** — Systems providing data or functionality.
* **Downstream Dependencies** — Systems consuming data or functionality.
* **Cascading Changes** — Changes required in other modules.
* **Risk Assessment** — Potential regressions.
* **Validation Requirements** — Areas requiring testing.

Implementation should never be performed until this analysis is complete.

---

## REQUIRED RELATIONSHIPS TO TRACK

The Dependency Graph must track:

* Module → Module Dependencies
* Database Dependencies (tables, views, procedures, shared entities)
* API Dependencies (providers and consumers)
* Event Dependencies (events, listeners, subscribers)
* Workflow Dependencies (business processes spanning multiple modules)
* Permission Dependencies (shared roles, policies, access controls)
* Reporting Dependencies (reports, dashboards, exports)
* Notification Dependencies (SMS, push notifications, alerts)
* Automation Dependencies (jobs, schedulers, workflows, triggers)
* Configuration Dependencies (settings, system options, rule engine keys)

---

## MANDATORY UPDATE RULE

Every implementation must update:

1. The affected Module Architecture Maps.
2. The Cross-Module Dependency Graph.

A task is not complete until both artifacts are updated.

---

## ENFORCEMENT

Before implementation:

Read Architecture Maps. Read Dependency Graph. Perform Impact Analysis.

After implementation:

Update Architecture Maps. Update Dependency Graph.

If any of these are missing or outdated, the task is incomplete.

The Dependency Graph is considered critical project infrastructure and must be maintained with the same importance as production code.

---

# DOMAIN LOGIC PRESERVATION PROTOCOL (MANDATORY)

The goal of every implementation is not to satisfy the request. The goal is to preserve and improve the correctness of the overall system.

A request describes a symptom. A request does not automatically describe the correct solution.

Before implementing any change, determine:

1. What behavior is being observed.
2. What behavior is expected.
3. What business rule is being violated.
4. Where that business rule truly belongs.
5. Which systems depend on that business rule.

Never assume the screen, form, API, controller, service, or file mentioned in the request is the correct place for the fix.

---

## ROOT CAUSE BEFORE FIX

Before modifying code, identify:

* Root cause.
* Business rule.
* Source of truth.
* Affected workflows.
* Affected modules.

Do not implement a fix until root cause analysis is complete.

---

## BUSINESS RULE FIRST

Every bug must be translated into a business rule.

Wrong: "The user can enter a negative quantity."
Correct: "Inventory quantities must never become negative."

The second statement describes a business rule. The first describes only one manifestation of the problem.

Always solve the business rule. Never solve only the symptom.

---

## SOURCE OF TRUTH RULE

Every business rule must have a source of truth (database constraint, domain service, validation service, workflow engine, permission system, state machine).

Before implementing a fix, identify where the source of truth should exist.

Whenever possible:

* Fix the source of truth.
* Avoid implementing duplicate validations in multiple locations.
* Avoid fixing only the UI.
* Avoid fixing only a single endpoint.
* Avoid fixing only a single workflow.

---

## SYSTEM-WIDE IMPACT REVIEW

Before implementing any change, ask:

* Where else can this action happen?
* Which APIs perform the same action?
* Which jobs perform the same action?
* Which imports perform the same action?
* Which automations perform the same action?
* Which modules perform the same action?

The solution must account for all valid entry points.

---

## NO LOCAL OPTIMIZATION

Never optimize for making a ticket pass. Never optimize for making a screen behave correctly in isolation. Never optimize for making a test pass.

Optimize for preserving the integrity of the entire system.

A fix that solves one screen while breaking architecture is a failed fix. A fix that solves one workflow while creating inconsistencies elsewhere is a failed fix.

---

## ARCHITECTURAL REVIEW REQUIRED

Before implementation, determine whether the proposed fix:

* Preserves existing business rules.
* Violates existing business rules.
* Introduces duplicate logic.
* Creates conflicting logic.
* Creates alternative sources of truth.
* Breaks system consistency.

If any of these occur, redesign the solution.

---

## MULTI-WORKFLOW VALIDATION

For every change, identify:

* Primary workflow.
* Secondary workflows.
* Administrative workflows.
* Automated workflows.
* Integration workflows.

Verify that the solution works consistently across all of them.

---

## IMPLEMENTATION DECISION RECORD

Before coding, document internally:

* **Issue:** What is happening.
* **Expected Behavior:** What should happen.
* **Business Rule:** Underlying rule.
* **Root Cause:** Actual cause.
* **Source of Truth:** Where rule should live.
* **Affected Modules:** List.
* **Affected Workflows:** List.
* **Chosen Solution:** Why this approach preserves system integrity.
* **Rejected Solutions:** Why simpler fixes were not used.

Only after this analysis may implementation begin.

---

## ENFORCEMENT

A change is considered incomplete if:

* It fixes only the symptom.
* It ignores root cause.
* It creates duplicate business logic.
* It introduces additional sources of truth.
* It does not evaluate downstream effects.
* It does not validate system-wide consistency.

The objective is not to satisfy the request. The objective is to preserve the correctness, consistency, and integrity of the entire ERP system.
