# URL-Based Company Switching

## Problem

The application previously stored the active company in the **server-side session** (`session('company_id')`). Since all browser tabs share the same PHP session, switching company in one tab would affect every other open tab — causing data mix-ups for users who work with multiple companies simultaneously.

**Example of the bug:**
1. Tab A: Creating a sale for **Company 1**
2. Tab B: User switches to **Company 2**
3. Tab A: User clicks "Add New Party" → party created under **Company 2** (wrong!)

---

## Solution

Company context is now embedded in the URL using a `/c/{company}` prefix:

```
Before: /sales/create             ← company depends on session (shared across tabs)
After:  /c/1/sales/create         ← Company 1, always, regardless of other tabs
        /c/2/sales/create         ← Company 2, always
```

Each tab has its own URL, so company context is **tab-independent**.

---

## Architecture

### URL Structure

All company-scoped routes are prefixed with `/c/{company}`:

```
/c/1/dashboard          → Dashboard for Company 1
/c/1/sale/create        → Create sale for Company 1
/c/2/customers          → Customer list for Company 2
/c/1/admin/companies    → Admin panel (under Company 1 context)
```

Non-company routes remain unchanged:
```
/                       → Login page
/login                  → Login POST
/logout                 → Logout
/dashboard              → Redirect to /c/{default}/dashboard
/cash-mode/enable       → Cash mode (switches company)
```

### Key Files Changed

| File | Change |
|---|---|
| `app/helpers.php` | New file — `currentCompanyId()`, `currentCompany()`, `companyRoute()` helpers |
| `composer.json` | Registered `app/helpers.php` in autoload |
| `app/Http/Middleware/SetActiveCompany.php` | Reads company from route param first, sets `URL::defaults()` |
| `routes/web.php` | All company-scoped routes wrapped in `Route::prefix('c/{company}')` |
| `app/Http/Controllers/*.php` | Replaced `session('company_id')` → `currentCompanyId()` |
| `app/Models/ActivityLog.php` | Uses `currentCompanyId()` for logging |
| `app/Support/CashMode.php` | Uses `currentCompany()` for mode check |
| `resources/views/layouts/sidebar.blade.php` | Company switcher now uses links instead of POST forms |
| `resources/views/**/*.blade.php` | All `session('company_id')` replaced with `currentCompanyId()` |

---

## How It Works

### 1. Middleware: `SetActiveCompany`

The middleware reads the company from multiple sources in priority order:

1. **Route parameter** `{company}` (primary — from URL)
2. **Query parameter** `company_id` (fallback for API routes)
3. **Session** `company_id` (legacy fallback)
4. **User default** company (final fallback)

It also:
- Validates the user can access the requested company
- Sets `URL::defaults(['company' => $companyId])` so all `route()` helper calls auto-inject the company parameter
- Keeps session in sync for backward compatibility

### 2. Helper Functions

```php
currentCompanyId()     // Returns int — the active company ID
currentCompany()       // Returns Company model instance
companyRoute($name)    // Generates route URL with company auto-injected
```

### 3. URL::defaults

This is the critical piece that makes the migration low-effort. By calling:

```php
URL::defaults(['company' => $companyId]);
```

...in the middleware, all `route('sale.index')` calls in controllers and Blade views automatically include the `{company}` parameter. This means:
- No changes needed to `redirect()->route()` calls in controllers
- No changes needed to `route()` calls in Blade views
- No changes needed to menu links

### 4. Company Switcher (Sidebar)

The company switcher dropdown now generates **navigation links** instead of POSTing a form:

```html
<!-- Before: POST form that changed session -->
<form action="/switch-company" method="POST">
    <input type="hidden" name="company_id" value="2">
</form>

<!-- After: Simple link to dashboard under different company -->
<a href="/c/2/dashboard">Company 2</a>
```

Benefits:
- Instant switch (no POST request)
- Tab-independent (each tab keeps its company)
- Bookmarkable
- Browser back/forward works correctly

---

## Special Cases

### Cash Mode
Cash mode activates a special "cash company" and redirects to its URL prefix. The `CashModeController` now explicitly redirects to `/c/{cashCompanyId}/dashboard` after enabling, and to the user's default company after disabling.

### API Routes
API routes (`/api/...`) continue to accept `company_id` as a query parameter. The middleware falls back to this for API routes that don't have the URL prefix.

### Login Redirect
After login, users are redirected to `/dashboard` which auto-redirects to `/c/{defaultCompany}/dashboard`.

### Admin Companies Resource
The admin companies CRUD uses `{companyRecord}` as its route parameter to avoid conflicting with the `{company}` prefix parameter.

---

## Migration Checklist

If you add new routes or controllers:

1. **New routes**: Add inside the `Route::prefix('c/{company}')` group in `routes/web.php`
2. **New controllers**: Use `currentCompanyId()` instead of `session('company_id')`
3. **New views**: Use `currentCompanyId()` for hidden inputs and AJAX URLs
4. **Route redirects**: `route('name')` works automatically (URL::defaults handles it)
5. **New Blade links**: `route('name')` works automatically
