Skip to content

Making margin visible in a four-store grocery chain

Four stores, no line-level margin data, and stock losses nobody could account for. We built the system that showed where the money went.

Client
An independent grocery chain
Sector
Retail
Duration
11 weeks
Year
2024
A shop assistant in the body care aisle counting along a shelf with one hand, the stock count for aisle four open on the phone in the other.

Margin per product line

Before
None
Now
Daily

Annual stock loss

Before
£13,400
Now
Near zero

Time counting stock

Before
~9 hrs / fortnight
Now
~2 hrs / fortnight

Revenue, first three months

Before
Baseline
Now
+83%

The problem

The owner ran four convenience stores and could tell you monthly revenue to the pound. He could not tell you which products made money.

Stock was counted on paper twice a month. The counts were transcribed into a spreadsheet by a manager who had built it himself, and the spreadsheet had been copied and adapted so many times that each store used a slightly different version.

Losses were running at a little over £13,000 a year across the estate. Nobody could say whether that was theft, waste, delivery shortfalls, or counting errors, because the data could not distinguish between them.

A clipboard with a handwritten stock count sheet and a printed spreadsheet marked with highlighter, resting on boxes in a shop stockroom.

What we found

We spent a fortnight in the stores before writing anything. Two things came out of it that were not in the brief.

The first was that an entire aisle was losing money. It had been kept because it had always been there, and no report had ever been capable of showing its contribution separately.

The second was that the shortfalls clustered. They appeared on particular shifts rather than evenly across the week, which meant the answer was not going to come from better counting.

The project manager writing in a notebook in a shop aisle while the owner, seen from behind, reaches for a shelf.
Hand-drawn sketches of phone screens for a stock count, spread across a desk with sticky notes, and a hand drawing another one.
Stockhand
Laptop screen of the margin report for week 37: sales, contribution, margin and stock loss across four shops, contribution ranked by category with household and cleaning below cost, and a list of lines that need a look.
Margin read per line rather than per store. The household aisle running below cost is the one that had been invisible for years.

How we got there

Eleven weeks, and most of the difficult part was not the software. It was getting four shops that each did things their own way to count the same thing the same way.

Four shops, four product lists

Each shop's spreadsheet named the same product differently, so nothing could be compared until there was one list. We matched every line by its barcode and put the ones that would not match in front of the owner to decide, a few at a time.

A name on every count, without slowing anyone down

Counts had to carry the name of whoever did them, but a password on a shared phone ends up written on the wall. Staff sign in once on their own phone with a four-digit code.

The engineer at a whiteboard mapping four shops' product lists into one, explaining it to colleagues at their desks.

The first count screen was too slow

The first version asked for a typed figure on every line. On busy mornings people skipped lines to finish. The version that shipped shows the expected figure, takes one tap when it matches, and only asks for a number when it does not.

One shop first

It ran in one shop alongside the paper count for two weeks before the other three moved over, so every fix came from the people doing the counting rather than from us guessing.

The project manager leaning over to show the engineer a flagged line on a phone, with the same screen open on the laptop in front of them.

What we built

Phone screen of a stock count in progress for aisle four, household and cleaning: 41 of 63 lines counted, each with its expected figure and a stepper, and surface spray flagged nine short.

Stock counts on a phone, not on paper

Counting moved off paper and onto whatever device staff already carried, timestamped and attributed to whoever did it. The paper step disappeared, and so did the transcription errors.

Phone screen of one flagged line, surface spray at Kirkstall: nine units unaccounted for, the count reconciled from the last full count through deliveries and till sales, and a grid of shifts with the shortfalls clustered on Tuesday and Wednesday late shifts.

Variance flagged as it happened

Counts that did not reconcile against deliveries and sales raised an alert with the shift attached, rather than surfacing in a month-end review that nobody had time to read.

Margin per line, not per store

Every product carried its landed cost, so contribution could be read per line, per category, and per store. The dead aisle became obvious within a week.

One version, four stores

The four diverging spreadsheets became one system, so numbers from different stores could finally be compared.

Tablet screen showing the four shops side by side, each with its margin this week, how many aisles the morning count has covered, and anything short, delivered or wasted today.

Afterwards

The revenue figure needs an honest caveat: the system did not generate it. Closing the dead aisle and reallocating the space did, and the system is what made that decision possible.

The loss figure is more directly attributable. Once counts carried a name and a timestamp, the pattern in the shortfalls resolved itself within a month.

The shop owner at a desk in the back office, mug in hand, reading the week's margin report on a laptop.

Built with

  • TypeScript
  • React
  • Node
  • Fastify
  • PostgreSQL
  • Prisma
  • Redis
  • Tailwind CSS
  • Barcode scanning
  • Docker

More case studies

Is this your problem too?

If any of the above sounded familiar, describe your version of it. The first conversation is about whether software is the right answer at all.

From £10,000Most projects land between £15,000 and £55,000.