Repository: OpenEnergyPlatform/oeplatform

Issue:
[OPR] Apply review result to oemetadata ressource (update metadata)
## Description of the issue

When a review is complete, the result must be applied to the reviewed metadata. Any field that has a newValue must be updated. 

## Ideas of solution

- Write the new values back to the oemetadata json 
- validate the structure of the new oemetadata json (we can use the upload metadata RESTApi endpoint)

## 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/metadata/__init__.py b/dataedit/metadata/__init__.py
--- a/dataedit/metadata/__init__.py
+++ b/dataedit/metadata/__init__.py
@@ -163,9 +163,6 @@ def load_metadata_from_db(schema, table):
 
     from dataedit.models import Table
 
-    # TODO maybe change this function to load metadata from Table.oemetadata
-    # (JSONB)field? or keep old functionality?
-    # metadata = actions.get_comment_table(schema, table)
     metadata = Table.load(schema=schema, table=table).oemetadata
 
     metadata = parse_meta_data(metadata, schema, table)
diff --git a/dataedit/views.py b/dataedit/views.py
--- a/dataedit/views.py
+++ b/dataedit/views.py
@@ -14,7 +14,7 @@
 from django.contrib.auth.decorators import login_required
 from django.contrib.auth.mixins import LoginRequiredMixin
 from django.contrib.postgres.search import SearchQuery
-from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
+from django.core.exceptions import PermissionDenied
 from django.db.models import Count, Q
 from django.http import Http404, HttpResponse, HttpResponseBadRequest, JsonResponse
 from django.shortcuts import get_object_or_404, redirect, render
@@ -920,22 +920,19 @@ def get(self, request, schema, table):
         ) or schema.startswith("_"):
             raise Http404("Schema not accessible")
 
-        tags = []  # TODO: Unused - Remove
-
-        # db = sec.dbname
-
         engine = actions._get_engine()
 
         if not engine.dialect.has_table(engine, table, schema=schema):
-            raise Http404
+            raise Http404("Table does not exist in the database")
 
-        # create a table for the metadata linked to the given table
         actions.create_meta(schema, table)
-
-        # the metadata are stored in the table's comment
         metadata = load_metadata_from_db(schema, table)
+        table_obj = Table.load(schema, table)
+        if table_obj is None:
+            raise Http404("Table object could not be loaded")
+
+        oemetadata = table_obj.oemetadata
 
-        # setup oemetadata string order according to oem v1.5.1
         from dataedit.metadata import TEMPLATE_V1_5
 
         def iter_oem_key_order(metadata: dict):
@@ -944,21 +941,16 @@ def iter_oem_key_order(metadata: dict):
                 yield key, metadata.get(key)
 
         ordered_oem_151 = {key: value for key, value in iter_oem_key_order(metadata)}
-
-        # the key order of the metadata matters
         meta_widget = MetaDataWidget(ordered_oem_151)
-
         revisions = []
 
-        # load the admin interface
         api_changes = change_requests(schema, table)
         data = api_changes.get("data")
         display_message = api_changes.get("display_message")
         display_items = api_changes.get("display_items")
 
         is_admin = False
-        can_add = False  # can upload data
-        table_obj = Table.load(schema, table)
+        can_add = False
         if request.user and not request.user.is_anonymous:
             is_admin = request.user.has_admin_permissions(schema, table)
             level = request.user.get_table_permission_level(table_obj)
@@ -967,19 +959,14 @@ def iter_oem_key_order(metadata: dict):
         table_label = table_obj.human_readable_name
 
         table_views = DBView.objects.filter(table=table).filter(schema=schema)
-
         default = DBView(name="default", type="table", table=table, schema=schema)
-
         view_id = request.GET.get("view")
 
-        if view_id == "default":
-            current_view = default
-        else:
-            try:
-                # at first, try to use the view, that is passed as get argument
-                current_view = table_views.get(id=view_id)
-            except ObjectDoesNotExist:
-                current_view = default
+        current_view = (
+            default
+            if view_id == "default" or not table_views.filter(id=view_id).exists()
+            else table_views.get(id=view_id)
+        )
 
         table_views = list(chain((default,), table_views))
 
@@ -995,21 +982,17 @@ def iter_oem_key_order(metadata: dict):
         opr_manager = PeerReviewManager()
         reviews = opr_manager.filter_opr_by_table(schema=schema, table=table)
 
-        # Get contributions
-        contributor = PeerReviewManager.load_contributor(schema=schema, table=table)
-        if contributor is not None:
-            opr_context.update({"contributor": contributor})
-        else:
-            opr_context.update({"contributor": None})
-
-        # Get reviews
-        reviewer = PeerReviewManager.load_reviewer(schema=schema, table=table)
-        if contributor is not None:
-            opr_context.update({"reviewer": reviewer})
-        else:
-            opr_context.update({"reviewer": None})
+        opr_context = {
+            "contributor": PeerReviewManager.load_contributor(
+                schema=schema, table=table
+            ),
+            "reviewer": PeerReviewManager.load_reviewer(schema=schema, table=table),
+            "opr_enabled": oemetadata
+            is not None,  # check if the table has the metadata
+        }
 
-        if reviews.last() is not None:
+        opr_result_context = {}
+        if reviews.exists():
             latest_review = reviews.last()
             opr_manager.update_open_since(opr=latest_review)
             current_reviewer = opr_manager.load(latest_review).current_reviewer
