> For the complete documentation index, see [llms.txt](https://rdeneau.gitbook.io/safe-clean-architecture/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://rdeneau.gitbook.io/safe-clean-architecture/shopfoo/management.md).

# Product Management

This page describes how products are managed in Shopfoo: editing product information, managing pricing, and simulating the business events that affect stock and sales.

## Business areas involved

Product management in Shopfoo spans four business areas:

| Area          | Responsibility                         | Claim            |
| ------------- | -------------------------------------- | ---------------- |
| **Catalog**   | Product information                    | `Feat.Catalog`   |
| **Sales**     | Pricing, customer orders and revenue   | `Feat.Sales`     |
| **Purchases** | Supplier orders and restocking         | `Feat.Warehouse` |
| **Warehouse** | Stock levels and inventory corrections | `Feat.Warehouse` |

Each business area on the product page is only rendered if the current user holds the corresponding claim. Within a visible area, the access level further determines the UI state: a **View** claim renders form components as read-only or disabled; an **Edit** claim enables full interaction.

## Task-Based UI approach

Rather than a single generic edit form, Shopfoo uses a **Task-Based UI**: each user intention maps to a dedicated, focused command. This avoids the anaemic CRUD screens typical of back-offices and makes the business intent explicit.

![alt text](/files/zKOIGpt1kJoSbX1nGenP)

{% hint style="info" %}
For an introduction to Task-Based UIs, see Derek Comartin's video [Task-Based UI](https://youtu.be/DjZepWrAKzM).
{% endhint %}

## Product editing

The **Edit product** task allows users to modify the descriptive information of a product. The fields available depend on the product type:

| Field       | 🏪 Bazaar | 📘 Books | Required | Max Length | Component                 |
| ----------- | :-------: | :------: | :------: | :--------: | ------------------------- |
| Name        |     ✅     |     ✅    |     ✅    |     128    | Text input                |
| Category    |     ✅     |     —    |     ✅    |      —     | Radio button group        |
| Subtitle    |     —     |     ✅    |          |     256    | Text input                |
| Authors     |     —     |     ✅    |          |      —     | Multi-select              |
| Image URL   |     ✅     |     ✅    |          |      —     | Text input + live preview |
| Description |     ✅     |     ✅    |          |     512    | Text input                |

Visual feedback guides the user during editing: a **character counter** (`remaining / max`) is displayed for length-constrained fields, and a **red border** highlights any field with an invalid value after edition.

{% hint style="info" %}
See the [Validation](/safe-clean-architecture/front-end/validation.md) page for the front-end validation implementation details.
{% endhint %}

## Pricing management

The **Update pricing** task manages the two price fields independently:

* **Retail price** — the price charged to the customer.
* **List price** (MSRP) — the manufacturer's recommended retail price.

This is a separate task from general editing because pricing decisions often involve different roles or approval workflows.

The available pricing actions are:

| Action           | List price | Retail price | Condition    |
| ---------------- | :--------: | :----------: | ------------ |
| Define           |      ✅     |       ✅      | Price = None |
| Increase price   |      ✅     |       ✅      | Price ≠ None |
| Decrease price   |      ✅     |       ✅      | Price ≠ None |
| Remove           |      ✅     |       —      | Price ≠ None |
| Mark as sold out |      —     |       ✅      | Stock = 0    |

<details open>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Demo</strong></summary>

![Pricing](/files/rHyVkmrW1t68aWECX40U)

</details>

{% hint style="info" %}
The pricing drawer uses the [DaisyUI Drawer](https://daisyui.com/components/drawer/) component and opens from the **right**, pushing the "Actions" column to the left. This keeps all prices visible while the drawer is open — handy when entering a price relative to the others (e.g. for a book, the Retail Price should never exceed the List Price, even though nothing enforces this technically).
{% endhint %}

## Sales entry

The **Input sales** task simulates **customer purchases** on the storefront. It affects the **Sales** area (revenue) and the **Warehouse** area (stock decrease).

Users enter the sale date, then the quantity bought, and finally the sale price — which is pre-filled with the current Retail Price. The stock level is decremented accordingly.

<details open>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Demo</strong></summary>

![Input sales](/files/y6G5y6UaivmyNGinm7Gs)

</details>

## Purchase entry

The **Receive purchased products** task simulates a **stock arrival from a supplier**. It represents goods received from a supplier, affecting both the **Purchases** area (supplier order) and the **Warehouse** area (stock increase).

Users enter the purchase date, then the quantity supplied, and finally the purchase price — which is not pre-filled. The stock level is incremented accordingly.

<details open>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Demo</strong></summary>

![Receive products](/files/QyKQjJ19RMJ4hcv2DzkM)

</details>

## Stock adjustment

The **Inventory adjustment** task simulates an **inventory correction** following a warehouse count. It falls under the **Warehouse** area and allows entering a different quantity to reconcile the recorded stock with the physical count.

<details open>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Demo</strong></summary>

![Inventory adjustment](/files/R5W25rrmLRRksVN407o4)

</details>

## Adding a new product

After an [Open Library search](/safe-clean-architecture/shopfoo/products.md#open-library-search), clicking on a book from the search results (marked with ✨) opens its product detail page. The catalog information fieldset is **pre-filled** with data fetched from the Open Library API (title, subtitle, authors, cover image…).

{% hint style="info" %}
You can also browse [openlibrary.org/books](https://openlibrary.org/books/) directly, pick the edition you want (e.g. one with a cover image), extract the **OLID** from its URL (e.g. `https://openlibrary.org/books/OL48562615M/Tidy_First` → OLID = `OL48562615M`), and enter it in the Shopfoo URL. It is the presence of an **OLID** (rather than an ISBN) in the SKU that triggers the Open Library lookup and activates add mode.
{% endhint %}

The page adapts to an **add mode** with two key differences from normal editing:

* The **Actions column** (pricing, sales, purchases, stock) is **not available** — an info banner explains why:

> **New product ✨** — Pricing and inventory can be configured once the product is added.

* The save button at the bottom of the catalog fieldset is labelled **"Add"** instead of "Save".

Once the product is added, the page switches back to **edit mode**: the info banner disappears, the button becomes "Save", and the Actions column is displayed (subject to the user's access level).

{% hint style="info" %}
Front-end validation (required fields, character limits, broken image detection) is fully active during add mode — see the [Validation](/safe-clean-architecture/front-end/validation.md) page for details.
{% endhint %}

<details open>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f5a5">🖥️</span> <strong>Demo</strong></summary>

![Adding a new product](/files/rZJG74dtWJaALyImDbDT)

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://rdeneau.gitbook.io/safe-clean-architecture/shopfoo/management.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
