# People Admin

Admin panel for managing customer/user records.
Route prefix: `/admin/people` — protected by `auth` + `is_admin` middleware, named with the `appshell.` prefix.

---

## User Deletion

**Route:** `DELETE /admin/people/{user}` → `appshell.people.destroy`  
**Controller:** `App\Http\Controllers\Vanilo\Admin\PeopleController@destroy`

Permanently deletes a user and every database record associated with them. The entire operation runs
inside a single `DB::transaction()` — if any step fails the database is left unchanged.

### Deletion order

Records are deleted in dependency order to avoid FK violations:

| Step | Table(s) | Condition |
|------|----------|-----------|
| 1 | `aff_conversions` | `affiliate_id` = user's affiliate |
| 2 | `aff_clicks` | `affiliate_id` = user's affiliate |
| 3 | `aff_payout_items` | via `payout_id` of user's payouts |
| 4 | `aff_payouts` | `affiliate_id` = user's affiliate |
| 5 | `aff_affiliates` (recruits) | `referred_by_affiliate_id` nulled, not deleted |
| 6 | `aff_affiliates` | user's own row |
| 7 | `aff_customer_attributions` | `user_id` = deleted user |
| 8 | `subscription_items` | via `subscription_id` of user's subscriptions |
| 9 | `subscriptions` | `user_id` = deleted user |
| 10 | `payments` | `user_id` = deleted user |
| 11 | `plugin_downloads` | `user_id` = deleted user |
| 12 | `plugin_coupons` | `user_id` = deleted user |
| 13 | `gifted_products` | `user_id` = deleted user |
| 14 | `messages` | via `conversation_id` of user's conversations |
| 15 | `conversations` | `user_id` = deleted user |
| 16 | `order_items` | via `order_id` of user's orders |
| 17 | `orders` | `user_id` = deleted user |
| 18 | `customer_addresses` | `customer_id` = deleted user |
| 19 | `model_has_roles` | `model_id` = deleted user |
| 20 | `model_has_permissions` | `model_id` = deleted user |
| 21 | `users` | the user row itself |

### Guards

- **Self-deletion blocked** — if the authenticated admin tries to delete their own account the
  action is rejected with an error flash and a redirect back to the user's show page.
- **Recruits preserved** — sub-affiliates recruited by the deleted user are not deleted; only their
  `referred_by_affiliate_id` is set to `null` so they remain active affiliates.

### UI

A **Danger Zone** card is rendered at the bottom of the user show page
(`resources/views/vendor/vanilo/people/show.blade.php`). The delete button is disabled when viewing
your own account. Clicking the button triggers a browser `confirm()` dialog before submitting the
`DELETE` request.

---

## Referral attribution at registration

`users.referred_by_affiliate_id` (added by migration `2026_03_13_000001`) permanently records which
affiliate referred a user at sign-up. It is written by:

- `RegisteredUserController@store` (email/password registration)
- `SocialiteController@callback` (OAuth new-user branch)

Both read the `affiliate_ref` cookie set by `TrackClickMiddleware`. The value survives cookie
expiry and is used as a fallback in `ApplicationController::resolveReferrer()` when a user joins
the affiliate programme long after the cookie has expired.
