Repository: OpenEnergyPlatform/oeplatform

Issue:
The "Active reviews" section on profile page is not updated if the latest review is closed
## Description of the issue

The "active reviews" section on the Profile page ("Reviews" tab) is designed to show the latest active and open review. It is meant to be a convenience feature for the user to access the review where the last interaction was applied.

Currently, this section is not updated if the last review the user was part of is closed. This is very problematic as this is the only way the contributor user can access a review. Once the latest review is closed, any previously started review will not be accessible anymore.

## Steps to Reproduce
1. Start a review & submit
2. Start another review that was created by the same user & Submit
3. Let the contributor user submit the review. (he can just submit the second review)
4. Finish the second review
5. The contributor user will not be able to reach the first review again.

## Ideas of solution

Update the filter method that query the latest review from the database by including the "is review open" condition in the filter query and update the "Active reviews" Section on the Profile page.

## Context and Environment
* Version used: 
* Operating system: 
* Environment setup and (python) version: 

## Workflow checklist
- [x] I am aware of the workflow in [CONTRIBUTING.md](https://github.com/OpenEnergyPlatform/oeplatform/blob/develop/CONTRIBUTING.md)



Discussion:

Resolving patch:
diff --git a/dataedit/models.py b/dataedit/models.py
--- a/dataedit/models.py
+++ b/dataedit/models.py
@@ -384,6 +384,28 @@ def filter_opr_by_reviewer(reviewer_user):
             review_id__status=ReviewDataStatus.SAVED.value
         )
     
+    @staticmethod
+    def filter_latest_open_opr_by_reviewer(reviewer_user):
+        """
+        Get the last open peer review for the given contributor.
+
+        Args:
+            contributor_user (User): The contributor user.
+
+        Returns:
+            PeerReview: Last open peer review or None if not found.
+        """
+        try:
+            return PeerReview.objects.filter(
+                reviewer=reviewer_user,
+                is_finished=False
+            ).exclude(
+                review_id__current_reviewer=Reviewer.CONTRIBUTOR.value,
+                review_id__status=ReviewDataStatus.SAVED.value
+            ).latest('date_started')
+        except PeerReview.DoesNotExist:
+            return None
+
     @staticmethod
     def filter_opr_by_contributor(contributor_user):
         """
@@ -404,27 +426,27 @@ def filter_opr_by_contributor(contributor_user):
             review_id__status=ReviewDataStatus.SAVED.value
         )
     
-    # @staticmethod
-    # def get_last_open_peer_review(contributor_user):
-    #     """
-    #     Get the last open peer review for the given contributor.
-
-    #     Args:
-    #         contributor_user (User): The contributor user.
-
-    #     Returns:
-    #         PeerReview: Last open peer review or None if not found.
-    #     """
-    #     try:
-    #         return PeerReview.objects.filter(
-    #             contributor=contributor_user,
-    #             is_finished=False
-    #         ).exclude(
-    #             review_id__current_reviewer=Reviewer.REVIEWER.value,
-    #             review_id__status=ReviewDataStatus.SAVED.value
-    #         ).latest('date_started')
-    #     except PeerReview.DoesNotExist:
-    #         return None
+    @staticmethod
+    def filter_latest_open_opr_by_contributor(contributor_user):
+        """
+        Get the last open peer review for the given contributor.
+
+        Args:
+            contributor_user (User): The contributor user.
+
+        Returns:
+            PeerReview: Last open peer review or None if not found.
+        """
+        try:
+            return PeerReview.objects.filter(
+                contributor=contributor_user,
+                is_finished=False
+            ).exclude(
+                review_id__current_reviewer=Reviewer.REVIEWER.value,
+                review_id__status=ReviewDataStatus.SAVED.value
+            ).latest('date_started')
+        except PeerReview.DoesNotExist:
+            return None
         
     @staticmethod
     def filter_opr_by_table(schema, table):
