# Rider Referrals Module — Deployment

Adds a **Referrals** item under Corporate / SACCO for the MKR Boda
referral programme. Riders are existing Corporate/SACCO members on a
referral-enabled scheme; patients and encounters come from the existing
patients / visits tables. Nothing is duplicated.

> **Supersedes the earlier rider-referral build.** The previous
> `rider_referrers` / `rider_referrals` / `rider_payout_*` tables,
> models, controllers and views are left **dormant** (not dropped).
> Their old routes have been removed from `routes/corporate.php`, so the
> old screens are simply unreachable. You can delete them later once
> you're happy with the new module — see "Optional cleanup" below.

## Package contents

```
database/migrations/2026_05_31_120000_create_referral_tracking_tables.php   NEW
app/Models/Referral.php                                                      NEW
app/Models/ReferralPayout.php                                                NEW
app/Http/Controllers/Corporate/ReferralController.php                        NEW
resources/views/corporate/referrals/index.blade.php                          NEW
resources/views/corporate/referrals/partials/new.blade.php                   NEW
resources/views/corporate/referrals/partials/today.blade.php                 NEW
resources/views/corporate/referrals/partials/ledger.blade.php                NEW
resources/views/corporate/referrals/partials/payouts.blade.php               NEW
resources/views/corporate/referrals/partials/status-badge.blade.php          NEW
resources/views/corporate/referrals/rider-profile.blade.php                  NEW
resources/views/corporate/referrals/print/statement.blade.php                NEW
resources/views/corporate/referrals/print/report.blade.php                   NEW

app/Http/Middleware/CorporateAccess.php        MODIFIED (adds referral-capture role rule)
routes/corporate.php                           MODIFIED (replaces old rider-referral routes)
resources/views/layouts/app.blade.php          MODIFIED (adds the Referrals menu link)
```

> ⚠️ The three MODIFIED files OVERWRITE the existing copies on the
> server. They are built on top of the current (31 May) versions, so as
> long as you haven't edited those three files since, unzip with `-o`
> straight over the top. If you HAVE edited them, hand-merge instead
> (the changes are small and described in step 4).

## Step 1 — Drop files into the Laravel root

```bash
cd /home/clararos/domains/go.crh.co.ke/public_html
unzip -o crh-referrals-module.zip -d .

# confirm the new files landed
ls database/migrations/2026_05_31_120000_create_referral_tracking_tables.php
ls app/Models/Referral.php app/Models/ReferralPayout.php
ls app/Http/Controllers/Corporate/ReferralController.php
ls resources/views/corporate/referrals/index.blade.php
```

All five `ls` lines should print a path.

## Step 2 — Run the migration

```bash
php artisan migrate
```

One new migration should run:
`2026_05_31_120000_create_referral_tracking_tables`

Verify the two tables exist:
```bash
mysql -u clararos_hmis -p'PASSWORD' clararos_hmis -e "
SHOW TABLES LIKE 'referral%';
DESCRIBE referrals;
DESCRIBE referral_payouts;
"
```

Expected: `referrals` and `referral_payouts` listed; `referrals` has a
unique index on `encounter_id`.

## Step 3 — Make sure MKR has the referral programme switched on

The module shows riders from any scheme where
`referral_program_enabled = 1`. That flag/column already exists (added by
the earlier `add_referral_settings_to_corporate_accounts` migration), and
the wipe-dummy-data script already sets it for MKR. Confirm:

```bash
mysql -u clararos_hmis -p'PASSWORD' clararos_hmis -e "
SELECT code, name, referral_program_enabled, referral_bounty_amount
FROM corporate_accounts WHERE referral_program_enabled = 1;
"
```

Expected: MKR SACCO, `referral_program_enabled = 1`,
`referral_bounty_amount = 100.00`. The fee shown at the desk and stored on
each referral comes from `referral_bounty_amount` — change it there if the
bounty ever changes (existing referrals keep their captured fee).

## Step 4 — What changed in the three MODIFIED files (for hand-merging)

