Repository: OpenEnergyPlatform/oeplatform

Issue:
[OPR] If review exists for a table load the reviewer and contributor view from the last review "datamodel" 
## Description of the issue

If the Open Peer Review was started and submitted (not saved) by the reviewer, a so called "datamodel" is created and stored in the database. This datamodel is a JSON file that stored the result of the peer review. It contains a list of the review result for each field of the metadata. The same happens if the contributor reacts to the review and submits the reaction.

It must be possible to load the review result on either the reviewer or contributor page based on the review result stored in the datamodel in the database. Basically this means if a review is present for the table load the inital data from the peereReview table and show it on the page for reviewer or contributor 

## Ideas of solution

- [x] Determine who's turn it currently is (reviewer and contributor pages are slightly different and are handled by different django views) ...  If the reviewer has submitted a paper, the process must be locked for the reviewer until the contributor responds and vice versa.
- [x] Load initial data from databse (datamodel) if a review is present and populate the templates with this data (javaScript)
- [ ] improve datamodel if needed

## Workflow checklist
- [ ] 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/helper.py b/dataedit/helper.py
new file mode 100644
--- /dev/null
+++ b/dataedit/helper.py
@@ -0,0 +1,70 @@
+def merge_field_reviews(current_json, new_json):
+    merged_json = new_json.copy()
+    review_dict = {}
+
+    for contrib_review in merged_json["reviews"]:
+        category = contrib_review["category"]
+        key = contrib_review["key"]
+        review_dict[(category, key)] = contrib_review["fieldReview"]
+
+    for reviewer_review in current_json["reviews"]:
+        category = reviewer_review["category"]
+        key = reviewer_review["key"]
+
+        if (category, key) in review_dict:
+            # Add field evaluations to the existing entry
+            existing_field_review = review_dict[(category, key)]
+            if isinstance(existing_field_review, dict):
+                existing_field_review = [existing_field_review]
+            if isinstance(reviewer_review["fieldReview"], dict):
+                reviewer_review["fieldReview"] = [reviewer_review["fieldReview"]]
+            merged_field_review = existing_field_review + reviewer_review["fieldReview"]
+            review_dict[(category, key)] = merged_field_review
+        else:
+            # Create new entry in Review-Dict
+            review_dict[(category, key)] = reviewer_review["fieldReview"]
+
+    # Insert updated field scores back into the JSON
+    merged_json["reviews"] = [
+        {
+            "category": category,
+            "key": key,
+            "fieldReview": review_dict[(category, key)]
+        }
+        for category, key in review_dict
+    ]
+
+    return merged_json
+
+
+def process_review_data(review_data, metadata, categories):
+    state_dict = {}
+
+    for review in review_data:
+        field_key = review.get('key')
+        field_review = review.get('fieldReview')
+
+        if isinstance(field_review, list):
+            # Sortiere die fieldReview-Einträge nach dem timestamp (neueste zuerst)
+            sorted_field_review = sorted(field_review, key=lambda x: x.get('timestamp'), reverse=True)
+            latest_field_review = sorted_field_review[0] if sorted_field_review else None
+
+            if latest_field_review:
+                state = latest_field_review.get('state')
+                reviewer_suggestion = latest_field_review.get('reviewerSuggestion')
+            else:
+                state = None
+                reviewer_suggestion = None
+        else:
+            state = field_review.get('state')
+            reviewer_suggestion = field_review.get('reviewerSuggestion')
+
+        if reviewer_suggestion is not None:
+            for category in categories:
+                for item in metadata[category]:
+                    if item['field'] == field_key:
+                        item['reviewer_suggestion'] = reviewer_suggestion
+                        break
+        state_dict[field_key] = state
+
+    return state_dict
diff --git a/dataedit/views.py b/dataedit/views.py
--- a/dataedit/views.py
+++ b/dataedit/views.py
@@ -45,6 +45,7 @@
 from dataedit.models import Table, PeerReview, PeerReviewManager, ReviewDataStatus
 from dataedit.models import View as DBView
 from dataedit.structures import TableTags, Tag
