The big picture
A lot is a label on some of your stock — never a second stock figure.
Your item has one on-hand quantity. Batch tracking does not add a second one. It lets you say which part of that quantity came in on which delivery, under which batch number, and when it goes off. Everything else follows from that one sentence.
So at any moment an item's stock is in two parts:
Because lots are a description and not a parallel ledger, you can switch batch tracking on for an item you already stock. Nothing has to be migrated and no stock-take is needed. Yesterday's stock simply shows as “not in any lot” until you label it (§05) or sell it.
Where the screens live
Batch & Expiry
Turn tracking on, set the shelf life and the alert window.
Item → InventoryLots on a receipt
Split a received line across the batches it arrived in.
PO → ReceiveAssign lot
Name stock you already hold. Quantity does not move.
Item detail → StockChoose lots
Send a specific batch back to the vendor.
PO → Return · Debit noteSwitching it on
Two switches and two numbers, per item — never account-wide.
Open the item, go to the Inventory step, and find the Batch & Expiry card.
| Control | What it does |
|---|---|
| Batch / Lot Tracking | Every unit that enters stock must name a batch. Receipts and inward adjustments will refuse to save without one. |
| Item Expires | Every batch must also carry an expiry date. Turning this on locks batch tracking on — a use-by date without a batch to hang it on means nothing, so the two can never disagree. |
| Shelf life (days) | Pre-fills the expiry on every goods receipt as receipt date + shelf life. Set it to 180 and a delivery taken today is offered an expiry six months out. You can always overwrite it. |
| Alert before (days) | How early this item should be called out as expiring. Leave blank to use the account default. |
A chemicals trader has dated and undated SKUs on the same shelf. Turning expiry on for the whole account would force a date onto the drum of bolts. Switch it on for the items that genuinely go off — the rest of your catalogue behaves exactly as it does today, with no lot fields anywhere.
These are catalogue settings, not stock settings. Changing them needs the permission to edit items. Somebody who can only receive goods can put stock into a batch, but cannot decide that an item stops expiring on their way past — that separation is enforced by the server, not just hidden in the app.
Receiving into lots
The Lots block on a goods receipt — quiet for one batch, ready for six.
Raise and approve the purchase order as usual, then open Receive. A line whose item is batch-tracked grows a LOTS block underneath its Accept / Reject boxes.
The one-batch case — the common one
The block starts with a single row and behaves like a single field:
- Type the lot / batch number from the supplier's label. That is the only thing you must do.
- Leave Qty empty — an empty box on the only row means all of it, and the grey hint shows you the number.
- Expiry is already filled in from the shelf life. Change it if the certificate says otherwise.
- Mfg is optional and nothing depends on it.
When one delivery is several batches
Press Add lot for each extra batch and type a quantity into every row. The header keeps a running count:
| Header reads | Meaning |
|---|---|
60 of 100 kg allocated | Still short. You are mid-typing — this is not an error yet. |
100 of 100 kg allocated ✓ | Balanced. Green with a tick. |
120 of 100 kg allocated | Over. Confirm will refuse and name the line. |
The ✕ on a row removes it — except on the last remaining row, where it clears the fields instead. A batch-tracked line always needs somewhere to type, and an empty block would read as “no batch required”, which is the opposite of the truth.
Typing a batch number you already hold
If the number matches a batch already in stock, the row tells you so and pre-fills the stored expiry rather than the shelf-life guess. If you then change that date, the message turns amber:
A batch number is the identity of a specific production run. The same number arriving with a different use-by date is almost always a typo, so Deetzo keeps the date it already has and adds your quantity to that batch. If this really is a different run, give it a different number — otherwise you would be quietly moving the expiry of stock already on your shelf, with nothing recording who changed it.
What Confirm refuses
| You will see | Fix |
|---|---|
| “…is batch-tracked — enter the lot 100 was received in.” | The Lots block is empty. Type the batch number. |
| “…lots total 60 but 100 was accepted — every unit must sit in a lot.” | Add the missing quantity, or a second row. |
| “…every batch needs a lot number.” | A row has a quantity but no number. |
| “…lot “B-1” is entered twice — merge the rows.” | Two rows share a number. Add them together on one row; keeping both would silently throw away the second expiry. |
| “…this item tracks expiry — enter the expiry date.” | A dated item has a row without a date. |
| “…expires 08/09/2026, on or before the receipt date — reject it instead.” | The goods are already out of date. They should not enter stock at all — put the quantity in Reject (QC), which raises an NCR against the supplier. |
Every message names the line and the batch, so a six-line receipt tells you exactly where to look.
If an incoming quality check applies to the item, Deetzo now raises one inspection per batch received, each stamped with its lot number — three batches on one delivery are three inspections. One inspection covering all three could only ever record a result about one of them, which is no use when somebody asks which batch you actually checked.
Expiry rules
Dates are compared by day, and stock leaves first-expiry-first-out.
Whole days, not clock time
An expiry is compared by date, never by hour. A batch dated tomorrow is fine on a receipt booked at any time today; a batch dated today is not, because it is out of date the moment it lands. That is why the picker refuses to offer a date on or before the receipt.
First-expiry-first-out
Once an item carries expiry dates, stock leaving your shelf is taken from the batch that goes off soonest, not the one that arrived first. A batch with no recorded date sorts last — an unknown date is not a claim that it is urgent — and stock that is not in any batch is used last of all, after every dated batch is exhausted.
| Item setting | How stock is picked when it leaves |
|---|---|
| Neither switch on | No batches. Nothing changes from today. |
| Batch tracking only | FIFO — the batch received earliest leaves first. |
| Item expires | FEFO — the batch expiring soonest leaves first. |
An out-of-date batch is skipped by the automatic allocation, always. It will never be handed to a movement quietly because it happened to be next in line — which is the whole point of recording the date.
Moving one deliberately is a different matter, and it stays deliberate: today the routes are a write-off and a return to the vendor (§07), both recorded as what they are. When batch picking reaches the sales side (§09), shipping an expired batch will take an explicit confirmation naming the batch and its date rather than being refused outright — a mistyped expiry should not be able to hard-block a real dispatch, and the expiring-stock report is the control that catches it earlier.
QC-HOLD
Held goods keep their batches on the receipt until they are let out.
If a blocking incoming quality check governs the item, the accepted quantity does not enter stock at receipt. It waits in the QC-HOLD balance, which sits outside your on-hand figure.
Because a batch is a description of stock you have, held goods cannot be in a batch yet — they are not in stock. So the batches you typed are stored on the goods receipt and attached to the stock the moment it is let out:
| How it is released | Which batch it lands in |
|---|---|
| The inspection is submitted — the normal way (pass or fail: the accepted qty is released, the rejected qty goes to an NCR) | The inspection names its batch (one is raised per batch, §02), so that batch is used, capped at what actually arrived under it. Clear the batches in any order you like and each one still lands in its own. |
| Manual release from the purchase order — the escape hatch when no inspection can ever clear the hold | It knows only a quantity, so it works through the batches on the receipt oldest first, picking up where the last release left off. Two half-releases therefore attach two different batches, not the same one twice. |
Quantity rejected out of a hold never entered your stock, so no batch is credited with it. Only what actually reaches good stock is labelled — which is why a partial pass of 7 out of 10 puts exactly 7 into the batch.
A hold whose receipt recorded no batches still releases normally — the quantity simply arrives as “not in any lot”, and the movement says so rather than inventing a batch number. You can label it afterwards with Assign lot.
Assign lot
How a business that already holds stock starts tracking it. No stock-take.
Switch batch tracking on for an item you already stock and the item's Stock panel shows a prompt:
Open it, type the batch number you know that stock to be, set the quantity and the expiry, and save.
What it does — and what it deliberately does not
- Your on-hand figure does not change. Not by a gram. This is a label, not an adjustment — if you need to change a quantity, that is Adjust stock (§06).
- The batch appears on the item, and the “not in any lot” figure drops by the same amount.
- A movement is recorded with a zero quantity change and the reason
lot_attribute, naming you, the batch and the expiry. Somebody reading the ledger later can see the claim was made and by whom. - You cannot label more than is unlabelled. Try, and you are told exactly how much is available. Going beyond it would not be a label — it would be an invention, and your batches would add up to more stock than you own.
You do not have to label everything, and you should not guess. Label the pallets you can actually identify from their paperwork and leave the rest unlabelled — it is honest, and it drains on its own as that older stock sells through. The prompt disappears by itself once nothing is left unlabelled.
If you type a batch number the item already holds, the quantity is added to that batch and its stored expiry is kept — the same rule as a goods receipt (§02).
Opening stock & adjustments
Stock that arrives without a purchase order still gets a batch.
A brand-new item
Creating an item with an opening quantity? The Inventory step offers an opening lot, expiry and mfg date beside it. Leave the lot blank and the opening stock is simply not in any batch yet — you can name it later with Assign lot.
On an existing item the stock figure on the form is a read-out, not an input: quantity moves through Adjust stock, and batches through Adjust stock or Assign lot.
Adjust stock
| Direction | Batch fields | Why |
|---|---|---|
| Adding stock | Lot, expiry and mfg appear, and the lot is required. | Stock coming in has to say which batch it is, exactly as a receipt does. |
| Removing stock | No batch fields at all. | An adjustment is a correction, not a picking list. Rather than have you guess which batch the loss came from, Deetzo takes it the same way any other outward movement does — first-expiry-first-out (§03). |
An inward adjustment on a dated item is also refused if the expiry has already passed — write it off rather than adding expired goods to stock.
Returns to a vendor
The one outward movement where you know better than the system.
Sending goods back is the case where automatic picking is wrong: the crate on the loading bay is a specific batch — usually the bad one — not whichever batch happens to expire soonest. So both return routes offer a picker:
- Purchase order → Return to vendor
- Vendor bill → Debit note (with “deduct from stock” on)
Enter the quantity, then press Choose lots. The sheet lists every batch you hold with its quantity, expiry and receipt date — expired in red, expiring soon in amber — and a running “4 of 10 kg picked”.
| Button | Effect |
|---|---|
| Fill | Fills the boxes with the allocation Deetzo would have made anyway. A starting point, then edit it. |
| Let the ledger choose | Clears your picks and allocates automatically — exactly what happened before this sheet existed. |
| Use these lots | Sends back precisely what you picked. |
This is the one outward route that is allowed to move an out-of-date batch, because sending it back to the supplier is exactly what the expiry block is pointing you towards. Anything your picks do not cover comes from unlabelled stock, and the movement records that honestly.
Reading the trail
One movement row per batch — which is what makes a recall answerable.
Open the item and view its stock history. A batch-tracked receipt writes one row per batch, each carrying its own quantity, batch number and expiry. A single merged row would make half a delivery invisible the day somebody asks what you did with batch B-2.
| Reason | What happened |
|---|---|
grn | Received into stock, in the named batch. |
grn_qc_hold | Received but held for inspection — not in stock, not yet in a batch (§04). |
grn_qc_release | The inspection was submitted; its accepted quantity left the hold and entered stock in its batch. |
qc_release_manual | Somebody released a hold by hand, and signed for it. |
lot_attribute | Existing stock was labelled with a batch. Quantity change is zero (§05). |
purchase_return | Sent back to the vendor, from the batches picked (§07). |
When a movement takes stock that was not in any batch, it records that quantity as untraced instead of attaching the nearest batch number. It means the trail will never claim more traceability than it actually has — which is the only kind of trail worth having when a regulator is reading it.
What is not here yet
Said plainly, so you can plan around it.
This release covers everything on the way in — receipts, holds, adjustments, labelling and returns. Still to come:
- Batch on the sales side — picking batches on an invoice, and printing batch and expiry columns on the invoice and delivery note.
- A Lots table on the item page and a Lot column on the movement screens. Until then, the movement history (§08) is where you read a batch's story.
- An expiring-stock report and daily expiry alerts.
- Full recall tracing — supplier → receipt → work order → invoice → customer, on one screen.
Batch-per-store. Batches and stores stay independent descriptions of your stock; there is no batch × warehouse grid, and moving stock between stores does not touch its batches.
Automatic backfill. Nothing will guess batch numbers for stock you received before switching tracking on — Assign lot (§05) is the path, by hand, for the quantities you can actually vouch for.
Quick reference
The page to keep open while your team learns it.
| Concept | Where / what |
|---|---|
| Turn it on | Item → Inventory step → Batch & Expiry card |
| Settings | Batch / Lot Tracking · Item Expires · Shelf life (days) · Alert before (days) |
| Receive into batches | Purchase order → Receive → the LOTS block on the line |
| Label existing stock | Item detail → Stock → Assign lot |
| Add stock outside a PO | Adjust stock (inward asks for a batch; outward does not) |
| Send a batch back | PO → Return to vendor · Vendor bill → Debit note → Choose lots |
| Picking order out | Expiry set → FEFO; batches only → FIFO; unlabelled stock always last |
| Expired stock | Cannot be issued or sold. Write it off, or return it to the vendor. |
| Movement reasons | grn · grn_qc_hold · grn_qc_release · qc_release_manual · lot_attribute · purchase_return |
| Same batch number twice | Quantity is added to the existing batch; the stored expiry is kept |
| Permissions | Edit-item to turn tracking on; the stock permissions (purchases, quality…) to put stock into a batch |
A lot is a label on part of your stock. It never adds up to a second stock figure, it never covers more than you own, and whatever is not labelled is reported as unlabelled rather than guessed at. Every rule in this guide — no migration, the refused over-allocation, the kept expiry, the “untraced” quantity — is that one idea being honest in a different place.