If you unzipped with `-o` you can skip this — it's only needed if you'd
edited these files yourself.

**`routes/corporate.php`** — the old `// Rider Referrals` block (dashboard,
riders CRUD, capture, payout runs) was replaced with the new set:
`referrals.index`, `referrals.search-riders`, `referrals.search-patients`,
`referrals.store`, `referrals.approve`, `referrals.cancel`,
`referrals.rider`, `referrals.mark-paid`, `referrals.statement`,
`referrals.export`. A `use ...\ReferralController;` import was added.

**`app/Http/Middleware/CorporateAccess.php`** — added a
`REFERRAL_CAPTURE_ROLES` set and a rule so that
`corporate.referrals.store` allows Reception/Cashier (front-desk capture).
Approve / cancel / payout stay on the admin/finance write roles.

**`resources/views/layouts/app.blade.php`** — added one nav link
("Referrals") in the Corporate / SACCO group, between Utilization and
Reports, visible to Admin, Finance and Reception/Cashier.

## Step 5 — Clear caches

```bash
php artisan route:clear
php artisan view:clear
php artisan config:clear
```

## Step 6 — Smoke test

1. Log in as **Reception/Cashier**.
2. Corporate / SACCO → **Referrals** → **New Referral** tab.
3. Search a rider by MKR number / name / phone — pick one.
4. Search a patient seen today — pick one. Date, fee (KES 100), encounter
   and MRN auto-fill. Click **Save Referral** (should take a few seconds).
5. You land on **Today's Referrals** with the new row, status **Pending**.
6. Try saving a second referral against the *same* encounter — it should
   be refused ("already linked to a referral").
7. Log in as **Admin/Finance**:
   - **Today's Referrals**: Approve / Cancel (cancel needs a reason).
   - **Referral Ledger**: filters + four summary cards + CSV/Excel/PDF export.
   - Click a rider name → drill-down profile + **Download Statement** (PDF).
   - **Payouts** tab (admin/finance only): outstanding-by-rider, **Mark as
     Paid** (records method + reference), and per-rider Statement.
8. Corporate / SACCO → **Audit Trail**: confirm `referral_created`,
   `referral_approved`, `referral_cancelled`, `payout_created`,
   `referral_paid` entries appear.

## Business rules enforced

- **One referral per encounter** — DB unique index + app check + race guard.
- **Fixed fee** — sourced from the scheme; not editable at the desk.
- **No hard deletes** — referrals only change status (Pending → Approved →
  Paid, or Cancelled). Cancel requires a reason and is audited.
- **Voided encounters never pay** — if an encounter is deleted or cancelled,
  its referral shows **Void** and is excluded from payable totals (the
  stored row is left intact for the audit trail).
- **Role gating** — Reception/Cashier can capture; only Admin/Finance can
  approve, cancel, run payouts, or pull statements.

## Optional cleanup (later, once you're happy)

The old rider-referral build is dormant but still on disk. When ready:

```bash
# remove old views
rm -rf resources/views/corporate/referrals/riders \
       resources/views/corporate/referrals/payouts \
       resources/views/corporate/referrals/referrals \
       resources/views/corporate/referrals/dashboard.blade.php
# old controllers + models + their migrations can also go, but only AFTER
# you drop the old tables in a planned maintenance window:
#   rider_referrals, rider_referrers, rider_payout_runs, rider_payout_lines
```

Leave the `referral_program_enabled` / `referral_bounty_amount` columns on
`corporate_accounts` — the new module uses them.

## Removal (roll back this module)

```bash
php artisan migrate:rollback --step=1   # drops referral_payouts + referrals
```
Then restore the previous `routes/corporate.php`,
`app/Http/Middleware/CorporateAccess.php` and
`resources/views/layouts/app.blade.php`, and delete the new
`app/Models/Referral*.php`, `ReferralController.php`, and
`resources/views/corporate/referrals/{index,rider-profile}.blade.php`,
`.../partials/*`, `.../print/*`.
