# `make:module` Command Guide

Complete usage reference for scaffolding new ERPFlow modules/plugins.

---

## Purpose

`make:module` generates a ready-to-sync module/plugin skeleton under `backend/Modules/` and frontend module scaffold by default.

It helps standardize module creation and reduces manual setup errors.

---

## Command Signature

```bash
php artisan make:module {name} [--slug=] [--sync] [--migrate] [--force]
```

### Required Argument

- `name`  
  Human/display/module class name (example: `HRMS`, `Task Manager`)

### Optional Flags

- `--slug=hrms`
  - Explicit module slug
  - If omitted, slug is auto-generated from `name` (kebab-case)
  - Slug must match: `^[a-z][a-z0-9_-]*$`

- `--sync`
  - Runs `php artisan platform:sync` after scaffold creation
  - Useful when you want module metadata registered to DB immediately

- `--migrate`
  - Runs `php artisan module:migrate {slug}` after scaffold
  - Applies module migration files (if present)

- `--force`
  - If module directory already exists, it is deleted and recreated
  - Use carefully (overwrites existing module scaffold files)

---

## Basic Usage Examples

### 1) Minimal module scaffold

```bash
docker compose exec backend php artisan make:module HRMS --slug=hrms
```

### 2) Scaffold + auto sync

```bash
docker compose exec backend php artisan make:module HRMS --slug=hrms --sync
```

### 3) Scaffold + sync + migrate

```bash
docker compose exec backend php artisan make:module HRMS --slug=hrms --sync --migrate
```

### 4) Force overwrite existing module

```bash
docker compose exec backend php artisan make:module HRMS --slug=hrms --force
```

---

## What Gets Generated

Assume command:

```bash
php artisan make:module HRMS --slug=hrms
```

### Backend paths

```text
backend/Modules/Hrms/
├── module.json
├── app/
│   ├── Models/.gitkeep
│   ├── Http/
│   │   ├── Controllers/.gitkeep
│   │   ├── Requests/.gitkeep
│   │   └── Resources/.gitkeep
│   ├── Repositories/.gitkeep
│   └── Services/.gitkeep
├── database/
│   ├── migrations/.gitkeep
│   └── seeds/.gitkeep
└── routes/
    └── api.php
```

### Frontend paths (default)

```text
frontend/src/modules/hrms/
├── index.tsx
├── api/.gitkeep
└── pages/.gitkeep
```

> Frontend scaffold is created in project root `frontend/` directory (not inside `backend/`).

---

## Generated `module.json` (Starter Contents)

Command creates a ready starter manifest including:

- `name`, `slug`, `version`
- basic visual metadata (`icon`, `color`)
- route prefixes
- default `status: disabled`
- default dependency: `platform`
- default actions: `view`, `create`, `update`, `delete`
- default menu item
- default permission entry
- empty placeholders for approval/dashboard/settings
- sample frontend route metadata

This is intended as a starting template; update it based on your module domain.

---

## Generated `routes/api.php`

A route stub is created with module prefix:

```php
Route::prefix('hrms')->group(function () {
    // Define module API routes here.
});
```

---

## Internal Naming Rules

- **Directory name** under `backend/Modules/` is generated as StudlyCase from slug
  - `hrms` -> `Hrms`
  - `task-manager` -> `TaskManager`
- **Slug** is kebab/underscore compatible, lowercase only
- If `--slug` is missing, slug is generated from `name`
  - `Task Manager` -> `task-manager`

---

## Behavior Matrix (Flags)

| Scenario | Result |
|---|---|
| No flags | Backend + frontend scaffold |
| `--sync` | Scaffold then `platform:sync` |
| `--migrate` | Scaffold then `module:migrate {slug}` |
| `--sync --migrate` | Scaffold, then sync, then migrate |
| Existing folder, no `--force` | Command fails safely |
| Existing folder + `--force` | Existing folder replaced |

---

## Typical Workflow After Creation

1. Run command (`make:module`)
2. Implement backend module code (controllers/services/repositories/migrations)
3. Implement frontend pages/routes
4. Run `platform:sync` (if not already run via `--sync`)
5. Run `module:migrate {slug}` (if migrations exist)
6. Open Plugin Manager -> install/enable
7. Assign permissions/roles and verify sidebar visibility

---

## Common Errors & Fixes

### Invalid slug format

- **Error:** invalid slug
- **Fix:** use lowercase and valid chars only (`a-z`, `0-9`, `_`, `-`)

### Directory already exists

- **Error:** module directory exists
- **Fix:** choose a new slug or run with `--force`

### Sync success but menu/permission missing

- **Cause:** `module.json` metadata incomplete or incorrect keys
- **Fix:** validate `actions`, `menus`, `permission` keys and rerun sync

### Migrate runs but no schema changes

- **Cause:** no migration files inside `database/migrations`
- **Fix:** add migration file(s), rerun `module:migrate {slug}`

### Need full module removal (DB + frontend + backend)

- **Use:** `php artisan delete:module {slug}`
- This command:
  - validates lifecycle/dependency safety via plugin uninstall step
  - deletes module DB records
  - deletes backend module folder (`backend/Modules/...`) including all generated artifacts
  - deletes frontend module folder (`frontend/src/modules/{slug}`)
- Useful flags:
  - `--skip-db` (files only; does not require the module to exist in the database)
  - `--skip-files` (DB only; module must exist in the database)
  - `--force` (skip confirmation)
- **Note:** migration tables are not rolled back automatically
- With `--skip-db`, you can pass the module slug (`system-configuration`) or directory name (`SystemConfiguration`)

---

## `delete:module` Command

