# AI inventory management that ends in a purchase request

> Atta keeps stock as a ledger, forecasts when each item runs out from measured usage and quoted lead times, and opens a restock request instead of ordering.

Updated 2026-11-06. Source: https://atta.sh/inventory-management

Atta keeps stock as a ledger of movements, so on hand is always a sum and a count writes only the difference. It works out when each item runs out from the measured usage rate and quoted lead times. When an item falls to its reorder point it opens a restock request, which goes through your approvals. It never orders on its own.

## Stock is a ledger

Every change to stock is a row in `stock_movement`: a signed quantity for one item at one location, with who did it and what it came from. On hand is `sum(quantity)`. There's no counter to drift.

A stock count writes the difference. If the system says 40 and someone counts 37, it writes a `counted` row of -3, so the history shows when the gap appeared and who counted.

Movement kinds are `received`, `issued`, `shipped`, `sold`, `transfer`, `adjusted`, `counted`, `reversed`, `consumed`, `produced` and `returned`.

## It refuses to go below zero

Committing an outbound, adjusting down or transferring out checks the shelf inside one transaction that locks the item rows. A shortfall is refused with both figures:

> Only 3 of Cable ties 200mm at Main. 5 asked.

An outbound is a document that takes stock out. A `use` issues it to a person or project, a `ship` sends it to an address, and a `sell` sells it to a customer with prices. Each is numbered (`OUT-2026-0014`) and moves through a status table. Cancelling a committed one writes `reversed` rows that put the stock back, keyed so it happens once.

## Receiving is one code path

When a purchase arrives, `receiveIntoStock` is the one place it becomes stock. Receiving on the request page, the store's fulfilled webhook and the inbound shipment page all write the same row, for the change in quantity only, so a webhook delivered twice writes nothing the second time. If the purchase belongs to an open inbound shipment, the stock lands at that shipment's location.

## Several locations

A location has a kind: warehouse, store, workshop, vehicle, quarantine, or the one system `transit` location. Stock moves between locations only through a numbered transfer, which writes rows from the source to transit on dispatch and from transit to the destination on receipt. Stock on a truck is still on hand and still has a value. Quarantine counts on hand but never as available.

Each location can have a minimum and a target for an item and the location that feeds it. Those levels draft transfers. They never move stock by themselves.

## When an item runs out

The outlook is a straight line, not a model. Atta measures daily usage from the ledger and then walks forward day by day, adding the landings it knows about: the unreceived part of an open inbound shipment with an expected date, a transfer in transit, a work order with a due date. Lead times are the quoted ones from the supplier's catalog line.

| Item | On hand | Usage per day | Cover | Next landing |
| --- | ---: | ---: | ---: | --- |
| Nitrile gloves, M (box) | 18 | 3 | 6 days | 40 on Nov 14 |
| Cable ties 200mm (bag) | 52 | 1.5 | 35 days | none |
| Label rolls 100x150 | 9 | 2 | 4.5 days | none, quoted lead time 7 days |

The gloves run out on day 6 and the next landing is on day 8, so there's a gap. The label rolls run out before a new order could arrive, so they're first in the list of what needs a decision. The cable ties are fine. Picking a source on the runway view draws a what-if landing and recounts the dry days.

## A reorder is a request

When on hand across all locations falls to the reorder point, Atta opens a request with one line linked to the item, for the reorder quantity at the last cost. It then goes through the ordinary approval chain, like any purchase. An item that already has an open restock request opens nothing new. The check runs hourly and right after anything lowers stock, and members who can manage inventory get a notification.

> **Atta, in Slack to Dana:** Label rolls 100x150 are at 9, below the reorder point of 12. I've opened a restock request for 40 rolls at $6.20, $248.00 in all, and it's waiting on you.

The agent reads stock and doesn't write it. `checkStock` answers "do we already have this" before the agent sources anything, and the inventory planner agent acts on the forecast by opening requests. Nothing the agent can call changes the ledger.

## Who can change stock

Everyone in the workspace can see stock. Creating items and locations, adjusting, counting, transferring and moving outbounds need the `inventory` capability, held by owners, admins and buyers, and every Server Action checks it again.

## Builds and kits

An item can have a bill of materials. A production run consumes the components at their average cost and writes one `produced` row at the rolled-up cost, in one transaction, so a retried run doesn't write twice. A kit is sold and never stocked: it holds no movements, and a sale withdraws its parts.

For the multi-site case, see [multi-site inventory](https://atta.sh/use-cases/multi-site-inventory).

## Questions

### Does Atta reorder stock automatically?

It opens a restock request when an item reaches its reorder point. The request goes through your approval rules like any purchase, so a person or your policy decides whether the order happens.

### How does it predict when an item runs out?

It measures daily usage from the movement ledger and projects it forward from the stock you have, adding known landings such as open inbound shipments and quoted lead times. It's a straight line from measured figures.

### What does a stock count do?

It writes a movement for the difference between what the system says and what was counted. Nothing is overwritten, so the history keeps the correction.

### Can it track stock across several locations?

Yes. Locations can be warehouses, stores, workshops or vehicles, and stock moves between them through numbered transfers that pass through a transit location, so stock on the road stays on hand.
