Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logic for the new registration (static) variables #3984

Merged
merged 11 commits into from
Mar 14, 2024
47 changes: 45 additions & 2 deletions src/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5619,11 +5619,54 @@ paths:
$ref: '#/components/headers/X-Is-Form-Designer'
Content-Language:
$ref: '#/components/headers/Content-Language'
/api/v2/variables/registration:
get:
operationId: variables_registration_list
description: List the registration static variables that will be associated
with every form
summary: Get registration static variables
tags:
- variables
security:
- cookieAuth: []
responses:
'200':
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/FormVariable'
description: ''
headers:
X-Session-Expires-In:
$ref: '#/components/headers/X-Session-Expires-In'
X-CSRFToken:
$ref: '#/components/headers/X-CSRFToken'
X-Is-Form-Designer:
$ref: '#/components/headers/X-Is-Form-Designer'
Content-Language:
$ref: '#/components/headers/Content-Language'
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/Exception'
description: ''
headers:
X-Session-Expires-In:
$ref: '#/components/headers/X-Session-Expires-In'
X-CSRFToken:
$ref: '#/components/headers/X-CSRFToken'
X-Is-Form-Designer:
$ref: '#/components/headers/X-Is-Form-Designer'
Content-Language:
$ref: '#/components/headers/Content-Language'
/api/v2/variables/static:
get:
operationId: variables_static_list
description: List the static data that will be associated with every form
summary: Get static data
description: List the static variables that will be associated with every form
summary: Get static variables
tags:
- variables
security:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,9 @@ def test_static_variable_in_trigger(self):

self.client.force_authenticate(user=user)
url = reverse("api:form-logic-rules", kwargs={"uuid_or_slug": form.uuid})
with patch("openforms.variables.service.register", new=register):
with patch(
"openforms.variables.service.static_variables_registry", new=register
):
response = self.client.put(url, data=form_logic_data)

self.assertEqual(status.HTTP_200_OK, response.status_code)
18 changes: 13 additions & 5 deletions src/openforms/registrations/base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from dataclasses import dataclass
from typing import TYPE_CHECKING
Expand All @@ -8,7 +10,9 @@
from openforms.utils.mixins import JsonSchemaSerializerMixin

if TYPE_CHECKING:
from openforms.plugins.registry import BaseRegistry
from openforms.submissions.models import Submission
from openforms.variables.base import BaseStaticVariable

SerializerCls = type[serializers.Serializer]

Expand Down Expand Up @@ -42,16 +46,14 @@
"""

@abstractmethod
def register_submission(
self, submission: "Submission", options: dict
) -> dict | None:
def register_submission(self, submission: Submission, options: dict) -> dict | None:
raise NotImplementedError()

def update_payment_status(self, submission: "Submission", options: dict):
def update_payment_status(self, submission: Submission, options: dict):
raise NotImplementedError()

def pre_register_submission(
self, submission: "Submission", options: dict
self, submission: Submission, options: dict
) -> PreRegistrationResult:
"""Perform any tasks before registering the submission

Expand All @@ -65,3 +67,9 @@
Return a list of custom templatetags libraries that will be added to the 'sandboxed' Django templates backend.
"""
return []

def get_variables_registry(self) -> BaseRegistry[BaseStaticVariable] | None:
"""
Return the static variables registry for this registration puglin.
"""
return None

Check warning on line 75 in src/openforms/registrations/base.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/base.py#L75

Added line #L75 was not covered by tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Generated by Django 4.2.10 on 2024-03-13 10:39

import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("submissions", "0004_auto_20231128_1536"),
("registrations_objects_api", "0012_fill_required_fields"),
]

operations = [
migrations.CreateModel(
name="ObjectsAPIRegistrationData",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"pdf_url",
models.URLField(
blank=True,
help_text="The PDF URL of the document on the Documents API.",
verbose_name="pdf url",
),
),
(
"csv_url",
models.URLField(
blank=True,
help_text="The CSV URL of the document on the Documents API.",
verbose_name="csv url",
),
),
(
"attachment_urls",
django.contrib.postgres.fields.ArrayField(
base_field=models.URLField(
help_text="The attachment URL on the Documents API.",
verbose_name="attachment url",
),
blank=True,
default=list,
help_text="The list of attachment URLs on the Documents API.",
size=None,
verbose_name="attachment urls",
),
),
(
"submission",
models.OneToOneField(
help_text="The submission linked to the registration data.",
on_delete=django.db.models.deletion.CASCADE,
related_name="objects_api_registration_data",
to="submissions.submission",
verbose_name="submission",
),
),
],
),
]
36 changes: 36 additions & 0 deletions src/openforms/registrations/contrib/objects_api/models.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ValidationError
from django.db import models
from django.template.loader import render_to_string
Expand Down Expand Up @@ -195,3 +196,38 @@ def apply_defaults_to(self, options):
options["payment_status_update_json"] = self.payment_status_update_json

options.setdefault("auteur", "Aanvrager")


class ObjectsAPIRegistrationData(models.Model):
"""Holds the temporary data available when registering a submission to the Objects API.