+from dataedit.helper import merge_field_reviews, process_review_data
 from login import models as login_models
 
 from .models import TableRevision
@@ -1971,14 +1972,16 @@ def get(self, request, schema, table, review_id=None):
                 "peer_review_reviewer",
                 kwargs={"schema": schema, "table": table, "review_id": review_id}
             )
-
-            existing_review = PeerReviewManager.filter_opr_by_id(opr_id=review_id).review
+            existing_review = PeerReviewManager.filter_opr_by_id(opr_id=review_id).review.get('reviews', [])
+            categories = ['general', 'spatial', 'temporal', 'source', 'license', 'contributor', 'resource']
+            state_dict = process_review_data(review_data=existing_review, metadata=metadata, categories=categories)
         else:
             url_peer_review = reverse(
                 "peer_review_create",
                 kwargs={"schema": schema, "table": table}
             )
-            existing_review=None
+            # existing_review={}
+            state_dict=None
 
         config_data = {
             "can_add": can_add,
@@ -1993,7 +1996,7 @@ def get(self, request, schema, table, review_id=None):
             "meta": metadata,
             "json_schema": json_schema,
             "field_descriptions_json": json.dumps(field_descriptions),
-            "existing_review": existing_review,
+            "state_dict": json.dumps(state_dict),
         }
         return render(request, 'dataedit/opr_review.html', context=context_meta)
 
@@ -2042,9 +2045,13 @@ def post(self, request, schema, table, review_id=None):
                     )
                     table_review.save(review_type=review_post_type)
                 else:
-                    # Aktiver PeerReview vorhanden, aktualisieren Sie den vorhandenen PeerReview
+                    # Aktiver PeerReview ist vorhanden ... aktualisieren 
+                    current_review_data = active_peer_review.review
+                    merged_review_data = merge_field_reviews(current_json=current_review_data, new_json=review_datamodel)
+
+                    # Set new review values and update existing review
                     active_peer_review.is_finished = review_finished
-                    active_peer_review.review = review_datamodel
+                    active_peer_review.review = merged_review_data
                     active_peer_review.reviewer = request.user
                     active_peer_review.contributor = contributor
                     active_peer_review.update(review_type=review_post_type)
@@ -2074,22 +2081,10 @@ def get(self, request, schema, table, review_id):
         json_schema = self.load_json_schema()
         field_descriptions = self.get_all_field_descriptions(json_schema)
         review_data = peer_review.review.get('reviews', [])
-        state_dict = {}
+        
         categories = ['general', 'spatial', 'temporal', 'source', 'license', 'contributor', 'resource']
-
-        for review in review_data:
-            field_key = review.get('key')
-            state = review.get('fieldReview', {}).get('state')
-            state_dict[field_key] = state
-            reviewer_suggestion = review.get('fieldReview', {}).get('reviewerSuggestion')
-            # print(reviewer_suggestion)
-            if reviewer_suggestion is not None:
-                review['value'] = reviewer_suggestion
-                for category in categories:
-                    for item in metadata[category]:
-                        if item['field'] == field_key:
-                            item['reviewer_suggestion'] = reviewer_suggestion
-
+        state_dict = process_review_data(review_data=review_data, metadata=metadata, categories=categories)    
+        
         context_meta = {"config": json.dumps(
             {"can_add": can_add,
              "url_peer_review": reverse(
@@ -2121,9 +2116,10 @@ def post(self, request, schema, table, review_id):
             review_datamodel = review_data.get("reviewData")
             review_state = review_data.get("reviewFinished")
             current_opr = PeerReviewManager.filter_opr_by_id(opr_id=review_id)
-            # existing_reviews = current_opr.review
-            # combined_reviews = existing_reviews + [review_datamodel]
-            current_opr.review = review_datamodel
+            existing_reviews = current_opr.review
+            merged_review = merge_field_reviews(current_json=existing_reviews, new_json=review_datamodel)
+
+            current_opr.review = merged_review
             current_opr.update(review_type=review_post_type)
 
         return render(request, 'dataedit/opr_contributor.html', context=context)


Test patch: