# Batches and expiry dates

> Track a product by batch with its expiry date: label the stock you have, receive new batches, pick them at the till, and see what expires soon.

*Section: Products and stock · Updated: 2026-10-19*

By the end you will have a product tracked by batch, with each batch's expiry date, and you will know how batches are picked at the till and where to see what expires soon.

Batches suit goods that go off or are recalled by lot: milk, medicine, cosmetics. Each batch has its own number, quantity and expiry date, in each warehouse.

## Track a product by batch

1. **Open the product** in **Products › All Products** and click **Edit**, or create a new one.
2. **Find Pharmacy Settings** (near the bottom; **ON THIS PAGE** jumps to it) and **switch on Track batches & expiry.**
3. **Click Save Changes.**

![Pharmacy Settings: Track batches & expiry with "Enable to capture batch numbers and expiry dates for this product on purchase and sale.", then Shelf Life (days), Prescription Required, Generic Name, Strength, Dosage Form, Pack Size, Manufacturer and Drug Schedule.](https://armpos.online/storage/help/43205b5fca-batches-and-expiry-dates-1-switch.webp)
*Once it is on, Shelf Life (days) appears below. The other fields are for pharmacies.*

## Stock you already have

Stock the product had before you switched tracking on has no batch, and the till can't sell it until it has one. Give it its batches once:

1. **Open the product with Edit again.** A new part, **Opening Batch & Expiry**, lists each warehouse's **Stock**, what is **In Batches** and the **Unbatched Stock**.
2. **Click Assign Batches** on the warehouse's row.
3. **Fill one line per batch:** **Batch No**, **Expiry Date**, **Manufacturing Date** if you have it, **Quantity** and **Unit Cost**. **+ Create** adds a line.
4. **Check Remaining to assign** reads 0, and **click Submit.**

![Opening Batch & Expiry for Milk: Default Warehouse with Stock 291, In Batches 0 and Unbatched Stock 291, and two batch lines: MLK-1015 with 150 at 2.27 and MLK-1019 with 141 at 2.27, Remaining to assign 0, Submit and Cancel.](https://armpos.online/storage/help/966f65b0f6-batches-and-expiry-dates-2-assign.webp)
*This only labels stock you have: the warehouse's quantity doesn't change.*

## New stock arrives in batches

On a purchase, a batch-tracked product's line opens a **Batches** table: **Batch No**, **Expiry Date**, **Manufacturing Date**, quantity and cost. The first line starts with the whole quantity; **+ Create** adds another. The batch quantities must add up to the line's quantity, and every line needs a **Batch No**: a line left without one is dropped when the purchase is saved, and that stock can't be sold at the till.

Batches are made when the purchase is **received**. A batch number the product already has in that warehouse is topped up.

## The Batches page

**[Products › Batches](/app/products/Batches)** lists every batch with its product, **Batch No**, **Warehouse**, **Expiry Date** (red once expired, amber when it expires soon, green otherwise), **Quantity**, cost and **Status**. Filter by **Warehouse**, **Status** or **Expiry Window** (**expired**, **Near Expiry**, **Valid**).

![Batches: Warehouse, Status and Expiry Window filters, Expiry warning window (days): 90, and Milk's batches MLK-1015 (2026-10-28, expires in 9d, 150) and MLK-1019 (2026-11-04, expires in 16d, 141), both Active.](https://armpos.online/storage/help/95b93e0c33-batches-and-expiry-dates-3-batches.webp)
*Expires in Nd is amber within the warning window.*

From a batch's row:

- **Edit** changes its number, dates, notes, quantity or **Status**. Changing the quantity changes the warehouse's stock by the difference. Setting **Quarantined** keeps it out of every sale until you set it back to **Active**.
- **Write Off** removes what is left of the batch from stock, with a reason: for spoiled or recalled goods.

## Selling from a batch

At the POS, a batch-tracked line in the cart shows **Batches**. **Pick the batch** in **Choose batch**: the list shows each batch's expiry date and quantity, the one expiring first at the top. Set how many come from it; to take from two batches, click **+ Create** and add a second line.

![The POS cart with 2 Milk, its Batches panel and Choose batch open on MLK-1015 · Expiry Date 2026-10-28 · 150 and MLK-1019 · Expiry Date 2026-11-04 · 141.](https://armpos.online/storage/help/5e5e6c681d-batches-and-expiry-dates-4-pos.webp)
*The batch expiring first is at the top of the list.*

**Pay Now** waits until every batch line is chosen and the quantities add up to the line's.

![The same line with MLK-1015 chosen for 1 of the 2 Milk, and the message "Total batch quantity does not match the line quantity".](https://armpos.online/storage/help/16a594203e-batches-and-expiry-dates-5-pos-check.webp)
*Here 2 are in the cart but only 1 is taken from the batch: set it to 2, or add a line for the other.*

**Add sale** has the same picker; a batch must be chosen when the sale is **Completed**.

> **Warning:** ArmPOS doesn't stop you selling a batch past its expiry date, and doesn't mark it expired by itself. Check the **Expiry Report** often, and **Write Off** or quarantine expired batches yourself.

## What expires soon

**[Reports › Expiry Report](/app/reports/expiry_report)** counts the batches **expired**, **Near Expiry** (within the warning window) and **Valid**, with their value, and lists them. **Reports › Batch Register** lists every batch with its purchase and supplier; click one for its full history. You also get a notification when a batch enters the warning window.

![Expiry Report: expired 0, Near Expiry 2 (value 660.57), Valid 0, Expiry warning window (days) 90, and Milk's two batches with their expiry dates, quantities and values.](https://armpos.online/storage/help/35f71d1e4f-batches-and-expiry-dates-6-expiry-report.webp)
*Near Expiry means within the warning window, 90 days unless you change it.*

The warning window is set in **Settings › System Settings**, on the **Pharmacy Settings** tab: **Expiry warning window (days)**.

## What's next

[Count and adjust stock](/app/help/count-and-adjust-stock): adjustments take from a batch you pick, or from the one expiring first.
