# Zuma — cPanel Deployment Guide

This guide gets the Laravel 12 backend running on a cPanel-managed shared
hosting account so you can test it online.

---

## 0. What's in this ZIP

```
mrbismarck/
├── app/                  Application code (controllers, models, services...)
├── bootstrap/            Framework bootstrap (app.php, providers.php)
├── config/               Configuration files
├── database/
│   ├── migrations/       Laravel migrations (source of truth for schema)
│   ├── seeders/          Demo data seeders
│   ├── factories/         Test factories
│   └── sql/
│       └── mrbismarck_schema.sql   ⬅ Manual schema import (fallback)
├── public/               Web root — index.php, .htaccess
├── resources/            Views (PDF templates etc.)
├── routes/               api.php, web.php, console.php
├── storage/              Logs, cache, sessions (needs write permission)
├── tests/                Pest test suite
├── .env.example          Copy to .env and fill in your values
├── artisan               Laravel CLI
├── composer.json
├── deploy.sh             ⬅ One-shot setup script (run via SSH)
└── DEPLOYMENT_GUIDE.md    This file
```

> 🪄 **New: Web Setup Wizard.** Once the files are uploaded and Composer
> dependencies are installed (Steps 1–4 below), you can do *everything
> else* — database connection, migrations, and step-by-step demo data
> seeding with retries — from your browser at **`/install`**, with no SSH
> needed. See **Section 7.5**. This is the recommended path if `php artisan
> db:seed` keeps failing for you over SSH.

---

## 1. Requirements Check

In cPanel, confirm:

