Cycle Counts
A targeted physical audit of a location or bin that snapshots expected quantities, collects your physical counts, and posts the differences as inventory adjustments.
A cycle count is how you reconcile what Knowledge ERP thinks is on the shelf against what's actually there. Rather than shutting down an entire warehouse for a full physical inventory, you run focused counts — one location at a time, one bin at a time — so stock accuracy stays high without interrupting operations.
When you create a count, the system automatically generates a count line for every unit in scope, snapshotting its current recorded quantity as the expected quantity. You then walk the shelves, enter what you actually see, and post the count — at which point any discrepancies are written back as Adjustment movements on the affected units.
A posted cycle count cannot be undone. The adjustment movements it creates are permanent and form part of each unit's movement history. If you made an error, run a new count to correct the quantities.
Creating a cycle count #
New counts are created from Inventory → Cycle Counts → New Cycle Count.
- Location — the warehouse, room, or vehicle to count. Leave blank to include all locations (single-location accounts hide this field entirely). The form defaults to your active location.
- Bin — optionally narrow the scope to a single bin within the location. The dropdown shows every bin's full hierarchical path (e.g. Warehouse A → Rack 5 → Shelf 3). See Locations & Bins.
- Notes — free-text memo for the count (who requested it, why, etc.).
Saving the form creates the count in Draft status and immediately generates count lines for every unit in the chosen scope.
Statuses #
A cycle count moves through four statuses:
- Draft — just created; lines have been generated but counting hasn't begun.
- In Progress — counting is underway. A count transitions here automatically the moment you open the Scan Mode page.
- Posted — all adjustments have been applied. Final state; the count is read-only.
- Cancelled — abandoned without posting. No adjustments were written.
Entering counts #
There are two ways to record what you physically counted for each line.
Table view #
On the count's Edit page, the Units to Count table lists every line with
its Product name, barcode, bin, expected quantity, counted quantity, and
variance. Click Enter Count on a line to type the physical quantity (as
a percentage, 0–10000 where 10000 = 100%) and an optional note. The
variance badge updates immediately — green for a surplus, red for a
shortage, gray for no difference.
The Mark All as Expected header action bulk-sets every uncounted line to its expected quantity (i.e. variance of zero), useful when you've confirmed a large section matches and want to close out the remaining lines quickly.
Scan Mode #
For faster floor counting, open Scan Mode from the Edit page header. The dedicated scan interface works like this:
- Scan a bin barcode to set an active bin filter — subsequent unit scans are matched only against units in that bin.
- Scan a unit barcode to pull up the matching count line.
- Confirm or adjust the quantity and save. The last five scanned units appear as a recent-activity list so you can spot errors quickly.
- Clear the bin filter at any time to scan across all bins again.
Opening Scan Mode transitions a Draft count to In Progress automatically.
Posting adjustments #
When all lines are entered — or when you're satisfied with what's been counted — click Post Adjustments on the Edit page. You'll see a confirmation dialog reminding you the action is irreversible.
Posting does the following for every line that has a counted_quantity:
- Compares
counted_quantitytoexpected_quantity. - If they differ, calls
adjust()on the inventory unit, setting itsquantity_remainingto the counted value and writing an Adjustment movement attributed to the cycle count. - Lines without a
counted_quantity(still blank) are skipped — they neither create an adjustment nor flag an error.
The count's status becomes Posted and posted_at is stamped with the
current time.
Lines where
counted_quantityequalsexpected_quantitydo not produce an adjustment movement — only genuine discrepancies touch unit records.
Cancelling a count #
If you started a count by mistake or it's no longer needed, Cancel Count from the Edit page header sets the status to Cancelled without writing any adjustments. Cancelled counts are retained for audit purposes.
Count lines #
Each line in the Units to Count table corresponds to one physical unit. A line records:
- Product and unit barcode — for identification.
- Bin — where the unit was located when the count was created.
- Expected quantity — the system's recorded
quantity_remainingat the moment lines were generated, stored as an integer (where10000= 100%). - Counted quantity — what you physically observed, same scale. Null until entered.
- Variance —
counted − expected, displayed as a signed percentage badge. - Notes — any remarks about this specific unit's count.
Relationship to units and movements #
Cycle counts work entirely through inventory units.
When a count is posted, each adjusted unit gains a new Adjustment movement in
its Movements tab, with the note "Cycle count" (plus your line note if
provided). This keeps the unit's movement history complete — anyone looking at
a unit can see exactly when an adjustment was made and trace it back to the
cycle count that caused it.
Cycle counts respect locations and bins: a count scoped to a bin only touches units in that bin; a count scoped to a location touches all units in that location regardless of bin; and a count with no location scopes every unit in the account.
Doing it from the API #
API note:
location_idis required when creating a cycle count via the API. The UI allows leaving it blank to count all locations, but the API does not support that mode.
# Create a cycle count (lines are generated automatically)
curl -X POST "https://your-domain.com/api/v1/inventory/cycle-counts" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"location_id": "<location-id>", "bin_id": "<bin-id>", "notes": "Q2 shelf audit"}'
# Submit counted quantities for specific lines
curl -X PUT "https://your-domain.com/api/v1/inventory/cycle-counts/{cycleCount}" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"counts": [
{"line_id": "<line-id>", "counted_quantity": 10000},
{"line_id": "<line-id>", "counted_quantity": 7500}
]
}'
# Post all adjustments — irreversible
curl -X POST "https://your-domain.com/api/v1/inventory/cycle-counts/{cycleCount}/post" \
-H "Authorization: Bearer $TOKEN"
Quantities are integers on a
0–10000scale over the API (10000= 100%,5000= 50%), matching the samequantity_remainingscale used on inventory units. Filter the list endpoint with?status=draftor?location_id=<id>to narrow results.