Skip to content

Commit fb69999

Browse files
SilviaAmAmsvenvandescheur
authored andcommitted
✨ [#397] Add zaak creation logic
1 parent 4408c51 commit fb69999

File tree

5 files changed

+210
-3
lines changed

5 files changed

+210
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Generated by Django 4.2.16 on 2024-10-14 12:51
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("destruction", "0023_destructionlist_destruction_report"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="destructionlist",
15+
name="internal_results",
16+
field=models.JSONField(
17+
default=dict,
18+
help_text="After this list is processed, the URL of the resources created in Open Zaak to store the destruction report are stored here.",
19+
verbose_name="internal result",
20+
),
21+
),
22+
migrations.AlterField(
23+
model_name="destructionlist",
24+
name="zaak_destruction_report_url",
25+
field=models.URLField(
26+
blank=True,
27+
help_text="The URL of the case containing the destruction report for this destruction list.",
28+
max_length=1000,
29+
verbose_name="zaak destruction report URL",
30+
),
31+
),
32+
]

backend/src/openarchiefbeheer/destruction/models.py

+27
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class DestructionList(models.Model):
9797
"The URL of the case containing the destruction report for this destruction list."
9898
),
9999
blank=True,
100+
max_length=1000,
100101
)
101102
processing_status = models.CharField(
102103
_("processing status"),
@@ -119,6 +120,14 @@ class DestructionList(models.Model):
119120
blank=True,
120121
null=True,
121122
)
123+
internal_results = models.JSONField(
124+
verbose_name=_("internal result"),
125+
help_text=_(
126+
"After this list is processed, the URL of the resources created in Open Zaak "
127+
"to store the destruction report are stored here."
128+
),
129+
default=dict,
130+
)
122131

123132
logs = GenericRelation(TimelineLog, related_query_name="destruction_list")
124133

@@ -244,6 +253,24 @@ def generate_destruction_report(self) -> None:
244253

245254
self.save()
246255

256+
def create_report_zaak(self) -> None:
257+
from .utils import (
258+
attach_report_to_zaak,
259+
create_eio_destruction_report,
260+
create_zaak_for_report,
261+
)
262+
263+
if self.processing_status == InternalStatus.succeeded:
264+
return
265+
266+
destruction_list = self
267+
store = ResultStore(store=destruction_list)
268+
269+
create_zaak_for_report(destruction_list, store)
270+
create_eio_destruction_report(destruction_list, store)
271+
272+
attach_report_to_zaak(destruction_list, store)
273+
247274