diff --git a/login/views.py b/login/views.py
--- a/login/views.py
+++ b/login/views.py
@@ -52,6 +52,7 @@ class ReviewsView(View):
     def get(self, request, user_id):
         """
         Load the reviews the user identifyes as reviewer and contributor for.
+
         :param request: A HTTP-request object sent by the Django framework.
         :param user_id: An user id
         :return: Profile renderer
@@ -61,28 +62,57 @@ def get(self, request, user_id):
         ##################################################################
         # get reviewer pov reviews
         ##################################################################
+        reviewed_context = {}
+
+        # get all reviews where current user is the reviewer
         peer_review_reviews = PeerReviewManager.filter_opr_by_reviewer(
             reviewer_user=user
         )
+
         latest_review = peer_review_reviews.last()
-        # print(latest_review)
         if latest_review is not None:
-            review_history = peer_review_reviews.exclude(pk=latest_review.pk)
-            current_manager = PeerReviewManager.load(latest_review)
-            # Update days open value stored in peerReviewManager table
-            current_manager.update_open_since(opr=latest_review)
-            latest_review_status = current_manager.status
-            latest_review_days_open = current_manager.is_open_since
-            current_reviewer = current_manager.current_reviewer
-            reviewed_context = {
-                "latest": latest_review,
-                "latest_status": latest_review_status,
-                "current_reviewer": current_reviewer,
-                "latest_days_open": latest_review_days_open, 
+
+            reviewed_context.update({"reviews_available": True}) # TODO: use this in template
+            
+            # Get the latest open peer review (where this user is the reviewer)
+            active_peer_review_revewier = PeerReviewManager.filter_latest_open_opr_by_reviewer(
+                reviewer_user=user
+            )
+
+            review_history = peer_review_reviews.exclude(pk=active_peer_review_revewier.pk)
+            
+            # Context da for the "All reviews" section on the profile page
+            reviewed_context.update({
+                "latest": latest_review, # mainly used to check if review exists
                 "history": review_history,
-            }
+            })
+
+            
+            if active_peer_review_revewier is not None:
+                current_manager = PeerReviewManager.load(active_peer_review_revewier)
+                # Update days open value stored in peerReviewManager table
+                current_manager.update_open_since(opr=active_peer_review_revewier)
+                latest_review_status = current_manager.status
+                latest_review_days_open = current_manager.is_open_since
+                current_reviewer = current_manager.current_reviewer
+
+                # All data in this dict is related to the latest active opr
+                # Context da for the "Active reviews" section on the profile page
+                reviewed_context.update({ 
+                    "latest_active": active_peer_review_revewier, # will always be updated if there is another opr available
+                    "latest_status": latest_review_status,
+                    "current_reviewer": current_reviewer,
+                    "latest_days_open": latest_review_days_open, 
+                })
+            else: # TODO remove else if not causes error in template
+                reviewed_context.update({ 
+                    "latest_active": None,
+                    "latest_status": None,
+                    "current_reviewer": None,
+                    "latest_days_open": None, 
+                })
         else:
-            reviewed_context = None
+            reviewed_context.update({"reviews_available": False})  # TODO: use this in template
 
         # Sort the reviews by table name
         sorted_reviews = sorted(peer_review_reviews, key=lambda x: x.table)
@@ -94,29 +124,58 @@ def get(self, request, user_id):
         ##################################################################
         # get contributor pov reviews
         ##################################################################
+        reviewed_contributions_context = {}
+
+        # all peer reviews related to the contributor user
         peer_review_contributions = PeerReviewManager.filter_opr_by_contributor(
             contributor_user=user
         )
         latest_reviewed_contribution = peer_review_contributions.last()
         if latest_reviewed_contribution is not None:
+
+            reviewed_contributions_context.update({"reviews_available": True}) # TODO: use this in template
+
+            # Get the latest open peer review (where this user is the contributor)
+            active_peer_review_contributor =  PeerReviewManager.filter_latest_open_opr_by_contributor(
+                contributor_user=user
+            )
+
             reviewed_contribution_history = peer_review_contributions.exclude(
-                pk=latest_reviewed_contribution.pk
+                pk=active_peer_review_contributor.pk
             )
-            current_manager = PeerReviewManager.load(latest_reviewed_contribution)
-            # Update days open value stored in peerReviewManager table
-            current_manager.update_open_since(opr=latest_reviewed_contribution)
-            latest_reviewed_contribution_status = current_manager.status
-            latest_reviewed_contribution_days_open = current_manager.is_open_since
-            current_reviewer = current_manager.current_reviewer
+
+            # Context da for the "All reviews" section on the profile page
             reviewed_contributions_context = {
-                "latest": latest_reviewed_contribution,
-                "latest_status": latest_reviewed_contribution_status,
-                "current_reviewer": current_reviewer,
-                "latest_days_open": latest_reviewed_contribution_days_open,
+                "latest": latest_reviewed_contribution, # mainly used to check if review exists
                 "history": reviewed_contribution_history,
             }
+
+            if active_peer_review_contributor is not None:
+
+                current_manager = PeerReviewManager.load(active_peer_review_contributor)
+                # Update days open value stored in peerReviewManager table
+                current_manager.update_open_since(opr=active_peer_review_contributor)
+                latest_reviewed_contribution_status = current_manager.status
+                latest_reviewed_contribution_days_open = current_manager.is_open_since
+                current_reviewer = current_manager.current_reviewer
+
+                # All data in this dict is related to the latest active opr
+                # Context da for the "Active reviews" section on the profile page
+                reviewed_contributions_context.update({ 
+                    "latest_active": active_peer_review_contributor, # will always be updated if there is another opr available
+                    "latest_status": latest_reviewed_contribution_status,
+                    "current_reviewer": current_reviewer,
+                    "latest_days_open": latest_reviewed_contribution_days_open, 
+                })
+            else: # TODO remove else if not causes error in template
+                reviewed_contributions_context.update({ 
+                    "latest_active": None,
+                    "latest_status": None,
+                    "current_reviewer": None,
+                    "latest_days_open": None, 
+                })         
         else:
-            reviewed_contributions_context = None
+            reviewed_contributions_context.update({"reviews_available": False}) # TODO: use this in template
 
         # Sort the reviews by table name
         sorted_contributions = sorted(peer_review_contributions, key=lambda x: x.table)


Test patch: