ThreadCount Community edition

Uniform stock management for healthcare linen rooms. Licensed under the GNU AGPL v3.
This commit is contained in:
ThreadCount
2026-09-13 08:45:19 +10:00
commit 1bc2de655a
505 changed files with 56223 additions and 0 deletions
@@ -0,0 +1,113 @@
import Link from "next/link";
import { Band, body, small } from "@/components/site";
import { GuideFoot, GuideHead, GuideMeta, Pitfalls, Steps, type Step } from "@/components/guide";
export const metadata = {
title: "How to run a uniform stocktake in a hospital, aged-care home or clinic",
description:
"A count that survives scrutiny in a hospital linen room or an aged-care store: what to count, how to split a room into shelves, what to do about garments at the laundry, and how to record a variance.",
alternates: { canonical: "/guides/uniform-stocktake" },
};
const STEPS: Step[] = [
{
n: "01",
h: "Decide what a count is for before you start",
p: <>A stocktake answers one of two questions, and they need different counts. Either you are correcting the on-hand figure so ordering stops going wrong, or you are producing a stock valuation someone in finance will sign. The first can be done shelf by shelf over a fortnight. The second has to be a single point in time with issuing stopped, or the number is meaningless. Most linen rooms need the first far more often than the second, and get into trouble by attempting the second casually.</>,
},
{
n: "02",
h: "Freeze movement, or record it",
p: <>The commonest way a count goes wrong is that garments move while it is happening. If you can, stop issuing for the duration. If you cannot and on a ward or in an aged-care home at shift change you usually cannot then write down every issue and every return made during the count, and apply them afterwards. An unrecorded issue mid-count looks exactly like a loss, and you will spend an afternoon chasing it.</>,
},
{
n: "03",
h: "Break the room into shelves, not into products",
p: <>Count by location, not by catalogue. A person standing at a shelf can count everything on it accurately; the same person asked to count &ldquo;all scrub tops&rdquo; has to walk the whole room, and will miss the bay by the door. Give every shelf and bay a name, count it as a unit, and record the count against that location. It also means two people can count different parts of the room at once without colliding.</>,
},
{
n: "04",
h: "Count by size, always",
p: <>&ldquo;Forty scrub tops&rdquo; is not a usable number. Forty tops that are all XXL is a shortage of every other size wearing a healthy total. Every count line should be item plus size, because that is the level at which you run out, and the level at which you reorder.</>,
},
{
n: "05",
h: "Account for what isnt on the shelf",
p: <>At any moment a large share of your stock is legitimately elsewhere: at the laundry, issued to staff, in a delivery not yet put away, or set aside for a starter pack. None of that is missing, but if your count only covers shelves then all of it reads as a loss. Decide in advance how each of those is treated and be consistent the usual approach is to count shelves only, and compare against expected shelf stock rather than against everything you have ever bought.</>,
},
{
n: "06",
h: "Write down why, not just what",
p: <>A variance with no reason beside it is worthless three weeks later. &ldquo;Twelve fewer size M tops than expected&rdquo; tells you nothing; &ldquo;twelve fewer, ward reported a bin sent to laundry unlogged&rdquo; tells you where to look next time. Make a reason mandatory past a threshold you choose five is a sensible starting point so small counting noise passes without ceremony and real gaps get explained while the explanation is still known.</>,
},
{
n: "07",
h: "Apply it, then look at the pattern",
p: <>Correcting the on-hand figure is the easy half. The value is in what repeats: the same size short every count, the same shelf always over, a variance that appears only after a particular roster. One count is an anecdote. Four counts with reasons attached is an argument you can take to a manager.</>,
},
];
const PITFALLS: [string, string][] = [
["Counting into a spreadsheet nobody reconciles", "A count that never gets applied to the on-hand figure changes nothing. If the spreadsheet is where it ends, ordering carries on from the same wrong number."],
["Recounting only the lines that look wrong", "Recounting a shortfall and accepting every surplus quietly biases the result. Recount by shelf, not by whether you liked the answer."],
["Treating the laundry as loss", "Garments in the wash are stock. Counted as missing, they justify orders you do not need, and the surplus arrives a fortnight later."],
["One person counting their own room", "Not because anyone is dishonest — because you see what you expect. Where the count feeds a valuation, have someone else count at least a sample."],
["No date on the count", "A number without the moment it was true cannot be reconciled against anything. Record when the count was taken, not when it was typed up."],
["Stopping at the total", "The total is the least useful figure in a stocktake. The per-size variance is the one that changes what you order on Monday."],
];
export default function Page() {
return (
<>
<GuideMeta
slug="uniform-stocktake"
title="How to run a uniform stocktake in a hospital, aged-care home or clinic"
description={metadata.description}
updated="2026-09-07"
/>
<GuideHead
kicker="Guide"
title="How to run a uniform stocktake"
lede="Counting a linen room is not hard, and neither is counting an aged-care store or a clinic cupboard. Producing a number that still means something a month later is, and that difference is almost entirely in the preparation."
/>
<Band>
<Steps steps={STEPS} />
</Band>
<Band tone="surface">
<div style={{ fontSize: 11.5, letterSpacing: "0.12em", textTransform: "uppercase", fontWeight: 800, borderBottom: "2px solid var(--color-text)", paddingBottom: 9 }}>
Where counts go wrong
</div>
<Pitfalls items={PITFALLS} />
</Band>
<Band>
<h2 style={{ fontFamily: "var(--font-heading)", fontWeight: 800, fontSize: "clamp(24px,3vw,36px)", letterSpacing: "-0.02em", margin: 0 }}>
Doing this in ThreadCount
</h2>
<p style={{ ...body, margin: "16px 0 0", maxWidth: "62ch" }}>
Counts are taken by location, on a phone, scanning each garment. The expected figure stays
on screen as you go, the tally survives putting the phone down mid-shelf, and a gap past
your chosen threshold asks for a reason before it will commit. Nothing is applied to your
on-hand figures until you commit the count.
</p>
<p style={{ ...small, margin: "14px 0 0", maxWidth: "62ch" }}>
None of which you need in order to follow the steps above a clipboard and a consistent
method will do. It is just faster when the expected number is already in your hand.
</p>
<div style={{ display: "flex", gap: 12, marginTop: 24, flexWrap: "wrap" }}>
<Link href="/demo" data-umami-event="open-demo" data-umami-event-placement="guide" className="btn btn-primary">Open the demo</Link>
<Link href="/features" className="btn btn-secondary">What else it does</Link>
</div>
</Band>
<GuideFoot
related={[
["Where hospital and aged-care uniforms actually go", "/guides/uniform-loss"],
["Charging uniforms to the right cost centre", "/guides/cost-centre-reporting"],
]}
/>
</>
);
}