diff --git a/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py b/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py
index 3c1277412b49bbeafaa15f05f58014bbb88c3dc7..4b46cc74036b44625b0df5d88c1d03d07c6c8449 100644
--- a/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py
+++ b/SAS/TMSS/backend/services/scheduling/lib/constraints/__init__.py
@@ -41,6 +41,7 @@ from typing import NamedTuple
 
 from lofar.sas.tmss.tmss.tmssapp import models
 from lofar.sas.tmss.tmss.exceptions import *
+from lofar.sas.tmss.tmss.tmssapp.reservations import get_active_station_reservations_in_timewindow
 
 ################## main data struct and methods ##################
 
@@ -238,23 +239,7 @@ def get_min_earliest_possible_start_time(scheduling_units: [models.SchedulingUni
         return lower_bound
 
 
-def get_active_station_reservations_in_timewindow(lower_bound, upper_bound):
-    """
-    Retrieve a list of all active stations reservations, which are reserved between a timewindow
-    TODO: use filter like filter(start_time__lte=upper) filter(stop_time__gte=lower)
-    BUT can not use filter of property, so find another 'fast' solution (no loop), therefore stop_time has to move to
-    to the model. See TMSS-668
-    Also move this part to other module
-    """
-    lst_active_station_reservations = []
-    reservations = models.Reservation.objects.all()
-    for station_reservation in reservations:
-        if (station_reservation.duration is not None and \
-                station_reservation.start_time < upper_bound and station_reservation.stop_time > lower_bound) \
-           or (station_reservation.duration is None and station_reservation.start_time < upper_bound):
-            lst_active_station_reservations += station_reservation.specifications_doc["resources"]["stations"]
-
-    return lst_active_station_reservations
+
 
 
 def can_run_within_station_reservations(scheduling_unit: models.SchedulingUnitBlueprint) -> bool:
diff --git a/SAS/TMSS/backend/services/scheduling/lib/constraints/template_constraints_v1.py b/SAS/TMSS/backend/services/scheduling/lib/constraints/template_constraints_v1.py
index 2b68de96458c95d1cd2e068f7916dc9851ff3a45..550efab2b7be2627304ce24c24f4cf95cd5cb9c0 100644
--- a/SAS/TMSS/backend/services/scheduling/lib/constraints/template_constraints_v1.py
+++ b/SAS/TMSS/backend/services/scheduling/lib/constraints/template_constraints_v1.py
@@ -283,7 +283,9 @@ def can_run_anywhere_within_timewindow_with_sky_constraints(scheduling_unit: mod
                     target_rise_and_set_times = coordinates_timestamps_and_stations_to_target_rise_and_set(angle1=angle1, angle2=angle2, direction_type=direction_type, timestamps=timestamps, stations=tuple(stations), angle_to_horizon=min_elevation)
                     for station, times in target_rise_and_set_times.items():
                         for i in range(len(timestamps)):
-                            if not (timestamps[i] > times[0]['rise'] and timestamps[i] < times[0]['set']):
+                            if times[0]['always_above_horizon']:
+                                continue
+                            if times[0]['always_below_horizon'] or not (timestamps[i] > times[0]['rise'] and timestamps[i] < times[0]['set']):
                                 if task['specifications_template'] == 'calibrator observation':
                                     logger.info('min_calibrator_elevation=%s constraint is not met at timestamp=%s' % (min_elevation.rad, timestamps[i]))
                                 else:
diff --git a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
index 45efbf8ae32a51b02d26139010d6f5c125fc2334..e8fadb2c6085117007f7913c8ecee0fa3808b434 100755
--- a/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
+++ b/SAS/TMSS/backend/services/scheduling/test/t_dynamic_scheduling.py
@@ -735,8 +735,11 @@ class TestSkyConstraints(unittest.TestCase):
         self.distance_mock.return_value = self.distance_data
         self.addCleanup(self.distance_patcher.stop)
         
-        self.target_rise_and_set_data = {"CS002": [{"rise": datetime(2020, 1, 1, 8, 0, 0), "set": datetime(2020, 1, 1, 12, 30, 0)},
-                                                   {"rise": datetime(2020, 1, 1, 8, 0, 0), "set": datetime(2020, 1, 1, 12, 30, 0)}]}
+        self.target_rise_and_set_data = {"CS002": [{"rise": datetime(2020, 1, 1, 8, 0, 0), "set": datetime(2020, 1, 1, 12, 30, 0), "always_above_horizon": False, "always_below_horizon": False},
+                                                   {"rise": datetime(2020, 1, 1, 8, 0, 0), "set": datetime(2020, 1, 1, 12, 30, 0), "always_above_horizon": False, "always_below_horizon": False}]}
+        self.target_rise_and_set_data_always_above = {"CS002": [{"rise": None, "set": None, "always_above_horizon": True, "always_below_horizon": False}]}
+        self.target_rise_and_set_data_always_below = {"CS002": [{"rise": None, "set": None, "always_above_horizon": False, "always_below_horizon": True}]}
+        
         self.target_rise_and_set_patcher = mock.patch('lofar.sas.tmss.services.scheduling.constraints.template_constraints_v1.coordinates_timestamps_and_stations_to_target_rise_and_set')
         self.target_rise_and_set_mock = self.target_rise_and_set_patcher.start()
         self.target_rise_and_set_mock.return_value = self.target_rise_and_set_data
@@ -760,21 +763,45 @@ class TestSkyConstraints(unittest.TestCase):
         
     # min_target_elevation
 
-    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_constraint_returns_true_when_met(self):
+    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_constraint_returns_true(self):
+        self.target_rise_and_set_mock.return_value = self.target_rise_and_set_data
+
         self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['sky'] = {'min_target_elevation': 0.1}
         self.scheduling_unit_blueprint.save()
-        timestamp = datetime(2020, 1, 1, 10, 0, 0)
+        timestamp = datetime(2020, 1, 1, 10, 0, 0)  # target sets after obs ends (mocked response)
         returned_value = tc1.can_run_anywhere_within_timewindow_with_sky_constraints(self.scheduling_unit_blueprint, timestamp, timestamp + timedelta(seconds=self.obs_duration))
         self.assertTrue(returned_value)
 
-    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_constraint_returns_false_when_not_met(self):
-        self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['sky'] = {'min_target_elevation': 0.2}
+    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_when_target_always_above_returns_true(self):
+        self.target_rise_and_set_mock.return_value = self.target_rise_and_set_data_always_above
+
+        self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['sky'] = {'min_target_elevation': 0.1}
         self.scheduling_unit_blueprint.save()
-        timestamp = datetime(2020, 1, 1, 11, 0, 0)
+        timestamp = datetime(2020, 1, 1, 10, 0, 0)  # target is always up (mocked response)
+        returned_value = tc1.can_run_anywhere_within_timewindow_with_sky_constraints(self.scheduling_unit_blueprint, timestamp, timestamp + timedelta(seconds=self.obs_duration))
+        self.assertTrue(returned_value)
+
+    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_constraint_returns_false(self):
+        self.target_rise_and_set_mock.return_value = self.target_rise_and_set_data
+
+        self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['sky'] = {'min_target_elevation': 0.1}
+        self.scheduling_unit_blueprint.save()
+        timestamp = datetime(2020, 1, 1, 11, 0, 0)  # target sets before obs ends (mocked response)
+        returned_value = tc1.can_run_anywhere_within_timewindow_with_sky_constraints(self.scheduling_unit_blueprint, timestamp, timestamp + timedelta(seconds=self.obs_duration))
+        self.assertFalse(returned_value)
+
+    def test_can_run_anywhere_within_timewindow_with_sky_constraints_with_min_target_elevation_when_target_is_always_below_returns_false(self):
+        self.target_rise_and_set_mock.return_value = self.target_rise_and_set_data_always_below
+
+        self.scheduling_unit_blueprint.draft.scheduling_constraints_doc['sky'] = {'min_target_elevation': 0.1}
+        self.scheduling_unit_blueprint.save()
+        timestamp = datetime(2020, 1, 1, 10, 0, 0)  # target is never up (mocked response)
         returned_value = tc1.can_run_anywhere_within_timewindow_with_sky_constraints(self.scheduling_unit_blueprint, timestamp, timestamp + timedelta(seconds=self.obs_duration))
         self.assertFalse(returned_value)
 
 
+
+
 class TestTimeConstraints(TestCase):
     """
     Tests for the time constraint checkers used in dynamic scheduling with different boundaries
@@ -1035,9 +1062,10 @@ class TestReservedStations(unittest.TestCase):
     """
 
     @staticmethod
-    def create_station_reservation(additional_name, lst_stations, start_time=datetime(2100, 1, 1, 0, 0, 0), duration=86400):
+    def create_station_reservation(additional_name, lst_stations, start_time=datetime(2100, 1, 1, 0, 0, 0),
+                                                                   stop_time=datetime(2100, 1, 2, 0, 0, 0)):
         """
-        Create a station reservation with given list of stations, start_time and duration (optional)
+        Create a station reservation with given list of stations, start_time and stop_time (optional)
         Default duration is 24 hours (defined in seconds)
         """
         reservation_template = models.ReservationTemplate.objects.get(name="resource reservation")
@@ -1048,7 +1076,7 @@ class TestReservedStations(unittest.TestCase):
                                    specifications_template=reservation_template,
                                    specifications_doc=reservation_template_spec,
                                    start_time=start_time,
-                                   duration=duration)
+                                   stop_time=stop_time)
         return res
 
     def setUp(self) -> None:
@@ -1070,8 +1098,7 @@ class TestReservedStations(unittest.TestCase):
         Set (1) reservation start_time > SUB start_time and reservation stop_time > SUB stop_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
-        reservation_stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
         station_reservation.save()
 
     def set_2_reservation_start_time_lt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
@@ -1079,8 +1106,7 @@ class TestReservedStations(unittest.TestCase):
         Set (2) reservation start_time < SUB start_time and reservation stop_time < SUB stop_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        reservation_stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
         station_reservation.save()
 
     def set_3_reservation_start_time_gt_sub_start_time_and_stop_time_lt_sub_stop_time(self, station_reservation):
@@ -1088,8 +1114,7 @@ class TestReservedStations(unittest.TestCase):
         Set (3) reservation start_time > SUB start_time and reservation stop_time < SUB stop_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
-        reservation_stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time - timedelta(minutes=5)
         station_reservation.save()
 
     def set_4_reservation_start_time_lt_sub_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
@@ -1097,8 +1122,7 @@ class TestReservedStations(unittest.TestCase):
         Set (4) reservation start_time < SUB start_time and reservation stop_time > SUB stop_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        reservation_stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
         station_reservation.save()
 
     def set_5_reservation_start_time_and_stop_time_lt_sub_start_time(self, station_reservation):
@@ -1106,8 +1130,7 @@ class TestReservedStations(unittest.TestCase):
         Set (5) reservation start_time and reservation stop_time < SUB start_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=60)
-        reservation_stop_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.start_time - timedelta(minutes=5)
         station_reservation.save()
 
     def set_6_reservation_start_time_and_stop_time_gt_sub_stop_time(self, station_reservation):
