Housekeeping brings soiled linen to Room C and takes clean linen back. Both parties attest on one device. This is the screen the whole system lives or dies on — if it is slower than shouting at the supervisor, staff go back to the register.
One device, two parties. The supervisor records, the ward staffer attests with their own code on the same handset. No second device, no network round-trip, no waiting.
Variance is recorded, never blocked. If 12 soiled come in and 9 clean go out, that is a real fact and the system takes it. Blocking the flow is how you teach staff to lie to it.
Offline-first. Basements and laundry docks have no signal. Movements queue locally and sync later. If the app fails once at the trolley, staff never open it again.
The code is not identity. It is a 4-digit attestation captured with actor, timestamp, device ID and coarse location, hashed into an immutable row. Not cryptographic — just enough to make "I never received those" untenable.
movement id MV-48213 type WARD_EXCHANGE from_node WARD_3B to_node ROOM_C status ATTESTED emergency_ref null lines BEDSHEET_90 declared 12 confirmed 12 cond SOILED PILLOW_CVR declared 8 confirmed 8 cond SOILED GOWN declared 3 confirmed 3 cond INFECTED asset_ids[] null ← populated in Phase 4 attestations party A R.Kadam method PIN 14:22:09 dev A81C party B M.Bhosale method PIN 14:22:31 dev A81C
Sahyadri Multispecialty, Nashik · depot operated by Company A. This person needs to know what they can issue right now, what is owed back, and what is waiting on a signature.
| Ref | Sent | Out | Back | Age | |
|---|---|---|---|---|---|
| C-2291 | 31 Jul | 100 | — | 3d | |
| C-2288 | 29 Jul | 118 | 118 | closed | settled |
| C-2284 | 26 Jul | 140 | 122 | 8d | 18 open |
| C-2280 | 24 Jul | 96 | 90 | 10d | disputed |
| Time | Ward | In | Out | Attested |
|---|---|---|---|---|
| 14:22 | Ward 3B | 23 | 23 | RK · MB |
| 13:05 | ICU | 18 | 20 | RK · SF |
| 11:40 | OT complex | 42 | 42 | RK · AN |
| 10:12 | Maternity | 16 | 14 | RK · PD |
| 08:55 | Ward 3B | 27 | 27 | RK · MB |
Shubham Industrial Laundry. Vendors will not install software or train staff. They get a magic link that does exactly three things: see what is expected, confirm a consignment, dispute a count.
| Ref | Picked up | Pieces | Owed back | Status |
|---|---|---|---|---|
| C-2291 | 31 Jul 08:10 | 100 | 100 | in wash |
| C-2284 | 26 Jul 07:55 | 140 | 18 | short 18 |
| C-2280 | 24 Jul 08:30 | 96 | 6 | disputed |
| C-2277 | 22 Jul 08:05 | 112 | 0 | settled |
Vestara Linen Services · 5 sites live. The point of this screen is not to show how much linen was lost. It is to show where it was lost — because loss you can localise stops being a write-off and becomes a debit note.
| Laundry | Return % | Rewash % | Turn |
|---|---|---|---|
| Shubham Industrial | 96.8 | 4.1 | 2.9d |
| Nirmal Wash Co. | 99.6 | 1.2 | 2.1d |
| Ganga Laundry | 98.9 | 2.8 | 3.4d |
| Pune Hygiene Svcs | 99.4 | 1.9 | 2.4d |
| Site | Type | Deployed | Shrinkage 30d | Days cover | Open items | Reconciliation |
|---|---|---|---|---|---|---|
| Sahyadri Nashik | Hospital | 3,240 | 3.8% | 4.1 | 4 open | Jul pending |
| Sahyadri Pune | Hospital | 4,110 | 1.9% | 5.6 | clear | Jul signed |
| Grand Meridien | Hotel | 2,880 | 1.4% | 6.2 | clear | Jul signed |
| Lilavati Wing B | Hospital | 2,460 | 4.2% | 2.2 | 5 open | Jul pending |
| Aster Aurangabad | Hospital | 2,130 | 2.1% | 3.8 | 2 open | Jul signed |
| Ref | Site | Leg | Pcs | Value | Age | State |
|---|---|---|---|---|---|---|
| D-0412 | Lilavati | Depot↔Laundry | 32 | ₹7,680 | 21d | disputed |
| D-0418 | Nashik | Depot↔Laundry | 18 | ₹4,320 | 8d | review |
| D-0421 | Nashik | Ward↔Depot | 11 | ₹2,640 | 5d | review |
| D-0424 | Aster | Ward↔Depot | 7 | ₹1,680 | 2d | raised |
Cells are coloured by days of cover, not raw counts — 200 sheets means nothing until you know the site burns 40 a day. A temporary allocation is modelled as a loan, so the lending site's par never looks broken.
| Bedsheet | Draw sheet | Pillow cvr | Blanket | Gown | Towel | |
|---|---|---|---|---|---|---|
| Sahyadri Nashik | 4.1184 pc | 3.696 | 6.8212 | 5.274 | 0.418 | 1.888 |
| Sahyadri Pune | 7.9402 | 6.4188 | 4.8240 | 5.596 | 8.2210 | 4.1176 |
| Grand Meridien | 6.2288 | —n/a | 7.1312 | 4.4120 | —n/a | 6.6420 |
| Lilavati Wing B | 2.2142 | 0.934 | 1.998 | 3.862 | 2.170 | 3.2110 |
| Aster Aurangabad | 3.8168 | 4.288 | 3.9156 | 2.444 | 4.692 | 3.5128 |
| ◈ Strategic reserve | 600held | 200held | 600held | 150held | 400held | 300held |
| From → To | Pcs | Age | Back |
|---|---|---|---|
| Pune → Lilavati | 120 | 18d | 0 |
| Meridien → Nashik | 80 | 6d | 80 |
| Reserve → Aster | 200 | 64d | 40 |
Sahyadri Multispecialty, Nashik. If this reads as a surveillance tool pointed at housekeeping, the hospital sabotages the counts and you end up with worse data than the register. So it leads with what they are judged on — stockouts and cost per bed-day.
| Ward | Par | Holding now | 28d net | Unreturned | Status |
|---|---|---|---|---|---|
| ICU · 2nd floor | 60 | 61 | −6 | 6 | at par |
| Ward 3B · General | 55 | 44 | −31 | 31 | review |
| OT complex | 90 | 88 | +3 | 0 | at par |
| Maternity · 4th | 50 | 52 | −8 | 8 | watch |
| Ward 2A | 45 | 42 | −12 | 12 | watch |
| Day care | 25 | 24 | +1 | 0 | at par |
Stock is never edited. There is no "adjust quantity" button anywhere in Kora. Balance at any node is the sum of confirmed inbound minus confirmed outbound — double-entry, exactly like accounting. The moment someone can UPDATE a movement, the audit trail becomes decorative.
| Ref | Timestamp | Type | From → To | Item | Decl | Conf | Cond | Attested |
|---|---|---|---|---|---|---|---|---|
| MV-48213 | 03 Aug 14:22 | WARD_EXCH | WARD_3B → ROOM_C | BEDSHEET_90 | 12 | 12 | soiled | RK·MB ✦ |
| MV-48213 | 03 Aug 14:22 | WARD_EXCH | ROOM_C → WARD_3B | BEDSHEET_90 | 12 | 12 | clean | RK·MB ✦ |
| MV-48209 | 03 Aug 13:05 | WARD_EXCH | ROOM_C → ICU | GOWN | 20 | 20 | clean | RK·SF ✦ |
| MV-48204 | 03 Aug 09:40 | DISPATCH | ROOM_C → LAUNDRY_L | ALL_TYPES | 100 | 100 | soiled | RK·SL ✦ |
| MV-48198 | 02 Aug 16:11 | RECEIPT | LAUNDRY_L → ROOM_C | PILLOW_CVR | 40 | 40 | clean | RK·SL |
| MV-48197 | 02 Aug 16:48 | REVERSAL | ↳ reverses MV-48198 | PILLOW_CVR | −40 | −40 | clean | RK·SL ✦ |
| MV-48196 | 02 Aug 16:50 | RECEIPT | LAUNDRY_L → ROOM_C | PILLOW_CVR | 40 | 34 | clean | RK·SL ✦ |
| MV-48196 | 02 Aug 16:50 | RECEIPT | LAUNDRY_L → REWASH | PILLOW_CVR | — | 6 | rewash | RK·SL ✦ |
| MV-48190 | 02 Aug 11:20 | CONDEMN | ROOM_C → CONDEMNED | BEDSHEET_90 | 14 | 14 | end of life | RK·AV ✦ |
| MV-48186 | 31 Jul 15:31 | WARD_EXCH | ROOM_C → ICU | BEDSHEET_90 | 40 | 40 | clean | ⚑ unattested |
| MV-48185 | 31 Jul 15:12 | LOAN_OUT | MERIDIEN → ROOM_C | BEDSHEET_90 | 80 | 80 | clean | GM·RK ✦ |
| MV-48180 | 28 Jul 18:00 | STOCKTAKE | ROOM_C adjustment | BEDSHEET_90 | — | −4 | counted | RK·AV ✦ |
No edits, no deletes. A wrong movement is cancelled by a reversing entry pointing at the original. Both rows survive.
Balances are derived, never written. Any node's stock is a query, not a column somebody can set.
Stocktake is the one sanctioned exception — and it produces an adjustment movement with a mandatory reason and an approver's attestation, not a silent edit.
Condemnation needs a second party. Otherwise it becomes the drain that hides theft.
Unattested rows are visible, not hidden. MV-48186 above is flagged from the emergency window and blocks month-close until cleared.
movement_line {
item_type_id
declared_qty
confirmed_qty
condition
asset_ids[] ← null today
} when tags exist, enforce
len(asset_ids) == confirmed_qty