# Admin & Customer Filtering Design

## Goal
Add admin-scoped indexes for reservations and buildings, and enhance the customer-scoped indexes for reservations and receipts, while keeping every non-admin user seeing only their own data.

## Scope
1. **Admin reservations index** – `GET /api/v1/admin/reservations`
2. **Admin buildings index** – `GET /api/v1/admin/buildings`
3. **Customer reservations filters** – `GET /api/v1/customer/reservations`
4. **Customer receipts filters** – `GET /api/v1/receipts`

No new controllers are created; the new admin actions live on the existing `ReservationController` and `BuildingController`.

## Architecture

### 1. Routes
Two new admin routes inside the existing `role:super_admin|admin` group:

```php
Route::get('admin/reservations', [ReservationController::class, 'adminIndex']);
Route::get('admin/buildings', [BuildingController::class, 'adminIndex']);
```

Existing customer/owner routes stay unchanged.

### 2. FilterService
Four new scope-specific methods in `App\Services\Filter\FilterService`:

- `applyToAdminReservationQuery(Builder $query, array $filters): Builder`
- `applyToAdminBuildingQuery(Builder $query, array $filters): Builder`
- `applyToCustomerReservationQuery(Builder $query, array $filters): Builder`
- `applyToCustomerReceiptQuery(Builder $query, array $filters): Builder`

Each method only applies filters; scoping (owner/customer/global) is the controller’s responsibility, keeping FilterService reusable and scope-agnostic.

### 3. Controllers

#### `ReservationController::adminIndex(ListReservationsRequest $request)`
- Authorizes `viewAny` on `Reservation` (super-admin bypasses, admin allowed via policy).
- Starts with `Reservation::query()` (no owner scoping).
- Calls `FilterService::applyToAdminReservationQuery($query, $request->validated())`.
- Returns `ReservationResource::collection(...)` paginated.

#### `BuildingController::adminIndex(ListBuildingsRequest $request)`
- Authorizes `viewAny` on `Building`.
- Starts with `Building::query()` (no owner scoping).
- Calls `FilterService::applyToAdminBuildingQuery($query, $request->validated())`.
- Returns `BuildingResource::collection(...)` paginated.

#### `ReservationController::index(ListReservationsRequest $request)`
Already branches by customer/owner/employee. The customer branch will be updated to call `FilterService::applyToCustomerReservationQuery(...)` before paginating.

#### `ReceiptController::index(ListReceiptsRequest $request)`
Already scopes by customer/owner/employee. The customer branch will call `FilterService::applyToCustomerReceiptQuery(...)` before paginating.

### 4. Filters

#### Admin reservations
Same fields already validated in `ListReservationsRequest`:
- `status[]` – reservation status
- `payment_status[]` – `paid|partially_paid|unpaid`
- `building_id`, `unit_id`
- `check_in_from` / `check_in_to`
- `check_out_from` / `check_out_to`
- `created_from` / `created_to`
- `guests_min`
- `source`
- `q` – reservation number or customer name

#### Admin buildings
New `ListBuildingsRequest` for the admin index:
- `status` – `active|inactive|hidden`
- `owner_id`
- `region_id`, `city_id`, `country_id`
- `q` – building name

#### Customer reservations
Reuses `ListReservationsRequest`. Allowed filters for the customer branch:
- `status[]`
- `payment_status[]`
- `check_in_from` / `check_in_to`
- `check_out_from` / `check_out_to`
- `q` – reservation number or unit name/number

#### Customer receipts
New `ListReceiptsRequest`:
- `payment_status` – derived from `paid_amount`/`remaining_amount`:
  - `paid` – `remaining_amount == 0`
  - `unpaid` – `paid_amount == 0`
  - `partially_paid` – everything else
- `from` / `to` – `created_at` date range
- `has_balance_due` – boolean; when true, `remaining_amount > 0`
- `q` – `document_number` partial match

### 5. Validation
- Extend `ListReservationsRequest` so it also accepts a `tab` parameter (`all|upcoming|past`) to preserve the existing tab-style slicing while adding the new filters.
- Create `ListBuildingsRequest` for admin buildings.
- Create `ListReceiptsRequest` for receipt filters.

### 6. Authorization
- Admin routes use the existing `role:super_admin|admin` middleware.
- Existing customer/owner routes continue to use policies (already updated to require approved owners/active employees).

### 7. Testing
Add feature tests for:
- Admin reservations index returns all reservations and respects filters.
- Admin buildings index returns all buildings and respects filters.
- Customer reservations filters are scoped to the authenticated customer.
- Customer receipts filters are scoped to the authenticated customer.
- Existing owner/customer scoping is not broken.

## Decisions
- **Dedicated admin routes** are added to keep admin logic explicit and avoid changing the behavior of the owner/customer indexes.
- **FilterService gets scope-specific methods** so each index can have its own supported filters without bloating a single generic method.
- **Controllers retain scoping responsibility**; FilterService only applies filters to an already-scoped query.
