Skip to main content
Version: v1.0.0

Sales Receipts

A sales receipt (SR) is the direct-to-consumer counterpart to the sales order. Where a sales order commits whole cases to a wholesale customer, a sales receipt records a direct-to-consumer order and can move fractional cases. The two are independent documents: a receipt is never tied to a sales order, and it carries its own number, its own lifecycle, and its own line items. Like the sales order it is the demand side of finished-goods inventory and single-sided: it draws products down and never produces or consumes materials.

This first version is manual, entered by hand through the REST API and the webclient. There is no Shopify or other integration yet (see Not yet). Product coming back from a completed receipt is handled by the separate sales returns module, layered on top without touching the receipt's own flow.

What it does

  • Track the order. At its core a sales receipt is a record of a consumer order: who the customer is, the sales channel it came through (optional, picked from the same channel list as sales orders), how the customer was acquired (an acquisition source such as a TikTok ad, required, picked from a managed list maintained in Settings), where it ships from, what they ordered, the cost of getting it to them (freight, fulfillment, and the rest), and how far along it is. The customer is typed text, not a link to the wholesale customer list: a name plus an optional customer ID, the customer's identifier in whatever system the order came from. Both are optional, so an anonymous consumer order is fine. A receipt can also be marked as a subscription sale and as a recurring (repeat) customer. The two are separate axes, both describe the individual sale, and both default to off; with the customer as typed text there is no stable identity to derive repeat business from, so recurring is a manual toggle. It carries its own number, SR-YYYY-NNNN, minted by a dedicated sales-receipt counter alongside the existing purchase, work, sales, and production counters. Each line item is a SKU, a quantity in cases that may be fractional, and a unit price you set. The unit cost is not locked on the receipt; it is read from inventory, so the receipt stays informational on cost.
  • Draw down finished-goods inventory. As the order advances it records what the customer wants (demand), what has been set aside for them (allocated), and what has actually shipped (consumed), all on the finished-goods ledger under its own sales-receipt source.

How it works

Sales receipt state machine

A sales receipt is always in exactly one status, and because there are no receipts to post against it, every status change is by hand. One chain carries the order from arrival to close, with an exit beside it. The sections below cover the chain, then what it does to inventory and to the dates.

The statuses

StatusTypeWhat it means
PlacedManualThe order has come in. Their ordered quantity is booked as demand.
PaidManualPayment has been captured, and the stock is allocated to them.
ShippedManualGoods have shipped and are on their way, and the stock is consumed.
CompletedEndpointClosed.
CancelledExitCancelled before it ships (only from Placed or Paid), which reverses its inventory effects. Can be reactivated, returning to wherever it last was.

The whole chain is set by hand and freely reversible to fix a mistake; the status is the only thing that moves inventory.

Moving between them

  • By hand, both ways. The whole chain is yours to move along, forward or back. Stepping back from Shipped un-ships and removes the consumption, stepping back from Paid removes the allocation, and so on.
  • Cancelling. Cancel an order before it ships to stop it and reverse its inventory effects; reactivate it to bring it back to where it last was. Once it is Shipped the order can no longer be cancelled, since the goods are already on their way.
  • Deleting. A hard delete physically removes all of the receipt's ledger rows, matching the established behavior for purchase, work, and production orders.

Effect on inventory

What you doLedger effect
The order comes in (Placed)books the ordered quantity as demand
Mark it Paidallocates the stock to the customer
Ship it (Shipped)consumes the stock out of inventory
Cancel (before Shipped)reverses the booked demand and allocation back to zero

Projecting forward inventory effects requires a ship-from location to be set, and every entry carries the SR number as its reference.

One rule keeps the ledger tidy: anything you undo is erased, not stamped with a counter entry. Step the order back out of Shipped and the consumption is simply removed. The only lasting reversal is a cancel, and even that disappears if you reactivate the order. The ledger always reflects only what is true right now.

Dates

  • Order date is yours. It defaults to today when you create the order and you can change it whenever.
  • Status dates (placed, confirmed, in transit, and so on) stamp themselves as the order reaches each status, but stay editable afterwards so you can correct them.

Each ledger entry takes its date from the status that produced it: the demand booking from the placed date, the allocation from the confirmed date, and the consumption from the in-transit date. These are business dates, so editing one moves its entry with it. The record-of-entry timestamp never moves, so the stock history always reads in true business-date order, which is what positions and the cost model sort by.

Not yet

One piece is deliberately left for its own follow-up issue, to be linked here once it lands:

  • Integration. A path that posts receipts in from Shopify, first through a cron job and later through a native integration. Until then, receipts are entered by hand.

Returns, the other piece originally deferred here, have since landed as their own module: see Sales Returns.

See also

Drive sales receipts through the REST API or the MCP server.