Free trial
Colour

Stock by location

Keep parts in several locations such as a store room and a van, move them between locations and record what is used.

For
OwnerService advisorTechnician
Hosting
Any hosting
Devices
All devices
Business
Repair shopFleet

Checked against Pop Dispatch 0.1.0

You will be able to hold a part in more than one place, move it between places, receive new stock, and record each use. A part's on-hand figure is the sum of what sits in each location, and no location goes below zero.

Before you start #

  • You need a role that handles parts: owner, manager, advisor or technician.
  • The write calls sit under /fleet, so they need dispatch_fleet in the licence. Reading stays open. See fleet-without-the-licence.
  • Parts come from the parts catalogue; see shop-stock-and-parts.

Steps #

  1. Add a location with POST /fleet/stock-locations, giving a code of up to 20 characters and a name. A code that already exists answers conflict. Every account has a location with the code main.
  2. Receive stock with POST /fleet/parts/{id}/receive, giving qty (a whole number from 1 to 100000) and, when you want one, location_id. Without it the stock goes into main.
  3. Move stock with POST /fleet/parts/{id}/transfer, giving qty, from_location_id and to_location_id. The two locations must differ. The move happens in one step, so the total stays the same.
  4. Record a use with POST /fleet/parts/{id}/consume, giving qty and optionally location_id, asset_id and job_id. The location's stock drops by qty.
  5. See where a part sits with GET /fleet/parts/{id}/stock. The answer lists on_hand and the quantity at each location.

Resale or internal use #

Each use announces part.consumed with the SKU, the quantity, the location_id, the asset_ref and a purpose.

  • resale means the part was sold on a job.
  • internal means the business used it up, which counts as repair and maintenance expense instead of cost of sales.

Set purpose yourself, or leave it out. When you leave it out, a part used on a vehicle your business operates defaults to internal, and every other use defaults to resale. Any other value answers validation_failed.

Older stock #

Stock recorded before locations existed moves into main the first time you touch the part, so the sum never changes. The older stock adjustment at POST /shop/parts/{id}/adjust lands in main too. Adjust and receive work on main unless you choose another location.

Technical details
  • Quantities sit in part_stock, one row for each part and location. Database triggers keep shop_parts.on_hand equal to the sum of those rows.
  • A change that would take a location below zero writes nothing and answers conflict with the quantity on hand.
  • Every write adds an audit entry.
  • part.consumed data: sku, qty, job_id, at, location_id, asset_ref, purpose. Ids are strings. Delivery to other systems arrives in Phase 9; see fleet-api-and-events.

If something goes wrong #

  • conflict (409): "Only N on hand" at that location. Receive more or transfer stock in first.
  • not_found (404): the part, location, asset or job does not exist.
  • validation_failed (422): qty is outside 1 to 100000, the two transfer locations match, or purpose is neither resale nor internal.
  • feature_not_licensed (403) or licence_read_only (403): see fleet-without-the-licence.