Skip to content

Commit

Permalink
Change default values for analog option updates to UNDOCUMENTED (#1322)
Browse files Browse the repository at this point in the history
* Change default values for updates to -2

* Unify behaviour & beautify code & forbid invalid keys
  • Loading branch information
jsangmeister committed May 9, 2022
1 parent 64aca77 commit 0c2d716
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 173 deletions.
111 changes: 44 additions & 67 deletions openslides_backend/action/actions/option/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
from ..vote.update import VoteUpdate
from ..vote.user_token_helper import get_user_token

option_keys = ("yes", "no", "abstain")
option_keys_map = {key[0].upper(): key for key in option_keys}


@register_action("option.update")
class OptionUpdateAction(UpdateAction):
Expand All @@ -34,35 +37,35 @@ class OptionUpdateAction(UpdateAction):
def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
"""Update votes and auto calculate yes, no, abstain."""

poll_id_option, poll, option = self._get_poll(instance["id"])
option, poll = self._get_option_and_poll(instance["id"])
state_change = self.check_state_change(instance, poll)

if poll_id_option:
self._handle_poll_option_data(instance, poll)
else:
if option.get("used_as_global_option_in_poll_id"):
self._handle_global_option_data(instance, poll)
else:
self._handle_poll_option_data(instance, poll)

id_to_vote = self._fetch_votes(option.get("vote_ids", []))

action_data_create = []
action_data_update = []
user_token = get_user_token()

for field_name, vote_name in (("yes", "Y"), ("no", "N"), ("abstain", "A")):
if field_name in instance:
vote_id = self._get_vote_id(vote_name, id_to_vote)
for letter, option_key in option_keys_map.items():
if option_key in instance:
vote_id = self._get_vote_id(letter, id_to_vote)
if vote_id is None:
action_data_create.append(
{
"option_id": instance["id"],
"value": vote_name,
"weight": instance[field_name],
"value": letter,
"weight": instance[option_key],
"user_token": user_token,
}
)
else:
action_data_update.append(
{"id": vote_id, "weight": instance[field_name]}
{"id": vote_id, "weight": instance[option_key]}
)
if action_data_create:
self.execute_other_action(VoteCreate, action_data_create)
Expand All @@ -89,23 +92,17 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:

return instance

def _get_poll(self, option_id: int) -> Tuple[bool, Dict[str, Any], Dict[str, Any]]:
def _get_option_and_poll(
self, option_id: int
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
option = self.datastore.get(
FullQualifiedId(self.model.collection, option_id),
["poll_id", "used_as_global_option_in_poll_id", "vote_ids", "meeting_id"],
)
poll_id_option = False
if option.get("poll_id"):
poll_id = option["poll_id"]
poll_id_option = True
elif option.get("used_as_global_option_in_poll_id"):
poll_id = option["used_as_global_option_in_poll_id"]
else:
raise ActionException("Dont find poll for option")
return (
poll_id_option,
option,
self.datastore.get(
FullQualifiedId(Collection("poll"), poll_id),
FullQualifiedId(Collection("poll"), option["poll_id"]),
[
"id",
"state",
Expand All @@ -119,59 +116,42 @@ def _get_poll(self, option_id: int) -> Tuple[bool, Dict[str, Any], Dict[str, Any
],
lock_result=["type"],
),
option,
)

def _handle_poll_option_data(
self, instance: Dict[str, Any], poll: Dict[str, Any]
) -> None:
data = self._get_data(instance)

if poll.get("type") == "analog":
if poll.get("pollmethod") == "N":
instance["no"] = data.get("no", "0.000000")
else:
instance["yes"] = data.get("yes", "0.000000")
if poll.get("pollmethod") in ("YN", "YNA"):
instance["no"] = data.get("no", "0.000000")
if poll.get("pollmethod") == "YNA":
instance["abstain"] = data.get("abstain", "0.000000")
pollmethod = poll["pollmethod"]
for letter, key in option_keys_map.items():
if letter in pollmethod:
instance[key] = data.get(key, "-2.000000")
else:
raise ActionException(
f"Pollmethod {pollmethod} does not support {key} votes"
)

def _handle_global_option_data(
self, instance: Dict[str, Any], poll: Dict[str, Any]
) -> None:
data = self._get_data(instance)

if poll.get("type") == "analog":
global_yes_enabled = poll.get("global_yes") and poll.get("pollmethod") in (
"Y",
"N",
)
if "yes" in data and global_yes_enabled:
instance["yes"] = data.get("yes", "0.000000")

global_no_enabled = poll.get("global_no") and poll.get("pollmethod") in (
"Y",
"N",
)
if "no" in data and global_no_enabled:
instance["no"] = data.get("no", "0.000000")

global_abstain_enabled = poll.get("global_abstain") and poll.get(
"pollmethod"
) in ("Y", "N")
if "abstain" in data and global_abstain_enabled:
instance["abstain"] = data.get("abstain", "0.000000")
for key in option_keys:
if poll.get(f"global_{key}") and poll.get("pollmethod") in ("Y", "N"):
instance[key] = data.get(key, "-2.000000")
elif key in data:
raise ActionException(
f"Global {key} votes are not allowed for this poll"
)

def _get_data(self, instance: Dict[str, Any]) -> Dict[str, Any]:
data = dict()
if "Y" in instance:
data["yes"] = instance.pop("Y")
if "N" in instance:
data["no"] = instance.pop("N")
if "A" in instance:
data["abstain"] = instance.pop("A")
return data
return {
key: instance.pop(letter)
for letter, key in option_keys_map.items()
if letter in instance
}

def _fetch_votes(self, vote_ids: List[int]) -> Dict[int, Dict[str, Any]]:
get_many_request = GetManyRequest(Collection("vote"), vote_ids, ["value"])
Expand All @@ -190,17 +170,14 @@ def _get_vote_id(
def check_state_change(
self, instance: Dict[str, Any], poll: Dict[str, Any]
) -> bool:
if poll.get("type") != Poll.TYPE_ANALOG:
return False
if poll.get("state") != Poll.STATE_CREATED:
return False

if instance.get("Y") or instance.get("N") or instance.get("A"):
return True
return False
return (
poll.get("type") == Poll.TYPE_ANALOG
and poll.get("state") == Poll.STATE_CREATED
and any(letter in instance for letter in option_keys_map.keys())
)

def check_permissions(self, instance: Dict[str, Any]) -> None:
_, poll, _ = self._get_poll(instance["id"])
_, poll = self._get_option_and_poll(instance["id"])
content_object_id = poll.get("content_object_id", "")
meeting_id = poll["meeting_id"]
check_poll_or_option_perms(
Expand Down
6 changes: 6 additions & 0 deletions openslides_backend/action/actions/poll/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
):
instance["state"] = Poll.STATE_PUBLISHED

# set votescast, votesvalid, votesinvalid defaults
if poll["type"] == Poll.TYPE_ANALOG:
for field in ("votescast", "votesvalid", "votesinvalid"):
if field not in instance:
instance[field] = "-2.000000"

return instance

def check_100_percent_base(self, instance: Dict[str, Any]) -> None:
Expand Down

0 comments on commit 0c2d716

Please sign in to comment.