#35 Sanity command
* refactors "toggling" of recorded/checked state * introduces mark_as_edited() for RecordableObjectMixin
This commit is contained in:
parent
80e72c2146
commit
bd36ab5b6f
@ -284,6 +284,8 @@ class EditCompensationForm(NewCompensationForm):
|
|||||||
self.instance.save()
|
self.instance.save()
|
||||||
|
|
||||||
self.instance.log.add(action)
|
self.instance.log.add(action)
|
||||||
|
|
||||||
|
intervention.mark_as_edited(user)
|
||||||
return self.instance
|
return self.instance
|
||||||
|
|
||||||
|
|
||||||
|
@ -271,6 +271,11 @@ class Compensation(AbstractCompensation, CEFMixin, CoherenceMixin):
|
|||||||
)
|
)
|
||||||
return docs
|
return docs
|
||||||
|
|
||||||
|
def add_new_action(self, form) -> CompensationAction:
|
||||||
|
super().add_new_action(form)
|
||||||
|
self.intervention.set_as_edited(form.user)
|
||||||
|
|
||||||
|
|
||||||
class CompensationDocument(AbstractDocument):
|
class CompensationDocument(AbstractDocument):
|
||||||
"""
|
"""
|
||||||
Specializes document upload for revocations with certain path
|
Specializes document upload for revocations with certain path
|
||||||
|
@ -7,6 +7,7 @@ Created on: 16.11.21
|
|||||||
"""
|
"""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
|
@ -274,7 +274,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
|
|||||||
|
|
||||||
# Now mock the eco account as it would be recorded (with invalid data)
|
# Now mock the eco account as it would be recorded (with invalid data)
|
||||||
# Make sure the deductible surface is high enough for the request
|
# Make sure the deductible surface is high enough for the request
|
||||||
self.eco_account.toggle_recorded(self.superuser)
|
self.eco_account.set_recorded(self.superuser)
|
||||||
self.eco_account.refresh_from_db()
|
self.eco_account.refresh_from_db()
|
||||||
self.eco_account.deductable_surface = test_surface + 1.00
|
self.eco_account.deductable_surface = test_surface + 1.00
|
||||||
self.eco_account.save()
|
self.eco_account.save()
|
||||||
|
@ -15,7 +15,8 @@ from konova.decorators import *
|
|||||||
from konova.forms import RemoveModalForm, SimpleGeomForm
|
from konova.forms import RemoveModalForm, SimpleGeomForm
|
||||||
from konova.utils.documents import get_document, remove_document
|
from konova.utils.documents import get_document, remove_document
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.generators import generate_qr_code
|
||||||
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION
|
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION, \
|
||||||
|
CHECKED_RECORDED_RESET
|
||||||
from konova.utils.user_checks import in_group
|
from konova.utils.user_checks import in_group
|
||||||
|
|
||||||
|
|
||||||
@ -130,8 +131,15 @@ def edit_view(request: HttpRequest, id: str):
|
|||||||
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
if data_form.is_valid() and geom_form.is_valid():
|
if data_form.is_valid() and geom_form.is_valid():
|
||||||
|
# Preserve state of intervention recorded/checked to determine whether the user must be informed or not
|
||||||
|
# about a change of the recorded/checked state
|
||||||
|
intervention_recorded = comp.intervention.recorded is not None
|
||||||
|
intervention_checked = comp.intervention.checked is not None
|
||||||
|
|
||||||
# The data form takes the geom form for processing, as well as the performing user
|
# The data form takes the geom form for processing, as well as the performing user
|
||||||
comp = data_form.save(request.user, geom_form)
|
comp = data_form.save(request.user, geom_form)
|
||||||
|
if intervention_recorded or intervention_checked:
|
||||||
|
messages.info(request, CHECKED_RECORDED_RESET)
|
||||||
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
||||||
return redirect("compensation:detail", id=comp.id)
|
return redirect("compensation:detail", id=comp.id)
|
||||||
else:
|
else:
|
||||||
|
@ -7,6 +7,7 @@ Created on: 15.11.21
|
|||||||
"""
|
"""
|
||||||
import shutil
|
import shutil
|
||||||
|
|
||||||
|
from django.contrib.auth.models import User
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import QuerySet
|
from django.db.models import QuerySet
|
||||||
|
|
||||||
|
@ -348,10 +348,7 @@ class EditInterventionForm(NewInterventionForm):
|
|||||||
self.instance.save()
|
self.instance.save()
|
||||||
|
|
||||||
# Uncheck and unrecord intervention due to changed data
|
# Uncheck and unrecord intervention due to changed data
|
||||||
if self.instance.checked:
|
self.instance.mark_as_edited(user)
|
||||||
self.instance.set_unchecked()
|
|
||||||
if self.instance.recorded:
|
|
||||||
self.instance.set_unrecorded(user)
|
|
||||||
|
|
||||||
return self.instance
|
return self.instance
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ class CheckModalForm(BaseModalForm):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
self.instance.toggle_checked(self.user)
|
self.instance.set_checked(self.user)
|
||||||
|
|
||||||
|
|
||||||
class NewDeductionModalForm(BaseModalForm):
|
class NewDeductionModalForm(BaseModalForm):
|
||||||
|
@ -138,40 +138,33 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
)
|
)
|
||||||
return revoc_docs, regular_docs
|
return revoc_docs, regular_docs
|
||||||
|
|
||||||
def toggle_recorded(self, user: User):
|
def set_unchecked(self):
|
||||||
""" Toggle the recorded state
|
log_entry = super().set_unchecked()
|
||||||
|
self.add_log_entry_to_compensations(log_entry)
|
||||||
|
|
||||||
For interventions the recorded action needs to be added to their compensation objects as well
|
def set_checked(self, user: User) -> UserActionLogEntry:
|
||||||
|
log_entry = super().set_checked(user)
|
||||||
|
self.add_log_entry_to_compensations(log_entry)
|
||||||
|
return log_entry
|
||||||
|
|
||||||
|
def set_unrecorded(self, user: User):
|
||||||
|
log_entry = super().set_unrecorded(user)
|
||||||
|
self.add_log_entry_to_compensations(log_entry)
|
||||||
|
|
||||||
|
def set_recorded(self, user: User) -> UserActionLogEntry:
|
||||||
|
log_entry = super().set_recorded(user)
|
||||||
|
self.add_log_entry_to_compensations(log_entry)
|
||||||
|
return log_entry
|
||||||
|
|
||||||
|
def add_log_entry_to_compensations(self, log_entry: UserActionLogEntry):
|
||||||
|
""" Adds the log entry to related compensations
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user (User): The performing user
|
log_entry (UserActionLogEntry): The log entry
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
log_entry = super().toggle_recorded(user)
|
|
||||||
|
|
||||||
# Add this action to the linked compensation logs as well
|
|
||||||
comps = self.compensations.all()
|
|
||||||
for comp in comps:
|
|
||||||
comp.log.add(log_entry)
|
|
||||||
|
|
||||||
def toggle_checked(self, user: User) -> UserActionLogEntry:
|
|
||||||
""" Toggle the checked state
|
|
||||||
|
|
||||||
For interventions the checked action needs to be added to their compensation objects as well
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
log_entry = super().toggle_checked(user)
|
|
||||||
# Leave if the log_entry is None (means "unchecked")
|
|
||||||
if log_entry is None:
|
|
||||||
return
|
|
||||||
# Add this action to the linked compensation logs as well
|
|
||||||
comps = self.compensations.all()
|
comps = self.compensations.all()
|
||||||
for comp in comps:
|
for comp in comps:
|
||||||
comp.log.add(log_entry)
|
comp.log.add(log_entry)
|
||||||
@ -202,7 +195,8 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
self.log.add(edited_action)
|
self.log.add(edited_action)
|
||||||
self.modified = edited_action
|
self.modified = edited_action
|
||||||
self.save()
|
self.save()
|
||||||
return pay
|
self.mark_as_edited(user)
|
||||||
|
return pay
|
||||||
|
|
||||||
def add_revocation(self, form):
|
def add_revocation(self, form):
|
||||||
""" Adds a new revocation to the intervention
|
""" Adds a new revocation to the intervention
|
||||||
@ -237,6 +231,7 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
file=form_data["file"],
|
file=form_data["file"],
|
||||||
instance=revocation
|
instance=revocation
|
||||||
)
|
)
|
||||||
|
self.mark_as_edited(user)
|
||||||
return revocation
|
return revocation
|
||||||
|
|
||||||
def add_deduction(self, form):
|
def add_deduction(self, form):
|
||||||
@ -266,8 +261,23 @@ class Intervention(BaseObject, ShareableObjectMixin, RecordableObjectMixin, Chec
|
|||||||
surface=form_data["surface"],
|
surface=form_data["surface"],
|
||||||
created=user_action_create,
|
created=user_action_create,
|
||||||
)
|
)
|
||||||
|
self.mark_as_edited(user)
|
||||||
return deduction
|
return deduction
|
||||||
|
|
||||||
|
def mark_as_edited(self, performing_user: User):
|
||||||
|
""" In case the object or a related object changed, internal processes need to be started, such as
|
||||||
|
unrecord and uncheck
|
||||||
|
|
||||||
|
Args:
|
||||||
|
performing_user (User): The user which performed the editing action
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
|
||||||
|
"""
|
||||||
|
super().mark_as_edited(performing_user)
|
||||||
|
if self.checked:
|
||||||
|
self.set_unchecked()
|
||||||
|
|
||||||
|
|
||||||
class InterventionDocument(AbstractDocument):
|
class InterventionDocument(AbstractDocument):
|
||||||
"""
|
"""
|
||||||
|
@ -485,5 +485,8 @@ class RecordModalForm(BaseModalForm):
|
|||||||
def save(self):
|
def save(self):
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
if self.cleaned_data["confirm"]:
|
if self.cleaned_data["confirm"]:
|
||||||
self.instance.toggle_recorded(self.user)
|
if self.instance.recorded:
|
||||||
|
self.instance.set_unrecorded(self.user)
|
||||||
|
else:
|
||||||
|
self.instance.set_recorded(self.user)
|
||||||
return self.instance
|
return self.instance
|
@ -203,6 +203,8 @@ class RecordableObjectMixin(models.Model):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if not self.recorded:
|
||||||
|
return None
|
||||||
action = UserActionLogEntry.get_unrecorded_action(user)
|
action = UserActionLogEntry.get_unrecorded_action(user)
|
||||||
self.recorded = None
|
self.recorded = None
|
||||||
self.save()
|
self.save()
|
||||||
@ -218,26 +220,27 @@ class RecordableObjectMixin(models.Model):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if self.recorded:
|
||||||
|
return None
|
||||||
action = UserActionLogEntry.get_recorded_action(user)
|
action = UserActionLogEntry.get_recorded_action(user)
|
||||||
self.recorded = action
|
self.recorded = action
|
||||||
self.save()
|
self.save()
|
||||||
self.log.add(action)
|
self.log.add(action)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def toggle_recorded(self, user: User) -> UserActionLogEntry:
|
def mark_as_edited(self, performing_user: User):
|
||||||
""" Un/Record intervention
|
""" In case the object or a related object changed, internal processes need to be started, such as
|
||||||
|
unrecord and uncheck
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
user (User): Performing user
|
performing_user (User): The user which performed the editing action
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not self.recorded:
|
|
||||||
ret_log_entry = self.set_recorded(user)
|
if self.recorded:
|
||||||
else:
|
self.set_unrecorded(performing_user)
|
||||||
ret_log_entry = self.set_unrecorded(user)
|
|
||||||
return ret_log_entry
|
|
||||||
|
|
||||||
|
|
||||||
class CheckableObjectMixin(models.Model):
|
class CheckableObjectMixin(models.Model):
|
||||||
@ -262,6 +265,9 @@ class CheckableObjectMixin(models.Model):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if not self.checked:
|
||||||
|
# Nothing to do
|
||||||
|
return
|
||||||
# Do not .delete() the checked attribute! Just set it to None, since a delete() would kill it out of the
|
# Do not .delete() the checked attribute! Just set it to None, since a delete() would kill it out of the
|
||||||
# log history, which is not what we want!
|
# log history, which is not what we want!
|
||||||
self.checked = None
|
self.checked = None
|
||||||
@ -277,27 +283,15 @@ class CheckableObjectMixin(models.Model):
|
|||||||
Returns:
|
Returns:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if self.checked:
|
||||||
|
# Nothing to do
|
||||||
|
return
|
||||||
action = UserActionLogEntry.get_checked_action(user)
|
action = UserActionLogEntry.get_checked_action(user)
|
||||||
self.checked = action
|
self.checked = action
|
||||||
self.save()
|
self.save()
|
||||||
self.log.add(action)
|
self.log.add(action)
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def toggle_checked(self, user: User) -> UserActionLogEntry:
|
|
||||||
""" Un/Record intervention
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): Performing user
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not self.checked:
|
|
||||||
ret_log_entry = self.set_checked(user)
|
|
||||||
else:
|
|
||||||
ret_log_entry = self.set_unchecked()
|
|
||||||
return ret_log_entry
|
|
||||||
|
|
||||||
|
|
||||||
class ShareableObjectMixin(models.Model):
|
class ShareableObjectMixin(models.Model):
|
||||||
# Users having access on this object
|
# Users having access on this object
|
||||||
|
Loading…
Reference in New Issue
Block a user