248275
class DestructionListItem(models.Model):
249276
destruction_list = models.ForeignKey(

backend/src/openarchiefbeheer/destruction/tasks.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,12 @@ def complete_and_notify(pk: int) -> None:
119119
if destruction_list.has_failures():
120120
raise DeletionProcessingError()
121121

122-
destruction_list.processing_status = InternalStatus.succeeded
123-
destruction_list.save()
124-
125122
destruction_list.set_status(ListStatus.deleted)
123+
126124
destruction_list.generate_destruction_report()
125+
destruction_list.create_report_zaak()
126+
127+
destruction_list.processing_status = InternalStatus.succeeded
128+
destruction_list.save()
127129

128130
notify_assignees_successful_deletion(destruction_list)

backend/src/openarchiefbeheer/destruction/utils.py

+123
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
1+
from base64 import b64encode
12
from typing import Protocol
23

34
from django.conf import settings
45
from django.core.mail import send_mail
56
from django.db import transaction
67
from django.db.models import OuterRef, Q, Subquery
8+
from django.utils import timezone
9+
from django.utils.translation import gettext_lazy as _
10+
11+
from zgw_consumers.client import build_client
12+
from zgw_consumers.constants import APITypes
13+
from zgw_consumers.models import Service
714

815
from openarchiefbeheer.accounts.models import User
16+
from openarchiefbeheer.config.models import ArchiveConfig
917
from openarchiefbeheer.emails.models import EmailConfig
1018
from openarchiefbeheer.emails.render_backend import get_sandboxed_backend
19+
from openarchiefbeheer.utils.results_store import ResultStore
1120
from openarchiefbeheer.zaken.models import Zaak
1221

1322
from .constants import InternalStatus, ListRole
@@ -121,3 +130,117 @@ def resync_items_and_zaken() -> None:
121130
Zaak.objects.filter(url=OuterRef("_zaak_url")).values("pk")[:1]
122131
)
123132
)
133+
134+
135+
def create_zaak_for_report(
136+
destruction_list: DestructionList, store: ResultStore
137+
) -> None:
138+
config = ArchiveConfig.get_solo()
139+
140+
zrc_service = Service.objects.get(api_type=APITypes.zrc)
141+
zrc_client = build_client(zrc_service)
142+
143+
with zrc_client:
144+
if not destruction_list.zaak_destruction_report_url:
145+
response = zrc_client.post(
146+
"zaken",
147+
headers={
148+
"Accept-Crs": "EPSG:4326",
149+
"Content-Crs": "EPSG:4326",
150+
},
151+
json={
152+
"bronorganisatie": config.bronorganisatie,
153+
"omschrijving": _("Destruction report of list: %(list_name)s")
154+
% {"list_name": destruction_list.name},
155+
"zaaktype": config.zaaktype,
156+
"vertrouwelijkheidaanduiding": "openbaar",
157+
"startdatum": timezone.now().date().isoformat(),
158+
"verantwoordelijkeOrganisatie": config.bronorganisatie,
159+
"archiefnominatie": "blijvend_bewaren",
160+
},
161+
timeout=settings.REQUESTS_DEFAULT_TIMEOUT,
162+
)
163+
response.raise_for_status()
164+
new_zaak = response.json()
165+
166+
destruction_list.zaak_destruction_report_url = new_zaak["url"]
167+
destruction_list.save()
168+
169+
if not store.has_created_resource("resultaten"):
170+
response = zrc_client.post(
171+
"resultaten",
172+
json={
173+
"zaak": destruction_list.zaak_destruction_report_url,
174+
"resultaattype": config.resultaattype,
175+
},
176+
)
177+
response.raise_for_status()
178+
store.add_created_resource("resultaten", response.json()["url"])
179+
180+
if not store.has_created_resource("statussen"):
181+
response = zrc_client.post(
182+
"statussen",
183+
json={
184+
"zaak": destruction_list.zaak_destruction_report_url,
185+
"statustype": config.statustype,
186+
"datum_status_gezet": timezone.now().date().isoformat(),
187+
},
188+
)
189+
response.raise_for_status()
190+
store.add_created_resource("statussen", response.json()["url"])
191+
192+
193+
def create_eio_destruction_report(
194+
destruction_list: DestructionList, store: ResultStore
195+
) -> None:
196+
if store.has_created_resource("enkelvoudiginformatieobjecten"):
197+
return
198+
199+
config = ArchiveConfig.get_solo()
200+
201+
drc_service = Service.objects.get(api_type=APITypes.drc)
202+
drc_client = build_client(drc_service)
203+
204+
with drc_client, destruction_list.destruction_report.open("rb") as f_report:
205+
response = drc_client.post(
206+
"enkelvoudiginformatieobjecten",
207+
json={
208+
"bronorganisatie": config.bronorganisatie,
209+
"creatiedatum": timezone.now().date().isoformat(),
210+
"titel": _("Destruction report of list: %(list_name)s")
211+
% {"list_name": destruction_list.name},
212+
"auteur": "Open Archiefbeheer",
213+
"taal": "nld",
214+
"formaat": "text/csv",
215+
"inhoud": b64encode(f_report.read()).decode("utf-8"),
216+
"informatieobjecttype": config.informatieobjecttype,
217+
"indicatie_gebruiksrecht": False,
218+
},
219+
)
220+
response.raise_for_status()
221+
new_document = response.json()
222+
223+
store.add_created_resource("enkelvoudiginformatieobjecten", new_document["url"])
224+
225+
226+
def attach_report_to_zaak(
227+
destruction_list: DestructionList, store: ResultStore
228+
) -> None:
229+
if store.has_created_resource("zaakinformatieobjecten"):
230+
return
231+
232+
zrc_service = Service.objects.get(api_type=APITypes.zrc)
233+
zrc_client = build_client(zrc_service)
234+
235+
with zrc_client:
236+
response = zrc_client.post(
237+
"zaakinformatieobjecten",
238+
json={
239+
"zaak": destruction_list.zaak_destruction_report_url,
240+
"informatieobject": store.get_created_resources(
241+
"enkelvoudiginformatieobjecten"
242+
)[0],
243+
},
244+
)
245+
response.raise_for_status()
246+
store.add_created_resource("zaakinformatieobjecten", response.json()["url"])

backend/src/openarchiefbeheer/utils/results_store.py

+23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
class InternalResults(TypedDict):
77
deleted_resources: dict[str, list]
8+
created_resources: dict[str, list]
89
resources_to_delete: dict[str, list]
910
traceback: str = ""
1011

@@ -27,6 +28,10 @@ def get_internal_results(self) -> InternalResults:
2728

2829
if not results.get("resources_to_delete"):
2930
results["resources_to_delete"] = defaultdict(list)
31+
32+
if not results.get("created_resources"):
33+
results["created_resources"] = defaultdict(list)
34+
3035
return results
3136

3237
def refresh_from_db(self) -> None:
@@ -48,16 +53,34 @@ def has_resource_to_delete(self, resource_type: str) -> bool:
4853
and len(results["resources_to_delete"][resource_type]) > 0
4954
)
5055

56+
def has_created_resource(self, resource_type: str) -> bool:
57+
results = self.get_internal_results()
58+
59+
return (
60+
resource_type in results["created_resources"]
61+
and len(results["created_resources"][resource_type]) > 0
62+
)
63+
5164
def add_resource_to_delete(self, resource_type: str, value: str) -> None:
5265
results = self.get_internal_results()
5366

5467
results["resources_to_delete"][resource_type].append(value)
5568
self.save()
5669

70+
def add_created_resource(self, resource_type: str, value) -> None:
71+
results = self.get_internal_results()
72+
73+
results["created_resources"][resource_type].append(value)
74+
self.save()
75+
5776
def get_resources_to_delete(self, resource_type: str) -> list[str]:
5877
results = self.get_internal_results()
5978
return results["resources_to_delete"][resource_type]
6079

80+
def get_created_resources(self, resource_type: str) -> list[str]:
81+
results = self.get_internal_results()
82+
return results["created_resources"][resource_type]
83+
6184
def clear_resources_to_delete(self, resource_type: str) -> None:
6285
results = self.get_internal_results()
6386
del results["resources_to_delete"][resource_type]

0 commit comments

Comments
 (0)