Inventory → Transactions
Purpose
Record every event that changes a container's balance — the entries that make up your DEA audit trail. This includes administrations to patients, dispenses to clients, waste, disposal, paper-trail adjustments, and intra-clinic transfers.
Transactions in CS Logbook are immutable. Once recorded, the original entry cannot be changed. Corrections route through a separate correction flow that strikes the original and posts a reversal + corrected entry pointing at it — the digital equivalent of a "single-line correction with a reason and date" in paper logs.
Regulatory basis: DEA rules require accurate, contemporaneous, immutable records; records of dispensing; and disposal records with a witness.
When to use it
- Administer to a patient — every dose given to an animal under your care
- Dispense to a client — controlled substances sent home with the owner
- Waste — drug intentionally wasted (expired, contaminated, partial dose remaining)
- Disposal — full container disposed via DEA Form 41 reverse-distribution or on-site destruction
- Adjustment — paper-trail correction reconciling a count discrepancy
- Transfer — moving substance between containers within your clinic (rare)
received transactions are auto-created when you complete the Receive container flow — do not file them manually.
Transaction types reference
| Type | Direction | Required fields beyond defaults | Witness required? |
|---|---|---|---|
received |
+ balance | (auto-created by Receive container form) | no |
administered |
− balance | patient, prescriber | no |
dispensed |
− balance | patient, prescriber | no |
waste |
− balance | reason, witness | yes |
disposal |
− balance (full container) | DEA Form 41 ref, witness | yes |
adjustment |
± balance | reason, justification | no (but soft-warning on large adjustments) |
transfer |
balanced (one −, one +) | source container, destination container | no |
Walkthrough — administering to a patient
Step 1 — Open the transactions list
Navigate to /home/<your-clinic>/inventory/transactions.
The list shows every transaction with date, type, container, quantity, performer, and patient (if applicable). Filter by type, date range, container, or patient using the filter bar.

The page shows six transaction-type buttons (Administer, Dispense, Adjust, Waste, Dispose, Transfer). Each opens its own full-page route. Clicking Waste opens the Record Waste page (/inventory/transactions/waste/new):

Pick a container, enter the quantity wasted, the waste method, the witness (must be a different staff member than the performer), and the reason (minimum 20 characters):

After saving, the transaction appears in the transactions list:

