diff --git a/src/senaite/referral/adapters/guards/sample.py b/src/senaite/referral/adapters/guards/sample.py
index d225589..38a8a95 100644
--- a/src/senaite/referral/adapters/guards/sample.py
+++ b/src/senaite/referral/adapters/guards/sample.py
@@ -67,3 +67,14 @@ def guard_invalidate_at_reference(self):
if not lab_code:
return False
return True
+
+ def guard_receive_at_reference(self):
+ """Returns true if current request contains a POST with the
+ 'receive_at_reference' action to ensure this transition is not
+ performed manually,
+ """
+ request = api.get_request()
+ lab_code = request.get("lab_code")
+ if not lab_code:
+ return False
+ return True
diff --git a/src/senaite/referral/adapters/listing/samples.py b/src/senaite/referral/adapters/listing/samples.py
index 64d59f5..e21b448 100644
--- a/src/senaite/referral/adapters/listing/samples.py
+++ b/src/senaite/referral/adapters/listing/samples.py
@@ -103,7 +103,11 @@ def add_review_states(self):
"id": "shipped",
"title": _("Referred"),
"contentFilter": {
- "review_state": ("shipped", "rejected_at_reference"),
+ "review_state": (
+ "shipped",
+ "rejected_at_reference",
+ "received_at_reference",
+ ),
"sort_on": "created",
"sort_order": "descending"},
"transitions": [],
diff --git a/src/senaite/referral/content/inboundsample.py b/src/senaite/referral/content/inboundsample.py
index 547f430..b9743aa 100644
--- a/src/senaite/referral/content/inboundsample.py
+++ b/src/senaite/referral/content/inboundsample.py
@@ -125,6 +125,12 @@ class IInboundSampleSchema(model.Schema):
)
)
+ # TODO 2.x Replace schema.List by senaite.core.schema.UIDReferenceField
+ directives.omitted("services")
+ services = schema.List(
+ title=_(u"label_inboundsample_services", default=u"Services"),
+ )
+
# TODO 2.x Replace schema.List by senaite.core.schema.UIDReferenceField
directives.omitted("sample")
sample = schema.List(
@@ -311,3 +317,21 @@ def getDateRejected(self):
"""Returns the datetime when this inbound sample was rejected or None
"""
return get_action_date(self, "reject_inbound_sample", default=None)
+
+ def setServices(self, value):
+ """Set the services from the current instance that match with the
+ analyses that were requested by the referring laboratory
+ """
+ set_uids_field_value(self, "services", value)
+
+ def getServices(self):
+ """Returns the services from current instance that match with the
+ analyses that were requested by the referring laboratory
+ """
+ return [api.get_object(uid) for uid in self.getRawServices()]
+
+ def getRawServices(self):
+ """Returns the UIDs of the services from current instance that match
+ with the analyses that were requested by the referring laboratory
+ """
+ return get_uids_field_value(self, "services") or []
diff --git a/src/senaite/referral/jsonapi/outboundsample.py b/src/senaite/referral/jsonapi/outboundsample.py
index 60a269d..debd866 100644
--- a/src/senaite/referral/jsonapi/outboundsample.py
+++ b/src/senaite/referral/jsonapi/outboundsample.py
@@ -33,6 +33,7 @@
from bika.lims.interfaces import ISubmitted
from bika.lims.utils import changeWorkflowState
from bika.lims.workflow import doActionFor
+from senaite.referral import logger
@implementer(IPushConsumer)
@@ -65,8 +66,16 @@ def process(self):
msg = "No retest found for '%s'" % sample_id
raise APIError(500, "ValueError: {}".format(msg))
- # Do not allow to modify the sample if not referred
- if api.get_review_status(sample) != "shipped":
+ # Do not allow to modify the sample if not received at reference
+ status = api.get_review_status(sample)
+ if status == "shipped":
+ # TODO Do not allow the modification of 'shipped' samples
+ logger.warn("Please upgrade reference instance to latest!!!. The "
+ "update of samples in 'shipped' statues won't be "
+ "supported in the near future, but only those in "
+ "'received_at_reference' status")
+
+ elif status != "received_at_reference":
# We don't rise an exception here because maybe the sample was
# updated earlier, but the reference lab got a timeout error and
# the remote user is now retrying the notification
diff --git a/src/senaite/referral/profiles/default/metadata.xml b/src/senaite/referral/profiles/default/metadata.xml
index bd38f0d..de9472e 100644
--- a/src/senaite/referral/profiles/default/metadata.xml
+++ b/src/senaite/referral/profiles/default/metadata.xml
@@ -6,11 +6,10 @@
dependencies before installing this add-on own profile.
-->
- 2003
+ 2005
profile-senaite.lims:default
-
diff --git a/src/senaite/referral/remotelab.py b/src/senaite/referral/remotelab.py
index 950334f..59624b8 100644
--- a/src/senaite/referral/remotelab.py
+++ b/src/senaite/referral/remotelab.py
@@ -21,7 +21,6 @@
import math
from bika.lims import api
from bika.lims.interfaces import IAnalysisRequest
-from bika.lims.interfaces import IInternalUse
from bika.lims.utils import format_supsub
from bika.lims.utils.analysis import format_uncertainty
from remotesession import RemoteSession
@@ -191,27 +190,24 @@ def update_analyses(self, sample, timeout=5):
"""
def get_valid_analyses(sample):
- # Sort by id descending to prioritize newest results if retests
+ # Get the analyses from current sample that were requested by the
+ # referring laboratory, sorted by id descending to prioritize
+ # newest results if retests
+ inbound_sample = sample.getInboundSample()
+ services = inbound_sample.getRawServices()
kwargs = {
"full_objects": True,
+ "getServiceUID": services,
"sort_on": "id",
"sort_order": "ascending",
}
- # Exclude old, but valid analyses with same keyword (e.g retests),
+ # exclude old, but valid analyses with same keyword (e.g retests),
# cause we want to update the referring lab with the newest result
analyses = {}
valid = ["verified", "published"]
for analysis in sample.getAnalyses(**kwargs):
- # Skip analyses for internal use
- if IInternalUse.providedBy(analysis):
- continue
-
- # Skip hidden, only interested in final results
- if analysis.getHidden():
- continue
-
# Skip analyses not in a suitable status
if api.get_review_status(analysis) not in valid:
continue
diff --git a/src/senaite/referral/setuphandlers.py b/src/senaite/referral/setuphandlers.py
index f1ab73d..dae8b10 100644
--- a/src/senaite/referral/setuphandlers.py
+++ b/src/senaite/referral/setuphandlers.py
@@ -75,12 +75,24 @@
"transitions": (
"verify",
"invalidate_at_reference",
+ "receive_at_reference",
"reject_at_reference",
"recall_from_shipment"
),
# Sample is read-only
"permissions_copy_from": "invalid",
},
+ "received_at_reference": {
+ "title": "Received at reference lab",
+ "description": "Sample received at reference laboratory",
+ "transitions": (
+ "verify",
+ "reject_at_reference",
+ "invalidate_at_reference",
+ ),
+ # Sample is read-only
+ "permissions_copy_from": "invalid",
+ },
"rejected_at_reference": {
"title": "Rejected at reference lab",
"description": "Sample rejected at reference laboratory",
@@ -106,6 +118,16 @@
"guard_expr": "python:here.guard_handler('ship')",
}
},
+ "receive_at_reference": {
+ "title": "Receive sample (at reference lab)",
+ "new_state": "received_at_reference",
+ "action": "Received at reference lab",
+ "guard": {
+ "guard_permissions": "",
+ "guard_roles": "",
+ "guard_expr": "python:here.guard_handler('receive_at_reference')",
+ }
+ },
"reject_at_reference": {
"title": "Reject sample (at reference lab)",
"new_state": "rejected_at_reference",
diff --git a/src/senaite/referral/upgrade/v01_00_000.zcml b/src/senaite/referral/upgrade/v01_00_000.zcml
index 454804c..b2dc79f 100644
--- a/src/senaite/referral/upgrade/v01_00_000.zcml
+++ b/src/senaite/referral/upgrade/v01_00_000.zcml
@@ -1,7 +1,6 @@
+ xmlns:genericsetup="http://namespaces.zope.org/genericsetup">
+
+
+
+