From 865ee4a15e38727395dd235b80685588e659d6c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jordi=20Puiggen=C3=A9?= <jp@naralabs.com>
Date: Wed, 15 Nov 2023 18:08:12 +0100
Subject: [PATCH] Added upgrade step to fix samples in registered status

---
 .../core/profiles/default/metadata.xml        |  2 +-
 src/senaite/core/upgrade/v02_05_000.py        | 70 ++++++++++++++++++-
 src/senaite/core/upgrade/v02_05_000.zcml      |  8 +++
 3 files changed, 77 insertions(+), 3 deletions(-)

diff --git a/src/senaite/core/profiles/default/metadata.xml b/src/senaite/core/profiles/default/metadata.xml
index f61f429289..c7cbbb94f2 100644
--- a/src/senaite/core/profiles/default/metadata.xml
+++ b/src/senaite/core/profiles/default/metadata.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0"?>
 <metadata>
-  <version>2520</version>
+  <version>2521</version>
   <dependencies>
     <dependency>profile-Products.ATContentTypes:base</dependency>
     <dependency>profile-Products.CMFEditions:CMFEditions</dependency>
diff --git a/src/senaite/core/upgrade/v02_05_000.py b/src/senaite/core/upgrade/v02_05_000.py
index 30c8b6adcd..2a4f6b5eff 100644
--- a/src/senaite/core/upgrade/v02_05_000.py
+++ b/src/senaite/core/upgrade/v02_05_000.py
@@ -21,7 +21,10 @@
 import transaction
 from Acquisition import aq_base
 from bika.lims import api
+from bika.lims.interfaces import IReceived
+from bika.lims.utils import changeWorkflowState
 from senaite.core import logger
+from senaite.core.api import security
 from senaite.core.api.catalog import add_index
 from senaite.core.api.catalog import del_column
 from senaite.core.api.catalog import del_index
@@ -34,17 +37,21 @@
 from senaite.core.catalog import SETUP_CATALOG
 from senaite.core.config import PROJECTNAME as product
 from senaite.core.permissions import ManageBika
+from senaite.core.permissions import TransitionReceiveSample
 from senaite.core.registry import get_registry_record
-from senaite.core.setuphandlers import CATALOG_MAPPINGS
 from senaite.core.setuphandlers import _run_import_step
 from senaite.core.setuphandlers import add_dexterity_items
+from senaite.core.setuphandlers import CATALOG_MAPPINGS
 from senaite.core.setuphandlers import setup_auditlog_catalog_mappings
 from senaite.core.setuphandlers import setup_catalog_mappings
 from senaite.core.setuphandlers import setup_core_catalogs
 from senaite.core.setuphandlers import setup_portal_catalog
 from senaite.core.upgrade import upgradestep
-from senaite.core.upgrade.utils import UpgradeUtils
 from senaite.core.upgrade.utils import uncatalog_brain
+from senaite.core.upgrade.utils import UpgradeUtils
+from senaite.core.workflow import ANALYSIS_WORKFLOW
+from senaite.core.workflow import SAMPLE_WORKFLOW
+from zope.interface import alsoProvides
 
 PORTAL_CATALOG = "portal_catalog"
 
@@ -482,3 +489,62 @@ def reindex_control_analyses(tool):
         obj._p_deactivate()
 
     logger.info("Reindexing control analyses [DONE]")
+
+
+def fix_samples_registered(tool):
+    """Transitions the samples in "registered" status to a suitable status,
+    either "sample_due", "recieved", or "to_be_sampled"
+    """
+    logger.info("Fixing samples in 'registered' status ...")
+
+    setup = api.get_setup()
+    auto_receive = setup.getAutoreceiveSamples()
+    query = {"review_state": "sample_registered"}
+    brains = api.search(query, SAMPLE_CATALOG)
+    total = len(brains)
+    for num, brain in enumerate(brains):
+        if num and num % 100 == 0:
+            logger.info("Fixing samples in 'registered' status: {}/{}"
+                        .format(num, total))
+
+        sample = api.get_object(brain)
+
+        creator = sample.Creator()
+        if sample.getSamplingRequired():
+            # sample has not been collected yet
+            changeWorkflowState(sample, SAMPLE_WORKFLOW, "to_be_sampled",
+                                actor=creator, action="to_be_sampled")
+            sample._p_deactivate()
+            continue
+
+        if auto_receive:
+            user = security.get_user(sample.creator())
+            if user.has_permission(TransitionReceiveSample, sample):
+                # Change status to sample_received
+                changeWorkflowState(sample, SAMPLE_WORKFLOW, "sample_received",
+                                    actor=creator, action="receive")
+
+                # Mark the secondary as received
+                alsoProvides(sample, IReceived)
+
+                # Set same received date as created
+                created = api.get_creation_date(sample)
+                sample.setDateReceived(created)
+
+                # Initialize analyses
+                for obj in sample.objectValues():
+                    if obj.portal_type != "Analysis":
+                        continue
+                    if api.get_review_status(obj) != "registered":
+                        continue
+                    changeWorkflowState(obj, ANALYSIS_WORKFLOW, "unassigned",
+                                        actor=creator, action="initialize")
+                sample._p_deactivate()
+                continue
+
+        # sample_due is the default initial status of the sample
+        changeWorkflowState(sample, SAMPLE_WORKFLOW, "sample_due",
+                            actor=creator, action="no_sampling_workflow")
+        sample._p_deactivate()
+
+    logger.info("Fixing samples in 'registered' status [DONE]")
diff --git a/src/senaite/core/upgrade/v02_05_000.zcml b/src/senaite/core/upgrade/v02_05_000.zcml
index 39704dcfe0..b8c0655395 100644
--- a/src/senaite/core/upgrade/v02_05_000.zcml
+++ b/src/senaite/core/upgrade/v02_05_000.zcml
@@ -3,6 +3,14 @@
     xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
     i18n_domain="senaite.core">
 
+  <genericsetup:upgradeStep
+      title="SENAITE.CORE 2.5.0: Fix samples in registered status"
+      description="Fixes the status of samples in registere status"
+      source="2520"
+      destination="2521"
+      handler=".v02_05_000.fix_samples_registered"
+      profile="senaite.core:default"/>
+
   <genericsetup:upgradeStep
       title="SENAITE.CORE 2.5.0: Import Workflow"
       description="Update Managed Permissions of Sample Workflow"