# Units — Contracts

> Produced by the Reversa **Writer** (phase: generation) · doc_level: `complete`
> Generated on 2026-09-21

**Confidence scale:** 🟢 CONFIRMED · 🟡 INFERRED · 🔴 GAP

External HTTP contract exposed by the `units` unit — the Laravel `resource settings/units` (`UnitController`) under the admin group (`['web','admin']`) with the `settings` prefix. It is a server-rendered **HTML/form** CRUD (redirect-back, not JSON), requires an authenticated admin session, and is a thin Encore\Admin `ModelForm` scaffold. `store`/`update`/`destroy`/`show`/`create` are framework defaults driven by `form()`; only `index`/`edit`/`grid`/`form` are overridden. 🟢 (`routes/web.php:86-89`, `UnitController.php`)

---

## Resource surface `settings/units` 🟢

| Method | Path | Purpose | Notes |
|--------|------|---------|-------|
| GET | `settings/units` | List + inline create form | Two-column: grid (id/name/description) + `Widgets\Form`. 🟢 (`:20-41`) |
| POST | `settings/units` | Create a unit | `name` (required) + `description`; `ModelForm::store`. 🟢 (`:76-82`) |
| GET | `settings/units/{id}/edit` | Edit form | `form()->edit($id)`; unknown id → `404`. 🟢 (`:43-49`) |
| PUT/PATCH | `settings/units/{id}` | Update a unit | `name` (required) + `description`; `ModelForm::update`. 🟢 (`:76-82`) |
| GET | `settings/units/{id}` (show) · GET `settings/units/create` · DELETE `settings/units/{id}` (destroy) | Framework defaults | Not surfaced in the UI: no create button, delete disabled on all rows. 🟡 (`:60,70`) |

- **Auth:** required; anonymous → `302 auth/login`. 🟢 (`routes/web.php:24-28`)
- **CSRF:** required on POST/PUT/DELETE (Laravel `web` middleware; Encore\Admin forms emit the token). 🟢
- **Create request (`POST settings/units`):**

  | Field | Type | Required | Notes |
  |-------|------|----------|-------|
  | `name` | string | ✅ | `rules('required')`. 🟢 (`:79`) |
  | `description` | string | ❌ | Free text. 🟢 (`:80`) |

- **Update request (`PUT settings/units/{id}`):** same field set (`name` required, `description`). 🟢 (`:79-80`)
- **Responses:** `200` HTML for list/edit; `302` redirect back on create/update; `422`/redirect-back on validation failure; `404` for an unknown id on edit/update. No JSON variant. 🟢
- **UI locks (not enforced server-side):** the id-1 row has no edit action; every row has delete disabled and there is no create button. These are grid-display gates, not authorization rules — the underlying resource routes still exist. 🟡 (`:60,67-70`)

---

## Consumed contracts (owned by other units)

`units` reads/writes only the `units` table through Eloquent; it calls no other unit's HTTP endpoint and no external service. 🟢

| Reads / writes | Owner unit | Purpose |
|----------------|------------|---------|
| `units` rows (CRUD) | this unit | measurement-unit master data |

---

## Producer/consumer relationships

| This unit is… | Counterparty | Contract |
|---------------|--------------|----------|
| **Producer** | `products-catalog` | the product create/edit screen lists units for the base-unit dropdown (`products.unit`, a **name string**) and the conversion-units table (`product_units.unit_id`, an integer FK). 🟢 (`units` flowchart:28-30) |
| **Producer** | `orders-crud` / `orders-print` | order lines capture `order_product.unit_id`; receipt + order-detail views label each line via `Unit::find(pivot.unit_id)->name`. 🟢 (`units` flowchart:31-32) |
| **Producer** | `customers-purchase-history` | customer-order line labels via `Unit::find(pivot.unit_id)->name`. 🟢 (`units` flowchart:40) |

---

## Cross-cutting contract notes

- **Scaffolded CRUD:** `store`/`update`/`destroy`/`show`/`create` are Encore\Admin `ModelForm` defaults; the domain contract is just `name`(required)+`description`. 🟢 (`:18,76-82`)
- **HTML/form, not JSON:** all responses are HTML pages or redirects. 🟢
- **Undeletable by design:** delete disabled on all rows because `product_units.unit_id` references units and receipts label lines via `Unit::find(pivot.unit_id)`. 🟡 (`:70`; `units` flowchart:30-32)
- **Protected default (id 1):** edit disabled on that row (active lock, unlike `categories`). 🟢 (`:67-69`)
- **Two keying schemes:** base unit is a name string (`products.unit`), conversions are ids (`product_units.unit_id`) — consumers must not assume a rename propagates. 🟡 (`units` flowchart:28-32)
- **Authorization:** authentication only; any admin may manage units. 🟡 (ADR-0009)
- **No observability:** unit mutations emit no telemetry. 🔴 (`UnitController.php`, absence)
