From 4a8c2d20a192e1d94fe452722e010739807383d2 Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Tue, 10 Oct 2023 17:58:32 +0200 Subject: [PATCH 1/5] :card_file_box: [#61] created Partij, Persoon, ContactPersoon and Organisatie models --- .../components/klantinteracties/__init__.py | 0 .../components/klantinteracties/apps.py | 5 + .../components/klantinteracties/constants.py | 60 +++ .../migrations/0001_initial.py | 371 ++++++++++++++++++ .../klantinteracties/migrations/__init__.py | 0 .../components/klantinteracties/models.py | 340 ++++++++++++++++ src/openklant/conf/base.py | 1 + 7 files changed, 777 insertions(+) create mode 100644 src/openklant/components/klantinteracties/__init__.py create mode 100644 src/openklant/components/klantinteracties/apps.py create mode 100644 src/openklant/components/klantinteracties/constants.py create mode 100644 src/openklant/components/klantinteracties/migrations/0001_initial.py create mode 100644 src/openklant/components/klantinteracties/migrations/__init__.py create mode 100644 src/openklant/components/klantinteracties/models.py diff --git a/src/openklant/components/klantinteracties/__init__.py b/src/openklant/components/klantinteracties/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/openklant/components/klantinteracties/apps.py b/src/openklant/components/klantinteracties/apps.py new file mode 100644 index 00000000..6de18f55 --- /dev/null +++ b/src/openklant/components/klantinteracties/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class KlantinteractiesConfig(AppConfig): + name = "openklant.components.klantinteracties" diff --git a/src/openklant/components/klantinteracties/constants.py b/src/openklant/components/klantinteracties/constants.py new file mode 100644 index 00000000..88a2ba0b --- /dev/null +++ b/src/openklant/components/klantinteracties/constants.py @@ -0,0 +1,60 @@ +from django.utils.translation import gettext_lazy as _ + +from djchoices import ChoiceItem, DjangoChoices + + +# TODO: change value when document gets updated: +# https://vng-realisatie.github.io/klantinteracties/informatiemodel/gegevenswoordenboek#detail_class_Model_Initiator +class Initiator(DjangoChoices): + gemeente = ChoiceItem("gemeente", _("Gemeente")) + klant = ChoiceItem("klant", _("Klant")) + vertegenwoordiger = ChoiceItem("vertegenwoordiger", _("Vertegenwoordiger")) + + +class Taakstatus(DjangoChoices): + te_verwerken = ChoiceItem("te_verwerken", _("Het verzoek is afgehandeld.")) + verwerkt = ChoiceItem("verwerkt", _("Het verzoek id buiten behandeling gesteld.")) + + +class SoortBezoekadres(DjangoChoices): + binnenlands_adres = ChoiceItem("binnenlands_adres", _("Binnenlands adres")) + buitenlands_adres = ChoiceItem("binnenlands_adres", _("Buitenlands adres")) + + +class AanduidingBijHuisnummer(DjangoChoices): + bij = ChoiceItem("bij", _("Bij")) + tegenover = ChoiceItem("tegenover", _("Tegenover")) + + +class SoortCorrespondentieadres(DjangoChoices): + postbusnummer = ChoiceItem("postbusnummer", _("Postbusnummer")) + antwoordnummer = ChoiceItem("antwoordnummer", _("Antwoordnummer")) + binnenlands_adres = ChoiceItem("binnenlands_adres", _("Binnenlands adres")) + buitenlands_adres = ChoiceItem("buitenlands_adres", _("Buitenlands adres")) + + +class SoortActor(DjangoChoices): + medewerker = ChoiceItem("medewerker", _("Medewerker")) + geautomatiseerde_actor = ChoiceItem( + "geautomatiseerde_actor", _("Geautomatiseerde actor") + ) + organisatorische_eenheid = ChoiceItem( + "organisatorische_eenheid", _("Organisatorische eenheid") + ) + + +class SoortInhoudsdeel(DjangoChoices): + informatieobject = ChoiceItem("informatieobject", _("Informatieobject")) + overig_object = ChoiceItem("overig_object", _("Overig object")) + tekst = ChoiceItem("tekst", _("Tekst")) + + +class SoortPartij(DjangoChoices): + persoon = ChoiceItem("persoon", _("Persoon")) + organisatie = ChoiceItem("organisatie", _("Organisatie")) + contactpersoon = ChoiceItem("contactpersoon", _("Contactpersoon")) + + +class Klantcontrol(DjangoChoices): + vertegenwoordiger = ChoiceItem("vertegenwoordiger", _("Vertegenwoordiger")) + klant = ChoiceItem("klant", _("Klant")) diff --git a/src/openklant/components/klantinteracties/migrations/0001_initial.py b/src/openklant/components/klantinteracties/migrations/0001_initial.py new file mode 100644 index 00000000..2d333eb1 --- /dev/null +++ b/src/openklant/components/klantinteracties/migrations/0001_initial.py @@ -0,0 +1,371 @@ +# Generated by Django 3.2.18 on 2023-10-10 15:54 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + initial = True + + dependencies = [] + + operations = [ + migrations.CreateModel( + name="Partij", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + help_text="Unieke (technische) identificatiecode van de partij.", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "nummer", + models.CharField( + help_text="Uniek identificerend nummer dat tijdens communicatie tussen mensen kan worden gebruikt om de specifieke partij aan te duiden.", + max_length=10, + validators=[django.core.validators.validate_integer], + verbose_name="Nummer", + ), + ), + ( + "interne_notitie", + models.CharField( + blank=True, + help_text="Mededelingen, aantekeningen of bijzonderheden over de partij, bedoeld voor intern gebruik.", + max_length=1000, + verbose_name="Interne notitie", + ), + ), + ( + "soort_partij", + models.CharField( + choices=[ + ("persoon", "Persoon"), + ("organisatie", "Organisatie"), + ("contactpersoon", "Contactpersoon"), + ], + help_text="Geeft aan van welke specifieke soort partij sprake is.", + max_length=14, + verbose_name="Soort partij", + ), + ), + ( + "indicatie_geheimhouding", + models.BooleanField( + help_text="Geeft aan of de verstrekker van partijgegevens heeft aangegeven dat deze gegevens als geheim beschouwd moeten worden.", + verbose_name="Indicatie geheimhouding", + ), + ), + ( + "voorkeurskanaal", + models.CharField( + blank=True, + help_text="Kanaal dat de partij bij voorkeur gebruikt voor contact met de gemeente.", + max_length=50, + verbose_name="Voorkeurskanaal", + ), + ), + ( + "voorkeurstaal", + models.CharField( + blank=True, + help_text="Taal waarin de partij bij voorkeur contact heeft met de gemeente.", + max_length=255, + verbose_name="Voorkeurstaal", + ), + ), + ( + "indicatie_actief", + models.BooleanField( + help_text="Geeft aan of de contactgegevens van de partij nog gebruikt morgen worden om contact op te nemen. Gegevens van niet-actieve partijen mogen hiervoor niet worden gebruikt.", + verbose_name="Indicatie actief", + ), + ), + ( + "correspondentieadres_nummeraanduiding_id", + models.UUIDField( + blank=True, + help_text="Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen.", + null=True, + unique=True, + verbose_name="Nummeraanduiding ID", + ), + ), + ( + "correspondentieadres_adresregel1", + models.CharField( + blank=True, + help_text="Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 1", + ), + ), + ( + "correspondentieadres_adresregel2", + models.CharField( + blank=True, + help_text="Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 2", + ), + ), + ( + "correspondentieadres_adresregel3", + models.CharField( + blank=True, + help_text="Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 3", + ), + ), + ( + "correspondentieadres_land", + models.CharField( + blank=True, + help_text="Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) aangeeft alwaar de ingeschrevene verblijft.", + max_length=4, + validators=[ + django.core.validators.MinLengthValidator(limit_value=4), + django.core.validators.validate_integer, + ], + verbose_name="Land", + ), + ), + ( + "bezoekadres_nummeraanduiding_id", + models.UUIDField( + blank=True, + help_text="Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen.", + null=True, + unique=True, + verbose_name="Nummeraanduiding ID", + ), + ), + ( + "bezoekadres_adresregel1", + models.CharField( + blank=True, + help_text="Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 1", + ), + ), + ( + "bezoekadres_adresregel2", + models.CharField( + blank=True, + help_text="Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 2", + ), + ), + ( + "bezoekadres_adresregel3", + models.CharField( + blank=True, + help_text="Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 3", + ), + ), + ( + "bezoekadres_land", + models.CharField( + blank=True, + help_text="Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) aangeeft alwaar de ingeschrevene verblijft.", + max_length=4, + validators=[ + django.core.validators.MinLengthValidator(limit_value=4), + django.core.validators.validate_integer, + ], + verbose_name="Land", + ), + ), + ], + options={ + "verbose_name": "partij", + "verbose_name_plural": "partijen", + }, + ), + migrations.CreateModel( + name="Persoon", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "contactnaam_voorletters", + models.CharField( + help_text="Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen de beginletter gecombineerd met de tweede letter van een voornaam.", + max_length=10, + verbose_name="Voorletters", + ), + ), + ( + "contactnaam_voornaam", + models.CharField( + blank=True, + help_text="De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Voornaam", + ), + ), + ( + "contactnaam_voorvoegsel_achternaam", + models.CharField( + blank=True, + help_text="Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=10, + verbose_name="Voorvoegsel achternaam", + ), + ), + ( + "contactnaam_achternaam", + models.CharField( + blank=True, + help_text="Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Achternaam", + ), + ), + ( + "partij", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="persoon", + to="klantinteracties.partij", + verbose_name="Partij", + ), + ), + ], + options={ + "verbose_name": "persoon", + "verbose_name_plural": "personen", + }, + ), + migrations.CreateModel( + name="Organisatie", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "naam", + models.CharField( + blank=True, + help_text="Naam van de organisatie.", + max_length=200, + verbose_name="Naam", + ), + ), + ( + "partij", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="organisatie", + to="klantinteracties.partij", + verbose_name="Partij", + ), + ), + ], + options={ + "verbose_name": "organisatie", + "verbose_name_plural": "organisaties", + }, + ), + migrations.CreateModel( + name="Contactpersoon", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "contactnaam_voorletters", + models.CharField( + help_text="Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen de beginletter gecombineerd met de tweede letter van een voornaam.", + max_length=10, + verbose_name="Voorletters", + ), + ), + ( + "contactnaam_voornaam", + models.CharField( + blank=True, + help_text="De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Voornaam", + ), + ), + ( + "contactnaam_voorvoegsel_achternaam", + models.CharField( + blank=True, + help_text="Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=10, + verbose_name="Voorvoegsel achternaam", + ), + ), + ( + "contactnaam_achternaam", + models.CharField( + blank=True, + help_text="Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Achternaam", + ), + ), + ( + "organisatie", + models.ForeignKey( + help_text="De organisatie waar een contactpersoon voor werkt.", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="contact_personen", + to="klantinteracties.organisatie", + verbose_name="Organistatie", + ), + ), + ( + "partij", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="contact_persoon", + to="klantinteracties.partij", + verbose_name="Partij", + ), + ), + ], + options={ + "verbose_name": "contact persoon", + "verbose_name_plural": "contact personen", + }, + ), + ] diff --git a/src/openklant/components/klantinteracties/migrations/__init__.py b/src/openklant/components/klantinteracties/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/openklant/components/klantinteracties/models.py b/src/openklant/components/klantinteracties/models.py new file mode 100644 index 00000000..7de24ec1 --- /dev/null +++ b/src/openklant/components/klantinteracties/models.py @@ -0,0 +1,340 @@ +import uuid + +from django.core.validators import MinLengthValidator, validate_integer +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from vng_api_common.descriptors import GegevensGroepType + +from .constants import SoortPartij + + +class Partij(models.Model): + id = models.UUIDField( + primary_key=True, + unique=True, + default=uuid.uuid4, + help_text=_("Unieke (technische) identificatiecode van de partij."), + ) + nummer = models.CharField( + _("Nummer"), + help_text=_( + "Uniek identificerend nummer dat tijdens communicatie tussen mensen kan " + "worden gebruikt om de specifieke partij aan te duiden." + ), + validators=[validate_integer], + max_length=10, + ) + interne_notitie = models.CharField( + _("Interne notitie"), + help_text=_( + "Mededelingen, aantekeningen of bijzonderheden over de partij, bedoeld voor intern gebruik." + ), + max_length=1000, + blank=True, + ) + soort_partij = models.CharField( + _("Soort partij"), + help_text=_("Geeft aan van welke specifieke soort partij sprake is."), + max_length=14, + choices=SoortPartij.choices, + ) + indicatie_geheimhouding = models.BooleanField( + _("Indicatie geheimhouding"), + help_text=_( + "Geeft aan of de verstrekker van partijgegevens heeft aangegeven dat " + "deze gegevens als geheim beschouwd moeten worden." + ), + ) + voorkeurskanaal = models.CharField( + _("Voorkeurskanaal"), + help_text=_( + "Kanaal dat de partij bij voorkeur gebruikt voor contact met de gemeente." + ), + max_length=50, + blank=True, + ) + voorkeurstaal = models.CharField( + _("Voorkeurstaal"), + help_text=_( + "Taal waarin de partij bij voorkeur contact heeft met de gemeente." + ), + max_length=255, + blank=True, + ) + indicatie_actief = models.BooleanField( + _("Indicatie actief"), + help_text=_( + "Geeft aan of de contactgegevens van de partij nog gebruikt morgen worden om contact op te nemen. " + "Gegevens van niet-actieve partijen mogen hiervoor niet worden gebruikt." + ), + ) + + # Correspondentieadres model fields: + correspondentieadres_nummeraanduiding_id = models.UUIDField( + verbose_name=_("Nummeraanduiding ID"), + help_text=_( + "Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen." + ), + unique=True, + blank=True, + null=True, + ) + correspondentieadres_adresregel1 = models.CharField( + _("Adresregel 1"), + help_text=_( + "Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_adresregel2 = models.CharField( + _("Adresregel 2"), + help_text=_( + "Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_adresregel3 = models.CharField( + _("Adresregel 3"), + help_text=_( + "Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_land = models.CharField( + _("Land"), + help_text=_( + "Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) " + "aangeeft alwaar de ingeschrevene verblijft." + ), + validators=[ + MinLengthValidator(limit_value=4), + validate_integer, + ], + max_length=4, + blank=True, + ) + + # Bezoekadres model fields: + bezoekadres_nummeraanduiding_id = models.UUIDField( + verbose_name=_("Nummeraanduiding ID"), + help_text=_( + "Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen." + ), + unique=True, + blank=True, + null=True, + ) + bezoekadres_adresregel1 = models.CharField( + _("Adresregel 1"), + help_text=_( + "Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_adresregel2 = models.CharField( + _("Adresregel 2"), + help_text=_( + "Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_adresregel3 = models.CharField( + _("Adresregel 3"), + help_text=_( + "Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_land = models.CharField( + _("Land"), + help_text=_( + "Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) " + "aangeeft alwaar de ingeschrevene verblijft." + ), + validators=[ + MinLengthValidator(limit_value=4), + validate_integer, + ], + max_length=4, + blank=True, + ) + + # Group types: + correspondentieadres = GegevensGroepType( + { + "nummeraanduiding id": correspondentieadres_nummeraanduiding_id, + "adresregel 1": correspondentieadres_adresregel1, + "adresregel 2": correspondentieadres_adresregel2, + "adresregel 3": correspondentieadres_adresregel3, + "land": correspondentieadres_land, + }, + ) + bezoekadres = GegevensGroepType( + { + "nummeraanduiding id": bezoekadres_nummeraanduiding_id, + "adresregel 1": bezoekadres_adresregel1, + "adresregel 2": bezoekadres_adresregel2, + "adresregel 3": bezoekadres_adresregel3, + "land": bezoekadres_land, + } + ) + + class Meta: + verbose_name = _("partij") + verbose_name_plural = _("partijen") + + +class Organisatie(models.Model): + partij = models.ForeignKey( + Partij, + on_delete=models.CASCADE, + verbose_name=_("Partij"), + related_name="organisatie", + null=True, + ) + naam = models.CharField( + _("Naam"), + help_text=_("Naam van de organisatie."), + max_length=200, + blank=True, + ) + + class Meta: + verbose_name = _("organisatie") + verbose_name_plural = _("organisaties") + + def __str__(self) -> str: + return self.naam + + +class Persoon(models.Model): + partij = models.ForeignKey( + Partij, + on_delete=models.CASCADE, + verbose_name=_("Partij"), + related_name="persoon", + null=True, + ) + contactnaam_voorletters = models.CharField( + _("Voorletters"), + help_text=_( + "Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen " + "de beginletter gecombineerd met de tweede letter van een voornaam." + ), + max_length=10, + ) + contactnaam_voornaam = models.CharField( + _("Voornaam"), + help_text=_( + "De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + contactnaam_voorvoegsel_achternaam = models.CharField( + _("Voorvoegsel achternaam"), + help_text=_( + "Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon " + "wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=10, + blank=True, + ) + contactnaam_achternaam = models.CharField( + _("Achternaam"), + help_text=_( + "Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + + Contactnaam = GegevensGroepType( + { + "voorletters": contactnaam_voorletters, + "voornaam": contactnaam_voornaam, + "voorvoegsel achternaam": contactnaam_voorvoegsel_achternaam, + "achternaam": contactnaam_achternaam, + } + ) + + class Meta: + verbose_name = _("persoon") + verbose_name_plural = _("personen") + + def __str__(self) -> str: + return self.contactnaam_voorletters + + +class Contactpersoon(models.Model): + partij = models.ForeignKey( + Partij, + on_delete=models.CASCADE, + verbose_name=_("Partij"), + related_name="contact_persoon", + null=True, + ) + organisatie = models.ForeignKey( + Organisatie, + on_delete=models.CASCADE, + verbose_name=_("Organistatie"), + related_name="contact_personen", + help_text=_("De organisatie waar een contactpersoon voor werkt."), + null=True, + ) + contactnaam_voorletters = models.CharField( + _("Voorletters"), + help_text=_( + "Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen " + "de beginletter gecombineerd met de tweede letter van een voornaam." + ), + max_length=10, + ) + contactnaam_voornaam = models.CharField( + _("Voornaam"), + help_text=_( + "De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + contactnaam_voorvoegsel_achternaam = models.CharField( + _("Voorvoegsel achternaam"), + help_text=_( + "Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon " + "wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=10, + blank=True, + ) + contactnaam_achternaam = models.CharField( + _("Achternaam"), + help_text=_( + "Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + + Contactnaam = GegevensGroepType( + { + "voorletters": contactnaam_voorletters, + "voornaam": contactnaam_voornaam, + "voorvoegsel achternaam": contactnaam_voorvoegsel_achternaam, + "achternaam": contactnaam_achternaam, + } + ) + + class Meta: + verbose_name = _("contact persoon") + verbose_name_plural = _("contact personen") + + def __str__(self) -> str: + return self.contactnaam_voorletters diff --git a/src/openklant/conf/base.py b/src/openklant/conf/base.py index 1dec9277..ab846f2e 100644 --- a/src/openklant/conf/base.py +++ b/src/openklant/conf/base.py @@ -137,6 +137,7 @@ "openklant.utils", "openklant.components.klanten", "openklant.components.contactmomenten", + "openklant.components.klantinteracties", ] MIDDLEWARE = [ From 35338255ef0d757a0cf007312857fbd5ae8f96f8 Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Wed, 11 Oct 2023 09:16:50 +0200 Subject: [PATCH 2/5] :card_file_box: [#62] changed models file into folder and added klantcontacten --- .../migrations/0002_klantcontact.py | 110 ++++++++++++++++++ .../klantinteracties/models/__init__.py | 2 + .../{ => models}/constants.py | 0 .../klantinteracties/models/klantcontacten.py | 89 ++++++++++++++ .../{models.py => models/partijen.py} | 0 5 files changed, 201 insertions(+) create mode 100644 src/openklant/components/klantinteracties/migrations/0002_klantcontact.py create mode 100644 src/openklant/components/klantinteracties/models/__init__.py rename src/openklant/components/klantinteracties/{ => models}/constants.py (100%) create mode 100644 src/openklant/components/klantinteracties/models/klantcontacten.py rename src/openklant/components/klantinteracties/{models.py => models/partijen.py} (100%) diff --git a/src/openklant/components/klantinteracties/migrations/0002_klantcontact.py b/src/openklant/components/klantinteracties/migrations/0002_klantcontact.py new file mode 100644 index 00000000..2d61aa75 --- /dev/null +++ b/src/openklant/components/klantinteracties/migrations/0002_klantcontact.py @@ -0,0 +1,110 @@ +# Generated by Django 3.2.18 on 2023-10-10 17:54 + +import django.core.validators +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("klantinteracties", "0001_initial"), + ] + + operations = [ + migrations.CreateModel( + name="Klantcontact", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + help_text="Unieke (technische) identificatiecode van de betrokkene bij klantcontact.", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "nummer", + models.CharField( + help_text="Uniek identificerend nummer dat tijdens communicatie tussen mensen kan worden gebruikt om het specifieke klantcontact aan te duiden.", + max_length=10, + validators=[django.core.validators.validate_integer], + verbose_name="Nummer", + ), + ), + ( + "kanaal", + models.CharField( + help_text="Communicatiekanaal dat bij het klantcontact werd gebruikt.", + max_length=50, + verbose_name="Kanaal", + ), + ), + ( + "onderwerp", + models.CharField( + help_text="Datgene waarover het klantcontact ging.", + max_length=200, + verbose_name="Onderwerp", + ), + ), + ( + "inhoud", + models.CharField( + blank=True, + help_text="Informatie die tijdens het klantcontact werd overgebracht of uitgewisseld, voor zover die voor betrokkenen of actoren relevant is.", + max_length=1000, + verbose_name="Inhoud", + ), + ), + ( + "initiator", + models.CharField( + choices=[ + ("gemeente", "Gemeente"), + ("klant", "Klant"), + ("vertegenwoordiger", "Vertegenwoordiger"), + ], + help_text="Degene die het klantcontact initieerde.", + max_length=17, + verbose_name="Initiator", + ), + ), + ( + "indicatie_contact_gelukt", + models.BooleanField( + help_text="Geeft, indien bekend, aan of de poging contact tussen de gemeente en inwoner(s) of organisatie(s) tot stand te brengen succesvol was.", + null=True, + verbose_name="Indicatie contact gelukt", + ), + ), + ( + "taal", + models.CharField( + help_text="Taal die bij het klantcontact werd gesproken of geschreven.", + max_length=255, + verbose_name="Taal", + ), + ), + ( + "vertrouwelijk", + models.BooleanField( + help_text="Geeft aan of onderwerp, inhoud en kenmerken van het klantcontact vertrouwelijk moeten worden behandeld.", + verbose_name="Vertrouwelijk", + ), + ), + ( + "plaatsgevonden_op", + models.DateTimeField( + help_text="Datum en tijdstip waarop het klantontact plaatsvond. Als het klantcontact een gesprek betrof, is dit het moment waarop het gesprek begon. Als het klantcontact verzending of ontvangst van informatie betrof, is dit bij benadering het moment waarop informatie door gemeente verzonden of ontvangen werd.", + verbose_name="Plaatsgevonden op", + ), + ), + ], + options={ + "verbose_name": "klantcontact", + "verbose_name_plural": "klantcontacten", + }, + ), + ] diff --git a/src/openklant/components/klantinteracties/models/__init__.py b/src/openklant/components/klantinteracties/models/__init__.py new file mode 100644 index 00000000..e87e3b09 --- /dev/null +++ b/src/openklant/components/klantinteracties/models/__init__.py @@ -0,0 +1,2 @@ +from .klantcontacten import * # noqa +from .partijen import * # noqa diff --git a/src/openklant/components/klantinteracties/constants.py b/src/openklant/components/klantinteracties/models/constants.py similarity index 100% rename from src/openklant/components/klantinteracties/constants.py rename to src/openklant/components/klantinteracties/models/constants.py diff --git a/src/openklant/components/klantinteracties/models/klantcontacten.py b/src/openklant/components/klantinteracties/models/klantcontacten.py new file mode 100644 index 00000000..c6e5a904 --- /dev/null +++ b/src/openklant/components/klantinteracties/models/klantcontacten.py @@ -0,0 +1,89 @@ +import uuid + +from django.core.validators import validate_integer +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from .constants import Initiator + + +class Klantcontact(models.Model): + id = models.UUIDField( + primary_key=True, + unique=True, + default=uuid.uuid4, + help_text=_( + "Unieke (technische) identificatiecode van de betrokkene bij klantcontact." + ), + ) + # TODO: add fk to Actor + # TODO: add fk to Onderwerpobject + # TODO: add fk to Inhoudsobject + nummer = models.CharField( + _("Nummer"), + help_text=_( + "Uniek identificerend nummer dat tijdens communicatie tussen mensen kan " + "worden gebruikt om het specifieke klantcontact aan te duiden." + ), + validators=[validate_integer], + max_length=10, + ) + kanaal = models.CharField( + _("Kanaal"), + help_text=_("Communicatiekanaal dat bij het klantcontact werd gebruikt."), + max_length=50, + ) + onderwerp = models.CharField( + _("Onderwerp"), + help_text=_("Datgene waarover het klantcontact ging."), + max_length=200, + ) + inhoud = models.CharField( + _("Inhoud"), + help_text=_( + "Informatie die tijdens het klantcontact werd overgebracht of uitgewisseld, " + "voor zover die voor betrokkenen of actoren relevant is." + ), + max_length=1000, + blank=True, + ) + initiator = models.CharField( + _("Initiator"), + help_text=_("Degene die het klantcontact initieerde."), + choices=Initiator.choices, + max_length=17, + ) + indicatie_contact_gelukt = models.BooleanField( + _("Indicatie contact gelukt"), + help_text=( + "Geeft, indien bekend, aan of de poging contact tussen de gemeente " + "en inwoner(s) of organisatie(s) tot stand te brengen succesvol was." + ), + null=True, + ) + taal = models.CharField( + _("Taal"), + help_text=_("Taal die bij het klantcontact werd gesproken of geschreven."), + max_length=255, + ) + vertrouwelijk = models.BooleanField( + _("Vertrouwelijk"), + help_text=_( + "Geeft aan of onderwerp, inhoud en kenmerken van het klantcontact vertrouwelijk moeten worden behandeld." + ), + ) + # TODO: does this field require auto_now? + plaatsgevonden_op = models.DateTimeField( + _("Plaatsgevonden op"), + help_text=_( + "Datum en tijdstip waarop het klantontact plaatsvond. Als het klantcontact " + "een gesprek betrof, is dit het moment waarop het gesprek begon. " + "Als het klantcontact verzending of ontvangst van informatie betrof, " + "is dit bij benadering het moment waarop informatie door gemeente verzonden of ontvangen werd." + ), + blank=False, + ) + + class Meta: + verbose_name = _("klantcontact") + verbose_name_plural = _("klantcontacten") diff --git a/src/openklant/components/klantinteracties/models.py b/src/openklant/components/klantinteracties/models/partijen.py similarity index 100% rename from src/openklant/components/klantinteracties/models.py rename to src/openklant/components/klantinteracties/models/partijen.py From b21cfec39127c5d703a7bf4b33e418fc7ca259cf Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Thu, 12 Oct 2023 11:29:43 +0200 Subject: [PATCH 3/5] :card_file_box: [#63] added model Betrokkene and added foreignkeys relations --- .../migrations/0003_betrokkene.py | 211 ++++++++++++++++++ .../klantinteracties/models/klantcontacten.py | 204 ++++++++++++++++- .../klantinteracties/models/partijen.py | 15 ++ 3 files changed, 428 insertions(+), 2 deletions(-) create mode 100644 src/openklant/components/klantinteracties/migrations/0003_betrokkene.py diff --git a/src/openklant/components/klantinteracties/migrations/0003_betrokkene.py b/src/openklant/components/klantinteracties/migrations/0003_betrokkene.py new file mode 100644 index 00000000..876e9253 --- /dev/null +++ b/src/openklant/components/klantinteracties/migrations/0003_betrokkene.py @@ -0,0 +1,211 @@ +# Generated by Django 3.2.18 on 2023-10-11 10:26 + +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("klantinteracties", "0002_klantcontact"), + ] + + operations = [ + migrations.CreateModel( + name="Betrokkene", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + help_text="Unieke (technische) identificatiecode van de betrokkene bij klantcontact.", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "rol", + models.CharField( + choices=[ + ("vertegenwoordiger", "Vertegenwoordiger"), + ("klant", "Klant"), + ], + help_text="Rol die de betrokkene bij klantcontact tijdens dat contact vervulde.", + max_length=17, + verbose_name="Rol", + ), + ), + ( + "organisatienaam", + models.CharField( + blank=True, + help_text="Naam van de organisatie waarmee de betrokkene bij klantcontact een relatie had.", + max_length=200, + verbose_name="Organisatienaam", + ), + ), + ( + "contactnaam_voorletters", + models.CharField( + help_text="Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen de beginletter gecombineerd met de tweede letter van een voornaam.", + max_length=10, + verbose_name="Voorletters", + ), + ), + ( + "contactnaam_voornaam", + models.CharField( + blank=True, + help_text="De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Voornaam", + ), + ), + ( + "contactnaam_voorvoegsel_achternaam", + models.CharField( + blank=True, + help_text="Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=10, + verbose_name="Voorvoegsel achternaam", + ), + ), + ( + "contactnaam_achternaam", + models.CharField( + blank=True, + help_text="Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente.", + max_length=200, + verbose_name="Achternaam", + ), + ), + ( + "correspondentieadres_nummeraanduiding_id", + models.UUIDField( + blank=True, + help_text="Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen.", + null=True, + unique=True, + verbose_name="Nummeraanduiding ID", + ), + ), + ( + "correspondentieadres_adresregel1", + models.CharField( + blank=True, + help_text="Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 1", + ), + ), + ( + "correspondentieadres_adresregel2", + models.CharField( + blank=True, + help_text="Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 2", + ), + ), + ( + "correspondentieadres_adresregel3", + models.CharField( + blank=True, + help_text="Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 3", + ), + ), + ( + "correspondentieadres_land", + models.CharField( + blank=True, + help_text="Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) aangeeft alwaar de ingeschrevene verblijft.", + max_length=4, + validators=[ + django.core.validators.MinLengthValidator(limit_value=4), + django.core.validators.validate_integer, + ], + verbose_name="Land", + ), + ), + ( + "bezoekadres_nummeraanduiding_id", + models.UUIDField( + blank=True, + help_text="Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen.", + null=True, + unique=True, + verbose_name="Nummeraanduiding ID", + ), + ), + ( + "bezoekadres_adresregel1", + models.CharField( + blank=True, + help_text="Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 1", + ), + ), + ( + "bezoekadres_adresregel2", + models.CharField( + blank=True, + help_text="Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 2", + ), + ), + ( + "bezoekadres_adresregel3", + models.CharField( + blank=True, + help_text="Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen.", + max_length=80, + verbose_name="Adresregel 3", + ), + ), + ( + "bezoekadres_land", + models.CharField( + blank=True, + help_text="Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) aangeeft alwaar de ingeschrevene verblijft.", + max_length=4, + validators=[ + django.core.validators.MinLengthValidator(limit_value=4), + django.core.validators.validate_integer, + ], + verbose_name="Land", + ), + ), + ( + "klantcontact", + models.ForeignKey( + help_text="'Klantcontact' had 'Betrokkene bij klantcontact'", + on_delete=django.db.models.deletion.CASCADE, + related_name="betrokkene", + to="klantinteracties.klantcontact", + verbose_name="Klantcontact", + ), + ), + ], + options={ + "verbose_name": "betrokkene bij klantcontact", + }, + ), + migrations.AddField( + model_name="partij", + name="betrokkene", + field=models.ForeignKey( + help_text="'Betrokkene bij klantcontact' was 'Partij'", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="partijen", + to="klantinteracties.betrokkene", + verbose_name="Betrokkene", + ), + ), + ] diff --git a/src/openklant/components/klantinteracties/models/klantcontacten.py b/src/openklant/components/klantinteracties/models/klantcontacten.py index c6e5a904..5e1648a3 100644 --- a/src/openklant/components/klantinteracties/models/klantcontacten.py +++ b/src/openklant/components/klantinteracties/models/klantcontacten.py @@ -1,10 +1,12 @@ import uuid -from django.core.validators import validate_integer +from django.core.validators import MinLengthValidator, validate_integer from django.db import models from django.utils.translation import gettext_lazy as _ -from .constants import Initiator +from vng_api_common.descriptors import GegevensGroepType + +from .constants import Initiator, Klantcontrol class Klantcontact(models.Model): @@ -87,3 +89,201 @@ class Klantcontact(models.Model): class Meta: verbose_name = _("klantcontact") verbose_name_plural = _("klantcontacten") + + +class Betrokkene(models.Model): + id = models.UUIDField( + primary_key=True, + unique=True, + default=uuid.uuid4, + help_text=_( + "Unieke (technische) identificatiecode van de betrokkene bij klantcontact." + ), + ) + klantcontact = models.ForeignKey( + Klantcontact, + on_delete=models.CASCADE, + verbose_name=_("Klantcontact"), + related_name="betrokkene", + help_text=_("'Klantcontact' had 'Betrokkene bij klantcontact'"), + null=False, + ) + # TODO: Add fk to Digital adres + rol = models.CharField( + _("Rol"), + help_text=_( + "Rol die de betrokkene bij klantcontact tijdens dat contact vervulde." + ), + choices=Klantcontrol.choices, + max_length=17, + ) + organisatienaam = models.CharField( + _("Organisatienaam"), + help_text=_( + "Naam van de organisatie waarmee de betrokkene bij klantcontact een relatie had." + ), + max_length=200, + blank=True, + ) + + # Contactnaam model fields: + contactnaam_voorletters = models.CharField( + _("Voorletters"), + help_text=_( + "Een afkorting van de voornamen. Meestal de beginletter, maar in sommige gevallen " + "de beginletter gecombineerd met de tweede letter van een voornaam." + ), + max_length=10, + ) + contactnaam_voornaam = models.CharField( + _("Voornaam"), + help_text=_( + "De voornaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + contactnaam_voorvoegsel_achternaam = models.CharField( + _("Voorvoegsel achternaam"), + help_text=_( + "Een eventueel voorvoegsel dat hoort bij de achternaam die de persoon " + "wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=10, + blank=True, + ) + contactnaam_achternaam = models.CharField( + _("Achternaam"), + help_text=_( + "Een achternaam die de persoon wil gebruiken tijdens communicatie met de gemeente." + ), + max_length=200, + blank=True, + ) + + # Correspondentieadres model fields: + correspondentieadres_nummeraanduiding_id = models.UUIDField( + verbose_name=_("Nummeraanduiding ID"), + help_text=_( + "Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen." + ), + unique=True, + blank=True, + null=True, + ) + correspondentieadres_adresregel1 = models.CharField( + _("Adresregel 1"), + help_text=_( + "Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_adresregel2 = models.CharField( + _("Adresregel 2"), + help_text=_( + "Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_adresregel3 = models.CharField( + _("Adresregel 3"), + help_text=_( + "Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + correspondentieadres_land = models.CharField( + _("Land"), + help_text=_( + "Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) " + "aangeeft alwaar de ingeschrevene verblijft." + ), + validators=[ + MinLengthValidator(limit_value=4), + validate_integer, + ], + max_length=4, + blank=True, + ) + + # Bezoekadres model fields: + bezoekadres_nummeraanduiding_id = models.UUIDField( + verbose_name=_("Nummeraanduiding ID"), + help_text=_( + "Identificatie van het adres bij de Basisregistratie Adressen en Gebouwen." + ), + unique=True, + blank=True, + null=True, + ) + bezoekadres_adresregel1 = models.CharField( + _("Adresregel 1"), + help_text=_( + "Eerste deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_adresregel2 = models.CharField( + _("Adresregel 2"), + help_text=_( + "Tweede deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_adresregel3 = models.CharField( + _("Adresregel 3"), + help_text=_( + "Derde deel van het adres dat niet voorkomt in de Basisregistratie Adressen en Gebouwen." + ), + max_length=80, + blank=True, + ) + bezoekadres_land = models.CharField( + _("Land"), + help_text=_( + "Een code, opgenomen in Tabel 34, Landentabel, die het land (buiten Nederland) " + "aangeeft alwaar de ingeschrevene verblijft." + ), + validators=[ + MinLengthValidator(limit_value=4), + validate_integer, + ], + max_length=4, + blank=True, + ) + + # Group types: + Contactnaam = GegevensGroepType( + { + "voorletters": contactnaam_voorletters, + "voornaam": contactnaam_voornaam, + "voorvoegsel achternaam": contactnaam_voorvoegsel_achternaam, + "achternaam": contactnaam_achternaam, + } + ) + correspondentieadres = GegevensGroepType( + { + "nummeraanduiding id": correspondentieadres_nummeraanduiding_id, + "adresregel 1": correspondentieadres_adresregel1, + "adresregel 2": correspondentieadres_adresregel2, + "adresregel 3": correspondentieadres_adresregel3, + "land": correspondentieadres_land, + }, + ) + bezoekadres = GegevensGroepType( + { + "nummeraanduiding id": bezoekadres_nummeraanduiding_id, + "adresregel 1": bezoekadres_adresregel1, + "adresregel 2": bezoekadres_adresregel2, + "adresregel 3": bezoekadres_adresregel3, + "land": bezoekadres_land, + } + ) + + class Meta: + verbose_name = _("betrokkene bij klantcontact") diff --git a/src/openklant/components/klantinteracties/models/partijen.py b/src/openklant/components/klantinteracties/models/partijen.py index 7de24ec1..714d3d44 100644 --- a/src/openklant/components/klantinteracties/models/partijen.py +++ b/src/openklant/components/klantinteracties/models/partijen.py @@ -7,6 +7,7 @@ from vng_api_common.descriptors import GegevensGroepType from .constants import SoortPartij +from .klantcontacten import Betrokkene class Partij(models.Model): @@ -16,6 +17,14 @@ class Partij(models.Model): default=uuid.uuid4, help_text=_("Unieke (technische) identificatiecode van de partij."), ) + betrokkene = models.ForeignKey( + Betrokkene, + on_delete=models.CASCADE, + verbose_name=_("Betrokkene"), + related_name="partijen", + help_text=_("'Betrokkene bij klantcontact' was 'Partij'"), + null=True, + ) nummer = models.CharField( _("Nummer"), help_text=_( @@ -222,6 +231,8 @@ class Persoon(models.Model): related_name="persoon", null=True, ) + + # Contactnaam model fields: contactnaam_voorletters = models.CharField( _("Voorletters"), help_text=_( @@ -256,6 +267,7 @@ class Persoon(models.Model): blank=True, ) + # Group types: Contactnaam = GegevensGroepType( { "voorletters": contactnaam_voorletters, @@ -289,6 +301,8 @@ class Contactpersoon(models.Model): help_text=_("De organisatie waar een contactpersoon voor werkt."), null=True, ) + + # Contactnaam model fields: contactnaam_voorletters = models.CharField( _("Voorletters"), help_text=_( @@ -323,6 +337,7 @@ class Contactpersoon(models.Model): blank=True, ) + # Group types: Contactnaam = GegevensGroepType( { "voorletters": contactnaam_voorletters, From 7d76a17694010092fd151ee59dc2c2f942bc5d2d Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Thu, 12 Oct 2023 12:11:17 +0200 Subject: [PATCH 4/5] :card_file_box: [#64] added digitaal adres model field --- .../migrations/0004_digitaaladres.py | 80 +++++++++++++++++++ .../klantinteracties/models/__init__.py | 1 + .../klantinteracties/models/digitaal_adres.py | 39 +++++++++ .../klantinteracties/models/klantcontacten.py | 10 ++- .../klantinteracties/models/partijen.py | 9 +++ 5 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 src/openklant/components/klantinteracties/migrations/0004_digitaaladres.py create mode 100644 src/openklant/components/klantinteracties/models/digitaal_adres.py diff --git a/src/openklant/components/klantinteracties/migrations/0004_digitaaladres.py b/src/openklant/components/klantinteracties/migrations/0004_digitaaladres.py new file mode 100644 index 00000000..886e5bce --- /dev/null +++ b/src/openklant/components/klantinteracties/migrations/0004_digitaaladres.py @@ -0,0 +1,80 @@ +# Generated by Django 3.2.18 on 2023-10-11 15:47 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("klantinteracties", "0003_betrokkene"), + ] + + operations = [ + migrations.CreateModel( + name="DigitaalAdres", + fields=[ + ( + "id", + models.UUIDField( + default=uuid.uuid4, + help_text="Unieke (technische) identificatiecode van het digitaal adres.", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "soort_digitaal_adres", + models.CharField( + help_text="Typering van het digitale adres die aangeeft via welk(e) kanaal of kanalen met dit adres contact kan worden opgenomen.", + max_length=254, + verbose_name="Soort digitaal adres", + ), + ), + ( + "adres", + models.CharField( + help_text="Digitaal adres waarmee een persoon of organisatie bereikt kan worden.", + max_length=80, + verbose_name="Adres", + ), + ), + ( + "omschrijving", + models.CharField( + help_text="Omschrijving van het digitaal adres.", + max_length=40, + verbose_name="Omschrijving", + ), + ), + ], + options={ + "verbose_name": "digitaal adres", + }, + ), + migrations.AddField( + model_name="betrokkene", + name="digitaal_adres", + field=models.ForeignKey( + help_text="'Digitaal Adres' had 'Betrokkene bij klantcontact'", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="partijen", + to="klantinteracties.digitaaladres", + verbose_name="Digitaal adres", + ), + ), + migrations.AddField( + model_name="partij", + name="digitaal_adres", + field=models.ForeignKey( + help_text="'Digitaal Adres' was 'Partij'", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="digitale_adressen", + to="klantinteracties.digitaaladres", + verbose_name="Digitaal adres", + ), + ), + ] diff --git a/src/openklant/components/klantinteracties/models/__init__.py b/src/openklant/components/klantinteracties/models/__init__.py index e87e3b09..7167c60a 100644 --- a/src/openklant/components/klantinteracties/models/__init__.py +++ b/src/openklant/components/klantinteracties/models/__init__.py @@ -1,2 +1,3 @@ +from .digitaal_adres import * # noqa from .klantcontacten import * # noqa from .partijen import * # noqa diff --git a/src/openklant/components/klantinteracties/models/digitaal_adres.py b/src/openklant/components/klantinteracties/models/digitaal_adres.py new file mode 100644 index 00000000..12f172c6 --- /dev/null +++ b/src/openklant/components/klantinteracties/models/digitaal_adres.py @@ -0,0 +1,39 @@ +import uuid + +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class DigitaalAdres(models.Model): + id = models.UUIDField( + primary_key=True, + unique=True, + default=uuid.uuid4, + help_text=_("Unieke (technische) identificatiecode van het digitaal adres."), + ) + soort_digitaal_adres = models.CharField( + _("Soort digitaal adres"), + help_text=_( + "Typering van het digitale adres die aangeeft via welk(e) kanaal of kanalen " + "met dit adres contact kan worden opgenomen." + ), + max_length=254, + ) + adres = models.CharField( + _("Adres"), + help_text=_( + "Digitaal adres waarmee een persoon of organisatie bereikt kan worden." + ), + max_length=80, + ) + omschrijving = models.CharField( + _("Omschrijving"), + help_text=_("Omschrijving van het digitaal adres."), + max_length=40, + ) + + class Meta: + verbose_name = _("digitaal adres") + + def __str__(self): + return self.adres diff --git a/src/openklant/components/klantinteracties/models/klantcontacten.py b/src/openklant/components/klantinteracties/models/klantcontacten.py index 5e1648a3..d97ab1d9 100644 --- a/src/openklant/components/klantinteracties/models/klantcontacten.py +++ b/src/openklant/components/klantinteracties/models/klantcontacten.py @@ -7,6 +7,7 @@ from vng_api_common.descriptors import GegevensGroepType from .constants import Initiator, Klantcontrol +from .digitaal_adres import DigitaalAdres class Klantcontact(models.Model): @@ -108,7 +109,14 @@ class Betrokkene(models.Model): help_text=_("'Klantcontact' had 'Betrokkene bij klantcontact'"), null=False, ) - # TODO: Add fk to Digital adres + digitaal_adres = models.ForeignKey( + DigitaalAdres, + on_delete=models.CASCADE, + verbose_name=_("Digitaal adres"), + related_name="partijen", + help_text=_("'Digitaal Adres' had 'Betrokkene bij klantcontact'"), + null=True, + ) rol = models.CharField( _("Rol"), help_text=_( diff --git a/src/openklant/components/klantinteracties/models/partijen.py b/src/openklant/components/klantinteracties/models/partijen.py index 714d3d44..dce84a9d 100644 --- a/src/openklant/components/klantinteracties/models/partijen.py +++ b/src/openklant/components/klantinteracties/models/partijen.py @@ -7,6 +7,7 @@ from vng_api_common.descriptors import GegevensGroepType from .constants import SoortPartij +from .digitaal_adres import DigitaalAdres from .klantcontacten import Betrokkene @@ -25,6 +26,14 @@ class Partij(models.Model): help_text=_("'Betrokkene bij klantcontact' was 'Partij'"), null=True, ) + digitaal_adres = models.ForeignKey( + DigitaalAdres, + on_delete=models.CASCADE, + verbose_name=_("Digitaal adres"), + related_name="digitale_adressen", + help_text=_("'Digitaal Adres' was 'Partij'"), + null=True, + ) nummer = models.CharField( _("Nummer"), help_text=_( From c76a686a91cfcfd8c18d227637ca37f4ca6d18c3 Mon Sep 17 00:00:00 2001 From: bart-maykin Date: Thu, 12 Oct 2023 17:14:10 +0200 Subject: [PATCH 5/5] :card_file_box: [#65] added actor model fields --- .../klantinteracties/migrations/0005_actor.py | 275 ++++++++++++++++++ .../klantinteracties/models/__init__.py | 1 + .../klantinteracties/models/actoren.py | 157 ++++++++++ .../klantinteracties/models/klantcontacten.py | 22 +- .../klantinteracties/models/mixins.py | 52 ++++ 5 files changed, 506 insertions(+), 1 deletion(-) create mode 100644 src/openklant/components/klantinteracties/migrations/0005_actor.py create mode 100644 src/openklant/components/klantinteracties/models/actoren.py create mode 100644 src/openklant/components/klantinteracties/models/mixins.py diff --git a/src/openklant/components/klantinteracties/migrations/0005_actor.py b/src/openklant/components/klantinteracties/migrations/0005_actor.py new file mode 100644 index 00000000..fcdc1cc8 --- /dev/null +++ b/src/openklant/components/klantinteracties/migrations/0005_actor.py @@ -0,0 +1,275 @@ +# Generated by Django 3.2.18 on 2023-10-13 13:39 + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + dependencies = [ + ("klantinteracties", "0004_digitaaladres"), + ] + + operations = [ + migrations.CreateModel( + name="Actor", + fields=[ + ( + "actoridentifcator_objecttype", + models.CharField( + help_text="Type van het object, bijvoorbeeld: 'INGESCHREVEN NATUURLIJK PERSOON'.", + max_length=200, + verbose_name="Objecttype", + ), + ), + ( + "actoridentifcator_soort_object_id", + models.CharField( + help_text="Naam van de eigenschap die het object identificeert, bijvoorbeeld: 'Burgerservicenummer'.", + max_length=200, + verbose_name="Soort Object ID", + ), + ), + ( + "actoridentifcator_object_id", + models.CharField( + help_text="Waarde van de eigenschap die het object identificeert, bijvoorbeeld: '123456788'.", + max_length=200, + verbose_name="Object ID", + ), + ), + ( + "actoridentifcator_register", + models.CharField( + help_text="Binnen het landschap van registers unieke omschrijving van het register waarin het object is geregistreerd, bijvoorbeeld: 'BRP'.", + max_length=200, + verbose_name="Object ID", + ), + ), + ( + "id", + models.UUIDField( + default=uuid.uuid4, + help_text="Unieke (technische) identificatiecode van de actor.", + primary_key=True, + serialize=False, + unique=True, + ), + ), + ( + "naam", + models.CharField( + help_text="Naam van de actor.", + max_length=200, + verbose_name="Naam", + ), + ), + ( + "soort_actor", + models.CharField( + choices=[ + ("medewerker", "Medewerker"), + ("geautomatiseerde_actor", "Geautomatiseerde actor"), + ("organisatorische_eenheid", "Organisatorische eenheid"), + ], + help_text="Geeft aan van welke specifieke soort actor sprake is.", + max_length=24, + verbose_name="Soort actor", + ), + ), + ( + "indicatie_actief", + models.BooleanField( + help_text="Geeft aan of aan de actor nog betrokken mag worden bij nieuwe klantcontacten. Voor niet-actieve is dit niet toegestaan.", + verbose_name="Indicatie actief", + ), + ), + ], + options={ + "verbose_name": "actor", + "verbose_name_plural": "actoren", + }, + ), + migrations.AddField( + model_name="klantcontact", + name="klantcontact", + field=models.ForeignKey( + blank=True, + help_text="De persoon of organisatie die betrokken was bij een klantcontact.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + related_name="klantcontacten", + to="klantinteracties.klantcontact", + verbose_name="Klant contact", + ), + ), + migrations.CreateModel( + name="OrganisatorischeEenheid", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "omschrijving", + models.CharField( + blank=True, + help_text="Omschrijving van de geautomatiseerde actor.", + max_length=200, + verbose_name="Omschrijving", + ), + ), + ( + "email", + models.EmailField( + blank=True, + help_text="Elektronisch postadres waaronder de MEDEWERKER in de regel bereikbaar is.", + max_length=254, + verbose_name="email address", + ), + ), + ( + "faxnummer", + models.CharField( + help_text="Faxnummer waaronder de organisatorische eenheid in de regel bereikbaar is.", + max_length=20, + verbose_name="Faxnummer", + ), + ), + ( + "telefoonnummer", + models.CharField( + help_text="Telefoonnummer waaronder de MEDEWERKER in de regel bereikbaar is.", + max_length=20, + verbose_name="Telefoonnummer", + ), + ), + ( + "actor", + models.ForeignKey( + help_text="'GeautomatiseerdeActor' was 'Actor'", + on_delete=django.db.models.deletion.CASCADE, + related_name="organisatorische_eenheid", + to="klantinteracties.actor", + verbose_name="Actor", + ), + ), + ], + options={ + "verbose_name": "organisatorische eenheid", + }, + ), + migrations.CreateModel( + name="Medewerker", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "functie", + models.CharField( + help_text="Functie van de geautomatiseerde actor of beschrijving van de werkzaamheden die deze uitvoert.", + max_length=40, + verbose_name="Functie", + ), + ), + ( + "email", + models.EmailField( + blank=True, + help_text="Elektronisch postadres waaronder de MEDEWERKER in de regel bereikbaar is.", + max_length=254, + verbose_name="email address", + ), + ), + ( + "telefoonnummer", + models.CharField( + help_text="Telefoonnummer waaronder de MEDEWERKER in de regel bereikbaar is.", + max_length=20, + verbose_name="Telefoonnummer", + ), + ), + ( + "actor", + models.ForeignKey( + help_text="'GeautomatiseerdeActor' was 'Actor'", + on_delete=django.db.models.deletion.CASCADE, + related_name="medewerker", + to="klantinteracties.actor", + verbose_name="Actor", + ), + ), + ], + options={ + "verbose_name": "medewerker", + "verbose_name_plural": "Mederwerkers", + }, + ), + migrations.CreateModel( + name="GeautomatiseerdeActor", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "functie", + models.CharField( + help_text="Functie van de geautomatiseerde actor of beschrijving van de werkzaamheden die deze uitvoert.", + max_length=40, + verbose_name="Functie", + ), + ), + ( + "omschrijving", + models.CharField( + blank=True, + help_text="Omschrijving van de geautomatiseerde actor.", + max_length=200, + verbose_name="Omschrijving", + ), + ), + ( + "actor", + models.ForeignKey( + help_text="'GeautomatiseerdeActor' was 'Actor'", + on_delete=django.db.models.deletion.CASCADE, + related_name="geautomatiseerde_actor", + to="klantinteracties.actor", + verbose_name="Actor", + ), + ), + ], + options={ + "verbose_name": "geautomatiseerde actor", + "verbose_name_plural": "geautomatiseerde actoren", + }, + ), + migrations.AddField( + model_name="klantcontact", + name="actoren", + field=models.ManyToManyField( + help_text="De actoren die tijdens het klantcontant contact had met klanten of hun vertegenwoordigers.", + related_name="klantcontacten", + to="klantinteracties.Actor", + verbose_name="Actoren", + ), + ), + ] diff --git a/src/openklant/components/klantinteracties/models/__init__.py b/src/openklant/components/klantinteracties/models/__init__.py index 7167c60a..84012ef7 100644 --- a/src/openklant/components/klantinteracties/models/__init__.py +++ b/src/openklant/components/klantinteracties/models/__init__.py @@ -1,3 +1,4 @@ +from .actoren import * # noqa from .digitaal_adres import * # noqa from .klantcontacten import * # noqa from .partijen import * # noqa diff --git a/src/openklant/components/klantinteracties/models/actoren.py b/src/openklant/components/klantinteracties/models/actoren.py new file mode 100644 index 00000000..a4a351f2 --- /dev/null +++ b/src/openklant/components/klantinteracties/models/actoren.py @@ -0,0 +1,157 @@ +import uuid + +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from .constants import SoortActor +from .mixins import ActorIdentifcatorMixin + + +class Actor(ActorIdentifcatorMixin): + id = models.UUIDField( + primary_key=True, + unique=True, + default=uuid.uuid4, + help_text=_("Unieke (technische) identificatiecode van de actor."), + ) + # TODO: add FK to Interne Taak + naam = models.CharField( + _("Naam"), + help_text=_("Naam van de actor."), + max_length=200, + ) + soort_actor = models.CharField( + _("Soort actor"), + help_text=_("Geeft aan van welke specifieke soort actor sprake is."), + choices=SoortActor.choices, + max_length=24, + ) + indicatie_actief = models.BooleanField( + _("Indicatie actief"), + help_text=_( + "Geeft aan of aan de actor nog betrokken mag worden bij nieuwe klantcontacten. " + "Voor niet-actieve is dit niet toegestaan." + ), + blank=False, + ) + + class Meta: + verbose_name = _("actor") + verbose_name_plural = _("actoren") + + def __str__(self): + return self.naam + + +class GeautomatiseerdeActor(models.Model): + actor = models.ForeignKey( + Actor, + on_delete=models.CASCADE, + verbose_name=_("Actor"), + related_name="geautomatiseerde_actor", + help_text=_("'GeautomatiseerdeActor' was 'Actor'"), + null=False, + ) + functie = models.CharField( + _("Functie"), + help_text=_( + "Functie van de geautomatiseerde actor of beschrijving van de werkzaamheden die deze uitvoert." + ), + max_length=40, + ) + omschrijving = models.CharField( + _("Omschrijving"), + help_text=_("Omschrijving van de geautomatiseerde actor."), + max_length=200, + blank=True, + ) + + class Meta: + verbose_name = _("geautomatiseerde actor") + verbose_name_plural = _("geautomatiseerde actoren") + + def __str__(self): + return self.functie + + +class Medewerker(models.Model): + actor = models.ForeignKey( + Actor, + on_delete=models.CASCADE, + verbose_name=_("Actor"), + related_name="medewerker", + help_text=_("'GeautomatiseerdeActor' was 'Actor'"), + null=False, + ) + functie = models.CharField( + _("Functie"), + help_text=_( + "Functie van de geautomatiseerde actor of beschrijving van de werkzaamheden die deze uitvoert." + ), + max_length=40, + ) + email = models.EmailField( + _("email address"), + help_text=_( + "Elektronisch postadres waaronder de MEDEWERKER in de regel bereikbaar is." + ), + blank=True, + ) + telefoonnummer = models.CharField( + _("Telefoonnummer"), + help_text=_( + "Telefoonnummer waaronder de MEDEWERKER in de regel bereikbaar is." + ), + max_length=20, + ) + + class Meta: + verbose_name = _("medewerker") + verbose_name_plural = _("Mederwerkers") + + def __str__(self): + return self.functie + + +class OrganisatorischeEenheid(models.Model): + actor = models.ForeignKey( + Actor, + on_delete=models.CASCADE, + verbose_name=_("Actor"), + related_name="organisatorische_eenheid", + help_text=_("'GeautomatiseerdeActor' was 'Actor'"), + null=False, + ) + omschrijving = models.CharField( + _("Omschrijving"), + help_text=_("Omschrijving van de geautomatiseerde actor."), + max_length=200, + blank=True, + ) + email = models.EmailField( + _("email address"), + help_text=_( + "Elektronisch postadres waaronder de MEDEWERKER in de regel bereikbaar is." + ), + blank=True, + ) + faxnummer = models.CharField( + _("Faxnummer"), + help_text=_( + "Faxnummer waaronder de organisatorische eenheid in de regel bereikbaar is." + ), + max_length=20, + ) + telefoonnummer = models.CharField( + _("Telefoonnummer"), + help_text=_( + "Telefoonnummer waaronder de MEDEWERKER in de regel bereikbaar is." + ), + max_length=20, + ) + + class Meta: + verbose_name = _("organisatorische eenheid") + + def __str__(self): + return self.omschrijving diff --git a/src/openklant/components/klantinteracties/models/klantcontacten.py b/src/openklant/components/klantinteracties/models/klantcontacten.py index d97ab1d9..14a337aa 100644 --- a/src/openklant/components/klantinteracties/models/klantcontacten.py +++ b/src/openklant/components/klantinteracties/models/klantcontacten.py @@ -6,6 +6,7 @@ from vng_api_common.descriptors import GegevensGroepType +from .actoren import Actor from .constants import Initiator, Klantcontrol from .digitaal_adres import DigitaalAdres @@ -19,7 +20,26 @@ class Klantcontact(models.Model): "Unieke (technische) identificatiecode van de betrokkene bij klantcontact." ), ) - # TODO: add fk to Actor + klantcontact = models.ForeignKey( + "self", + on_delete=models.SET_NULL, + related_name="klantcontacten", + verbose_name=_("Klant contact"), + help_text=_( + "De persoon of organisatie die betrokken was bij een klantcontact." + ), + blank=True, + null=True, + ) + actoren = models.ManyToManyField( + Actor, + verbose_name=_("Actoren"), + related_name="klantcontacten", + help_text=_( + "De actoren die tijdens het klantcontant contact had met klanten of hun vertegenwoordigers." + ), + blank=False, + ) # TODO: add fk to Onderwerpobject # TODO: add fk to Inhoudsobject nummer = models.CharField( diff --git a/src/openklant/components/klantinteracties/models/mixins.py b/src/openklant/components/klantinteracties/models/mixins.py new file mode 100644 index 00000000..91224800 --- /dev/null +++ b/src/openklant/components/klantinteracties/models/mixins.py @@ -0,0 +1,52 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from vng_api_common.descriptors import GegevensGroepType + + +class ActorIdentifcatorMixin(models.Model): + actoridentifcator_objecttype = models.CharField( + _("Objecttype"), + help_text=_( + "Type van het object, bijvoorbeeld: 'INGESCHREVEN NATUURLIJK PERSOON'." + ), + max_length=200, + blank=False, + ) + actoridentifcator_soort_object_id = models.CharField( + _("Soort Object ID"), + help_text=_( + "Naam van de eigenschap die het object identificeert, bijvoorbeeld: 'Burgerservicenummer'." + ), + max_length=200, + blank=False, + ) + actoridentifcator_object_id = models.CharField( + _("Object ID"), + help_text=_( + "Waarde van de eigenschap die het object identificeert, bijvoorbeeld: '123456788'." + ), + max_length=200, + blank=False, + ) + actoridentifcator_register = models.CharField( + _("Object ID"), + help_text=_( + "Binnen het landschap van registers unieke omschrijving van het register waarin " + "het object is geregistreerd, bijvoorbeeld: 'BRP'." + ), + max_length=200, + blank=False, + ) + + actoridentifcator = GegevensGroepType( + { + "objecttype": actoridentifcator_objecttype, + "soort object id": actoridentifcator_soort_object_id, + "object id": actoridentifcator_object_id, + "register": actoridentifcator_register, + } + ) + + class Meta: + abstract = True