Skip to content

Commit

Permalink
Merge pull request #1075 from maykinmedia/feature/2149-show-new-answe…
Browse files Browse the repository at this point in the history
…r-to-question

✨ [#2149] Display new answer header for mijn vragen list
  • Loading branch information
alextreme authored Mar 15, 2024
2 parents 9397863 + c2aa742 commit 761f3e2
Show file tree
Hide file tree
Showing 23 changed files with 442 additions and 87 deletions.
31 changes: 28 additions & 3 deletions src/open_inwoner/accounts/views/contactmoments.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
from open_inwoner.openklant.api_models import KlantContactMoment
from open_inwoner.openklant.clients import build_client
from open_inwoner.openklant.constants import Status
from open_inwoner.openklant.models import ContactFormSubject
from open_inwoner.openklant.models import ContactFormSubject, KlantContactMomentAnswer
from open_inwoner.openklant.views.contactform import ContactFormView
from open_inwoner.openklant.wrap import (
contactmoment_has_new_answer,
fetch_klantcontactmoment,
fetch_klantcontactmomenten,
get_fetch_parameters,
get_kcm_answer_mapping,
)
from open_inwoner.openzaak.clients import build_client as build_client_openzaak
from open_inwoner.utils.mixins import PaginationMixin
Expand Down Expand Up @@ -71,12 +73,17 @@ class KCMDict(TypedDict):
onderwerp: str
status: str
antwoord: str
new_answer_available: bool


class KlantContactMomentBaseView(
CommonPageMixin, BaseBreadcrumbMixin, KlantContactMomentAccessMixin, TemplateView
):
def get_kcm_data(self, kcm: KlantContactMoment) -> KCMDict:
def get_kcm_data(
self,
kcm: KlantContactMoment,
local_kcm_mapping: Optional[dict[str, KlantContactMomentAnswer]] = None,
) -> KCMDict:
data = {
"registered_date": kcm.contactmoment.registratiedatum,
"channel": kcm.contactmoment.kanaal.title(),
Expand All @@ -87,6 +94,9 @@ def get_kcm_data(self, kcm: KlantContactMoment) -> KCMDict:
"type": kcm.contactmoment.type,
"status": Status.safe_label(kcm.contactmoment.status, _("Onbekend")),
"antwoord": kcm.contactmoment.antwoord,
"new_answer_available": contactmoment_has_new_answer(
kcm.contactmoment, local_kcm_mapping=local_kcm_mapping
),
}

# replace e_suite_subject_code with OIP configured subject, if applicable
Expand Down Expand Up @@ -155,7 +165,15 @@ def get_context_data(self, **kwargs):
kcms = fetch_klantcontactmomenten(
**get_fetch_parameters(self.request, use_vestigingsnummer=True)
)
ctx["contactmomenten"] = [self.get_kcm_data(kcm) for kcm in kcms]
ctx["contactmomenten"] = [
self.get_kcm_data(
kcm,
local_kcm_mapping=get_kcm_answer_mapping(
[kcm.contactmoment for kcm in kcms], self.request.user
),
)
for kcm in kcms
]
paginator_dict = self.paginate_with_context(ctx["contactmomenten"])
ctx.update(paginator_dict)
return ctx
Expand Down Expand Up @@ -188,6 +206,13 @@ def get_context_data(self, **kwargs):
if not kcm:
raise Http404()

local_kcm, is_created = KlantContactMomentAnswer.objects.get_or_create( # noqa
user=self.request.user, contactmoment_url=kcm.contactmoment.url
)
if not local_kcm.is_seen:
local_kcm.is_seen = True
local_kcm.save()

if client := build_client("contactmomenten"):
zaken_client = build_client_openzaak("zaak")
ocm = client.retrieve_objectcontactmoment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"vorigContactmoment": null,
"volgendContactmoment": null,
"bronorganisatie": "WwXGZrg",
"registratiedatum": "2022-05-15T23:12:13+00:00",
"registratiedatum": "2030-05-15T23:12:13+00:00",
"voorkeurskanaal": "xyz",
"voorkeurstaal": "vzT",
"tekst": "Mag ik mijn garage veranderen in een kantoor?\n\n",
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,6 @@
"previous": null,
"next": null,
"results": [
{
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-cccccccccccc",
"url": "https://contactmomenten.nl/api/v1/klantcontactmomenten/aaaaaaaa-aaaa-aaaa-aaaa-cccccccccccc",
"klant": "https://klanten.nl/api/v1/klant/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"contactmoment": "https://contactmomenten.nl/api/v1/contactmoment/aaaaaaaa-aaaa-aaaa-aaaa-bbbbbbbbbbbb",
"rol": "gesprekspartner",
"gelezen": true
},
{
"uuid": "aaaaaaaa-aaaa-aaaa-aaaa-ccccccccccc2",
"url": "https://contactmomenten.nl/api/v1/klantcontactmomenten/aaaaaaaa-aaaa-aaaa-aaaa-ccccccccccc2",
Expand Down

This file was deleted.

This file was deleted.

12 changes: 11 additions & 1 deletion src/open_inwoner/cms/cases/views/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@

from open_inwoner.openklant.clients import build_client as build_client_openklant
from open_inwoner.openklant.models import OpenKlantConfig
from open_inwoner.openklant.wrap import get_fetch_parameters
from open_inwoner.openklant.wrap import (
contactmoment_has_new_answer,
get_fetch_parameters,
get_kcm_answer_mapping,
)
from open_inwoner.openzaak.api_models import Status, StatusType, Zaak
from open_inwoner.openzaak.clients import (
ZakenClient,
Expand Down Expand Up @@ -155,6 +159,12 @@ def get_context_data(self, **kwargs):
questions = [ocm.contactmoment for ocm in objectcontactmomenten]
questions.sort(key=lambda q: q.registratiedatum, reverse=True)

kcm_answer_mapping = get_kcm_answer_mapping(questions, self.request.user)
for question in questions:
question.new_answer_available = contactmoment_has_new_answer(
question, kcm_answer_mapping
)

statustypen = []
if catalogi_client := build_client_openzaak("catalogi"):
statustypen = catalogi_client.fetch_status_types_no_cache(
Expand Down
6 changes: 4 additions & 2 deletions src/open_inwoner/components/templatetags/file_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from filer.models.filemodels import File

from open_inwoner.cms.cases.views.status import SimpleFile
from open_inwoner.utils.time import is_new
from open_inwoner.utils.time import instance_is_new

register = template.Library()

Expand Down Expand Up @@ -147,7 +147,9 @@ def file(file, **kwargs):
created = getattr(file, "created", None)
kwargs["created"] = created

if is_new(file, "created", datetime.timedelta(days=settings.DOCUMENT_RECENT_DAYS)):
if instance_is_new(
file, "created", datetime.timedelta(days=settings.DOCUMENT_RECENT_DAYS)
):
kwargs["recently_added"] = True

if "show_download" not in kwargs:
Expand Down
3 changes: 3 additions & 0 deletions src/open_inwoner/conf/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,9 @@
# recent documents: created/added no longer than n days in the past
DOCUMENT_RECENT_DAYS = config("DOCUMENT_RECENT_DAYS", default=1)

# recent answers to contactmomenten: no longer than n days in the past
CONTACTMOMENT_NEW_DAYS = config("CONTACTMOMENT_NEW_DAYS", default=7)

#
# Maykin 2FA
#
Expand Down
4 changes: 4 additions & 0 deletions src/open_inwoner/conf/fixtures/django-admin-index.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@
"openklant",
"openklantconfig"
],
[
"openklant",
"klantcontactmomentanswer"
],
[
"openzaak",
"catalogusconfig"
Expand Down
14 changes: 13 additions & 1 deletion src/open_inwoner/openklant/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ordered_model.admin import OrderedInlineModelAdminMixin, OrderedTabularInline
from solo.admin import SingletonModelAdmin

from .models import ContactFormSubject, OpenKlantConfig
from .models import ContactFormSubject, KlantContactMomentAnswer, OpenKlantConfig


class ContactFormSubjectInlineAdmin(OrderedTabularInline):
Expand Down Expand Up @@ -70,3 +70,15 @@ class OpenKlantConfigAdmin(OrderedInlineModelAdminMixin, SingletonModelAdmin):
},
),
]


@admin.register(KlantContactMomentAnswer)
class KlantContactMomentAnswerAdmin(admin.ModelAdmin):
search_fields = [
"user__first_name",
"user__last_name",
"user__email",
"contactmoment_url",
]
list_filter = ["is_seen"]
list_display = ["user", "contactmoment_url", "is_seen"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 4.2.10 on 2024-03-15 15:19

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("openklant", "0008_openklantconfig_use_rsin_for_innnnpid_query_parameter"),
]

operations = [
migrations.CreateModel(
name="KlantContactMomentAnswer",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"contactmoment_url",
models.URLField(max_length=1000, verbose_name="ContactMoment URL"),
),
(
"is_seen",
models.BooleanField(
default=False,
help_text="Whether or not the user has seen the answer",
verbose_name="Is seen",
),
),
(
"user",
models.ForeignKey(
help_text="This is the user that asked the question to which this is an answer.",
on_delete=django.db.models.deletion.CASCADE,
related_name="contactmoment_answers",
to=settings.AUTH_USER_MODEL,
verbose_name="User",
),
),
],
options={
"verbose_name": "KlantContactMoment",
"verbose_name_plural": "KlantContactMomenten",
"unique_together": {("user", "contactmoment_url")},
},
),
]
25 changes: 25 additions & 0 deletions src/open_inwoner/openklant/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,28 @@ class Meta(OrderedModel.Meta):

