diff --git a/data/example-data.json b/data/example-data.json index a4d7b1ee3..b3fb5b098 100644 --- a/data/example-data.json +++ b/data/example-data.json @@ -358,6 +358,7 @@ "motion_poll_default_type": "pseudoanonymous", "motion_poll_default_method": "YNA", "motion_poll_default_onehundred_percent_base": "YNA", + "motion_poll_default_required_majority": "no_majority", "motion_poll_default_group_ids": [ 2, 3 @@ -384,6 +385,7 @@ "assignment_poll_default_type": "pseudoanonymous", "assignment_poll_default_method": "Y", "assignment_poll_default_onehundred_percent_base": "valid", + "assignment_poll_default_required_majority": "no_majority", "assignment_poll_default_group_ids": [ 2, 3 @@ -1956,6 +1958,7 @@ "max_votes_amount": 1, "max_votes_per_option": 1, "onehundred_percent_base": "YNA", + "required_majority": "no_majority", "votesvalid": "2.000000", "votesinvalid": "9.000000", "votescast": "2.000000", @@ -1982,6 +1985,7 @@ "max_votes_amount": 1, "max_votes_per_option": 1, "onehundred_percent_base": "YNA", + "required_majority": "no_majority", "sequential_number": 2, "content_object_id": "motion/1", "option_ids": [ @@ -2008,6 +2012,7 @@ "global_no": true, "global_abstain": true, "onehundred_percent_base": "YNA", + "required_majority": "no_majority", "sequential_number": 3, "content_object_id": "assignment/1", "option_ids": [ @@ -2031,6 +2036,7 @@ "global_no": true, "global_abstain": true, "onehundred_percent_base": "Y", + "required_majority": "no_majority", "votesvalid": "9.000000", "votesinvalid": "2.000000", "votescast": "16.000000", @@ -2059,6 +2065,7 @@ "global_no": true, "global_abstain": false, "onehundred_percent_base": "valid", + "required_majority": "no_majority", "votesvalid": "1.000000", "votesinvalid": "0.000000", "votescast": "1.000000", diff --git a/docs/actions/meeting.update.md b/docs/actions/meeting.update.md index 1c3dd1ea0..891e58f15 100644 --- a/docs/actions/meeting.update.md +++ b/docs/actions/meeting.update.md @@ -122,6 +122,7 @@ motion_poll_default_type: string; motion_poll_default_method: string; motion_poll_default_onehundred_percent_base: string; + motion_poll_default_required_majority: string; motion_poll_default_group_ids: Id[]; motion_poll_default_backend: string; motion_poll_projection_name_order_first: string; @@ -156,6 +157,7 @@ assignment_poll_default_type: string; assignment_poll_default_method: string; assignment_poll_default_onehundred_percent_base: string; + assignment_poll_default_required_majority: string; assignment_poll_default_group_ids: Id[]; assignment_poll_default_backend: string; diff --git a/docs/actions/poll.create.md b/docs/actions/poll.create.md index cfce7457f..e36ba6e6d 100644 --- a/docs/actions/poll.create.md +++ b/docs/actions/poll.create.md @@ -36,6 +36,7 @@ Payload: global_no: boolean, global_abstain: boolean, onehundred_percent_base: string, + required_majority: string, backend: string, // Optional, only for type==named diff --git a/docs/actions/poll.update.md b/docs/actions/poll.update.md index a623e6009..911fae614 100644 --- a/docs/actions/poll.update.md +++ b/docs/actions/poll.update.md @@ -21,6 +21,7 @@ title: string, description: string, onehundred_percent_base: string, + required_majority: string, // Optional, type==analog, every state votesvalid: number, diff --git a/meta b/meta index 324a41108..6520727a6 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit 324a41108459cce406bd319ee59ea61d37daa9d7 +Subproject commit 6520727a6aeeb6bbb6d084f3e00caf336cfb5799 diff --git a/openslides_backend/action/actions/meeting/update.py b/openslides_backend/action/actions/meeting/update.py index ef6472bb8..d02073438 100644 --- a/openslides_backend/action/actions/meeting/update.py +++ b/openslides_backend/action/actions/meeting/update.py @@ -134,6 +134,7 @@ "motion_poll_default_type", "motion_poll_default_method", "motion_poll_default_onehundred_percent_base", + "motion_poll_default_required_majority", "motion_poll_default_group_ids", "motion_poll_default_backend", "motion_poll_projection_name_order_first", @@ -165,6 +166,7 @@ "assignment_poll_default_type", "assignment_poll_default_method", "assignment_poll_default_onehundred_percent_base", + "assignment_poll_default_required_majority", "assignment_poll_default_group_ids", "assignment_poll_default_backend", "topic_poll_default_group_ids", diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index d7f60f48c..cea6c4b38 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -63,6 +63,7 @@ class PollCreateAction( "global_no", "global_abstain", "onehundred_percent_base", + "required_majority", "votesvalid", "votesinvalid", "votescast", diff --git a/openslides_backend/action/actions/poll/update.py b/openslides_backend/action/actions/poll/update.py index 80acbeddf..3b7d21a7d 100644 --- a/openslides_backend/action/actions/poll/update.py +++ b/openslides_backend/action/actions/poll/update.py @@ -45,6 +45,7 @@ class PollUpdateAction( "title", "description", "onehundred_percent_base", + "required_majority", "votesvalid", "votesinvalid", "votescast", diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index cf209a456..3c0d63545 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -556,6 +556,12 @@ class Meeting(Model, MeetingModelMixin): ] }, ) + motion_poll_default_required_majority = fields.CharField( + default="no_majority", + constraints={ + "enum": ["no_majority", "two_third_majority", "absolute_majority"] + }, + ) motion_poll_default_group_ids = fields.RelationListField( to={"group": "used_as_motion_poll_default_id"} ) @@ -634,6 +640,12 @@ class Meeting(Model, MeetingModelMixin): ] }, ) + assignment_poll_default_required_majority = fields.CharField( + default="no_majority", + constraints={ + "enum": ["no_majority", "two_third_majority", "absolute_majority"] + }, + ) assignment_poll_default_group_ids = fields.RelationListField( to={"group": "used_as_assignment_poll_default_id"} ) @@ -1913,6 +1925,12 @@ class Poll(Model, PollModelMixin): ] }, ) + required_majority = fields.CharField( + default="no_majority", + constraints={ + "enum": ["no_majority", "two_third_majority", "absolute_majority"] + }, + ) votesvalid = fields.DecimalField() votesinvalid = fields.DecimalField() votescast = fields.DecimalField() diff --git a/tests/system/action/meeting/test_update.py b/tests/system/action/meeting/test_update.py index 74b9b5557..b653dabe3 100644 --- a/tests/system/action/meeting/test_update.py +++ b/tests/system/action/meeting/test_update.py @@ -382,6 +382,21 @@ def test_update_poll_default_backend_fields(self) -> None: }, ) + def test_update_poll_default_required_majority_fields(self) -> None: + self.basic_test( + { + "motion_poll_default_required_majority": "two_third_majority", + "assignment_poll_default_required_majority": "no_majority", + } + ) + self.assert_model_exists( + "meeting/1", + { + "motion_poll_default_required_majority": "two_third_majority", + "assignment_poll_default_required_majority": "no_majority", + }, + ) + def test_update_poll_default_live_voting_enabled(self) -> None: self.basic_test({"poll_default_live_voting_enabled": True}) self.assert_model_exists( diff --git a/tests/system/action/poll/test_create.py b/tests/system/action/poll/test_create.py index 7f5ff1f91..f7f286827 100644 --- a/tests/system/action/poll/test_create.py +++ b/tests/system/action/poll/test_create.py @@ -35,6 +35,7 @@ def test_create_correct(self) -> None: "global_no": True, "global_abstain": True, "onehundred_percent_base": "Y", + "required_majority": "absolute_majority", "min_votes_amount": 5, "max_votes_amount": 10, "max_votes_per_option": 1, @@ -55,6 +56,7 @@ def test_create_correct(self) -> None: "global_option_id": 2, "state": "finished", "onehundred_percent_base": "Y", + "required_majority": "absolute_majority", "is_pseudoanonymized": False, "min_votes_amount": 5, "max_votes_amount": 10, diff --git a/tests/system/action/poll/test_update.py b/tests/system/action/poll/test_update.py index bfdba6031..12d59f57b 100644 --- a/tests/system/action/poll/test_update.py +++ b/tests/system/action/poll/test_update.py @@ -174,6 +174,14 @@ def test_update_backend(self) -> None: self.assert_status_code(response, 200) self.assert_model_exists("poll/1", {"backend": "long"}) + def test_update_required_majority(self) -> None: + response = self.request( + "poll.update", + {"required_majority": "absolute_majority", "id": 1}, + ) + self.assert_status_code(response, 200) + self.assert_model_exists("poll/1", {"required_majority": "absolute_majority"}) + def test_update_backend_not_allowed(self) -> None: self.set_models({"poll/1": {"state": Poll.STATE_FINISHED}}) response = self.request( diff --git a/tests/system/presenter/test_check_database_all.py b/tests/system/presenter/test_check_database_all.py index 2df737858..0daacccf6 100644 --- a/tests/system/presenter/test_check_database_all.py +++ b/tests/system/presenter/test_check_database_all.py @@ -107,6 +107,7 @@ def get_meeting_defaults(self) -> dict[str, Any]: "motion_poll_default_type": "pseudoanonymous", "motion_poll_default_method": "YNA", "motion_poll_default_onehundred_percent_base": "YNA", + "motion_poll_default_required_majority": "no_majority", "motion_poll_default_backend": "fast", "motion_poll_projection_name_order_first": "last_name", "motion_poll_projection_max_columns": 6, @@ -129,6 +130,7 @@ def get_meeting_defaults(self) -> dict[str, Any]: "assignment_poll_default_type": "pseudoanonymous", "assignment_poll_default_method": "Y", "assignment_poll_default_onehundred_percent_base": "valid", + "assignment_poll_default_required_majority": "no_majority", "assignment_poll_default_backend": "fast", "poll_default_type": "analog", "poll_default_onehundred_percent_base": "YNA",