@@ -1021,11 +1004,6 @@ def iter_oem_key_order(metadata: dict):
                 }
             )
 
-            # OPR result tab for latest review
-            # TODO: Update this as soon as more then one review can be done per table:
-            # ... check if last review is finished
-            # ... check if any finished review for this table exists
-            # ... get the latest finished review
             if latest_review.is_finished:
                 badge = latest_review.review.get("badge")
                 date_finished = latest_review.date_finished
@@ -1039,7 +1017,6 @@ def iter_oem_key_order(metadata: dict):
                         "review_exists": True,
                     }
                 )
-
         else:
             opr_context.update({"opr_id": None, "opr_current_reviewer": None})
             opr_result_context.update({"review_exists": False, "finished": False})
@@ -1049,15 +1026,13 @@ def iter_oem_key_order(metadata: dict):
         #########################################################
 
         context_dict = {
-            # Not in use?
-            # "comment_on_table": dict(metadata),
             "meta_widget": meta_widget.render(),
             "revisions": revisions,
             "kinds": ["table", "map", "graph"],
             "table": table,
             "schema": schema,
             "table_label": table_label,
-            "tags": tags,
+            # "tags": tags,
             "data": data,
             "display_message": display_message,
             "display_items": display_items,
@@ -1071,8 +1046,6 @@ def iter_oem_key_order(metadata: dict):
             "opr_result": opr_result_context,
         }
 
-        context_dict.update(current_view.options)
-
         return render(request, "dataedit/dataview.html", context=context_dict)
 
     def post(self, request, schema, table):
@@ -1563,6 +1536,7 @@ def update_table_tags(request):
     messasge = messages.success(
         request,
         'Please note that OEMetadata keywords and table tags are synchronized. When submitting new tags, you may notice automatic changes to the table tags on the OEP and/or the "Keywords" field in the metadata.',  # noqa
+        # noqa
     )
 
     return render(
@@ -1980,7 +1954,6 @@ def sort_in_category(self, schema, table, oemetadata):
                 "source": [...],
                 "license": [...],
                 "contributor": [...],
-                "resource": [...]
             }
 
         """
@@ -1992,7 +1965,6 @@ def sort_in_category(self, schema, table, oemetadata):
         source_key_list = []
         license_key_list = []
         contributor_key_list = []
-        resource_key_list = []
 
         for i in val:
             fieldKey = list(i.values())[0]
@@ -2006,8 +1978,6 @@ def sort_in_category(self, schema, table, oemetadata):
                 license_key_list.append(i)
             elif fieldKey.split(".")[0] == "contributors":
                 contributor_key_list.append(i)
-            elif fieldKey.split(".")[0] == "resources":
-                resource_key_list.append(i)
             elif (
                 fieldKey.split(".")[0] == "name"
                 or fieldKey.split(".")[0] == "title"
@@ -2028,7 +1998,6 @@ def sort_in_category(self, schema, table, oemetadata):
             "source": source_key_list,
             "license": license_key_list,
             "contributor": contributor_key_list,
-            "resource": resource_key_list,
         }
 
         return meta
@@ -2106,8 +2075,7 @@ def get(self, request, schema, table, review_id=None):
             can_add = level >= login_models.WRITE_PERM
 
         oemetadata = self.load_json(schema, table, review_id)
-        metadata = self.sort_in_category(schema, table, oemetadata=oemetadata)
-        # Generate URL for peer_review_reviewer
+        metadata = self.sort_in_category(schema, table, oemetadata=oemetadata)        # Generate URL for peer_review_reviewer
         if review_id is not None:
             url_peer_review = reverse(
                 "dataedit:peer_review_reviewer",
@@ -2123,7 +2091,6 @@ def get(self, request, schema, table, review_id=None):
                 "source",
                 "license",
                 "contributor",
-                "resource",
             ]
             state_dict = process_review_data(
                 review_data=existing_review, metadata=metadata, categories=categories
@@ -2199,12 +2166,18 @@ def post(self, request, schema, table, review_id=None):
             - After a review is finished, the table's metadata is updated, and the table
             can be moved to a different schema or topic (TODO).
         """
-        print(review_id)
         context = {}
         if request.method == "POST":
             # get the review data and additional application metadata
             # from user peer review submit/save
             review_data = json.loads(request.body)
+            if review_id:
+                contributor_review = PeerReview.objects.filter(id=review_id).first()
+                if contributor_review:
+                    contributor_review_data = contributor_review.review.get(
+                        "reviews", []
+                    )
+                    review_data["reviewData"]["reviews"].extend(contributor_review_data)
 
             # The type can be "save" or "submit" as this triggers different behavior
             review_post_type = review_data.get("reviewType")
@@ -2261,6 +2234,11 @@ def post(self, request, schema, table, review_id=None):
 
                 save_metadata_to_db(schema, table, metadata)
 
+                if active_peer_review:
+                    # Update the oemetadata in the active PeerReview
+                    active_peer_review.oemetadata = metadata
+                    active_peer_review.save()
+
                 # TODO: also update reviewFinished in review datamodel json
                 # logging.INFO(f"Table {table.name} is now reviewed and can be moved
                 # to the destination schema.")
@@ -2308,7 +2286,6 @@ def get(self, request, schema, table, review_id):
             "source",
             "license",
             "contributor",
-            "resource",
         ]
         state_dict = process_review_data(
             review_data=review_data, metadata=metadata, categories=categories


Test patch: