From 43e30bf762b62dfe43d5db7242d17836af84faa6 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Tue, 7 Oct 2025 16:49:06 +0200 Subject: [PATCH 01/19] Update meta and models --- meta | 2 +- openslides_backend/models/models.py | 30 +++++++++++++++++++---------- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/meta b/meta index b2e83a19c..8ac6804c8 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit b2e83a19cd9d6fd69e7e080bce986b2c25a90fdd +Subproject commit 8ac6804c8904619257472fd2d39c0f62577da704 diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index 047f6658e..e773d80f5 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -1523,7 +1523,8 @@ class ListOfSpeakers(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) moderator_notes = fields.HTMLStrictField() @@ -1685,7 +1686,8 @@ class Topic(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) attachment_meeting_mediafile_ids = fields.RelationListField( @@ -1749,7 +1751,8 @@ class Motion(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) title = fields.CharField(required=True) @@ -2082,7 +2085,8 @@ class MotionCommentSection(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) submitter_can_write = fields.BooleanField() @@ -2135,7 +2139,8 @@ class MotionCategory(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) parent_id = fields.RelationField( @@ -2166,7 +2171,8 @@ class MotionBlock(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) motion_ids = fields.RelationListField( @@ -2329,7 +2335,8 @@ class MotionWorkflow(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) state_ids = fields.RelationListField( @@ -2419,7 +2426,8 @@ class Poll(Model, PollModelMixin): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) crypt_key = fields.CharField( @@ -2556,7 +2564,8 @@ class Assignment(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) candidate_ids = fields.RelationListField( @@ -2876,7 +2885,8 @@ class Projector(Model): read_only=True, constant=True, constraints={ - "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only." + "sequence_scope": "meeting_id", + "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) current_projection_ids = fields.RelationListField( From a20eeb6dd9f9a6a5faf7ab8496d182404b310ede Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Tue, 7 Oct 2025 16:49:43 +0200 Subject: [PATCH 02/19] Remove sequential_number from set_models in tests --- .../system/action/agenda_item/test_assign.py | 22 +--------- .../system/action/agenda_item/test_create.py | 22 +++------- .../system/action/agenda_item/test_delete.py | 7 --- .../action/agenda_item/test_numbering.py | 44 ++++++------------- tests/system/action/agenda_item/test_sort.py | 29 +----------- .../system/action/agenda_item/test_update.py | 20 +++------ tests/system/action/assignment/test_delete.py | 9 ---- tests/system/action/assignment/test_update.py | 10 ----- .../assignment_candidate/test_create.py | 8 ---- .../assignment_candidate/test_delete.py | 10 ----- .../action/assignment_candidate/test_sort.py | 8 ---- .../assignment_candidate/test_update.py | 2 - tests/system/action/base.py | 4 -- .../action/list_of_speakers/test_delete.py | 3 -- .../test_delete_all_speakers.py | 4 -- .../list_of_speakers/test_re_add_last.py | 12 ----- .../action/list_of_speakers/test_update.py | 2 - tests/system/action/mediafile/test_delete.py | 2 +- tests/system/action/meeting/test_archive.py | 4 -- tests/system/action/meeting/test_clone.py | 13 ------ tests/system/action/meeting/test_delete.py | 3 -- .../test_delete_all_speakers_of_all_lists.py | 2 - tests/system/action/meeting/test_import.py | 1 - .../meeting/test_replace_projector_id.py | 2 +- tests/system/action/meeting/test_update.py | 2 - .../action/meeting_mediafile/test_delete.py | 3 -- .../system/action/meeting_user/test_delete.py | 4 -- .../system/action/meeting_user/test_update.py | 4 -- tests/system/action/motion/test_create.py | 3 -- .../action/motion/test_create_amendment.py | 3 -- .../motion/test_create_sequential_number.py | 1 - .../action/motion/test_set_number_mixin.py | 9 ---- .../action/motion/test_set_recommendation.py | 1 - tests/system/action/motion/test_update.py | 11 ----- .../motion/test_update_with_other_actions.py | 1 - .../system/action/motion_block/test_delete.py | 2 - .../system/action/motion_block/test_update.py | 2 - .../action/motion_category/test_create.py | 3 -- .../action/motion_category/test_delete.py | 1 - .../motion_category/test_number_motions.py | 1 - .../action/motion_category/test_sort.py | 2 - .../test_sort_motions_in_categories.py | 1 - .../action/motion_category/test_update.py | 5 --- .../action/motion_comment/test_create.py | 1 - .../action/motion_comment/test_delete.py | 1 - .../action/motion_comment/test_update.py | 1 - .../motion_comment_section/test_delete.py | 1 - .../motion_comment_section/test_sort.py | 6 --- .../motion_comment_section/test_update.py | 1 - .../system/action/motion_state/test_create.py | 1 - .../system/action/motion_state/test_update.py | 1 - .../action/motion_workflow/test_delete.py | 1 - tests/system/action/option/test_create.py | 2 - tests/system/action/option/test_update.py | 3 -- tests/system/action/poll/poll_test_mixin.py | 1 - tests/system/action/poll/test_publish.py | 1 - tests/system/action/poll/test_reset.py | 1 - tests/system/action/poll/test_start.py | 1 - tests/system/action/poll/test_stop.py | 7 --- tests/system/action/poll/test_vote.py | 27 ------------ tests/system/action/projection/test_create.py | 2 - .../action/projector/test_add_to_preview.py | 6 +-- tests/system/action/projector/test_delete.py | 1 - tests/system/action/projector/test_next.py | 6 +-- .../system/action/projector/test_previous.py | 6 +-- tests/system/action/projector/test_project.py | 8 +--- .../action/projector/test_project_preview.py | 2 +- tests/system/action/projector/test_toggle.py | 1 - tests/system/action/projector/test_update.py | 4 +- tests/system/action/speaker/test_create.py | 21 +-------- .../action/speaker/test_create_for_merge.py | 2 - .../speaker/test_create_point_of_order.py | 16 ------- tests/system/action/speaker/test_delete.py | 16 ------- .../system/action/speaker/test_end_speech.py | 2 - tests/system/action/speaker/test_pause.py | 2 - tests/system/action/speaker/test_sort.py | 8 ---- tests/system/action/speaker/test_speak.py | 4 -- tests/system/action/speaker/test_unpause.py | 2 - tests/system/action/speaker/test_update.py | 2 - .../test_add_time.py | 4 -- .../test_create.py | 2 - .../test_delete.py | 2 - .../test_update.py | 4 -- tests/system/action/test_archived_meeting.py | 4 -- tests/system/action/topic/test_create.py | 12 +---- tests/system/action/topic/test_delete.py | 10 ----- tests/system/action/topic/test_import.py | 13 ++---- tests/system/action/topic/test_json_upload.py | 5 +-- tests/system/action/topic/test_update.py | 16 ++----- tests/system/action/user/test_delete.py | 4 -- .../system/action/user/test_merge_together.py | 1 - tests/system/action/user/test_update.py | 9 ++-- tests/system/presenter/test_check_database.py | 16 ------- .../presenter/test_check_database_all.py | 16 ------- tests/system/presenter/test_export_meeting.py | 2 - .../presenter/test_get_history_information.py | 1 - 96 files changed, 59 insertions(+), 532 deletions(-) diff --git a/tests/system/action/agenda_item/test_assign.py b/tests/system/action/agenda_item/test_assign.py index d62ec18f7..b79723926 100644 --- a/tests/system/action/agenda_item/test_assign.py +++ b/tests/system/action/agenda_item/test_assign.py @@ -10,16 +10,14 @@ class AgendaItemAssignActionTest(BaseActionTestCase): "agenda_item/8": {"meeting_id": 1, "content_object_id": "topic/2"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, } def test_assign_parent_none(self) -> None: @@ -51,33 +49,27 @@ def test_assign_parent_none(self) -> None: }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 222, }, "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "tropic", - "sequential_number": 2, }, "topic/3": { "meeting_id": 222, "title": "tropic", - "sequential_number": 3, }, } ) @@ -128,33 +120,27 @@ def test_assign_parent_set(self) -> None: }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 222, }, "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "tropic", - "sequential_number": 2, }, "topic/3": { "meeting_id": 222, "title": "tropic", - "sequential_number": 3, }, } ) @@ -186,23 +172,19 @@ def test_assign_multiple_action_data_items(self) -> None: "agenda_item/8": {"meeting_id": 222, "content_object_id": "topic/2"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "tropic", - "sequential_number": 2, }, } ) diff --git a/tests/system/action/agenda_item/test_create.py b/tests/system/action/agenda_item/test_create.py index 0f8be5791..73630d162 100644 --- a/tests/system/action/agenda_item/test_create.py +++ b/tests/system/action/agenda_item/test_create.py @@ -7,13 +7,11 @@ class AgendaItemSystemTest(BaseActionTestCase): PERMISSION_TEST_MODELS = { "motion/1": { "title": "motion1", - "sequential_number": 1, "state_id": 1, "meeting_id": 1, }, "list_of_speakers/1": { "content_object_id": "motion/1", - "sequential_number": 1, "meeting_id": 1, }, } @@ -41,10 +39,9 @@ def test_create_more_fields(self) -> None: self.create_motion(1) self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/42": { @@ -102,10 +99,9 @@ def test_create_parent_weight(self) -> None: self.create_motion(1, 2) self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/42": { @@ -167,10 +163,9 @@ def test_create_differing_meeting_ids(self) -> None: self.create_motion(4) self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/1": { @@ -237,10 +232,9 @@ def test_create_calc_fields_parent_agenda_internal(self) -> None: self.create_motion(2) self.set_models( { - "topic/2": {"meeting_id": 2, "title": "jungle", "sequential_number": 2}, + "topic/2": {"meeting_id": 2, "title": "jungle"}, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 2, }, "agenda_item/3": { @@ -272,10 +266,9 @@ def test_create_calc_fields_parent_internal_internal(self) -> None: self.create_motion(2) self.set_models( { - "topic/2": {"meeting_id": 2, "title": "jungle", "sequential_number": 2}, + "topic/2": {"meeting_id": 2, "title": "jungle"}, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 2, }, "agenda_item/3": { @@ -306,10 +299,9 @@ def test_create_calc_fields_parent_internal_hidden(self) -> None: self.create_motion(2) self.set_models( { - "topic/2": {"meeting_id": 2, "title": "jungle", "sequential_number": 2}, + "topic/2": {"meeting_id": 2, "title": "jungle"}, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 2, }, "agenda_item/3": { @@ -368,11 +360,9 @@ def test_create_replace_reverse_of_multi_content_object_id_required_error( "meeting_id": 1, "agenda_item_id": 1, "title": "just do it", - "sequential_number": 1, }, "list_of_speakers/42": { "content_object_id": "assignment/1", - "sequential_number": 12, "meeting_id": 1, }, "agenda_item/1": {"meeting_id": 1, "content_object_id": "assignment/1"}, diff --git a/tests/system/action/agenda_item/test_delete.py b/tests/system/action/agenda_item/test_delete.py index e1f68df70..9447fad54 100644 --- a/tests/system/action/agenda_item/test_delete.py +++ b/tests/system/action/agenda_item/test_delete.py @@ -19,13 +19,11 @@ def test_delete_correct(self) -> None: "agenda_item/111": {"meeting_id": 20, "content_object_id": "topic/1"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 20, }, "topic/1": { "meeting_id": 20, "title": "tropic", - "sequential_number": 1, }, } ) @@ -40,13 +38,11 @@ def test_delete_wrong_id(self) -> None: "agenda_item/112": {"meeting_id": 20, "content_object_id": "topic/1"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 20, }, "topic/1": { "meeting_id": 20, "title": "tropic", - "sequential_number": 1, }, } ) @@ -60,13 +56,11 @@ def test_delete_topic(self) -> None: { "topic/34": { "title": "tropic", - "sequential_number": 1, "agenda_item_id": 111, "meeting_id": 20, }, "list_of_speakers/23": { "content_object_id": "topic/34", - "sequential_number": 11, "meeting_id": 20, }, "agenda_item/111": {"content_object_id": "topic/34", "meeting_id": 20}, @@ -108,7 +102,6 @@ def test_delete_with_projection(self) -> None: }, "projector/1": { "current_projection_ids": [1], - "sequential_number": 1, "meeting_id": 20, }, } diff --git a/tests/system/action/agenda_item/test_numbering.py b/tests/system/action/agenda_item/test_numbering.py index 157951567..344d2e555 100644 --- a/tests/system/action/agenda_item/test_numbering.py +++ b/tests/system/action/agenda_item/test_numbering.py @@ -9,16 +9,14 @@ class AgendaItemNumberingTester(BaseActionTestCase): """ PERMISSION_TEST_MODELS = { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "agenda_item/1": { @@ -42,22 +40,19 @@ def setUp(self) -> None: def test_numbering(self) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, - "topic/3": {"meeting_id": 1, "title": "tropic", "sequential_number": 3}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, + "topic/3": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 1, }, "agenda_item/1": { @@ -97,22 +92,19 @@ def test_numbering_prefix(self) -> None: "meeting/1": { "agenda_number_prefix": "P-", }, - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, - "topic/3": {"meeting_id": 1, "title": "tropic", "sequential_number": 3}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, + "topic/3": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 1, }, "agenda_item/1": { @@ -152,22 +144,19 @@ def test_numbering_roman(self) -> None: "meeting/1": { "agenda_numeral_system": "roman", }, - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, - "topic/3": {"meeting_id": 1, "title": "tropic", "sequential_number": 3}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, + "topic/3": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 1, }, "agenda_item/1": { @@ -204,16 +193,14 @@ def test_numbering_roman(self) -> None: def test_numbering_without_parents(self) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "tropic", "sequential_number": 2}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "agenda_item/1": { @@ -240,20 +227,17 @@ def test_numbering_without_parents(self) -> None: def test_numbering_with_non_public_items(self) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "topic/2": { "meeting_id": 1, "title": "tropic Al", - "sequential_number": 2, }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "agenda_item/1": { diff --git a/tests/system/action/agenda_item/test_sort.py b/tests/system/action/agenda_item/test_sort.py index 6a7a1fb7b..933d359e2 100644 --- a/tests/system/action/agenda_item/test_sort.py +++ b/tests/system/action/agenda_item/test_sort.py @@ -4,10 +4,9 @@ class AgendaItemSortActionTest(BaseActionTestCase): PERMISSION_TEST_MODELS = { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/42": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/22": { @@ -27,11 +26,9 @@ def test_sort_single_node_correct(self) -> None: "topic/2": { "meeting_id": 222, "title": "jungle", - "sequential_number": 2, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 11, "meeting_id": 222, }, "agenda_item/22": { @@ -58,21 +55,17 @@ def test_sort_not_all_sorted(self) -> None: "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "jungle", - "sequential_number": 2, }, "list_of_speakers/42": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "agenda_item/22": { @@ -100,14 +93,12 @@ def test_sort_complex_correct(self) -> None: f"topic/{id_}": { "meeting_id": 222, "title": "tropic jungle", - "sequential_number": id_, } for id_ in range(1, 7) }, **{ f"list_of_speakers/{10 + id_}": { "content_object_id": f"topic/{id_}", - "sequential_number": 10 + id_, "meeting_id": 222, } for id_ in range(1, 7) @@ -173,31 +164,25 @@ def test_sort_not_a_tree(self) -> None: "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "jungle", - "sequential_number": 2, }, "topic/3": { "meeting_id": 222, "title": "tropic", - "sequential_number": 3, }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 222, }, "agenda_item/1": { @@ -237,31 +222,25 @@ def test_sort_circle_fail(self) -> None: "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "jungle", - "sequential_number": 2, }, "topic/3": { "meeting_id": 222, "title": "tropic", - "sequential_number": 3, }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 222, }, "agenda_item/1": { @@ -303,31 +282,25 @@ def test_small_tree_correct(self) -> None: "topic/1": { "meeting_id": 222, "title": "tropic", - "sequential_number": 1, }, "topic/2": { "meeting_id": 222, "title": "jungle", - "sequential_number": 2, }, "topic/3": { "meeting_id": 222, "title": "tropic", - "sequential_number": 3, }, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 222, }, "list_of_speakers/42": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 222, }, "list_of_speakers/64": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 222, }, "agenda_item/1": { diff --git a/tests/system/action/agenda_item/test_update.py b/tests/system/action/agenda_item/test_update.py index 8fe7f02a3..3cefbe525 100644 --- a/tests/system/action/agenda_item/test_update.py +++ b/tests/system/action/agenda_item/test_update.py @@ -10,13 +10,11 @@ def setUp(self) -> None: self.set_models( { "topic/102": { - "sequential_number": 1, "title": "tropic", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "topic/102", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/111": { @@ -60,10 +58,9 @@ def test_update_all_fields(self) -> None: def test_update_type_change_with_children(self) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, "list_of_speakers/42": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/111": {"child_ids": [222]}, @@ -109,16 +106,14 @@ def test_update_tag_ids_remove(self) -> None: def test_update_multiple_with_tag(self) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "jungle", "sequential_number": 2}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "jungle"}, "list_of_speakers/42": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/64": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "tag/1": { @@ -153,22 +148,19 @@ def update_multiple_with_type_variations( ) -> None: self.set_models( { - "topic/1": {"meeting_id": 1, "title": "tropic", "sequential_number": 1}, - "topic/2": {"meeting_id": 1, "title": "jungle", "sequential_number": 2}, - "topic/3": {"meeting_id": 1, "title": "jungle", "sequential_number": 3}, + "topic/1": {"meeting_id": 1, "title": "tropic"}, + "topic/2": {"meeting_id": 1, "title": "jungle"}, + "topic/3": {"meeting_id": 1, "title": "jungle"}, "list_of_speakers/42": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/64": { "content_object_id": "topic/2", - "sequential_number": 12, "meeting_id": 1, }, "list_of_speakers/128": { "content_object_id": "topic/3", - "sequential_number": 13, "meeting_id": 1, }, "agenda_item/1": { diff --git a/tests/system/action/assignment/test_delete.py b/tests/system/action/assignment/test_delete.py index 061192a9a..33f7b2671 100644 --- a/tests/system/action/assignment/test_delete.py +++ b/tests/system/action/assignment/test_delete.py @@ -5,13 +5,11 @@ class AssignmentDeleteActionTest(BaseActionTestCase): PERMISSION_TEST_MODELS = { "assignment/111": { - "sequential_number": 1, "meeting_id": 1, "title": "title_srtgb123", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, } @@ -24,13 +22,11 @@ def test_delete_correct(self) -> None: self.set_models( { "assignment/111": { - "sequential_number": 1, "meeting_id": 110, "title": "title_srtgb123", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 110, }, } @@ -43,7 +39,6 @@ def test_delete_correct_cascading(self) -> None: self.set_models( { "assignment/111": { - "sequential_number": 1, "title": "Dr. Assignment", "list_of_speakers_id": 222, "agenda_item_id": 333, @@ -51,7 +46,6 @@ def test_delete_correct_cascading(self) -> None: "phase": "finished", }, "list_of_speakers/222": { - "sequential_number": 1, "closed": False, "content_object_id": "assignment/111", "meeting_id": 110, @@ -67,7 +61,6 @@ def test_delete_correct_cascading(self) -> None: "meeting_id": 110, }, "projector/1": { - "sequential_number": 1, "meeting_id": 110, }, "assignment_candidate/1111": {"assignment_id": 111, "meeting_id": 110}, @@ -86,11 +79,9 @@ def test_delete_wrong_id(self) -> None: { "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 110, }, "assignment/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 110, }, diff --git a/tests/system/action/assignment/test_update.py b/tests/system/action/assignment/test_update.py index 5db7cc91e..50b99a6bb 100644 --- a/tests/system/action/assignment/test_update.py +++ b/tests/system/action/assignment/test_update.py @@ -5,13 +5,11 @@ class AssignmentUpdateActionTest(BaseActionTestCase): PERMISSION_TEST_MODELS = { "assignment/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, } @@ -24,13 +22,11 @@ def test_update_correct(self) -> None: self.set_models( { "assignment/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, } @@ -49,13 +45,11 @@ def test_update_correct_full_fields(self) -> None: "assignment_poll_add_candidates_to_list_of_speakers": True }, "assignment/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, "meeting_mediafile/11": { @@ -97,12 +91,10 @@ def test_update_wrong_id(self) -> None: { "assignment/111": { "title": "title_srtgb123", - "sequential_number": 1, "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, }, @@ -127,12 +119,10 @@ def prepare_voting_phase_test( }, "assignment/1": { "title": "assignment_with_candidates", - "sequential_number": 1, "meeting_id": 1, "phase": phase, }, "list_of_speakers/1": { - "sequential_number": 1, "content_object_id": "assignment/1", "meeting_id": 1, }, diff --git a/tests/system/action/assignment_candidate/test_create.py b/tests/system/action/assignment_candidate/test_create.py index 0d9ed7c6c..a0839ac5b 100644 --- a/tests/system/action/assignment_candidate/test_create.py +++ b/tests/system/action/assignment_candidate/test_create.py @@ -23,14 +23,12 @@ def setUp(self) -> None: "user_id": 110, }, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1, "phase": "voting", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, } @@ -42,13 +40,11 @@ def test_create_count_calls(self) -> None: "user/110": {"username": "test_Xcdfgee"}, "meeting_user/110": {"meeting_id": 1333, "user_id": 110}, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, } @@ -80,13 +76,11 @@ def test_create_wrong_field(self) -> None: { "user/110": {"username": "test_Xcdfgee"}, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1133, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1133, }, "meeting_user/110": {"meeting_id": 1133, "user_id": 110}, @@ -116,14 +110,12 @@ def test_create_finished(self) -> None: "user_id": 110, }, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, "phase": "finished", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, } diff --git a/tests/system/action/assignment_candidate/test_delete.py b/tests/system/action/assignment_candidate/test_delete.py index f96b881b8..3d0ad05e8 100644 --- a/tests/system/action/assignment_candidate/test_delete.py +++ b/tests/system/action/assignment_candidate/test_delete.py @@ -17,14 +17,12 @@ def setUp(self) -> None: "username": "user", }, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1, "phase": "voting", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1, }, "assignment_candidate/111": { @@ -42,13 +40,11 @@ def test_delete_correct(self) -> None: "user/110": {"username": "user"}, "meeting_user/110": {"meeting_id": 1333, "user_id": 110}, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, "assignment_candidate/111": { @@ -69,13 +65,11 @@ def test_delete_correct_empty_user(self) -> None: self.set_models( { "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, "assignment_candidate/111": { @@ -101,13 +95,11 @@ def test_delete_wrong_id(self) -> None: "user/110": {"username": "user"}, "meeting_user/110": {"meeting_id": 1333, "user_id": 110}, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, "assignment_candidate/112": { @@ -134,14 +126,12 @@ def test_delete_finished(self) -> None: "user/110": {"username": "user"}, "meeting_user/110": {"meeting_id": 1333, "user_id": 110}, "assignment/111": { - "sequential_number": 1, "title": "title_xTcEkItp", "meeting_id": 1333, "phase": "finished", }, "list_of_speakers/23": { "content_object_id": "assignment/111", - "sequential_number": 11, "meeting_id": 1333, }, "assignment_candidate/111": { diff --git a/tests/system/action/assignment_candidate/test_sort.py b/tests/system/action/assignment_candidate/test_sort.py index 09b1477d7..da5dd9a4b 100644 --- a/tests/system/action/assignment_candidate/test_sort.py +++ b/tests/system/action/assignment_candidate/test_sort.py @@ -9,13 +9,11 @@ def setUp(self) -> None: super().setUp() self.permission_test_models: dict[str, dict[str, Any]] = { "assignment/222": { - "sequential_number": 1, "title": "title_SNLGsvIV", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/222", - "sequential_number": 11, "meeting_id": 1, }, "user/233": {"username": "username_233"}, @@ -39,13 +37,11 @@ def test_sort_correct_1(self) -> None: self.set_models( { "assignment/222": { - "sequential_number": 1, "title": "title_SNLGsvIV", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/222", - "sequential_number": 11, "meeting_id": 1, }, "user/233": {"username": "username_233"}, @@ -79,13 +75,11 @@ def test_sort_missing_model(self) -> None: self.set_models( { "assignment/222": { - "sequential_number": 1, "title": "title_SNLGsvIV", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/222", - "sequential_number": 11, "meeting_id": 1, }, "user/233": {"username": "username_233"}, @@ -114,13 +108,11 @@ def test_sort_another_section_db(self) -> None: self.set_models( { "assignment/222": { - "sequential_number": 1, "title": "title_SNLGsvIV", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/222", - "sequential_number": 11, "meeting_id": 1, }, "user/233": {"username": "username_233"}, diff --git a/tests/system/action/assignment_candidate/test_update.py b/tests/system/action/assignment_candidate/test_update.py index 4ec556b02..041a39af4 100644 --- a/tests/system/action/assignment_candidate/test_update.py +++ b/tests/system/action/assignment_candidate/test_update.py @@ -8,13 +8,11 @@ def setUp(self) -> None: self.set_models( { "assignment/222": { - "sequential_number": 1, "title": "title_SNLGsvIV", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/222", - "sequential_number": 11, "meeting_id": 1, }, "user/233": {"username": "username_233"}, diff --git a/tests/system/action/base.py b/tests/system/action/base.py index f074dd90e..363b14544 100644 --- a/tests/system/action/base.py +++ b/tests/system/action/base.py @@ -229,14 +229,12 @@ def create_motion( { f"motion/{base}": { "title": f"motion{base}", - "sequential_number": base, "state_id": state_id or meeting_id, "meeting_id": meeting_id, **motion_data, }, f"list_of_speakers/{base}": { "content_object_id": f"motion/{base}", - "sequential_number": base, "meeting_id": meeting_id, }, } @@ -263,7 +261,6 @@ def create_meeting(self, base: int = 1, meeting_data: PartialModel = {}) -> None **meeting_data, }, f"projector/{base}": { - "sequential_number": base, "meeting_id": base, **{field: base for field in Meeting.reverse_default_projectors()}, }, @@ -272,7 +269,6 @@ def create_meeting(self, base: int = 1, meeting_data: PartialModel = {}) -> None f"group/{base+2}": {"meeting_id": base, "name": f"group{base+2}"}, f"motion_workflow/{base}": { "name": "flo", - "sequential_number": base, "meeting_id": base, "first_state_id": base, }, diff --git a/tests/system/action/list_of_speakers/test_delete.py b/tests/system/action/list_of_speakers/test_delete.py index d8be3c51a..6833bf441 100644 --- a/tests/system/action/list_of_speakers/test_delete.py +++ b/tests/system/action/list_of_speakers/test_delete.py @@ -16,13 +16,11 @@ def setUp(self) -> None: { "topic/42": { "title": "leet improvement discussion", - "sequential_number": 42, "meeting_id": 78, }, "agenda_item/23": {"content_object_id": "topic/42", "meeting_id": 78}, "list_of_speakers/111": { "content_object_id": "topic/42", - "sequential_number": 10, "closed": True, "meeting_id": 78, }, @@ -32,7 +30,6 @@ def setUp(self) -> None: "meeting_id": 78, }, "projector/1": { - "sequential_number": 1, "meeting_id": 78, }, } diff --git a/tests/system/action/list_of_speakers/test_delete_all_speakers.py b/tests/system/action/list_of_speakers/test_delete_all_speakers.py index 4fe1c2ab9..9c8ebda00 100644 --- a/tests/system/action/list_of_speakers/test_delete_all_speakers.py +++ b/tests/system/action/list_of_speakers/test_delete_all_speakers.py @@ -10,13 +10,11 @@ def setUp(self) -> None: self.permission_test_models: dict[str, dict[str, Any]] = { "topic/32": { "title": "leet improvement discussion", - "sequential_number": 2, "meeting_id": 1, }, "agenda_item/42": {"content_object_id": "topic/32", "meeting_id": 1}, "list_of_speakers/111": { "content_object_id": "topic/32", - "sequential_number": 11, "closed": False, "meeting_id": 1, }, @@ -32,13 +30,11 @@ def test_delete_all_correct(self) -> None: }, "topic/32": { "title": "leet improvement discussion", - "sequential_number": 2, "meeting_id": 222, }, "agenda_item/42": {"content_object_id": "topic/32", "meeting_id": 222}, "list_of_speakers/111": { "content_object_id": "topic/32", - "sequential_number": 11, "closed": False, "meeting_id": 222, "speaker_ids": list(range(1, 11)), diff --git a/tests/system/action/list_of_speakers/test_re_add_last.py b/tests/system/action/list_of_speakers/test_re_add_last.py index ef395100c..079951f34 100644 --- a/tests/system/action/list_of_speakers/test_re_add_last.py +++ b/tests/system/action/list_of_speakers/test_re_add_last.py @@ -17,13 +17,11 @@ def setUp(self) -> None: "user/44": {"username": "zoro"}, "topic/32": { "title": "to pick", - "sequential_number": 42, "meeting_id": 1, }, "agenda_item/32": {"content_object_id": "topic/32", "meeting_id": 1}, "list_of_speakers/111": { "content_object_id": "topic/32", - "sequential_number": 11, "meeting_id": 1, }, "speaker/222": { @@ -86,12 +84,10 @@ def test_correct_in_closed_list(self) -> None: { "topic/42": { "title": "to pick", - "sequential_number": 43, "meeting_id": 1, }, "agenda_item/64": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/112": { - "sequential_number": 12, "content_object_id": "topic/42", "closed": True, "meeting_id": 1, @@ -120,12 +116,10 @@ def test_no_speakers(self) -> None: { "topic/42": { "title": "to pick", - "sequential_number": 43, "meeting_id": 1, }, "agenda_item/64": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/112": { - "sequential_number": 12, "content_object_id": "topic/42", "meeting_id": 1, }, @@ -217,13 +211,11 @@ def test_with_interposed_question(self) -> None: }, "topic/42": { "title": "to pick", - "sequential_number": 43, "meeting_id": 1, }, "agenda_item/64": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/222": { "meeting_id": 1, - "sequential_number": 12, "content_object_id": "topic/42", }, "speaker/333": { @@ -265,13 +257,11 @@ def test_with_anonymous_interposed_questions(self) -> None: }, "topic/42": { "title": "to pick", - "sequential_number": 43, "meeting_id": 1, }, "agenda_item/64": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/222": { "meeting_id": 1, - "sequential_number": 12, "content_object_id": "topic/42", }, "speaker/333": { @@ -309,12 +299,10 @@ def test_with_interposed_question_error(self) -> None: }, "topic/42": { "title": "to pick", - "sequential_number": 43, "meeting_id": 1, }, "agenda_item/64": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/222": { - "sequential_number": 12, "content_object_id": "topic/42", "meeting_id": 1, }, diff --git a/tests/system/action/list_of_speakers/test_update.py b/tests/system/action/list_of_speakers/test_update.py index a26c5f729..8eede55e5 100644 --- a/tests/system/action/list_of_speakers/test_update.py +++ b/tests/system/action/list_of_speakers/test_update.py @@ -10,13 +10,11 @@ def setUp(self) -> None: { "topic/42": { "title": "leet improvement discussion", - "sequential_number": 42, "meeting_id": 1, }, "agenda_item/32": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/111": { "content_object_id": "topic/42", - "sequential_number": 10, "closed": False, "meeting_id": 1, }, diff --git a/tests/system/action/mediafile/test_delete.py b/tests/system/action/mediafile/test_delete.py index 02313b60d..fd8654c6b 100644 --- a/tests/system/action/mediafile/test_delete.py +++ b/tests/system/action/mediafile/test_delete.py @@ -164,7 +164,7 @@ def test_delete_check_relations(self) -> None: "current_projector_id": 1, "meeting_id": 111, }, - "projector/1": {"sequential_number": 1, "meeting_id": 111}, + "projector/1": {"meeting_id": 111}, } ) response = self.request("mediafile.delete", {"id": 222}) diff --git a/tests/system/action/meeting/test_archive.py b/tests/system/action/meeting/test_archive.py index 295d7f503..6421b852a 100644 --- a/tests/system/action/meeting/test_archive.py +++ b/tests/system/action/meeting/test_archive.py @@ -84,7 +84,6 @@ def test_archive_meeting_with_inactive_speakers(self) -> None: self.set_models( { "list_of_speakers/1": { - "sequential_number": 1, "meeting_id": 1, "content_object_id": "motion/1", }, @@ -113,7 +112,6 @@ def create_poll(self, base: int, state: str) -> None: "pollmethod": "YNA", "onehundred_percent_base": "YNA", "meeting_id": 1, - "sequential_number": base, "content_object_id": "motion/1", "state": state, } @@ -133,7 +131,6 @@ def test_archive_meeting_with_active_speaker(self) -> None: self.set_models( { "list_of_speakers/1": { - "sequential_number": 1, "meeting_id": 1, "content_object_id": "motion/1", }, @@ -164,7 +161,6 @@ def test_archive_meeting_with_active_speaker_and_polls(self) -> None: self.set_models( { "list_of_speakers/1": { - "sequential_number": 1, "meeting_id": 1, "content_object_id": "motion/1", }, diff --git a/tests/system/action/meeting/test_clone.py b/tests/system/action/meeting/test_clone.py index 0360840eb..884210943 100644 --- a/tests/system/action/meeting/test_clone.py +++ b/tests/system/action/meeting/test_clone.py @@ -1181,7 +1181,6 @@ def test_clone_with_forwarded_motion(self) -> None: "motion/1": { "meeting_id": 1, "all_derived_motion_ids": [2], - "sequential_number": 1, "list_of_speakers_id": 1, "title": "motion1", "state_id": 1, @@ -1190,7 +1189,6 @@ def test_clone_with_forwarded_motion(self) -> None: "meeting_id": 4, "origin_id": 1, "origin_meeting_id": 1, - "sequential_number": 2, "list_of_speakers_id": 2, "title": "motion1 forwarded", "state_id": 4, @@ -1198,7 +1196,6 @@ def test_clone_with_forwarded_motion(self) -> None: "motion/3": { "meeting_id": 4, "all_derived_motion_ids": [4], - "sequential_number": 3, "list_of_speakers_id": 3, "title": "motion3", "state_id": 4, @@ -1207,28 +1204,23 @@ def test_clone_with_forwarded_motion(self) -> None: "meeting_id": 1, "origin_id": 3, "origin_meeting_id": 4, - "sequential_number": 4, "list_of_speakers_id": 4, "title": "motion3 forwarded", "state_id": 1, }, "list_of_speakers/1": { - "sequential_number": 1, "content_object_id": "motion/1", "meeting_id": 1, }, "list_of_speakers/2": { - "sequential_number": 2, "content_object_id": "motion/2", "meeting_id": 4, }, "list_of_speakers/3": { - "sequential_number": 3, "content_object_id": "motion/3", "meeting_id": 4, }, "list_of_speakers/4": { - "sequential_number": 4, "content_object_id": "motion/4", "meeting_id": 1, }, @@ -1483,7 +1475,6 @@ def test_clone_amendment_paragraphs(self) -> None: "motion/1": { "list_of_speakers_id": 1, "meeting_id": 1, - "sequential_number": 1, "state_id": 1, "title": "dummy", "amendment_paragraphs": Jsonb( @@ -1496,7 +1487,6 @@ def test_clone_amendment_paragraphs(self) -> None: "list_of_speakers/1": { "content_object_id": "motion/1", "meeting_id": 1, - "sequential_number": 1, }, } ) @@ -1560,7 +1550,6 @@ def test_clone_with_list_election(self) -> None: "closed": False, "meeting_id": 1, "content_object_id": "assignment/1", - "sequential_number": 1, }, "assignment/1": { "id": 1, @@ -1568,7 +1557,6 @@ def test_clone_with_list_election(self) -> None: "title": "Duckburg town council", "meeting_id": 1, "open_posts": 0, - "sequential_number": 1, "list_of_speakers_id": 1, }, "poll_candidate/1": { @@ -1631,7 +1619,6 @@ def test_clone_with_list_election(self) -> None: "max_votes_amount": 1, "min_votes_amount": 1, "content_object_id": "assignment/1", - "sequential_number": 1, "is_pseudoanonymized": True, "max_votes_per_option": 1, "onehundred_percent_base": "disabled", diff --git a/tests/system/action/meeting/test_delete.py b/tests/system/action/meeting/test_delete.py index ba077575f..3546d5af0 100644 --- a/tests/system/action/meeting/test_delete.py +++ b/tests/system/action/meeting/test_delete.py @@ -203,7 +203,6 @@ def test_delete_with_poll_candidates_and_speakers(self) -> None: "assignment/140": { "meeting_id": 1, "title": "test_title", - "sequential_number": 140, }, "poll/150": { "meeting_id": 1, @@ -212,7 +211,6 @@ def test_delete_with_poll_candidates_and_speakers(self) -> None: "type": "analog", "pollmethod": "YNA", "meeting_id": 1, - "sequential_number": 150, }, "option/160": { "meeting_id": 1, @@ -238,7 +236,6 @@ def test_delete_with_poll_candidates_and_speakers(self) -> None: "list_of_speakers/190": { "meeting_id": 1, "content_object_id": "assignment/140", - "sequential_number": 190, }, "speaker/210": { "meeting_id": 1, diff --git a/tests/system/action/meeting/test_delete_all_speakers_of_all_lists.py b/tests/system/action/meeting/test_delete_all_speakers_of_all_lists.py index f37473372..6b72bc031 100644 --- a/tests/system/action/meeting/test_delete_all_speakers_of_all_lists.py +++ b/tests/system/action/meeting/test_delete_all_speakers_of_all_lists.py @@ -11,13 +11,11 @@ def setUp(self) -> None: self.test_models: dict[str, dict[str, Any]] = { "motion/1": { "title": "motion1", - "sequential_number": 1, "state_id": 1, "meeting_id": 1, }, "list_of_speakers/11": { "meeting_id": 1, - "sequential_number": 11, "content_object_id": "motion/1", }, "speaker/1": {"list_of_speakers_id": 11, "meeting_id": 1}, diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index 3907bcb41..88fbd8ffe 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -37,7 +37,6 @@ def setUp(self) -> None: "projector/1": {"meeting_id": 1}, "motion/1": { "meeting_id": 1, - "sequential_number": 26, "number_value": 31, }, "gender/1": {"name": "male", "organization_id": 1}, diff --git a/tests/system/action/meeting/test_replace_projector_id.py b/tests/system/action/meeting/test_replace_projector_id.py index f92b5f713..36341bf5b 100644 --- a/tests/system/action/meeting/test_replace_projector_id.py +++ b/tests/system/action/meeting/test_replace_projector_id.py @@ -11,7 +11,7 @@ def setUp(self) -> None: "projector/1": { "used_as_default_projector_for_motion_in_meeting_id": 1 }, - "projector/20": {"meeting_id": 1, "sequential_number": 20}, + "projector/20": {"meeting_id": 1}, } ) diff --git a/tests/system/action/meeting/test_update.py b/tests/system/action/meeting/test_update.py index 7a7b061f9..ed2762ad1 100644 --- a/tests/system/action/meeting/test_update.py +++ b/tests/system/action/meeting/test_update.py @@ -103,7 +103,6 @@ def setup_projector_related_fields( "projector/2": { "name": "Projector 2", "meeting_id": 1, - "sequential_number": 2, } } ) @@ -201,7 +200,6 @@ def test_update_reference_projector_to_internal_projector_error(self) -> None: "name": "Projector 2", "is_internal": True, "meeting_id": 1, - "sequential_number": 2, }, }, ) diff --git a/tests/system/action/meeting_mediafile/test_delete.py b/tests/system/action/meeting_mediafile/test_delete.py index 8854fbe3d..c6895b691 100644 --- a/tests/system/action/meeting_mediafile/test_delete.py +++ b/tests/system/action/meeting_mediafile/test_delete.py @@ -42,7 +42,6 @@ def test_delete_complex(self) -> None: }, "list_of_speakers/3": { "meeting_id": 1, - "sequential_number": 3, "content_object_id": "meeting_mediafile/2", }, "projection/4": { @@ -51,13 +50,11 @@ def test_delete_complex(self) -> None: }, "topic/5": { "meeting_id": 1, - "sequential_number": 5, "title": "pic me", }, "agenda_item/6": {"content_object_id": "topic/5", "meeting_id": 1}, "list_of_speakers/7": { "content_object_id": "topic/5", - "sequential_number": 1, "meeting_id": 1, }, } diff --git a/tests/system/action/meeting_user/test_delete.py b/tests/system/action/meeting_user/test_delete.py index 8d57c5433..98b119f10 100644 --- a/tests/system/action/meeting_user/test_delete.py +++ b/tests/system/action/meeting_user/test_delete.py @@ -25,12 +25,10 @@ def test_delete_with_speaker(self) -> None: "meeting_user/5": {"user_id": 1, "meeting_id": 10}, "topic/11": { "title": "tipic", - "sequential_number": 11, "meeting_id": 10, }, "agenda_item/6": {"content_object_id": "topic/11", "meeting_id": 101}, "list_of_speakers/11": { - "sequential_number": 11, "content_object_id": "topic/11", "meeting_id": 10, }, @@ -69,13 +67,11 @@ def test_delete_with_editor_and_working_group_speaker(self) -> None: { "meeting_user/5": {"user_id": 1, "meeting_id": 10}, "list_of_speakers/12": { - "sequential_number": 12, "content_object_id": "motion/11", "meeting_id": 10, }, "motion/11": { "title": "morse", - "sequential_number": 11, "state_id": 10, "meeting_id": 10, }, diff --git a/tests/system/action/meeting_user/test_update.py b/tests/system/action/meeting_user/test_update.py index 18df90981..e5a7b2ce2 100644 --- a/tests/system/action/meeting_user/test_update.py +++ b/tests/system/action/meeting_user/test_update.py @@ -43,18 +43,15 @@ def test_update_merge_fields_correct(self) -> None: { "meeting_user/2": test_dict, "list_of_speakers/11": { - "sequential_number": 11, "content_object_id": "assignment/11", "meeting_id": 1, }, "list_of_speakers/12": { - "sequential_number": 12, "content_object_id": "motion/11", "meeting_id": 1, }, "assignment/11": { "title": "somehow, someone", - "sequential_number": 11, "meeting_id": 1, }, "assignment_candidate/1": { @@ -64,7 +61,6 @@ def test_update_merge_fields_correct(self) -> None: }, "motion/11": { "title": "morse", - "sequential_number": 11, "state_id": 1, "meeting_id": 1, }, diff --git a/tests/system/action/motion/test_create.py b/tests/system/action/motion/test_create.py index 867e4ccea..8e0ee51d1 100644 --- a/tests/system/action/motion/test_create.py +++ b/tests/system/action/motion/test_create.py @@ -65,16 +65,13 @@ def test_create_simple_fields(self) -> None: "motion_category/124": { "name": "name_wbtlHQro", "meeting_id": 1, - "sequential_number": 124, }, "motion_block/78": { "title": "title_kXTvKvjc", "meeting_id": 1, - "sequential_number": 78, }, "list_of_speakers/23": { "content_object_id": "motion_block/78", - "sequential_number": 11, "meeting_id": 1, }, "tag/56": {"name": "name_56", "meeting_id": 1}, diff --git a/tests/system/action/motion/test_create_amendment.py b/tests/system/action/motion/test_create_amendment.py index f8896b114..5b9b21580 100644 --- a/tests/system/action/motion/test_create_amendment.py +++ b/tests/system/action/motion/test_create_amendment.py @@ -19,16 +19,13 @@ def setUp(self) -> None: "motion_category/12": { "meeting_id": 1, "name": "Category 12", - "sequential_number": 1, }, "motion_block/13": { "meeting_id": 1, "title": "Block 13", - "sequential_number": 1, }, "list_of_speakers/42": { "content_object_id": "motion_block/13", - "sequential_number": 11, "meeting_id": 1, }, } diff --git a/tests/system/action/motion/test_create_sequential_number.py b/tests/system/action/motion/test_create_sequential_number.py index 41e57a58c..f66a94f02 100644 --- a/tests/system/action/motion/test_create_sequential_number.py +++ b/tests/system/action/motion/test_create_sequential_number.py @@ -23,7 +23,6 @@ def create_workflow(self, workflow_id: int = 12, meeting_id: int = 222) -> None: { f"motion_workflow/{workflow_id}": { "name": f"motion_workflow{workflow_id}", - "sequential_number": workflow_id, "first_state_id": state_id, "meeting_id": meeting_id, }, diff --git a/tests/system/action/motion/test_set_number_mixin.py b/tests/system/action/motion/test_set_number_mixin.py index 9bf902165..5b975031f 100644 --- a/tests/system/action/motion/test_set_number_mixin.py +++ b/tests/system/action/motion/test_set_number_mixin.py @@ -189,7 +189,6 @@ def test_create_set_number_get_number_per_category(self) -> None: "motion_category/176": { "name": "name_category_176", "meeting_id": 222, - "sequential_number": 176, }, } ) @@ -230,7 +229,6 @@ def test_create_set_number_unique_check_jump(self) -> None: "motion_category/176": { "name": "name_category_176", "meeting_id": 222, - "sequential_number": 176, }, } ) @@ -388,18 +386,15 @@ def setUp(self) -> None: "name": "A", "prefix": "A", "meeting_id": 222, - "sequential_number": 7, }, "motion_category/8": { "name": "B", "prefix": "B", "meeting_id": 222, - "sequential_number": 8, }, "motion_category/9": { "name": "no prefix", "meeting_id": 222, - "sequential_number": 9, }, } ) @@ -533,7 +528,6 @@ def set_test_models(self, meeting_data: dict[str, Any] = {}) -> None: "name": "A", "prefix": "A", "meeting_id": 222, - "sequential_number": 7, }, } ) @@ -546,12 +540,10 @@ def _create_models_for_number_per_category_1(self) -> None: "name": "B", "prefix": "B", "meeting_id": 222, - "sequential_number": 8, }, "motion_category/9": { "name": "no prefix", "meeting_id": 222, - "sequential_number": 9, }, } ) @@ -904,7 +896,6 @@ def test_set_number(self) -> None: "name": "A", "prefix": "A", "meeting_id": 222, - "sequential_number": 7, }, "motion_state/76": { "name": "test0", diff --git a/tests/system/action/motion/test_set_recommendation.py b/tests/system/action/motion/test_set_recommendation.py index 26d7a17c9..a9b256b8b 100644 --- a/tests/system/action/motion/test_set_recommendation.py +++ b/tests/system/action/motion/test_set_recommendation.py @@ -53,7 +53,6 @@ def test_set_recommendation_not_matching_workflow_ids(self) -> None: { "motion_workflow/2": { "name": "motion_workflow 2", - "sequential_number": 2, "first_state_id": 77, "meeting_id": 1, }, diff --git a/tests/system/action/motion/test_update.py b/tests/system/action/motion/test_update.py index 6da1b6ef0..110361b64 100644 --- a/tests/system/action/motion/test_update.py +++ b/tests/system/action/motion/test_update.py @@ -39,7 +39,6 @@ def create_workflow( { f"motion_workflow/{base}": { "name": f"motion_workflow{base}", - "sequential_number": base, "first_state_id": base, "meeting_id": meeting_id, }, @@ -179,16 +178,13 @@ def test_update_correct_2(self) -> None: "motion_category/4": { "meeting_id": 1, "name": "name_GdPzDztT", - "sequential_number": 4, }, "motion_block/51": { "meeting_id": 1, "title": "title_ddyvpXch", - "sequential_number": 51, }, "list_of_speakers/23": { "content_object_id": "motion_block/51", - "sequential_number": 11, "meeting_id": 1, }, } @@ -324,16 +320,13 @@ def test_update_metadata_missing_motion(self) -> None: "motion_category/4": { "name": "name_GdPzDztT", "meeting_id": 1, - "sequential_number": 4, }, "motion_block/51": { "title": "title_ddyvpXch", "meeting_id": 1, - "sequential_number": 51, }, "list_of_speakers/23": { "content_object_id": "motion_block/51", - "sequential_number": 11, "meeting_id": 1, }, } @@ -631,16 +624,13 @@ def test_update_permission_metadata_allowed(self) -> None: "motion_category/2": { "meeting_id": 1, "name": "test", - "sequential_number": 2, }, "motion_block/4": { "meeting_id": 1, "title": "blocky", - "sequential_number": 4, }, "list_of_speakers/23": { "content_object_id": "motion_block/4", - "sequential_number": 11, "meeting_id": 1, }, "tag/3": {"meeting_id": 1, "name": "bla"}, @@ -701,7 +691,6 @@ def test_update_permission_metadata_and_submitter(self) -> None: "motion_category/2": { "meeting_id": 1, "name": "test", - "sequential_number": 2, } } ) diff --git a/tests/system/action/motion/test_update_with_other_actions.py b/tests/system/action/motion/test_update_with_other_actions.py index e02828f86..55d4fadc9 100644 --- a/tests/system/action/motion/test_update_with_other_actions.py +++ b/tests/system/action/motion/test_update_with_other_actions.py @@ -19,7 +19,6 @@ def setUp(self) -> None: "motion_category/3": { "meeting_id": 222, "name": "category", - "sequential_number": 3, }, } ) diff --git a/tests/system/action/motion_block/test_delete.py b/tests/system/action/motion_block/test_delete.py index 36a2481fc..90f77ae7f 100644 --- a/tests/system/action/motion_block/test_delete.py +++ b/tests/system/action/motion_block/test_delete.py @@ -10,13 +10,11 @@ def setUp(self) -> None: { "motion_block/111": { "title": "title_srtgb123", - "sequential_number": 111, "list_of_speakers_id": 222, "meeting_id": 1, }, "list_of_speakers/222": { "closed": False, - "sequential_number": 15, "content_object_id": "motion_block/111", "meeting_id": 1, }, diff --git a/tests/system/action/motion_block/test_update.py b/tests/system/action/motion_block/test_update.py index 2f62d08e5..80ae1099a 100644 --- a/tests/system/action/motion_block/test_update.py +++ b/tests/system/action/motion_block/test_update.py @@ -10,13 +10,11 @@ def setUp(self) -> None: { "motion_block/111": { "title": "title_srtgb123", - "sequential_number": 111, "list_of_speakers_id": 222, "meeting_id": 1, }, "list_of_speakers/222": { "closed": False, - "sequential_number": 15, "content_object_id": "motion_block/111", "meeting_id": 1, }, diff --git a/tests/system/action/motion_category/test_create.py b/tests/system/action/motion_category/test_create.py index 42e687d64..564dade66 100644 --- a/tests/system/action/motion_category/test_create.py +++ b/tests/system/action/motion_category/test_create.py @@ -13,7 +13,6 @@ def test_create_good_case_full_fields(self) -> None: "motion_category/123": { "name": "name_bWdKLQxL", "meeting_id": 222, - "sequential_number": 1, "weight": 1, }, } @@ -59,7 +58,6 @@ def test_create_increment_weight(self) -> None: "name": "name_bWdKLQxL", "meeting_id": 222, "weight": 1, - "sequential_number": 1, }, } ) @@ -167,7 +165,6 @@ def test_create_not_unique_prefix(self) -> None: "name": "name_bWdKLQxL", "meeting_id": 222, "prefix": "test", - "sequential_number": 1, } } ) diff --git a/tests/system/action/motion_category/test_delete.py b/tests/system/action/motion_category/test_delete.py index 014029575..33c02420b 100644 --- a/tests/system/action/motion_category/test_delete.py +++ b/tests/system/action/motion_category/test_delete.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "motion_category/111": { "name": "name_srtgb123", "meeting_id": 1, - "sequential_number": 111, }, } ) diff --git a/tests/system/action/motion_category/test_number_motions.py b/tests/system/action/motion_category/test_number_motions.py index 1484baad5..61a68dc56 100644 --- a/tests/system/action/motion_category/test_number_motions.py +++ b/tests/system/action/motion_category/test_number_motions.py @@ -19,7 +19,6 @@ def create_motion_category( f"motion_category/{base}": { "name": f"category {base}", "meeting_id": meeting_id, - "sequential_number": base, **category_data, } } diff --git a/tests/system/action/motion_category/test_sort.py b/tests/system/action/motion_category/test_sort.py index e967d9321..9814d810e 100644 --- a/tests/system/action/motion_category/test_sort.py +++ b/tests/system/action/motion_category/test_sort.py @@ -12,7 +12,6 @@ def setUp(self) -> None: "motion_category/22": { "name": "category 22", "meeting_id": 1, - "sequential_number": 22, }, } @@ -22,7 +21,6 @@ def create_motion_category(self, base: int) -> None: f"motion_category/{base}": { "name": f"category {base}", "meeting_id": 222, - "sequential_number": base, } } ) diff --git a/tests/system/action/motion_category/test_sort_motions_in_categories.py b/tests/system/action/motion_category/test_sort_motions_in_categories.py index e4d33126a..e633ece86 100644 --- a/tests/system/action/motion_category/test_sort_motions_in_categories.py +++ b/tests/system/action/motion_category/test_sort_motions_in_categories.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "motion_category/222": { "name": "category 222", "meeting_id": 1, - "sequential_number": 222, } } ) diff --git a/tests/system/action/motion_category/test_update.py b/tests/system/action/motion_category/test_update.py index bf5f42e2b..41819a94b 100644 --- a/tests/system/action/motion_category/test_update.py +++ b/tests/system/action/motion_category/test_update.py @@ -12,7 +12,6 @@ def setUp(self) -> None: "name": "name_srtgb123", "prefix": "prefix_JmDHFgvH", "meeting_id": 1, - "sequential_number": 111, } } ) @@ -24,11 +23,9 @@ def test_update_correct_all_fields(self) -> None: "title": "motion 89", "meeting_id": 1, "state_id": 1, - "sequential_number": 89, }, "list_of_speakers/23": { "content_object_id": "motion/89", - "sequential_number": 11, "meeting_id": 1, }, } @@ -60,7 +57,6 @@ def test_update_wrong_id(self) -> None: "name": "name_srtgb123", "prefix": "prefix_JmDHFgvH", "meeting_id": 1, - "sequential_number": 111, } } ) @@ -77,7 +73,6 @@ def test_update_non_unique_prefix(self) -> None: "name": "name_already", "prefix": "test", "meeting_id": 1, - "sequential_number": 110, }, } ) diff --git a/tests/system/action/motion_comment/test_create.py b/tests/system/action/motion_comment/test_create.py index 70b44b83a..bbb12b6ec 100644 --- a/tests/system/action/motion_comment/test_create.py +++ b/tests/system/action/motion_comment/test_create.py @@ -12,7 +12,6 @@ def setUp(self) -> None: "motion_comment_section/78": { "meeting_id": 1, "name": "test", - "sequential_number": 78, }, "group/3": {"write_comment_section_ids": [78]}, } diff --git a/tests/system/action/motion_comment/test_delete.py b/tests/system/action/motion_comment/test_delete.py index dba5f584b..6d63141a0 100644 --- a/tests/system/action/motion_comment/test_delete.py +++ b/tests/system/action/motion_comment/test_delete.py @@ -17,7 +17,6 @@ def setUp(self) -> None: "motion_comment_section/78": { "meeting_id": 1, "name": "test", - "sequential_number": 78, }, "group/3": {"write_comment_section_ids": [78]}, } diff --git a/tests/system/action/motion_comment/test_update.py b/tests/system/action/motion_comment/test_update.py index 64a9fce21..88bf535f6 100644 --- a/tests/system/action/motion_comment/test_update.py +++ b/tests/system/action/motion_comment/test_update.py @@ -18,7 +18,6 @@ def setUp(self) -> None: "motion_comment_section/78": { "meeting_id": 1, "name": "test", - "sequential_number": 78, }, "group/3": {"write_comment_section_ids": [78]}, } diff --git a/tests/system/action/motion_comment_section/test_delete.py b/tests/system/action/motion_comment_section/test_delete.py index 43a103430..72f9c994e 100644 --- a/tests/system/action/motion_comment_section/test_delete.py +++ b/tests/system/action/motion_comment_section/test_delete.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "motion_comment_section/111": { "name": "name_srtgb123", "meeting_id": 1, - "sequential_number": 111, }, } ) diff --git a/tests/system/action/motion_comment_section/test_sort.py b/tests/system/action/motion_comment_section/test_sort.py index dcc441c32..c8edf100c 100644 --- a/tests/system/action/motion_comment_section/test_sort.py +++ b/tests/system/action/motion_comment_section/test_sort.py @@ -12,12 +12,10 @@ def setUp(self) -> None: "motion_comment_section/31": { "meeting_id": 1, "name": "name_loisueb", - "sequential_number": 31, }, "motion_comment_section/32": { "meeting_id": 1, "name": "name_blanumop", - "sequential_number": 32, }, } @@ -37,7 +35,6 @@ def test_sort_missing_model(self) -> None: "motion_comment_section/31": { "meeting_id": 1, "name": "name_loisueb", - "sequential_number": 31, }, } ) @@ -57,17 +54,14 @@ def test_sort_another_section_db(self) -> None: "motion_comment_section/31": { "meeting_id": 1, "name": "name_loisueb", - "sequential_number": 31, }, "motion_comment_section/32": { "meeting_id": 1, "name": "name_blanumop", - "sequential_number": 32, }, "motion_comment_section/33": { "meeting_id": 1, "name": "name_polusiem", - "sequential_number": 33, }, } ) diff --git a/tests/system/action/motion_comment_section/test_update.py b/tests/system/action/motion_comment_section/test_update.py index 06c0f7f12..05e45d7c1 100644 --- a/tests/system/action/motion_comment_section/test_update.py +++ b/tests/system/action/motion_comment_section/test_update.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "motion_comment_section/111": { "name": "name_srtgb123", "meeting_id": 1, - "sequential_number": 111, }, } ) diff --git a/tests/system/action/motion_state/test_create.py b/tests/system/action/motion_state/test_create.py index 77c831021..70d76c2b3 100644 --- a/tests/system/action/motion_state/test_create.py +++ b/tests/system/action/motion_state/test_create.py @@ -60,7 +60,6 @@ def test_create_as_new_first_state_of_second_workflow(self) -> None: "name": "test_name_43", "meeting_id": 1, "first_state_id": 2, - "sequential_number": 43, }, "motion_state/2": { "meeting_id": 1, diff --git a/tests/system/action/motion_state/test_update.py b/tests/system/action/motion_state/test_update.py index 9ce0323c6..25a5cf887 100644 --- a/tests/system/action/motion_state/test_update.py +++ b/tests/system/action/motion_state/test_update.py @@ -86,7 +86,6 @@ def test_update_wrong_workflow_mismatch(self) -> None: "name": "name_Ycefgee", "meeting_id": 1, "first_state_id": 113, - "sequential_number": 90, }, "motion_state/113": { "name": "name_srtfg113", diff --git a/tests/system/action/motion_workflow/test_delete.py b/tests/system/action/motion_workflow/test_delete.py index 5e02626dc..6d53e5e29 100644 --- a/tests/system/action/motion_workflow/test_delete.py +++ b/tests/system/action/motion_workflow/test_delete.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "motion_workflow/2": { "name": "workflow 2", "meeting_id": 1, - "sequential_number": 2, "first_state_id": 2, }, "motion_state/2": { diff --git a/tests/system/action/option/test_create.py b/tests/system/action/option/test_create.py index 61e22bb15..37e297cb7 100644 --- a/tests/system/action/option/test_create.py +++ b/tests/system/action/option/test_create.py @@ -30,14 +30,12 @@ def test_create_with_both_text_and_content_object_id(self) -> None: self.set_models( { "motion/112": { - "sequential_number": 11, "title": "mosh pit", "state_id": 111, "meeting_id": 111, }, "list_of_speakers/23": { "content_object_id": "motion/112", - "sequential_number": 11, "meeting_id": 111, }, } diff --git a/tests/system/action/option/test_update.py b/tests/system/action/option/test_update.py index b4d336880..3be91d940 100644 --- a/tests/system/action/option/test_update.py +++ b/tests/system/action/option/test_update.py @@ -25,18 +25,15 @@ def setUp(self) -> None: { "topic/1": { "title": "to pic", - "sequential_number": 1, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1", "meeting_id": 1}, "list_of_speakers/23": { "content_object_id": "topic/1", - "sequential_number": 11, "meeting_id": 1, }, "poll/65": { "title": "pool", - "sequential_number": 1, "content_object_id": "topic/1", "type": "analog", "state": "created", diff --git a/tests/system/action/poll/poll_test_mixin.py b/tests/system/action/poll/poll_test_mixin.py index 7f35fc16f..1a020e770 100644 --- a/tests/system/action/poll/poll_test_mixin.py +++ b/tests/system/action/poll/poll_test_mixin.py @@ -24,7 +24,6 @@ def prepare_users_and_poll(self, user_count: int) -> list[int]: "option_ids": [1], "meeting_id": 1, "entitled_group_ids": [3], - "sequential_number": 1, "onehundred_percent_base": "YNA", "title": "Poll 1", }, diff --git a/tests/system/action/poll/test_publish.py b/tests/system/action/poll/test_publish.py index a397e8709..16fd1eb4c 100644 --- a/tests/system/action/poll/test_publish.py +++ b/tests/system/action/poll/test_publish.py @@ -16,7 +16,6 @@ def setUp(self) -> None: "state": "finished", "meeting_id": 1, "content_object_id": "topic/1", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "YNA", }, diff --git a/tests/system/action/poll/test_reset.py b/tests/system/action/poll/test_reset.py index 1a2795d9b..6ce1c3d4c 100644 --- a/tests/system/action/poll/test_reset.py +++ b/tests/system/action/poll/test_reset.py @@ -129,7 +129,6 @@ def test_reset_not_allowed_to_vote_again(self) -> None: "max_votes_per_option": 1, "type": "named", "backend": "long", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "Y", "content_object_id": "topic/1", diff --git a/tests/system/action/poll/test_start.py b/tests/system/action/poll/test_start.py index b0eb53dda..dbf01ddd9 100644 --- a/tests/system/action/poll/test_start.py +++ b/tests/system/action/poll/test_start.py @@ -55,7 +55,6 @@ def setUp(self) -> None: "votescast": "0.000000", "backend": "fast", **self.get_poll_data(), - "sequential_number": 1, "onehundred_percent_base": "YNA", }, } diff --git a/tests/system/action/poll/test_stop.py b/tests/system/action/poll/test_stop.py index 50de40a6f..a461ca0be 100644 --- a/tests/system/action/poll/test_stop.py +++ b/tests/system/action/poll/test_stop.py @@ -24,7 +24,6 @@ def setUp(self) -> None: "content_object_id": "topic/1", "state": Poll.STATE_STARTED, "meeting_id": 1, - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "Y", }, @@ -57,7 +56,6 @@ def add_to_list(id_: int) -> None: "meeting_id": 1, "entitled_group_ids": [1], "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, "option/1": {"meeting_id": 1, "poll_id": 1}, @@ -170,7 +168,6 @@ def test_stop_assignment_poll(self) -> None: "state": Poll.STATE_STARTED, "meeting_id": 1, "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, } @@ -196,7 +193,6 @@ def test_stop_entitled_users_at_stop_user_only_once(self) -> None: "meeting_id": 1, "entitled_group_ids": [3, 4], "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, "user/2": { @@ -245,7 +241,6 @@ def test_stop_entitled_users_not_present(self) -> None: "meeting_id": 1, "entitled_group_ids": [3], "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, "user/2": { @@ -296,7 +291,6 @@ def test_stop_entitled_users_with_delegations(self) -> None: "meeting_id": 1, "entitled_group_ids": [3], "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, "user/2": { @@ -358,7 +352,6 @@ def test_stop_entitled_users_with_delegations_turned_off(self) -> None: "meeting_id": 1, "entitled_group_ids": [3], "onehundred_percent_base": "Y", - "sequential_number": 1, "title": "Poll 1", }, "user/2": { diff --git a/tests/system/action/poll/test_vote.py b/tests/system/action/poll/test_vote.py index 8c2b0535a..82fc4d9a9 100644 --- a/tests/system/action/poll/test_vote.py +++ b/tests/system/action/poll/test_vote.py @@ -111,7 +111,6 @@ def test_vote_correct_pollmethod_Y(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "meeting/113": { @@ -175,7 +174,6 @@ def test_value_check(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -227,7 +225,6 @@ def test_vote_correct_pollmethod_YN(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -317,7 +314,6 @@ def test_vote_wrong_votes_total(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, "user/1": { @@ -364,7 +360,6 @@ def test_vote_pollmethod_Y_wrong_value(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "YNA", }, @@ -414,7 +409,6 @@ def test_vote_no_votes_total_check_by_YNA(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -463,7 +457,6 @@ def test_vote_no_votes_total_check_by_YNA_max_votes_error(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -510,7 +503,6 @@ def test_vote_no_votes_total_check_by_YN(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -559,7 +551,6 @@ def test_vote_wrong_votes_total_min_case(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -629,7 +620,6 @@ def test_vote_global(self) -> None: "pollmethod": "YNA", "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, } @@ -689,7 +679,6 @@ def test_vote_schema_problems(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "YNA", }, "user/1": { @@ -726,7 +715,6 @@ def test_vote_invalid_vote_value(self) -> None: "meeting_id": 113, "backend": "fast", "type": "named", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "YNA", }, @@ -773,7 +761,6 @@ def test_vote_not_started_in_service(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "YNA", }, @@ -819,7 +806,6 @@ def test_vote_option_not_in_poll(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, "user/1": { @@ -885,7 +871,6 @@ def test_double_vote(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, } @@ -946,7 +931,6 @@ def test_check_user_in_entitled_group(self) -> None: "state": Poll.STATE_STARTED, "backend": "fast", "type": "named", - "sequential_number": 1, "title": "Poll 1", "onehundred_percent_base": "YNA", }, @@ -984,7 +968,6 @@ def test_check_user_present_in_meeting(self) -> None: "backend": "fast", "type": "named", "pollmethod": "YNA", - "sequential_number": 1, "onehundred_percent_base": "Y", }, } @@ -1010,7 +993,6 @@ def test_check_str_validation(self) -> None: "pollmethod": "Y", "state": Poll.STATE_STARTED, "backend": "fast", - "sequential_number": 1, "onehundred_percent_base": "Y", }, "user/1": { @@ -1058,7 +1040,6 @@ def test_default_vote_weight(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, "meeting/113": {"users_enable_vote_weight": True}, @@ -1123,7 +1104,6 @@ def test_vote_weight_not_enabled(self) -> None: "max_votes_per_option": 1, "backend": "fast", "type": "named", - "sequential_number": 1, "onehundred_percent_base": "Y", }, "meeting/113": { @@ -1241,7 +1221,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "YNA", }, ) @@ -1437,7 +1416,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) @@ -1663,7 +1641,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 5, "max_votes_per_option": 3, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) @@ -1775,7 +1752,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) @@ -1980,7 +1956,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) @@ -2145,7 +2120,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) @@ -2298,7 +2272,6 @@ def create_poll(self) -> None: "min_votes_amount": 1, "max_votes_amount": 10, "max_votes_per_option": 1, - "sequential_number": 1, "onehundred_percent_base": "Y", }, ) diff --git a/tests/system/action/projection/test_create.py b/tests/system/action/projection/test_create.py index c8a55ea73..ef04f76c9 100644 --- a/tests/system/action/projection/test_create.py +++ b/tests/system/action/projection/test_create.py @@ -8,12 +8,10 @@ def test_create(self) -> None: { "assignment/1": { "title": "title_srtgb123", - "sequential_number": 1, "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/1", - "sequential_number": 11, "meeting_id": 1, }, } diff --git a/tests/system/action/projector/test_add_to_preview.py b/tests/system/action/projector/test_add_to_preview.py index 46fe416d0..89cdc49b7 100644 --- a/tests/system/action/projector/test_add_to_preview.py +++ b/tests/system/action/projector/test_add_to_preview.py @@ -12,15 +12,13 @@ def setUp(self) -> None: "assignment/1": { "meeting_id": 1, "title": "test assignment", - "sequential_number": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/1", - "sequential_number": 11, "meeting_id": 1, }, - "projector/2": {"meeting_id": 1, "sequential_number": 2}, - "projector/3": {"meeting_id": 1, "sequential_number": 3}, + "projector/2": {"meeting_id": 1}, + "projector/3": {"meeting_id": 1}, "projection/10": { "meeting_id": 1, "content_object_id": "assignment/1", diff --git a/tests/system/action/projector/test_delete.py b/tests/system/action/projector/test_delete.py index 782b6bb0b..018ffb9b9 100644 --- a/tests/system/action/projector/test_delete.py +++ b/tests/system/action/projector/test_delete.py @@ -11,7 +11,6 @@ def setUp(self) -> None: "projector/111": { "name": "name_srtgb123", "meeting_id": 1, - "sequential_number": 111, "used_as_default_projector_for_motion_in_meeting_id": 1, }, } diff --git a/tests/system/action/projector/test_next.py b/tests/system/action/projector/test_next.py index 2c1df5504..5dbe37576 100644 --- a/tests/system/action/projector/test_next.py +++ b/tests/system/action/projector/test_next.py @@ -8,9 +8,9 @@ def setUp(self) -> None: self.create_meeting() self.set_models( { - "projector/2": {"meeting_id": 1, "sequential_number": 2}, - "projector/3": {"meeting_id": 1, "sequential_number": 3}, - "projector/4": {"meeting_id": 1, "sequential_number": 4}, + "projector/2": {"meeting_id": 1}, + "projector/3": {"meeting_id": 1}, + "projector/4": {"meeting_id": 1}, "projection/1": { "current_projector_id": 3, "meeting_id": 1, diff --git a/tests/system/action/projector/test_previous.py b/tests/system/action/projector/test_previous.py index 3eae9b198..4ec19649b 100644 --- a/tests/system/action/projector/test_previous.py +++ b/tests/system/action/projector/test_previous.py @@ -8,9 +8,9 @@ def setUp(self) -> None: self.create_meeting() self.set_models( { - "projector/2": {"meeting_id": 1, "sequential_number": 2}, - "projector/3": {"meeting_id": 1, "sequential_number": 3}, - "projector/4": {"meeting_id": 1, "sequential_number": 4}, + "projector/2": {"meeting_id": 1}, + "projector/3": {"meeting_id": 1}, + "projector/4": {"meeting_id": 1}, "projection/1": { "current_projector_id": 3, "meeting_id": 1, diff --git a/tests/system/action/projector/test_project.py b/tests/system/action/projector/test_project.py index bb5c11b3f..658d582e8 100644 --- a/tests/system/action/projector/test_project.py +++ b/tests/system/action/projector/test_project.py @@ -10,8 +10,8 @@ def setUp(self) -> None: self.set_models( { "projector/1": {"scroll": 80}, - "projector/65": {"meeting_id": 1, "sequential_number": 65}, - "projector/75": {"meeting_id": 1, "sequential_number": 75}, + "projector/65": {"meeting_id": 1}, + "projector/75": {"meeting_id": 1}, "projection/105": { "meeting_id": 1, "content_object_id": "assignment/452", @@ -40,21 +40,17 @@ def setUp(self) -> None: "assignment/452": { "meeting_id": 1, "title": "assignment 452", - "sequential_number": 452, }, "assignment/453": { "meeting_id": 1, "title": "assignment 453", - "sequential_number": 453, }, "list_of_speakers/23": { "content_object_id": "assignment/452", - "sequential_number": 11, "meeting_id": 1, }, "list_of_speakers/42": { "content_object_id": "assignment/453", - "sequential_number": 12, "meeting_id": 1, }, } diff --git a/tests/system/action/projector/test_project_preview.py b/tests/system/action/projector/test_project_preview.py index 7b9d857b8..69c51a830 100644 --- a/tests/system/action/projector/test_project_preview.py +++ b/tests/system/action/projector/test_project_preview.py @@ -8,7 +8,7 @@ def setUp(self) -> None: self.create_meeting() self.set_models( { - "projector/2": {"meeting_id": 1, "sequential_number": 2}, + "projector/2": {"meeting_id": 1}, "projection/1": { "current_projector_id": 1, "meeting_id": 1, diff --git a/tests/system/action/projector/test_toggle.py b/tests/system/action/projector/test_toggle.py index bc6ccf849..4893c2621 100644 --- a/tests/system/action/projector/test_toggle.py +++ b/tests/system/action/projector/test_toggle.py @@ -20,7 +20,6 @@ def create_poll(self, base: int) -> None: "backend": "fast", "pollmethod": "YN", "onehundred_percent_base": Poll.ONEHUNDRED_PERCENT_BASE_YN, - "sequential_number": base, "content_object_id": "motion/1", } } diff --git a/tests/system/action/projector/test_update.py b/tests/system/action/projector/test_update.py index 8d9928229..759b492be 100644 --- a/tests/system/action/projector/test_update.py +++ b/tests/system/action/projector/test_update.py @@ -8,7 +8,7 @@ def setUp(self) -> None: self.create_meeting() def test_update_correct(self) -> None: - self.set_models({"projector/2": {"meeting_id": 1, "sequential_number": 2}}) + self.set_models({"projector/2": {"meeting_id": 1}}) response = self.request( "projector.update", { @@ -97,7 +97,7 @@ def test_update_add_used_as_default_projector_in_meeting_id(self) -> None: "projector/1": { "used_as_default_projector_for_topic_in_meeting_id": 1, }, - "projector/2": {"sequential_number": 2, "meeting_id": 1}, + "projector/2": {"meeting_id": 1}, } ) response = self.request( diff --git a/tests/system/action/speaker/test_create.py b/tests/system/action/speaker/test_create.py index dd3c6ab20..e8b3a5222 100644 --- a/tests/system/action/speaker/test_create.py +++ b/tests/system/action/speaker/test_create.py @@ -26,10 +26,9 @@ def setUp(self) -> None: "password": self.auth.hash(DEFAULT_PASSWORD), }, "meeting_user/17": {"meeting_id": 1, "user_id": 7}, - "topic/1337": {"title": "leet", "sequential_number": 1337, "meeting_id": 1}, + "topic/1337": {"title": "leet", "meeting_id": 1}, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [], "meeting_id": 1, @@ -241,12 +240,10 @@ def test_create_add_2_speakers_in_1_action(self) -> None: { "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -290,12 +287,10 @@ def test_create_add_2_speakers_in_2_actions(self) -> None: "user/9": {"username": "Wulf-Siegmar"}, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [1], "meeting_id": 7844, @@ -347,12 +342,10 @@ def test_create_user_present(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [], "meeting_id": 7844, @@ -388,12 +381,10 @@ def test_create_user_not_present(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [], "meeting_id": 7844, @@ -436,12 +427,10 @@ def test_create_standard_speaker_in_only_talker_list(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [1], "meeting_id": 7844, @@ -516,12 +505,10 @@ def test_create_standard_speaker_at_the_end_of_filled_list(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [1, 2, 3], "meeting_id": 7844, @@ -554,12 +541,10 @@ def test_create_not_in_meeting(self) -> None: "user/7": {"username": "Helgard"}, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 4, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [], "meeting_id": 4, @@ -835,12 +820,10 @@ def test_create_category_weights_with_ranks(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [1, 2, 3, 4, 5], "meeting_id": 1, @@ -913,12 +896,10 @@ def test_create_category_key_error_problem(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "speaker_ids": [1], "meeting_id": 1, diff --git a/tests/system/action/speaker/test_create_for_merge.py b/tests/system/action/speaker/test_create_for_merge.py index ae29c0835..fdb7ec05d 100644 --- a/tests/system/action/speaker/test_create_for_merge.py +++ b/tests/system/action/speaker/test_create_for_merge.py @@ -15,7 +15,6 @@ def setUp(self) -> None: self.set_models( { "motion/357": { - "sequential_number": 357, "state_id": 1, "title": "title_YIDYXmKj", "meeting_id": 1, @@ -27,7 +26,6 @@ def setUp(self) -> None: }, "meeting_user/78": {"meeting_id": 1, "user_id": 78}, "list_of_speakers/1": { - "sequential_number": 1, "content_object_id": "motion/357", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_create_point_of_order.py b/tests/system/action/speaker/test_create_point_of_order.py index befe9f35c..b9fcc3184 100644 --- a/tests/system/action/speaker/test_create_point_of_order.py +++ b/tests/system/action/speaker/test_create_point_of_order.py @@ -25,7 +25,6 @@ def test_create_poo_in_only_talker_list(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -33,7 +32,6 @@ def test_create_poo_in_only_talker_list(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [1], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -120,7 +118,6 @@ def test_create_poo_after_existing_poo_before_standard(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -128,7 +125,6 @@ def test_create_poo_after_existing_poo_before_standard(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [1, 2, 3], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -230,7 +226,6 @@ def test_create_poo_after_existing_poo_before_standard_and_more(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -238,7 +233,6 @@ def test_create_poo_after_existing_poo_before_standard_and_more(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [1, 2, 3, 4], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -330,7 +324,6 @@ def test_create_poo_after_existing_poo_at_the_end(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -338,7 +331,6 @@ def test_create_poo_after_existing_poo_at_the_end(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [1], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -383,7 +375,6 @@ def test_create_poo_already_exist(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -391,7 +382,6 @@ def test_create_poo_already_exist(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [42], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -427,7 +417,6 @@ def test_create_poo_not_activated_in_meeting(self) -> None: { "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -435,7 +424,6 @@ def test_create_poo_not_activated_in_meeting(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "speaker_ids": [], "content_object_id": "topic/1337", "meeting_id": 7844, @@ -467,7 +455,6 @@ def test_create_poo_without_user_id(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -475,7 +462,6 @@ def test_create_poo_without_user_id(self) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 7844, }, @@ -509,7 +495,6 @@ def setup_create_poo_for_other_user(self, allow: bool = False) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 7844, }, "agenda_item/1": { @@ -517,7 +502,6 @@ def setup_create_poo_for_other_user(self, allow: bool = False) -> None: "meeting_id": 7844, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 7844, }, diff --git a/tests/system/action/speaker/test_delete.py b/tests/system/action/speaker/test_delete.py index 565037ed2..c6058df82 100644 --- a/tests/system/action/speaker/test_delete.py +++ b/tests/system/action/speaker/test_delete.py @@ -26,11 +26,9 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -55,11 +53,9 @@ def test_delete_correct(self) -> None: }, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, @@ -89,12 +85,10 @@ def test_delete_wrong_id(self) -> None: }, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "agenda_item/8": {"meeting_id": 111, "content_object_id": "topic/1337"}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, @@ -151,11 +145,9 @@ def test_delete_correct_on_closed_los(self) -> None: }, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "list_of_speakers/23": { - "sequential_number": 23, "closed": True, "content_object_id": "topic/1337", "meeting_id": 111, @@ -185,11 +177,9 @@ def test_delete_with_removed_user(self) -> None: }, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, @@ -212,11 +202,9 @@ def test_delete_with_deleted_user(self) -> None: { "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, @@ -326,12 +314,10 @@ def test_with_active_structure_level_speaker(self) -> None: }, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 111, }, "agenda_item/8": {"meeting_id": 111, "content_object_id": "topic/1337"}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, @@ -391,11 +377,9 @@ def test_with_paused_structure_level_speaker(self) -> None: }, "topic/1337": { "title": "leet", - "sequential_number": 1337, "meeting_id": 111, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 111, }, diff --git a/tests/system/action/speaker/test_end_speech.py b/tests/system/action/speaker/test_end_speech.py index 524fc16a8..c6e89b36c 100644 --- a/tests/system/action/speaker/test_end_speech.py +++ b/tests/system/action/speaker/test_end_speech.py @@ -28,12 +28,10 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_pause.py b/tests/system/action/speaker/test_pause.py index c459aa39d..3711b4fd6 100644 --- a/tests/system/action/speaker/test_pause.py +++ b/tests/system/action/speaker/test_pause.py @@ -18,12 +18,10 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_sort.py b/tests/system/action/speaker/test_sort.py index 57fddb31e..82412f880 100644 --- a/tests/system/action/speaker/test_sort.py +++ b/tests/system/action/speaker/test_sort.py @@ -10,12 +10,10 @@ def setUp(self) -> None: self.permission_test_models: dict[str, dict[str, Any]] = { "topic/1337": { "title": "introduction leek gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/222": { - "sequential_number": 222, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -29,12 +27,10 @@ def test_sort_correct_1(self) -> None: { "topic/1337": { "title": "introduction leek gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/222": { - "sequential_number": 222, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -57,12 +53,10 @@ def test_sort_missing_model(self) -> None: { "topic/1337": { "title": "introduction leek gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/222": { - "sequential_number": 222, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -84,12 +78,10 @@ def test_sort_another_section_db(self) -> None: { "topic/1337": { "title": "introduction leek gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/222": { - "sequential_number": 222, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_speak.py b/tests/system/action/speaker/test_speak.py index ab0961336..512a2bb2b 100644 --- a/tests/system/action/speaker/test_speak.py +++ b/tests/system/action/speaker/test_speak.py @@ -18,12 +18,10 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, @@ -387,11 +385,9 @@ def test_speak_stop_paused_speaker(self) -> None: { "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_unpause.py b/tests/system/action/speaker/test_unpause.py index f644035b8..4a021553c 100644 --- a/tests/system/action/speaker/test_unpause.py +++ b/tests/system/action/speaker/test_unpause.py @@ -18,12 +18,10 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7, "speaker_ids": [890]}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/speaker/test_update.py b/tests/system/action/speaker/test_update.py index bf3df6dc1..1054f63bf 100644 --- a/tests/system/action/speaker/test_update.py +++ b/tests/system/action/speaker/test_update.py @@ -19,12 +19,10 @@ def setUp(self) -> None: "meeting_user/7": {"meeting_id": 1, "user_id": 7}, "topic/1337": { "title": "introduction leet gathering", - "sequential_number": 1337, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, "list_of_speakers/23": { - "sequential_number": 23, "content_object_id": "topic/1337", "meeting_id": 1, }, diff --git a/tests/system/action/structure_level_list_of_speakers/test_add_time.py b/tests/system/action/structure_level_list_of_speakers/test_add_time.py index cf8f842bd..4708be545 100644 --- a/tests/system/action/structure_level_list_of_speakers/test_add_time.py +++ b/tests/system/action/structure_level_list_of_speakers/test_add_time.py @@ -16,25 +16,21 @@ def setUp(self) -> None: }, "topic/32": { "title": "leet improvement discussion", - "sequential_number": 32, "meeting_id": 1, }, "topic/42": { "title": "leet improvement discussion 2nd", - "sequential_number": 42, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/32", "meeting_id": 1}, "agenda_item/2": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/1": { "meeting_id": 1, - "sequential_number": 1, "content_object_id": "topic/32", "structure_level_list_of_speakers_ids": [1, 2, 3], }, "list_of_speakers/2": { "meeting_id": 1, - "sequential_number": 2, "content_object_id": "topic/42", "structure_level_list_of_speakers_ids": [4], }, diff --git a/tests/system/action/structure_level_list_of_speakers/test_create.py b/tests/system/action/structure_level_list_of_speakers/test_create.py index 1bfe6e8a4..143b15720 100644 --- a/tests/system/action/structure_level_list_of_speakers/test_create.py +++ b/tests/system/action/structure_level_list_of_speakers/test_create.py @@ -14,14 +14,12 @@ def setUp(self) -> None: }, "topic/32": { "title": "leet improvement discussion", - "sequential_number": 32, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/32", "meeting_id": 1}, "structure_level/1": {"meeting_id": 1, "name": "d."}, "list_of_speakers/2": { "meeting_id": 1, - "sequential_number": 1, "content_object_id": "topic/32", }, } diff --git a/tests/system/action/structure_level_list_of_speakers/test_delete.py b/tests/system/action/structure_level_list_of_speakers/test_delete.py index f87173399..ecf3a73c7 100644 --- a/tests/system/action/structure_level_list_of_speakers/test_delete.py +++ b/tests/system/action/structure_level_list_of_speakers/test_delete.py @@ -11,7 +11,6 @@ def test_delete(self) -> None: }, "topic/32": { "title": "leet improvement discussion", - "sequential_number": 32, "meeting_id": 1, }, "agenda_item/8": {"meeting_id": 1, "content_object_id": "topic/32"}, @@ -22,7 +21,6 @@ def test_delete(self) -> None: }, "list_of_speakers/2": { "meeting_id": 1, - "sequential_number": 2, "content_object_id": "topic/32", "structure_level_list_of_speakers_ids": [3], }, diff --git a/tests/system/action/structure_level_list_of_speakers/test_update.py b/tests/system/action/structure_level_list_of_speakers/test_update.py index dd2a2efd2..c79443076 100644 --- a/tests/system/action/structure_level_list_of_speakers/test_update.py +++ b/tests/system/action/structure_level_list_of_speakers/test_update.py @@ -18,12 +18,10 @@ def setUp(self) -> None: }, "topic/1337": { "title": "leet improvement discussion", - "sequential_number": 1337, "meeting_id": 1, }, "topic/42": { "title": "leet improvement discussion", - "sequential_number": 42, "meeting_id": 1, }, "agenda_item/1": {"content_object_id": "topic/1337", "meeting_id": 1}, @@ -36,7 +34,6 @@ def setUp(self) -> None: "list_of_speakers/2": { "meeting_id": 1, "content_object_id": "topic/1337", - "sequential_number": 2, "structure_level_list_of_speakers_ids": [3], }, "structure_level_list_of_speakers/3": { @@ -49,7 +46,6 @@ def setUp(self) -> None: "list_of_speakers/4": { "meeting_id": 1, "content_object_id": "topic/42", - "sequential_number": 4, "structure_level_list_of_speakers_ids": [5], }, "structure_level_list_of_speakers/5": { diff --git a/tests/system/action/test_archived_meeting.py b/tests/system/action/test_archived_meeting.py index 540ea56af..6e7bf9812 100644 --- a/tests/system/action/test_archived_meeting.py +++ b/tests/system/action/test_archived_meeting.py @@ -98,13 +98,11 @@ def test_delete_meeting(self) -> None: }, "topic/23": { "title": "to pic", - "sequential_number": 1, "meeting_id": 1, }, "agenda_item/8": {"content_object_id": "topic/23", "meeting_id": 1}, "list_of_speakers/11": { "content_object_id": "topic/23", - "sequential_number": 11, "meeting_id": 1, }, "speaker/1": { @@ -119,13 +117,11 @@ def test_delete_meeting(self) -> None: }, "topic/42": { "title": "to pic", - "sequential_number": 2, "meeting_id": 1, }, "agenda_item/9": {"content_object_id": "topic/42", "meeting_id": 1}, "list_of_speakers/12": { "content_object_id": "topic/42", - "sequential_number": 11, "meeting_id": 1, }, "speaker/3": { diff --git a/tests/system/action/topic/test_create.py b/tests/system/action/topic/test_create.py index decbc8b5d..a46539155 100644 --- a/tests/system/action/topic/test_create.py +++ b/tests/system/action/topic/test_create.py @@ -7,11 +7,7 @@ class TopicCreateSystemTest(BaseActionTestCase): def test_create(self) -> None: self.create_meeting() - self.set_models( - { - "topic/41": {"title": "0", "sequential_number": 1, "meeting_id": 1}, - } - ) + self.set_models({"topic/41": {"title": "0", "meeting_id": 1}}) response = self.request("topic.create", {"meeting_id": 1, "title": "test"}) self.assert_status_code(response, 200) self.assert_model_exists( @@ -190,11 +186,7 @@ def test_create_more_fields(self) -> None: def test_create_multiple_with_existing_sequential_number(self) -> None: self.create_meeting() - self.set_models( - { - "topic/1": {"title": "0", "meeting_id": 1, "sequential_number": 42}, - } - ) + self.set_models({"topic/1": {"title": "0", "meeting_id": 1}}) response = self.request_multi( "topic.create", [ diff --git a/tests/system/action/topic/test_delete.py b/tests/system/action/topic/test_delete.py index a035d8ab0..aec31637b 100644 --- a/tests/system/action/topic/test_delete.py +++ b/tests/system/action/topic/test_delete.py @@ -10,13 +10,11 @@ def setUp(self) -> None: self.create_meeting() self.permission_test_models: dict[str, dict[str, Any]] = { "topic/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "topic/111", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/8": {"meeting_id": 1, "content_object_id": "topic/111"}, @@ -26,13 +24,11 @@ def test_delete_correct(self) -> None: self.set_models( { "topic/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "topic/111", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/8": {"meeting_id": 1, "content_object_id": "topic/111"}, @@ -47,12 +43,10 @@ def test_delete_wrong_id(self) -> None: { "topic/112": { "meeting_id": 1, - "sequential_number": 12, "title": "title_srtgb123", }, "list_of_speakers/23": { "content_object_id": "topic/112", - "sequential_number": 11, "meeting_id": 1, }, "agenda_item/9": {"meeting_id": 1, "content_object_id": "topic/112"}, @@ -66,12 +60,10 @@ def test_delete_correct_cascading(self) -> None: self.set_models( { "topic/111": { - "sequential_number": 1, "title": "title_srtgb123", "meeting_id": 1, }, "list_of_speakers/222": { - "sequential_number": 22, "closed": False, "content_object_id": "topic/111", "meeting_id": 1, @@ -114,14 +106,12 @@ def test_delete_with_agenda_item_and_filled_los(self) -> None: { "topic/1": { "title": "tipuc", - "sequential_number": 1, "agenda_item_id": 3, "list_of_speakers_id": 3, "meeting_id": 1, }, "agenda_item/3": {"content_object_id": "topic/1", "meeting_id": 1}, "list_of_speakers/3": { - "sequential_number": 1, "content_object_id": "topic/1", "meeting_id": 1, }, diff --git a/tests/system/action/topic/test_import.py b/tests/system/action/topic/test_import.py index 08132d781..bb3345039 100644 --- a/tests/system/action/topic/test_import.py +++ b/tests/system/action/topic/test_import.py @@ -77,7 +77,7 @@ def test_import_abort_import_with_error(self) -> None: def test_import_found_id_and_text_field(self) -> None: self.set_models( { - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 22}, + "topic/1": {"title": "test", "meeting_id": 22}, "import_preview/2": { "state": ImportState.DONE, "name": "topic", @@ -117,7 +117,6 @@ def test_import_found_id_and_agenda_fields(self) -> None: self.set_models( { "topic/1": { - "sequential_number": 1, "title": "test", "meeting_id": 22, "agenda_item_id": 7, @@ -176,7 +175,7 @@ def test_import_found_id_and_agenda_fields(self) -> None: def test_import_duplicate_and_topic_deleted(self) -> None: self.set_models( { - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 22}, + "topic/1": {"title": "test", "meeting_id": 22}, "meeting/22": {"topic_ids": [1]}, } ) @@ -245,9 +244,7 @@ def test_import_topic_switched_id(self) -> None: self.json_upload_duplicate_in_db() self.request("topic.delete", {"id": 3}) self.assert_model_not_exists("topic/3") - self.create_model( - "topic/4", {"sequential_number": 2, "title": "test", "meeting_id": 22} - ) + self.create_model("topic/4", {"title": "test", "meeting_id": 22}) response = self.request("topic.import", {"id": 1, "import": True}) self.assert_status_code(response, 200) result = response.json["results"][0][0] @@ -259,9 +256,7 @@ def test_import_topic_switched_id(self) -> None: def test_import_topic_duplicate_id(self) -> None: self.json_upload_duplicate_in_db() - self.create_model( - "topic/4", {"sequential_number": 2, "title": "test", "meeting_id": 22} - ) + self.create_model("topic/4", {"title": "test", "meeting_id": 22}) response = self.request("topic.import", {"id": 1, "import": True}) self.assert_status_code(response, 200) result = response.json["results"][0][0] diff --git a/tests/system/action/topic/test_json_upload.py b/tests/system/action/topic/test_json_upload.py index ded78043e..cc4cd3188 100644 --- a/tests/system/action/topic/test_json_upload.py +++ b/tests/system/action/topic/test_json_upload.py @@ -144,9 +144,7 @@ def test_json_upload_duplicate_in_data(self) -> None: ) def test_json_upload_duplicate_in_existing_topic(self) -> None: - self.set_models( - {"topic/10": {"sequential_number": 5, "title": "test", "meeting_id": 22}} - ) + self.set_models({"topic/10": {"title": "test", "meeting_id": 22}}) response = self.request( "topic.json_upload", { @@ -229,7 +227,6 @@ def json_upload_duplicate_in_db(self) -> None: self.set_models( { "topic/3": { - "sequential_number": 2, "title": "test", "text": "old one", "meeting_id": 22, diff --git a/tests/system/action/topic/test_update.py b/tests/system/action/topic/test_update.py index e28cdcb7d..9275938e7 100644 --- a/tests/system/action/topic/test_update.py +++ b/tests/system/action/topic/test_update.py @@ -9,16 +9,12 @@ def setUp(self) -> None: super().setUp() self.permission_test_models: dict[str, dict[str, Any]] = { "meeting/1": {"name": "test", "is_active_in_organization_id": 1}, - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 1}, + "topic/1": {"title": "test", "meeting_id": 1}, } def test_update_simple(self) -> None: self.create_meeting() - self.set_models( - { - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 1}, - } - ) + self.set_models({"topic/1": {"title": "test", "meeting_id": 1}}) response = self.request( "topic.update", {"id": 1, "title": "test2", "text": "text"} ) @@ -31,7 +27,7 @@ def test_update_with_attachment(self) -> None: self.create_meeting() self.set_models( { - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 1}, + "topic/1": {"title": "test", "meeting_id": 1}, "mediafile/1": {"owner_id": "meeting/1", "meeting_mediafile_ids": [11]}, "meeting_mediafile/11": { "is_public": False, @@ -61,11 +57,7 @@ def test_update_with_attachment(self) -> None: def test_update_text_with_iframe(self) -> None: self.create_meeting() - self.set_models( - { - "topic/1": {"sequential_number": 1, "title": "test", "meeting_id": 1}, - } - ) + self.set_models({"topic/1": {"title": "test", "meeting_id": 1}}) response = self.request( "topic.update", {"id": 1, "text": ""} ) diff --git a/tests/system/action/user/test_delete.py b/tests/system/action/user/test_delete.py index 61128e8a7..e3c3cd0a4 100644 --- a/tests/system/action/user/test_delete.py +++ b/tests/system/action/user/test_delete.py @@ -90,13 +90,11 @@ def test_delete_with_speaker(self) -> None: "meeting_id": 1, }, "list_of_speakers/1": { - "sequential_number": 1, "meeting_id": 1, "content_object_id": "topic/1", }, "topic/1": { "title": "tropic", - "sequential_number": 1, "meeting_id": 1, }, "agenda_item/8": {"meeting_id": 1, "content_object_id": "topic/1"}, @@ -140,12 +138,10 @@ def test_delete_with_candidate(self) -> None: "assignment/123": { "title": "test_assignment", "candidate_ids": [34], - "sequential_number": 123, "meeting_id": 1, }, "list_of_speakers/23": { "content_object_id": "assignment/123", - "sequential_number": 11, "meeting_id": 1, }, } diff --git a/tests/system/action/user/test_merge_together.py b/tests/system/action/user/test_merge_together.py index fce164a79..6bfc2839b 100644 --- a/tests/system/action/user/test_merge_together.py +++ b/tests/system/action/user/test_merge_together.py @@ -1463,7 +1463,6 @@ def test_merge_with_assignment_candidates_in_finished_assignment(self) -> None: }, "assignment/11": { "meeting_id": 1, - "sequential_number": 11, "title": "a signment", "phase": "finished", "candidate_ids": [112, 114], diff --git a/tests/system/action/user/test_update.py b/tests/system/action/user/test_update.py index 8ab160a32..ed58c276e 100644 --- a/tests/system/action/user/test_update.py +++ b/tests/system/action/user/test_update.py @@ -3004,10 +3004,9 @@ def test_group_removal_with_speaker(self) -> None: "committee_id": 63, "present_user_ids": [1234], }, - "topic/1": {"title": "tropic", "sequential_number": 1, "meeting_id": 4}, + "topic/1": {"title": "tropic", "meeting_id": 4}, "list_of_speakers/1": { "meeting_id": 4, - "sequential_number": 1, "content_object_id": "topic/1", }, "speaker/14": { @@ -3083,10 +3082,9 @@ def test_partial_group_removal_with_speaker(self) -> None: "user_id": 1234, "speaker_ids": [14, 24], }, - "topic/1": {"title": "tropic", "sequential_number": 1, "meeting_id": 4}, + "topic/1": {"title": "tropic", "meeting_id": 4}, "list_of_speakers/1": { "meeting_id": 4, - "sequential_number": 1, "content_object_id": "topic/1", }, "speaker/14": { @@ -3147,14 +3145,13 @@ def test_update_with_internal_fields(self) -> None: "poll_candidate_ids": [1], "vote_ids": [1, 2], }, - "topic/1": {"title": "tropic", "sequential_number": 1, "meeting_id": 1}, + "topic/1": {"title": "tropic", "meeting_id": 1}, "poll/1": { "title": "pull", "type": "analog", "pollmethod": "YNA", "meeting_id": 1, "option_ids": [1, 2], - "sequential_number": 1, "content_object_id": "topic/1", }, "option/1": { diff --git a/tests/system/presenter/test_check_database.py b/tests/system/presenter/test_check_database.py index 88c1d9000..ffc047420 100644 --- a/tests/system/presenter/test_check_database.py +++ b/tests/system/presenter/test_check_database.py @@ -195,7 +195,6 @@ def test_correct(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -215,7 +214,6 @@ def test_correct(self) -> None: "show_recommendation_extension_field": False, }, "projector/1": { - "sequential_number": 1, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, "name": "Default projector", @@ -425,7 +423,6 @@ def test_correct_relations(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -446,7 +443,6 @@ def test_correct_relations(self) -> None: "motion_ids": [1], }, "projector/1": { - "sequential_number": 1, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, "name": "Default projector", @@ -485,7 +481,6 @@ def test_correct_relations(self) -> None: "motion/1": { "submitter_ids": [5], "meeting_id": 1, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -500,7 +495,6 @@ def test_correct_relations(self) -> None: }, "list_of_speakers/6": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/1", "meeting_id": 1, }, @@ -526,14 +520,12 @@ def test_correct_relations(self) -> None: "title": "test", "open_posts": 0, "phase": "search", - "sequential_number": 1, "candidate_ids": [9], "meeting_id": 1, "list_of_speakers_id": 11, }, "list_of_speakers/11": { "closed": True, - "sequential_number": 1, "content_object_id": "assignment/10", "meeting_id": 1, }, @@ -600,7 +592,6 @@ def test_relation_2(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -621,7 +612,6 @@ def test_relation_2(self) -> None: "motion_ids": [1], }, "projector/1": { - "sequential_number": 1, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, "name": "Default projector", @@ -684,7 +674,6 @@ def test_relation_2(self) -> None: "default_amendment_workflow_meeting_id": 2, "default_workflow_meeting_id": 2, "state_ids": [2], - "sequential_number": 2, }, "motion_state/2": { "css_class": "lightblue", @@ -704,7 +693,6 @@ def test_relation_2(self) -> None: "motion_ids": [2], }, "projector/2": { - "sequential_number": 1, "meeting_id": 2, "used_as_reference_projector_meeting_id": 2, "name": "Default projector", @@ -728,7 +716,6 @@ def test_relation_2(self) -> None: }, "motion/1": { "meeting_id": 1, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -739,7 +726,6 @@ def test_relation_2(self) -> None: }, "motion/2": { "meeting_id": 2, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -750,13 +736,11 @@ def test_relation_2(self) -> None: }, "list_of_speakers/3": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/1", "meeting_id": 1, }, "list_of_speakers/4": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/2", "meeting_id": 2, }, diff --git a/tests/system/presenter/test_check_database_all.py b/tests/system/presenter/test_check_database_all.py index 4c4ba9108..5db363c6f 100644 --- a/tests/system/presenter/test_check_database_all.py +++ b/tests/system/presenter/test_check_database_all.py @@ -229,7 +229,6 @@ def test_correct(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -251,7 +250,6 @@ def test_correct(self) -> None: "show_recommendation_extension_field": False, }, "projector/1": { - "sequential_number": 1, "is_internal": False, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, @@ -504,7 +502,6 @@ def test_correct_relations(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -527,7 +524,6 @@ def test_correct_relations(self) -> None: "motion_ids": [1], }, "projector/1": { - "sequential_number": 1, "is_internal": False, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, @@ -569,7 +565,6 @@ def test_correct_relations(self) -> None: "motion/1": { "submitter_ids": [5], "meeting_id": 1, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -584,7 +579,6 @@ def test_correct_relations(self) -> None: }, "list_of_speakers/6": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/1", "meeting_id": 1, }, @@ -610,14 +604,12 @@ def test_correct_relations(self) -> None: "title": "test", "open_posts": 0, "phase": "search", - "sequential_number": 1, "candidate_ids": [9], "meeting_id": 1, "list_of_speakers_id": 11, }, "list_of_speakers/11": { "closed": True, - "sequential_number": 1, "content_object_id": "assignment/10", "meeting_id": 1, }, @@ -721,7 +713,6 @@ def test_relation_2(self) -> None: "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, }, "motion_state/1": { "css_class": "lightblue", @@ -744,7 +735,6 @@ def test_relation_2(self) -> None: "motion_ids": [1], }, "projector/1": { - "sequential_number": 1, "is_internal": False, "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, @@ -810,7 +800,6 @@ def test_relation_2(self) -> None: "default_amendment_workflow_meeting_id": 2, "default_workflow_meeting_id": 2, "state_ids": [2], - "sequential_number": 2, }, "motion_state/2": { "css_class": "lightblue", @@ -832,7 +821,6 @@ def test_relation_2(self) -> None: "motion_ids": [2], }, "projector/2": { - "sequential_number": 1, "is_internal": False, "meeting_id": 2, "used_as_reference_projector_meeting_id": 2, @@ -859,7 +847,6 @@ def test_relation_2(self) -> None: }, "motion/1": { "meeting_id": 1, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -870,7 +857,6 @@ def test_relation_2(self) -> None: }, "motion/2": { "meeting_id": 2, - "sequential_number": 1, "title": "test Motion", "category_weight": 10000, "sort_weight": 10000, @@ -881,13 +867,11 @@ def test_relation_2(self) -> None: }, "list_of_speakers/3": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/1", "meeting_id": 1, }, "list_of_speakers/4": { "closed": True, - "sequential_number": 1, "content_object_id": "motion/2", "meeting_id": 2, }, diff --git a/tests/system/presenter/test_export_meeting.py b/tests/system/presenter/test_export_meeting.py index 440c57b4b..ce568ef6f 100644 --- a/tests/system/presenter/test_export_meeting.py +++ b/tests/system/presenter/test_export_meeting.py @@ -229,7 +229,6 @@ def test_export_meeting_with_ex_user(self) -> None: "motion/1": { "list_of_speakers_id": 1, "meeting_id": 1, - "sequential_number": 1, "state_id": 1, "submitter_ids": [1], "title": "dummy", @@ -242,7 +241,6 @@ def test_export_meeting_with_ex_user(self) -> None: "list_of_speakers/1": { "content_object_id": "motion/1", "meeting_id": 1, - "sequential_number": 1, }, "motion_state/1": { "motion_ids": [1], diff --git a/tests/system/presenter/test_get_history_information.py b/tests/system/presenter/test_get_history_information.py index 415dcadee..cd90041dc 100644 --- a/tests/system/presenter/test_get_history_information.py +++ b/tests/system/presenter/test_get_history_information.py @@ -40,7 +40,6 @@ def test_simple(self) -> None: { "motion_workflow/1": { "name": "work", - "sequential_number": 1, "first_state_id": 1, "meeting_id": 1, }, From 3010672ea4e9eb65e0f6e3fa2c131a76b9588bf4 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Tue, 7 Oct 2025 19:02:48 +0200 Subject: [PATCH 03/19] Start of actions cleanup --- docs/actions/motion.create.md | 3 +-- docs/actions/motion.create_forwarded.md | 1 - .../action/actions/list_of_speakers/create.py | 3 +-- .../actions/motion/base_create_forwarded.py | 2 -- .../action/actions/motion/create.py | 1 - .../action/actions/motion/create_base.py | 7 ------- .../action/actions/poll/create.py | 2 -- .../action/actions/projector/create.py | 3 +-- .../action/actions/topic/create.py | 2 -- openslides_backend/models/fields.py | 2 ++ .../action/motion/test_create_forwarded.py | 19 +++++++------------ .../motion/test_create_sequential_number.py | 2 +- tests/system/action/projector/test_create.py | 2 +- tests/system/action/topic/test_create.py | 9 ++------- 14 files changed, 16 insertions(+), 42 deletions(-) diff --git a/docs/actions/motion.create.md b/docs/actions/motion.create.md index 72f6b348f..90481ae60 100644 --- a/docs/actions/motion.create.md +++ b/docs/actions/motion.create.md @@ -62,7 +62,6 @@ There are some fields that need special attention: - `agenda_*`: See [Agenda](https://github.com/OpenSlides/OpenSlides/wiki/Agenda#additional-fields-during-creation-of-agenda-content-objects). Other things to do when creating motions: -- Set the field `sequential_number`: It is the `max+1` of `sequential_number` of all motions in the same meeting. If there are no other motions in this meeting (e.g. this is the first one), it gets 1. - Set timestamps: - always set `last_modified` and `created` to the current timestamp - if the state pointed to by `first_state_id` of the given workflow has the flag `set_workflow_timestamp` set, also set `workflow_timestamp`to the current timestamp. @@ -98,7 +97,7 @@ This is the procedure to determine what to set for the field `number`: * Remember: `number` must be unique. If a motion with this number already exists, increment `number_value` by one and go to the last step (the prefix is the same, the number incremented - try again). * If there is a unique `number`, save it into the motion. Done! * Note: The complete calculation is restricted to motions and other objects from the same meeting. - + ### Some examples for determinating the number. First comes the general setup and the test cases are numbered: `meeting/motions_number_type="manually"` diff --git a/docs/actions/motion.create_forwarded.md b/docs/actions/motion.create_forwarded.md index 0519b3ed0..5600ba190 100644 --- a/docs/actions/motion.create_forwarded.md +++ b/docs/actions/motion.create_forwarded.md @@ -56,7 +56,6 @@ The result object for each instance has the format ``` { id: Id, - sequential_number: int, non_forwarded_amendment_amount: int, // Number of amendments that couldn't be returned because of forwarding being not allowed in the state amendment_result_data: [...], // List of result data objects in the same format, for all newly created amendments for the newly created motion } diff --git a/openslides_backend/action/actions/list_of_speakers/create.py b/openslides_backend/action/actions/list_of_speakers/create.py index 7c0f7ab6a..e00929772 100644 --- a/openslides_backend/action/actions/list_of_speakers/create.py +++ b/openslides_backend/action/actions/list_of_speakers/create.py @@ -5,12 +5,11 @@ from ...mixins.create_action_with_inferred_meeting import ( CreateActionWithInferredMeeting, ) -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema # This action is not registered because you can not call it from outside. -class ListOfSpeakersCreate(SequentialNumbersMixin, CreateActionWithInferredMeeting): +class ListOfSpeakersCreate(CreateActionWithInferredMeeting): name = "list_of_speakers.create" model = ListOfSpeakers() schema = DefaultSchema(ListOfSpeakers()).get_create_schema(["content_object_id"]) diff --git a/openslides_backend/action/actions/motion/base_create_forwarded.py b/openslides_backend/action/actions/motion/base_create_forwarded.py index 0383a6386..a1cb94a5c 100644 --- a/openslides_backend/action/actions/motion/base_create_forwarded.py +++ b/openslides_backend/action/actions/motion/base_create_forwarded.py @@ -197,8 +197,6 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: else: name = committee.get("name", f"Committee {committee['id']}") instance["additional_submitter"] = name - - self.set_sequential_number(instance) self.handle_number(instance) self.set_origin_ids(instance) self.set_text_hash(instance) diff --git a/openslides_backend/action/actions/motion/create.py b/openslides_backend/action/actions/motion/create.py index 888ec3ad3..c36a74754 100644 --- a/openslides_backend/action/actions/motion/create.py +++ b/openslides_backend/action/actions/motion/create.py @@ -131,7 +131,6 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: self.set_state_from_workflow(instance, meeting) self.create_submitters(instance) - self.set_sequential_number(instance) self.set_created_last_modified_and_number(instance) self.set_text_hash(instance) instance = super().update_instance(instance) diff --git a/openslides_backend/action/actions/motion/create_base.py b/openslides_backend/action/actions/motion/create_base.py index 726793a70..a8dae1fcf 100644 --- a/openslides_backend/action/actions/motion/create_base.py +++ b/openslides_backend/action/actions/motion/create_base.py @@ -5,7 +5,6 @@ from ....models.models import Motion from ....shared.patterns import fqid_from_collection_and_id from ...mixins.create_action_with_dependencies import CreateActionWithDependencies -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ..agenda_item.agenda_creation import CreateActionWithAgendaItemMixin from ..agenda_item.create import AgendaItemCreate from ..list_of_speakers.create import ListOfSpeakersCreate @@ -22,7 +21,6 @@ class MotionCreateBase( MeetingUserHelperMixin, CreateActionWithDependencies, CreateActionWithAgendaItemMixin, - SequentialNumbersMixin, SetNumberMixin, CreateActionWithListOfSpeakersMixin, ): @@ -64,11 +62,6 @@ def create_submitters(self, instance: dict[str, Any]) -> None: MotionSubmitterCreateAction, [data], skip_history=True ) - def set_sequential_number(self, instance: dict[str, Any]) -> None: - instance["sequential_number"] = self.get_sequential_number( - instance["meeting_id"] - ) - def set_created_last_modified_and_number(self, instance: dict[str, Any]) -> None: self.set_created_last_modified(instance) self.set_number( diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index d7f60f48c..2d43b990d 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -8,7 +8,6 @@ from ....shared.schema import decimal_schema, id_list_schema, optional_fqid_schema from ...generics.create import CreateAction from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action from ..option.create import OptionCreateAction @@ -33,7 +32,6 @@ @register_action("poll.create") class PollCreateAction( PollValidationMixin, - SequentialNumbersMixin, CreateAction, PollPermissionMixin, PollHistoryMixin, diff --git a/openslides_backend/action/actions/projector/create.py b/openslides_backend/action/actions/projector/create.py index 3cb65e228..1955db1db 100644 --- a/openslides_backend/action/actions/projector/create.py +++ b/openslides_backend/action/actions/projector/create.py @@ -1,13 +1,12 @@ from ....models.models import Meeting, Projector from ....permissions.permissions import Permissions from ...generics.create import CreateAction -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action @register_action("projector.create") -class ProjectorCreateAction(SequentialNumbersMixin, CreateAction): +class ProjectorCreateAction(CreateAction): """ Action to create a projector. """ diff --git a/openslides_backend/action/actions/topic/create.py b/openslides_backend/action/actions/topic/create.py index 3596d78e5..3371785ab 100644 --- a/openslides_backend/action/actions/topic/create.py +++ b/openslides_backend/action/actions/topic/create.py @@ -5,7 +5,6 @@ from ....shared.schema import id_list_schema from ...action import Action from ...mixins.create_action_with_dependencies import CreateActionWithDependencies -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action from ..agenda_item.agenda_creation import ( @@ -23,7 +22,6 @@ @register_action("topic.create") class TopicCreate( AttachmentMixin, - SequentialNumbersMixin, CreateActionWithDependencies, CreateActionWithAgendaItemMixin, CreateActionWithListOfSpeakersMixin, diff --git a/openslides_backend/models/fields.py b/openslides_backend/models/fields.py index 12fefb899..a1329819a 100644 --- a/openslides_backend/models/fields.py +++ b/openslides_backend/models/fields.py @@ -121,6 +121,8 @@ def get_schema(self) -> Schema: def check_required_not_fulfilled( self, instance: dict[str, Any], is_create: bool ) -> bool: + if self.constraints.get("sequence_scope"): + return False if self.own_field_name not in instance: return is_create return instance[self.own_field_name] is None diff --git a/tests/system/action/motion/test_create_forwarded.py b/tests/system/action/motion/test_create_forwarded.py index fe2580eae..24d1300ee 100644 --- a/tests/system/action/motion/test_create_forwarded.py +++ b/tests/system/action/motion/test_create_forwarded.py @@ -323,13 +323,11 @@ def test_allowed_to_forward_amendments_indirectly(self) -> None: { "id": 14, "non_forwarded_amendment_amount": 0, - "sequential_number": 1, "amendment_result_data": [ { "amendment_result_data": [], "id": 15, "non_forwarded_amendment_amount": 0, - "sequential_number": 2, } ], } @@ -344,6 +342,7 @@ def test_allowed_to_forward_amendments_indirectly(self) -> None: "amendment_ids": [15], "state_id": 4, "additional_submitter": "committee_forwarder", + "sequential_number": 2, }, ) self.assert_model_exists( @@ -357,6 +356,7 @@ def test_allowed_to_forward_amendments_indirectly(self) -> None: "amendment_paragraphs": {"0": "texts"}, "additional_submitter": "committee_forwarder", "marked_forwarded": False, + "sequential_number": 1, }, ) @@ -472,23 +472,19 @@ def test_allowed_to_forward_amendments_indirectly_complex(self) -> None: { "id": 18, "non_forwarded_amendment_amount": 1, - "sequential_number": 1, "amendment_result_data": [ { "id": 19, "non_forwarded_amendment_amount": 0, - "sequential_number": 2, "amendment_result_data": [], }, { "id": 20, "non_forwarded_amendment_amount": 1, - "sequential_number": 3, "amendment_result_data": [ { "id": 21, "non_forwarded_amendment_amount": 0, - "sequential_number": 4, "amendment_result_data": [], }, ], @@ -506,7 +502,7 @@ def test_allowed_to_forward_amendments_indirectly_complex(self) -> None: "text": "test", "amendment_ids": [19, 20], "additional_submitter": "A man, A hairy woman", - "sequential_number": 1, + "sequential_number": 4, "state_id": 4, }, ) @@ -520,7 +516,7 @@ def test_allowed_to_forward_amendments_indirectly_complex(self) -> None: "meeting_id": 4, "amendment_paragraphs": {"0": "texts"}, "additional_submitter": "A man", - "sequential_number": 2, + "sequential_number": 1, "state_id": 4, "marked_forwarded": True, }, @@ -552,7 +548,7 @@ def test_allowed_to_forward_amendments_indirectly_complex(self) -> None: "state_id": 4, "amendment_paragraphs": {"0": "testssss"}, "additional_submitter": None, - "sequential_number": 4, + "sequential_number": 2, "marked_forwarded": True, }, ) @@ -1277,12 +1273,10 @@ def test_amendment_forwarding_different_states(self) -> None: { "id": 4, "non_forwarded_amendment_amount": 1, - "sequential_number": 1, "amendment_result_data": [ { "id": 5, "non_forwarded_amendment_amount": 0, - "sequential_number": 2, "amendment_result_data": [], }, ], @@ -1300,7 +1294,7 @@ def test_amendment_forwarding_different_states(self) -> None: "amendment_ids": [5], "all_origin_ids": [1], "origin_meeting_id": 1, - "sequential_number": 1, + "sequential_number": 2, "additional_submitter": "committee_forwarder", "identical_motion_ids": None, }, @@ -1317,6 +1311,7 @@ def test_amendment_forwarding_different_states(self) -> None: "amendment_paragraphs": {"0": "paragraph"}, "all_origin_ids": [3], "additional_submitter": "committee_forwarder", + "sequential_number": 1, }, ) self.assert_model_not_exists("motion/6") diff --git a/tests/system/action/motion/test_create_sequential_number.py b/tests/system/action/motion/test_create_sequential_number.py index f66a94f02..dd2f5bf09 100644 --- a/tests/system/action/motion/test_create_sequential_number.py +++ b/tests/system/action/motion/test_create_sequential_number.py @@ -114,7 +114,7 @@ def test_create_sequential_numbers_deleted_motion(self) -> None: }, ) self.assert_status_code(response, 200) - self.assert_model_exists("motion/2", {"sequential_number": 1}) + self.assert_model_exists("motion/2", {"sequential_number": 2}) @pytest.mark.skip( "Seems to run into an infinite loop, probably since the database is broken. TODO: unskip once this is fixed" diff --git a/tests/system/action/projector/test_create.py b/tests/system/action/projector/test_create.py index 72f53349a..28d3ba995 100644 --- a/tests/system/action/projector/test_create.py +++ b/tests/system/action/projector/test_create.py @@ -15,7 +15,7 @@ def test_create_correct_and_defaults(self) -> None: self.assert_status_code(response, 200) model = self.assert_model_exists( "projector/223", - {"name": "test projector", "meeting_id": 222, "sequential_number": 223}, + {"name": "test projector", "meeting_id": 222, "sequential_number": 2}, ) self.assert_defaults(Projector, model) diff --git a/tests/system/action/topic/test_create.py b/tests/system/action/topic/test_create.py index a46539155..b7f551f9e 100644 --- a/tests/system/action/topic/test_create.py +++ b/tests/system/action/topic/test_create.py @@ -24,9 +24,6 @@ def test_create(self) -> None: ) self.assertTrue(response.json["success"]) self.assertEqual(response.json["message"], "Actions handled successfully") - self.assertEqual( - response.json["results"], [[{"id": 42, "sequential_number": 2}]] - ) def test_create_multiple_requests(self) -> None: self.create_meeting() @@ -195,10 +192,8 @@ def test_create_multiple_with_existing_sequential_number(self) -> None: ], ) self.assert_status_code(response, 200) - topic = self.get_model("topic/2") - self.assertEqual(topic.get("sequential_number"), 43) - topic = self.get_model("topic/3") - self.assertEqual(topic.get("sequential_number"), 44) + self.assert_model_exists("topic/2", {"sequential_number": 2}) + self.assert_model_exists("topic/3", {"sequential_number": 3}) def test_create_meeting_id_agenda_tag_ids_mismatch(self) -> None: """Tag 8 is from meeting 8 and a topic for meeting 1 should be created. From 6c6ed513f485ae19f246e92e13383d42f72de7fc Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 8 Oct 2025 10:49:57 +0200 Subject: [PATCH 04/19] Finish cleanup --- data/example-data.json | 49 +--------------- .../assignment/create_update_delete.py | 2 - .../actions/motion/base_create_forwarded.py | 1 + .../motion_block/create_update_delete.py | 2 - .../motion_category/create_update_delete.py | 4 +- .../actions/motion_comment_section/create.py | 5 +- .../action/actions/motion_workflow/create.py | 7 +-- .../action/actions/motion_workflow/import_.py | 4 +- .../action/mixins/sequential_numbers_mixin.py | 42 -------------- tests/system/action/assignment/test_create.py | 56 ++++++++++--------- tests/system/action/meeting/test_create.py | 3 + tests/system/action/meeting/test_import.py | 51 +++++++++-------- .../action/motion_workflow/test_create.py | 5 +- .../action/motion_workflow/test_import.py | 2 +- tests/system/action/projector/test_create.py | 4 +- 15 files changed, 80 insertions(+), 157 deletions(-) delete mode 100644 openslides_backend/action/mixins/sequential_numbers_mixin.py diff --git a/data/example-data.json b/data/example-data.json index 6379615bf..0bb35c4ce 100644 --- a/data/example-data.json +++ b/data/example-data.json @@ -144,7 +144,7 @@ "meeting_ids": [ 1 ], - "organization_id": 1, + "organization_id": 1, "committee_ids": [ 1 ] @@ -965,7 +965,6 @@ "list_of_speakers": { "1": { "id": 1, - "sequential_number": 1, "content_object_id": "motion/1", "closed": false, "speaker_ids": [ @@ -977,14 +976,12 @@ }, "2": { "id": 2, - "sequential_number": 2, "content_object_id": "motion/2", "closed": false, "meeting_id": 1 }, "3": { "id": 3, - "sequential_number": 3, "content_object_id": "topic/1", "closed": false, "speaker_ids": [ @@ -995,28 +992,24 @@ }, "4": { "id": 4, - "sequential_number": 4, "content_object_id": "topic/2", "closed": false, "meeting_id": 1 }, "5": { "id": 5, - "sequential_number": 5, "content_object_id": "topic/3", "closed": false, "meeting_id": 1 }, "6": { "id": 6, - "sequential_number": 6, "content_object_id": "topic/4", "closed": false, "meeting_id": 1 }, "7": { "id": 7, - "sequential_number": 7, "content_object_id": "topic/5", "closed": false, "speaker_ids": [ @@ -1027,7 +1020,6 @@ }, "8": { "id": 8, - "sequential_number": 8, "content_object_id": "topic/6", "closed": false, "speaker_ids": [ @@ -1037,21 +1029,18 @@ }, "9": { "id": 9, - "sequential_number": 9, "content_object_id": "topic/7", "closed": false, "meeting_id": 1 }, "10": { "id": 10, - "sequential_number": 10, "content_object_id": "topic/8", "closed": false, "meeting_id": 1 }, "11": { "id": 11, - "sequential_number": 11, "content_object_id": "assignment/1", "closed": false, "speaker_ids": [ @@ -1063,21 +1052,18 @@ }, "12": { "id": 12, - "sequential_number": 12, "content_object_id": "motion/3", "closed": false, "meeting_id": 1 }, "13": { "id": 13, - "sequential_number": 13, "content_object_id": "motion/4", "closed": false, "meeting_id": 1 }, "14": { "id": 14, - "sequential_number": 14, "content_object_id": "assignment/2", "closed": false, "speaker_ids": [ @@ -1088,14 +1074,12 @@ }, "15": { "id": 15, - "sequential_number": 15, "content_object_id": "motion_block/1", "closed": false, "meeting_id": 1 }, "16": { "id": 16, - "sequential_number": 16, "content_object_id": "meeting_mediafile/1", "closed": false, "meeting_id": 1 @@ -1104,7 +1088,7 @@ "speaker": { "11": { "id": 11, - "weight": 11, + "weight": 11, "begin_time": 1584512636, "end_time": 1584512638, "list_of_speakers_id": 1, @@ -1200,7 +1184,6 @@ "1": { "id": 1, "title": "A", - "sequential_number": 1, "agenda_item_id": 3, "list_of_speakers_id": 3, "meeting_id": 1 @@ -1208,7 +1191,6 @@ "2": { "id": 2, "title": "B", - "sequential_number": 2, "agenda_item_id": 4, "list_of_speakers_id": 4, "meeting_id": 1 @@ -1216,7 +1198,6 @@ "3": { "id": 3, "title": "C", - "sequential_number": 3, "agenda_item_id": 5, "list_of_speakers_id": 5, "meeting_id": 1 @@ -1224,7 +1205,6 @@ "4": { "id": 4, "title": "D", - "sequential_number": 4, "agenda_item_id": 6, "list_of_speakers_id": 6, "meeting_id": 1 @@ -1232,7 +1212,6 @@ "5": { "id": 5, "title": "E", - "sequential_number": 5, "agenda_item_id": 7, "list_of_speakers_id": 7, "meeting_id": 1 @@ -1240,7 +1219,6 @@ "6": { "id": 6, "title": "F", - "sequential_number": 6, "agenda_item_id": 8, "list_of_speakers_id": 8, "meeting_id": 1 @@ -1248,7 +1226,6 @@ "7": { "id": 7, "title": "G", - "sequential_number": 7, "agenda_item_id": 9, "list_of_speakers_id": 9, "meeting_id": 1 @@ -1256,7 +1233,6 @@ "8": { "id": 8, "title": "H", - "sequential_number": 8, "agenda_item_id": 10, "list_of_speakers_id": 10, "meeting_id": 1 @@ -1267,7 +1243,6 @@ "id": 1, "number": "A1", "number_value": 1, - "sequential_number": 1, "title": "test", "text": "
    \n
  • Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque
  • \n
  • penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat ma
  • \n
  • ssa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, vene
    \n
    \nnatis vitae, justo. Null
    \nam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibu
  • \n
  • s in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem.Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut
  • \n
", "modified_final_version": "

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi.Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae, eleifend ac, enim. Aliquam lorem ante, dapibus in, viverra quis, feugiat a, tellus. Phasellus viverra nulla ut metus varius laoreet. Quisque rutrum. Aenean imperdiet. Etiam ultricies nisi vel augue. Curabitur ullamcorper ultricies nisi. Nam eget dui. Etiam rhoncus. Maecenas tempus, tellus eget condimentum rhoncus, sem quam semper libero, sit amet adipiscing sem neque sed ipsum. Nam quam nunc, blandit vel, luctus pulvinar, hendrerit id, lorem.Maecenas nec odio et ante tincidunt tempus. Donec vitae sapien ut libero venenatis faucibus. Nullam quis ante. Etiam sit amet orci eget eros faucibus tincidunt. Duis leo. Sed fringilla mauris sit amet nibh. Donec sodales sagittis magna. Sed consequat, leo eget bibendum sodales, augue velit cursus nunc, quis gravida magna mi a libero. Fusce vulputate eleifend sapien. Vestibulum purus quam, scelerisque ut, mollis sed, nonummy id, metus. Nullam accumsan lorem in dui. Cras ultricies mi eu turpis hendrerit fringilla. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; In ac dui quis mi consectetuer lacinia. Nam pretium turpis et arcu. Duis arcu tortor, suscipit eget, imperdiet nec, imperdiet iaculis, ipsum. Sed aliquam ultrices mauris. Integer ante arcu, accumsan a, consectetuer eget, posuere ut, mauris. Praesent adipiscing. Phasellus ullamcorper ipsum rutrum nunc. Nunc nonummy metus. Vestibulum volutpat pretium libero. Cras id dui. Aenean ut

", @@ -1304,7 +1279,6 @@ "id": 2, "number": "1 - 1", "number_value": 1, - "sequential_number": 2, "title": "\u00c4nderungsantrag zu 1", "text": "

lömk

", "text_hash": "0339e76557663e3a6f03b9e347409f97", @@ -1335,7 +1309,6 @@ "id": 3, "number": "2", "number_value": 2, - "sequential_number": 3, "title": "ohne", "text": "

sf

", "text_hash": "60d31eb37595dd44584be5ef363283e3", @@ -1367,7 +1340,6 @@ "id": 4, "number": "3", "number_value": 3, - "sequential_number": 4, "title": "komplex", "text": "

sdf sdfpdfkw wef

\n\n

wepkf 

\n\n

weüpfk 

\n\n

weüpfdfg

", "text_hash": "af905e34b34d2b08b60c6af41153f078", @@ -1436,7 +1408,6 @@ "id": 1, "name": "Neu", "weight": 10000, - "sequential_number": 1, "comment_ids": [ 1 ], @@ -1458,7 +1429,6 @@ "prefix": "C", "weight": 2, "level": 0, - "sequential_number": 1, "child_ids": [ 2 ], @@ -1473,7 +1443,6 @@ "prefix": "B", "weight": 4, "level": 1, - "sequential_number": 2, "parent_id": 1, "motion_ids": [ 1, @@ -1486,7 +1455,6 @@ "1": { "id": 1, "title": "BLOCK A", - "sequential_number": 1, "motion_ids": [ 3, 4 @@ -1646,7 +1614,7 @@ "allow_support": false, "set_workflow_timestamp": true, "allow_motion_forwarding": true, - "allow_amendment_forwarding": true, + "allow_amendment_forwarding": true, "meeting_id": 1 }, "6": { @@ -1900,7 +1868,6 @@ "1": { "id": 1, "name": "Simple Workflow", - "sequential_number": 1, "state_ids": [ 1, 2, @@ -1915,7 +1882,6 @@ "2": { "id": 2, "name": "Complex Workflow", - "sequential_number": 2, "state_ids": [ 5, 6, @@ -1948,7 +1914,6 @@ "votesvalid": "2.000000", "votesinvalid": "9.000000", "votescast": "2.000000", - "sequential_number": 1, "content_object_id": "motion/1", "option_ids": [ 1 @@ -1971,7 +1936,6 @@ "max_votes_amount": 1, "max_votes_per_option": 1, "onehundred_percent_base": "YNA", - "sequential_number": 2, "content_object_id": "motion/1", "option_ids": [ 3 @@ -1997,7 +1961,6 @@ "global_no": true, "global_abstain": true, "onehundred_percent_base": "YNA", - "sequential_number": 3, "content_object_id": "assignment/1", "option_ids": [ 5 @@ -2023,7 +1986,6 @@ "votesvalid": "9.000000", "votesinvalid": "2.000000", "votescast": "16.000000", - "sequential_number": 4, "content_object_id": "assignment/1", "option_ids": [ 7, @@ -2051,7 +2013,6 @@ "votesvalid": "1.000000", "votesinvalid": "0.000000", "votescast": "1.000000", - "sequential_number": 5, "content_object_id": "assignment/2", "voted_ids": [ 1 @@ -2298,7 +2259,6 @@ "title": "Wahl", "open_posts": 1, "phase": "voting", - "sequential_number": 1, "candidate_ids": [ 1, 2, @@ -2322,7 +2282,6 @@ "open_posts": 1, "phase": "search", "number_poll_candidates": true, - "sequential_number": 2, "candidate_ids": [ 4, 5 @@ -2426,7 +2385,6 @@ "show_title": true, "show_logo": true, "show_clock": true, - "sequential_number": 1, "current_projection_ids": [ 3, 4 @@ -2472,7 +2430,6 @@ "show_title": true, "show_logo": true, "show_clock": true, - "sequential_number": 2, "used_as_default_projector_for_list_of_speakers_in_meeting_id": 1, "used_as_default_projector_for_current_los_in_meeting_id": 1, "meeting_id": 1 diff --git a/openslides_backend/action/actions/assignment/create_update_delete.py b/openslides_backend/action/actions/assignment/create_update_delete.py index 0938dc43a..b58431c4d 100644 --- a/openslides_backend/action/actions/assignment/create_update_delete.py +++ b/openslides_backend/action/actions/assignment/create_update_delete.py @@ -8,7 +8,6 @@ from ...action_set import ActionSet from ...generics.update import UpdateAction from ...mixins.create_action_with_dependencies import CreateActionWithDependencies -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action_set from ..agenda_item.agenda_creation import ( @@ -26,7 +25,6 @@ class AssignmentCreate( AttachmentMixin, - SequentialNumbersMixin, CreateActionWithDependencies, CreateActionWithAgendaItemMixin, CreateActionWithListOfSpeakersMixin, diff --git a/openslides_backend/action/actions/motion/base_create_forwarded.py b/openslides_backend/action/actions/motion/base_create_forwarded.py index a1cb94a5c..5261423d6 100644 --- a/openslides_backend/action/actions/motion/base_create_forwarded.py +++ b/openslides_backend/action/actions/motion/base_create_forwarded.py @@ -197,6 +197,7 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: else: name = committee.get("name", f"Committee {committee['id']}") instance["additional_submitter"] = name + self.handle_number(instance) self.set_origin_ids(instance) self.set_text_hash(instance) diff --git a/openslides_backend/action/actions/motion_block/create_update_delete.py b/openslides_backend/action/actions/motion_block/create_update_delete.py index f3883d01d..19f62e954 100644 --- a/openslides_backend/action/actions/motion_block/create_update_delete.py +++ b/openslides_backend/action/actions/motion_block/create_update_delete.py @@ -2,7 +2,6 @@ from ....permissions.permissions import Permissions from ...action_set import ActionSet from ...mixins.create_action_with_dependencies import CreateActionWithDependencies -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action_set from ..agenda_item.agenda_creation import ( @@ -17,7 +16,6 @@ class MotionBlockCreate( - SequentialNumbersMixin, CreateActionWithDependencies, CreateActionWithAgendaItemMixin, CreateActionWithListOfSpeakersMixin, diff --git a/openslides_backend/action/actions/motion_category/create_update_delete.py b/openslides_backend/action/actions/motion_category/create_update_delete.py index bfaf6ad16..b76386461 100644 --- a/openslides_backend/action/actions/motion_category/create_update_delete.py +++ b/openslides_backend/action/actions/motion_category/create_update_delete.py @@ -3,13 +3,13 @@ from ....models.models import MotionCategory from ....permissions.permissions import Permissions from ...action_set import ActionSet -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin +from ...generics.create import CreateAction from ...mixins.weight_mixin import WeightMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action_set -class MotionCategoryCreate(SequentialNumbersMixin, WeightMixin): +class MotionCategoryCreate(CreateAction, WeightMixin): def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: instance["weight"] = self.get_weight(instance["meeting_id"]) return super().update_instance(instance) diff --git a/openslides_backend/action/actions/motion_comment_section/create.py b/openslides_backend/action/actions/motion_comment_section/create.py index b65827552..d38aaf8fe 100644 --- a/openslides_backend/action/actions/motion_comment_section/create.py +++ b/openslides_backend/action/actions/motion_comment_section/create.py @@ -4,15 +4,12 @@ from ....permissions.permissions import Permissions from ...generics.create import CreateAction from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action @register_action("motion_comment_section.create") -class MotionCommentSectionCreateAction( - SequentialNumbersMixin, CreateAction, ForbidAnonymousGroupMixin -): +class MotionCommentSectionCreateAction(CreateAction, ForbidAnonymousGroupMixin): """ Create Action with default weight. """ diff --git a/openslides_backend/action/actions/motion_workflow/create.py b/openslides_backend/action/actions/motion_workflow/create.py index 35cdf8697..55c18bb4b 100644 --- a/openslides_backend/action/actions/motion_workflow/create.py +++ b/openslides_backend/action/actions/motion_workflow/create.py @@ -6,7 +6,6 @@ from ...action import Action from ...generics.create import CreateAction from ...mixins.create_action_with_dependencies import CreateActionWithDependencies -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin from ...util.action_type import ActionType from ...util.default_schema import DefaultSchema from ...util.register import register_action @@ -17,7 +16,7 @@ @register_action("motion_workflow.create") -class MotionWorkflowCreateAction(SequentialNumbersMixin, CreateActionWithDependencies): +class MotionWorkflowCreateAction(CreateActionWithDependencies): """ Action to create a motion workflow. """ @@ -44,7 +43,7 @@ def get_dependent_action_data( @register_action( "motion_workflow.create_simple_workflow", action_type=ActionType.BACKEND_INTERNAL ) -class MotionWorkflowCreateSimpleWorkflowAction(SequentialNumbersMixin, CreateAction): +class MotionWorkflowCreateSimpleWorkflowAction(CreateAction): """ Action to create a simple motion workflow. """ @@ -114,7 +113,7 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: @register_action( "motion_workflow.create_complex_workflow", action_type=ActionType.BACKEND_INTERNAL ) -class MotionWorkflowCreateComplexWorkflowAction(SequentialNumbersMixin, CreateAction): +class MotionWorkflowCreateComplexWorkflowAction(CreateAction): """ Action to create a complex motion workflow. """ diff --git a/openslides_backend/action/actions/motion_workflow/import_.py b/openslides_backend/action/actions/motion_workflow/import_.py index a245bfc6c..50047ab5f 100644 --- a/openslides_backend/action/actions/motion_workflow/import_.py +++ b/openslides_backend/action/actions/motion_workflow/import_.py @@ -5,7 +5,7 @@ from ....permissions.permissions import Permissions from ....shared.exceptions import ActionException from ....shared.schema import str_list_schema -from ...mixins.sequential_numbers_mixin import SequentialNumbersMixin +from ...generics.create import CreateAction from ...util.default_schema import DefaultSchema from ...util.register import register_action from ..motion_state.create import MotionStateCreateAction @@ -13,7 +13,7 @@ @register_action("motion_workflow.import") -class MotionWorkflowImport(SequentialNumbersMixin): +class MotionWorkflowImport(CreateAction): """ Action to import a motion workflow. """ diff --git a/openslides_backend/action/mixins/sequential_numbers_mixin.py b/openslides_backend/action/mixins/sequential_numbers_mixin.py deleted file mode 100644 index a612e2302..000000000 --- a/openslides_backend/action/mixins/sequential_numbers_mixin.py +++ /dev/null @@ -1,42 +0,0 @@ -from typing import Any - -from ...models.models import Model -from ...services.database.interface import Database -from ...shared.filters import FilterOperator -from ..generics.create import CreateAction -from ..util.typing import ActionResultElement - - -class SequentialNumbersMixin(CreateAction): - datastore: Database - model: Model - - def get_sequential_number(self, meeting_id: int) -> int: - """ - Creates a sequential number, unique per meeting and returns it - """ - filter = FilterOperator("meeting_id", "=", meeting_id) - - number = self.datastore.max( - collection=self.model.collection, - filter_=filter, - field="sequential_number", - ) - number = 1 if number is None else number + 1 - return number - - def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: - instance = super().update_instance(instance) - instance["sequential_number"] = self.get_sequential_number( - instance["meeting_id"] - ) - return instance - - def create_action_result_element( - self, instance: dict[str, Any] - ) -> ActionResultElement | None: - result = super().create_action_result_element(instance) - if result is None: - result = {"id": instance["id"]} - result["sequential_number"] = instance["sequential_number"] - return result diff --git a/tests/system/action/assignment/test_create.py b/tests/system/action/assignment/test_create.py index 54eabbcd7..eadb1578b 100644 --- a/tests/system/action/assignment/test_create.py +++ b/tests/system/action/assignment/test_create.py @@ -21,16 +21,19 @@ def test_create(self) -> None: "assignment.create", {"title": "test_Xcdfgee", "meeting_id": 110} ) self.assert_status_code(response, 200) - assert response.json["results"] == [[{"id": 1, "sequential_number": 1}]] - model = self.get_model("assignment/1") - assert model.get("title") == "test_Xcdfgee" - assert model.get("meeting_id") == 110 - assert model.get("open_posts") == 0 - assert model.get("phase") == "search" - assert model.get("sequential_number") == 1 - agenda_item = self.get_model("agenda_item/1") - self.assertEqual(agenda_item.get("meeting_id"), 110) - self.assertEqual(agenda_item.get("content_object_id"), "assignment/1") + self.assert_model_exists( + "assignment/1", + { + "title": "test_Xcdfgee", + "meeting_id": 110, + "open_posts": 0, + "phase": "search", + "sequential_number": 1, + }, + ) + self.assert_model_exists( + "agenda_item/1", {"meeting_id": 110, "content_object_id": "assignment/1"} + ) self.assert_model_exists( "list_of_speakers/1", {"content_object_id": "assignment/1", "closed": True} ) @@ -41,12 +44,12 @@ def test_create_other_agenda_item_check(self) -> None: "assignment.create", {"title": "test_Xcdfgee", "meeting_id": 110} ) self.assert_status_code(response, 200) - model = self.get_model("assignment/1") - assert model.get("title") == "test_Xcdfgee" - assert model.get("meeting_id") == 110 - agenda_item = self.get_model("agenda_item/1") - self.assertEqual(agenda_item.get("meeting_id"), 110) - self.assertEqual(agenda_item.get("content_object_id"), "assignment/1") + self.assert_model_exists( + "assignment/1", {"title": "test_Xcdfgee", "meeting_id": 110} + ) + self.assert_model_exists( + "agenda_item/1", {"meeting_id": 110, "content_object_id": "assignment/1"} + ) def test_create_other_agenda_item_check_2(self) -> None: self.set_models({"meeting/110": {"agenda_item_creation": "default_no"}}) @@ -54,9 +57,9 @@ def test_create_other_agenda_item_check_2(self) -> None: "assignment.create", {"title": "test_Xcdfgee", "meeting_id": 110} ) self.assert_status_code(response, 200) - model = self.get_model("assignment/1") - assert model.get("title") == "test_Xcdfgee" - assert model.get("meeting_id") == 110 + self.assert_model_exists( + "assignment/1", {"title": "test_Xcdfgee", "meeting_id": 110} + ) self.assert_model_not_exists("agenda_item/1") def test_create_other_agenda_item_check_3(self) -> None: @@ -70,9 +73,9 @@ def test_create_other_agenda_item_check_3(self) -> None: }, ) self.assert_status_code(response, 200) - model = self.get_model("assignment/1") - assert model.get("title") == "test_Xcdfgee" - assert model.get("meeting_id") == 110 + self.assert_model_exists( + "assignment/1", {"title": "test_Xcdfgee", "meeting_id": 110} + ) self.assert_model_not_exists("agenda_item/1") def test_create_agenda_item_no_default(self) -> None: @@ -86,11 +89,10 @@ def test_create_agenda_item_no_default(self) -> None: }, ) self.assert_status_code(response, 200) - model = self.get_model("assignment/1") - assert model.get("title") == "test_Xcdfgee" - assert model.get("meeting_id") == 110 - agenda_item = self.get_model("agenda_item/1") - assert agenda_item.get("content_object_id") == "assignment/1" + self.assert_model_exists( + "assignment/1", {"title": "test_Xcdfgee", "meeting_id": 110} + ) + self.assert_model_exists("agenda_item/1", {"content_object_id": "assignment/1"}) def test_create_full_fields(self) -> None: self.create_mediafile(1, 110) diff --git a/tests/system/action/meeting/test_create.py b/tests/system/action/meeting/test_create.py index e989e428a..06038ab58 100644 --- a/tests/system/action/meeting/test_create.py +++ b/tests/system/action/meeting/test_create.py @@ -85,6 +85,7 @@ def test_create_simple_and_complex_workflow(self) -> None: "default_amendment_workflow_meeting_id": 1, "state_ids": [1, 2, 3, 4], "first_state_id": 1, + "sequential_number": 1, }, ) self.assert_model_exists( @@ -112,6 +113,7 @@ def test_create_simple_and_complex_workflow(self) -> None: "meeting_id": 1, "state_ids": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "first_state_id": 5, + "sequential_number": 2, }, ) self.assert_model_exists( @@ -152,6 +154,7 @@ def test_create_simple_and_complex_workflow(self) -> None: "name": "Default projector", "meeting_id": 1, "used_as_reference_projector_meeting_id": 1, + "sequential_number": 1, **{field: 1 for field in Meeting.reverse_default_projectors()}, }, ) diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index 88fbd8ffe..7982afc4c 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -35,10 +35,7 @@ def setUp(self) -> None: }, "group/1": {"meeting_id": 1, "name": "group1_m1"}, "projector/1": {"meeting_id": 1}, - "motion/1": { - "meeting_id": 1, - "number_value": 31, - }, + "motion/1": {"meeting_id": 1, "number_value": 31}, "gender/1": {"name": "male", "organization_id": 1}, "gender/4": {"name": "diverse", "organization_id": 1}, } @@ -270,7 +267,6 @@ def create_request_data( "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 1, } }, "motion_state": { @@ -324,7 +320,6 @@ def create_request_data( "preview_projection_ids": [], "history_projection_ids": [], **{field: 1 for field in Meeting.reverse_default_projectors()}, - "sequential_number": 1, } }, }, @@ -395,7 +390,6 @@ def get_motion_data(self, obj_id: int, data: dict[str, Any] = {}) -> dict[str, A "title": "bla", "number": "1 - 1", "number_value": 1, - "sequential_number": 2, "text": "

lömk

", "amendment_paragraphs": {}, "modified_final_version": "", @@ -535,7 +529,6 @@ def test_replace_ids_and_write_to_datastore(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], } @@ -606,7 +599,9 @@ def test_replace_ids_and_write_to_datastore(self) -> None: self.assert_model_exists( "meeting_user/2", {"meeting_id": 2, "user_id": 1, "group_ids": [2]} ) - self.assert_model_exists("projector/2", {"meeting_id": 2}) + self.assert_model_exists( + "projector/2", {"meeting_id": 2, "sequential_number": 2} + ) self.assert_model_exists("group/2", {"meeting_user_ids": [1, 2]}) self.assert_model_exists( "personal_note/1", @@ -900,7 +895,6 @@ def test_double_import(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], } @@ -991,7 +985,9 @@ def test_double_import(self) -> None: }, ) assert start <= meeting_3.get("imported_at", 0) <= start + 300 - self.assert_model_exists("projector/3", {"meeting_id": 3}) + self.assert_model_exists( + "projector/3", {"meeting_id": 3, "sequential_number": 3} + ) self.assert_model_exists( "group/4", { @@ -1163,7 +1159,6 @@ def test_motion_recommendation_extension(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], }, @@ -1172,7 +1167,6 @@ def test_motion_recommendation_extension(self) -> None: "meeting_id": 1, "content_object_id": "motion/2", "closed": False, - "sequential_number": 2, "speaker_ids": [], "projection_ids": [], }, @@ -1192,6 +1186,7 @@ def test_motion_recommendation_extension(self) -> None: "state_extension_reference_ids": ["motion/2"], "recommendation_extension": "bla[motion/2]bla", "recommendation_extension_reference_ids": ["motion/2"], + "sequential_number": 3, }, ) @@ -1404,7 +1399,6 @@ def test_motion_all_derived_motion_ids(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], } @@ -1424,6 +1418,7 @@ def test_motion_all_derived_motion_ids(self) -> None: "derived_motion_ids": None, "all_origin_ids": None, "all_derived_motion_ids": None, + "sequential_number": 2, }, ) @@ -1458,7 +1453,6 @@ def test_motion_all_origin_ids(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], }, @@ -1467,7 +1461,6 @@ def test_motion_all_origin_ids(self) -> None: "meeting_id": 1, "content_object_id": "motion/2", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], }, @@ -1479,9 +1472,13 @@ def test_motion_all_origin_ids(self) -> None: request_data["meeting"]["motion_state"]["1"]["motion_ids"] = [1, 2] response = self.request("meeting.import", request_data) self.assert_status_code(response, 200) - motion = self.assert_model_exists("motion/2", {"meeting_id": 2}) + motion = self.assert_model_exists( + "motion/2", {"meeting_id": 2, "sequential_number": 2} + ) assert motion.get("all_origin_ids") is None - motion = self.assert_model_exists("motion/3", {"meeting_id": 2}) + motion = self.assert_model_exists( + "motion/3", {"meeting_id": 2, "sequential_number": 3} + ) assert motion.get("all_derived_motion_ids") is None def test_foreign_motion_all_origin_ids(self) -> None: @@ -1504,7 +1501,6 @@ def test_foreign_motion_all_origin_ids(self) -> None: "meeting_id": 1, "content_object_id": "motion/2", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], }, @@ -1519,7 +1515,12 @@ def test_foreign_motion_all_origin_ids(self) -> None: self.assert_status_code(response, 200) self.assert_model_exists( "motion/2", - {"meeting_id": 2, "all_origin_ids": None, "origin_meeting_id": None}, + { + "meeting_id": 2, + "all_origin_ids": None, + "origin_meeting_id": None, + "sequential_number": 2, + }, ) def test_missing_required_field(self) -> None: @@ -2189,7 +2190,6 @@ def test_import_amendment_paragraphs(self) -> None: "meeting_id": 1, "content_object_id": "motion/1", "closed": False, - "sequential_number": 1, "speaker_ids": [], "projection_ids": [], } @@ -2208,7 +2208,13 @@ def test_import_amendment_paragraphs(self) -> None: self.assert_status_code(response, 200) self.assert_model_exists( "motion/2", - {"amendment_paragraphs": {"1": "<it>test</it>", "2": "broken"}}, + { + "amendment_paragraphs": { + "1": "<it>test</it>", + "2": "broken", + }, + "sequential_number": 2, + }, ) def test_import_with_wrong_decimal(self) -> None: @@ -2536,6 +2542,7 @@ def test_delete_statutes(self) -> None: "motion_workflow/1", { "default_statute_amendment_workflow_meeting_id": None, + "sequential_number": 1, }, ) diff --git a/tests/system/action/motion_workflow/test_create.py b/tests/system/action/motion_workflow/test_create.py index f980c8af7..32854dbb5 100644 --- a/tests/system/action/motion_workflow/test_create.py +++ b/tests/system/action/motion_workflow/test_create.py @@ -11,7 +11,7 @@ def test_create(self) -> None: self.assert_status_code(response, 200) self.assert_model_exists( "motion_workflow/43", - {"name": "test_Xcdfgee", "first_state_id": 43, "sequential_number": 43}, + {"name": "test_Xcdfgee", "first_state_id": 43, "sequential_number": 2}, ) self.assert_model_exists( "motion_state/43", {"workflow_id": 43, "first_state_of_workflow_id": 43} @@ -43,7 +43,8 @@ def test_create_simple_workflow(self) -> None: ) self.assert_status_code(response, 200) self.assert_model_exists( - "motion_workflow/43", {"name": "test_Xcdfgee", "first_state_id": 43} + "motion_workflow/43", + {"name": "test_Xcdfgee", "first_state_id": 43, "sequential_number": 2}, ) self.assert_model_exists( "motion_state/43", diff --git a/tests/system/action/motion_workflow/test_import.py b/tests/system/action/motion_workflow/test_import.py index 11e365963..fd351df32 100644 --- a/tests/system/action/motion_workflow/test_import.py +++ b/tests/system/action/motion_workflow/test_import.py @@ -53,7 +53,7 @@ def test_import_simple_case(self) -> None: { "name": "test_Xcdfgee", "first_state_id": 43, - "sequential_number": 43, + "sequential_number": 2, }, ) self.assert_model_exists( diff --git a/tests/system/action/projector/test_create.py b/tests/system/action/projector/test_create.py index 28d3ba995..5442956e8 100644 --- a/tests/system/action/projector/test_create.py +++ b/tests/system/action/projector/test_create.py @@ -81,7 +81,9 @@ def test_create_set_used_as_default_in_meeting_id(self) -> None: "projector/223", {"used_as_default_projector_for_topic_in_meeting_id": 222}, ) - self.assert_model_exists("meeting/222", {"default_projector_topic_ids": [223]}) + self.assert_model_exists( + "meeting/222", {"default_projector_topic_ids": [222, 223]} + ) def test_create_set_wrong_used_as_default__in_meeting_id(self) -> None: response = self.request( From 2780e30e67c75598d4271cd88b99ed1c4080919f Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 8 Oct 2025 12:22:46 +0200 Subject: [PATCH 05/19] Fix database tests --- tests/database/writer/system/test_create.py | 4 ---- tests/database/writer/system/util.py | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/tests/database/writer/system/test_create.py b/tests/database/writer/system/test_create.py index 79a8e9b1e..87c805fd0 100644 --- a/tests/database/writer/system/test_create.py +++ b/tests/database/writer/system/test_create.py @@ -121,7 +121,6 @@ def test_create_11_field_as_1n() -> None: "fields": { "title": "2", "meeting_id": 1, - "sequential_number": 1, "state_id": 1, }, }, @@ -131,7 +130,6 @@ def test_create_11_field_as_1n() -> None: "fields": { "title": "2", "meeting_id": 1, - "sequential_number": 2, "state_id": 1, }, }, @@ -141,7 +139,6 @@ def test_create_11_field_as_1n() -> None: "fields": { "content_object_id": "motion/1", "meeting_id": 1, - "sequential_number": 1, }, }, { @@ -150,7 +147,6 @@ def test_create_11_field_as_1n() -> None: "fields": { "content_object_id": "motion/2", "meeting_id": 1, - "sequential_number": 2, }, }, ] diff --git a/tests/database/writer/system/util.py b/tests/database/writer/system/util.py index abe3cdede..5350f6c8f 100644 --- a/tests/database/writer/system/util.py +++ b/tests/database/writer/system/util.py @@ -4,6 +4,7 @@ import pytest from psycopg import Cursor, rows +from openslides_backend.models.models import Meeting from openslides_backend.services.database.database_reader import ( DatabaseReader, GetManyRequest, @@ -136,8 +137,8 @@ def get_group_base_data() -> list[dict[str, Any]]: "fqid": "projector/1", "fields": { "name": "1", - "sequential_number": 1, "meeting_id": 1, + **{field: 1 for field in Meeting.reverse_default_projectors()}, }, }, { @@ -156,7 +157,6 @@ def get_group_base_data() -> list[dict[str, Any]]: "fields": { "name": "1", "meeting_id": 1, - "sequential_number": 1, "first_state_id": 1, }, }, From da1114e97c8b36eece43bb9c83bef80d175e8456 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 8 Oct 2025 17:02:56 +0200 Subject: [PATCH 06/19] Clean merged files --- tests/system/action/base.py | 2 -- .../test_delete_history_information.py | 2 -- .../system/action/user/test_merge_together.py | 18 ++++++------------ 3 files changed, 6 insertions(+), 16 deletions(-) diff --git a/tests/system/action/base.py b/tests/system/action/base.py index 38ea3753c..46892b5c2 100644 --- a/tests/system/action/base.py +++ b/tests/system/action/base.py @@ -560,7 +560,6 @@ def create_topic( { f"topic/{base}": { "title": "test", - "sequential_number": base, "meeting_id": meeting_id, **topic_data, }, @@ -570,7 +569,6 @@ def create_topic( }, f"list_of_speakers/{base}": { "content_object_id": f"topic/{base}", - "sequential_number": 1, "meeting_id": meeting_id, }, } diff --git a/tests/system/action/organization/test_delete_history_information.py b/tests/system/action/organization/test_delete_history_information.py index 28602df50..e21158de3 100644 --- a/tests/system/action/organization/test_delete_history_information.py +++ b/tests/system/action/organization/test_delete_history_information.py @@ -17,12 +17,10 @@ def test_delete_history_information_correct(self) -> None: "organization/1": {"name": "Orga", "enable_electronic_voting": True}, "assignment/1": { "title": "test_assignment_ohneivoh9caiB8Yiungo", - "sequential_number": 1, "open_posts": 1, "meeting_id": 1, }, "list_of_speakers/1": { - "sequential_number": 1, "content_object_id": "assignment/1", "meeting_id": 1, }, diff --git a/tests/system/action/user/test_merge_together.py b/tests/system/action/user/test_merge_together.py index 57c37d186..d7d8b15bc 100644 --- a/tests/system/action/user/test_merge_together.py +++ b/tests/system/action/user/test_merge_together.py @@ -237,13 +237,11 @@ def create_assignment( { f"assignment/{base}": { "title": "just do it", - "sequential_number": base, "meeting_id": meeting_id, **assignment_data, }, f"list_of_speakers/{base + 100}": { "content_object_id": f"assignment/{base}", - "sequential_number": base + 100, "meeting_id": meeting_id, }, } @@ -1886,12 +1884,10 @@ def add_list_of_speakers( "title": f"MB{base_id}", "meeting_id": meeting_id, "list_of_speakers_id": base_id, - "sequential_number": base_id, }, f"list_of_speakers/{base_id}": { "content_object_id": block_fqid, "meeting_id": meeting_id, - "sequential_number": base_id, }, f"structure_level_list_of_speakers/{base_id * 2 - 1}": { "structure_level_id": meeting_id, @@ -2198,14 +2194,12 @@ def test_with_speakers_different_sllos(self) -> None: def archive_all_meetings(self) -> None: self.set_models( { - **{ - f"meeting/{id_}": { - "is_archived_in_organization_id": ONE_ORGANIZATION_ID, - "is_active_in_organization_id": None, - } - for id_ in range(1, 11, 3) - }, - } + f"meeting/{id_}": { + "is_archived_in_organization_id": ONE_ORGANIZATION_ID, + "is_active_in_organization_id": None, + } + for id_ in range(1, 11, 3) + }, ) def test_merge_archived_with_user_fields(self) -> None: From 2edd3d3fe51207c09d59073bf0198f4fd1bcc4ff Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 9 Oct 2025 10:15:59 +0200 Subject: [PATCH 07/19] Adapt backend to meta --- tests/system/action/base_generic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/system/action/base_generic.py b/tests/system/action/base_generic.py index a21f4cc91..be77f82d5 100644 --- a/tests/system/action/base_generic.py +++ b/tests/system/action/base_generic.py @@ -54,6 +54,7 @@ def create_table_view(cls, yml: str) -> None: final_info_code, missing_handled_attributes, im_table_code, + create_trigger_partitioned_sequences_code, create_trigger_1_1_relation_not_null_code, create_trigger_relationlistnotnull_code, create_trigger_unique_ids_pair_code, From b9db8a59c4e28fdfc80e413a1d5f477e366c40df Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 9 Oct 2025 10:19:27 +0200 Subject: [PATCH 08/19] Update meta --- meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta b/meta index 8ac6804c8..31791866f 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit 8ac6804c8904619257472fd2d39c0f62577da704 +Subproject commit 31791866f02e01e75fc3f797c83df88ccba396a1 From 49dee81330e981af7ebc7989475f334abbec4c5f Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 9 Oct 2025 16:24:55 +0200 Subject: [PATCH 09/19] Test meeting_import with sequential_number --- .../action/actions/meeting/import_.py | 4 +-- tests/system/action/meeting/test_import.py | 28 ++++++++----------- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/openslides_backend/action/actions/meeting/import_.py b/openslides_backend/action/actions/meeting/import_.py index 275bce6f9..0be1820de 100644 --- a/openslides_backend/action/actions/meeting/import_.py +++ b/openslides_backend/action/actions/meeting/import_.py @@ -1,7 +1,7 @@ import re -import time from collections import defaultdict from collections.abc import Iterable +from datetime import datetime from typing import Any from openslides_backend.action.actions.meeting.mixins import MeetingPermissionMixin @@ -407,7 +407,7 @@ def update_meeting_and_users(self, instance: dict[str, Any]) -> None: meeting["enable_anonymous"] = False # set imported_at - meeting["imported_at"] = round(time.time()) + meeting["imported_at"] = datetime.now() def get_meeting_from_json(self, json_data: Any) -> Any: """ diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index 7982afc4c..ab9eb9219 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -19,23 +19,10 @@ class MeetingImport(BaseActionTestCase): def setUp(self) -> None: super().setUp() + self.create_meeting(1, {"external_id": "ext_id"}) + self.create_motion(1, 1, motion_data={"number_value": 31}) self.set_models( { - ONE_ORGANIZATION_FQID: { - "active_meeting_ids": [1], - "committee_ids": [1], - "gender_ids": [1, 4], - }, - "committee/1": {"organization_id": 1, "meeting_ids": [1]}, - "meeting/1": { - "committee_id": 1, - "group_ids": [1], - "external_id": "ext_id", - "is_active_in_organization_id": ONE_ORGANIZATION_ID, - }, - "group/1": {"meeting_id": 1, "name": "group1_m1"}, - "projector/1": {"meeting_id": 1}, - "motion/1": {"meeting_id": 1, "number_value": 31}, "gender/1": {"name": "male", "organization_id": 1}, "gender/4": {"name": "diverse", "organization_id": 1}, } @@ -267,6 +254,7 @@ def create_request_data( "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], + "sequential_number": 42, } }, "motion_state": { @@ -320,6 +308,7 @@ def create_request_data( "preview_projection_ids": [], "history_projection_ids": [], **{field: 1 for field in Meeting.reverse_default_projectors()}, + "sequential_number": 63, } }, }, @@ -623,8 +612,13 @@ def test_check_calc_fields(self) -> None: response = self.request("meeting.import", request_data) self.assert_status_code(response, 200) self.assert_model_exists("user/2", {"meeting_ids": [2]}) - meeting2 = self.assert_model_exists("meeting/2") - self.assertCountEqual(meeting2["user_ids"], [1, 2]) + self.assert_model_exists("meeting/2", {"user_ids": [1, 2]}) + self.assert_model_exists( + "projector/2", {"meeting_id": 2, "sequential_number": 1} + ) + self.assert_model_exists( + "motion_workflow/2", {"meeting_id": 2, "sequential_number": 1} + ) def test_check_usernames_1(self) -> None: request_data = self.create_request_data( From d34429356c998a6c6163ad884d772f4364e3be22 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 9 Oct 2025 16:27:46 +0200 Subject: [PATCH 10/19] Fix committee_id in test data --- tests/system/action/meeting/test_import.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index ab9eb9219..f730a4c42 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -32,7 +32,7 @@ def create_request_data( self, datapart: dict[str, Any] | None = None ) -> dict[str, Any]: data: dict[str, Any] = { - "committee_id": 1, + "committee_id": 60, "meeting": { "meeting": { "1": { From c617b969754d320caaf88faf31bf287c0153d46d Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 9 Oct 2025 16:35:09 +0200 Subject: [PATCH 11/19] Remove sequential_numbers from shared test data --- tests/system/action/meeting/test_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index f730a4c42..0efe69582 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -254,7 +254,6 @@ def create_request_data( "default_amendment_workflow_meeting_id": 1, "default_workflow_meeting_id": 1, "state_ids": [1], - "sequential_number": 42, } }, "motion_state": { @@ -308,7 +307,6 @@ def create_request_data( "preview_projection_ids": [], "history_projection_ids": [], **{field: 1 for field in Meeting.reverse_default_projectors()}, - "sequential_number": 63, } }, }, @@ -609,6 +607,8 @@ def test_replace_ids_and_write_to_datastore(self) -> None: def test_check_calc_fields(self) -> None: request_data = self.create_request_data({}) + request_data["meeting"]["motion_workflow"]["1"]["sequential_number"] = 42 + request_data["meeting"]["projector"]["1"]["sequential_number"] = 63 response = self.request("meeting.import", request_data) self.assert_status_code(response, 200) self.assert_model_exists("user/2", {"meeting_ids": [2]}) From 615f6ca730ddd2f2c284ceeb730d31d141f9b98d Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Tue, 28 Oct 2025 16:06:22 +0100 Subject: [PATCH 12/19] Update sequential_number test --- meta | 2 +- tests/system/action/meeting/test_import.py | 43 ++++++++++++++++++++-- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/meta b/meta index 31791866f..6a3e6dc4f 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit 31791866f02e01e75fc3f797c83df88ccba396a1 +Subproject commit 6a3e6dc4f96e21210df36389c66bb19c8038fdcb diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index 0efe69582..c47676767 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -607,17 +607,54 @@ def test_replace_ids_and_write_to_datastore(self) -> None: def test_check_calc_fields(self) -> None: request_data = self.create_request_data({}) - request_data["meeting"]["motion_workflow"]["1"]["sequential_number"] = 42 + for field in ["motion_workflow_ids", "motion_state_ids"]: + request_data["meeting"]["meeting"]["1"][field] = [1, 2, 3] + for id_ in range(2, 4): + request_data["meeting"]["motion_state"][str(id_)] = { + "id": id_, + "meeting_id": 1, + "name": f"state{id_}", + "weight": 1, + "workflow_id": id_, + "first_state_of_workflow_id": id_, + } + + # sequential_number is given request_data["meeting"]["projector"]["1"]["sequential_number"] = 63 + request_data["meeting"]["motion_workflow"]["1"]["sequential_number"] = 42 + # sequential_number is not given + request_data["meeting"]["motion_workflow"]["2"] = { + "id": 2, + "meeting_id": 1, + "name": "workflow2", + "first_state_id": 2, + "state_ids": [2], + "sequential_number": 41, + } + # sequential_number is smaller than max_sequential_number + request_data["meeting"]["motion_workflow"]["3"] = { + "id": 3, + "meeting_id": 1, + "name": "workflow3", + "first_state_id": 3, + "state_ids": [3], + } + response = self.request("meeting.import", request_data) self.assert_status_code(response, 200) self.assert_model_exists("user/2", {"meeting_ids": [2]}) self.assert_model_exists("meeting/2", {"user_ids": [1, 2]}) self.assert_model_exists( - "projector/2", {"meeting_id": 2, "sequential_number": 1} + "projector/2", {"meeting_id": 2, "sequential_number": 63} + ) + self.assert_model_exists( + "motion_workflow/2", {"meeting_id": 2, "sequential_number": 42} + ) + self.assert_model_exists( + "motion_workflow/3", {"meeting_id": 2, "sequential_number": 41} ) self.assert_model_exists( - "motion_workflow/2", {"meeting_id": 2, "sequential_number": 1} + "motion_workflow/4", {"meeting_id": 2, "sequential_number": 43} ) def test_check_usernames_1(self) -> None: From d0dac8b545fd4d934d7ff984654334cc04d618b8 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Tue, 28 Oct 2025 16:31:13 +0100 Subject: [PATCH 13/19] Fix comments --- tests/system/action/meeting/test_import.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index c47676767..3fb3ff84b 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -622,7 +622,7 @@ def test_check_calc_fields(self) -> None: # sequential_number is given request_data["meeting"]["projector"]["1"]["sequential_number"] = 63 request_data["meeting"]["motion_workflow"]["1"]["sequential_number"] = 42 - # sequential_number is not given + # sequential_number is smaller than max_sequential_number request_data["meeting"]["motion_workflow"]["2"] = { "id": 2, "meeting_id": 1, @@ -631,7 +631,7 @@ def test_check_calc_fields(self) -> None: "state_ids": [2], "sequential_number": 41, } - # sequential_number is smaller than max_sequential_number + # sequential_number is not given request_data["meeting"]["motion_workflow"]["3"] = { "id": 3, "meeting_id": 1, From dcdec4e4200f61e43a2d2dee98b28e0aea0ccc69 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 29 Oct 2025 12:03:06 +0100 Subject: [PATCH 14/19] Update meta hash --- meta | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meta b/meta index 6a3e6dc4f..54491cca1 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit 6a3e6dc4f96e21210df36389c66bb19c8038fdcb +Subproject commit 54491cca156071401f742e40bc71fc1e89975dcc From b91faa0e1cc07bdb8562dfcc9e2fa5715e2243d4 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 29 Oct 2025 14:22:45 +0100 Subject: [PATCH 15/19] Regenerate models and lint --- openslides_backend/action/actions/__init__.py | 3 +- .../action/actions/option/__init__.py | 1 - .../action/actions/option/create.py | 96 --------- .../action/actions/option/delete.py | 38 ---- .../action/actions/option/set_auto_fields.py | 28 --- .../action/actions/option/update.py | 185 ---------------- .../action/actions/poll/create.py | 74 +++---- .../action/actions/poll/mixins.py | 26 +-- .../action/actions/poll/reset.py | 24 +-- openslides_backend/models/models.py | 201 +++++------------- tests/system/action/meeting/test_import.py | 6 +- 11 files changed, 113 insertions(+), 569 deletions(-) delete mode 100644 openslides_backend/action/actions/option/__init__.py delete mode 100644 openslides_backend/action/actions/option/create.py delete mode 100644 openslides_backend/action/actions/option/delete.py delete mode 100644 openslides_backend/action/actions/option/set_auto_fields.py delete mode 100644 openslides_backend/action/actions/option/update.py diff --git a/openslides_backend/action/actions/__init__.py b/openslides_backend/action/actions/__init__.py index 98bf12457..ff6b28356 100644 --- a/openslides_backend/action/actions/__init__.py +++ b/openslides_backend/action/actions/__init__.py @@ -5,7 +5,7 @@ def prepare_actions_map() -> None: New modules have to be added here. """ - from . import ( # noqa + from . import ( # noqa; option, agenda_item, assignment, assignment_candidate, @@ -30,7 +30,6 @@ def prepare_actions_map() -> None: motion_submitter, motion_workflow, motion_working_group_speaker, - option, organization, organization_tag, personal_note, diff --git a/openslides_backend/action/actions/option/__init__.py b/openslides_backend/action/actions/option/__init__.py deleted file mode 100644 index a27b3acfe..000000000 --- a/openslides_backend/action/actions/option/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import create, delete, set_auto_fields, update # noqa diff --git a/openslides_backend/action/actions/option/create.py b/openslides_backend/action/actions/option/create.py deleted file mode 100644 index 854f75768..000000000 --- a/openslides_backend/action/actions/option/create.py +++ /dev/null @@ -1,96 +0,0 @@ -from typing import Any - -from openslides_backend.shared.schema import id_list_schema - -from ....models.models import Option -from ....shared.exceptions import ActionException -from ...generics.create import CreateAction -from ...util.action_type import ActionType -from ...util.default_schema import DefaultSchema -from ...util.register import register_action -from ..poll_candidate_list.create import PollCandidateListCreate -from ..vote.create import VoteCreate -from ..vote.user_token_helper import get_user_token - - -@register_action("option.create", action_type=ActionType.BACKEND_INTERNAL) -class OptionCreateAction(CreateAction): - """ - (internal) Action to create an option - """ - - model = Option() - schema = DefaultSchema(Option()).get_create_schema( - required_properties=["meeting_id"], - optional_properties=[ - "text", - "poll_id", - "used_as_global_option_in_poll_id", - "content_object_id", - "yes", - "no", - "abstain", - "weight", - ], - additional_optional_fields={"poll_candidate_user_ids": id_list_schema}, - ) - - def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: - keyword = self.check_one_of_three_keywords(instance) - action_data = [] - user_token = get_user_token() - yes_data = self.get_vote_action_data(instance, "Y", "yes", user_token) - if yes_data is not None: - action_data.append(yes_data) - no_data = self.get_vote_action_data(instance, "N", "no", user_token) - if no_data is not None: - action_data.append(no_data) - abstain_data = self.get_vote_action_data(instance, "A", "abstain", user_token) - if abstain_data is not None: - action_data.append(abstain_data) - if action_data: - self.apply_instance(instance) - self.execute_other_action(VoteCreate, action_data) - if keyword == "poll_candidate_user_ids": - self.apply_instance(instance) - user_ids = instance.pop("poll_candidate_user_ids") - self.execute_other_action( - PollCandidateListCreate, - [ - { - "option_id": instance["id"], - "meeting_id": instance["meeting_id"], - "entries": [ - {"user_id": user_id, "weight": i} - for i, user_id in enumerate(user_ids, start=1) - ], - } - ], - ) - - return instance - - def get_vote_action_data( - self, instance: dict[str, Any], value: str, prop: str, user_token: str - ) -> dict[str, Any] | None: - if instance.get(prop): - return { - "value": value, - "weight": instance[prop], - "option_id": instance["id"], - "user_token": user_token, - } - return None - - @staticmethod - def check_one_of_three_keywords(instance: dict[str, Any]) -> str: - keys = [ - key - for key in ("text", "content_object_id", "poll_candidate_user_ids") - if key in instance - ] - if len(keys) != 1: - raise ActionException( - "Need one of text, content_object_id or poll_candidate_user_ids." - ) - return keys[0] diff --git a/openslides_backend/action/actions/option/delete.py b/openslides_backend/action/actions/option/delete.py deleted file mode 100644 index b2bc679e6..000000000 --- a/openslides_backend/action/actions/option/delete.py +++ /dev/null @@ -1,38 +0,0 @@ -from typing import Any - -from ....models.models import Option -from ....shared.patterns import ( - collection_from_fqid, - fqid_from_collection_and_id, - id_from_fqid, -) -from ...generics.delete import DeleteAction -from ...util.action_type import ActionType -from ...util.default_schema import DefaultSchema -from ...util.register import register_action -from ..poll_candidate_list.delete import PollCandidateListDelete - - -@register_action("option.delete", action_type=ActionType.BACKEND_INTERNAL) -class OptionDelete(DeleteAction): - """ - Action to delete options. - """ - - model = Option() - schema = DefaultSchema(Option()).get_delete_schema() - - def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: - option = self.datastore.get( - fqid_from_collection_and_id("option", instance["id"]), ["content_object_id"] - ) - if ( - option.get("content_object_id") - and collection_from_fqid(option["content_object_id"]) - == "poll_candidate_list" - ): - self.execute_other_action( - PollCandidateListDelete, - [{"id": id_from_fqid(option["content_object_id"])}], - ) - return instance diff --git a/openslides_backend/action/actions/option/set_auto_fields.py b/openslides_backend/action/actions/option/set_auto_fields.py deleted file mode 100644 index f297d50e7..000000000 --- a/openslides_backend/action/actions/option/set_auto_fields.py +++ /dev/null @@ -1,28 +0,0 @@ -from typing import Any - -from ....models.models import Option -from ...generics.update import UpdateAction -from ...util.action_type import ActionType -from ...util.default_schema import DefaultSchema -from ...util.register import register_action - - -@register_action("option.set_auto_fields", action_type=ActionType.BACKEND_INTERNAL) -class OptionSetAutoFields(UpdateAction): - """ - Action to calculate auto fields for options (yes, no, abstain) - """ - - model = Option() - schema = DefaultSchema(Option()).get_update_schema( - optional_properties=["yes", "no", "abstain"] - ) - - def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: - set_without_calc = ( - instance.get("yes") or instance.get("no") or instance.get("abstain") - ) - if not set_without_calc: - # TODO in this case we should autogenerate the fields. - raise NotImplementedError() - return instance diff --git a/openslides_backend/action/actions/option/update.py b/openslides_backend/action/actions/option/update.py deleted file mode 100644 index 9c1225d8d..000000000 --- a/openslides_backend/action/actions/option/update.py +++ /dev/null @@ -1,185 +0,0 @@ -from typing import Any - -from ....models.models import Option, Poll -from ....services.database.commands import GetManyRequest -from ....shared.exceptions import ActionException -from ....shared.patterns import fqid_from_collection_and_id -from ....shared.schema import decimal_schema -from ...generics.update import UpdateAction -from ...util.default_schema import DefaultSchema -from ...util.register import register_action -from ..poll.functions import check_poll_or_option_perms -from ..poll.set_state import PollSetState -from ..vote.create import VoteCreate -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): - """ - Action to update an option. - """ - - model = Option() - schema = DefaultSchema(Option()).get_update_schema( - additional_optional_fields={ - "Y": decimal_schema, - "N": decimal_schema, - "A": decimal_schema, - "publish_immediately": {"type": "boolean"}, - } - ) - - def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: - """Update votes and auto calculate yes, no, abstain.""" - - option, poll = self._get_option_and_poll(instance["id"]) - state_change = self.check_state_change(instance, poll) - - 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 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": letter, - "weight": instance[option_key], - "user_token": user_token, - } - ) - else: - action_data_update.append( - {"id": vote_id, "weight": instance[option_key]} - ) - if action_data_create: - self.execute_other_action(VoteCreate, action_data_create) - if action_data_update: - self.execute_other_action(VoteUpdate, action_data_update) - - execute_other_action = False - if state_change: - state = Poll.STATE_FINISHED - execute_other_action = True - if ( - execute_other_action - or ( - poll["state"] == Poll.STATE_FINISHED - and poll["type"] == Poll.TYPE_ANALOG - ) - ) and instance.get("publish_immediately"): - state = Poll.STATE_PUBLISHED - execute_other_action = True - if execute_other_action: - self.execute_other_action( - PollSetState, [{"id": poll["id"], "state": state}] - ) - - instance.pop("publish_immediately", None) - return instance - - def _get_option_and_poll( - self, option_id: int - ) -> tuple[dict[str, Any], dict[str, Any]]: - option = self.datastore.get( - fqid_from_collection_and_id(self.model.collection, option_id), - ["poll_id", "used_as_global_option_in_poll_id", "vote_ids", "meeting_id"], - ) - return ( - option, - self.datastore.get( - fqid_from_collection_and_id("poll", option["poll_id"]), - [ - "id", - "state", - "type", - "pollmethod", - "global_yes", - "global_no", - "global_abstain", - "meeting_id", - "content_object_id", - ], - lock_result=["type"], - ), - ) - - def _handle_poll_option_data( - self, instance: dict[str, Any], poll: dict[str, Any] - ) -> None: - if poll.get("type") == "analog": - data = self._get_data(instance) - pollmethod = poll["pollmethod"] - for letter, key in option_keys_map.items(): - if letter in pollmethod: - instance[key] = data.get(key, "-2.000000") - elif data.get(key) is not None: - 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: - if poll.get("type") == "analog": - data = self._get_data(instance) - 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]: - 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("vote", vote_ids, ["value"]) - gm_result = self.datastore.get_many([get_many_request]) - votes = gm_result.get("vote", {}) - return votes - - def _get_vote_id( - self, search_value: str, id_to_vote: dict[int, dict[str, Any]] - ) -> int | None: - for key, item in id_to_vote.items(): - if item["value"] == search_value: - return key - return None - - def check_state_change( - self, instance: dict[str, Any], poll: dict[str, Any] - ) -> bool: - 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_option_and_poll(instance["id"]) - content_object_id = poll.get("content_object_id", "") - meeting_id = poll["meeting_id"] - check_poll_or_option_perms( - content_object_id, self.datastore, self.user_id, meeting_id - ) diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index 2d43b990d..9ce7e58ab 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -10,7 +10,7 @@ from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action -from ..option.create import OptionCreateAction +# from ..option.create import OptionCreateAction from .base import base_check_onehundred_percent_base from .mixins import PollHistoryMixin, PollPermissionMixin, PollValidationMixin @@ -132,38 +132,38 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: if not state.get("allow_create_poll"): raise ActionException("Motion state doesn't allow to create poll.") - # handle non-global options - unique_set = set() - - for weight, option in enumerate(instance.get("options", []), start=1): - # check the keys with staticmethod from option.create, where they belong - key = OptionCreateAction.check_one_of_three_keywords(option) - data: dict[str, Any] = { - "poll_id": instance["id"], - "meeting_id": instance["meeting_id"], - "weight": weight, - key: option[key], - } - - o_obj = f"{key},{option[key]}" - if o_obj in unique_set: - raise ActionException( - f"Duplicated option in poll.options: {option[key]}" - ) - else: - unique_set.add(o_obj) - - if instance["type"] == "analog": - if instance["pollmethod"] == "N": - data["no"] = self.parse_vote_value(option, "N") - else: - data["yes"] = self.parse_vote_value(option, "Y") - if instance["pollmethod"] in ("YN", "YNA"): - data["no"] = self.parse_vote_value(option, "N") - if instance["pollmethod"] == "YNA": - data["abstain"] = self.parse_vote_value(option, "A") - - action_data.append(data) + # # handle non-global options + # unique_set = set() + + # for weight, option in enumerate(instance.get("options", []), start=1): + # # check the keys with staticmethod from option.create, where they belong + # key = OptionCreateAction.check_one_of_three_keywords(option) + # data: dict[str, Any] = { + # "poll_id": instance["id"], + # "meeting_id": instance["meeting_id"], + # "weight": weight, + # key: option[key], + # } + + # o_obj = f"{key},{option[key]}" + # if o_obj in unique_set: + # raise ActionException( + # f"Duplicated option in poll.options: {option[key]}" + # ) + # else: + # unique_set.add(o_obj) + + # if instance["type"] == "analog": + # if instance["pollmethod"] == "N": + # data["no"] = self.parse_vote_value(option, "N") + # else: + # data["yes"] = self.parse_vote_value(option, "Y") + # if instance["pollmethod"] in ("YN", "YNA"): + # data["no"] = self.parse_vote_value(option, "N") + # if instance["pollmethod"] == "YNA": + # data["abstain"] = self.parse_vote_value(option, "A") + + # action_data.append(data) # handle global option global_data = { @@ -183,10 +183,10 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: # Execute the create option actions self.apply_instance(instance) - self.execute_other_action( - OptionCreateAction, - action_data, - ) + # self.execute_other_action( + # OptionCreateAction, + # action_data, + # ) # set state instance["state"] = Poll.STATE_CREATED diff --git a/openslides_backend/action/actions/poll/mixins.py b/openslides_backend/action/actions/poll/mixins.py index e4ffdf0fa..0f7b8f918 100644 --- a/openslides_backend/action/actions/poll/mixins.py +++ b/openslides_backend/action/actions/poll/mixins.py @@ -13,7 +13,7 @@ fqid_from_collection_and_id, ) from ...action import Action -from ..option.set_auto_fields import OptionSetAutoFields +# from ..option.set_auto_fields import OptionSetAutoFields from ..projector_countdown.mixins import CountdownCommand, CountdownControl from ..vote.create import VoteCreate from ..vote.user_token_helper import get_user_token @@ -180,18 +180,18 @@ def on_stop(self, instance: dict[str, Any]) -> None: raise VoteServiceException("Invalid response from vote service") self.execute_other_action(VoteCreate, action_data) # update results into option - self.execute_other_action( - OptionSetAutoFields, - [ - { - "id": _id, - "yes": str(option["Y"]), - "no": str(option["N"]), - "abstain": str(option["A"]), - } - for _id, option in option_results.items() - ], - ) + # self.execute_other_action( + # OptionSetAutoFields, + # [ + # { + # "id": _id, + # "yes": str(option["Y"]), + # "no": str(option["N"]), + # "abstain": str(option["A"]), + # } + # for _id, option in option_results.items() + # ], + # ) # set voted ids voted_ids = results["user_ids"] instance["voted_ids"] = voted_ids diff --git a/openslides_backend/action/actions/poll/reset.py b/openslides_backend/action/actions/poll/reset.py index 3a7120975..ea91f2657 100644 --- a/openslides_backend/action/actions/poll/reset.py +++ b/openslides_backend/action/actions/poll/reset.py @@ -10,7 +10,7 @@ from ...util.default_schema import DefaultSchema from ...util.register import register_action from ...util.typing import ActionData -from ..option.set_auto_fields import OptionSetAutoFields +# from ..option.set_auto_fields import OptionSetAutoFields from ..vote.delete import VoteDelete from .mixins import PollHistoryMixin, PollPermissionMixin @@ -92,7 +92,7 @@ def delete_all_votes(self, poll_id: int) -> None: option = options[option_id] if option.get("vote_ids"): self._delete_votes(option["vote_ids"]) - self._clear_option_auto_fields(option_id) + # self._clear_option_auto_fields(option_id) def _get_option_ids(self, poll_id: int) -> list[int]: poll = self.datastore.get( @@ -119,16 +119,16 @@ def _delete_votes(self, vote_ids: list[int]) -> None: action_data.append({"id": id_}) self.execute_other_action(VoteDelete, action_data) - def _clear_option_auto_fields(self, option_id: int) -> None: - action_data = [ - { - "id": option_id, - "yes": "0.000000", - "no": "0.000000", - "abstain": "0.000000", - } - ] - self.execute_other_action(OptionSetAutoFields, action_data) + # def _clear_option_auto_fields(self, option_id: int) -> None: + # action_data = [ + # { + # "id": option_id, + # "yes": "0.000000", + # "no": "0.000000", + # "abstain": "0.000000", + # } + # ] + # self.execute_other_action(OptionSetAutoFields, action_data) def get_on_success(self, action_data: ActionData) -> Callable[[], None]: def on_success() -> None: diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index e773d80f5..b66e26bd7 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -46,11 +46,6 @@ class Organization(Model): saml_metadata_idp = fields.TextField() saml_metadata_sp = fields.TextField() saml_private_key = fields.TextField() - vote_decrypt_public_main_key = fields.CharField( - constraints={ - "description": "Public key from vote decrypt to validate cryptographic votes." - } - ) committee_ids = fields.RelationListField( to={"committee": "organization_id"}, is_view_field=True, is_primary=True ) @@ -162,12 +157,11 @@ class User(Model): is_view_field=True, write_fields=("nm_poll_voted_ids_user_t", "user_id", "poll_id", []), ) - option_ids = fields.RelationListField( - to={"option": "content_object_id"}, is_view_field=True + acting_vote_ids = fields.RelationListField( + to={"vote": "acting_user_id"}, is_view_field=True ) - vote_ids = fields.RelationListField(to={"vote": "user_id"}, is_view_field=True) - delegated_vote_ids = fields.RelationListField( - to={"vote": "delegated_user_id"}, is_view_field=True + represented_vote_ids = fields.RelationListField( + to={"vote": "represented_user_id"}, is_view_field=True ) poll_candidate_ids = fields.RelationListField( to={"poll_candidate": "user_id"}, is_view_field=True @@ -828,13 +822,22 @@ class Meeting(Model, MeetingModelMixin): poll_default_group_ids = fields.RelationListField( to={"group": "used_as_poll_default_id"}, is_view_field=True ) - poll_default_backend = fields.CharField( - default="fast", constraints={"enum": ["long", "fast"]} - ) poll_default_live_voting_enabled = fields.BooleanField( default=False, constraints={ - "description": "Defines default 'poll.live_voting_enabled' option suggested to user. Is not used in the validations." + "description": "Defines default 'poll.published' before finished option suggested to user. Is not used in the validations." + }, + ) + poll_default_allow_invalid = fields.BooleanField( + default=False, + constraints={ + "description": "Defines defaut `poll.allow_invalid` option suggested to user." + }, + ) + poll_default_allow_vote_split = fields.BooleanField( + default=False, + constraints={ + "description": "Defines defaut `poll.allow_vote_split` option suggested to user." }, ) poll_couple_countdown = fields.BooleanField(default=True) @@ -972,14 +975,6 @@ class Meeting(Model, MeetingModelMixin): poll_ids = fields.RelationListField( to={"poll": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True ) - option_ids = fields.RelationListField( - to={"option": "meeting_id"}, - on_delete=fields.OnDelete.CASCADE, - is_view_field=True, - ) - vote_ids = fields.RelationListField( - to={"vote": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True - ) assignment_ids = fields.RelationListField( to={"assignment": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, @@ -1921,12 +1916,6 @@ class Motion(Model): is_view_field=True, equal_fields="meeting_id", ) - option_ids = fields.RelationListField( - to={"option": "content_object_id"}, - on_delete=fields.OnDelete.CASCADE, - is_view_field=True, - equal_fields="meeting_id", - ) change_recommendation_ids = fields.RelationListField( to={"motion_change_recommendation": "motion_id"}, on_delete=fields.OnDelete.CASCADE, @@ -2366,60 +2355,41 @@ class Poll(Model, PollModelMixin): verbose_name = "poll" id = fields.IntegerField(required=True, constant=True) - description = fields.TextField() title = fields.CharField(required=True) - type = fields.CharField( + method = fields.CharField( required=True, - constraints={"enum": ["analog", "named", "pseudoanonymous", "cryptographic"]}, + constraints={ + "enum": ["approval", "selection", "rating-score", "rating-approval"] + }, ) - backend = fields.CharField( - required=True, default="fast", constraints={"enum": ["long", "fast"]} + config = fields.TextField( + constraints={ + "description": "Values to configure the poll. Depends on the value in poll/method." + } ) - is_pseudoanonymized = fields.BooleanField() - pollmethod = fields.CharField( - required=True, constraints={"enum": ["Y", "YN", "YNA", "N"]} + visibility = fields.CharField( + required=True, constraints={"enum": ["manually", "named", "open", "secret"]} ) state = fields.CharField( - default="created", - constraints={"enum": ["created", "started", "finished", "published"]}, - ) - min_votes_amount = fields.IntegerField(default=1, constraints={"minimum": 1}) - max_votes_amount = fields.IntegerField(default=1, constraints={"minimum": 1}) - max_votes_per_option = fields.IntegerField(default=1, constraints={"minimum": 1}) - global_yes = fields.BooleanField(default=False) - global_no = fields.BooleanField(default=False) - global_abstain = fields.BooleanField(default=False) - onehundred_percent_base = fields.CharField( - required=True, - default="disabled", + default="created", constraints={"enum": ["created", "started", "finished"]} + ) + result = fields.TextField( constraints={ - "enum": [ - "Y", - "YN", - "YNA", - "N", - "valid", - "cast", - "entitled", - "entitled_present", - "disabled", - ] - }, + "description": "Calculated result. The format depends on the value in poll/method. Can be manually set when visibility is set to manually." + } ) - votesvalid = fields.DecimalField() - votesinvalid = fields.DecimalField() - votescast = fields.DecimalField() - entitled_users_at_stop = fields.JSONField() - live_voting_enabled = fields.BooleanField( + published = fields.BooleanField( + default=False, constraints={"description": "If true, users can see the result."} + ) + allow_invalid = fields.BooleanField( default=False, constraints={ - "description": "If true, the vote service sends the votes of the users to the autoupdate service." + "description": "If true, the vote service does not validate. This is always the case for secret polls." }, ) - live_votes = fields.JSONField( - constraints={ - "description": "dict from user to their vote. The value is null, when live voting is disabled." - } + allow_vote_split = fields.BooleanField( + default=False, + constraints={"description": "If true, users can split there vote."}, ) sequential_number = fields.IntegerField( required=True, @@ -2430,39 +2400,18 @@ class Poll(Model, PollModelMixin): "description": "The (positive) serial number of this model in its meeting. This number is auto-generated and read-only.", }, ) - crypt_key = fields.CharField( - read_only=True, - constraints={"description": "base64 public key to cryptographic votes."}, - ) - crypt_signature = fields.CharField( - read_only=True, - constraints={"description": "base64 signature of cryptographic_key."}, - ) - votes_raw = fields.TextField( - read_only=True, constraints={"description": "original form of decrypted votes."} - ) - votes_signature = fields.CharField( - read_only=True, - constraints={"description": "base64 signature of votes_raw field."}, - ) content_object_id = fields.GenericRelationField( to={"motion": "poll_ids", "assignment": "poll_ids", "topic": "poll_ids"}, required=True, constant=True, equal_fields="meeting_id", ) - option_ids = fields.RelationListField( - to={"option": "poll_id"}, + vote_ids = fields.RelationListField( + to={"vote": "poll_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True, equal_fields="meeting_id", ) - global_option_id = fields.RelationField( - to={"option": "used_as_global_option_in_poll_id"}, - on_delete=fields.OnDelete.CASCADE, - constant=True, - equal_fields="meeting_id", - ) voted_ids = fields.RelationListField( to={"user": "poll_voted_ids"}, is_view_field=True, @@ -2486,64 +2435,19 @@ class Poll(Model, PollModelMixin): ) -class Option(Model): - collection = "option" - verbose_name = "option" - - id = fields.IntegerField(required=True, constant=True) - weight = fields.IntegerField(default=10000) - text = fields.HTMLStrictField() - yes = fields.DecimalField() - no = fields.DecimalField() - abstain = fields.DecimalField() - poll_id = fields.RelationField( - to={"poll": "option_ids"}, constant=True, equal_fields="meeting_id" - ) - used_as_global_option_in_poll_id = fields.RelationField( - to={"poll": "global_option_id"}, - is_view_field=True, - constant=True, - equal_fields="meeting_id", - ) - vote_ids = fields.RelationListField( - to={"vote": "option_id"}, - on_delete=fields.OnDelete.CASCADE, - is_view_field=True, - equal_fields="meeting_id", - ) - content_object_id = fields.GenericRelationField( - to={ - "poll_candidate_list": "option_id", - "user": "option_ids", - "motion": "option_ids", - }, - constant=True, - equal_fields="meeting_id", - ) - meeting_id = fields.RelationField( - to={"meeting": "option_ids"}, required=True, constant=True - ) - - class Vote(Model): collection = "vote" verbose_name = "vote" id = fields.IntegerField(required=True, constant=True) - weight = fields.DecimalField(constant=True) - value = fields.CharField(constant=True) - user_token = fields.CharField(required=True, constant=True) - option_id = fields.RelationField( - to={"option": "vote_ids"}, - required=True, - constant=True, - equal_fields="meeting_id", - ) - user_id = fields.RelationField(to={"user": "vote_ids"}) - delegated_user_id = fields.RelationField(to={"user": "delegated_vote_ids"}) - meeting_id = fields.RelationField( - to={"meeting": "vote_ids"}, required=True, constant=True + weight = fields.DecimalField(constant=True, default="1.000000") + split = fields.BooleanField(default=False) + value = fields.TextField(constant=True) + poll_id = fields.RelationField( + to={"poll": "vote_ids"}, required=True, constant=True, equal_fields="meeting_id" ) + acting_user_id = fields.RelationField(to={"user": "acting_vote_ids"}) + represented_user_id = fields.RelationField(to={"user": "represented_vote_ids"}) class Assignment(Model): @@ -2664,13 +2568,6 @@ class PollCandidateList(Model): meeting_id = fields.RelationField( to={"meeting": "poll_candidate_list_ids"}, required=True, constant=True ) - option_id = fields.RelationField( - to={"option": "content_object_id"}, - is_view_field=True, - required=True, - constant=True, - equal_fields="meeting_id", - ) class PollCandidate(Model): diff --git a/tests/system/action/meeting/test_import.py b/tests/system/action/meeting/test_import.py index 3fb3ff84b..e051605fd 100644 --- a/tests/system/action/meeting/test_import.py +++ b/tests/system/action/meeting/test_import.py @@ -6,11 +6,7 @@ from openslides_backend.action.action_worker import ActionWorkerState from openslides_backend.models.models import Meeting -from openslides_backend.shared.util import ( - ONE_ORGANIZATION_FQID, - ONE_ORGANIZATION_ID, - get_initial_data_file, -) +from openslides_backend.shared.util import ONE_ORGANIZATION_FQID, get_initial_data_file from tests.system.action.base import BaseActionTestCase from tests.system.util import Profiler, performance From 14b20db9f724068f4fe29de37769a9b7649e6417 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 29 Oct 2025 14:29:41 +0100 Subject: [PATCH 16/19] Lint --- openslides_backend/action/actions/poll/create.py | 1 + openslides_backend/action/actions/poll/mixins.py | 1 + openslides_backend/action/actions/poll/reset.py | 1 + 3 files changed, 3 insertions(+) diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index 9ce7e58ab..1b57711a1 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -10,6 +10,7 @@ from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action + # from ..option.create import OptionCreateAction from .base import base_check_onehundred_percent_base from .mixins import PollHistoryMixin, PollPermissionMixin, PollValidationMixin diff --git a/openslides_backend/action/actions/poll/mixins.py b/openslides_backend/action/actions/poll/mixins.py index 0f7b8f918..52a888216 100644 --- a/openslides_backend/action/actions/poll/mixins.py +++ b/openslides_backend/action/actions/poll/mixins.py @@ -13,6 +13,7 @@ fqid_from_collection_and_id, ) from ...action import Action + # from ..option.set_auto_fields import OptionSetAutoFields from ..projector_countdown.mixins import CountdownCommand, CountdownControl from ..vote.create import VoteCreate diff --git a/openslides_backend/action/actions/poll/reset.py b/openslides_backend/action/actions/poll/reset.py index ea91f2657..1ad111c9d 100644 --- a/openslides_backend/action/actions/poll/reset.py +++ b/openslides_backend/action/actions/poll/reset.py @@ -10,6 +10,7 @@ from ...util.default_schema import DefaultSchema from ...util.register import register_action from ...util.typing import ActionData + # from ..option.set_auto_fields import OptionSetAutoFields from ..vote.delete import VoteDelete from .mixins import PollHistoryMixin, PollPermissionMixin From bbf0a87f06c5f4bd93e1384fc8e9fb4e97544e65 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Wed, 29 Oct 2025 14:34:25 +0100 Subject: [PATCH 17/19] Lint --- openslides_backend/action/actions/poll/create.py | 2 -- openslides_backend/action/actions/poll/mixins.py | 2 -- openslides_backend/action/actions/poll/reset.py | 2 -- 3 files changed, 6 deletions(-) diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index 1b57711a1..19a481796 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -10,8 +10,6 @@ from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action - -# from ..option.create import OptionCreateAction from .base import base_check_onehundred_percent_base from .mixins import PollHistoryMixin, PollPermissionMixin, PollValidationMixin diff --git a/openslides_backend/action/actions/poll/mixins.py b/openslides_backend/action/actions/poll/mixins.py index 52a888216..418c616e8 100644 --- a/openslides_backend/action/actions/poll/mixins.py +++ b/openslides_backend/action/actions/poll/mixins.py @@ -13,8 +13,6 @@ fqid_from_collection_and_id, ) from ...action import Action - -# from ..option.set_auto_fields import OptionSetAutoFields from ..projector_countdown.mixins import CountdownCommand, CountdownControl from ..vote.create import VoteCreate from ..vote.user_token_helper import get_user_token diff --git a/openslides_backend/action/actions/poll/reset.py b/openslides_backend/action/actions/poll/reset.py index 1ad111c9d..b9bb3e8e7 100644 --- a/openslides_backend/action/actions/poll/reset.py +++ b/openslides_backend/action/actions/poll/reset.py @@ -10,8 +10,6 @@ from ...util.default_schema import DefaultSchema from ...util.register import register_action from ...util.typing import ActionData - -# from ..option.set_auto_fields import OptionSetAutoFields from ..vote.delete import VoteDelete from .mixins import PollHistoryMixin, PollPermissionMixin From 6ff24d6bc74e72f46f65d9bccd313a4546df389e Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Mon, 10 Nov 2025 14:05:21 +0100 Subject: [PATCH 18/19] Minor fixes --- docs/actions/poll.create.md | 1 - docs/actions/poll.update.md | 1 - .../action/actions/poll/create.py | 1 - .../action/actions/poll/update.py | 1 - openslides_backend/models/models.py | 215 ++++++++++++------ tests/system/action/option/test_update.py | 3 +- 6 files changed, 150 insertions(+), 72 deletions(-) diff --git a/docs/actions/poll.create.md b/docs/actions/poll.create.md index 3af4954a4..8cbcfc772 100644 --- a/docs/actions/poll.create.md +++ b/docs/actions/poll.create.md @@ -28,7 +28,6 @@ Payload: // Optional content_object_id: Fqid, - description: string, min_votes_amount: number, max_votes_amount: number, max_votes_per_option: number, diff --git a/docs/actions/poll.update.md b/docs/actions/poll.update.md index ffed841fd..c2b0abb5a 100644 --- a/docs/actions/poll.update.md +++ b/docs/actions/poll.update.md @@ -19,7 +19,6 @@ // Optional, every state title: string, - description: string, onehundred_percent_base: string, // Optional, type==analog, every state diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index 19a481796..875e6e87b 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -52,7 +52,6 @@ class PollCreateAction( }, optional_properties=[ "content_object_id", - "description", "min_votes_amount", "max_votes_amount", "max_votes_per_option", diff --git a/openslides_backend/action/actions/poll/update.py b/openslides_backend/action/actions/poll/update.py index c8603aea5..abcd7fef0 100644 --- a/openslides_backend/action/actions/poll/update.py +++ b/openslides_backend/action/actions/poll/update.py @@ -43,7 +43,6 @@ class PollUpdateAction( "global_abstain", "entitled_group_ids", "title", - "description", "onehundred_percent_base", "votesvalid", "votesinvalid", diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index b66e26bd7..9991b62e9 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -157,14 +157,17 @@ class User(Model): is_view_field=True, write_fields=("nm_poll_voted_ids_user_t", "user_id", "poll_id", []), ) - acting_vote_ids = fields.RelationListField( - to={"vote": "acting_user_id"}, is_view_field=True + option_ids = fields.RelationListField( + to={"option": "content_object_id"}, is_view_field=True, is_primary=True ) - represented_vote_ids = fields.RelationListField( - to={"vote": "represented_user_id"}, is_view_field=True + vote_ids = fields.RelationListField( + to={"vote": "user_id"}, is_view_field=True, is_primary=True + ) + delegated_vote_ids = fields.RelationListField( + to={"vote": "delegated_user_id"}, is_view_field=True, is_primary=True ) poll_candidate_ids = fields.RelationListField( - to={"poll_candidate": "user_id"}, is_view_field=True + to={"poll_candidate": "user_id"}, is_view_field=True, is_primary=True ) home_committee_id = fields.RelationField(to={"committee": "native_user_ids"}) history_position_ids = fields.RelationListField( @@ -225,19 +228,16 @@ class MeetingUser(Model): ) motion_editor_ids = fields.RelationListField( to={"motion_editor": "meeting_user_id"}, - on_delete=fields.OnDelete.CASCADE, is_view_field=True, equal_fields="meeting_id", ) motion_working_group_speaker_ids = fields.RelationListField( to={"motion_working_group_speaker": "meeting_user_id"}, - on_delete=fields.OnDelete.CASCADE, is_view_field=True, equal_fields="meeting_id", ) motion_submitter_ids = fields.RelationListField( to={"motion_submitter": "meeting_user_id"}, - on_delete=fields.OnDelete.CASCADE, is_view_field=True, equal_fields="meeting_id", ) @@ -494,9 +494,7 @@ class Meeting(Model, MeetingModelMixin): to={"organization": "archived_meeting_ids"}, constraints={"description": "Backrelation and boolean flag at once"}, ) - description = fields.CharField( - default="Presentation and assembly system", constraints={"maxLength": 100} - ) + description = fields.CharField(constraints={"maxLength": 100}) location = fields.CharField() start_time = fields.TimestampField() end_time = fields.TimestampField() @@ -673,6 +671,8 @@ class Meeting(Model, MeetingModelMixin): motions_export_preamble = fields.TextField() motions_export_submitter_recommendation = fields.BooleanField(default=True) motions_export_follow_recommendation = fields.BooleanField(default=False) + motions_enable_restricted_editor_for_manager = fields.BooleanField() + motions_enable_restricted_editor_for_non_manager = fields.BooleanField() motion_poll_ballot_paper_selection = fields.CharField( default="CUSTOM_NUMBER", constraints={ @@ -715,10 +715,10 @@ class Meeting(Model, MeetingModelMixin): ) motion_poll_projection_max_columns = fields.IntegerField(required=True, default=6) poll_candidate_list_ids = fields.RelationListField( - to={"poll_candidate_list": "meeting_id"}, is_view_field=True + to={"poll_candidate_list": "meeting_id"}, is_view_field=True, is_primary=True ) poll_candidate_ids = fields.RelationListField( - to={"poll_candidate": "meeting_id"}, is_view_field=True + to={"poll_candidate": "meeting_id"}, is_view_field=True, is_primary=True ) meeting_user_ids = fields.RelationListField( to={"meeting_user": "meeting_id"}, @@ -822,22 +822,13 @@ class Meeting(Model, MeetingModelMixin): poll_default_group_ids = fields.RelationListField( to={"group": "used_as_poll_default_id"}, is_view_field=True ) - poll_default_live_voting_enabled = fields.BooleanField( - default=False, - constraints={ - "description": "Defines default 'poll.published' before finished option suggested to user. Is not used in the validations." - }, - ) - poll_default_allow_invalid = fields.BooleanField( - default=False, - constraints={ - "description": "Defines defaut `poll.allow_invalid` option suggested to user." - }, + poll_default_backend = fields.CharField( + default="fast", constraints={"enum": ["long", "fast"]} ) - poll_default_allow_vote_split = fields.BooleanField( + poll_default_live_voting_enabled = fields.BooleanField( default=False, constraints={ - "description": "Defines defaut `poll.allow_vote_split` option suggested to user." + "description": "Defines default 'poll.live_voting_enabled' option suggested to user. Is not used in the validations." }, ) poll_couple_countdown = fields.BooleanField(default=True) @@ -973,7 +964,22 @@ class Meeting(Model, MeetingModelMixin): is_view_field=True, ) poll_ids = fields.RelationListField( - to={"poll": "meeting_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True + to={"poll": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + is_primary=True, + ) + option_ids = fields.RelationListField( + to={"option": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + is_primary=True, + ) + vote_ids = fields.RelationListField( + to={"vote": "meeting_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + is_primary=True, ) assignment_ids = fields.RelationListField( to={"assignment": "meeting_id"}, @@ -1916,6 +1922,13 @@ class Motion(Model): is_view_field=True, equal_fields="meeting_id", ) + option_ids = fields.RelationListField( + to={"option": "content_object_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + is_primary=True, + equal_fields="meeting_id", + ) change_recommendation_ids = fields.RelationListField( to={"motion_change_recommendation": "motion_id"}, on_delete=fields.OnDelete.CASCADE, @@ -1985,9 +1998,7 @@ class MotionSubmitter(Model): id = fields.IntegerField(required=True, constant=True) weight = fields.IntegerField() - meeting_user_id = fields.RelationField( - to={"meeting_user": "motion_submitter_ids"}, required=True - ) + meeting_user_id = fields.RelationField(to={"meeting_user": "motion_submitter_ids"}) motion_id = fields.RelationField( to={"motion": "submitter_ids"}, required=True, @@ -2005,9 +2016,7 @@ class MotionEditor(Model): id = fields.IntegerField(required=True, constant=True) weight = fields.IntegerField() - meeting_user_id = fields.RelationField( - to={"meeting_user": "motion_editor_ids"}, required=True - ) + meeting_user_id = fields.RelationField(to={"meeting_user": "motion_editor_ids"}) motion_id = fields.RelationField( to={"motion": "editor_ids"}, required=True, @@ -2026,7 +2035,7 @@ class MotionWorkingGroupSpeaker(Model): id = fields.IntegerField(required=True, constant=True) weight = fields.IntegerField() meeting_user_id = fields.RelationField( - to={"meeting_user": "motion_working_group_speaker_ids"}, required=True + to={"meeting_user": "motion_working_group_speaker_ids"} ) motion_id = fields.RelationField( to={"motion": "working_group_speaker_ids"}, @@ -2256,6 +2265,7 @@ class MotionState(Model): allow_motion_forwarding = fields.BooleanField(default=False) allow_amendment_forwarding = fields.BooleanField() set_workflow_timestamp = fields.BooleanField(default=False) + state_button_label = fields.CharField() submitter_withdraw_state_id = fields.RelationField( to={"motion_state": "submitter_withdraw_back_ids"}, equal_fields=["meeting_id", "workflow_id"], @@ -2356,41 +2366,54 @@ class Poll(Model, PollModelMixin): id = fields.IntegerField(required=True, constant=True) title = fields.CharField(required=True) - method = fields.CharField( + type = fields.CharField( required=True, - constraints={ - "enum": ["approval", "selection", "rating-score", "rating-approval"] - }, + constraints={"enum": ["analog", "named", "pseudoanonymous", "cryptographic"]}, ) - config = fields.TextField( - constraints={ - "description": "Values to configure the poll. Depends on the value in poll/method." - } + backend = fields.CharField( + required=True, default="fast", constraints={"enum": ["long", "fast"]} ) - visibility = fields.CharField( - required=True, constraints={"enum": ["manually", "named", "open", "secret"]} + is_pseudoanonymized = fields.BooleanField() + pollmethod = fields.CharField( + required=True, constraints={"enum": ["Y", "YN", "YNA", "N"]} ) state = fields.CharField( - default="created", constraints={"enum": ["created", "started", "finished"]} - ) - result = fields.TextField( + default="created", + constraints={"enum": ["created", "started", "finished", "published"]}, + ) + min_votes_amount = fields.IntegerField(default=1, constraints={"minimum": 1}) + max_votes_amount = fields.IntegerField(default=1, constraints={"minimum": 1}) + max_votes_per_option = fields.IntegerField(default=1, constraints={"minimum": 1}) + global_yes = fields.BooleanField(default=False) + global_no = fields.BooleanField(default=False) + global_abstain = fields.BooleanField(default=False) + onehundred_percent_base = fields.CharField( + required=True, + default="disabled", constraints={ - "description": "Calculated result. The format depends on the value in poll/method. Can be manually set when visibility is set to manually." - } - ) - published = fields.BooleanField( - default=False, constraints={"description": "If true, users can see the result."} + "enum": [ + "Y", + "YN", + "YNA", + "N", + "valid", + "cast", + "entitled", + "entitled_present", + "disabled", + ] + }, ) - allow_invalid = fields.BooleanField( + votesvalid = fields.DecimalField() + votesinvalid = fields.DecimalField() + votescast = fields.DecimalField() + entitled_users_at_stop = fields.JSONField() + live_voting_enabled = fields.BooleanField( default=False, constraints={ - "description": "If true, the vote service does not validate. This is always the case for secret polls." + "description": "If true, the vote service sends the votes of the users to the autoupdate service." }, ) - allow_vote_split = fields.BooleanField( - default=False, - constraints={"description": "If true, users can split there vote."}, - ) sequential_number = fields.IntegerField( required=True, read_only=True, @@ -2406,10 +2429,17 @@ class Poll(Model, PollModelMixin): constant=True, equal_fields="meeting_id", ) - vote_ids = fields.RelationListField( - to={"vote": "poll_id"}, + option_ids = fields.RelationListField( + to={"option": "poll_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True, + is_primary=True, + equal_fields="meeting_id", + ) + global_option_id = fields.RelationField( + to={"option": "used_as_global_option_in_poll_id"}, + on_delete=fields.OnDelete.CASCADE, + constant=True, equal_fields="meeting_id", ) voted_ids = fields.RelationListField( @@ -2435,19 +2465,62 @@ class Poll(Model, PollModelMixin): ) +class Option(Model): + collection = "option" + verbose_name = "option" + + id = fields.IntegerField(required=True, constant=True) + weight = fields.IntegerField(default=10000) + text = fields.HTMLStrictField() + yes = fields.DecimalField() + no = fields.DecimalField() + abstain = fields.DecimalField() + poll_id = fields.RelationField( + to={"poll": "option_ids"}, constant=True, equal_fields="meeting_id" + ) + used_as_global_option_in_poll_id = fields.RelationField( + to={"poll": "global_option_id"}, constant=True, equal_fields="meeting_id" + ) + vote_ids = fields.RelationListField( + to={"vote": "option_id"}, + on_delete=fields.OnDelete.CASCADE, + is_view_field=True, + is_primary=True, + equal_fields="meeting_id", + ) + content_object_id = fields.GenericRelationField( + to={ + "poll_candidate_list": "option_id", + "user": "option_ids", + "motion": "option_ids", + }, + constant=True, + equal_fields="meeting_id", + ) + meeting_id = fields.RelationField( + to={"meeting": "option_ids"}, required=True, constant=True + ) + + class Vote(Model): collection = "vote" verbose_name = "vote" id = fields.IntegerField(required=True, constant=True) - weight = fields.DecimalField(constant=True, default="1.000000") - split = fields.BooleanField(default=False) - value = fields.TextField(constant=True) - poll_id = fields.RelationField( - to={"poll": "vote_ids"}, required=True, constant=True, equal_fields="meeting_id" + weight = fields.DecimalField(constant=True) + value = fields.CharField(constant=True) + user_token = fields.CharField(required=True, constant=True) + option_id = fields.RelationField( + to={"option": "vote_ids"}, + required=True, + constant=True, + equal_fields="meeting_id", + ) + user_id = fields.RelationField(to={"user": "vote_ids"}) + delegated_user_id = fields.RelationField(to={"user": "delegated_vote_ids"}) + meeting_id = fields.RelationField( + to={"meeting": "vote_ids"}, required=True, constant=True ) - acting_user_id = fields.RelationField(to={"user": "acting_vote_ids"}) - represented_user_id = fields.RelationField(to={"user": "represented_vote_ids"}) class Assignment(Model): @@ -2563,11 +2636,19 @@ class PollCandidateList(Model): to={"poll_candidate": "poll_candidate_list_id"}, on_delete=fields.OnDelete.CASCADE, is_view_field=True, + is_primary=True, equal_fields="meeting_id", ) meeting_id = fields.RelationField( to={"meeting": "poll_candidate_list_ids"}, required=True, constant=True ) + option_id = fields.RelationField( + to={"option": "content_object_id"}, + is_view_field=True, + required=True, + constant=True, + equal_fields="meeting_id", + ) class PollCandidate(Model): diff --git a/tests/system/action/option/test_update.py b/tests/system/action/option/test_update.py index 3be91d940..2afff49ec 100644 --- a/tests/system/action/option/test_update.py +++ b/tests/system/action/option/test_update.py @@ -160,6 +160,7 @@ def test_update_global_option(self) -> None: "global_no": True, "global_abstain": True, }, + "option/57": {"used_as_global_option_in_poll_id": 65}, } ) response = self.request( @@ -177,7 +178,7 @@ def test_update_global_option(self) -> None: ) def test_update_global_option_invalid(self) -> None: - self.set_models({"poll/65": {"global_option_id": 57}}) + self.set_models({"option/57": {"used_as_global_option_in_poll_id": 65}}) response = self.request( "option.update", {"id": 57, "Y": "1.000000"}, From ae6c693ffb8579b51176d496804f3c1a214889b8 Mon Sep 17 00:00:00 2001 From: vkrasnovyd Date: Thu, 13 Nov 2025 11:10:09 +0100 Subject: [PATCH 19/19] Update meta, revert vote changes --- docs/actions/poll.create.md | 1 + docs/actions/poll.update.md | 1 + meta | 2 +- openslides_backend/action/actions/__init__.py | 3 +- .../action/actions/option/__init__.py | 1 + .../action/actions/option/create.py | 96 +++++++++ .../action/actions/option/delete.py | 38 ++++ .../action/actions/option/set_auto_fields.py | 28 +++ .../action/actions/option/update.py | 185 ++++++++++++++++++ .../action/actions/poll/create.py | 74 +++---- .../action/actions/poll/mixins.py | 25 +-- .../action/actions/poll/reset.py | 23 +-- .../action/actions/poll/update.py | 1 + openslides_backend/models/models.py | 2 +- 14 files changed, 418 insertions(+), 62 deletions(-) create mode 100644 openslides_backend/action/actions/option/__init__.py create mode 100644 openslides_backend/action/actions/option/create.py create mode 100644 openslides_backend/action/actions/option/delete.py create mode 100644 openslides_backend/action/actions/option/set_auto_fields.py create mode 100644 openslides_backend/action/actions/option/update.py diff --git a/docs/actions/poll.create.md b/docs/actions/poll.create.md index 8cbcfc772..3af4954a4 100644 --- a/docs/actions/poll.create.md +++ b/docs/actions/poll.create.md @@ -28,6 +28,7 @@ Payload: // Optional content_object_id: Fqid, + description: string, min_votes_amount: number, max_votes_amount: number, max_votes_per_option: number, diff --git a/docs/actions/poll.update.md b/docs/actions/poll.update.md index c2b0abb5a..ffed841fd 100644 --- a/docs/actions/poll.update.md +++ b/docs/actions/poll.update.md @@ -19,6 +19,7 @@ // Optional, every state title: string, + description: string, onehundred_percent_base: string, // Optional, type==analog, every state diff --git a/meta b/meta index 54491cca1..0d0c67022 160000 --- a/meta +++ b/meta @@ -1 +1 @@ -Subproject commit 54491cca156071401f742e40bc71fc1e89975dcc +Subproject commit 0d0c670221f1aa28694df50741ab65670bf6d61b diff --git a/openslides_backend/action/actions/__init__.py b/openslides_backend/action/actions/__init__.py index ff6b28356..98bf12457 100644 --- a/openslides_backend/action/actions/__init__.py +++ b/openslides_backend/action/actions/__init__.py @@ -5,7 +5,7 @@ def prepare_actions_map() -> None: New modules have to be added here. """ - from . import ( # noqa; option, + from . import ( # noqa agenda_item, assignment, assignment_candidate, @@ -30,6 +30,7 @@ def prepare_actions_map() -> None: motion_submitter, motion_workflow, motion_working_group_speaker, + option, organization, organization_tag, personal_note, diff --git a/openslides_backend/action/actions/option/__init__.py b/openslides_backend/action/actions/option/__init__.py new file mode 100644 index 000000000..a27b3acfe --- /dev/null +++ b/openslides_backend/action/actions/option/__init__.py @@ -0,0 +1 @@ +from . import create, delete, set_auto_fields, update # noqa diff --git a/openslides_backend/action/actions/option/create.py b/openslides_backend/action/actions/option/create.py new file mode 100644 index 000000000..854f75768 --- /dev/null +++ b/openslides_backend/action/actions/option/create.py @@ -0,0 +1,96 @@ +from typing import Any + +from openslides_backend.shared.schema import id_list_schema + +from ....models.models import Option +from ....shared.exceptions import ActionException +from ...generics.create import CreateAction +from ...util.action_type import ActionType +from ...util.default_schema import DefaultSchema +from ...util.register import register_action +from ..poll_candidate_list.create import PollCandidateListCreate +from ..vote.create import VoteCreate +from ..vote.user_token_helper import get_user_token + + +@register_action("option.create", action_type=ActionType.BACKEND_INTERNAL) +class OptionCreateAction(CreateAction): + """ + (internal) Action to create an option + """ + + model = Option() + schema = DefaultSchema(Option()).get_create_schema( + required_properties=["meeting_id"], + optional_properties=[ + "text", + "poll_id", + "used_as_global_option_in_poll_id", + "content_object_id", + "yes", + "no", + "abstain", + "weight", + ], + additional_optional_fields={"poll_candidate_user_ids": id_list_schema}, + ) + + def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: + keyword = self.check_one_of_three_keywords(instance) + action_data = [] + user_token = get_user_token() + yes_data = self.get_vote_action_data(instance, "Y", "yes", user_token) + if yes_data is not None: + action_data.append(yes_data) + no_data = self.get_vote_action_data(instance, "N", "no", user_token) + if no_data is not None: + action_data.append(no_data) + abstain_data = self.get_vote_action_data(instance, "A", "abstain", user_token) + if abstain_data is not None: + action_data.append(abstain_data) + if action_data: + self.apply_instance(instance) + self.execute_other_action(VoteCreate, action_data) + if keyword == "poll_candidate_user_ids": + self.apply_instance(instance) + user_ids = instance.pop("poll_candidate_user_ids") + self.execute_other_action( + PollCandidateListCreate, + [ + { + "option_id": instance["id"], + "meeting_id": instance["meeting_id"], + "entries": [ + {"user_id": user_id, "weight": i} + for i, user_id in enumerate(user_ids, start=1) + ], + } + ], + ) + + return instance + + def get_vote_action_data( + self, instance: dict[str, Any], value: str, prop: str, user_token: str + ) -> dict[str, Any] | None: + if instance.get(prop): + return { + "value": value, + "weight": instance[prop], + "option_id": instance["id"], + "user_token": user_token, + } + return None + + @staticmethod + def check_one_of_three_keywords(instance: dict[str, Any]) -> str: + keys = [ + key + for key in ("text", "content_object_id", "poll_candidate_user_ids") + if key in instance + ] + if len(keys) != 1: + raise ActionException( + "Need one of text, content_object_id or poll_candidate_user_ids." + ) + return keys[0] diff --git a/openslides_backend/action/actions/option/delete.py b/openslides_backend/action/actions/option/delete.py new file mode 100644 index 000000000..b2bc679e6 --- /dev/null +++ b/openslides_backend/action/actions/option/delete.py @@ -0,0 +1,38 @@ +from typing import Any + +from ....models.models import Option +from ....shared.patterns import ( + collection_from_fqid, + fqid_from_collection_and_id, + id_from_fqid, +) +from ...generics.delete import DeleteAction +from ...util.action_type import ActionType +from ...util.default_schema import DefaultSchema +from ...util.register import register_action +from ..poll_candidate_list.delete import PollCandidateListDelete + + +@register_action("option.delete", action_type=ActionType.BACKEND_INTERNAL) +class OptionDelete(DeleteAction): + """ + Action to delete options. + """ + + model = Option() + schema = DefaultSchema(Option()).get_delete_schema() + + def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: + option = self.datastore.get( + fqid_from_collection_and_id("option", instance["id"]), ["content_object_id"] + ) + if ( + option.get("content_object_id") + and collection_from_fqid(option["content_object_id"]) + == "poll_candidate_list" + ): + self.execute_other_action( + PollCandidateListDelete, + [{"id": id_from_fqid(option["content_object_id"])}], + ) + return instance diff --git a/openslides_backend/action/actions/option/set_auto_fields.py b/openslides_backend/action/actions/option/set_auto_fields.py new file mode 100644 index 000000000..f297d50e7 --- /dev/null +++ b/openslides_backend/action/actions/option/set_auto_fields.py @@ -0,0 +1,28 @@ +from typing import Any + +from ....models.models import Option +from ...generics.update import UpdateAction +from ...util.action_type import ActionType +from ...util.default_schema import DefaultSchema +from ...util.register import register_action + + +@register_action("option.set_auto_fields", action_type=ActionType.BACKEND_INTERNAL) +class OptionSetAutoFields(UpdateAction): + """ + Action to calculate auto fields for options (yes, no, abstain) + """ + + model = Option() + schema = DefaultSchema(Option()).get_update_schema( + optional_properties=["yes", "no", "abstain"] + ) + + def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: + set_without_calc = ( + instance.get("yes") or instance.get("no") or instance.get("abstain") + ) + if not set_without_calc: + # TODO in this case we should autogenerate the fields. + raise NotImplementedError() + return instance diff --git a/openslides_backend/action/actions/option/update.py b/openslides_backend/action/actions/option/update.py new file mode 100644 index 000000000..9c1225d8d --- /dev/null +++ b/openslides_backend/action/actions/option/update.py @@ -0,0 +1,185 @@ +from typing import Any + +from ....models.models import Option, Poll +from ....services.database.commands import GetManyRequest +from ....shared.exceptions import ActionException +from ....shared.patterns import fqid_from_collection_and_id +from ....shared.schema import decimal_schema +from ...generics.update import UpdateAction +from ...util.default_schema import DefaultSchema +from ...util.register import register_action +from ..poll.functions import check_poll_or_option_perms +from ..poll.set_state import PollSetState +from ..vote.create import VoteCreate +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): + """ + Action to update an option. + """ + + model = Option() + schema = DefaultSchema(Option()).get_update_schema( + additional_optional_fields={ + "Y": decimal_schema, + "N": decimal_schema, + "A": decimal_schema, + "publish_immediately": {"type": "boolean"}, + } + ) + + def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: + """Update votes and auto calculate yes, no, abstain.""" + + option, poll = self._get_option_and_poll(instance["id"]) + state_change = self.check_state_change(instance, poll) + + 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 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": letter, + "weight": instance[option_key], + "user_token": user_token, + } + ) + else: + action_data_update.append( + {"id": vote_id, "weight": instance[option_key]} + ) + if action_data_create: + self.execute_other_action(VoteCreate, action_data_create) + if action_data_update: + self.execute_other_action(VoteUpdate, action_data_update) + + execute_other_action = False + if state_change: + state = Poll.STATE_FINISHED + execute_other_action = True + if ( + execute_other_action + or ( + poll["state"] == Poll.STATE_FINISHED + and poll["type"] == Poll.TYPE_ANALOG + ) + ) and instance.get("publish_immediately"): + state = Poll.STATE_PUBLISHED + execute_other_action = True + if execute_other_action: + self.execute_other_action( + PollSetState, [{"id": poll["id"], "state": state}] + ) + + instance.pop("publish_immediately", None) + return instance + + def _get_option_and_poll( + self, option_id: int + ) -> tuple[dict[str, Any], dict[str, Any]]: + option = self.datastore.get( + fqid_from_collection_and_id(self.model.collection, option_id), + ["poll_id", "used_as_global_option_in_poll_id", "vote_ids", "meeting_id"], + ) + return ( + option, + self.datastore.get( + fqid_from_collection_and_id("poll", option["poll_id"]), + [ + "id", + "state", + "type", + "pollmethod", + "global_yes", + "global_no", + "global_abstain", + "meeting_id", + "content_object_id", + ], + lock_result=["type"], + ), + ) + + def _handle_poll_option_data( + self, instance: dict[str, Any], poll: dict[str, Any] + ) -> None: + if poll.get("type") == "analog": + data = self._get_data(instance) + pollmethod = poll["pollmethod"] + for letter, key in option_keys_map.items(): + if letter in pollmethod: + instance[key] = data.get(key, "-2.000000") + elif data.get(key) is not None: + 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: + if poll.get("type") == "analog": + data = self._get_data(instance) + 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]: + 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("vote", vote_ids, ["value"]) + gm_result = self.datastore.get_many([get_many_request]) + votes = gm_result.get("vote", {}) + return votes + + def _get_vote_id( + self, search_value: str, id_to_vote: dict[int, dict[str, Any]] + ) -> int | None: + for key, item in id_to_vote.items(): + if item["value"] == search_value: + return key + return None + + def check_state_change( + self, instance: dict[str, Any], poll: dict[str, Any] + ) -> bool: + 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_option_and_poll(instance["id"]) + content_object_id = poll.get("content_object_id", "") + meeting_id = poll["meeting_id"] + check_poll_or_option_perms( + content_object_id, self.datastore, self.user_id, meeting_id + ) diff --git a/openslides_backend/action/actions/poll/create.py b/openslides_backend/action/actions/poll/create.py index 875e6e87b..2d43b990d 100644 --- a/openslides_backend/action/actions/poll/create.py +++ b/openslides_backend/action/actions/poll/create.py @@ -10,6 +10,7 @@ from ...mixins.forbid_anonymous_group_mixin import ForbidAnonymousGroupMixin from ...util.default_schema import DefaultSchema from ...util.register import register_action +from ..option.create import OptionCreateAction from .base import base_check_onehundred_percent_base from .mixins import PollHistoryMixin, PollPermissionMixin, PollValidationMixin @@ -52,6 +53,7 @@ class PollCreateAction( }, optional_properties=[ "content_object_id", + "description", "min_votes_amount", "max_votes_amount", "max_votes_per_option", @@ -130,38 +132,38 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: if not state.get("allow_create_poll"): raise ActionException("Motion state doesn't allow to create poll.") - # # handle non-global options - # unique_set = set() - - # for weight, option in enumerate(instance.get("options", []), start=1): - # # check the keys with staticmethod from option.create, where they belong - # key = OptionCreateAction.check_one_of_three_keywords(option) - # data: dict[str, Any] = { - # "poll_id": instance["id"], - # "meeting_id": instance["meeting_id"], - # "weight": weight, - # key: option[key], - # } - - # o_obj = f"{key},{option[key]}" - # if o_obj in unique_set: - # raise ActionException( - # f"Duplicated option in poll.options: {option[key]}" - # ) - # else: - # unique_set.add(o_obj) - - # if instance["type"] == "analog": - # if instance["pollmethod"] == "N": - # data["no"] = self.parse_vote_value(option, "N") - # else: - # data["yes"] = self.parse_vote_value(option, "Y") - # if instance["pollmethod"] in ("YN", "YNA"): - # data["no"] = self.parse_vote_value(option, "N") - # if instance["pollmethod"] == "YNA": - # data["abstain"] = self.parse_vote_value(option, "A") - - # action_data.append(data) + # handle non-global options + unique_set = set() + + for weight, option in enumerate(instance.get("options", []), start=1): + # check the keys with staticmethod from option.create, where they belong + key = OptionCreateAction.check_one_of_three_keywords(option) + data: dict[str, Any] = { + "poll_id": instance["id"], + "meeting_id": instance["meeting_id"], + "weight": weight, + key: option[key], + } + + o_obj = f"{key},{option[key]}" + if o_obj in unique_set: + raise ActionException( + f"Duplicated option in poll.options: {option[key]}" + ) + else: + unique_set.add(o_obj) + + if instance["type"] == "analog": + if instance["pollmethod"] == "N": + data["no"] = self.parse_vote_value(option, "N") + else: + data["yes"] = self.parse_vote_value(option, "Y") + if instance["pollmethod"] in ("YN", "YNA"): + data["no"] = self.parse_vote_value(option, "N") + if instance["pollmethod"] == "YNA": + data["abstain"] = self.parse_vote_value(option, "A") + + action_data.append(data) # handle global option global_data = { @@ -181,10 +183,10 @@ def update_instance(self, instance: dict[str, Any]) -> dict[str, Any]: # Execute the create option actions self.apply_instance(instance) - # self.execute_other_action( - # OptionCreateAction, - # action_data, - # ) + self.execute_other_action( + OptionCreateAction, + action_data, + ) # set state instance["state"] = Poll.STATE_CREATED diff --git a/openslides_backend/action/actions/poll/mixins.py b/openslides_backend/action/actions/poll/mixins.py index 418c616e8..e4ffdf0fa 100644 --- a/openslides_backend/action/actions/poll/mixins.py +++ b/openslides_backend/action/actions/poll/mixins.py @@ -13,6 +13,7 @@ fqid_from_collection_and_id, ) from ...action import Action +from ..option.set_auto_fields import OptionSetAutoFields from ..projector_countdown.mixins import CountdownCommand, CountdownControl from ..vote.create import VoteCreate from ..vote.user_token_helper import get_user_token @@ -179,18 +180,18 @@ def on_stop(self, instance: dict[str, Any]) -> None: raise VoteServiceException("Invalid response from vote service") self.execute_other_action(VoteCreate, action_data) # update results into option - # self.execute_other_action( - # OptionSetAutoFields, - # [ - # { - # "id": _id, - # "yes": str(option["Y"]), - # "no": str(option["N"]), - # "abstain": str(option["A"]), - # } - # for _id, option in option_results.items() - # ], - # ) + self.execute_other_action( + OptionSetAutoFields, + [ + { + "id": _id, + "yes": str(option["Y"]), + "no": str(option["N"]), + "abstain": str(option["A"]), + } + for _id, option in option_results.items() + ], + ) # set voted ids voted_ids = results["user_ids"] instance["voted_ids"] = voted_ids diff --git a/openslides_backend/action/actions/poll/reset.py b/openslides_backend/action/actions/poll/reset.py index b9bb3e8e7..3a7120975 100644 --- a/openslides_backend/action/actions/poll/reset.py +++ b/openslides_backend/action/actions/poll/reset.py @@ -10,6 +10,7 @@ from ...util.default_schema import DefaultSchema from ...util.register import register_action from ...util.typing import ActionData +from ..option.set_auto_fields import OptionSetAutoFields from ..vote.delete import VoteDelete from .mixins import PollHistoryMixin, PollPermissionMixin @@ -91,7 +92,7 @@ def delete_all_votes(self, poll_id: int) -> None: option = options[option_id] if option.get("vote_ids"): self._delete_votes(option["vote_ids"]) - # self._clear_option_auto_fields(option_id) + self._clear_option_auto_fields(option_id) def _get_option_ids(self, poll_id: int) -> list[int]: poll = self.datastore.get( @@ -118,16 +119,16 @@ def _delete_votes(self, vote_ids: list[int]) -> None: action_data.append({"id": id_}) self.execute_other_action(VoteDelete, action_data) - # def _clear_option_auto_fields(self, option_id: int) -> None: - # action_data = [ - # { - # "id": option_id, - # "yes": "0.000000", - # "no": "0.000000", - # "abstain": "0.000000", - # } - # ] - # self.execute_other_action(OptionSetAutoFields, action_data) + def _clear_option_auto_fields(self, option_id: int) -> None: + action_data = [ + { + "id": option_id, + "yes": "0.000000", + "no": "0.000000", + "abstain": "0.000000", + } + ] + self.execute_other_action(OptionSetAutoFields, action_data) def get_on_success(self, action_data: ActionData) -> Callable[[], None]: def on_success() -> None: diff --git a/openslides_backend/action/actions/poll/update.py b/openslides_backend/action/actions/poll/update.py index abcd7fef0..c8603aea5 100644 --- a/openslides_backend/action/actions/poll/update.py +++ b/openslides_backend/action/actions/poll/update.py @@ -43,6 +43,7 @@ class PollUpdateAction( "global_abstain", "entitled_group_ids", "title", + "description", "onehundred_percent_base", "votesvalid", "votesinvalid", diff --git a/openslides_backend/models/models.py b/openslides_backend/models/models.py index 9991b62e9..d54423132 100644 --- a/openslides_backend/models/models.py +++ b/openslides_backend/models/models.py @@ -2366,6 +2366,7 @@ class Poll(Model, PollModelMixin): id = fields.IntegerField(required=True, constant=True) title = fields.CharField(required=True) + description = fields.CharField() type = fields.CharField( required=True, constraints={"enum": ["analog", "named", "pseudoanonymous", "cryptographic"]}, @@ -2944,7 +2945,6 @@ class Projection(Model): stable = fields.BooleanField(default=False) weight = fields.IntegerField() type = fields.CharField() - content = fields.JSONField() current_projector_id = fields.RelationField( to={"projector": "current_projection_ids"}, equal_fields="meeting_id" )