Remove motion logs
This commit is contained in:
parent
55c162809c
commit
4308de3164
14
openslides/motions/migrations/0023_remove_motion_log.py
Normal file
14
openslides/motions/migrations/0023_remove_motion_log.py
Normal file
@ -0,0 +1,14 @@
|
||||
# Generated by Django 2.1.7 on 2019-04-01 06:58
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [("motions", "0022_auto_20190320_0840")]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(model_name="motionlog", name="motion"),
|
||||
migrations.RemoveField(model_name="motionlog", name="person"),
|
||||
migrations.DeleteModel(name="MotionLog"),
|
||||
]
|
@ -6,7 +6,6 @@ from django.contrib.contenttypes.fields import GenericRelation
|
||||
from django.core.exceptions import ImproperlyConfigured, ValidationError
|
||||
from django.db import IntegrityError, models, transaction
|
||||
from django.db.models import Max
|
||||
from django.utils import formats, timezone
|
||||
from jsonfield import JSONField
|
||||
|
||||
from openslides.agenda.models import Item
|
||||
@ -81,7 +80,6 @@ class MotionManager(models.Manager):
|
||||
"comments__section",
|
||||
"comments__section__read_groups",
|
||||
"agenda_items",
|
||||
"log_messages",
|
||||
"polls",
|
||||
"attachments",
|
||||
"tags",
|
||||
@ -540,17 +538,6 @@ class Motion(RESTModelMixin, models.Model):
|
||||
"""
|
||||
return self.agenda_item.pk
|
||||
|
||||
def write_log(self, message_list, person=None, skip_autoupdate=False):
|
||||
"""
|
||||
Write a log message.
|
||||
|
||||
The message should be in English.
|
||||
"""
|
||||
if person and not person.is_authenticated:
|
||||
person = None
|
||||
motion_log = MotionLog(motion=self, message_list=message_list, person=person)
|
||||
motion_log.save(skip_autoupdate=skip_autoupdate)
|
||||
|
||||
def is_amendment(self):
|
||||
"""
|
||||
Returns True if the motion is an amendment.
|
||||
@ -903,50 +890,6 @@ class MotionBlock(RESTModelMixin, models.Model):
|
||||
return {"title": self.title}
|
||||
|
||||
|
||||
class MotionLog(RESTModelMixin, models.Model):
|
||||
"""Save a logmessage for a motion."""
|
||||
|
||||
motion = models.ForeignKey(
|
||||
Motion, on_delete=models.CASCADE, related_name="log_messages"
|
||||
)
|
||||
"""The motion to witch the object belongs."""
|
||||
|
||||
message_list = JSONField()
|
||||
"""
|
||||
The log message. It should be a list of strings in English.
|
||||
"""
|
||||
|
||||
person = models.ForeignKey(
|
||||
settings.AUTH_USER_MODEL, on_delete=SET_NULL_AND_AUTOUPDATE, null=True
|
||||
)
|
||||
"""A user object, who created the log message. Optional."""
|
||||
|
||||
time = models.DateTimeField(auto_now=True)
|
||||
"""The Time, when the loged action was performed."""
|
||||
|
||||
class Meta:
|
||||
default_permissions = ()
|
||||
ordering = ["-time"]
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Return a string, representing the log message.
|
||||
"""
|
||||
localtime = timezone.localtime(self.time)
|
||||
time = formats.date_format(localtime, "DATETIME_FORMAT")
|
||||
message_list = "".join(self.message_list)
|
||||
time_and_messages = f"{time} {message_list}"
|
||||
if self.person is not None:
|
||||
return f"{time_and_messages} by {self.person}"
|
||||
return time_and_messages
|
||||
|
||||
def get_root_rest_element(self):
|
||||
"""
|
||||
Returns the motion to this instance which is the root REST element.
|
||||
"""
|
||||
return self.motion
|
||||
|
||||
|
||||
class MotionVote(RESTModelMixin, BaseVote):
|
||||
"""Saves the votes for a MotionPoll.
|
||||
|
||||
|
@ -25,7 +25,6 @@ from .models import (
|
||||
MotionChangeRecommendation,
|
||||
MotionComment,
|
||||
MotionCommentSection,
|
||||
MotionLog,
|
||||
MotionPoll,
|
||||
State,
|
||||
StatuteParagraph,
|
||||
@ -171,24 +170,6 @@ class AmendmentParagraphsJSONSerializerField(Field):
|
||||
return data
|
||||
|
||||
|
||||
class MotionLogSerializer(ModelSerializer):
|
||||
"""
|
||||
Serializer for motion.models.MotionLog objects.
|
||||
"""
|
||||
|
||||
message = SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = MotionLog
|
||||
fields = ("message_list", "person", "time", "message")
|
||||
|
||||
def get_message(self, obj):
|
||||
"""
|
||||
Concats the message parts to one string. Useful for smart template code.
|
||||
"""
|
||||
return str(obj)
|
||||
|
||||
|
||||
class MotionPollSerializer(ModelSerializer):
|
||||
"""
|
||||
Serializer for motion.models.MotionPoll objects.
|
||||
@ -385,7 +366,6 @@ class MotionSerializer(ModelSerializer):
|
||||
"""
|
||||
|
||||
comments = MotionCommentSerializer(many=True, read_only=True)
|
||||
log_messages = MotionLogSerializer(many=True, read_only=True)
|
||||
polls = MotionPollSerializer(many=True, read_only=True)
|
||||
modified_final_version = CharField(allow_blank=True, required=False)
|
||||
reason = CharField(allow_blank=True, required=False)
|
||||
@ -435,7 +415,6 @@ class MotionSerializer(ModelSerializer):
|
||||
"agenda_item_id",
|
||||
"agenda_type",
|
||||
"agenda_parent_id",
|
||||
"log_messages",
|
||||
"sort_parent",
|
||||
"weight",
|
||||
"created",
|
||||
|
@ -223,9 +223,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
for submitter in submitters:
|
||||
Submitter.objects.add(submitter, motion)
|
||||
|
||||
# Write the log message and initiate response.
|
||||
motion.write_log(["Motion created"], request.user)
|
||||
|
||||
# Send new submitters and supporters via autoupdate because users
|
||||
# without permission to see users may not have them but can get it now.
|
||||
# TODO: Skip history.
|
||||
@ -298,16 +295,13 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
serializer.is_valid(raise_exception=True)
|
||||
updated_motion = serializer.save()
|
||||
|
||||
# Write the log message, check removal of supporters and initiate response.
|
||||
# TODO: Log if a motion was updated.
|
||||
updated_motion.write_log(["Motion updated"], request.user)
|
||||
# Check removal of supporters and initiate response.
|
||||
if (
|
||||
config["motions_remove_supporters"]
|
||||
and updated_motion.state.allow_support
|
||||
and not has_perm(request.user, "motions.can_manage")
|
||||
):
|
||||
updated_motion.supporters.clear()
|
||||
updated_motion.write_log(["All supporters removed"], request.user)
|
||||
|
||||
# Send new supporters via autoupdate because users
|
||||
# without permission to see users may not have them but can get it now.
|
||||
@ -390,19 +384,15 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
comment.comment = comment_value
|
||||
comment.save()
|
||||
|
||||
# write log
|
||||
motion.write_log([f"Comment {section.name} updated"], request.user)
|
||||
message = ["Comment {arg1} updated", section.name]
|
||||
else: # DELETE
|
||||
try:
|
||||
comment = MotionComment.objects.get(motion=motion, section=section)
|
||||
except MotionComment.DoesNotExist:
|
||||
# Be silent about not existing comments, but do not create a log entry.
|
||||
# Be silent about not existing comments.
|
||||
pass
|
||||
else:
|
||||
comment.delete()
|
||||
|
||||
motion.write_log([f"Comment {section.name} deleted"], request.user)
|
||||
message = ["Comment {arg1} deleted", section.name]
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
@ -512,7 +502,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
):
|
||||
raise ValidationError({"detail": "You can not support this motion."})
|
||||
motion.supporters.add(request.user)
|
||||
motion.write_log(["Motion supported"], request.user)
|
||||
# Send new supporter via autoupdate because users without permission
|
||||
# to see users may not have it but can get it now.
|
||||
# TODO: Skip history.
|
||||
@ -524,7 +513,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
if not motion.state.allow_support or not motion.is_supporter(request.user):
|
||||
raise ValidationError({"detail": "You can not unsupport this motion."})
|
||||
motion.supporters.remove(request.user)
|
||||
motion.write_log(["Motion unsupported"], request.user)
|
||||
message = "You have unsupported this motion successfully."
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
@ -580,13 +568,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
)
|
||||
message = f"The state of the motion was set to {motion.state.name}."
|
||||
|
||||
# Write the log message and initiate response.
|
||||
motion.write_log(
|
||||
message_list=[f"State set to {motion.state.name}"],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion,
|
||||
@ -661,13 +642,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Write the log message.
|
||||
motion.write_log(
|
||||
message_list=["State set to", " ", motion.state.name],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion,
|
||||
@ -731,13 +705,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
)
|
||||
message = f"The recommendation of the motion was set to {label}."
|
||||
|
||||
# Write the log message and initiate response.
|
||||
motion.write_log(
|
||||
message_list=["Recommendation set to", " ", label],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion,
|
||||
@ -820,13 +787,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
else "None"
|
||||
)
|
||||
|
||||
# Write the log message.
|
||||
motion.write_log(
|
||||
message_list=["Recommendation set to", " ", label],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Fire autoupdate and save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion,
|
||||
@ -850,7 +810,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
|
||||
motion.follow_recommendation()
|
||||
|
||||
# Save and write log.
|
||||
motion.save(
|
||||
update_fields=[
|
||||
"state",
|
||||
@ -861,11 +820,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
],
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
motion.write_log(
|
||||
message_list=["State set to", " ", motion.state.name],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
|
||||
# Now send all changes to the clients.
|
||||
inform_changed_data(
|
||||
@ -891,7 +845,6 @@ class MotionViewSet(TreeSortMixin, ModelViewSet):
|
||||
poll = motion.create_poll(skip_autoupdate=True)
|
||||
except WorkflowError as err:
|
||||
raise ValidationError({"detail": err})
|
||||
motion.write_log(["Vote created"], request.user, skip_autoupdate=True)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
@ -989,7 +942,6 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
response = super().update(*args, **kwargs)
|
||||
poll = self.get_object()
|
||||
poll.motion.write_log(["Vote updated"], self.request.user)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
@ -1004,7 +956,6 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
||||
"""
|
||||
poll = self.get_object()
|
||||
result = super().destroy(*args, **kwargs)
|
||||
poll.motion.write_log(["Vote deleted"], self.request.user)
|
||||
|
||||
# Fire autoupdate again to save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
@ -1362,12 +1313,6 @@ class MotionBlockViewSet(ModelViewSet):
|
||||
# Follow recommendation.
|
||||
motion.follow_recommendation()
|
||||
motion.save(skip_autoupdate=True)
|
||||
# Write the log message.
|
||||
motion.write_log(
|
||||
message_list=["State set to", " ", motion.state.name],
|
||||
person=request.user,
|
||||
skip_autoupdate=True,
|
||||
)
|
||||
# Fire autoupdate and save information to OpenSlides history.
|
||||
inform_changed_data(
|
||||
motion,
|
||||
|
@ -15,7 +15,6 @@ from openslides.motions.models import (
|
||||
MotionChangeRecommendation,
|
||||
MotionComment,
|
||||
MotionCommentSection,
|
||||
MotionLog,
|
||||
State,
|
||||
StatuteParagraph,
|
||||
Submitter,
|
||||
@ -44,7 +43,6 @@ def test_motion_db_queries():
|
||||
* 1 request for all motion comment sections required for the comments
|
||||
* 1 request for all users required for the read_groups of the sections
|
||||
* 1 request to get the agenda item,
|
||||
* 1 request to get the motion log,
|
||||
* 1 request to get the polls,
|
||||
* 1 request to get the attachments,
|
||||
* 1 request to get the tags,
|
||||
@ -71,7 +69,7 @@ def test_motion_db_queries():
|
||||
)
|
||||
# TODO: Create some polls etc.
|
||||
|
||||
assert count_queries(Motion.get_elements) == 13
|
||||
assert count_queries(Motion.get_elements) == 12
|
||||
|
||||
|
||||
@pytest.mark.django_db(transaction=False)
|
||||
@ -914,12 +912,6 @@ class ManageComments(TestCase):
|
||||
comment = MotionComment.objects.get()
|
||||
self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf")
|
||||
|
||||
# Check for a log entry
|
||||
motion_logs = MotionLog.objects.filter(motion=self.motion)
|
||||
self.assertEqual(motion_logs.count(), 1)
|
||||
comment_log = motion_logs.get()
|
||||
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
|
||||
|
||||
def test_update_comment(self):
|
||||
comment = MotionComment(
|
||||
motion=self.motion,
|
||||
@ -940,12 +932,6 @@ class ManageComments(TestCase):
|
||||
comment = MotionComment.objects.get()
|
||||
self.assertEqual(comment.comment, "test_comment_fk3jrnfwsdg%fj=feijf")
|
||||
|
||||
# Check for a log entry
|
||||
motion_logs = MotionLog.objects.filter(motion=self.motion)
|
||||
self.assertEqual(motion_logs.count(), 1)
|
||||
comment_log = motion_logs.get()
|
||||
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
|
||||
|
||||
def test_delete_comment(self):
|
||||
comment = MotionComment(
|
||||
motion=self.motion,
|
||||
@ -962,12 +948,6 @@ class ManageComments(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(MotionComment.objects.count(), 0)
|
||||
|
||||
# Check for a log entry
|
||||
motion_logs = MotionLog.objects.filter(motion=self.motion)
|
||||
self.assertEqual(motion_logs.count(), 1)
|
||||
comment_log = motion_logs.get()
|
||||
self.assertTrue(self.section_read_write.name in comment_log.message_list[0])
|
||||
|
||||
def test_delete_not_existing_comment(self):
|
||||
"""
|
||||
This should fail silently; no error, if the user wants to delete
|
||||
@ -981,10 +961,6 @@ class ManageComments(TestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(MotionComment.objects.count(), 0)
|
||||
|
||||
# Check that no log entry was created
|
||||
motion_logs = MotionLog.objects.filter(motion=self.motion)
|
||||
self.assertEqual(motion_logs.count(), 0)
|
||||
|
||||
def test_create_comment_no_write_permission(self):
|
||||
response = self.client.post(
|
||||
reverse("motion-manage-comments", args=[self.motion.pk]),
|
||||
|
Loading…
Reference in New Issue
Block a user