Skip to content

Commit

Permalink
Create mixin for motion update and create payload validation
Browse files Browse the repository at this point in the history
  • Loading branch information
luisa-beerboom committed Oct 12, 2023
1 parent 2d8d4a4 commit fa95426
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 57 deletions.
1 change: 1 addition & 0 deletions openslides_backend/action/actions/motion/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
create_forwarded,
delete,
follow_recommendation,
json_upload,
reset_recommendation,
reset_state,
set_recommendation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from typing import Any, Dict

from openslides_backend.shared.patterns import fqid_from_collection_and_id

from .set_number_mixin import SetNumberMixin


class MotionCheckCreateUpdatePayloadMixin(SetNumberMixin):
"""
TODO: Add description
"""

def get_payload_integrity_error_message(
self, instance: Dict[str, Any], is_update: bool = False
) -> str | None:
meeting_id = instance["meeting_id"] if not is_update else 0
if is_update:
if (
instance.get("text")
or instance.get("amendment_paragraphs")
or instance.get("reason") == ""
or instance.get("number")
):
motion = self.datastore.get(
fqid_from_collection_and_id(self.model.collection, instance["id"]),
["text", "amendment_paragraphs", "meeting_id"],
)
meeting_id = motion["meeting_id"]

if instance.get("text"):
if not motion.get("text"):
return (
"Cannot update text, because it was not set in the old values."
)
if instance.get("amendment_paragraphs"):
if not motion.get("amendment_paragraphs"):
return "Cannot update amendment_paragraphs, because it was not set in the old values."
else:
if instance.get("lead_motion_id"):
if instance.get("statute_paragraph_id"):
return "You can't give both of lead_motion_id and statute_paragraph_id."
if not instance.get("text") and not instance.get(
"amendment_paragraphs"
):
return "Text or amendment_paragraphs is required in this context."
if instance.get("text") and instance.get("amendment_paragraphs"):
return "You can't give both of text and amendment_paragraphs"
else:
if not instance.get("text"):
return "Text is required"
if instance.get("amendment_paragraphs"):
return "You can't give amendment_paragraphs in this context"
if instance.get("reason") == "" if is_update else not instance.get("reason"):
meeting = self.datastore.get(
fqid_from_collection_and_id("meeting", meeting_id),
["motions_reason_required"],
)
if meeting.get("motions_reason_required"):
return (
"Reason is required to update."
if is_update
else "Reason is required"
)
if instance.get("number"):
if not self._check_if_unique(
instance["number"], meeting_id, instance["id"]
):
return "Number is not unique."
return None
33 changes: 10 additions & 23 deletions openslides_backend/action/actions/motion/create.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from typing import Any, Dict

from openslides_backend.action.actions.motion.check_create_update_payload_mixin import (
MotionCheckCreateUpdatePayloadMixin,
)

from ....models.models import Motion
from ....permissions.base_classes import Permission
from ....permissions.permission_helper import has_perm
Expand All @@ -21,7 +25,9 @@


@register_action("motion.create")
class MotionCreate(AmendmentParagraphHelper, MotionCreateBase):
class MotionCreate(
AmendmentParagraphHelper, MotionCheckCreateUpdatePayloadMixin, MotionCreateBase
):
"""
Create Action for motions.
"""
Expand Down Expand Up @@ -85,30 +91,14 @@ def prefetch(self, action_data: ActionData) -> None:

def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
# special check logic
error_message = self.get_payload_integrity_error_message(instance)
if error_message:
raise ActionException(error_message)
if instance.get("lead_motion_id"):
if instance.get("statute_paragraph_id"):
raise ActionException(
"You can't give both of lead_motion_id and statute_paragraph_id."
)
if not instance.get("text") and not instance.get("amendment_paragraphs"):
raise ActionException(
"Text or amendment_paragraphs is required in this context."
)
if instance.get("text") and instance.get("amendment_paragraphs"):
raise ActionException(
"You can't give both of text and amendment_paragraphs"
)
if instance.get("text") and "amendment_paragraphs" in instance:
del instance["amendment_paragraphs"]
if instance.get("amendment_paragraphs") and "text" in instance:
del instance["text"]
else:
if not instance.get("text"):
raise ActionException("Text is required")
if instance.get("amendment_paragraphs"):
raise ActionException(
"You can't give amendment_paragraphs in this context"
)
if instance.get("amendment_paragraphs"):
self.validate_amendment_paragraphs(instance)
# if lead_motion and not has perm motion.can_manage
Expand All @@ -135,11 +125,8 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
"motions_default_workflow_id",
"motions_default_amendment_workflow_id",
"motions_default_statute_amendment_workflow_id",
"motions_reason_required",
],
)
if meeting.get("motions_reason_required") and not instance.get("reason"):
raise ActionException("Reason is required")