When starting the submission registration, this model is first populated. The Objects API
registration variables can then safely make use of this model to provide their data.
"""

submission = models.OneToOneField(
"submissions.Submission",
on_delete=models.CASCADE,
verbose_name=_("submission"),
help_text=_("The submission linked to the registration data."),
related_name="objects_api_registration_data",
)
pdf_url = models.URLField(
_("pdf url"),
help_text=_("The PDF URL of the document on the Documents API."),
blank=True,
)
csv_url = models.URLField(
_("csv url"),
help_text=_("The CSV URL of the document on the Documents API."),
blank=True,
)
attachment_urls = ArrayField(
models.URLField(
_("attachment url"), help_text=_("The attachment URL on the Documents API.")
),
verbose_name=_("attachment urls"),
help_text=_("The list of attachment URLs on the Documents API."),
blank=True,
default=list,
)
Comment on lines +225 to +233
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is too naive, you lose the information of which file/component the Document URL belongs too.

I'd still prefer to have the variable of a file upload explicitly mapped into the schema, e.g. something like:

type: object
properties:
  proofOfEmployment:
    type: string
    format: uri
  bankStatements:
    type: array
    items:
        type: string
        format: uri

so that you can make the (single) file upload "proof of employment" to /proofOfEmployment and the multi-file upload "bank statements" to /bankStatements

Possibly we do this in a separate PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Considering this requires thinking and probably some work, it will probably be part of the next PR

16 changes: 14 additions & 2 deletions src/openforms/registrations/contrib/objects_api/plugin.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
from __future__ import annotations

import logging
from functools import partial
from typing import Any
from typing import TYPE_CHECKING, Any

from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from typing_extensions import override

from openforms.registrations.utils import execute_unless_result_exists
from openforms.submissions.models import Submission
from openforms.utils.date import get_today

from ...base import BasePlugin
Expand All @@ -17,9 +18,14 @@
from .client import get_objects_client
from .config import ObjectsAPIOptionsSerializer
from .models import ObjectsAPIConfig
from .registration_variables import Registry, register as variables_registry
from .submission_registration import HANDLER_MAPPING
from .typing import RegistrationOptions

if TYPE_CHECKING:
from openforms.submissions.models import Submission


PLUGIN_IDENTIFIER = "objects_api"

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -58,6 +64,8 @@

handler = HANDLER_MAPPING[options["version"]]

handler.save_registration_data(submission, options)

object_data = handler.get_object_data(
submission=submission,
options=options,
Expand Down Expand Up @@ -129,3 +137,7 @@
headers={"Content-Crs": "EPSG:4326"},
)
response.raise_for_status()

@override
def get_variables_registry(self) -> Registry:
return variables_registry

Check warning on line 143 in src/openforms/registrations/contrib/objects_api/plugin.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/plugin.py#L143

Added line #L143 was not covered by tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
from __future__ import annotations

from typing import TYPE_CHECKING

from django.utils.translation import gettext_lazy as _

from openforms.plugins.registry import BaseRegistry
from openforms.variables.base import BaseStaticVariable
from openforms.variables.constants import FormVariableDataTypes

if TYPE_CHECKING:
from openforms.submissions.models import Submission


class Registry(BaseRegistry[BaseStaticVariable]):
"""
A registry for the Objects API registration variables.
"""

module = "objects_api"


register = Registry()
"""The Objects API registration variables registry."""


@register("pdf_url")
class PdfUrl(BaseStaticVariable):
name = _("PDF Url")
data_type = FormVariableDataTypes.string

def get_initial_value(self, submission: Submission | None = None):
return (

Check warning on line 33 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L33

Added line #L33 was not covered by tests
submission.objects_api_registration_data.pdf_url
if submission is not None
else None
)
Viicos marked this conversation as resolved.
Show resolved Hide resolved


@register("csv_url")
class CsvUrl(BaseStaticVariable):
name = _("CSV Url")
data_type = FormVariableDataTypes.string

def get_initial_value(self, submission: Submission | None = None):
return (

Check warning on line 46 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L46

Added line #L46 was not covered by tests
submission.objects_api_registration_data.csv_url
if submission is not None
else None
)


@register("attachment_urls")
class AttachmentUrls(BaseStaticVariable):
name = _("Attachment Urls")
data_type = FormVariableDataTypes.array

def get_initial_value(self, submission: Submission | None = None):
return (

Check warning on line 59 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L59

Added line #L59 was not covered by tests
submission.objects_api_registration_data.attachment_urls
if submission is not None
else None
)


@register("payment_completed")
class PaymentCompleted(BaseStaticVariable):
name = _("Payment completed")
data_type = FormVariableDataTypes.boolean

def get_initial_value(self, submission: Submission | None = None):
return submission.payment_user_has_paid if submission is not None else None

Check warning on line 72 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L72

Added line #L72 was not covered by tests


@register("payment_amount")
class PaymentAmount(BaseStaticVariable):
name = _("Payment amount")
data_type = FormVariableDataTypes.string

def get_initial_value(self, submission: Submission | None = None):
return str(submission.payments.sum_amount()) if submission is not None else None

Check warning on line 81 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L81

Added line #L81 was not covered by tests


@register("payment_public_order_ids")
class PaymentPublicOrderIds(BaseStaticVariable):
name = _("Payment public order IDs")
data_type = FormVariableDataTypes.array

def get_initial_value(self, submission: Submission | None = None):
return (

Check warning on line 90 in src/openforms/registrations/contrib/objects_api/registration_variables.py

View check run for this annotation

Codecov / codecov/patch

src/openforms/registrations/contrib/objects_api/registration_variables.py#L90

Added line #L90 was not covered by tests
submission.payments.get_completed_public_order_ids()
if submission is not None
else None
)
Loading
Loading