RIDING BYTES
← All insights

July 29, 2026 · 6 min read

SENAITE.storage grows up: retention rules, Retrieve, and printable stickers

A tour of what shipped in senaite.storage this half. Configurable retention with per-service rules, an ISO-aligned Retrieve transition with mandatory reason, and Code128 stickers for facilities and containers.

SENAITE.storage grows up: retention rules, Retrieve, and printable stickers

senaite.storage started as a map: facilities, positions, containers. You put a sample in a slot; you knew where it lived. The last few months turned that map into a lifecycle: how long material stays, why it comes back out, and how you find its box on a shelf when the scanner is the only tool you have.

Configurable retention

Every accredited lab has retention rules. Water samples keep for one duration, blood for another, “Chikungunya positive” for something else again. Until #62, senaite.storage did not know any of this. Retention lived in a spreadsheet.

The new Retention Rules grid in the Storage control panel maps an Analysis Service, optionally a specific result value, to a retention period in days. The rule matching algorithm is explicit:

Storage Settings, Retention Rules tab. Days before expiration set to 5. Three retention-period rows: Analysis Service Cs-134 with 90-day retention, Cs-137 with 90-day retention, and a Cs-134 row with no retention value set. Save and Cancel buttons at the bottom.
Retention Rules in the Storage control panel. One row per analysis service, optionally per result value, mapped to a retention period.
  1. Walk every analysis on the sample.
  2. For each analysis, look up rules by service UID.
  3. If a rule specifies a result value, match that too.
  4. Specific rules (with result) beat general rules.
  5. When several rules match, the longest retention wins.

This covers two real-world patterns cleanly. If the organism is the result of a test (an “Identified organism” service whose result is “E. coli”), you match on result value. If the organism is a dedicated test (a “Chikungunya” service whose result is Positive or Negative), you match on the same field. The store view auto-populates the retention days from the rule; a lab tech overrides it only when needed.

Companions land on top: #63 adds result-type-specific controls (different fields for numeric vs string results), #64 exposes Storage Expiry Date as a column, #65 adds a “Past Retention” filter, and #66 paints samples in red when they cross their expiry. The end result is a listing where the tech triaging the fridge on Monday morning can see, at a glance, what to move to disposal.

Recover became Retrieve

Small, but the kind of change that matters when auditors read your SOPs. #67 renames every user-facing occurrence of “recover” to “retrieve”, to align with ISO 17025 and ISO 15189 wording. Internal transition IDs (recover, recover_samples) and permission strings are untouched, so add-ons that hook into the transition keep working. Only labels, buttons, and messages moved.

A required reason on retrieval

Rejection has always asked why. Retrieval, until #70, did not. That is a hole in the audit trail: a sample went into storage and came back out, and nothing recorded whether it was for a re-run, a client dispute, or a second-opinion test.

The Storage control panel now carries a Retrieve Reasons grid. Lab managers configure the picklist (“Rerun”, “Client inquiry”, “External confirmation”) and a toggle makes selection mandatory. Trigger Retrieve on a stored sample and you land on a form where you pick a reason, or type a custom one via “Other…”. An info viewlet on the sample carries the reason, actor, and date from that moment on.

Code128 stickers for storage locations

You cannot barcode-scan into a shelf if the shelf has no barcode. #72 fills that gap with a StorageLocation_50x30mm sticker template that renders a Code128 barcode of the location’s getId() plus the breadcrumb full title as human-readable text. A GetStorageStickers adapter registers it for IStorageFacility, IStoragePosition, IStorageContainer, and IStorageSamplesContainer. The listings gain a Print stickers action in every review state, reusing the existing workflow_action?action=print_stickers redirect.

Sticker print dialog. Template dropdown set to 'Storage location (50x30mm)', number of copies 1, Back and Print buttons. A preview shows the printed sticker: a Code128 barcode above the location id SS-00001 with '9x9 Container' as human-readable text, on a labelled millimetre ruler.
A StorageLocation_50x30mm sticker rendered. Code128 barcode of the location id, breadcrumb title as human-readable text, previewed against a millimetre scale.

Peel a sticker onto a shelf, and a scanner now reads back the exact same string the sample-storage forms accept. The template id is senaite.storage:StorageLocation_50x30mm.pt; override it per instance the same way you override any other sticker.

A quieter change that mattered

#74 switched the stored and past-retention sample listings to flat_listing. No new features, just a faster render on containers with hundreds of samples. Worth naming because it removes one of the last “storage is slow” complaints.

Two people reviewing notes on paper next to a laptop

Bring this to your lab

Whether you are evaluating SENAITE, scaling it across sites, or wiring up instruments and monitoring, the team that wrote the platform is the team you talk to.