```bash
php artisan delete:module {slug} [--skip-db] [--skip-files] [--force]
```

### What gets deleted

| Target | Default | `--skip-db` | `--skip-files` |
|---|---|---|---|
| Module DB record | Yes | No | Yes |
| `backend/Modules/{Name}/` (all artifacts) | Yes | Yes | No |
| `frontend/src/modules/{slug}/` | Yes | Yes | No |
| Migration tables | No | No | No |

### Examples

```bash
# Full delete (module must exist in database)
docker compose exec backend php artisan delete:module system-configuration --force

# Files only, no database lookup required
docker compose exec backend php artisan delete:module SystemConfiguration --skip-db --force

# Database only
docker compose exec backend php artisan delete:module system-configuration --skip-files --force
```

---

## Best Practices

- Keep `status: disabled` initially until module is validated
- Use stable slug naming; avoid changing slug later
- Add migrations before first production sync/install
- Treat generated files as scaffold only; implement domain logic immediately
- Use `--force` only in local/dev

---

## Quick Copy-Paste Commands

```bash
# create module (backend + frontend by default)
docker compose exec backend php artisan make:module HRMS --slug=hrms

# create module + sync + migrate
docker compose exec backend php artisan make:module HRMS --slug=hrms --sync --migrate

# delete module from DB + backend/frontend files
docker compose exec backend php artisan delete:module hrms

# sync manually
docker compose exec backend php artisan platform:sync

# run module migrations manually
docker compose exec backend php artisan module:migrate hrms
```

---

## Module Artifact Generators

After scaffolding a module with `make:module`, use these commands to generate backend artifacts inside `backend/Modules/{StudlyName}/`.

All generators share this signature pattern:

```bash
php artisan make:module:{artifact} {slug} {name} [--force]
```

### Commands

| Command | Example |
|---|---|
| `make:module:model` | `php artisan make:module:model hrms Employee` |
| `make:module:controller` | `php artisan make:module:controller hrms EmployeeController` |
| `make:module:service` | `php artisan make:module:service hrms EmployeeService` |
| `make:module:repository` | `php artisan make:module:repository hrms EmployeeRepository` |
| `make:module:migration` | `php artisan make:module:migration hrms create_employees_table` |
| `make:module:seeder` | `php artisan make:module:seeder hrms EmployeeSeeder` |
| `make:module:request` | `php artisan make:module:request hrms StoreEmployeeRequest` |
| `make:module:resource` | `php artisan make:module:resource hrms EmployeeResource` |

### Generated Paths (slug: `hrms` → `Modules/Hrms`)

| Generator | Output Path |
|---|---|
| model | `backend/Modules/Hrms/app/Models/{Name}.php` |
| controller | `backend/Modules/Hrms/app/Http/Controllers/{Name}.php` |
| service | `backend/Modules/Hrms/app/Services/{Name}.php` |
| service interface | `backend/Modules/Hrms/app/Contracts/{Name}Interface.php` |
| repository | `backend/Modules/Hrms/app/Repositories/{Name}.php` |
| repository interface | `backend/Modules/Hrms/app/Contracts/{Name}Interface.php` |
| request | `backend/Modules/Hrms/app/Http/Requests/{Name}.php` |
| resource | `backend/Modules/Hrms/app/Http/Resources/{Name}.php` |
| migration | `backend/Modules/Hrms/database/migrations/{timestamp}_{name}.php` |
| seeder | `backend/Modules/Hrms/database/seeds/{Name}.php` |

### Namespace Convention

Composer autoload maps `Modules\\` to `backend/Modules/`, so generated classes use namespaces like:

- `Modules\Hrms\app\Models\Employee`
- `Modules\Hrms\app\Http\Controllers\EmployeeController`
- `Modules\Hrms\app\Contracts\EmployeeServiceInterface`
- `Modules\Hrms\database\seeds\EmployeeSeeder`

### Recommended Workflow

1. `php artisan make:module HRMS --slug=hrms`
2. Generate domain artifacts (model, migration, repository, service, request, resource, controller)
3. Add service/repository bindings in the module service provider:

```php
$this->app->bind(EmployeeServiceInterface::class, EmployeeService::class);
$this->app->bind(EmployeeRepositoryInterface::class, EmployeeRepository::class);
```

4. `php artisan platform:sync`
5. `php artisan module:migrate hrms`
6. Wire routes in `backend/Modules/Hrms/routes/api.php`

### Full Example (HRMS Employee)

```bash
docker compose exec backend php artisan make:module HRMS --slug=hrms --force
docker compose exec backend php artisan make:module:model hrms Employee
docker compose exec backend php artisan make:module:migration hrms create_employees_table
docker compose exec backend php artisan make:module:repository hrms EmployeeRepository
docker compose exec backend php artisan make:module:service hrms EmployeeService
docker compose exec backend php artisan make:module:request hrms StoreEmployeeRequest
docker compose exec backend php artisan make:module:request hrms UpdateEmployeeRequest
docker compose exec backend php artisan make:module:resource hrms EmployeeResource
docker compose exec backend php artisan make:module:controller hrms EmployeeController
docker compose exec backend php artisan make:module:seeder hrms EmployeeSeeder
docker compose exec backend php artisan module:migrate hrms
```

### Generator Flags & Errors

- `--force` — overwrite an existing generated file
- Missing module folder or `module.json` — command fails with: **Run `make:module` first**
- Service/repository generators print provider binding hints when complete
- Controller generator prints companion command hints when request/resource/service files are missing

---

*Guide scope: ERPFlow custom plugin architecture (`backend/Modules/*` + `platform:sync` + Plugin Manager lifecycle).*
