Stock
Stock that can tell you which lot actually shipped
A stock figure is only worth as much as the discipline behind it. Akkad treats every movement as an event with an author, a before and an after, and — when you track batches — a specific lot it came out of. That is what makes the difference between knowing you have four hundred boxes and knowing which four hundred, bought at what cost, expiring when.
Stock in Akkad is a single figure per item or variant, scoped to one organisation. There is no location model, no branch model, and no transfer feature — and being clear about that matters more than being vague and impressive. What Akkad does instead is go unusually deep on the one number: where it moved, why, who moved it, what it cost, and which lot it came from.
The design rule underneath all of it is that a number should be derived wherever it can be. A parent item's stock is the sum of its variants. A variant's stock, once batch tracking is on, is the sum of its batches. Nothing is written in two places, so nothing can disagree with itself.
01
Every path that changes stock
There are exactly six, and all six write the same kind of history entry — user, timestamp, stock before, stock after.
| Path | What happens | Reversible |
|---|---|---|
| Manual adjustment | A person sets a new figure. The before and after are both recorded, which is what makes a count reconcilable later. | By a further adjustment |
| Sales orders | Deducted when the order is created, rebalanced by the difference when the order is edited, restored when it is cancelled or reverted. | Yes, automatically |
| Storefront orders | Public orders take stock down the same way in-app orders do, through the same code path — the channel does not get its own arithmetic. | Yes, automatically |
| Purchase order receipt | Receiving posts stock in, creating or merging batches for tracked items and incrementing item or variant stock otherwise. | Yes, in full or in part |
| Batch create, adjust or delete | Direct work on a lot — recording a delivery, writing off damage, correcting a miscount. | By a further adjustment |
| Bulk import | A spreadsheet import writes stock and writes history rows for every movement it causes. | By a further import or adjustment |
Every one of these takes a row-level lock on the item, the variant and the affected batches while it works. Two cashiers selling the last unit at the same second is not an edge case in a busy shop; it is Tuesday. Locking is what makes the second one lose cleanly rather than both of them winning.
02
The rules behind every write
Four decisions govern what any of the six paths is allowed to do.
Stock tracking is per item, not per system
Some things are not counted. A service, a made-to-order dish, a fee. Turn stock management off on that item and it is never decremented and always reads as available — no phantom negative numbers, no fake reorder alerts. The restaurant build ships with this off by default for dishes, for exactly this reason.
Negative stock is a decision you make once
An organisation-wide setting decides whether a sale may exceed stock. With it off, the sale is refused and the error names the item or variant, how many are available and how many were asked for — in the reader's own language, so the person at the counter can act on it. With it on, the figure is allowed to go negative rather than blocking a sale you know is real.
Derived numbers are never written directly
Parent stock comes from variants. Item stock comes from batches. There is no path in the system that sets a derived figure by hand, because a figure that can be set two ways will eventually be set two ways.
Every movement has an author
A stock change with no name attached is an argument waiting to happen. Each entry carries the person, the moment, and the value on both sides of the change.
03
First to expire, first out
Batch tracking is opt-in per item, because most catalogues have some items where lots matter and many where they do not. Turn it on and the batch becomes the source of truth: a lot carries its own quantity, its own cost per base unit, its own expiry date, its lot number and its notes, and the item's stock becomes the sum of them.
Deduction is first-expired-first-out, not plain first-in-first-out — and the distinction is not academic. Lots do not arrive in expiry order. A delivery received in March can expire before one received in January. Akkad sends dated batches first, soonest expiry first, and only then falls back to undated lots in the order they were created. The stock that leaves your shelf is the stock closest to being worthless.
Each deduction writes an allocation record tying that batch to that order line. This is the quiet part that makes everything downstream possible — reversal, costing and the refusal to delete a lot that has already been sold from all read the same records.
- Turning batch tracking on does not lose the stock you already have: the item is locked and a migration batch is created per variant carrying the existing figure across.
- Batches sort the same way everywhere they appear — non-empty first, dated before undated, soonest expiry, then oldest created. Item detail returns the first 50 with a flag when there are more.
- When negative stock is allowed, an oversell is pushed onto the latest-expiry lot rather than spawning a phantom batch. When it is not allowed, the sale is refused.
04
The interesting one
A cancelled order goes back to the lots it came from
Most systems restore a number. Akkad restores the batches. Because every deduction recorded which lot it consumed and how much, cancelling an order returns each quantity to the exact lot it left — the right expiry dates, the right costs, not a lump sum dropped onto whichever batch happens to be nearest. A cancellation leaves your stock in the state it was actually in, not in a state that merely sums to the same total.
Cost of goods reflects the lot that shipped
After expiry-first deduction runs, the order line's cost is set to the weighted average of the batch costs actually consumed, and the order's total cost is refreshed. If half the line came from a lot bought cheap and half from a lot bought dear, your margin says so.
Re-receiving a lot re-averages its cost
Receiving more of an existing lot weighted-averages the incoming cost into the batch before the quantity goes up, so later sales are never costed at a stale price. A lot that had run down to nothing adopts the new cost outright, because there is no old stock left for it to be an average of.
Merging is deliberately strict
A receipt merges into an existing batch only when the lot number and the expiry date both match exactly. Any difference creates a new batch. Two different lots quietly becoming one is the failure that makes a recall impossible to answer, so the system prefers an extra row over a wrong one.
Costs convert at the pack boundary
Batch costs are always held per base unit. When you receive a purchase order priced by the carton, or sell a line priced by the box, the conversion happens on the way in and on the way out, so a pack-sold item is not silently costed twelve times high.
05
Safety rails
Batch data becomes worthless the moment it can be edited out from under an order that already shipped. These are the specific things the system refuses to do.
A lot with allocations cannot be deleted
If any order or receipt drew from a batch, that batch stays. Deleting it would leave orders pointing at stock that never existed, which is worse than a cluttered list.
Purchase-order reversal checks before it acts
Reversing a receipt pre-checks each affected lot and refuses if units from that lot have already been sold. The check aggregates every allocation on the batch, so several small partial sales cannot add up to more than the reversal noticed.
Write-offs are allowed, and logged
Manually adjusting a lot below its allocated total is permitted, because shrinkage, breakage and theft are real and the system does not get to pretend otherwise. What it does is record it, with the before and after, under your name.
Locks are held across the whole movement
Items, variants and batches are locked for the duration of every mutation, so concurrent sales, edits and receipts serialise instead of interleaving into a wrong total.
06
Suppliers and purchase orders
Buying is where lot numbers and costs actually enter your data, so the purchase order carries the full inventory vocabulary rather than a simplified version of it.
- 1
Keep suppliers properly
Name, email, two phone numbers, city, two address lines, postal code and notes. The supplier list searches across all eight fields at once, so a half-remembered phone number finds the right company. Bulk deletion uses a partial-success policy: it commits only if there were successes and the failure rate stayed at or below one in ten, and otherwise rolls the whole thing back.
- 2
Raise a purchase order
Each PO takes the next number from a per-organisation counter, so numbering is sequential and gap-free. Supplier details are snapshotted onto the order — both phones, email, city, both address lines, postal code. Edit or delete the supplier a year later and the historical PO still says who you actually bought from.
- 3
Record the lot at the moment of receiving
Line items carry item, variant, quantity, cost, SKU, image, category, item type, the pack name, quantity and count — and the lot number, expiry date and batch notes. The expiry date is captured when the goods are in front of you, which is the only moment anyone can actually read it off the carton.
- 4
Receive, and stock posts itself
Receiving creates or merges batches for tracked items, converting per-pack cost to per-base-unit cost first, and increments item or variant stock otherwise. Rows are locked, a history entry is written per movement, and parent stock is re-derived. Totals track products, extra fees, the order total and the total units.
- 5
Reverse a mistake, in whole or in part
Reversal can undo an entire receipt or only a number of units on one line, with the sold-from-that-lot check applied first and the negative-stock setting respected. Three attachments per PO are supported — supplier invoices as PDF up to 10 MB, or photographs through the image pipeline.
07
What is about to expire, and what it is worth
The expiry report sorts your dated stock into four windows measured from today. They are mutually exclusive, so nothing is counted twice and the tiers sum to the total.
| Tier | Window | What it tells you |
|---|---|---|
| Expired | Before today | Stock that is already unsellable and is still sitting on a shelf. Usually the most surprising number the first time. |
| Expiring this week | 0–7 days | The discount-it-now window. Items, units and value at risk. |
| Expiring this month | 8–30 days | Still enough time to move it at a smaller markdown or push it into a promotion. |
| Expiring this quarter | 31–90 days | The planning horizon — what not to reorder, and what to stop buying deep on. |
Every tier reports distinct items affected, units expiring and value at risk, priced from the batch's own cost and falling back to the item's cost when a lot has none. Drilling in gives one row per item or variant with its units, value at risk, earliest expiry, days remaining and batch count, soonest first. The report is not pharmacy-specific — any organisation that tracks batches gets it, and organisations that do not simply see zeros.
08
Stock Health
Expiry answers what will spoil. Stock Health answers the other two questions: what is costing you sales by being absent, and what is costing you cash by being present. Every item lands in exactly one of five buckets, computed from how fast it actually sells.
Out of stock
Nothing on hand. Paired with a lost-revenue-per-day figure derived from how quickly it was selling before it ran out — which is what turns a list of empty shelves into a priority order.
Reorder now
Days of cover have fallen to or below your lead time. By the time the delivery arrives you would be empty, so this is already late.
Reorder soon
Cover is at or below your target days. The comfortable moment to place the order rather than the urgent one.
Overstock
More than 90 days of cover, or selling at zero velocity while holding stock — dead stock. Reported with the capital tied up in it.
Healthy
Enough cover to sell through comfortably and not so much that it is idle money. Most of a well-run catalogue should be here.
Tuned to your trade
The measurement window runs 7 to 365 days and defaults to 30. Target days of cover runs 1 to 365 and defaults to 14. Lead time runs 0 to 365 and defaults to 3. A greengrocer and a hardware shop do not share a definition of soon.
Velocity is measured honestly, and the report never tells you what to buy
Sales velocity is units sold in the window divided by the days the item was actually available — capped at the item's age, so a product added last week is not judged as though it had thirty days to sell. Only real sales count, only stock-managed items are included, and quantities are summed in base units specifically so an item sold by the box is not read as selling twelve times slower than it is. What Stock Health will not do is prescribe an order quantity or a spend. It describes the position and names the cost of it — lost revenue per day where shelves are empty, capital tied up where they are too full — and leaves the buying decision to the person who knows what the supplier will actually deliver.
09
The alert that arrives before the problem
A report only helps the person who opens it. Expiry is precisely the kind of thing nobody opens a report about until after it has cost them, so Akkad pushes it.
A job runs once a day, early morning, and sends two tiers: stock hitting the seven-day mark, and stock expiring today. Both are matched on the exact day in your organisation's own local time — which is also what makes the alert self-deduplicating. Because the run happens once a day and matches an exact date, an item can only ever satisfy each tier once. There is no dedup table to keep, and therefore no dedup table to get out of step and start double-sending.
Each recipient gets one digest rather than one message per item, in their own language, deep-linked straight into the expiry report. It goes to owners and to anyone holding the permission to view that report — the people who can actually do something about it, and not the whole team.
10
Questions
Do I have to use batches?
No. Batch tracking is opt-in per item, so you can run lots on the twenty products where expiry matters and leave the other two thousand as plain stock figures. Turning it on later is safe: the existing figure is carried across into a migration batch rather than being lost at the switchover.
Does this track serial numbers?
No. Batches are lot-level, not unit-level. You can answer which lot a sale came from; you cannot answer which individual unit. If per-unit serial tracking is a requirement, this is not that system.
What happens if two people sell the last unit at the same moment?
Items, variants and batches are locked at row level for the whole of every mutation, so the two requests serialise. The first one takes the stock. The second one either is refused with a message naming what is available, or is allowed to go negative — depending on the setting you chose for your organisation.
Can I reverse only part of a delivery?
Yes. Purchase-order reversal works on a number of units of a single line as well as on the whole receipt. Before it runs, it checks each affected lot and refuses if units from that lot have already been sold, aggregating every allocation so several partial sales cannot slip past.
How is cost of goods calculated when a line spans two lots?
By weighted average of the lots actually consumed. Expiry-first deduction decides which lots those are, the line's cost is set from their real costs in proportion, and the order's total cost is refreshed. Receiving more of an existing lot re-averages that lot's cost before the quantity increases, so nothing is later costed at a stale price.
Does Stock Health work for items sold by the box?
Yes, and it is one of the specific things it gets right. Velocity is summed in base units, so a product that moves four cartons of twelve a week reads as forty-eight units a week rather than four — which is the difference between a correct reorder point and one that is an order of magnitude off.
Related
Catalogue
The items these figures belong to — variants, pack sizes, categories and the importer that brings them in.
Orders
How order status moves stock, how edits rebalance it, and why a replayed submission never deducts twice.
Reports
Where cost of goods lands — sales performance, category profitability and the financial report.
इसे अपने ही कैटलॉग पर परखें
अपने हिसाब का प्लान चुनें, स्प्रेडशीट से प्रोडक्ट इम्पोर्ट करें, और उसी दिन चलता हुआ स्टोर, काउंटर और ऑर्डर बुक पाएँ।
फ़्री प्लान उपलब्ध है। आज़माने के लिए कार्ड की ज़रूरत नहीं। इम्पोर्ट आपका मौजूदा कैटलॉग साथ ले आता है।