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

✨ [#183] added afgehandeld_op field for internetaken #185

Merged
merged 4 commits into from
May 22, 2024
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
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .actoren import * # noqa
from .digitaal_adres import * # noqa
from .internetaken import * # noqa
from .klantcontacten import * # noqa
from .partijen import * # noqa
2 changes: 1 addition & 1 deletion src/openklant/components/klantinteracties/admin/actoren.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
from django.contrib import admin
from django.utils.translation import gettext_lazy as _

from ..admin.internezaken import InterneTaakInlineAdmin
from ..models.actoren import (
Actor,
ActorKlantcontact,
GeautomatiseerdeActor,
Medewerker,
OrganisatorischeEenheid,
)
from .internetaken import InterneTaakInlineAdmin


class GeautomatiseerdeActorInlineAdmin(admin.StackedInline):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class InterneTaakAdmin(admin.ModelAdmin):
"nummer",
"status",
"toegewezen_op",
"afgehandeld_op",
)
list_filter = (
"actor",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

from openklant.components.klantinteracties.models.actoren import ActorKlantcontact

from ..admin.internezaken import InterneTaakInlineAdmin
from ..models.klantcontacten import Betrokkene, Bijlage, Klantcontact, Onderwerpobject
from .internetaken import InterneTaakInlineAdmin


class BetrokkeneInlineAdmin(admin.StackedInline):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
)
from openklant.components.klantinteracties.api.validators import internetaak_exists
from openklant.components.klantinteracties.models.actoren import Actor
from openklant.components.klantinteracties.models.constants import Taakstatus
from openklant.components.klantinteracties.models.internetaken import InterneTaak
from openklant.components.klantinteracties.models.klantcontacten import Klantcontact

Expand Down Expand Up @@ -58,6 +59,7 @@ class Meta:
"toelichting",
"status",
"toegewezen_op",
"afgehandeld_op",
)
extra_kwargs = {
"uuid": {"read_only": True},
Expand All @@ -68,6 +70,23 @@ class Meta:
},
}

def validate(self, attrs):
status = attrs.get("status", None)
if status is None and self.instance is not None:
status = self.instance.status

if attrs.get("afgehandeld_op") and status != Taakstatus.verwerkt:
raise serializers.ValidationError(
{
"afgehandeld_op": _(
"De Internetaak kan geen afgehandeld op datum bevatten "
"als de status niet op '{verwerkt}' staat."
).format(verwerkt=Taakstatus.verwerkt)
}
)

return super().validate(attrs)

