diff --git a/src/openforms/formio/formatters/tests/test_kitchensink.py b/src/openforms/formio/formatters/tests/test_kitchensink.py index d58ee6fe11..82029675b1 100644 --- a/src/openforms/formio/formatters/tests/test_kitchensink.py +++ b/src/openforms/formio/formatters/tests/test_kitchensink.py @@ -1,5 +1,8 @@ +from typing import Any + from django.utils.translation import gettext as _ +from openforms.submissions.models import Submission from openforms.submissions.tests.factories import ( SubmissionFactory, SubmissionFileAttachmentFactory, @@ -12,15 +15,15 @@ from .utils import load_json -def _get_printable_data(submission): - printable_data = [] - for key, ( - component, - value, - ) in submission.get_ordered_data_with_component_type().items(): - printable_data.append( - (component["label"], format_value(component, value, as_html=False)) - ) +def _get_printable_data(submission: Submission) -> list[tuple[str, Any]]: + printable_data: list[tuple[str, Any]] = [] + merged_data = submission.data + + for component in filter_printable(submission.form.iter_components(recursive=True)): + key = component["key"] + value = format_value(component, merged_data.get(key), as_html=False) + printable_data.append((component.get("label", key), value)) + return printable_data diff --git a/src/openforms/registrations/contrib/camunda/plugin.py b/src/openforms/registrations/contrib/camunda/plugin.py index 415a9a3608..85b64dbf4c 100644 --- a/src/openforms/registrations/contrib/camunda/plugin.py +++ b/src/openforms/registrations/contrib/camunda/plugin.py @@ -48,7 +48,7 @@ def get_process_variables( ] ) - merged_data: dict[str, Any] = submission.get_merged_data() + merged_data = submission.data for component in submission.form.iter_components(recursive=True): if (key := component.get("key")) not in simple_mappings: continue diff --git a/src/openforms/registrations/contrib/microsoft_graph/plugin.py b/src/openforms/registrations/contrib/microsoft_graph/plugin.py index a2d4bec28c..48260e326a 100644 --- a/src/openforms/registrations/contrib/microsoft_graph/plugin.py +++ b/src/openforms/registrations/contrib/microsoft_graph/plugin.py @@ -64,7 +64,7 @@ def register_submission(self, submission: Submission, options: dict) -> None: submission_report.content, folder_name / "report.pdf" ) - data = submission.get_merged_data() + data = submission.data data["__metadata__"] = {"submission_language": submission.language_code} uploader.upload_json(data, folder_name / "data.json") diff --git a/src/openforms/submissions/admin.py b/src/openforms/submissions/admin.py index edb9a0fff8..9618fa8855 100644 --- a/src/openforms/submissions/admin.py +++ b/src/openforms/submissions/admin.py @@ -269,7 +269,6 @@ def change_view(self, request, object_id, form_url="", extra_context=None): raise Http404(f"No {self.model._meta.object_name} matches the given query.") submission_details_view_admin(submission, request.user) extra_context = { - "data": submission.get_ordered_data_with_component_type(), "attachments": submission.get_merged_attachments(), "image_components": IMAGE_COMPONENTS, } diff --git a/src/openforms/submissions/mapping.py b/src/openforms/submissions/mapping.py index 7d610b8eaf..900ddcdfed 100644 --- a/src/openforms/submissions/mapping.py +++ b/src/openforms/submissions/mapping.py @@ -97,7 +97,7 @@ def apply_data_mapping( attr_key_lookup[attribute] = key # grab submitted data - data = submission.get_merged_data() + data = submission.data for target_path, conf in mapping_config.items(): if isinstance(conf, str): @@ -137,7 +137,7 @@ def get_unmapped_data( """ companion to apply_data_mapping() returns data not mapped to RegistrationAttributes """ - data = submission.get_merged_data() + data = submission.data attr_key_lookup = dict() diff --git a/src/openforms/submissions/models/submission.py b/src/openforms/submissions/models/submission.py index 76ebf0ddae..83a21b6c28 100644 --- a/src/openforms/submissions/models/submission.py +++ b/src/openforms/submissions/models/submission.py @@ -2,9 +2,8 @@ import logging import uuid -from collections import OrderedDict from dataclasses import dataclass -from typing import TYPE_CHECKING, Mapping +from typing import TYPE_CHECKING, Any, Mapping from django.conf import settings from django.db import models, transaction @@ -52,7 +51,7 @@ @dataclass class SubmissionState: form_steps: list[FormStep] - submission_steps: list["SubmissionStep"] + submission_steps: list[SubmissionStep] def _get_step_offset(self): completed_steps = sorted( @@ -66,7 +65,7 @@ def _get_step_offset(self): ) return offset - def get_last_completed_step(self) -> "SubmissionStep" | None: + def get_last_completed_step(self) -> SubmissionStep | None: """ Determine the last step that was filled out. @@ -86,7 +85,7 @@ def get_last_completed_step(self) -> "SubmissionStep" | None: ) return next(candidates, None) - def get_submission_step(self, form_step_uuid: str) -> "SubmissionStep" | None: + def get_submission_step(self, form_step_uuid: str) -> SubmissionStep | None: return next( ( step @@ -96,7 +95,7 @@ def get_submission_step(self, form_step_uuid: str) -> "SubmissionStep" | None: None, ) - def resolve_step(self, form_step_uuid: str) -> "SubmissionStep": + def resolve_step(self, form_step_uuid: str) -> SubmissionStep: return self.get_submission_step(form_step_uuid=form_step_uuid) @@ -467,7 +466,7 @@ def remove_sensitive_data(self): @elasticapm.capture_span(span_type="app.data.loading") def load_submission_value_variables_state( self, refresh: bool = False - ) -> "SubmissionValueVariablesState": + ) -> SubmissionValueVariablesState: if hasattr(self, "_variables_state") and not refresh: return self._variables_state @@ -593,36 +592,18 @@ def render_summary_page(self) -> list[JSONObject]: return summary_data @property - def steps(self) -> list["SubmissionStep"]: + def steps(self) -> list[SubmissionStep]: # fetch the existing DB records for submitted form steps submission_state = self.load_execution_state() return submission_state.submission_steps - def get_last_completed_step(self) -> "SubmissionStep" | None: + def get_last_completed_step(self) -> SubmissionStep | None: """ Determine which is the next step for the current submission. """ submission_state = self.load_execution_state() return submission_state.get_last_completed_step() - def get_ordered_data_with_component_type(self) -> OrderedDict: - from openforms.formio.formatters.printable import filter_printable - - ordered_data = OrderedDict() - merged_data = self.get_merged_data() - - # first collect data we have in the same order the components are defined in the form - for component in filter_printable(self.form.iter_components(recursive=True)): - key = component["key"] - value = merged_data.get(key, None) - component.setdefault("label", key) - ordered_data[key] = ( - component, - value, - ) - - return ordered_data - def get_merged_appointment_data(self) -> dict[str, dict[str, str | dict]]: component_config_key_to_appointment_key = { "appointments.showProducts": "productIDAndName", @@ -633,7 +614,7 @@ def get_merged_appointment_data(self) -> dict[str, dict[str, str | dict]]: "appointments.phoneNumber": "clientPhoneNumber", } - merged_data = self.get_merged_data() + merged_data = self.data appointment_data = {} for component in self.form.iter_components(recursive=True): @@ -655,12 +636,20 @@ def get_merged_appointment_data(self) -> dict[str, dict[str, str | dict]]: return appointment_data - def get_merged_data(self) -> dict: + @property + def data(self) -> dict[str, Any]: + """The filled-in data of the submission. + + This is a mapping between variable keys and their corresponding values. + + .. note:: + + Keys containings dots (``.``) will be nested under another mapping. + Static variables values are *not* included. + """ values_state = self.load_submission_value_variables_state() return values_state.get_data() - data = property(get_merged_data) - def get_co_signer(self) -> str: if not self.co_sign_data: return "" @@ -668,16 +657,16 @@ def get_co_signer(self) -> str: logger.warning("Incomplete co-sign data for submission %s", self.uuid) return co_signer - def get_attachments(self) -> "SubmissionFileAttachmentQuerySet": + def get_attachments(self) -> SubmissionFileAttachmentQuerySet: from .submission_files import SubmissionFileAttachment return SubmissionFileAttachment.objects.for_submission(self) @property - def attachments(self) -> "SubmissionFileAttachmentQuerySet": + def attachments(self) -> SubmissionFileAttachmentQuerySet: return self.get_attachments() - def get_merged_attachments(self) -> Mapping[str, list["SubmissionFileAttachment"]]: + def get_merged_attachments(self) -> Mapping[str, list[SubmissionFileAttachment]]: if not hasattr(self, "_merged_attachments"): self._merged_attachments = self.get_attachments().as_form_dict() return self._merged_attachments diff --git a/src/openforms/submissions/templates/admin/submissions/submission/change_form.html b/src/openforms/submissions/templates/admin/submissions/submission/change_form.html index 57a6156948..e5cbaa922c 100644 --- a/src/openforms/submissions/templates/admin/submissions/submission/change_form.html +++ b/src/openforms/submissions/templates/admin/submissions/submission/change_form.html @@ -3,26 +3,6 @@ {% block after_field_sets %}