Skip to content

Commit

Permalink
[#4396] Added the attributes retrieval functionality
Browse files Browse the repository at this point in the history
This is not the whole prefill plugin functionality. This commit handles
the procedures in order to be able to send to the frontend the available
attributes (for mapping the form variable with the objecttype attribute)
depending on the selected objecttype's version.
  • Loading branch information
vaszig committed Sep 2, 2024
1 parent 5960d08 commit 7ac1670
Show file tree
Hide file tree
Showing 13 changed files with 441 additions and 26 deletions.
56 changes: 43 additions & 13 deletions src/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8537,6 +8537,8 @@ components:
* `main` - Main
* `authorizee` - Authorizee
prefillOptions:
$ref: '#/components/schemas/FormVariableOptions'
dataType:
allOf:
- $ref: '#/components/schemas/DataTypeEnum'
Expand Down Expand Up @@ -8568,6 +8570,27 @@ components:
- key
- name
- source
FormVariableOptions:
type: object
properties:
prefillPlugin:
type: string
description: The selected prefill plugin.
objectsApiGroup:
type: integer
description: Which Objects API group to use.
objecttypeUuid:
type: string
format: uuid
title: objecttype
description: 'UUID of the objecttype in the Objecttypes API. '
objecttypeVersion:
type: integer
description: Version of the objecttype in the Objecttypes API.
variablesMapping:
type: array
items:
$ref: '#/components/schemas/ObjecttypeVariableMapping'
FormVersion:
type: object
properties:
Expand Down Expand Up @@ -9121,6 +9144,26 @@ components:
- namePlural
- url
- uuid
ObjecttypeVariableMapping:
type: object
description: A mapping between a form variable key and the corresponding Objecttype
attribute.
properties:
variableKey:
type: string
description: The 'dotted' path to a form variable key. The format should
comply to how Formio handles nested component keys.
pattern: ^(\w|\w[\w.\-]*\w)$
targetPath:
type: array
items:
type: string
title: Segment of a JSON path
description: Representation of the JSON target location as a list of string
segments.
required:
- targetPath
- variableKey
ObjecttypeVersion:
type: object
properties:
Expand Down Expand Up @@ -9627,19 +9670,6 @@ components:
description: |-
* `main` - Main
* `authorizee` - Authorizee
PrefillObjectsAPIAttribute:
type: object
properties:
value:
type: string
title: ID
description: The unique attribute identifier
label:
type: string
description: The human-readable name for an attribute.
required:
- label
- value
PrefillPlugin:
type: object
properties:
Expand Down
2 changes: 2 additions & 0 deletions src/openforms/forms/admin/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class FormVariableAdmin(admin.ModelAdmin):
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"prefill_options",
"data_type",
"is_sensitive_data",
"initial_value",
Expand All @@ -31,6 +32,7 @@ class FormVariableAdmin(admin.ModelAdmin):
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"prefill_options",
"data_type",
"data_format",
"is_sensitive_data",
Expand Down
73 changes: 72 additions & 1 deletion src/openforms/forms/api/serializers/form_variable.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
from collections import defaultdict

from django.db.models import Q
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from drf_spectacular.utils import OpenApiExample, extend_schema_serializer
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from openforms.api.fields import RelatedFieldFromContext
from openforms.api.fields import (
PrimaryKeyRelatedAsChoicesField,
RelatedFieldFromContext,
)
from openforms.api.serializers import ListWithChildSerializer
from openforms.formio.api.fields import FormioVariableKeyField
from openforms.registrations.contrib.objects_api.models import ObjectsAPIGroupConfig
from openforms.utils.mixins import JsonSchemaSerializerMixin
from openforms.variables.api.serializers import ServiceFetchConfigurationSerializer
from openforms.variables.constants import FormVariableSources
from openforms.variables.models import ServiceFetchConfiguration
Expand All @@ -16,6 +24,67 @@
from ...models import Form, FormDefinition, FormVariable


@extend_schema_serializer(
examples=[
OpenApiExample(
name="Variable mapping example",
value={
"variable_key": "a_component_variable",
"target_path": ["path", "to.the", "target"],
},
)
]
)
class ObjecttypeVariableMappingSerializer(serializers.Serializer):
"""A mapping between a form variable key and the corresponding Objecttype attribute."""

variable_key = FormioVariableKeyField(
label=_("variable key"),
help_text=_(
"The 'dotted' path to a form variable key. The format should comply to how Formio handles nested component keys."
),
)
target_path = serializers.ListField(
child=serializers.CharField(label=_("Segment of a JSON path")),
label=_("target path"),
help_text=_(
"Representation of the JSON target location as a list of string segments."
),
)


class FormVariableOptionsSerializer(JsonSchemaSerializerMixin, serializers.Serializer):
prefill_plugin = serializers.CharField(
required=False, help_text=_("The selected prefill plugin.")
)
objects_api_group = PrimaryKeyRelatedAsChoicesField(
queryset=ObjectsAPIGroupConfig.objects.exclude(
Q(objects_service=None)
| Q(objecttypes_service=None)
| Q(drc_service=None)
| Q(catalogi_service=None)
),
label=("Objects API group"),
required=False,
help_text=_("Which Objects API group to use."),
)
objecttype_uuid = serializers.UUIDField(
label=_("objecttype"),
required=False,
help_text=_("UUID of the objecttype in the Objecttypes API. "),
)
objecttype_version = serializers.IntegerField(
label=_("objecttype version"),
required=False,
help_text=_("Version of the objecttype in the Objecttypes API."),
)
variables_mapping = ObjecttypeVariableMappingSerializer(
label=_("variables mapping"),
many=True,
required=False,
)


class FormVariableListSerializer(ListWithChildSerializer):
def get_child_serializer_class(self):
return FormVariableSerializer
Expand Down Expand Up @@ -110,6 +179,7 @@ class FormVariableSerializer(serializers.HyperlinkedModelSerializer):
service_fetch_configuration = ServiceFetchConfigurationSerializer(
required=False, allow_null=True
)
prefill_options = FormVariableOptionsSerializer(required=False)

class Meta:
model = FormVariable
Expand All @@ -124,6 +194,7 @@ class Meta:
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"prefill_options",
"data_type",
"data_format",
"is_sensitive_data",
Expand Down
20 changes: 20 additions & 0 deletions src/openforms/forms/api/typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from typing import TYPE_CHECKING, Required, TypedDict

if TYPE_CHECKING:
from openforms.registrations.contrib.objects_api.models import ObjectsAPIGroupConfig


class _BasePrefillOptions(TypedDict):
prefill_plugin: str


class ObjecttypeVariableMapping(TypedDict):
variable_key: str
target_path: list[str]


class ObjectsAPIPrefillOptions(_BasePrefillOptions):
objects_api_group: Required[ObjectsAPIGroupConfig]
objecttype_uuid: Required[str]
objecttype_version: Required[int]
variables_mapping: Required[list[ObjecttypeVariableMapping]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Generated by Django 4.2.15 on 2024-08-21 11:04

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("forms", "0097_v267_to_v270"),
]

operations = [
migrations.AddField(
model_name="formvariable",
name="prefill_options",
field=models.JSONField(
blank=True, default=dict, verbose_name="prefill options"
),
),
]
5 changes: 5 additions & 0 deletions src/openforms/forms/models/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ class FormVariable(models.Model):
default=IdentifierRoles.main,
max_length=100,
)
prefill_options = models.JSONField(
_("prefill options"),
default=dict,
blank=True,
)
data_type = models.CharField(
verbose_name=_("data type"),
help_text=_("The type of the value that will be associated with this variable"),
Expand Down
11 changes: 0 additions & 11 deletions src/openforms/prefill/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,3 @@ class PrefillAttributeSerializer(serializers.Serializer):
label=_("Label"),
help_text=_("The human-readable name for an attribute."),
)


