# Brands Specification

## Purpose

The Brands capability provides back-office administrators with a reference-data editor for product brands. Brands are permanent master data: every product must belong to a brand via a required foreign key, so brands cannot be deleted. Only name and description are managed.

## Requirements

### Requirement: List brands on the management screen

The system SHALL render a two-column management screen at `GET settings/brand` showing, in the left column, a grid of all existing brands with columns `id` (sortable), `name`, and `description`, and in the right column an inline create form. The grid SHALL NOT display a create button, export control, row selector, filter, or pagination. (Implemented in `app/Http/Controllers/BrandController.php:19-40,53-64`)

#### Scenario: Authenticated admin loads the brand list

- **GIVEN** an authenticated administrator
- **WHEN** they request `GET settings/brand`
- **THEN** the system returns HTTP 200 with a page containing the brand grid (columns: id, name, description) and an inline "new brand" form

### Requirement: Create a brand via the inline form

The system SHALL accept `POST settings/brand` with `name` (required) and `description` (optional) and, on valid input, persist a new brand and redirect back to the list. On missing `name`, the system SHALL reject the request and redirect back with validation errors without persisting any brand. (Implemented in `app/Http/Controllers/BrandController.php:75-81`)

#### Scenario: Valid brand submission

- **GIVEN** an authenticated administrator on the brand management screen
- **WHEN** they submit the inline form with a non-empty `name` and any `description`
- **THEN** a new brand is persisted and the system redirects (HTTP 302) back to `settings/brand`

#### Scenario: Missing name validation

- **GIVEN** an authenticated administrator on the brand management screen
- **WHEN** they submit the inline form without providing `name`
- **THEN** no brand is created and the system redirects back with a validation error for the `name` field

### Requirement: Edit an existing brand

The system SHALL provide an edit form at `GET settings/brand/{id}/edit` with fields `name` (required) and `description`. Submitting `PUT settings/brand/{id}` with valid input SHALL update the brand and redirect back to the list. Requesting an unknown `id` SHALL return HTTP 404. (Implemented in `app/Http/Controllers/BrandController.php:42-48,75-81`)

#### Scenario: Successful brand edit

- **GIVEN** an authenticated administrator and an existing brand with id ≠ 1
- **WHEN** they request `GET settings/brand/{id}/edit` and submit the form with a non-empty `name`
- **THEN** the brand's `name` and `description` are updated and the system redirects (HTTP 302) to the list

#### Scenario: Edit with missing name

- **GIVEN** an authenticated administrator editing an existing brand
- **WHEN** they submit `PUT settings/brand/{id}` without `name`
- **THEN** the brand is not updated and the system redirects back with a validation error for `name`

#### Scenario: Edit unknown brand

- **GIVEN** an authenticated administrator
- **WHEN** they request `GET settings/brand/{id}/edit` for a non-existent `id`
- **THEN** the system returns HTTP 404

### Requirement: Lock the default brand from editing

The system SHALL suppress the edit action for the brand with id `1` in the grid row-action controls, preventing it from being edited through the UI. (Implemented in `app/Http/Controllers/BrandController.php:65-68`)

#### Scenario: Default brand row has no edit action

- **GIVEN** an authenticated administrator viewing the brand grid
- **WHEN** the grid renders the row whose `id` is `1`
- **THEN** no edit action is present on that row

#### Scenario: Other brand rows have an edit action

- **GIVEN** an authenticated administrator viewing the brand grid
- **WHEN** the grid renders a row whose `id` is not `1`
- **THEN** the edit action is present on that row

### Requirement: Prevent deletion of all brands

The system SHALL suppress the delete action for every brand row in the grid, making no brand deletable through the UI. (Implemented in `app/Http/Controllers/BrandController.php:69`)

#### Scenario: No brand row offers delete

- **GIVEN** an authenticated administrator viewing the brand grid
- **WHEN** any row's actions are inspected
- **THEN** no delete action is present on any row

### Requirement: Require an authenticated admin session

The system SHALL redirect unauthenticated requests for any route under `settings/brand` to `auth/login` with HTTP 302. (Implemented in `routes/web.php:24-28,86-87`)

#### Scenario: Anonymous access is redirected

- **GIVEN** a request that carries no valid admin session
- **WHEN** any `settings/brand` route is requested
- **THEN** the system responds with HTTP 302 to `auth/login`

#### Scenario: Authenticated access is permitted

- **GIVEN** a request that carries a valid admin session
- **WHEN** `GET settings/brand` is requested
- **THEN** the system responds with HTTP 200
