---
title: Transfers and Stockcount
description: Move stock between branches with FEFO deduction and reconcile shelf counts with system quantities.
---

You keep branches balanced with transfers in `apps/server/src/features/transfers/route.ts` and you reconcile the shelf with the system through stockcounts in `apps/server/src/features/stockcount/route.ts`.

### Transfer stock between branches

Post to `POST /transfers` with `from_branch_id`, `to_branch_id`, `medicine_id`, `qty`, and optional `notes`. You need `admin`, `branch_manager`, or `inventory_manager`. The two branches must differ, both must be active, and the medicine must be active.

```bash
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"from_branch_id":"'"$FROM"'","to_branch_id":"'"$TO"'","medicine_id":"'"$MEDICINE_ID"'","qty":24,"notes":"Cover weekend demand"}' \
  "http://localhost:8000/api/v1/transfers"
```

The server deducts the source with FEFO through `selectTransferFefoBatches` in `apps/server/src/features/transfers/queries.ts`, decrements each source batch, then creates a destination batch whose number follows `TRF-{from_branch_id first 4}-{UTC timestamp}-{batch uuid slice}` such as `TRF-BR001-202605040915-A1B2`, carrying the earliest slice expiry and unit cost per the logic in `apps/server/src/features/transfers/service.ts`. The ledger sees one `OUT` movement at the source and one `IN` movement at the destination, both with `reference_type: transfer` sharing one transfer id. The transfer record lands as `COMPLETED` immediately. List history with `GET /transfers` filtered by `branch_id`, `medicine_id`, `from_date`, and `to_date`, capped at 100 rows.

### Print the count sheet

Call `GET /stockcount` to get your branch sheet: every active medicine with `branch_quantity`, `system_quantity`, and `batch_count`, computed from active batches with remaining quantity and a valid expiry. Fill in the physical count per row on your side before submitting.

```bash
curl -H "Authorization: Bearer $TOKEN" "http://localhost:8000/api/v1/stockcount"
```

Your branch comes from your own auth context, so you cannot count another branch by parameter. Roles allowed are `admin`, `branch_manager`, `inventory_manager`, `pharmacist`, and `auditor` for reading.

### Submit counts and apply adjustments

Post counted rows to `POST /stockcount/submit` with an `items` array of `medicine_id`, `counted_quantity`, and optional `notes`. Each non-zero delta repairs the batch quantities and writes one `ADJUST` movement with `reference_type: stock_count`, so the ledger sum for that medicine drops or rises accordingly.

```bash
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"items":[{"medicine_id":"'"$MEDICINE_ID"'","counted_quantity":118,"notes":"Shelf plus overstock"}]}' \
  "http://localhost:8000/api/v1/stockcount/submit"
```

Batch repair follows a fixed rule: a surplus is added to the newest active batch (`created_at DESC`), while a deficit is taken oldest-first by `expiry_date ASC` across active batches. Zero-variance rows are skipped, and the response reports `adjustments_made` with per-item `db_quantity`, `counted_quantity`, and `delta`.

### Avoid failed transfers and counts

You get `400 Source and destination branches must differ` when both ids match, `404 Source branch not found` when the source branch is missing or inactive, `404 Destination branch not found` when the destination is, and `400` from FEFO when the source holds no sellable batches. Submit an empty `items` array and you get `400 No items submitted`. Count at opening or closing time so sales do not move quantities under you.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8000/api/v1/transfers?branch_id=$BRANCH_ID&medicine_id=$MEDICINE_ID"
```

Re-pull `GET /stockcount` after submitting to confirm every variance reads zero before you close the session. When a deficit exceeds what the oldest-first walk can cover, recount that shelf before you post again so you do not adjust against a miscount.

```bash
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"items":[{"medicine_id":"'"$MEDICINE_ID"'","counted_quantity":0,"notes":"Empty shelf confirmed"}]}' \
  "http://localhost:8000/api/v1/stockcount/submit"
```

Every submit writes to the audit log with your branch and adjustment count, so a supervisor can trace who changed what.

### Next steps

Review `/inventory/medicines-and-batches` to trace an adjustment in a medicine movement history, and open `/inventory/alerts-and-expiry` to confirm your corrected quantities cleared any low-stock alerts.