class PrefillObjectsAPIAttributeSerializer(serializers.Serializer):
value = serializers.CharField(
label=_("ID"),
help_text=_("The unique attribute identifier"),
)
label = serializers.CharField(
label=_("Label"),
help_text=_("The human-readable name for an attribute."),
)
7 changes: 6 additions & 1 deletion src/openforms/prefill/contrib/objects_api/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from ...base import BasePlugin
from ...constants import IdentifierRoles
from ...registry import register
from .utils import retrieve_properties

logger = logging.getLogger(__name__)

Expand All @@ -25,7 +26,8 @@ class ObjectsAPIPrefill(BasePlugin):
def get_available_attributes(
reference: dict[str, Any] | None = None,
) -> Iterable[tuple[str, str]]:
pass
assert reference is not None
return retrieve_properties(reference)

@classmethod
def get_prefill_values(
Expand All @@ -41,3 +43,6 @@ def get_co_sign_values(
cls, submission: Submission, identifier: str
) -> tuple[dict[str, Any], str]:
pass

def check_config(self):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
interactions:
- request:
body: null
headers:
Accept:
- '*/*'
Accept-Encoding:
- gzip, deflate, br
Authorization:
- Token 171be5abaf41e7856b423ad513df1ef8f867ff48
Connection:
- keep-alive
User-Agent:
- python-requests/2.32.2
method: GET
uri: http://localhost:8001/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3
response:
body:
string: '{"url":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48/versions/3","version":3,"objectType":"http://objecttypes-web:8000/api/v2/objecttypes/8e46e0a5-b1b4-449b-b9e9-fa3cea655f48","status":"draft","jsonSchema":{"$id":"https://example.com/person.schema.json","type":"object","title":"Person","$schema":"https://json-schema.org/draft/2020-12/schema","properties":{"age":{"type":"integer","minimum":18},"name":{"type":"object","properties":{"last.name":{"type":"string"}}},"nested":{"type":"object","properties":{"unrelated":{"type":"string"},"submission_payment_amount":{"type":"number","multipleOf":0.01}}},"submission_date":{"type":"string","format":"date-time"},"submission_csv_url":{"type":"string","format":"uri"},"submission_pdf_url":{"type":"string","format":"uri"},"submission_payment_completed":{"type":"boolean"},"submission_payment_public_ids":{"type":"array"}}},"createdAt":"2024-02-08","modifiedAt":"2024-02-08","publishedAt":"2024-02-08"}'
headers:
Allow:
- GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Connection:
- keep-alive
Content-Length:
- '985'
Content-Type:
- application/json
Cross-Origin-Opener-Policy:
- same-origin
Date:
- Wed, 28 Aug 2024 08:04:23 GMT
Referrer-Policy:
- same-origin
Server:
- nginx/1.27.0
Vary:
- origin
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- DENY
status:
code: 200
message: OK
version: 1
Loading

0 comments on commit 7ac1670

Please sign in to comment.