diff --git a/SAS/TMSS/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
index 710b9cdd942de6a52ed6c40ebd92d774602b61ae..353f7a16ea0eb7c3f5977161162336f3214e675a 100644
--- a/SAS/TMSS/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/src/tmss/tmssapp/models/specification.py
@@ -436,7 +436,8 @@ class CycleQuota(Model):
 
 
 class Project(NamedCommonPK):
-    cycles = ManyToManyField('Cycle', blank=True, related_name='projects', help_text='Cycles to which this project belongs (NULLable).')
+    # todo: cycles should be protected since we have to manually decide to clean up projects with a cycle or keep them without cycle, however, ManyToManyField does not allow for that
+    cycles = ManyToManyField('Cycle', related_name='projects', null=True, help_text='Cycles to which this project belongs (NULLable).')
     priority_rank = FloatField(null=False, help_text='Priority of this project w.r.t. other projects. Projects can interrupt observations of lower-priority projects.') # todo: add if needed: validators=[MinValueValidator(0.0), MaxValueValidator(1.0)]
     trigger_priority = IntegerField(default=1000, help_text='Priority of this project w.r.t. triggers.') # todo: verify meaning and add to help_text: "Triggers with higher priority than this threshold can interrupt observations of projects."
     can_trigger = BooleanField(default=False, help_text='True if this project is allowed to supply observation requests on the fly, possibly interrupting currently running observations (responsive telescope).')
@@ -587,6 +588,19 @@ class SchedulingUnitDraft(NamedCommon):
 
 
 class SchedulingUnitBlueprint(NamedCommon):
+    class Status(Enum):
+        DEFINED = "defined"
+        FINISHED = "finished"
+        CANCELLED = "cancelled"
+        ERROR = "error"
+        OBSERVING = "observing"
+        OBSERVED = "observed"
+        PROCESSING = "processing"
+        PROCESSED = "processed"
+        INGESTING = "ingesting"
+        SCHEDULED = "scheduled"
+        SCHEDULABLE = "schedulable"
+
     requirements_doc = JSONField(help_text='Scheduling and/or quality requirements for this scheduling unit (IMMUTABLE).')
     do_cancel = BooleanField()
     requirements_template = ForeignKey('SchedulingUnitTemplate', on_delete=CASCADE, help_text='Schema used for requirements_doc (IMMUTABLE).')
@@ -657,36 +671,34 @@ class SchedulingUnitBlueprint(NamedCommon):
 
         # Determine status per task_type (unfortunately did not manage with updatable view)
         status_overview_counter = Counter()
-        status_overview_counter_per_type = {type.value:Counter() for type in TaskType.Choices}
-        for tb in self.task_blueprints.prefetch_related('specifications_template').all():
+        status_overview_counter_per_type = {type.value: Counter() for type in TaskType.Choices}
+        for tb in self.task_blueprints.select_related('specifications_template').all():
             status_overview_counter[tb.status] += 1
             status_overview_counter_per_type[tb.specifications_template.type.value][tb.status] += 1
 
         # The actual determination of the SchedulingunitBlueprint status
         if not self._task_graph_instantiated():
-            status = "defined"
+            return SchedulingUnitBlueprint.Status.DEFINED.value
         elif self._all_task_finished(status_overview_counter):
-            status = "finished"
+            return SchedulingUnitBlueprint.Status.FINISHED.value
         elif self._any_task_cancelled(status_overview_counter):
-            status = "cancelled"
+            return SchedulingUnitBlueprint.Status.CANCELLED.value
         elif self._any_task_error(status_overview_counter):
-            status = "error"
+            return SchedulingUnitBlueprint.Status.ERROR.value
         elif self._any_task_started_observed_finished(status_overview_counter):
             if not self._all_observation_task_observed_finished(status_overview_counter_per_type):
-                status = "observing"
+                return SchedulingUnitBlueprint.Status.OBSERVING.value
             elif not self._any_processing_task_started_or_finished(status_overview_counter_per_type):
-                status = "observed"
+                return SchedulingUnitBlueprint.Status.OBSERVED.value
             elif not self._all_processing_tasks_and_observation_tasks_finished(status_overview_counter_per_type):
-                status = "processing"
+                return SchedulingUnitBlueprint.Status.PROCESSING.value
             elif not self._any_ingest_task_started(status_overview_counter_per_type):
-                status = "processed"
+                return SchedulingUnitBlueprint.Status.PROCESSED.value
             else:
-                status = "ingesting"
+                return SchedulingUnitBlueprint.Status.INGESTING.value
         elif self._any_task_scheduled(status_overview_counter):
