Die meisten Proben in einem Labor durchlaufen dieselbe
Geschichte: gebucht, empfangen, getestet, verifiziert,
freigegeben. Was danach passiert, wurde bislang entweder pro
Labor selbst erfunden oder ausserhalb von SENAITE dokumentiert.
Zwei aktuelle PRs in senaite.core liefern jetzt echte Enden.
Ein Dispose-Workflow, opt-in
senaite.core#2970
führt eine echte dispose-Transition und einen disposed-Status
ein. Aktiviert man in der Konfiguration den Schalter
Dispose-Workflow (dispose_workflow_enabled, standardmässig
aus), bekommt jeder Nach-Empfangs-Status eine Dispose-Aktion:
sample_received, to_be_verified, to_be_preserved,
verified, published, rejected, invalid, sogar
cancelled. Die Probe, die ein Jahr storniert im Kühlschrank
lag, kann jetzt sauber als entsorgt festgehalten werden, mit
Bearbeiter, Datum und Begründung.
Das dispose_samples-Formular verlangt einen Kommentar,
vorbelegt mit einem sinnvollen Standardtext. Ein Alert-Viewlet
auf der Probenansicht trägt die Entsorgungs-Metadaten dauerhaft.
Ein Guard blockiert die Entsorgung, solange eine Analyse noch
auf einem Worksheet liegt. Die Partitions-Primary-Regeln gelten:
Entsorgt man ein Primary, folgen die Partitionen; entsorgt man
die letzte Partition, wird das Primary automatisch mit entsorgt.
Eine neue Berechtigung, senaite.core: Transition: Dispose Sample, wird an LabManager und Manager vergeben. Ein
Upgrade-Schritt registriert Berechtigung, Status und Transition;
sichtbar wird nichts, bis der Schalter umgelegt wird.
Dispatch, jetzt optional und sperrend
senaite.core#2971
macht denselben Schritt für den bestehenden Dispatch-Flow. Die
dispatch-Transition und der dispatched-Reiter im Review-State
sind an Sample-Dispatch-Workflow aktivieren gekoppelt. Für
bestehende Installationen schaltet ein Upgrade-Schritt Dispatch
ein, damit nichts bricht; neue Installationen starten ohne.
Wichtiger: Dispatch sperrt jetzt die Analysen der Probe. Vor diesem PR war eine dispatchte Probe nur an ihrem Review-State erkennbar; die JSON-API konnte weiterhin Ergebnisse darauf schreiben, weil die Analyse-Bearbeitungsrechte am Analyse-Status hängen, nicht am Proben-Status. Diese Lücke ist zu.
Der wiederverwendbare Sperrmechanismus
Interessant ist, was beide Features teilen. Statt einer
Einzelfall-Regel “dispatchte Analysen sind gesperrt” führt der
PR das Marker-Interface ILockingState und einen neuen
Analyse-Status namens locked ein. IDisposed und IDispatched
erben beide von ILockingState. Der Analyse-Sperr-Guard liest:
ILockingState.providedBy(sample)
Mehr nicht. Jeder künftige Proben-Status, der dasselbe Verhalten
möchte, etwa ein hypothetisches IStored in senaite.storage,
erbt schlicht ILockingState und bekommt Analyse-Sperrung
umsonst.
Die Sperrung ist sorgfältig darin, was sie anfasst. Analysen in
einem Terminal-Status (cancelled, rejected, retracted)
werden nicht angerührt, damit das Entsorgen einer stornierten
Probe deren Analysen nicht auf locked heraufhebt und deren
is_active-Status wahrheitsgemäss bleibt. Der locked-Status
hat eine einzige versteckte, automatische unlock-Transition;
ihr after_unlock-Event rollt jede Analyse in den Status
zurück, den sie vor der Sperrung hatte. Restauriert man eine
Probe, kommen die Analysen mit ihrem Ursprungsstatus wieder,
ohne Buchhaltung im Aufrufer.
Was das für ein Labor bedeutet
Zwei sofortige Gewinne.
Erstens ist das Ende einer Probe jetzt erstklassig modelliert. Sagt Ihre Aufbewahrungsrichtlinie “zwei Jahre halten, dann entsorgen”, ist die Entsorgung eine Transition mit Bearbeiter, Datum und Begründung, direkt auf der Probe. Auditoren haben eine Anlaufstelle.
Zweitens können sich nachgelagerte Integrationen auf den Terminal-Status einer Probe verlassen. Nach Dispatch oder Dispose wird kein Adapter, kein Admin-Skript, kein JSON-API-Call still ein Ergebnis mutieren. Die Sperrung wird in der Workflow-Schicht durchgesetzt, oberhalb des schreibenden Codes.
Beide Schalter starten aus. Braucht Ihr Labor sie nicht, ändert sich der Alltag nicht. Braucht es sie, passen sie ohne Custom-Code.