self.set_state_from_workflow(instance, meeting)
self.create_submitters(instance)
Expand Down
65 changes: 65 additions & 0 deletions openslides_backend/action/actions/motion/json_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from ....models.models import Motion
from ....permissions.permissions import Permissions
from ....shared.schema import required_id_schema
from ...mixins.import_mixins import ImportState, JsonUploadMixin
from ...util.default_schema import DefaultSchema
from ...util.register import register_action


@register_action("motion.json_upload")
class MotionJsonUpload(JsonUploadMixin):
"""
Action to allow to upload a json. It is used as first step of an import.
"""

model = Motion()
schema = DefaultSchema(Motion()).get_default_schema(
additional_required_fields={
"data": {
"type": "array",
"items": {
"type": "object",
"properties": {
**model.get_properties(
"title",
"text",
"number",
"reason",
),
# "submitters_verbose": str,
# "submitters_username": str,
# "supporters_verbose": str,
# "supporters_username": str,
# "category_name": str,
# "category_prefix": str,
# "tags": str,
# "block": str,
# "motion_amendment": str,
},
"required": ["title", "text"],
"additionalProperties": False,
},
"minItems": 1,
"uniqueItems": False,
},
"meeting_id": required_id_schema,
}
)

headers = [
# {"property": "title", "type": "string"},
# {"property": "text", "type": "string"},
# {"property": "number", "type": "string", "is_object": True},
# {"property": "reason", "type": "string"},
# {"property": "submitters_verbose", "type": "string", "is_list": True},
# {"property": "submitters_username", "type": "string", "is_object": True, "is_list": True},
# {"property": "supporters_verbose", "type": "string", "is_list": True},
# {"property": "supporters_usernames", "type": "string", "is_object": True, "is_list": True},
# {"property": "category_name", "type": "string", "is_object": True},
# {"property": "category_prefix", "type": "string"},
# {"property": "tags", "type": "string", "is_object": True, "is_list": True},
# {"property": "block", "type": "string", "is_object": True},
# {"property": "motion_amendment", "type": "boolean", "is_object": True},
]
permission = Permissions.Motion.CAN_MANAGE
row_state: ImportState
47 changes: 13 additions & 34 deletions openslides_backend/action/actions/motion/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
from copy import deepcopy
from typing import Any, Dict, List, Optional

from openslides_backend.action.actions.motion.check_create_update_payload_mixin import (
MotionCheckCreateUpdatePayloadMixin,
)
from openslides_backend.shared.typing import HistoryInformation

from ....models.models import Motion
Expand Down Expand Up @@ -30,7 +33,11 @@

@register_action("motion.update")
class MotionUpdate(
UpdateAction, AmendmentParagraphHelper, PermissionHelperMixin, SetNumberMixin
UpdateAction,
AmendmentParagraphHelper,
MotionCheckCreateUpdatePayloadMixin,
PermissionHelperMixin,
SetNumberMixin,
):
"""
Action to update motions.
Expand Down Expand Up @@ -95,34 +102,13 @@ def prefetch(self, action_data: ActionData) -> None:
def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
timestamp = round(time.time())
instance["last_modified"] = timestamp
if (
instance.get("text")
or instance.get("amendment_paragraphs")
or instance.get("reason") == ""
):
motion = self.datastore.get(
fqid_from_collection_and_id(self.model.collection, instance["id"]),
["text", "amendment_paragraphs", "meeting_id"],
)

if instance.get("text"):
if not motion.get("text"):
raise ActionException(
"Cannot update text, because it was not set in the old values."
)
error_message = self.get_payload_integrity_error_message(
instance, is_update=True
)
if error_message:
raise ActionException(error_message)
if instance.get("amendment_paragraphs"):
if not motion.get("amendment_paragraphs"):
raise ActionException(
"Cannot update amendment_paragraphs, because it was not set in the old values."
)
self.validate_amendment_paragraphs(instance)
if instance.get("reason") == "":
meeting = self.datastore.get(
fqid_from_collection_and_id("meeting", motion["meeting_id"]),
["motions_reason_required"],
)
if meeting.get("motions_reason_required"):
raise ActionException("Reason is required to update.")

if instance.get("workflow_id"):
workflow_id = instance.pop("workflow_id")
Expand All @@ -147,13 +133,6 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
if f"{prefix}_extension" in instance:
self.set_extension_reference_ids(prefix, instance)

if instance.get("number"):
meeting_id = self.get_meeting_id(instance)
if not self._check_if_unique(
instance["number"], meeting_id, instance["id"]
):
raise ActionException("Number is not unique.")

return instance

def set_extension_reference_ids(
Expand Down
Empty file.

0 comments on commit fa95426

Please sign in to comment.