# Tracking stock

The Stock module tracks how many units of a product you can still sell. Open it from **Stock** in the navigation; it has two screens: **Levels** (the stock table) and **Locations** (your warehouses and pickup points). The Stock entry only appears when the module is enabled for the active business, and every screen needs a business selected first (you'll see "Select a business first." otherwise).

The core rule: **products without a stock record sell without limits.** Tracking a product is opt-in. Until you track it, the storefront can sell it in any quantity; once tracked, its quantity caps how many units can be sold and low levels get flagged.

The product's own **Track stock** switch (on the product page, under **Stock & shipping**) comes first: while it is off, the product sells without limits and storefronts see it as untracked, even if it has a stock record here. See [Product fields](/docs/products/index#product-fields).

Quantities follow the product's unit, so stock can be fractional: 47.84 m² of fabric or 12.5 kg of flour. Every quantity field on these screens takes up to 3 decimals, with a dot or a comma.

## Track a product

1. On **Stock**, click **Track product**. An inline panel titled **Start tracking a product** opens (the button label changes to **Close** while it's open).
2. Pick a product from the **Select product...** dropdown. This is required; leaving it empty shows "Pick a product to track."
3. If the product has variants, a variant selector appears. Leave it on **Whole product** to track the product as a whole, or pick a variant to track that variant separately.
4. Optionally pick a location from **Select location...**.
5. Enter a **Quantity** (0 or more, with at most 3 decimals).
6. Optionally enter a **Threshold** and toggle **Allow backorder**.
7. Click **Track**.

| Field | Description |
| --- | --- |
| Product | Required. The product to track. |
| Variant | Only shown when the product has variants. Defaults to **Whole product**. |
| Location | Optional. Ties this stock record to one of your locations. |
| Quantity | Required. 0 or more, with at most 3 decimals. |
| Threshold | Optional, same format as Quantity. Rows at or below it are flagged as low; when unset, the default of 5 is used for the warning. |
| Allow backorder | Lets the product keep selling when quantity runs out. |

You can track the same product several times with different variants or locations; each combination gets its own row in the table.

## Read the stock table

| Column | Meaning |
| --- | --- |
| Product | The product name; shows "Product — Variant label" when a variant is tracked. |
| SKU | The product's SKU. |
| Location | Location name and code, when the row is tied to a location. |
| Quantity | The on-hand count. Sortable, and editable by clicking it. Shows red at 0 and amber at or below the threshold. |
| Available | Quantity minus reserved: what can still be sold. |
| Reserved | Units held by carts currently in checkout. Released automatically when the reservation expires or becomes a sale when the order is placed. Not editable. |
| Threshold | The low-stock threshold; `-` when unset. |
| Updated | When the row last changed. Sortable. |

Only **Quantity** can be edited; **Available** and **Reserved** are computed. Some columns (SKU, Location, Available, Reserved, Threshold, Updated) are hidden on small screens.

Use the search box to filter the table. When at least one location exists, a **Location** filter appears as well.

## Adjust a quantity

1. Click the quantity value in a row. It turns into an inline editor.
2. Change the quantity and, if you want, the threshold, location, and **Allow backorder** switch.
3. Optionally type a **Reason**. It's free text and is saved into the movement history, so future you knows why the number changed.
4. Click **Save** (or press Enter). **Cancel** or Escape discards the edit.

Quantity and threshold must be 0 or more, with at most 3 decimals: otherwise you see "Quantity must be 0 or more, with at most 3 decimals." or "Threshold must be 0 or more, with at most 3 decimals."

### View movement history

Click anywhere on a row (outside the quantity editor) to open a **Movements** panel below the table, titled "Movements: {product}". It's a read-only history, 25 entries per page with **Previous**/**Next** controls:

| Column | Meaning |
| --- | --- |
| Type | The kind of movement (adjustment, transfer, and so on). |
| Delta | The signed change, e.g. `+5`. |
| Location | Where the movement happened. |
| Reason | The reason entered with an adjustment, if any. |
| Reference | What caused the movement (its type and ID). |
| Date | When it happened, with time. |

Click **Close** to hide the panel.

A sale books a negative movement, and cancelling or refunding the order books the return. The return never exceeds what the order actually took: a line that was sold while the product was untracked, or converted from a quote without stock, puts nothing back. See [Change an order's status](/docs/selling/orders#change-an-orders-status).

## Transfer stock between locations

1. Click **Transfer stock**. A dialog opens: "Move quantity between locations for a product."
2. Pick the product, and a variant if applicable (**Whole product** by default).
3. Pick the **From location** and **To location**. They must differ ("Pick two different locations.").
4. Enter the quantity: greater than 0, with at most 3 decimals ("Quantity must be greater than 0, with at most 3 decimals." otherwise).
5. Click **Transfer**.

The **Transfer** button stays disabled until a product is picked. Transfers show up in the movement history of the affected rows.

## Stop tracking a product

Click **Untrack** on a row. A confirmation dialog titled **Untrack stock** asks: 'Stop tracking stock for "{product}"? The product will sell without limits.'

Untracking does **not** set the stock to zero or block sales. It deletes the stock record at your default location, which means the product goes back to selling in unlimited quantities. Untracking a row tied to a different location is not currently supported: clicking **Untrack** on such a row fails or removes the default-location record instead of the one you clicked. If you want to stop sales instead, keep the record and set its quantity to 0 with **Allow backorder** off.

## Import and export CSV

- **Export CSV** downloads the current stock table as `stock.csv`.
- **Import CSV** opens an **Import stock** dialog. Upload one `.csv` file with a header row. After the import you'll see how many rows were created, updated, and failed, with per-row error messages. Valid rows are imported even when other rows fail. The table refreshes when you close the dialog after a successful import.

The easiest way to get the expected columns is to export first and edit that file.

## Manage locations

Open **Stock → Locations** to manage the warehouses and stock points this business fulfills from. Locations power the per-location rows on the Levels screen, the Location filter, and stock transfers.

### Add or edit a location

1. Click **New location** (or **Edit** on an existing row).
2. Fill in the fields and save.

| Field | Description |
| --- | --- |
| Name | Required. |
| Code | Optional short code, shown in mono next to the name on the Levels screen. |
| Priority | Whole number, defaults to 0. Sortable in the table. |

### Default and active

- Exactly one location is the default, marked with a **Default** badge. Every other row shows a **Set default** button; clicking it makes that row the new default.
- Each row has an **Active** switch that takes effect immediately. A failure to save shows a toast.

### Delete a location

Click the delete button on a row. A **Delete location** dialog confirms: 'Delete "{name}"? This cannot be undone.' There is no undo.

## Low stock warnings and notifications

A row counts as low when its quantity is at or below its threshold; when no threshold is set, the default of 5 applies. Low rows show their quantity in amber, and a quantity of 0 shows in red.

Low stock surfaces in two more places:

- The dashboard shows a **Low stock** card listing affected products, with a **View all** link back to the Stock screen. When nothing is low it reads "No products at or below 5 in stock."
- The notification bell in the top bar receives a notification when stock runs low, showing the product (and variant), the available count against the threshold, and the location. Use **Mark all read** to clear the badge.

Storefronts read the same availability through the public API; see the API reference at [/api/stock/availability](/api/stock/availability) for how stock appears to your storefront.
