Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

End interposed questions with their parents #2139

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions openslides_backend/action/actions/speaker/end_speech.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from time import time
from typing import Any, Dict

from openslides_backend.action.actions.speaker.delete import SpeakerDeleteAction
from openslides_backend.action.actions.speaker.speech_state import SpeechState
from openslides_backend.action.mixins.singular_action_mixin import SingularActionMixin
from openslides_backend.action.util.typing import ActionData
from openslides_backend.shared.filters import And, FilterOperator

from ....models.models import Speaker
from ....permissions.permissions import Permissions
Expand All @@ -27,6 +31,36 @@ class SpeakerEndSpeach(SingularActionMixin, CountdownControl, UpdateAction):
)
permission = Permissions.ListOfSpeakers.CAN_MANAGE

def get_updated_instances(self, action_data: ActionData) -> ActionData:
self.end_time = round(time())
instance = next(iter(action_data))
yield instance
# additionally yield all child interposed questions
db_instance = self.datastore.get(
fqid_from_collection_and_id("speaker", instance["id"]),
["list_of_speakers_id", "meeting_id", "speech_state"],
)
if db_instance.get("speech_state") != SpeechState.INTERPOSED_QUESTION:
result = self.datastore.filter(
"speaker",
And(
FilterOperator("meeting_id", "=", db_instance["meeting_id"]),
FilterOperator(
"list_of_speakers_id", "=", db_instance["list_of_speakers_id"]
),
FilterOperator(
"speech_state", "=", SpeechState.INTERPOSED_QUESTION
),
FilterOperator("end_time", "=", None),
),
["begin_time"],
)
for id, speaker in result.items():
if speaker.get("begin_time") is not None:
yield {"id": id}
else:
self.execute_other_action(SpeakerDeleteAction, [{"id": id}])

def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
instance = super().update_instance(instance)
speaker = self.datastore.get(
Expand All @@ -46,7 +80,7 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
raise ActionException(
f"Speaker {instance['id']} is not speaking at the moment."
)
instance["end_time"] = now = round(time())
instance["end_time"] = self.end_time

if speaker.get("pause_time"):
instance["total_pause"] = (
Expand All @@ -56,7 +90,7 @@ def update_instance(self, instance: Dict[str, Any]) -> Dict[str, Any]:
)
instance["pause_time"] = None
else:
self.decrease_structure_level_countdown(now, speaker)
self.decrease_structure_level_countdown(self.end_time, speaker)

self.control_los_countdown(speaker["meeting_id"], CountdownCommand.RESET)
return instance
40 changes: 40 additions & 0 deletions tests/system/action/speaker/test_end_speech.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,46 @@ def test_interposed_question(self) -> None:
def test_intervention(self) -> None:
self.with_structure_level_and_speech_state(SpeechState.INTERVENTION)

def test_end_started_child_interposed_question(self) -> None:
self.set_models(
{
"meeting_user/7": {"speaker_ids": [890, 891]},
"list_of_speakers/23": {"speaker_ids": [890, 891], "meeting_id": 1},
"speaker/890": {
"pause_time": 11000,
},
"speaker/891": {
"meeting_user_id": 7,
"list_of_speakers_id": 23,
"begin_time": 10000,
"speech_state": SpeechState.INTERPOSED_QUESTION,
"meeting_id": 1,
},
}
)
response = self.request("speaker.end_speech", {"id": 890})
self.assert_status_code(response, 200)
speaker = self.get_model("speaker/891")
self.assertIsNotNone(speaker.get("end_time"))
self.assert_model_exists("speaker/890", {"end_time": speaker["end_time"]})

def test_end_waiting_child_interposed_question(self) -> None:
self.set_models(
{
"meeting_user/7": {"speaker_ids": [890, 891]},
"list_of_speakers/23": {"speaker_ids": [890, 891], "meeting_id": 1},
"speaker/891": {
"meeting_user_id": 7,
"list_of_speakers_id": 23,
"speech_state": SpeechState.INTERPOSED_QUESTION,
"meeting_id": 1,
},
}
)
response = self.request("speaker.end_speech", {"id": 890})
self.assert_status_code(response, 200)
self.assert_model_deleted("speaker/891")

def test_end_speech_no_permissions(self) -> None:
self.base_permission_test(self.models, "speaker.end_speech", {"id": 890})

Expand Down