@transaction.atomic
def create(self, validated_data):
actor_uuid = str(validated_data.pop("actor").get("uuid"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from freezegun import freeze_time
from rest_framework import status
from vng_api_common.tests import reverse

from openklant.components.klantinteracties.models.internetaken import InterneTaak
from openklant.components.klantinteracties.models.tests.factories.actoren import (
ActorFactory,
)
Expand Down Expand Up @@ -36,6 +38,7 @@ def test_read_internetaak(self):

self.assertEqual(response.status_code, status.HTTP_200_OK)

@freeze_time("2024-01-01T12:00:00Z")
def test_create_internetaak(self):
actor = ActorFactory.create()
klantcontact = KlantcontactFactory.create()
Expand Down Expand Up @@ -65,6 +68,9 @@ def test_create_internetaak(self):
self.assertEqual(response_data["gevraagdeHandeling"], "gevraagdeHandeling")
self.assertEqual(response_data["toelichting"], "toelichting")
self.assertEqual(response_data["status"], "verwerkt")
self.assertTrue(
InterneTaak.objects.filter(afgehandeld_op="2024-01-01T12:00:00Z").exists()
)

with self.subTest("auto_generate_max_nummer_plus_one"):
data["nummer"] = ""
Expand Down Expand Up @@ -98,6 +104,87 @@ def test_create_internetaak(self):
"Het maximaal aantal tekens is bereikt.",
)

@freeze_time("2024-01-01T12:00:00Z")
def test_create_internetaak_with_status_te_verwerken(self):
actor = ActorFactory.create()
klantcontact = KlantcontactFactory.create()

list_url = reverse("klantinteracties:internetaak-list")
data = {
"toegewezenAanActor": {"uuid": str(actor.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact.uuid)},
"nummer": "1312312312",
"gevraagdeHandeling": "gevraagdeHandeling",
"toelichting": "toelichting",
"status": "te_verwerken",
}

response = self.client.post(list_url, data)

self.assertEqual(response.status_code, status.HTTP_201_CREATED)

response_data = response.json()

self.assertEqual(response_data["toegewezenAanActor"]["uuid"], str(actor.uuid))
self.assertEqual(
response_data["aanleidinggevendKlantcontact"]["uuid"],
str(klantcontact.uuid),
)
self.assertEqual(response_data["nummer"], "1312312312")
self.assertEqual(response_data["gevraagdeHandeling"], "gevraagdeHandeling")
self.assertEqual(response_data["toelichting"], "toelichting")
self.assertEqual(response_data["status"], "te_verwerken")
self.assertFalse(
InterneTaak.objects.filter(afgehandeld_op="2024-01-01T12:00:00Z").exists()
)

with self.subTest("validate_afgehandeld_op_error_with_te_verwerken_status"):
del data["nummer"]
data["afgehandeldOp"] = "2024-01-01T01:00:00Z"
response = self.client.post(list_url, data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
response_data = response.json()
self.assertEqual(response_data["invalidParams"][0]["name"], "afgehandeldOp")
self.assertEqual(
response_data["invalidParams"][0]["reason"],
"De Internetaak kan geen afgehandeld op datum bevatten als de status niet op 'verwerkt' staat.",
)

def test_create_internetaak_with_afgehandeld_op_date(self):
actor = ActorFactory.create()
klantcontact = KlantcontactFactory.create()

list_url = reverse("klantinteracties:internetaak-list")
data = {
"toegewezenAanActor": {"uuid": str(actor.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact.uuid)},
"nummer": "1312312312",
"gevraagdeHandeling": "gevraagdeHandeling",
"toelichting": "toelichting",
"status": "verwerkt",
"afgehandeldOp": "2024-01-01T01:00:00Z",
}

response = self.client.post(list_url, data)

self.assertEqual(response.status_code, status.HTTP_201_CREATED)

response_data = response.json()

self.assertEqual(response_data["toegewezenAanActor"]["uuid"], str(actor.uuid))
self.assertEqual(
response_data["aanleidinggevendKlantcontact"]["uuid"],
str(klantcontact.uuid),
)
self.assertEqual(response_data["nummer"], "1312312312")
self.assertEqual(response_data["gevraagdeHandeling"], "gevraagdeHandeling")
self.assertEqual(response_data["toelichting"], "toelichting")
self.assertEqual(response_data["status"], "verwerkt")
self.assertTrue(
InterneTaak.objects.filter(afgehandeld_op="2024-01-01T01:00:00Z").exists()
)

@freeze_time("2024-01-01T12:00:00Z")
def test_update_internetaak(self):
actor, actor2 = ActorFactory.create_batch(2)
klantcontact, klantcontact2 = KlantcontactFactory.create_batch(2)
Expand All @@ -107,7 +194,7 @@ def test_update_internetaak(self):
nummer="1237713712",
gevraagde_handeling="gevraagdeHandeling",
toelichting="toelichting",
status="verwerkt",
status="te_verwerken",
)
detail_url = reverse(
"klantinteracties:internetaak-detail",
Expand All @@ -123,15 +210,15 @@ def test_update_internetaak(self):
self.assertEqual(data["nummer"], "1237713712")
self.assertEqual(data["gevraagdeHandeling"], "gevraagdeHandeling")
self.assertEqual(data["toelichting"], "toelichting")
self.assertEqual(data["status"], "verwerkt")
self.assertEqual(data["status"], "te_verwerken")

data = {
"toegewezenAanActor": {"uuid": str(actor2.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact2.uuid)},
"nummer": "9999999999",
"gevraagdeHandeling": "changed",
"toelichting": "changed",
"status": "te_verwerken",
"status": "verwerkt",
}

response = self.client.put(detail_url, data)
Expand All @@ -147,7 +234,80 @@ def test_update_internetaak(self):
self.assertEqual(data["nummer"], "9999999999")
self.assertEqual(data["gevraagdeHandeling"], "changed")
self.assertEqual(data["toelichting"], "changed")
self.assertEqual(data["status"], "te_verwerken")
self.assertEqual(data["status"], "verwerkt")
self.assertTrue(
InterneTaak.objects.filter(afgehandeld_op="2024-01-01T12:00:00Z").exists()
)

with freeze_time("2024-01-01T12:20:00Z") and self.subTest(
"updating_on_later_date_does_not_change_afgehandeld_op"
):
response = self.client.put(detail_url, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(
InterneTaak.objects.filter(
afgehandeld_op="2024-01-01T12:20:00Z"
).exists()
)

with self.subTest(
"changing_status_back_to_te_verwerken_clears_afgehandeld_op_field"
):
data = {
"toegewezenAanActor": {"uuid": str(actor2.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact2.uuid)},
"gevraagdeHandeling": "changed",
"status": "te_verwerken",
}
response = self.client.put(detail_url, data)
data = response.json()
self.assertEqual(data["status"], "te_verwerken")
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(InterneTaak.objects.count(), 1)
self.assertIsNone(InterneTaak.objects.first().afgehandeld_op)

with self.subTest("with_afgehandeld_op_data_value"):
data = {
"toegewezenAanActor": {"uuid": str(actor2.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact2.uuid)},
"gevraagdeHandeling": "changed",
"status": "verwerkt",
"afgehandeldOp": "2024-01-01T01:00:00Z",
}
response = self.client.put(detail_url, data)
self.assertEqual(response.status_code, status.HTTP_200_OK)
data = response.json()

self.assertEqual(data["toegewezenAanActor"]["uuid"], str(actor2.uuid))
self.assertEqual(
data["aanleidinggevendKlantcontact"]["uuid"], str(klantcontact2.uuid)
)
self.assertEqual(data["nummer"], "9999999999")
self.assertEqual(data["gevraagdeHandeling"], "changed")
self.assertEqual(data["toelichting"], "changed")
self.assertEqual(data["status"], "verwerkt")
self.assertTrue(
InterneTaak.objects.filter(
afgehandeld_op="2024-01-01T01:00:00Z"
).exists()
)

with self.subTest("validate_afgehandeld_op_error_with_te_verwerken_status"):
data = {
"toegewezenAanActor": {"uuid": str(actor2.uuid)},
"aanleidinggevendKlantcontact": {"uuid": str(klantcontact2.uuid)},
"gevraagdeHandeling": "changed",
"status": "te_verwerken",
"afgehandeldOp": "2024-01-01T01:00:00Z",
}
response = self.client.put(detail_url, data)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
data = response.json()
self.assertEqual(data["invalidParams"][0]["name"], "afgehandeldOp")
self.assertEqual(
data["invalidParams"][0]["reason"],
"De Internetaak kan geen afgehandeld op datum bevatten als de status niet op 'verwerkt' staat.",
)

def test_partial_update_internetaak(self):
actor = ActorFactory.create()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.11 on 2024-04-24 08:45

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("klantinteracties", "0014_alter_internetaak_status"),
]

operations = [
migrations.AddField(
model_name="internetaak",
name="afgehandeld_op",
field=models.DateTimeField(
blank=True,
help_text="Datum en tijdstip wanneer de interne taak was afgehandeld: EXPERIMENTEEL.",
null=True,
verbose_name="afgehandeld op",
),
),
]
16 changes: 16 additions & 0 deletions src/openklant/components/klantinteracties/models/internetaken.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.core.validators import validate_integer
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from openklant.components.utils.number_generator import number_generator
Expand Down Expand Up @@ -71,13 +72,28 @@ class InterneTaak(models.Model):
auto_now_add=True,
blank=False,
)
afgehandeld_op = models.DateTimeField(
_("afgehandeld op"),
help_text=_(
"Datum en tijdstip wanneer de interne taak was afgehandeld: EXPERIMENTEEL."
),
editable=True,
blank=True,
null=True,
)

class Meta:
verbose_name = _("interne taak")
verbose_name_plural = _("interne taken")

def save(self, *args, **kwargs):
number_generator(self, InterneTaak)
if self.afgehandeld_op is None:
if self.status == Taakstatus.verwerkt:
self.afgehandeld_op = timezone.now()
else:
if self.status == Taakstatus.te_verwerken:
self.afgehandeld_op = None
return super().save(*args, **kwargs)

def __str__(self):
Expand Down
15 changes: 15 additions & 0 deletions src/openklant/components/klantinteracties/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3263,8 +3263,16 @@ components:
readOnly: true
description: Datum en tijdstip waarop de interne taak aan een actor werd
toegewezen.
afgehandeldOp:
type: string
format: date-time
readOnly: true
nullable: true
description: 'Datum en tijdstip wanneer de interne taak was afgehandeld:
EXPERIMENTEEL.'
required:
- aanleidinggevendKlantcontact
- afgehandeldOp
- gevraagdeHandeling
- status
- toegewezenAanActor
Expand Down Expand Up @@ -4405,6 +4413,13 @@ components:
readOnly: true
description: Datum en tijdstip waarop de interne taak aan een actor werd
toegewezen.
afgehandeldOp:
type: string
format: date-time
readOnly: true
nullable: true
description: 'Datum en tijdstip wanneer de interne taak was afgehandeld:
EXPERIMENTEEL.'
PatchedKlantcontact:
type: object
properties:
Expand Down
Loading