- **PHP version**: 8.3 (MultiPHP Manager → set PHP 8.3 for your domain)
- **PHP extensions enabled** (MultiPHP INI Editor): `pdo_mysql`, `mbstring`,
  `bcmath`, `ctype`, `fileinfo`, `json`, `openssl`, `tokenizer`, `xml`, `curl`,
  `gd` or `imagick`, `redis` (optional — only if you'll run queues/Horizon)
- **SSH access** (Security → SSH Access). Most things below assume SSH +
  Composer access via cPanel's "Setup Node.js/Python/etc" or Terminal app.
  If you truly have NO SSH/Composer, see **Section 11 (No-SSH fallback)**.
- **MySQL database** created via *MySQL® Databases* (note the DB name,
  username, password — cPanel usually prefixes these with `cpaneluser_`).

---

## 2. Upload the files

**Recommended layout — keep the app OUTSIDE `public_html`:**

1. Create a folder alongside `public_html`, e.g. `~/mrbismarck/` (use File
   Manager → "+ Folder" at the home directory level, not inside public_html).
2. Upload this ZIP there and extract it, so you end up with
   `~/mrbismarck/app`, `~/mrbismarck/public`, etc.
3. In cPanel → **Domains** (or "Addon Domains" / "Subdomains"), set the
   **Document Root** for the domain/subdomain you're testing on to:
   ```
   /home/cpanelusername/mrbismarck/public
   ```
   This is the cleanest setup — Laravel's `public/` folder becomes your web
   root directly, and everything else (`.env`, `app/`, etc.) stays outside
   web-accessible space.

**If your host does NOT let you change the Document Root** (some
budget shared plans only allow `public_html`):

1. Upload & extract the ZIP into `~/mrbismarck/` (outside `public_html`) as
   above.
2. Then copy (not move) the **contents** of `~/mrbismarck/public/` into
   `public_html/` (i.e. `public_html/index.php`, `public_html/.htaccess`,
   `public_html/build/` etc. — directly inside `public_html`, not in a
   subfolder).
3. Edit the copied `public_html/index.php` and change the two `require`
   paths from `__DIR__.'/../vendor/autoload.php'` and
   `__DIR__.'/../bootstrap/app.php'` to point at your app folder, e.g.:
   ```php
   require __DIR__.'/../mrbismarck/vendor/autoload.php';
   $app = require_once __DIR__.'/../mrbismarck/bootstrap/app.php';
   ```
4. Delete the root `.htaccess` included in this ZIP (it's only for the
   "whole project in public_html" approach, which is **NOT recommended**
   for security — it would expose `.env` and `app/` source if misconfigured).

---

## 3. Configure `.env`

```bash
cd ~/mrbismarck
cp .env.example .env
nano .env   # or edit via File Manager
```

Set at minimum:

```ini
APP_NAME="Zuma"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://yourdomain.com

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=cpanelusername_zuma
DB_USERNAME=cpanelusername_dbuser
DB_PASSWORD=your_db_password

SESSION_DRIVER=database
QUEUE_CONNECTION=database
CACHE_STORE=database
FILESYSTEM_DISK=local
```

> 💡 **No Redis on shared hosting?** Set `QUEUE_CONNECTION=database`,
> `CACHE_STORE=database`, `SESSION_DRIVER=database` instead of `redis`.
> Horizon requires Redis — if you don't have it, skip Horizon entirely
> (queues will still work via the database driver + cron, see Section 6).

> ⚠️ **Keep `FILESYSTEM_DISK=local` unless you have real AWS S3
> credentials.** If it's set to `s3` while `AWS_ACCESS_KEY_ID` /
> `AWS_URL` are blank, the S3 client gets an empty endpoint URL and
> seeding/booting will fail with `Curl error (code 3): URL using
> bad/illegal format or missing URL`. Switch to S3 later once you've
> filled in `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_BUCKET`,
> and a non-empty `AWS_URL`.

Leave payment gateway / OpenAI / Firebase keys blank for now if you're just
testing — the app will run fine, those integrations simply won't be
reachable until configured.

---

## 4. Install dependencies & generate key

```bash
cd ~/mrbismarck
composer install --no-dev --optimize-autoloader
php artisan key:generate
```

If `composer` isn't found, try `php8.3 /usr/local/bin/composer` or install
it per your host's docs (cPanel → Terminal → `which composer`).

---

## 5. Build the database

**Option A — fresh migrate + full demo data (recommended):**

```bash
php artisan migrate --seed
```

This creates all 55 tables (application tables + Sanctum, Spatie
permissions/activity log, and queue/cache tables), then seeds:
- 955 users (1 super admin, 3 country directors, 1 finance manager,
  100 drivers, 50 vendors, 800 customers)
- 100 restaurants with full menus
- 200 products across 6 categories
- 200 jobs + 100 freelance gigs
- 200 properties
- 100 hotels + 50 tours
- Sample rides

**Option B — import the SQL file manually (no demo data):**

If `php artisan migrate` fails for any reason, import
`database/sql/mrbismarck_schema.sql` via phpMyAdmin (Import tab) against the
empty database you created in cPanel. This creates the schema + roles/
permissions only (55 tables, including roles/permissions, activity log and
Sanctum tokens). You can then run `php artisan db:seed` separately if PHP
CLI works, to add demo data on top.

**Option C — Web Setup Wizard (recommended if seeding keeps failing):**

Skip Options A and B entirely and use **Section 7.5** below — it runs
migrations and each seeder individually from your browser, with retries.

---

## 6. Final setup steps

```bash
php artisan storage:link
php artisan config:cache
php artisan route:cache
chmod -R 775 storage bootstrap/cache
```

**Queue worker (for payment webhooks, notifications, AI scoring jobs):**
Since Horizon needs Redis + a persistent process (often unavailable on
shared hosting), set up a **cron job** instead:

cPanel → Cron Jobs → Add New Cron Job:
```
* * * * * cd /home/cpanelusername/mrbismarck && php artisan schedule:run >> /dev/null 2>&1
```

And run the queue worker via cron every minute (processes a batch then exits
— good enough for testing):
```
* * * * * cd /home/cpanelusername/mrbismarck && timeout 50 php artisan queue:work --stop-when-empty >> /dev/null 2>&1
```

---

## 7. Test it

Visit:
```
https://yourdomain.com/api/v1/auth/login
```
(should return a JSON validation error — that means routing works ✅)

Login with the seeded super admin:
```
POST /api/v1/auth/login
{
  "phone": "254700000001",
  "password": "Password@123"
}
```

---

## 7.5. Web Setup Wizard (`/install`)

If `php artisan db:seed` keeps failing over SSH, or you don't have SSH
access at all, use the browser-based wizard instead. After uploading the
files and running `composer install` (Steps 1–4), visit:

```
https://yourdomain.com/install
```

The wizard walks through, in order:

1. **Requirements** — checks PHP version, required extensions
   (`pdo_mysql`, `mbstring`, `gd`, etc.) and that `storage/` and
   `bootstrap/cache/` are writable.
2. **App & Database** — enter your app name/URL and DB credentials. It
   tests the connection, writes `.env` for you (including
   `FILESYSTEM_DISK=local` to avoid the S3/curl trap), and generates
   `APP_KEY` if missing.
3. **Migrations** — runs `php artisan migrate --force` and shows the
   output.
4. **Seed demo data** — each seeder (Roles, Core Users, Demo Accounts,
   Rides, Restaurants, Products, Jobs, Properties, Hotels) has its own
   **Run** button and shows its own output. If one fails, fix the
   underlying issue and click **Retry** on just that step — no need to
   start over. There's also a **"Quick demo data"** toggle that seeds
   ~85 users instead of ~950, for hosts with tight execution-time limits.
5. **Finish** — publishes Filament admin assets, caches config/routes,
   and shows you the full demo login table.

**Locking:** once you click "Finish", the wizard writes
`storage/app/install.lock` and refuses further access. To re-run it later
(e.g. to re-seed), add `INSTALL_SECRET=somesecret` to `.env` and visit
`/install?key=somesecret`.

> ⚠️ Treat `/install` like any other admin tool — it can rewrite your
> `.env` and re-run migrations/seeders. The lock file is your main
> protection once setup is done; don't share the `INSTALL_SECRET`.

---

## 8. Demo Accounts — Access Levels

After seeding, every role has at least one working login. **Password for all
demo accounts: `Password@123`**

| Role | Phone (login) | Email | Where to log in |
|---|---|---|---|
| Super Admin | `254700000001` | admin@zuma.app | `/admin` (Filament) or API |
| Country Director (KE/UG/TZ) | `254700000002` / `256700000002` / `255700000002` | director.ke@zuma.app etc. | `/admin` or API |
| Finance Manager | `254700000003` | finance@zuma.app | `/admin` or API |
| Business Manager | `254700000010` | demo.business@zuma.app | `/admin` or API |
| Merchant | `254700000011` | demo.merchant@zuma.app | API only |
| Restaurant Owner | `254700000012` | demo.restaurant@zuma.app | API only |
| Property Owner | `254700000013` | demo.property@zuma.app | API only |
| Real Estate Agent | `254700000014` | demo.agent@zuma.app | API only |
| Employer | `254700000015` | demo.employer@zuma.app | API only |
| Freelancer | `254700000016` | demo.freelancer@zuma.app | API only |
| Driver | `254700001001` | (random, see seeder) | API only |
| Vendor | `254700002001` | (random, see seeder) | API only |
| Customer | `254700010001` | (random, see seeder) | API only |

- **`/admin`** (Filament) only accepts `super_admin`, `country_director`,
  `business_manager`, and `finance_manager` roles — by design
  (`User::canAccessPanel()`). All other roles will see "credentials do not
  match" even with the right password, because Filament's login checks both
  the password AND panel access together.
- **All other roles** (customer, driver, vendor, merchant, restaurant,
  property_owner, agent, employer, freelancer, affiliate) authenticate via
  the **API** — this is how the Flutter/Vue mobile and web apps would log
  users in:
  ```bash
  curl -X POST https://yourdomain.com/api/v1/auth/login \
    -H "Content-Type: application/json" \
    -d '{"phone":"254700001001","password":"Password@123"}'
  ```
  This returns a Sanctum `access_token` to use as `Authorization: Bearer ...`
  on subsequent requests — the same flow a mobile app uses.

## 9. Partner Applications (Business Registration)

The landing page now includes a "Partner with us" registration form (scroll
to **For Partners** → **Apply to become a partner**). It covers all 10
partner types (driver, restaurant, vendor, property owner, agent, employer,
freelancer, affiliate, courier, hotel/tour operator) across all 3 countries,
plus a multi-select of service interests covering all 13 modules.

Submissions POST to `/api/v1/partner-applications` (public, rate-limited to
10/min) and are stored in the `partner_applications` table. View and manage
them in `/admin` under **Growth → Partner Applications** — mark as
Contacted/Approved/Rejected and add internal notes.

## 10. Admin Dashboard (Filament)

A web-based admin panel is included at:

```
https://yourdomain.com/admin
```

Login with the seeded super admin **email** (Filament login uses email, not
phone):

```
Email:    admin@zuma.app
Password: Password@123
```

From here you can manage Users & Roles, Drivers, Rides, Orders,
Transactions (read-only ledger), and Loans (with Approve/Reject actions).
The dashboard home shows live platform stats (users, rides today, revenue,
pending loans, etc.).

If `/admin` shows a 404 or unstyled page after deployment, run:
```bash
php artisan filament:assets
php artisan optimize:clear
```

Only users with role `super_admin`, `country_director`, `business_manager`,
or `finance_manager` AND `status = active` can log into `/admin` — other
roles (customer, driver, vendor, etc.) will be denied access even with valid
credentials, by design (`User::canAccessPanel()`).

---

## 11. No-SSH fallback (last resort)

If your host genuinely gives you no terminal/SSH/Composer:

1. Ask support to enable **SSH Access** and **Composer** — most cPanel
   hosts (Namecheap, Hostinger, A2, etc.) support this on request even on
   shared plans.
2. If truly impossible, you'll need to run `composer install` on your local
   machine (or this sandbox) and **upload the entire `vendor/` folder**
   (~150-300MB) via FTP — slow but works. Then import
   `database/sql/mrbismarck_schema.sql` via phpMyAdmin for the schema, run
   `php artisan key:generate` if you have *any* CLI access (even a "Run PHP
   Script" cPanel feature), or generate a 32-byte base64 key locally and set
   `APP_KEY=base64:...` directly in `.env`.
3. Demo data (seeders) **require PHP CLI** — without it you'll have an empty
   but functional schema (use Option B above + register your own test user
   via `/api/v1/auth/register`).

---

## 12. Troubleshooting

| Symptom | Fix |
|---|---|
| 500 error, blank page | Set `APP_DEBUG=true` temporarily, check `storage/logs/laravel.log` |
| "could not find driver" | Enable `pdo_mysql` in MultiPHP INI Editor |
| 403 / "Forbidden" on all routes | Check `public/.htaccess` exists and `mod_rewrite` is enabled |
| Migrations fail on FULLTEXT index | Your MySQL must be 5.7+/MariaDB 10.2+ with InnoDB fulltext support (most cPanel hosts since ~2018 are fine) |
| Storage/log permission errors | `chmod -R 775 storage bootstrap/cache` |
| Queue jobs never run | Set up the cron jobs in Section 6 |

---

Default login after seeding: **`254700000001`** / **`Password@123`**
(super admin — change this immediately on a public-facing deployment!)