@@ -1115,8 +1138,7 @@ class TestReservedStations(unittest.TestCase):
         Set (6) reservation start_time and reservation stop_time > SUB stop_time
         """
         station_reservation.start_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=5)
-        reservation_stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=65)
-        station_reservation.duration = (reservation_stop_time - station_reservation.start_time).total_seconds()
+        station_reservation.stop_time = self.scheduling_unit_blueprint.stop_time + timedelta(minutes=65)
         station_reservation.save()
 
     def update_station_groups_of_scheduling_unit_blueprint(self):
@@ -1234,7 +1256,7 @@ class TestReservedStations(unittest.TestCase):
         Test with different reservation start time and NO stop_time
         start_time after SUB stop_time 'can run' all others 'can NOT run'
         """
-        reservation_two_no_duration = self.create_station_reservation("Two-NoDuration", ["CS001", "CS002"], duration=None)
+        reservation_two_no_duration = self.create_station_reservation("Two-NoDuration", ["CS001", "CS002"], stop_time=None)
         # reservation start_time > SUB start_time and < SUB stop_time
         reservation_two_no_duration.start_time = self.scheduling_unit_blueprint.start_time + timedelta(minutes=5)
         reservation_two_no_duration.save()
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/CMakeLists.txt b/SAS/TMSS/backend/src/tmss/tmssapp/CMakeLists.txt
index 58c545f7ed434d8c05064e1fad48ebf0c93d821a..456c9935792dbfd31873e09098211a46c046828d 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/CMakeLists.txt
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/CMakeLists.txt
@@ -10,6 +10,7 @@ set(_py_files
     subtasks.py
     tasks.py
     conversions.py
+    reservations.py
     )
 
 python_install(${_py_files}
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py b/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
index ae926e172f4a39a4ff77a442346fbf25d4505e35..3c0e184ce79ac8e697043dcf8ced5dceba3bf1eb 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/conversions.py
@@ -126,9 +126,10 @@ def coordinates_timestamps_and_stations_to_target_rise_and_set(angle1: float, an
     :param stations: tuple of station names, e.g. ("CS002",)
     :param angle_to_horizon: the angle between horizon and given coordinates for which rise and set times are returned
     :return A dict that maps station names to a list of dicts with rise and set times for each requested date.
+            If rise and set are None, the target is always above or below horizon, and the respective boolean is True.
         E.g.
-        {"CS002": [{"rise": datetime(2020, 1, 1, 4, 0, 0), "set": datetime(2020, 1, 1, 11, 0, 0)},
-                   {"rise": datetime(2020, 1, 2, 4, 0, 0), "set": datetime(2020, 1, 2, 11, 0, 0)}]
+        {"CS002": [{"rise": datetime(2020, 1, 1, 4, 0, 0), "set": datetime(2020, 1, 1, 11, 0, 0), "always_above_horizon": False, "always_below_horizon": False},
+                   {"rise": datetime(2020, 1, 2, 4, 0, 0), "set": datetime(2020, 1, 2, 11, 0, 0), "always_above_horizon": False, "always_below_horizon": False}]
         }
     """
     if direction_type == "J2000":
@@ -140,10 +141,29 @@ def coordinates_timestamps_and_stations_to_target_rise_and_set(angle1: float, an
         for timestamp in timestamps:
             # todo: this can probably be made faster by moving the following logic to an own function with single station/timestamp as input and putting the lru_cache on there.
             observer = create_astroplan_observer_for_station(station)
-            target_set = observer.target_set_time(target=coord, time=Time(timestamp), horizon=angle_to_horizon, which='next', n_grid_points=TARGET_SET_RISE_PRECISION)
-            target_rise = observer.target_rise_time(target=coord, time=Time(target_set), horizon=angle_to_horizon, which='previous', n_grid_points=TARGET_SET_RISE_PRECISION)
+            try:
+                target_set = observer.target_set_time(target=coord, time=Time(timestamp), horizon=angle_to_horizon, which='next', n_grid_points=TARGET_SET_RISE_PRECISION)
+                target_rise = observer.target_rise_time(target=coord, time=Time(target_set), horizon=angle_to_horizon, which='previous', n_grid_points=TARGET_SET_RISE_PRECISION)
+                return_dict.setdefault(station, []).append(
+                    {"rise": target_rise.to_datetime(),
+                     "set": target_set.to_datetime(),
+                     "always_above_horizon": False,
+                     "always_below_horizon": False})
+            except TypeError as e:
+                if "numpy.float64" in str(e):
+                    # Note: when the target is always above or below horizon, astroplan excepts with the not very
+                    #  meaningful error: 'numpy.float64' object does not support item assignment
+                    # Determine whether the target is always above or below horizon so that we can return some useful
+                    # additional info, e.g. for scheduling purposes.
+                    is_up = observer.target_is_up(target=coord, time=Time(timestamp), horizon=angle_to_horizon)
+                    return_dict.setdefault(station, []).append(
+                        {"rise": None,
+                         "set": None,
+                         "always_above_horizon": is_up,
+                         "always_below_horizon": not is_up})
+                else:
+                    raise
 
-            return_dict.setdefault(station, []).append({"rise": target_rise.to_datetime(), "set": target_set.to_datetime()})
 
     return return_dict
 
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0001_initial.py b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0001_initial.py
index bc33c5696ec718a0c662eb600e2e28a9091913d0..d4095c88c950c3c628f52c4a477d6389e9dd2699 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0001_initial.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/migrations/0001_initial.py
@@ -453,7 +453,7 @@ class Migration(migrations.Migration):
                 ('name', models.CharField(help_text='Human-readable name of this object.', max_length=128)),
                 ('description', models.CharField(help_text='Short description for this reservation, used in overviews', max_length=255)),
                 ('start_time', models.DateTimeField(help_text='Start of this reservation.')),
-                ('duration', models.IntegerField(help_text='Duration of this reservation (in seconds). If null, then this reservation is indefinitely.', null=True)),
+                ('stop_time', models.DateTimeField(help_text='Stop time of this reservation. If null, then this reservation is indefinitely.', null=True)),
                 ('specifications_doc', django.contrib.postgres.fields.jsonb.JSONField(help_text='Properties of this reservation')),
             ],
             options={
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
index b85c8621f279d382f317ad59870267b703ffefe6..9645087251cecf7f2b6c5eddd11779ee123f5f37 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/models/specification.py
@@ -328,7 +328,7 @@ class ProjectQuota(Model):
 
 
 class ProjectQuotaArchiveLocation(Model):
-    project_quota = ForeignKey('ProjectQuota', null=False, related_name="project_quota", on_delete=PROTECT, help_text='Project to wich this quota belongs.')
+    project_quota = ForeignKey('ProjectQuota', null=False, related_name="project_quota_archive_location", on_delete=PROTECT, help_text='The ProjectQuota for this archive location')
     archive_location = ForeignKey('Filesystem', null=False, on_delete=PROTECT, help_text='Location of an archive LTA cluster.')
 
     def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
@@ -1060,18 +1060,18 @@ class Reservation(NamedCommon):
     project = ForeignKey('Project', null=True, related_name='reservations', on_delete=CASCADE, help_text='Reservation will be accounted for this project.')
     description = CharField(max_length=255, help_text='Short description for this reservation, used in overviews')
     start_time = DateTimeField(help_text='Start of this reservation.')
-    duration = IntegerField(null=True, help_text='Duration of this reservation (in seconds). If null, then this reservation is indefinitely.')
+    stop_time = DateTimeField(null=True, help_text='Stop of this reservation. If null, then this reservation is indefinitely.')
     specifications_doc = JSONField(help_text='Properties of this reservation')
     specifications_template = ForeignKey('ReservationTemplate', on_delete=CASCADE, help_text='Schema used for specifications_doc.')
 
-    # TODO add stop_time to the model and calculate either duration or stop_time (in serializer)
-    # See TMSS-668
     @property
-    def stop_time(self) -> datetime.datetime:
-        '''The stop_time based on start_time+duration if duration is known, else None'''
-        if self.duration:
-            return self.start_time + datetime.timedelta(seconds=self.duration)
-        return None
+    def duration(self) -> int:
+        '''return the overall duration (in seconds) of this task, if stop_time in None than duration ia also None
+        '''
+        if self.stop_time:
+            return (self.stop_time - self.start_time).total_seconds()
+        else:
+            return None
 
     def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
         annotate_validate_add_defaults_to_doc_using_template(self, 'specifications_doc', 'specifications_template')
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/populate.py b/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
index 25cb33a8e3f4f580c3824bc60290cc647090ab78..55632a06799b3933e9007e1e76094a545c1bf42e 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/populate.py
@@ -136,36 +136,158 @@ def populate_test_data():
 
 
 def populate_cycles(apps, schema_editor):
-    for nr in range(0, 18):
+    #  Cycle 0 deviates from any patterns
+    cycle = models.Cycle.objects.create(name="Cycle 00",
+                                        description="Lofar Cycle 0",
+                                        start=datetime(2013, 2, 11, 0, 0, 0, 0, tzinfo=timezone.utc),
+                                        stop=datetime(2013, 11, 14, 0, 0, 0, 0, tzinfo=timezone.utc))
+
+    models.CycleQuota.objects.bulk_create([models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time"),
+                                                             value=0.8 * cycle.duration.total_seconds()),
+                                           # rough guess. 80% of total time available for observing
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="CEP Processing Time"),
+                                                             value=0.8 * cycle.duration.total_seconds()),
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(name="LTA Storage"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Support Time"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time Commissioning"),
+                                                             value=0.05 * cycle.duration.total_seconds()),
+                                           # rough guess. 5% of total time available for observing
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time prio A"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time prio B"),
+                                                             value=0)  # needs to be filled in by user (SOS)
+                                           ])
+
+    #  Cycles 1-10 follow the same pattern
+    for nr in range(1, 11):
         cycle = models.Cycle.objects.create(name="Cycle %02d" % nr,
                                             description="Lofar Cycle %s" % nr,
-                                            start=datetime(2013+nr//2, 6 if nr%2==0 else 11, 1, 0, 0, 0, 0, tzinfo=timezone.utc),
-                                            stop=datetime(2013+(nr+1)//2, 6 if nr%2==1 else 11, 1, 0, 0, 0, 0, tzinfo=timezone.utc))
+                                            start=datetime(2013+nr//2, 5 if nr%2==0 else 11, 15, 0, 0, 0, 0, tzinfo=timezone.utc),
+                                            stop=datetime(2013+(nr+1)//2, 5 if nr%2==1 else 11, 14, 0, 0, 0, 0, tzinfo=timezone.utc))
 
         models.CycleQuota.objects.bulk_create([models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="observing_time"),
+                                                                 resource_type=ResourceType.objects.get(name="LOFAR Observing Time"),
                                                                  value=0.8*cycle.duration.total_seconds()), # rough guess. 80% of total time available for observing
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="cep_processing_time"),
+                                                                 resource_type=ResourceType.objects.get(name="CEP Processing Time"),
                                                                  value=0.8*cycle.duration.total_seconds()),
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="lta_storage"),
+                                                                 resource_type=ResourceType.objects.get(name="LTA Storage"),
                                                                  value=0), # needs to be filled in by user (SOS)
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="support_time"),
+                                                                 resource_type=ResourceType.objects.get(name="LOFAR Support Time"),
                                                                  value=0),  # needs to be filled in by user (SOS)
 
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="observing_time_commissioning"),
+                                                                 resource_type=ResourceType.objects.get(name="LOFAR Observing Time Commissioning"),
                                                                  value=0.05*cycle.duration.total_seconds()), # rough guess. 5% of total time available for observing
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="observing_time_prio_a"),
+                                                                 resource_type=ResourceType.objects.get(name="LOFAR Observing Time prio A"),
                                                                  value=0), # needs to be filled in by user (SOS)
                                                models.CycleQuota(cycle=cycle,
-                                                                 resource_type=ResourceType.objects.get(name="observing_time_prio_b"),
+                                                                 resource_type=ResourceType.objects.get(name="LOFAR Observing Time prio B"),
                                                                  value=0) # needs to be filled in by user (SOS)
                                                ])
 
+    #  Cycle 11 deviates from any patterns
+    cycle = models.Cycle.objects.create(name="Cycle 11",
+                                        description="Lofar Cycle 11",
+                                        start=datetime(2018, 11, 15, 0, 0, 0, 0, tzinfo=timezone.utc),
+                                        stop=datetime(2019, 5, 31, 0, 0, 0, 0, tzinfo=timezone.utc))
+
+    models.CycleQuota.objects.bulk_create([models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time"),
+                                                             value=0.8 * cycle.duration.total_seconds()),
+                                           # rough guess. 80% of total time available for observing
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="CEP Processing Time"),
+                                                             value=0.8 * cycle.duration.total_seconds()),
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LTA Storage"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Support Time"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time Commissioning"),
+                                                             value=0.05 * cycle.duration.total_seconds()),
+                                           # rough guess. 5% of total time available for observing
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time prio A"),
+                                                             value=0),  # needs to be filled in by user (SOS)
+                                           models.CycleQuota(cycle=cycle,
+                                                             resource_type=ResourceType.objects.get(
+                                                                 name="LOFAR Observing Time prio B"),
+                                                             value=0)  # needs to be filled in by user (SOS)
+                                           ])
+
+    #  Cycles 12-19 follow the same pattern
+    for nr in range(12, 20):
+        cycle = models.Cycle.objects.create(name="Cycle %02d" % nr,
+                                            description="Lofar Cycle %s" % nr,
+                                            start=datetime(2013 + nr // 2, 6 if nr % 2 == 0 else 12, 1, 0, 0, 0, 0,
+                                                           tzinfo=timezone.utc),
+                                            stop=datetime(2013 + (nr + 1) // 2, 5 if nr % 2 == 1 else 11,
+                                                          30 if nr % 2 == 0 else 31, 0, 0,
+                                                          0, 0, tzinfo=timezone.utc))
+
+        models.CycleQuota.objects.bulk_create([models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LOFAR Observing Time"),
+                                                                 value=0.8 * cycle.duration.total_seconds()),
+                                               # rough guess. 80% of total time available for observing
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="CEP Processing Time"),
+                                                                 value=0.8 * cycle.duration.total_seconds()),
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LTA Storage"),
+                                                                 value=0),  # needs to be filled in by user (SOS)
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LOFAR Support Time"),
+                                                                 value=0),  # needs to be filled in by user (SOS)
+
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LOFAR Observing Time Commissioning"),
+                                                                 value=0.05 * cycle.duration.total_seconds()),
+                                               # rough guess. 5% of total time available for observing
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LOFAR Observing Time prio A"),
+                                                                 value=0),  # needs to be filled in by user (SOS)
+                                               models.CycleQuota(cycle=cycle,
+                                                                 resource_type=ResourceType.objects.get(
+                                                                     name="LOFAR Observing Time prio B"),
+                                                                 value=0)  # needs to be filled in by user (SOS)
+                                               ])
+
+
 def populate_projects(apps, schema_editor):
     from lofar.sas.tmss.test.tmss_test_data_django_models import SchedulingSet_test_data
 
@@ -184,7 +306,7 @@ def populate_projects(apps, schema_editor):
         # for convenience, create a schedulingset for each project
         models.SchedulingSet.objects.create(**SchedulingSet_test_data(name="Test Scheduling Set", project=tmss_project))
 
-        project_quota = ProjectQuota.objects.create(project=tmss_project, value=1e12, resource_type=ResourceType.objects.get(name="lta_storage"))
+        project_quota = ProjectQuota.objects.create(project=tmss_project, value=1e12, resource_type=ResourceType.objects.get(name="LTA Storage"))
         sara_fs = Filesystem.objects.get(name="Lofar Storage (SARA)")
         models.ProjectQuotaArchiveLocation.objects.create(project_quota=project_quota, archive_location=sara_fs)
 
@@ -194,18 +316,7 @@ def populate_resources(apps, schema_editor):
     time_q = Quantity.objects.get(value=Quantity.Choices.TIME.value)
     number_q = Quantity.objects.get(value=Quantity.Choices.NUMBER.value)
 
-    ResourceType.objects.bulk_create([ResourceType(name="lta_storage", description="Amount of storage in the LTA (in bytes)", quantity=bytes_q),
-                                      ResourceType(name="cep_storage", description="Amount of storage on the CEP processing cluster (in bytes)", quantity=bytes_q),
-                                      ResourceType(name="cep_processing_time", description="Processing time on the CEP processing cluster (in seconds)", quantity=time_q),
-                                      ResourceType(name="observing_time", description="Observing time (in seconds)", quantity=time_q),
-                                      ResourceType(name="observing_time_prio_a", description="Observing time with priority A (in seconds)", quantity=time_q),
-                                      ResourceType(name="observing_time_prio_b", description="Observing time with priority B (in seconds)", quantity=time_q),
-                                      ResourceType(name="observing_time_commissioning", description="Observing time for Commissioning/DDT (in seconds)", quantity=time_q),
-                                      ResourceType(name="support_time", description="Support time by human (in seconds)", quantity=time_q),
-                                      ResourceType(name="number_of_triggers", description="Number of trigger events (as integer)", quantity=number_q),
-                                      # TODO these duplicates have names that front-end expects.
-                                      # TODO We should not have doubles.
-                                      ResourceType(name="LTA Storage", description="Amount of storage in the LTA (in bytes)", quantity=bytes_q),
+    ResourceType.objects.bulk_create([ResourceType(name="LTA Storage", description="Amount of storage in the LTA (in bytes)", quantity=bytes_q),
                                       ResourceType(name="CEP Storage", description="Amount of storage on the CEP processing cluster (in bytes)", quantity=bytes_q),
                                       ResourceType(name="CEP Processing Time", description="Processing time on the CEP processing cluster (in seconds)", quantity=time_q),
                                       ResourceType(name="LOFAR Observing Time", description="Observing time (in seconds)", quantity=time_q),
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/reservations.py b/SAS/TMSS/backend/src/tmss/tmssapp/reservations.py
new file mode 100644
index 0000000000000000000000000000000000000000..3cc5cd8794191a8e2fc9ddd064e54dc120b97f42
--- /dev/null
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/reservations.py
@@ -0,0 +1,13 @@
+from lofar.sas.tmss.tmss.tmssapp import models
+
+
+def get_active_station_reservations_in_timewindow(lower_bound, upper_bound):
+    """
+    Retrieve a list of all active stations reservations, which are reserved between a timewindow
+    """
+    lst_active_station_reservations = []
+    for res in models.Reservation.objects.filter(start_time__lt=upper_bound, stop_time__gt=lower_bound).values('specifications_doc'):
+        lst_active_station_reservations += res["specifications_doc"]["resources"]["stations"]
+    for res in models.Reservation.objects.filter(start_time__lt=upper_bound, stop_time=None).values('specifications_doc'):
+        lst_active_station_reservations += res["specifications_doc"]["resources"]["stations"]
+    return list(set(lst_active_station_reservations))
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/UC1-scheduling-unit-observation-strategy.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/UC1-scheduling-unit-observation-strategy.json
index 9763e45af29ef026a061b6b801f3931a0f5b8302..07081c0e3098153f07f55d8078608ece8776bec7 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/UC1-scheduling-unit-observation-strategy.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/UC1-scheduling-unit-observation-strategy.json
@@ -9,8 +9,7 @@
         "pointing": {
           "direction_type": "J2000",
           "angle1": 0,
-          "angle2": 0,
-          "angle3": 0
+          "angle2": 0
         },
         "name": "calibrator1"
       },
@@ -80,8 +79,7 @@
         "tile_beam": {
           "direction_type": "J2000",
           "angle1": 0.42,
-          "angle2": 0.43,
-          "angle3": 0.44
+          "angle2": 0.43
         },
         "SAPs": [
           {
@@ -89,8 +87,7 @@
             "digital_pointing": {
               "direction_type": "J2000",
               "angle1": 0.24,
-              "angle2": 0.25,
-              "angle3": 0.26
+              "angle2": 0.25
             },
             "subbands": [
               349,
@@ -102,8 +99,7 @@
             "digital_pointing": {
               "direction_type": "J2000",
               "angle1": 0.27,
-              "angle2": 0.28,
-              "angle3": 0.29
+              "angle2": 0.28
             },
             "subbands": [
               349,
@@ -169,8 +165,7 @@
         "pointing": {
           "direction_type": "J2000",
           "angle1": 0,
-          "angle2": 0,
-          "angle3": 0
+          "angle2": 0
         },
         "name": "calibrator2"
       },
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template-pointing-1.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template-pointing-1.json
index 88668838c82f03c889baee2825b7f8bf9823d3a4..75e850155bd192c799fc8e659516ac23c9ee2f2d 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template-pointing-1.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/common_schema_template-pointing-1.json
@@ -42,12 +42,6 @@
           "title": "Angle 2",
           "description": "Second angle (e.g. DEC)",
           "default": 0
-        },
-        "angle3": {
-          "type": "number",
-          "title": "Angle 3",
-          "description": "Third angle (e.g. N in LMN)",
-          "default": 0
         }
       },
       "required": [
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
index 9caf086d923d583720925e44d47dfbc255f95885..732e7c01dc4b52dab7e4bf0b55c0972de92ea8d4 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/scheduling_constraints_template-constraints-1.json
@@ -111,13 +111,13 @@
           "properties": {
             "from": {
               "type": "number",
-              "minimum": -0.20943951,
-              "maximum": 0.20943951
+              "minimum": -86400,
+              "maximum": 86400
             },
             "to": {
               "type": "number",
-              "minimum": -0.20943951,
-              "maximum": 0.20943951
+              "minimum": -86400,
+              "maximum": 86400
             }
           },
           "additionalProperties": false
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/short-observation-pipeline-ingest-scheduling-unit-observation-strategy.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/short-observation-pipeline-ingest-scheduling-unit-observation-strategy.json
index 23756bfb22a1d883279f592b8c01d7b453847e7b..ac3277566c7e385713036301a3c2a6af7bd3c911 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/short-observation-pipeline-ingest-scheduling-unit-observation-strategy.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/short-observation-pipeline-ingest-scheduling-unit-observation-strategy.json
@@ -30,8 +30,7 @@
         "tile_beam": {
           "direction_type": "J2000",
           "angle1": 5.233660650313663,
-          "angle2": 0.7109404782526458,
-          "angle3": 0
+          "angle2": 0.7109404782526458
         },
         "SAPs": [
           {
@@ -40,8 +39,7 @@
             "digital_pointing": {
               "direction_type": "J2000",
               "angle1": 5.233660650313663,
-              "angle2": 0.7109404782526458,
-              "angle3": 0
+              "angle2": 0.7109404782526458
             },
             "subbands": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243]
           }
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-beamforming-observation-scheduling-unit-observation-strategy.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-beamforming-observation-scheduling-unit-observation-strategy.json
index a711c97f18d6bb9f3facbe17f4f5f1a15e41f423..f74ee652b3c73ffbedb2451edce6531cf93f8990 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-beamforming-observation-scheduling-unit-observation-strategy.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-beamforming-observation-scheduling-unit-observation-strategy.json
@@ -14,8 +14,7 @@
             "digital_pointing": {
               "direction_type": "J2000",
               "angle1": 5.233660650313663,
-              "angle2": 0.7109404782526458,
-              "angle3": 0
+              "angle2": 0.7109404782526458
             },
             "subbands": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243]
           }
@@ -26,8 +25,7 @@
         "tile_beam": {
           "direction_type": "J2000",
           "angle1": 5.233660650313663,
-          "angle2": 0.7109404782526458,
-          "angle3": 0
+          "angle2": 0.7109404782526458
         },
         "beamformers": [ {} ]
       },
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json
index 06e34636cc16cd68ccfc10c68b3b7180634d9070..4ea17e719fad83f17b9746f474f1761f9682a48f 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/schemas/simple-observation-scheduling-unit-observation-strategy.json
@@ -30,8 +30,7 @@
         "tile_beam": {
           "direction_type": "J2000",
           "angle1": 5.233660650313663,
-          "angle2": 0.7109404782526458,
-          "angle3": 0
+          "angle2": 0.7109404782526458
         },
         "SAPs": [
           {
@@ -40,8 +39,7 @@
             "digital_pointing": {
               "direction_type": "J2000",
               "angle1": 5.233660650313663,
-              "angle2": 0.7109404782526458,
-              "angle3": 0
+              "angle2": 0.7109404782526458
             },
             "subbands": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243]
           }
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
index 188494e0936defd8c69f473f887661876a8ad5d1..47086104958108a4cc364a1c07c84c200d909d64 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/serializers/specification.py
@@ -171,10 +171,12 @@ class ProjectSerializer(DynamicRelationalHyperlinkedModelSerializer):
 
 
 class ProjectQuotaSerializer(DynamicRelationalHyperlinkedModelSerializer):
+    project_quota_archive_location = serializers.HyperlinkedRelatedField('projectquotaarchivelocation-detail', source='*', read_only=True)
+
     class Meta:
         model = models.ProjectQuota
         fields = '__all__'
-        extra_fields = ['resource_type']
+        extra_fields = ['resource_type', 'project_quota_archive_location']
 
 
 class ProjectQuotaArchiveLocationSerializer(DynamicRelationalHyperlinkedModelSerializer):
@@ -388,7 +390,7 @@ class ReservationSerializer(DynamicRelationalHyperlinkedModelSerializer):
     class Meta:
         model = models.Reservation
         fields = '__all__'
-        extra_fields = ['stop_time']
+        extra_fields = ['duration']
 
 
 class TaskBlueprintExtendedSerializer(TaskBlueprintSerializer):
diff --git a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
index 243cb8b3ddbc8729a94b61606a3a7a4c93b5be42..60499017cdc4a4247f7716881ca2840f45ffb96a 100644
--- a/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
+++ b/SAS/TMSS/backend/src/tmss/tmssapp/subtasks.py
@@ -99,7 +99,7 @@ def _add_pointings(pointing_a, pointing_b):
         raise SubtaskCreationException(
             "Cannot add pointings because direction types differ pointing_a=%s; pointing_b=%s" % (pointing_a, pointing_b))
     pointing = {"direction_type": pointing_a['direction_type']}
-    for angle in ['angle1', 'angle2', 'angle3']:
+    for angle in ['angle1', 'angle2']:
         pointing[angle] = pointing_a.get(angle, 0.0) + pointing_b.get(angle, 0.0)
     return pointing
 
diff --git a/SAS/TMSS/backend/test/t_adapter.py b/SAS/TMSS/backend/test/t_adapter.py
index f67d013c90e33f656334d3416444ec70006f7ffb..772a2d43ed706e328371dc2cdb048f38f65db9ed 100755
--- a/SAS/TMSS/backend/test/t_adapter.py
+++ b/SAS/TMSS/backend/test/t_adapter.py
@@ -214,7 +214,7 @@ class SIPadapterTest(unittest.TestCase):
         specifications_doc['stations']['filter'] = "HBA_210_250"
         feedback_template = models.DataproductFeedbackTemplate.objects.get(name='feedback')
         # feedback_doc = get_default_json_object_for_schema(feedback_template.schema)  # todo <- fix the default generator, for some reason it does not produce valid json here...
-        feedback_doc = {'percentage_written': 100, 'frequency': {'subbands': [156], 'central_frequencies': [33593750.0], 'channel_width': 6103.515625, 'channels_per_subband': 32}, 'time': {'start_time': '2013-02-16T17:00:00', 'duration': 5.02732992172, 'sample_width': 2.00278016}, 'antennas': {'set': 'HBA_DUAL', 'fields': [{'type': 'HBA', 'field': 'HBA0', 'station': 'CS001'}, {'type': 'HBA', 'field': 'HBA1', 'station': 'CS001'}]}, 'target': {'pointing': {'angle1': 0, 'angle2': 0, 'angle3': 0, 'direction_type': 'J2000'}}, 'samples': {'polarisations': ['XX', 'XY', 'YX', 'YY'], 'type': 'float', 'bits': 32, 'writer': 'standard', 'writer_version': '2.2.0', 'complex': True}, '$schema': 'http://127.0.0.1:8001/api/schemas/dataproductfeedbacktemplate/feedback/1#'}
+        feedback_doc = {'percentage_written': 100, 'frequency': {'subbands': [156], 'central_frequencies': [33593750.0], 'channel_width': 6103.515625, 'channels_per_subband': 32}, 'time': {'start_time': '2013-02-16T17:00:00', 'duration': 5.02732992172, 'sample_width': 2.00278016}, 'antennas': {'set': 'HBA_DUAL', 'fields': [{'type': 'HBA', 'field': 'HBA0', 'station': 'CS001'}, {'type': 'HBA', 'field': 'HBA1', 'station': 'CS001'}]}, 'target': {'pointing': {'angle1': 0, 'angle2': 0, 'direction_type': 'J2000'}}, 'samples': {'polarisations': ['XX', 'XY', 'YX', 'YY'], 'type': 'float', 'bits': 32, 'writer': 'standard', 'writer_version': '2.2.0', 'complex': True}, '$schema': 'http://127.0.0.1:8001/api/schemas/dataproductfeedbacktemplate/feedback/1#'}
         for dp in specifications_doc['stations']['digital_pointings']:
             dp['subbands'] = list(range(8))
         # Create SubTask(output)
diff --git a/SAS/TMSS/backend/test/t_conversions.py b/SAS/TMSS/backend/test/t_conversions.py
index 7f8d66d6e4b8758b3cf13bf04bf3d8488deb89ad..1773168c7b1ded14c41aee27f0fddd6683d9f9f7 100755
--- a/SAS/TMSS/backend/test/t_conversions.py
+++ b/SAS/TMSS/backend/test/t_conversions.py
@@ -362,6 +362,35 @@ class UtilREST(unittest.TestCase):
                 self.assertNotEqual(rise, rise_last)
             rise_last = rise
 
+    def test_util_target_rise_and_set_detects_when_target_above_horizon(self):
+
+        # assert always below and always above are usually false
+        r = requests.get(BASE_URL + '/util/target_rise_and_set?angle1=0.5&angle2=0.8&timestamps=2020-01-01&horizon=0.2', auth=AUTH)
+        self.assertEqual(r.status_code, 200)
+        r_dict = json.loads(r.content.decode('utf-8'))
+        self.assertIsNotNone(r_dict['CS002'][0]['rise'])
+        self.assertIsNotNone(r_dict['CS002'][0]['set'])
+        self.assertFalse(r_dict['CS002'][0]['always_below_horizon'])
+        self.assertFalse(r_dict['CS002'][0]['always_above_horizon'])
+
+        # assert rise and set are None and flag is true when target is always above horizon
+        r = requests.get(BASE_URL + '/util/target_rise_and_set?angle1=0.5&angle2=0.8&timestamps=2020-01-01&horizon=0.1', auth=AUTH)
+        self.assertEqual(r.status_code, 200)
+        r_dict = json.loads(r.content.decode('utf-8'))
+        self.assertIsNone(r_dict['CS002'][0]['rise'])
+        self.assertIsNone(r_dict['CS002'][0]['set'])
+        self.assertTrue(r_dict['CS002'][0]['always_above_horizon'])
+        self.assertFalse(r_dict['CS002'][0]['always_below_horizon'])
+
+        # assert rise and set are None and flag is true when target is always below horizon
+        r = requests.get(BASE_URL + '/util/target_rise_and_set?angle1=0.5&angle2=-0.5&timestamps=2020-01-01&horizon=0.2', auth=AUTH)
+        self.assertEqual(r.status_code, 200)
+        r_dict = json.loads(r.content.decode('utf-8'))
+        self.assertIsNone(r_dict['CS002'][0]['rise'])
+        self.assertIsNone(r_dict['CS002'][0]['set'])
+        self.assertFalse(r_dict['CS002'][0]['always_above_horizon'])
+        self.assertTrue(r_dict['CS002'][0]['always_below_horizon'])
+
 
 if __name__ == "__main__":
     os.environ['TZ'] = 'UTC'
diff --git a/SAS/TMSS/backend/test/t_reservations.py b/SAS/TMSS/backend/test/t_reservations.py
index ae8a41b8a47b88c94a826d1bd0454e2254b856a5..c19f18ef56a8a3ec29bff4f43fb243487618607e 100755
--- a/SAS/TMSS/backend/test/t_reservations.py
+++ b/SAS/TMSS/backend/test/t_reservations.py
@@ -46,6 +46,200 @@ rest_data_creator = TMSSRESTTestDataCreator(BASE_URL, AUTH)
 
 from lofar.sas.tmss.tmss.tmssapp import models
 
+
+from lofar.sas.tmss.tmss.tmssapp.reservations import get_active_station_reservations_in_timewindow
+
+
+class TestStationReservations(unittest.TestCase):
+    """
+    Tests for the active station reservations
+    """
+
+    def setUp(self) -> None:
+         # wipe all reservations in between tests, so the tests don't influence each other
+        for reservation in models.Reservation.objects.all():
+            reservation.delete()
+
+    @staticmethod
+    def create_station_reservation(additional_name, lst_stations, start_time, stop_time=None):
+        """
+        Create a station reservation with given list of stations, start_time and stop_time
+        """
+        reservation_template = models.ReservationTemplate.objects.get(name="resource reservation")
+        reservation_template_spec = get_default_json_object_for_schema(reservation_template.schema)
+        reservation_template_spec["resources"] = {"stations": lst_stations }
+        res = models.Reservation.objects.create(name="Station Reservation %s" % additional_name,
+                                   description="Station reservation for testing",
+                                   specifications_template=reservation_template,
+                                   specifications_doc=reservation_template_spec,
+                                   start_time=start_time,
+                                   stop_time=stop_time)
+
+    def test_no_stations_reservation(self):
+        """
+        Check that creating 'default' reservation with no additional station reservation added, we still can
+        call 'get_active_station_reservations_in_timewindow' and it will return an empty list
+        """
+        reservation_template = models.ReservationTemplate.objects.get(name="resource reservation")
+        reservation_template_spec = get_default_json_object_for_schema(reservation_template.schema)
+        res = models.Reservation.objects.create(name="AnyReservation",
+                                   description="Reservation of something else",
+                                   specifications_template=reservation_template,
+                                   specifications_doc=reservation_template_spec,
+                                   start_time=datetime.now(),
+                                   stop_time=None)
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(datetime.now(), datetime.now()+timedelta(weeks=53)))
+
+    def test_active_station_reservation(self):
+        """
+        Test station reservation when 2 stations are reserved for 24hr with both same start and stop time
+        Check 'get_active_station_reservations_in_timewindow' with different time ranges
+        """
+        reservation_start_time = datetime(2020, 1, 1, 0, 0, 0)
+        reservation_stop_time = datetime(2020, 1, 2, 0, 0, 0)
+        reservation_stations = ["CS001", "CS002"]
+        self.create_station_reservation("two_stations", reservation_stations, reservation_start_time, reservation_stop_time)
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(datetime.now(), datetime.now()))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_stop_time))
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_start_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_start_time+timedelta(seconds=1)))
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(reservation_stop_time,
+                                                                            reservation_stop_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_stop_time-timedelta(seconds=1),
+                                                                            reservation_stop_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time-timedelta(weeks=53),
+                                                                            reservation_stop_time+timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            datetime.now()+timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(datetime(2020, 1, 1, 12, 0, 0),
+                                                                            datetime(2020, 1, 2, 12, 0, 0)))
+
+    def test_active_station_reservation_with_same_station_overlap(self):
+        """
+        Test station reservation when 2 stations are reserved for 24hr with both same start and stop time
+        Same stations are reserved separately as well, which should result NOT result in having the station twice in
+        the resulting active station list
+        Check 'get_active_station_reservations_in_timewindow' with different time ranges
+        """
+        reservation_start_time = datetime(2020, 1, 1, 0, 0, 0)
+        reservation_stop_time = datetime(2020, 1, 2, 0, 0, 0)
+        reservation_stations = ["CS001", "CS002"]
+        self.create_station_reservation("two_stations", reservation_stations, reservation_start_time, reservation_stop_time)
+        self.create_station_reservation("cs1", ["CS001"], reservation_start_time, reservation_stop_time)
+        self.create_station_reservation("cs2", ["CS002"], reservation_start_time, reservation_stop_time)
+
+        # same lower_bound as upper_bound, empty list
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(datetime.now(), datetime.now()))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_stop_time))
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_start_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_start_time + timedelta(seconds=1)))
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(reservation_stop_time,
+                                                                            reservation_stop_time + timedelta(seconds=1)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_stop_time - timedelta(seconds=1),
+                                                                            reservation_stop_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time - timedelta(weeks=53),
+                                                                            reservation_stop_time + timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            datetime.now() + timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(datetime(2020, 1, 1, 12, 0, 0),
+                                                                            datetime(2020, 1, 2, 12, 0, 0)))
+
+    def test_active_station_reservation_with_station_no_stop_time(self):
+        """
+        Test station reservation when 2 stations are reserved forever both same start and stop time
+        Check 'get_active_station_reservations_in_timewindow' with different time ranges
+        """
+        reservation_start_time = datetime(2020, 1, 1, 0, 0, 0)
+        reservation_stations = ["CS001", "CS002"]
+        self.create_station_reservation("two_stations_no_end_time", reservation_stations, reservation_start_time)
+
+        # we are now still in reservation started in 2020
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(datetime.now(), datetime.now()))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            reservation_start_time + timedelta(seconds=1)))
+        # before start time, always empty
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(reservation_start_time - timedelta(seconds=1),
+                                                                            reservation_start_time))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time - timedelta(weeks=53),
+                                                                            reservation_start_time + timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(reservation_start_time,
+                                                                            datetime.now() + timedelta(weeks=53)))
+        self.assertCountEqual(reservation_stations,
+                              get_active_station_reservations_in_timewindow(datetime(2020, 1, 1, 12, 0, 0),
+                                                                            datetime(2020, 1, 2, 12, 0, 0)))
+
+    def test_active_station_reservation_every_hour_one_station(self):
+        """
+        Test station reservation when 1 station is reserved for 1 hour
+        Check 'get_active_station_reservations_in_timewindow' with different time ranges
+        """
+        first_day = 1
+        last_day = 7
+        reservation_start_time = datetime(2020, 1, first_day, 0, 0, 0)
+        reservation_stop_time = datetime(2020, 1, last_day+1, 0, 0, 0)
+        for day_nbr in range(first_day, last_day+1):
+            self.create_station_reservation("cs%s" % day_nbr, ["CS00%d" % day_nbr],
+                                            datetime(2020, 1, day_nbr, 12, 0, 0), datetime(2020, 1, day_nbr+1, 0, 0, 0))
+
+        self.assertCountEqual([],
+                              get_active_station_reservations_in_timewindow(datetime.now(), datetime.now()))
+        self.assertCountEqual(["CS001","CS002","CS003","CS004","CS005","CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time))
+        self.assertCountEqual(["CS002","CS003","CS004","CS005","CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=1), reservation_stop_time))
+        self.assertCountEqual(["CS003","CS004","CS005","CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=2), reservation_stop_time))
+        self.assertCountEqual(["CS004","CS005","CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=3), reservation_stop_time))
+        self.assertCountEqual(["CS005","CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=4), reservation_stop_time))
+        self.assertCountEqual(["CS006","CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=5), reservation_stop_time))
+        self.assertCountEqual(["CS007"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time+timedelta(days=6), reservation_stop_time))
+
+        self.assertCountEqual(["CS001","CS002","CS003","CS004","CS005","CS006"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=1)))
+        self.assertCountEqual(["CS001","CS002","CS003","CS004","CS005"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=2)))
+        self.assertCountEqual(["CS001","CS002","CS003","CS004"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=3)))
+        self.assertCountEqual(["CS001","CS002","CS003"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=4)))
+        self.assertCountEqual(["CS001","CS002"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=5)))
+        self.assertCountEqual(["CS001"],
+                              get_active_station_reservations_in_timewindow(reservation_start_time, reservation_stop_time-timedelta(days=6)))
 from lofar.sas.tmss.tmss.exceptions import SchemaValidationException
 from django.core.exceptions import ValidationError
 
diff --git a/SAS/TMSS/backend/test/t_subtasks.py b/SAS/TMSS/backend/test/t_subtasks.py
index c3a8c261bd74c019f4728aa4d525e376aad875cf..806fcd682579d20829b1b010f5548fb530ae73e1 100755
--- a/SAS/TMSS/backend/test/t_subtasks.py
+++ b/SAS/TMSS/backend/test/t_subtasks.py
@@ -230,10 +230,10 @@ class SubTasksCreationFromTaskBluePrint(unittest.TestCase):
     def test_create_subtasks_from_task_blueprint_translates_SAP_names(self):
         task_blueprint = create_task_blueprint_object_for_testing('target observation')
         task_blueprint.specifications_doc['SAPs'] = [{'name': 'target1', 'target': '', 'subbands': [],
-                                                      'digital_pointing': {'angle1': 0.1, 'angle2': 0.1, 'angle3': 0.1,
+                                                      'digital_pointing': {'angle1': 0.1, 'angle2': 0.1,
                                                                            'direction_type': 'J2000'}},
                                                      {'name': 'target2', 'target': '', 'subbands': [],
-                                                      'digital_pointing': {'angle1': 0.2, 'angle2': 0.2, 'angle3': 0.2,
+                                                      'digital_pointing': {'angle1': 0.2, 'angle2': 0.2,
                                                                            'direction_type': 'J2000'}}]
         subtask = create_observation_control_subtask_from_task_blueprint(task_blueprint)
         i = 0
@@ -386,9 +386,9 @@ class SettingTest(unittest.TestCase):
 
 class SubTaskCreationFromTaskBlueprintBeamformer(unittest.TestCase):
     saps = [{"name": "target1", "target": "", "subbands": [349, 372],
-             "digital_pointing": {"angle1": 0.24, "angle2": 0.25, "angle3": 0.26, "direction_type": "J2000"}},
+             "digital_pointing": {"angle1": 0.24, "angle2": 0.25, "direction_type": "J2000"}},
             {"name": "target2", "target": "", "subbands": [309, 302],
-             "digital_pointing": {"angle1": 0.42, "angle2": 0.52, "angle3": 0.62, "direction_type": "J2000"}}
+             "digital_pointing": {"angle1": 0.42, "angle2": 0.52, "direction_type": "J2000"}}
     ]
     beamformers = [{"name": "beamformer1",
                     "coherent": {"settings": {"stokes": "I", "time_integration_factor": 8, "subbands_per_file": 244,
@@ -447,7 +447,7 @@ class SubTaskCreationFromTaskBlueprintBeamformer(unittest.TestCase):
 
     def test_generate_tab_ring_pointings_returns_correct_pointings(self):
 
-        pointing = {"angle1": 0.11, "angle2": 0.22, "angle3": 0.33, "direction_type": "J2000"}
+        pointing = {"angle1": 0.11, "angle2": 0.22, "direction_type": "J2000"}
         tab_rings = {"width": 1, "count": 1}
 
         # assert center pointing is returned
@@ -469,9 +469,9 @@ class SubTaskCreationFromTaskBlueprintBeamformer(unittest.TestCase):
     def test_add_pointings_adds_correctly(self):
 
         pointing_a = {"angle1": 0.11, "angle2": 0.22, "direction_type": "J2000"}
-        pointing_b = {"angle1": 0.88, "angle2": 0.66, "angle3": 0.77, "direction_type": "J2000"}
+        pointing_b = {"angle1": 0.88, "angle2": 0.66, "direction_type": "J2000"}
         pointing_sum = _add_pointings(pointing_a, pointing_b)
-        self.assertEqual(pointing_sum, {"angle1": 0.99, "angle2": 0.88, "angle3": 0.77, "direction_type": "J2000"})
+        self.assertEqual(pointing_sum, {"angle1": 0.99, "angle2": 0.88, "direction_type": "J2000"})
 
     def test_filter_subbands_filters_correctly(self):
         subbands = [1,3,4,5,10,11,12,13,19,20]
diff --git a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
index 5fd6407a83fab52cadb1226617d3eba5e3822c8c..d3da150deaa98063eb7c714b99090c37447c8597 100755
--- a/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
+++ b/SAS/TMSS/backend/test/t_tmssapp_specification_REST_API.py
@@ -2898,7 +2898,7 @@ class ReservationTestCase(unittest.TestCase):
         GET_OK_and_assert_equal_expected_response(self, url, reservation_test_data)
 
         test_patch = {"description": "This is a new and improved description",
-                      "duration": 90}
+                      "stop_time": None}
 
         # PATCH item and verify
         expected_patch_data = test_data_creator.update_schema_from_template("reservationtemplate", test_patch)
diff --git a/SAS/TMSS/backend/test/tmss_test_data_django_models.py b/SAS/TMSS/backend/test/tmss_test_data_django_models.py
index 8535c5e223890e3be48467853ecb486f073985fe..03bd63e347821654485556b3e2c146e9aea2d92b 100644
--- a/SAS/TMSS/backend/test/tmss_test_data_django_models.py
+++ b/SAS/TMSS/backend/test/tmss_test_data_django_models.py
@@ -562,6 +562,11 @@ def Reservation_test_data(name="MyReservation", duration=None, start_time=None,
     if start_time is None:
         start_time = datetime.utcnow() + timedelta(hours=12)
 
+    if duration is None:
+        stop_time = None
+    else:
+        stop_time = start_time + timedelta(seconds=duration)
+
     specifications_template = models.ReservationTemplate.objects.create(**ReservationTemplate_test_data())
     specifications_doc = get_default_json_object_for_schema(specifications_template.schema)
 
@@ -570,7 +575,7 @@ def Reservation_test_data(name="MyReservation", duration=None, start_time=None,
             "description": "Test Reservation",
             "tags": ["TMSS", "TESTING"],
             "start_time": start_time,
-            "duration": duration, # can be None
+            "stop_time": stop_time, # can be None
             "specifications_doc": specifications_doc,
             "specifications_template": specifications_template}
 
diff --git a/SAS/TMSS/backend/test/tmss_test_data_rest.py b/SAS/TMSS/backend/test/tmss_test_data_rest.py
index afd7c5d57cd097130cf4707066e6a8b92b952f2a..551a251a68857807ceb4e4bf63699d6bd575c44d 100644
--- a/SAS/TMSS/backend/test/tmss_test_data_rest.py
+++ b/SAS/TMSS/backend/test/tmss_test_data_rest.py
@@ -851,6 +851,11 @@ class TMSSRESTTestDataCreator():
         if start_time is None:
             start_time = datetime.utcnow() + timedelta(hours=12)
 
+        if duration is None:
+            stop_time = None
+        else:
+            stop_time = start_time + timedelta(seconds=duration)
+
         if specifications_template_url is None:
             specifications_template_url = self.post_data_and_get_url(self.ReservationTemplate(), '/reservation_template/')
 
@@ -860,12 +865,15 @@ class TMSSRESTTestDataCreator():
         if isinstance(start_time, datetime):
             start_time = start_time.isoformat()
 
+        if isinstance(stop_time, datetime):
+            stop_time = stop_time.isoformat()
+
         return {"name": name,
                 "project": project_url,
                 "description": "Test Reservation",
                 "tags": ["TMSS", "TESTING"],
                 "start_time": start_time,
-                "duration": duration, # can be None
+                "stop_time": stop_time, # can be None
                 "specifications_doc": specifications_doc,
                 "specifications_template": specifications_template_url}
 
diff --git a/SAS/TMSS/frontend/tmss_webapp/package.json b/SAS/TMSS/frontend/tmss_webapp/package.json
index e9cc1d244a28ffcb034292897693fb7875c7a0f9..5de0cf8841f3e116bcd8cf264c26613650b2467f 100644
--- a/SAS/TMSS/frontend/tmss_webapp/package.json
+++ b/SAS/TMSS/frontend/tmss_webapp/package.json
@@ -38,6 +38,7 @@
     "react-bootstrap-datetimepicker": "0.0.22",
     "react-calendar-timeline": "^0.27.0",
     "react-dom": "^16.13.1",
+    "react-flatpickr": "^3.10.7",
     "react-frame-component": "^4.1.2",
     "react-json-to-table": "^0.1.7",
     "react-json-view": "^1.19.1",
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/App.js b/SAS/TMSS/frontend/tmss_webapp/src/App.js
index 12ca8a5aa7118073ce961d010b690f1d54143a1a..74a6f8c2bd0dc57fea26971a4d83c1bf3d076c4b 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/App.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/App.js
@@ -8,6 +8,9 @@ import {AppFooter } from './layout/components/AppFooter';
 import {RoutedContent} from './routes';
 import {AppBreadcrumb } from "./layout/components/AppBreadcrumb";
 import {withRouter } from 'react-router';
+import handleResponse from "./response.handler"
+import { setAppGrowl } from './layout/components/AppGrowl';
+import { Growl } from 'primereact/components/growl/Growl';
 
 import 'primeicons/primeicons.css';
 import 'primereact/resources/themes/nova-light/theme.css';
@@ -139,6 +142,7 @@ class App extends Component {
         //console.log(this.props);
         return (
         <React.Fragment>
+            <Growl ref={(el) => setAppGrowl(el)} />
             <div className="App">
                 {/* <div className={wrapperClass} onClick={this.onWrapperClick}> */}
                 <div className={wrapperClass}>
@@ -177,4 +181,4 @@ class App extends Component {
     }
 }
 
-export default App;
+export default handleResponse(App);
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/components/Spreadsheet/CustomDateComp.js b/SAS/TMSS/frontend/tmss_webapp/src/components/Spreadsheet/CustomDateComp.js
index 98d84429009f475b44411113fe6d7d6d319dcf88..50623578335782048c11ba4ff25bb4f182370119 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/components/Spreadsheet/CustomDateComp.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/components/Spreadsheet/CustomDateComp.js
@@ -1,7 +1,11 @@
 import React, { Component } from 'react';
+import Flatpickr from "react-flatpickr";
 import {Calendar} from 'primereact/calendar';
 import moment from 'moment';
 import UIConstants from '../../utils/ui.constants';
+import UtilService from '../../services/util.service';
+
+import "flatpickr/dist/flatpickr.css";
 
 //const DATE_TIME_FORMAT = 'YYYY-MM-DD HH:mm:ss';
 
@@ -16,9 +20,13 @@ export default class CustomDateComp extends Component {
   componentDidMount(){
     let parentRows = this.props.agGridReact.props.rowData[this.props.node.rowIndex];
     let parentCellData = parentRows[this.props.colDef.field];
-    this.setState({
-      date:parentCellData
-    })
+    UtilService.getUTC()
+    .then(systemTime => {
+      this.setState({
+        date:parentCellData,
+        systemTime: moment.utc(systemTime)
+      })
+    });
   }
 
   isPopup() {
@@ -33,30 +41,30 @@ export default class CustomDateComp extends Component {
   }
 
   render() {
-    return (
-         <Calendar
-              d dateFormat = {UIConstants.CALENDAR_DATE_FORMAT}
-              value= {this.state.date}
-              onChange= {e => {this.updateDateChanges(e)}}
-             // onBlur= {e => {this.updateDateChanges(e)}}
-             //data-testid="start"
-              todayButtonClassName="today-calendar-btn"
-              showButtonBar
-              showTime= {true}
-              showSeconds= {true}
-              hourFormat= "24"
-              showIcon= {false} inline
-          />
-        );
+    return this.state.systemTime?(
+        <Flatpickr
+            data-enable-time 
+            options={{
+                    "inline": true,
+                    "enableSeconds": true,
+                    "time_24hr": true,
+                    "defaultDate": this.state.systemTime?this.state.systemTime.format(UIConstants.CALENDAR_DEFAULTDATE_FORMAT):"",
+                    "defaultHour": this.state.systemTime?this.state.systemTime.hours():12,
+                    "defaultMinute": this.state.systemTime?this.state.systemTime.minutes():0
+                    }}
+            value={this.state.date}
+            onChange= {value => {this.updateDateChanges(value[0]?value[0]:this.state.date)}}
+        />
+    ):"";
   }
 
 
   updateDateChanges(e){  
-    this.setState({date : e.value || ''});  
+    this.setState({date : e || ''});  
   }
 
   ondatechange(e){
-    this.setState({date : e.value}); 
+    this.setState({date : e}); 
   }
    
   getDate() {
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/response.handler.js b/SAS/TMSS/frontend/tmss_webapp/src/response.handler.js
new file mode 100644
index 0000000000000000000000000000000000000000..7c4da4c87de73f67983fb60f36e2c6aff269ab8d
--- /dev/null
+++ b/SAS/TMSS/frontend/tmss_webapp/src/response.handler.js
@@ -0,0 +1,45 @@
+import React, {useEffect} from "react";
+import axios from "axios";
+import { appGrowl } from './layout/components/AppGrowl';
+import UIConstants from './utils/ui.constants';
+import Auth from './authenticate/auth';
+/**
+ * Trigger and validate the response for https status code
+ * @param {*} Wrapped 
+ * @returns 
+ */
+const handleResponse= Wrapped => {
+    function HandleResponse(props) {
+        useEffect(()=>{
+            axios.interceptors.response.use(function (response) {
+                return response;
+            }, function (error) {
+                showMessage(error.response);
+                return Promise.reject(error);
+            });
+        })
+        return (
+            <Wrapped {...props} />
+        );
+    }
+
+    /**
+     * Catch relavent http status code details to show in growl
+     * @param {*} response 
+     */
+    function showMessage(response) {
+        const httpStatusMsg = UIConstants.httpStatusMessages[response.status];
+        if(httpStatusMsg) {
+            appGrowl.show({severity: httpStatusMsg.severity, summary: httpStatusMsg.summary, sticky: httpStatusMsg.sticky, detail: '['+response.status+'] '+JSON.stringify(response.statusText)+ ' ['+httpStatusMsg.detail+']'});
+        }   else {
+            appGrowl.show({severity: 'error', summary: 'Error', sticky: 'true', detail: '['+response.status+'] '+JSON.stringify(response.statusText)+ '   '+JSON.stringify(response.data)});
+        }
+        if (response.status === 401) {
+            Auth.logout();
+            window.location.href = "/login";
+        }
+    }
+    return HandleResponse;
+}
+
+export default handleResponse;
\ No newline at end of file
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
index 7ef3b05cc8bf50d554ae4f4fcd64e409b7e853c0..b64a1d66d444ac9001fe31e5ce2486d70f8c54b8 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Cycle/edit.js
@@ -318,7 +318,7 @@ export class CycleEdit extends Component {
                         this.saveCycleQuota(cycle);
                     }   else {
                         this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to update Cycle'});
-                        this.setState({errors: cycle});
+                        //this.setState({errors: cycle});
                     }
                 });
         }
@@ -373,7 +373,7 @@ export class CycleEdit extends Component {
         if (_.keys(quotaError).length === 0) {
             dialog = {header: 'Success', detail: 'Cycle updated successfully.'};
         }   else {
-            dialog = {header: 'Error', detail: 'Cycle updated successfully but resource allocation not updated properly. Try again!'};
+            dialog = {header: 'Error', detail: 'Cycle updated successfully but resource allocation not updated properly.'};
         }
         this.setState({dialogVisible: true, dialog: dialog});
     }
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
index c21f5afcd834388b99fe3836cd7d598be970a608..caf0c0b6e487bff2e139cdab5f857a9cc0bca1c5 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/create.js
@@ -325,12 +325,17 @@ export class ProjectCreate extends Component {
             }
             ProjectService.saveProject(this.state.project, this.defaultResourcesEnabled?projectQuota:[])
                 .then(project => {
+                    
                     if (project.url) {
                         let dialog = {};
-                        if (this.defaultResourcesEnabled) {
-                            dialog = {header: 'Success', detail: 'Project saved successfully. Do you want to create another project?'};
+                        if (project.isQuotaCreated) {
+                            if (this.defaultResourcesEnabled) {
+                                dialog = {header: 'Success', detail: 'Project saved successfully. Do you want to create another project?'};
+                            }   else {
+                                dialog = {header: 'Success', detail: 'Project saved successfully with default Resource allocations. Do you want to view and edit them?'};
+                            }
                         }   else {
-                            dialog = {header: 'Success', detail: 'Project saved successfully with default Resource allocations. Do you want to view and edit them?'};
+                            dialog = {header: 'Warning', detail: 'Project saved successfully, but resource allocation not saved.'};
                         }
                         this.setState({project:project, dialogVisible: true, dialog: dialog, isDirty: false});
                     }   else {
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
index b8bd0f3e2f9833bf6290e035240e88bad4d9695d..ac275f366da7624c2c9a2149b18690d2b9db297a 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Project/edit.js
@@ -335,7 +335,7 @@ export class ProjectEdit extends Component {
             // project['archive_subdirectory'] = (project['archive_subdirectory'].substr(-1) === '/' ? project['archive_subdirectory'] : `${project['archive_subdirectory']}/`).toLowerCase();
             ProjectService.updateProject(this.props.match.params.id, project)
                 .then(async (project) => { 
-                    if (project && this.state.project.updated_at !== project.updated_at) {
+                    if (project && project.isUpdated && this.state.project.updated_at !== project.updated_at) {
                         this.saveProjectQuota(project);
                     }   else {
                         this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to update Project'});
@@ -381,20 +381,20 @@ export class ProjectEdit extends Component {
         }
         for (const projectQuota of updatingProjectQuota) {
             const updatedProjectQuota = await ProjectService.updateProjectQuota(projectQuota);
-            if (!updatedProjectQuota) {
+            if (!updatedProjectQuota || (updatedProjectQuota.status && updatedProjectQuota.status > 299)) {
                 quotaError[projectQuota.resource_type_id] = true;
             }
         }
         for (const projectQuota of newProjectQuota) {
             const createdProjectQuota = await ProjectService.saveProjectQuota(projectQuota);
-            if (!createdProjectQuota) {
+            if (!createdProjectQuota || (createdProjectQuota.status && createdProjectQuota.status > 299)) {
                 quotaError[projectQuota.resource_type_id] = true;
             }
         }
         if (_.keys(quotaError).length === 0) {
             dialog = {header: 'Success', detail: 'Project updated successfully.'};
         }   else {
-            dialog = {header: 'Error', detail: 'Project updated successfully but resource allocation not updated properly. Try again!'};
+            dialog = {header: 'Error', detail: 'Project updated successfully but resource allocation not updated properly.'};
         }
         this.setState({dialogVisible: true, dialog: dialog, isDirty: false});
     }
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/Scheduling.Constraints.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/Scheduling.Constraints.js
index 35725047eaeceb182457875029cbba90b4cd7320..396b74fd9c413e4ca93798b76ba3462889ac7dd0 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/Scheduling.Constraints.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/Scheduling.Constraints.js
@@ -4,6 +4,7 @@ import _ from 'lodash';
 import Jeditor from '../../components/JSONEditor/JEditor'; 
 import UnitConversion from '../../utils/unit.converter';
 import UIConstants from '../../utils/ui.constants';
+import UtilService from '../../services/util.service';
 /* eslint-disable react-hooks/exhaustive-deps */
 
 export default (props) => {
@@ -11,6 +12,7 @@ export default (props) => {
     const { parentFunction = (editorFn) => { editorFunction = editorFn;} } = props;
     const [constraintSchema, setConstraintSchema] = useState();
     const [initialValue, setInitialValue] = useState();
+    const [systemTime, setSystemTime] = useState();
     //SU Constraint Editor Property Order,format and validation
     const configureProperties = (properties) => {
         for (const propertyKey in properties) {
@@ -69,7 +71,8 @@ export default (props) => {
         }
     };
     //DateTime flatPicker component enabled with seconds
-    const setDateTimeOption = (propertyValue) => {
+    const setDateTimeOption = async(propertyValue) => {
+        const systemTime = moment.utc((await UtilService.getUTC()));
         propertyValue.format = 'datetime-local';
         propertyValue.validationType = 'dateTime';
         propertyValue.skipFormat = true;
@@ -83,6 +86,9 @@ export default (props) => {
                 "enableSeconds": true,
                 "time_24hr": true,
                 "allowInput": true,
+                "defaultDate": systemTime.format(UIConstants.CALENDAR_DEFAULTDATE_FORMAT),
+                "defaultHour": systemTime.hour(),
+                "defaultMinute": systemTime.minutes()
            }          
         };
     };
@@ -101,7 +107,7 @@ export default (props) => {
             } else if(definitionName === 'timewindow') {
                 for (let property in schema.definitions.timewindow.properties) {
                     if(property === 'to' || property === 'from'){
-                        setDateTimeOption(schema.definitions.timewindow.properties[property]);
+                        // setDateTimeOption(schema.definitions.timewindow.properties[property]);
                         if (property === 'from') {
                             schema.definitions.timewindow.properties[property].propertyOrder = 1;
                         } else {
@@ -148,7 +154,9 @@ export default (props) => {
         }
     }
 
-    const constraintStrategy = () => {
+    const constraintStrategy = async() => {
+        const currentSystemTime = moment.utc(await UtilService.getUTC())
+        setSystemTime(currentSystemTime);
         // const constraintTemplate = { ...props.constraintTemplate }
         const constraintTemplate = _.cloneDeep(props.constraintTemplate);
         if (constraintTemplate.schema) {
@@ -196,6 +204,9 @@ export default (props) => {
         if (!props.constraintTemplate) {
             return;
         }
+        UtilService.getUTC().then(utcTime => {
+            setSystemTime(moment.utc(utcTime));
+        });
         if (props.initValue) {
             modifyInitiValue();
         }
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js
index 161657340ba91b073e152f4afd04f45212a892de..6e8e565a824195df4de6e33736a6715eea03e577 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/excelview.schedulingset.js
@@ -1723,12 +1723,13 @@ export class SchedulingSetCreate extends Component {
     async saveSU() {
         let newSUCount = 0;
         let existingSUCount = 0;
+        let isUpdated = true;
         try{
             this.setState({
                // saveDialogVisible: false,
                 confirmDialogVisible: false,
                 showSpinner: true
-            })
+            });
          
             let newSU = this.state.schedulingUnit;
             let parameters = this.state.schedulingUnitList[0]['requirements_doc'].parameters;
@@ -1911,7 +1912,10 @@ export class SchedulingSetCreate extends Component {
                     if(taskdata){
                         taskDrafts = taskdata.data.results;
                     }
-                    await ScheduleService.updateSUDraftFromObservStrategy(observStrategy, newSU, taskDrafts, this.state.tasksToUpdate, tmpStationGroups);
+                    let updateSu = await ScheduleService.updateSUDraftFromObservStrategy(observStrategy, newSU, taskDrafts, this.state.tasksToUpdate, tmpStationGroups);
+                    if (updateSu && !updateSu.isSUUpdated) {
+                        isUpdated = false;
+                    } 
                     existingSUCount++;
                 }
                 else if  (suRow.id === 0 && this.isNotEmpty(suRow.suname) && this.isNotEmpty(suRow.sudesc)){
@@ -1921,7 +1925,10 @@ export class SchedulingSetCreate extends Component {
                         scheduling_constraints_template_id: newSU['scheduling_constraints_template_id'],
                         scheduling_set_id: newSU['scheduling_set_id']
                     }
-                    await ScheduleService.saveSUDraftFromObservStrategy(observStrategy, newSchedulueUnit, newConstraint, tmpStationGroups);
+                    let updateSu = await ScheduleService.saveSUDraftFromObservStrategy(observStrategy, newSchedulueUnit, newConstraint, tmpStationGroups);
+                    if (updateSu && !updateSu.isSUUpdated) {
+                        isUpdated = false;
+                    }
                     newSUCount++;
                 }
             }
@@ -1932,7 +1939,13 @@ export class SchedulingSetCreate extends Component {
                 this.dialogType = "success";
                 this.dialogHeader = "Success";
                 this.showIcon = true;
-                this.dialogMsg = '['+newSUCount+'] Scheduling Units are created & ['+existingSUCount+'] Scheduling Units are updated successfully.';
+                if (isUpdated) {
+                    this.dialogMsg = '['+newSUCount+'] Scheduling Units are created & ['+existingSUCount+'] Scheduling Units are updated successfully.';
+                }   else {
+                    this.dialogHeader = "Warning";
+                    this.dialogMsg = '['+newSUCount+'] Scheduling Units are created & ['+existingSUCount+'] Scheduling Units are updated successfully, and there are some Schedule Unit/Task failed to create/update';
+                }
+                
                 this.dialogContent = "";
                 this.onCancel = this.close;
                 this.onClose = this.close;
@@ -1944,6 +1957,7 @@ export class SchedulingSetCreate extends Component {
             }
         }catch(err){
             this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to create/update Scheduling Units'});
+            this.setState({showSpinner: false});
         }
     }
   
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/schedulingset.create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/schedulingset.create.js
index b9273de4b8be558f5f7cd8345c1dc7152c78f017..2b34d370565a6284dde6d7b40b222befe78a564c 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/schedulingset.create.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Scheduling/schedulingset.create.js
@@ -5,6 +5,7 @@ import UIConstants from '../../utils/ui.constants';
 import { CustomDialog } from '../../layout/components/CustomDialog';
 import ScheduleService from '../../services/schedule.service';
 import { Growl } from 'primereact/components/growl/Growl';
+import { appGrowl } from './../../layout/components/AppGrowl';
 
 export class SchedulingSet extends Component {
 
@@ -32,13 +33,13 @@ export class SchedulingSet extends Component {
                                 schedulingSet['generator_doc'] = {};
                                 schedulingSet['scheduling_unit_drafts'] = [];
                                 const suSet = await ScheduleService.saveSchedulingSet(schedulingSet);                         
-                                if (suSet.id !== null) {
-                                    this.growl.show({severity: 'success', summary: 'Success', detail: 'Scheduling Set is created successfully.'});
+                                if (suSet.id && suSet.id !== null) {
+                                    appGrowl.show({severity: 'success', summary: 'Success', detail: 'Scheduling Set is created successfully.'});
                                     this.setState({suSet: suSet, dialogVisible: true, });
                                     this.props.onCancel();
-                                }   else {
+                                } /*  else {
                                     this.growl.show({severity: 'error', summary: 'Error Occured', detail: schedulingSet.message || 'Unable to save Scheduling Set'});
-                                }
+                                } */
                             }
                         }},
                          {id:"no", title: 'Cancel', callback: this.props.onCancel} ];
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/reservation.create.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/reservation.create.js
index 4809304616b85fe9a91f3828a8a16f5b29f64dda..e1b884053169d5a05dd9ab001e45af3c7ae0804a 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/reservation.create.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/reservation.create.js
@@ -6,6 +6,7 @@ import { Growl } from 'primereact/components/growl/Growl';
 import AppLoader from '../../layout/components/AppLoader';
 import PageHeader from '../../layout/components/PageHeader';
 import UIConstants from '../../utils/ui.constants';
+import Flatpickr from "react-flatpickr";
 import { Calendar } from 'primereact/calendar';
 import { InputMask } from 'primereact/inputmask';
 import { Dropdown } from 'primereact/dropdown';
@@ -18,6 +19,9 @@ import ProjectService from '../../services/project.service';
 import ReservationService from '../../services/reservation.service';
 import UnitService from '../../utils/unit.converter';
 import Jeditor from '../../components/JSONEditor/JEditor';
+import UtilService from '../../services/util.service';
+
+import "flatpickr/dist/flatpickr.css";
 
 /**
  * Component to create a new Reservation
@@ -38,7 +42,7 @@ export class ReservationCreate extends Component {
             reservation: { 
                 name: '',
                 description: '', 
-                start_time: '',
+                start_time: null,
                 duration: '',
                 project: (props.match?props.match.params.project:null) || null,
             },
@@ -78,9 +82,11 @@ export class ReservationCreate extends Component {
     async initReservation() {
         const promises = [  ProjectService.getProjectList(),
                             ReservationService.getReservationTemplates(),
+                            UtilService.getUTC()
                         ];
         let emptyProjects = [{url: null, name: "Select Project"}];
        Promise.all(promises).then(responses => {
+            let systemTime = moment.utc(responses[2]);
             this.projects = emptyProjects.concat(responses[0]);
             this.reservationTemplates = responses[1];
 
@@ -95,8 +101,9 @@ export class ReservationCreate extends Component {
                 paramsSchema: schema,
                 isLoading: false,
                 reservationTemplate: reservationTemplate,
+                systemTime: systemTime
             });
-            });    
+        });    
         
     }
     
@@ -209,7 +216,6 @@ export class ReservationCreate extends Component {
                 }
             }
         }
-        
         this.setState({errors: errors, validFields: validFields});
         if (Object.keys(validFields).length === Object.keys(this.formRules).length) {
             validForm = true;
@@ -232,7 +238,7 @@ export class ReservationCreate extends Component {
         }
     }
 
-    saveReservation(){
+    async saveReservation(){
         let reservation = this.state.reservation;
         let project = this.projects.find(project => project.name === reservation.project);
         reservation['start_time'] = moment(reservation['start_time']).format(UIConstants.CALENDAR_DATETIME_FORMAT);
@@ -240,13 +246,13 @@ export class ReservationCreate extends Component {
         reservation['project']=  project ? project.url: null;
         reservation['specifications_template']= this.reservationTemplates[0].url;
         reservation['specifications_doc']= this.paramsOutput;
-        reservation = ReservationService.saveReservation(reservation); 
-        if (reservation && reservation !== null){
+        reservation = await ReservationService.saveReservation(reservation); 
+        if (reservation && reservation.id){
             const dialog = {header: 'Success', detail: 'Reservation is created successfully. Do you want to create another Reservation?'};
             this.setState({ dialogVisible: true, dialog: dialog,  paramsOutput: {}, showDialog: false, isDirty: false})
-        }  else {
+        }/*  else {
             this.growl.show({severity: 'error', summary: 'Error Occured', detail: 'Unable to save Reservation', showDialog: false, isDirty: false});
-        }
+        }*/
     }
 
     /**
@@ -356,20 +362,27 @@ export class ReservationCreate extends Component {
                             <div className="p-field p-grid">
                                     <label htmlFor="reservationName" className="col-lg-2 col-md-2 col-sm-12">From Date <span style={{color:'red'}}>*</span></label>
                                     <div className="col-lg-3 col-md-3 col-sm-12">
-                                        <Calendar 
-                                            d dateFormat="yy-mm-dd"
-                                            value= {this.state.reservation.start_time}
-                                            onChange= {e => this.setParams('start_time',e.value)}
-                                            data-testid="start_time"
-                                            tooltip="Moment at which the reservation starts from, that is, when its reservation can run." tooltipOptions={this.tooltipOptions}
-                                            showIcon={true}
-                                            showTime= {true}
-                                            showSeconds= {true}
-                                            hourFormat= "24"
-                                        />
-                                    
-                                        <label className={this.state.errors.from?"error":"info"}>
-                                            {this.state.errors.start_time ? this.state.errors.start_time : ""}
+                                        <Flatpickr data-enable-time data-input options={{
+                                                    "inlineHideInput": true,
+                                                    "wrap": true,
+                                                    "enableSeconds": true,
+                                                    "time_24hr": true,
+                                                    "allowInput": true,
+                                                    "defaultDate": this.state.systemTime.format(UIConstants.CALENDAR_DEFAULTDATE_FORMAT),
+                                                    "defaultHour": this.state.systemTime.hours(),
+                                                    "defaultMinute": this.state.systemTime.minutes()
+                                                    }}
+                                                    title="Start of this reservation"
+                                                    value={this.state.reservation.start_time}
+                                                    onChange= {value => {this.setParams('start_time', value[0]?value[0]:this.state.reservation.start_time);
+                                                        this.setReservationParams('start_time', value[0]?value[0]:this.state.reservation.start_time)}} >
+                                            <input type="text" data-input className={`p-inputtext p-component ${this.state.errors.start_time && this.state.touched.start_time?'input-error':''}`} />
+                                            <i className="fa fa-calendar" data-toggle style={{position: "absolute", marginLeft: '-25px', marginTop:'5px', cursor: 'pointer'}} ></i>
+                                            <i className="fa fa-times" style={{position: "absolute", marginLeft: '-50px', marginTop:'5px', cursor: 'pointer'}} 
+                                                onClick={e => {this.setParams('start_time', ''); this.setReservationParams('start_time', '')}}></i>
+                                        </Flatpickr>
+                                        <label className={this.state.errors.start_time && this.state.touched.start_time?"error":"info"}>
+                                            {this.state.errors.start_time && this.state.touched.start_time ? this.state.errors.start_time : ""}
                                         </label>
                                     </div>
                                     <div className="col-lg-1 col-md-1 col-sm-12"></div>
@@ -380,6 +393,8 @@ export class ReservationCreate extends Component {
                                             value={this.state.reservation.duration} 
                                             mask="99:99:99" 
                                             placeholder="HH:mm:ss" 
+                                            tooltip="Duration of this reservation. If it is empty, then this reservation is indefinite."
+                                            tooltipOptions={this.tooltipOptions}
                                             onChange= {e => this.setParams('duration',e.value)}
                                             ref={input =>{this.input = input}}
                                             />
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
index 828386d19450af0473e199ad44430a7b4491e8ed..56437953e4ee0ed1bd91c69fda2fd9512bb7f703 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/routes/Timeline/view.js
@@ -845,9 +845,9 @@ export class TimelineView extends Component {
         if (this.state.redirect) {
             return <Redirect to={ {pathname: this.state.redirect} }></Redirect>
         }
-         if (this.state.loader) {
-            return <AppLoader />
-        }
+        //  if (this.state.loader) {
+        //     return <AppLoader />
+        // }
         const isSUDetsVisible = this.state.isSUDetsVisible;
         const isTaskDetsVisible = this.state.isTaskDetsVisible;
         const canExtendSUList = this.state.canExtendSUList;
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
index 095f5b009d342fdc124972bcd8ece09ac4eab7d3..9e110bc09653909d2045fea90ae3b68107cefaa7 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/cycle.service.js
@@ -100,7 +100,7 @@ const CycleService = {
         return response.data;
       } catch (error) {
         console.log(error.response.data);
-        return error.response.data;
+        //return error.response.data;
       }
     },
     deleteCycleQuota: async function(cycleQuota) {
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js
index 2ad00beed53a2655373cb373486180ab375ef8a1..5613c91deba01e0375f622e7e16700d872c9a494 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/project.service.js
@@ -68,10 +68,14 @@ const ProjectService = {
     saveProject: async function(project, projectQuota) {
       try {
         const response = await axios.post(('/api/project/'), project);
-        project = response.data
-        for (let quota of projectQuota) {
+        project = response.data;
+        project['isQuotaCreated'] = true;
+        for (let  quota of projectQuota) {
           quota.project = project.url;
-          this.saveProjectQuota(quota);
+          let response = await this.saveProjectQuota(quota);
+          if (response.status > 299) {
+              project['isQuotaCreated'] = false;
+          }
         }
         return response.data;
       } catch (error) {
@@ -83,29 +87,33 @@ const ProjectService = {
     updateProject: async function(id, project) {
       try {
         const response = await axios.put((`/api/project/${id}/`), project);
-        return response.data;
+        project = response.data;
+        project['isUpdated'] = true;
+        return project;
       } catch (error) {
-        // console.log(error);
         console.log(error.response.data);
-        return error.response.data;
+        project = error.response.data;
+        project['isUpdated'] = false;
+        return project;
       }
     },
     saveProjectQuota: async function(projectQuota) {
       try {
         const response = await axios.post(('/api/project_quota/'), projectQuota);
-        return response.data;
+        return response;
       } catch (error) {
         console.error(error);
-        return null;
+        return error.response;
       }
     },
     updateProjectQuota: async function(projectQuota) {
+      const response = null;
       try {
         const response = await axios.put(`/api/project_quota/${projectQuota.id}/`, projectQuota);
         return response.data;
       } catch (error) {
         console.error(error);
-        return null;
+        return response;
       }
     },
     deleteProjectQuota: async function(projectQuota) {
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
index db6284425c56b108d1b5ff8dd08a341e6a78a9ef..eb1d3364f5d71f6eb31b17ba27803daafdd6f057 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/services/schedule.service.js
@@ -493,9 +493,10 @@ const ScheduleService = {
     updateSUDraftFromObservStrategy: async function(observStrategy,schedulingUnit,tasks,tasksToUpdate,station_groups) {
         try {
             delete schedulingUnit['duration'];
-           
+            schedulingUnit['isSUUpdated'] = false;
             schedulingUnit = await this.updateSchedulingUnitDraft(schedulingUnit);
             if (!schedulingUnit.error) {
+                schedulingUnit['isSUUpdated'] = true;
                 for (const taskToUpdate in tasksToUpdate) {
                     let task = tasks.find(task => { return task.name === taskToUpdate});
                     task.specifications_doc = observStrategy.template.tasks[taskToUpdate].specifications_doc;
@@ -515,6 +516,7 @@ const ScheduleService = {
             return schedulingUnit;
         }   catch(error) {
             console.error(error);
+            schedulingUnit['isSUUpdated'] = false;
             return {
                 error: true,
                 message: 'Unable to Update Task Drafts'
diff --git a/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js b/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js
index b4ca89eb6f0b31d99092b8d978ffb1e0e9c695f3..b2cdb71562603a663bddc1420395566d4a823afb 100644
--- a/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js
+++ b/SAS/TMSS/frontend/tmss_webapp/src/utils/ui.constants.js
@@ -3,6 +3,15 @@ const UIConstants = {
     timeline: {
         types: { NORMAL: "NORMAL", WEEKVIEW:"WEEKVIEW"}
     },
+    httpStatusMessages: {
+        400: {severity: 'error', summary: 'Error', sticky: true, detail: 'Error while process request, please contact system admin'},
+        401: {severity: 'error', summary: 'Error', sticky: true, detail: 'Not authenticated, Please retry to login with valid credential'},
+        403: {severity: 'error', summary: 'Error', sticky: true, detail: 'Unknown request, please contact system admin'},
+        404: {severity: 'error', summary: 'Error', sticky: true, detail: 'URL is not recognized, please contact system admin'},
+        408: {severity: 'error', summary: 'Error', sticky: true, detail: 'Request is taking more time to response, please contact system admin'},
+        500: {severity: 'error', summary: 'Error', sticky: true, detail: 'Internal Server Error, URL may not exists, please contact system admin'},
+        503: {severity: 'error', summary: 'Error', sticky: true, detail: 'Server not available, please check system admin'},
+    },
     CALENDAR_DATE_FORMAT: 'yy-mm-dd',
     CALENDAR_DATETIME_FORMAT : 'YYYY-MM-DD HH:mm:ss',
     CALENDAR_TIME_FORMAT: 'HH:mm:ss',