def __str__(self):
return self.subject


class KlantContactMomentAnswer(models.Model):
user = models.ForeignKey(
"accounts.User",
verbose_name=_("User"),
on_delete=models.CASCADE,
related_name="contactmoment_answers",
help_text=_(
"This is the user that asked the question to which this is an answer."
),
)
contactmoment_url = models.URLField(
verbose_name=_("ContactMoment URL"), max_length=1000
)
is_seen = models.BooleanField(
verbose_name=_("Is seen"),
help_text=_("Whether or not the user has seen the answer"),
default=False,
)

class Meta:
verbose_name = _("KlantContactMoment")
verbose_name_plural = _("KlantContactMomenten")
unique_together = [["user", "contactmoment_url"]]
3 changes: 2 additions & 1 deletion src/open_inwoner/openklant/tests/data.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,9 @@ def __init__(self):
type="SomeType",
kanaal="MAIL",
status=Status.afgehandeld,
antwoord="",
antwoord="foo",
onderwerp="e_suite_subject_code",
registratiedatum="2022-01-01T12:00:00Z",
)
self.contactmoment2 = generate_oas_component_cached(
"cmc",
Expand Down
9 changes: 9 additions & 0 deletions src/open_inwoner/openklant/tests/factories.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import factory
from zgw_consumers.api_models.base import factory as zgw_factory

from open_inwoner.accounts.tests.factories import UserFactory
from open_inwoner.openklant.api_models import ContactMoment


Expand All @@ -14,3 +15,11 @@ class Meta:

def make_contactmoment(contact_moment_data: dict):
return zgw_factory(ContactMoment, contact_moment_data)


class KlantContactMomentAnswerFactory(factory.django.DjangoModelFactory):
class Meta:
model = "openklant.KlantContactMomentAnswer"

contactmoment_url = factory.Faker("url")
user = factory.SubFactory(UserFactory)
Loading

0 comments on commit 761f3e2

Please sign in to comment.