# Whitelabel Platform Setup - Implementation Plan (Approved)

## Final Product Decisions

1. Branding is global only.
2. Single-place mode is hide-only (no DB enforcement on assignments).
3. Access is strictly superadmin.
4. Entry route is hidden and direct: `/admin/platform-setup`.
5. Disabled modules must be hidden and must not process related jobs.
6. Branding applies platform-wide.
7. No navigation menu entry for this setup page.
8. No extra authentication layer on top of normal back-office auth.

---

## Implemented Structure

### New Config

- `config/platform_setup.php`
  - runtime cache TTL
  - default module states
  - env hard overrides (`MODULE_*_ENABLED`)

### New Persistence

- `platform_settings`
  - app/brand naming
  - contact identity
  - logo and favicon storage paths
  - `is_multi_place`, `default_place_id`
  - `updated_by_user_id`

- `platform_module_toggles`
  - `module_key`, `enabled`
  - global scope metadata
  - `updated_by_user_id`

### New Domain Layer

- `App\Models\PlatformSetting`
- `App\Models\PlatformModuleToggle`
- `App\Services\PlatformSetup\PlatformSetupService`
  - settings/module cache
  - module checks
  - orderable-module mapping
  - single-place filter helper
  - runtime branding config application
  - logo/favicon publishing to public assets

### New Superadmin Page

- `App\Filament\V1\Pages\PlatformSetupPage`
- hidden from navigation (`shouldRegisterNavigation() => false`)
- strict access (`employee.is_super_admin`)
- sections:
  - Branding
  - Business identity
  - Platform mode
  - Modules

---

## Runtime Wiring

### Boot-time Runtime Branding

- `AppServiceProvider::boot()`
  - applies platform runtime config early (`app.name`, `filament.brand`, favicon/logo values)

### Queue Guarding for Disabled Modules

- `AppServiceProvider::registerModuleQueueGuards()`
  - drops QuickBooks jobs when QuickBooks module is disabled
  - drops hotel channel sync/import jobs when Hotel module is disabled

### Filament Navigation Hiding

- `FilamentServiceProvider`
  - module-aware hiding for:
    - QuickBooks
    - Hotel
    - Restaurant
    - Shop
    - Bookable sections (personal/wellness/group/activity/service/event/protocol/daypass)
  - single-place filtering in V1 place navigation

### Filament Direct URL Blocking (Hide Completely)

- `App\Http\Middleware\EnsureFilamentModuleRouteEnabledMiddleware`
  - active on Filament auth middleware stack
  - blocks direct access (`404`) to disabled-module routes

### API Route-Level Module Blocking

- `App\Http\Middleware\EnsureModuleEnabledMiddleware`
  - generic `module.enabled:{key}` middleware
  - currently applied to chatbot route group:
    - `routes/chatbot.php` uses `module.enabled:chatbot`

### UpsertOrder Server-Side Enforcement

- `UpsertOrderRequest`
- `UpsertOrderChatbotRequest`
  - rejects disabled bookable orderable types at validation stage

### V2 Single-Place Filtering

- `App\Filament\V2\Pages\V2Page`
  - accessible places now filtered through `PlatformSetupService`

---

## Branding UI Overrides

- `resources/views/vendor/filament/components/brand.blade.php`
- `resources/views/vendor/filament/components/layouts/card.blade.php`
  - both now consume runtime platform logo/brand values

---

## Operational Notes

### Added env knobs

- `PLATFORM_SETUP_CACHE_TTL_SECONDS`
- `MODULE_QUICKBOOKS_ENABLED`
- `MODULE_HOTEL_ENABLED`
- `MODULE_RESTAURANT_ENABLED`
- `MODULE_SHOP_ENABLED`
- `MODULE_CHATBOT_ENABLED`
- `MODULE_BOOKABLE_*_ENABLED` (all supported bookable families)

### Deployment order

1. Run migrations.
2. Clear config/cache.
3. Restart workers (to apply queue guards + runtime config).