Step 2 — Click the transaction type
There's no single "Add transaction" button — each of the six type buttons opens its own full-page route: Administer → /inventory/transactions/administration/new, Dispense → /dispense/new, Adjust → /adjustment/new, Waste → /waste/new, Dispose → /disposal/new, Transfer → /transfer/new. Each page carries a ‹ Back to transactions link. (For many entries at once, Bulk adjustment and Bulk waste live at /transactions/bulk-adjustment and /transactions/bulk-waste.)
Step 3 — Pick the container
Select from active containers (status unopened or opened). Disposed, depleted, expired, transferred, or destroyed containers are not selectable — that's the hard block from the DEA record-retention rule preserving audit integrity.
The form shows the container's current balance so you can see what you're drawing from.
Step 4 — Choose transaction type and fill required fields
For administered:
- Quantity — amount drawn (e.g.,
0.3); cannot exceed current balance - Date / time — when the dose was given (default: now)
- Patient — pick from your patient list, or quick-add a new patient inline
- Prescriber — the prescribing veterinarian; defaults to the signed-in user if they're a prescribing vet
- Notes — clinical context (e.g., "Pre-anesthetic for spay surgery")
Click Save. The container's balance decreases. The transaction is now permanent.
Step 5 — Quick-add a patient (if needed)
If the patient isn't yet in your system, click the + Add patient button next to the patient combobox. A mini-form opens that captures the minimum needed fields (client + name + species). The patient is created and auto-selected. See people/patients.md for the full patient form.
Walkthrough — recording waste with a witness
Step 1 — Open the transaction form
Same as above.
Step 2 — Select container, type = waste
Step 3 — Fill waste-specific fields
- Quantity — what was wasted (e.g.,
0.2mLof leftover at end of shift) - Reason — why it was wasted (
leftover at end of shift,contaminated,expired,dropped, etc.) - Witness — pick another clinic member who witnessed the waste. A witness is required by DEA rules.
The witness must be a different user than the one filing the transaction. The form blocks save if the witness equals the performer.
Click Save. The transaction is recorded with both performer and witness on the audit trail.
Step 4 — Witness sees a notification
The witnessing clinic member receives an in-app notification of the witnessed transaction (informational; they don't need to take action — their identity is already recorded).
Walkthrough — correcting a transaction
Step 1 — Open the transaction detail
From the list, click into the transaction you need to correct.
Step 2 — Click "Correct transaction"
You're taken to the Correct Transaction page (/inventory/transactions/<id>/correct). Only a still-correctable transaction is eligible — an original that's already been corrected, or a correction entry itself, can't be corrected again (a deep-link to a non-correctable transaction sends you back to the detail page). The form asks for:
- Corrected quantity — the right amount (positive; the app re-signs reduction types negative automatically). Pre-filled with the original quantity.
- Corrected transaction date — the right date the event occurred. Pre-filled with the original.
- Correction date — when you're making the correction (defaults to today).
- Correction reason — why you're correcting (required; minimum 10 characters; goes on the audit trail).
Step 3 — Submit
The original transaction is not modified. Instead it is preserved and struck (DEA red-line strikethrough model): a reversal entry backs out the original and a corrected entry restates the balance, both referencing the original. On success you're returned to the transaction detail page.
This is the only way to change a recorded transaction. Direct edits to the underlying transaction row are hard-blocked at the database level — any attempt to UPDATE or DELETE a transaction record fails with an RLS rejection.
Field reference
Transaction form (generalized)
| Field | Label | Type | Required | Validation |
|---|---|---|---|---|
container_id |
Container | combobox | ✓ | uuid; container must be unopened or opened |
transaction_type |
Type | select | ✓ | enum: administered, dispensed, waste, disposal, adjustment, transfer (received is auto-only) |
quantity |
Quantity | number | ✓ | > 0; cannot exceed current_balance for negative-direction types |
unit |
Unit | display | auto | inherited from container |
transaction_date |
Date / time | datetime | ✓ | not in future (soft warning if backdated > 7 days) |
patient_id |
Patient | combobox | conditional | uuid; required for administered / dispensed |
prescriber_user_id |
Prescriber | combobox | conditional | uuid; required for administered / dispensed; must be a prescribing vet |
witnessed_by |
Witness | combobox | conditional | uuid; required for waste / disposal; must differ from performer |
reason |
Reason | textarea | conditional | required for waste / adjustment / disposal; max 500 |
notes |
Notes | textarea | optional | max 1000 |
Hidden / system fields: id, account_id, performed_by (signed-in user), lock_version (container optimistic concurrency), created_at.
Edge cases
Concurrent transactions on the same container
CS Logbook uses optimistic concurrency via lock_version. If two clinic members log transactions on the same container at the same moment, the second save will fail with "Concurrent transaction detected — please refresh and try again". The first transaction succeeds; the second user retries.
Waste with witness — performer ≠ witness
The form prevents you from selecting yourself as the witness. If you're the only person on shift, file the waste later when a witness is available, or use the adjustment type with notes documenting the situation (which doesn't require a witness but is honest about the gap).
Backdated transaction soft warning
If you set transaction_date more than 7 days in the past, the form shows a soft warning: "Transactions are typically logged contemporaneously. Backdated entries are allowed but should be documented." You can still save; document the reason in Notes.
Quantity exceeds current balance
The form rejects save if you try to draw more than the container holds. To handle a multi-container administration (e.g., 1.5mL when the active container has only 0.3mL left), use the transaction split flow — the form detects insufficient balance and prompts you to draw from another container with sufficient balance.
Hard block: edit / delete on existing transactions
Direct UPDATE or DELETE on a transaction record is rejected at the RLS layer. The only way to change a transaction is via the corrections RPC. This is a deliberate audit-integrity guard per DEA record-retention rules.
Subscription gating
received and administered / dispensed / waste / disposal transactions require an active subscription at INSERT time (per RLS WITH CHECK). If your billing lapses, you can still view existing transactions but cannot record new ones. See Settings → Billing for renewal.
Common mistakes
- Filing a manual
receivedtransaction after using the Receive container form. The form auto-creates the receipt; manual entry double-counts. - Using
adjustmentfor everything.adjustmentis for paper-trail corrections, not for waste or administration. Use the right type so reports group correctly. - Forgetting the witness on waste. The form will block save without one. If a witness was present but you forgot to record their identity, file the transaction with the actual witness's user as the witnessed_by, even if it's a few minutes after the event.
- Editing transactions outside the corrections RPC. Direct DB access is blocked, but if you find yourself running raw SQL to "fix" a transaction, stop. Use the corrections flow — that's the audit trail DEA inspectors will look for.
- Selecting the wrong patient. Patient mis-selection during a busy shift is the most common audit error. The patient combobox supports search by name and microchip — type quickly to filter, then double-check before saving.
Related
- Containers — what transactions affect
- People → Patients — the animals on
administered/dispensedtransactions - Glossary § Transaction
- Glossary § Transaction type
- Audits → Spot checks — verify balances against transactions
- Audits → Theft / loss — DEA Form 106