Skip to content

Commit

Permalink
raise on attempt to cancel actio item where reference_obj exists
Browse files Browse the repository at this point in the history
  • Loading branch information
erikvw committed Dec 6, 2023
1 parent bdecce7 commit 1b0a23f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 8 deletions.
4 changes: 4 additions & 0 deletions edc_action_item/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ class ActionItemError(Exception):
pass


class ActionItemStatusError(Exception):
pass


class ActionTypeError(Exception):
pass

Expand Down
16 changes: 14 additions & 2 deletions edc_action_item/forms/action_item_form.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django import forms
from edc_constants.constants import NEW, OPEN
from django.apps import apps as django_apps
from edc_constants.constants import CANCELLED, NEW, OPEN

from ..models import ActionItem

Expand All @@ -14,13 +15,24 @@ class ActionItemForm(forms.ModelForm):
def clean(self):
cleaned_data = super().clean()
self.force_open_status()
self.raise_if_cannot_cancel()
return cleaned_data

def force_open_status(self):
def force_open_status(self) -> None:
"""Sets status to open for edited NEW action items."""
if self.instance.id and self.cleaned_data.get("status") == NEW:
self.cleaned_data["status"] = OPEN

def raise_if_cannot_cancel(self) -> None:
if (
self.instance.id
and self.cleaned_data.get("status") == CANCELLED
and django_apps.get_model(self.instance.reference_model)
.objects.filter(action_identifier=self.instance.action_identifier)
.exists()
):
raise forms.ValidationError({"status": "Invalid. This action cannot be cancelled"})

class Meta:
model = ActionItem
fields = "__all__"
15 changes: 13 additions & 2 deletions edc_action_item/models/action_item.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.db.models.deletion import PROTECT
from edc_constants.constants import NEW
from edc_constants.constants import CANCELLED, NEW
from edc_identifier.model_mixins import NonUniqueSubjectIdentifierFieldMixin
from edc_model.models import BaseUuidModel, HistoricalRecords
from edc_notification.model_mixins import NotificationModelMixin
Expand All @@ -17,7 +17,7 @@

from .. import Action
from ..choices import ACTION_STATUS, PRIORITY
from ..exceptions import SubjectDoesNotExist
from ..exceptions import ActionItemStatusError, SubjectDoesNotExist
from ..identifiers import ActionIdentifier
from ..site_action_items import site_action_items
from .action_type import ActionType
Expand Down Expand Up @@ -166,6 +166,17 @@ def save(self, *args, **kwargs):
self.reference_model = self.action_type.reference_model
self.related_reference_model = self.action_type.related_reference_model
self.instructions = self.action_type.instructions
else:
if (
self.status in [NEW, CANCELLED]
and django_apps.get_model(self.reference_model)
.objects.filter(action_identifier=self.action_identifier)
.exists()
):
raise ActionItemStatusError(
"Invalid action item status. Reference model exists. "
f"Got `{self.get_status_display()}`. Perhaps catch this in the form"
)
super().save(*args, **kwargs)

def natural_key(self) -> tuple[str]:
Expand Down
4 changes: 2 additions & 2 deletions edc_action_item/site_action_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from edc_prn.prn import Prn
from edc_prn.site_prn_forms import AlreadyRegistered as PrnAlreadyRegistered
from edc_prn.site_prn_forms import site_prn_forms
from edc_sites import InvalidSiteError
from edc_sites import InvalidSiteForSubjectError
from edc_sites.valid_site_for_subject_or_raise import valid_site_for_subject_or_raise

from .create_or_update_action_type import create_or_update_action_type
Expand Down Expand Up @@ -120,7 +120,7 @@ def get_by_model(self, model=None) -> Type[Action] | Type[ActionWithNotification
def get_show_link_to_add_actions(self, subject_identifier: str = None) -> list[Wrapper]:
try:
valid_site_for_subject_or_raise(subject_identifier)
except InvalidSiteError:
except InvalidSiteForSubjectError:
wrappers = []
else:
names = [v.name for v in self.registry.values() if v.show_link_to_add]
Expand Down
23 changes: 21 additions & 2 deletions edc_action_item/tests/tests/test_action_item.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from django.core.exceptions import ObjectDoesNotExist
from django.db.models.deletion import ProtectedError
from django.test import TestCase
from edc_constants.constants import CLOSED, NEW, OPEN
from edc_constants.constants import CANCELLED, CLOSED, NEW, OPEN

from edc_action_item.action import Action
from edc_action_item.create_or_update_action_type import create_or_update_action_type
from edc_action_item.exceptions import SubjectDoesNotExist
from edc_action_item.exceptions import ActionItemStatusError, SubjectDoesNotExist
from edc_action_item.forms import ActionItemForm
from edc_action_item.get_action_type import get_action_type
from edc_action_item.models import ActionItem, ActionType
Expand Down Expand Up @@ -318,3 +318,22 @@ def test_reopens_children_on_change(self):
self.assertEqual(form_two.action_item.status, OPEN)
self.assertEqual(form_three.action_item.status, OPEN)
self.assertEqual(form_one.action_item.status, CLOSED)

def test_cannot_cancel_if_reference_obj_exists(self):
site_action_items.register(FormOneAction)
site_action_items.register(FormTwoAction)
site_action_items.register(FormThreeAction)

form_one_action = FormOneAction(subject_identifier=self.subject_identifier)
form_one = FormOne.objects.create(
subject_identifier=self.subject_identifier,
action_identifier=form_one_action.action_identifier,
)
form_one.f1 = "blah"
form_one.save()

form_one.refresh_from_db()
self.assertEqual(form_one.action_item.status, CLOSED)

form_one.action_item.status = CANCELLED
self.assertRaises(ActionItemStatusError, form_one.action_item.save)

0 comments on commit 1b0a23f

Please sign in to comment.