Skip to content

Stock bookings

Every stock booking is one movement record. This page shows, for each kind of booking, what the reference app checks, which record it writes and what other devices derive from it. All examples book the article "Cordless drill 18 V" (4A7C...6A80, serial-tracked) or "Wireless access point AP-7" (8C1F...0A13, not serial-tracked).

Locations used: Shelf A01 2B0E6C1A-7D44-4F1B-9C3E-5A8D2F6B1C07 (code N-A01), Service van 1 6F3D9A20-1C5B-4E77-8A2D-3B9C0E4F5A61 (code V-01).

Goods arrive and are put on a shelf.

Checks on the device: for serial-tracked articles one serial number per unit, none of them already in stock.

Record written:

{
"entity": "movement",
"id": "77AA0C41-2E9B-4F7D-8B1A-5D3C2E1F0A99",
"op": "upsert",
"hlc": "001791792000123-0002-3F2A9C1B",
"data": {
"type": "receipt",
"article_id": "4A7C2E91-0B3D-4F6A-8E15-7C9B2D4F6A80",
"to_location_id": "2B0E6C1A-7D44-4F1B-9C3E-5A8D2F6B1C07",
"quantity": 2,
"serials": ["DR-1001", "DR-1002"],
"note": "Order 4711",
"booked_at": "2026-10-12T08:00:00Z",
"booked_by": "Erika Mustermann"
}
}

Derived: stock at N-A01 +2; DR-1001 and DR-1002 in stock at N-A01.

Goods leave the warehouse without a document (consumption, disposal, a sale handled elsewhere).

Checks: quantity not above the stock at the source location; serial numbers in stock at that location.

{
"entity": "movement",
"id": "5B7D9F1A-3C5E-4708-9A2C-4E6A8C0E2B35",
"op": "upsert",
"hlc": "001791793800000-0000-3F2A9C1B",
"data": {
"type": "issue",
"article_id": "8C1F3D2E-5B7A-4A61-9F0E-2B4C6D8E0A13",
"from_location_id": "2B0E6C1A-7D44-4F1B-9C3E-5A8D2F6B1C07",
"quantity": 1,
"note": "Used for repair 2026-118",
"booked_at": "2026-10-12T08:30:00Z",
"booked_by": "Erika Mustermann"
}
}

Issues to a customer or site with a document are delivery notes; equipment that has to come back is a loan.

Goods move between two locations of the inventory, for example from the shelf into a service van.

Checks: as for an issue, at the source location.

{
"entity": "movement",
"id": "6C8EA02B-4D6F-4819-AB3D-5F7B9D1F3C46",
"op": "upsert",
"hlc": "001791794700000-0000-3F2A9C1B",
"data": {
"type": "transfer",
"article_id": "4A7C2E91-0B3D-4F6A-8E15-7C9B2D4F6A80",
"from_location_id": "2B0E6C1A-7D44-4F1B-9C3E-5A8D2F6B1C07",
"to_location_id": "6F3D9A20-1C5B-4E77-8A2D-3B9C0E4F5A61",
"quantity": 1,
"serials": ["DR-1002"],
"booked_at": "2026-10-12T08:45:00Z",
"booked_by": "Erika Mustermann"
}
}

Derived: N-A01 −1, V-01 +1; DR-1002 in stock at V-01.

Someone counts what is on a shelf and enters the counted quantity. The device writes the difference to the stock it computed, so that counts on several devices add up.

Checks: the counted quantity differs from the computed stock.

Counted 17 access points where the device computed 20:

{
"entity": "movement",
"id": "3E5A7C9B-1D2F-4A6B-8C0E-2F4A6C8E0B13",
"op": "upsert",
"hlc": "001791797400000-0000-3F2A9C1B",
"data": {
"type": "adjustment",
"article_id": "8C1F3D2E-5B7A-4A61-9F0E-2B4C6D8E0A13",
"to_location_id": "2B0E6C1A-7D44-4F1B-9C3E-5A8D2F6B1C07",
"quantity": -3,
"counted": 17,
"booked_at": "2026-10-12T09:30:00Z",
"booked_by": "Erika Mustermann"
}
}

Derived: stock at N-A01 −3. If another device booked an issue of 1 at the same time offline, the result after syncing is 16: the count was made against a stock that did not include that issue. Count again when the numbers disagree.

An adjustment may carry serial numbers; each one is then in stock at to_location_id, also for a negative adjustment. The reference app does not require serial numbers on counts.

Movements cannot be changed or deleted. A wrong receipt of 10 instead of 1 is corrected with an issue of 9 (or a stock count) that references the mistake in note. Pushing a delete of a movement is rejected with immutable; pushing a changed version with the same id is ignored.

For articles with track_serials: true:

Booking Serial rule
receipt one new serial per unit; a serial already in stock is refused
issue, transfer one serial per unit, each in stock at the source location
adjustment serials optional; listed serials become in stock at the location
delivery note line as issue
loan handover as issue
loan return (ok, damaged) as receipt, the serials handed out
loan return (lost) no movement; the serial stays "issued"

The state of a serial is decided by its latest movement (by booked_at, then hlc), see Derived state. A serial that left on a loan and is still outstanding is shown as "on loan" with the loan's number and borrower.

Codes are not part of the records' merge logic, but labels printed by one client are scanned by others, so the reference app's resolution order is listed here. A scanned or typed code (trimmed) is resolved by the first rule that matches:

  1. App URL. lve://location/<code>, lve://article/<sku> and lve://serial/<serial> (percent-encoded path, scheme and kind case-insensitive). inventar:// is read as an older spelling of lve://. The value is compared case-insensitively with the location code, the item number or the serial number. lve://pair?... is a pairing link.
  2. GS1 element string with AI 01 (GTIN, 14 digits) and optionally AI 21 (serial number), in raw form with FNC1 separators or in human-readable form (01)04012345678901(21)ABC. The GTIN (and its shorter EAN/UPC forms) is looked up in the article barcodes; the serial is taken over into the booking.
  3. Location code, case-insensitive.
  4. Barcode of an article, exact; a 12-digit UPC-A also matches its 13-digit EAN form with a leading zero and the other way round.
  5. Item number (sku), case-insensitive.
  6. Serial number, case-insensitive.

The reference app puts lve://location/<code> into the QR codes of location labels and lve://article/<sku> into those of article labels; other clients SHOULD use the same URLs so that labels work across apps.