-            status = "scheduled"
-        else:
-            status = "schedulable"
-        return status
+            return SchedulingUnitBlueprint.Status.SCHEDULED.value
+        return SchedulingUnitBlueprint.Status.SCHEDULABLE.value
 
     def _task_graph_instantiated(self):
         return self._get_total_nbr_tasks() > 0
@@ -734,15 +746,15 @@ class SchedulingUnitBlueprint(NamedCommon):
 
     @staticmethod
     def _get_total_nbr_observation_tasks(status_overview_counter_per_type):
-        return len(status_overview_counter_per_type[TaskType.Choices.OBSERVATION.value].elements())
+        return len(tuple(status_overview_counter_per_type[TaskType.Choices.OBSERVATION.value].elements()))
 
     @staticmethod
     def _get_total_nbr_processing_tasks(status_overview_counter_per_type):
-        return len(status_overview_counter_per_type[TaskType.Choices.PIPELINE.value].elements())
+        return len(tuple(status_overview_counter_per_type[TaskType.Choices.PIPELINE.value].elements()))
 
     @staticmethod
     def _get_total_nbr_ingest_tasks(status_overview_counter_per_type):
-        return len(status_overview_counter_per_type[TaskType.Choices.INGEST.value].elements())
+        return len(tuple(status_overview_counter_per_type[TaskType.Choices.INGEST.value].elements()))
 
 
 class TaskDraft(NamedCommon):
@@ -968,27 +980,28 @@ class TaskBlueprint(NamedCommon):
         if nr_of_subtasks == 0:
             return "defined"
 
-        if len([s for s in subtasks if s['state'] in ('defining','defined')]) == nr_of_subtasks:
+        if any(s for s in subtasks if s['state'] == 'defining'):
             return "defined"
 
         if len([s for s in subtasks if s['state'] == 'finished']) == nr_of_subtasks:
                 return "finished"
 
-        if any(s for s in subtasks if s['state'] == 'scheduled'):
-            return "scheduled"
-
         if any(s for s in subtasks if s['state'] in ('cancelling', 'cancelled')):
             return "cancelled"
 
         if any(s for s in subtasks if s['state'] == 'error'):
             return "error"
 
-        if any(s for s in subtasks if s['specifications_template__type_id'] == 'observation' and s['state'] in ('cancelling', 'cancelled')):
+        observations = [s for s in subtasks if s['specifications_template__type_id'] == 'observation']
+        if observations and all(obs and obs['state'] in ('finishing', 'finished') for obs in observations):
             return "observed"
 
         if any(s for s in subtasks if s['state'] in ('starting','started','queueing','queued','finishing','finished')):
             return "started"
 
+        if any(s for s in subtasks if s['state'] == 'scheduled'):
+            return "scheduled"
+
         return "schedulable"
 
 
diff --git a/SAS/TMSS/test/t_tasks.py b/SAS/TMSS/test/t_tasks.py
index 1b4aefc9e56a1dccccb7fdbf92abac85068ace38..6bca6f3f1bc03fac0d59777fb195b5a50230921c 100755
--- a/SAS/TMSS/test/t_tasks.py
+++ b/SAS/TMSS/test/t_tasks.py
@@ -475,7 +475,7 @@ class SchedulingUnitBlueprintStateTest(unittest.TestCase):
             subtask.save()
         # Check task.status as precondition
         self.assertEqual(task_state, task.status,
-                         "PRECONDITION DOES NOT MET. Expect %s task to be equal to %s (but is %s)" % (
+                         "INCORRECT PRECONDITION. Expected %s task to have status=%s, but actual status=%s)" % (
                          task_type, task_state, task.status))
 
     def test_state_with_no_tasks(self):
diff --git a/SAS/TMSS/test/tmss_test_data_rest.py b/SAS/TMSS/test/tmss_test_data_rest.py
index e0e121edb5c823c74e8619fd8e59c131bebc11de..82f35cf01ae41d98230365c02cc85fbdc0ec8908 100644
--- a/SAS/TMSS/test/tmss_test_data_rest.py
+++ b/SAS/TMSS/test/tmss_test_data_rest.py
@@ -199,7 +199,7 @@ class TMSSRESTTestDataCreator():
                 "trigger_priority": 1000,
                 "can_trigger": False,
                 "private_data": True,
-                "cycles": [],
+                "cycles": [self.post_data_and_get_url(self.Cycle(), '/cycle')],
                 "archive_subdirectory": 'my_project/'}
 
     def ResourceType(self, description="my resource_type description"):