diff --git a/src/openforms/appointments/base.py b/src/openforms/appointments/base.py
index ff4b626e7b..0367aa3315 100644
--- a/src/openforms/appointments/base.py
+++ b/src/openforms/appointments/base.py
@@ -49,21 +49,6 @@ def __str__(self):
return self.identifier
-@dataclass()
-class Customer:
- """
- Deprecated in favour of the :class:`CustomerDetails`.
- """
-
- last_name: str
- birthdate: date
- initials: str | None = None
- phonenumber: str | None = None
-
- def __str__(self):
- return self.last_name
-
-
F = TypeVar("F", bound=TextChoices)
# generic type for the plugin-specific enum of field names
@@ -210,7 +195,7 @@ def create_appointment(
products: list[Product],
location: Location,
start_at: datetime,
- client: CustomerDetails[F] | Customer,
+ client: CustomerDetails[F],
remarks: str = "",
) -> str:
"""
@@ -219,7 +204,7 @@ def create_appointment(
:param products: List of :class:`Product`, as obtained from :meth:`get_available_products`.
:param location: An :class:`Location`, as obtained from :meth:`get_locations`.
:param start_at: A `datetime` to start the appointment, as obtained from :meth:`get_dates`.
- :param client: A :class:`Customer` that holds client details.
+ :param client: A :class:`CustomerDetails` that holds client details.
:param remarks: A ``str`` for additional remarks, added to the appointment.
:returns: An appointment identifier as ``str``.
:raises AppointmentCreateFailed: If the appointment could not be created.
diff --git a/src/openforms/appointments/contrib/demo/plugin.py b/src/openforms/appointments/contrib/demo/plugin.py
index fe3cb57808..aec28e3ae0 100644
--- a/src/openforms/appointments/contrib/demo/plugin.py
+++ b/src/openforms/appointments/contrib/demo/plugin.py
@@ -43,7 +43,7 @@ def get_dates(self, products, location, start_at=None, end_at=None):
def get_times(self, products, location, day):
today = timezone.localdate()
- times = (time(12, 0), time(15, 15), time(15, 45))
+ times = (time(12, 0), time(15, 15), time(15, 45), time(17, 45))
return [timezone.make_aware(datetime.combine(today, _time)) for _time in times]
def get_required_customer_fields(
diff --git a/src/openforms/appointments/contrib/jcc/plugin.py b/src/openforms/appointments/contrib/jcc/plugin.py
index 40586a2703..0879caacea 100644
--- a/src/openforms/appointments/contrib/jcc/plugin.py
+++ b/src/openforms/appointments/contrib/jcc/plugin.py
@@ -1,5 +1,4 @@
import logging
-import warnings
from collections import Counter
from contextlib import contextmanager
from datetime import date, datetime
@@ -20,14 +19,7 @@
from openforms.plugins.exceptions import InvalidPluginConfiguration
from openforms.utils.date import TIMEZONE_AMS, datetime_in_amsterdam
-from ...base import (
- AppointmentDetails,
- BasePlugin,
- Customer,
- CustomerDetails,
- Location,
- Product,
-)
+from ...base import AppointmentDetails, BasePlugin, CustomerDetails, Location, Product
from ...exceptions import (
AppointmentCreateFailed,
AppointmentDeleteFailed,
@@ -251,28 +243,10 @@ def create_appointment(
products: list[Product],
location: Location,
start_at: datetime,
- client: CustomerDetails[CustomerFields] | Customer,
+ client: CustomerDetails[CustomerFields],
remarks: str = "",
) -> str:
product_ids = squash_ids(products)
-
- # Phasing out Customer in favour of CustomerDetails, so convert to the new type
- if isinstance(client, Customer):
- warnings.warn(
- "Fixed customer fields via the Customer class are deprecated, use "
- "dynamic CustomerDetails with 'get_required_customer_fields' instead.",
- DeprecationWarning,
- )
- client = CustomerDetails(
- details={
- CustomerFields.last_name: client.last_name,
- CustomerFields.birthday: client.birthdate.isoformat(),
- # Phone number is often required for appointment,
- # use fake phone number if no client phone number
- CustomerFields.main_tel: client.phonenumber or "0123456789",
- }
- )
-
customer_details = {
FIELD_TO_XML_NAME[key]: value for key, value in client.details.items()
}
diff --git a/src/openforms/appointments/contrib/qmatic/plugin.py b/src/openforms/appointments/contrib/qmatic/plugin.py
index d49b3aa206..9c639abeb6 100644
--- a/src/openforms/appointments/contrib/qmatic/plugin.py
+++ b/src/openforms/appointments/contrib/qmatic/plugin.py
@@ -1,5 +1,4 @@
import json
-import logging
import warnings
from collections import Counter
from contextlib import contextmanager
@@ -19,14 +18,7 @@
from openforms.formio.typing import Component
from openforms.plugins.exceptions import InvalidPluginConfiguration
-from ...base import (
- AppointmentDetails,
- BasePlugin,
- Customer,
- CustomerDetails,
- Location,
- Product,
-)
+from ...base import AppointmentDetails, BasePlugin, CustomerDetails, Location, Product
from ...exceptions import (
AppointmentCreateFailed,
AppointmentDeleteFailed,
@@ -73,25 +65,6 @@ def wrapper(*args, **kwargs) -> T:
return decorator
-def normalize_customer_details(client: _CustomerDetails | Customer) -> _CustomerDetails:
- # Phasing out Customer in favour of CustomerDetails, so convert to the new type
- if isinstance(client, Customer):
- warnings.warn(
- "Fixed customer fields via the Customer class are deprecated, use "
- "dynamic CustomerDetails with 'get_required_customer_fields' instead.",
- DeprecationWarning,
- )
- client = _CustomerDetails(
- details={
- CustomerFields.last_name: client.last_name,
- CustomerFields.birthday: client.birthdate.isoformat(),
- CustomerFields.first_name: client.initials or "",
- CustomerFields.phone_number: client.phonenumber or "",
- }
- )
- return client
-
-
@register("qmatic")
class QmaticAppointment(BasePlugin[CustomerFields]):
"""
@@ -314,11 +287,18 @@ def create_appointment(
products: list[Product],
location: Location,
start_at: datetime,
- client: _CustomerDetails | Customer,
+ client: _CustomerDetails,
remarks: str = "",
) -> str:
assert products, "Can't book for empty products"
- customer = normalize_customer_details(client)
+ customer = _CustomerDetails(
+ details={
+ CustomerFields.last_name: client.last_name,
+ CustomerFields.birthday: client.birthdate.isoformat(),
+ CustomerFields.first_name: client.initials or "",
+ CustomerFields.phone_number: client.phonenumber or "",
+ }
+ )
product_names = ", ".join(sorted({product.name for product in products}))
unique_product_ids, num_customers = self._count_products(products)
diff --git a/src/openforms/appointments/tasks.py b/src/openforms/appointments/tasks.py
index 4411a750ed..4cbd164f1b 100644
--- a/src/openforms/appointments/tasks.py
+++ b/src/openforms/appointments/tasks.py
@@ -1,5 +1,4 @@
import logging
-import warnings
from celery_once import QueueOnce
@@ -8,10 +7,8 @@
from .core import book_for_submission
from .exceptions import AppointmentRegistrationFailed, NoAppointmentForm
-from .models import AppointmentInfo
-from .utils import book_appointment_for_submission
-__all__ = ["maybe_register_appointment"]
+__all__ = ["register_appointment"]
logger = logging.getLogger(__name__)
@@ -21,7 +18,7 @@
ignore_result=False,
once={"graceful": True}, # do not spam error monitoring
)
-def maybe_register_appointment(submission_id: int) -> None | str:
+def register_appointment(submission_id: int) -> None | str:
"""
Register an appointment for the submission IF relevant.
@@ -32,26 +29,9 @@ def maybe_register_appointment(submission_id: int) -> None | str:
be stored in the database. If appointment registration fails, this feedback
should find its way back to the end-user.
"""
- warnings.warn(
- "This task is deprecated because of the new appointment flow.",
- PendingDeprecationWarning,
- )
- logger.info("Registering appointment for submission %d (if needed!)", submission_id)
+ logger.info("Registering appointment for submission %d", submission_id)
submission = Submission.objects.select_related("form").get(id=submission_id)
- try:
- appointment_id = submission.appointment_info.appointment_id
- except AppointmentInfo.DoesNotExist:
- pass
- else:
- # idempotency - do not register a new appointment if there already is one.
- if appointment_id:
- logger.info(
- "Submission %s already has an appointment ID, aborting.", submission.pk
- )
- return
-
- # Try the new appointments implementation first
try:
return book_for_submission(submission=submission)
except NoAppointmentForm:
@@ -63,15 +43,3 @@ def maybe_register_appointment(submission_id: int) -> None | str:
extra={"submission": submission_id},
)
raise
-
- # otherwise, fall back to the old form
- logger.info("Attempting old appointment booking for submission %r", submission_id)
- try:
- book_appointment_for_submission(submission)
- except AppointmentRegistrationFailed as exc:
- logger.info(
- "Appointment registration failed, aborting workflow.",
- exc_info=exc,
- extra={"submission": submission_id},
- )
- raise
diff --git a/src/openforms/appointments/utils.py b/src/openforms/appointments/utils.py
index 2d9213dfab..0b7b435d92 100644
--- a/src/openforms/appointments/utils.py
+++ b/src/openforms/appointments/utils.py
@@ -2,25 +2,18 @@
import io
import logging
import re
-import warnings
-from datetime import datetime
from django.utils.translation import gettext_lazy as _
import elasticapm
import qrcode
-from openforms.forms.models import Form, FormStep
from openforms.logging import logevent
from openforms.submissions.models import Submission
-from .base import BasePlugin, Customer, Location, Product
+from .base import BasePlugin
from .constants import AppointmentDetailsStatus
-from .exceptions import (
- AppointmentCreateFailed,
- AppointmentDeleteFailed,
- AppointmentRegistrationFailed,
-)
+from .exceptions import AppointmentDeleteFailed
from .models import Appointment, AppointmentInfo, AppointmentsConfig
from .registry import register
@@ -36,18 +29,6 @@ def get_plugin(plugin: str = "") -> BasePlugin:
return register[plugin]
-def get_missing_fields_labels(
- appointment_data: dict, missing_fields_keys: list[str]
-) -> list[str]:
- labels = []
- for key in missing_fields_keys:
- if label := appointment_data.get(key, {}).get("label"):
- labels.append(label)
- else:
- labels.append(key)
- return sorted(labels)
-
-
def get_formatted_phone_number(phone_number: str | None) -> str | None:
"""
Remove any character that isn't numeric or a space, +, or - character
@@ -61,118 +42,6 @@ def get_formatted_phone_number(phone_number: str | None) -> str | None:
return phone_number[:16]
-@elasticapm.capture_span(span_type="app.appointments.book")
-def book_appointment_for_submission(submission: Submission) -> None:
- warnings.warn(
- "Old-style appointments are deprecated, please update the form to use "
- "the reworked appointments.",
- DeprecationWarning,
- )
- try:
- # Delete the previous appointment info if there is one since
- # since a new one will be created
- # This function will be called multiple times on a failure so
- # this is the case a previous appointment_info may exist
- submission.appointment_info.delete()
- except AppointmentInfo.DoesNotExist:
- pass
-
- appointment_data = submission.get_merged_appointment_data()
-
- expected_information = [
- "productIDAndName",
- "locationIDAndName",
- "appStartTime",
- "clientLastName",
- "clientDateOfBirth",
- ]
-
- absent_or_empty_information = []
-
- for key in expected_information:
- # there is a non-empty value, continue - this is good
- if appointment_data.get(key, {}).get("value"):
- continue
- absent_or_empty_information.append(key)
-
- # Submission was never intended to make an appointment so just return
- if set(absent_or_empty_information) == set(expected_information):
- return
-
- # Partially filled out form (or appointment fields are present in the form and not
- # filled at all). Note that the "contract" states an exception gets raised here
- # which aborts the celery chain execution so that the end-user can be shown the
- # error information.
- if absent_or_empty_information:
- # Incomplete information to make an appointment
- logevent.appointment_register_skip(submission)
- missing_fields_labels = get_missing_fields_labels(
- appointment_data, absent_or_empty_information
- )
- error_information = _(
- "The following appointment fields should be filled out: {fields}"
- ).format(fields=", ".join(missing_fields_labels))
- AppointmentInfo.objects.create(
- status=AppointmentDetailsStatus.missing_info,
- error_information=error_information,
- submission=submission,
- )
- raise AppointmentRegistrationFailed(
- "No registration attempted because of incomplete information. "
- )
-
- product = Product(
- identifier=appointment_data["productIDAndName"]["value"]["identifier"],
- name=appointment_data["productIDAndName"]["value"]["name"],
- )
- location = Location(
- identifier=appointment_data["locationIDAndName"]["value"]["identifier"],
- name=appointment_data["locationIDAndName"]["value"]["name"],
- )
- appointment_client = Customer(
- last_name=appointment_data["clientLastName"]["value"],
- birthdate=datetime.strptime(
- appointment_data["clientDateOfBirth"]["value"], "%Y-%m-%d"
- ).date(),
- phonenumber=get_formatted_phone_number(
- appointment_data.get("clientPhoneNumber", {}).get("value")
- ),
- )
- start_at = datetime.strptime(
- appointment_data["appStartTime"]["value"], "%Y-%m-%dT%H:%M:%S%z"
- )
-
- plugin = get_plugin()
- try:
- logevent.appointment_register_start(submission, plugin)
- appointment_id = plugin.create_appointment(
- [product], location, start_at, appointment_client
- )
- appointment_info = AppointmentInfo.objects.create(
- status=AppointmentDetailsStatus.success,
- appointment_id=appointment_id,
- submission=submission,
- start_time=start_at,
- )
- logevent.appointment_register_success(appointment_info, plugin)
- except AppointmentCreateFailed as e:
- logger.error("Appointment creation failed", exc_info=e)
- # This is displayed to the end-user!
- error_information = _(
- "A technical error occurred while we tried to book your appointment. "
- "Please verify if all the data is correct or try again later."
- )
- appointment_info = AppointmentInfo.objects.create(
- status=AppointmentDetailsStatus.failed,
- error_information=error_information,
- submission=submission,
- )
- logevent.appointment_register_failure(appointment_info, plugin, e)
- raise AppointmentRegistrationFailed("Unable to create appointment") from e
-
- cancel_previous_submission_appointment(submission)
-
-
@elasticapm.capture_span(span_type="app.appointments.cancel")
def cancel_previous_submission_appointment(submission: Submission) -> None:
"""
@@ -260,26 +129,6 @@ def create_base64_qrcode(text):
return base64.b64encode(buffer.read()).decode("ascii")
-def find_first_appointment_step(form: Form) -> FormStep | None:
- """
- Find the first step in a form dealing with appointments.
-
- This looks at the component configuration for each step and detects if a component
- is holding appointment-related meta-information. If no such step is found, ``None``
- is returned.
- """
- for form_step in form.formstep_set.select_related("form_definition"):
- for component in form_step.iter_components(recursive=True):
- if "appointments" not in component:
- continue
-
- if component["appointments"].get("showProducts"):
- return form_step
-
- # no component in any form step found that satisfies
- return None
-
-
def get_confirmation_mail_suffix(submission: Submission) -> str:
"""
Determine the suffix, if appropriate for the subject of the confirmation mail.
diff --git a/src/openforms/formio/formatters/tests/files/appointments_components.json b/src/openforms/formio/formatters/tests/files/appointments_components.json
index 5d5f657ba7..e69de29bb2 100644
--- a/src/openforms/formio/formatters/tests/files/appointments_components.json
+++ b/src/openforms/formio/formatters/tests/files/appointments_components.json
@@ -1,805 +0,0 @@
-{
- "display": "form",
- "components": [
- {
- "id": "e1vezz1",
- "key": "appointmentProduct",
- "type": "select",
- "input": true,
- "label": "Select Appointment Product",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showProducts": true
- }
- },
- {
- "id": "e1vezz2",
- "key": "appointmentProductEmpty",
- "type": "select",
- "input": true,
- "label": "Select Appointment Product Empty",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showProducts": true
- }
- },
- {
- "id": "e1vezz3",
- "key": "appointmentLocation",
- "type": "select",
- "input": true,
- "label": "Select Appointment Location",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showLocations": true
- }
- },
- {
- "id": "e1vezz4",
- "key": "appointmentLocationEmpty",
- "type": "select",
- "input": true,
- "label": "Select Appointment Location Empty",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showLocations": true
- }
- },
- {
- "id": "e1vezz5",
- "key": "appointmentDate",
- "type": "select",
- "input": true,
- "label": "Select Appointment Date",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showDates": true
- }
- },
- {
- "id": "e1vezz6",
- "key": "appointmentDateEmpty",
- "type": "select",
- "input": true,
- "label": "Select Appointment Date Empty",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showDates": true
- }
- },
- {
- "id": "e1vezz7",
- "key": "appointmentTime",
- "type": "select",
- "input": true,
- "label": "Select Appointment Time",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showTimes": true
- }
- },
- {
- "id": "e1vezz8",
- "key": "appointmentTimeEmpty",
- "type": "select",
- "input": true,
- "label": "Select Appointment Time Empty",
- "limit": 100,
- "filter": "",
- "hidden": false,
- "idPath": "id",
- "prefix": "",
- "suffix": "",
- "unique": false,
- "widget": null,
- "dataSrc": "values",
- "dbIndex": false,
- "overlay": {
- "top": "",
- "left": "",
- "style": "",
- "width": "",
- "height": ""
- },
- "tooltip": "",
- "disabled": false,
- "lazyLoad": true,
- "multiple": false,
- "redrawOn": "",
- "tabindex": "",
- "template": "{{ item.label }}",
- "validate": {
- "custom": "",
- "unique": false,
- "plugins": [],
- "multiple": false,
- "required": true,
- "customPrivate": false,
- "onlyAvailableItems": false,
- "strictDateValidation": false
- },
- "autofocus": false,
- "encrypted": false,
- "hideLabel": false,
- "indexeddb": {
- "filter": {}
- },
- "minSearch": 0,
- "modalEdit": false,
- "protected": false,
- "refreshOn": "",
- "tableView": true,
- "attributes": {},
- "errorLabel": "",
- "persistent": true,
- "properties": {},
- "validateOn": "change",
- "clearOnHide": true,
- "conditional": {
- "eq": "",
- "show": null,
- "when": null
- },
- "customClass": "",
- "description": "",
- "fuseOptions": {
- "include": "score",
- "threshold": 0.3
- },
- "ignoreCache": false,
- "placeholder": "",
- "searchField": "",
- "showInEmail": true,
- "authenticate": false,
- "defaultValue": "",
- "registration": {
- "attribute": ""
- },
- "selectFields": "",
- "customOptions": {},
- "dataGridLabel": false,
- "labelPosition": "top",
- "readOnlyValue": false,
- "searchEnabled": true,
- "showCharCount": false,
- "showWordCount": false,
- "uniqueOptions": false,
- "valueProperty": "",
- "calculateValue": "",
- "clearOnRefresh": false,
- "useExactSearch": false,
- "calculateServer": false,
- "isSensitiveData": false,
- "selectThreshold": 0.3,
- "allowMultipleMasks": false,
- "customDefaultValue": "",
- "allowCalculateOverride": false,
- "appointments": {
- "showTimes": true
- }
- }
- ]
-}
diff --git a/src/openforms/formio/formatters/tests/files/appointments_data.json b/src/openforms/formio/formatters/tests/files/appointments_data.json
index 888c38843e..e69de29bb2 100644
--- a/src/openforms/formio/formatters/tests/files/appointments_data.json
+++ b/src/openforms/formio/formatters/tests/files/appointments_data.json
@@ -1,10 +0,0 @@
-{
- "appointmentProduct": {"identifier": "foo", "name": "Foo Product"},
- "appointmentProductEmpty": "",
- "appointmentLocation": {"identifier": "foo", "name": "Foo Location"},
- "appointmentLocationEmpty": "",
- "appointmentDate": "2022-02-14",
- "appointmentDateEmpty": "",
- "appointmentTime": "2022-02-14T08:15:00+01:00",
- "appointmentTimeEmpty": ""
-}
diff --git a/src/openforms/submissions/models/submission.py b/src/openforms/submissions/models/submission.py
index f41ec6716f..a527d0403a 100644
--- a/src/openforms/submissions/models/submission.py
+++ b/src/openforms/submissions/models/submission.py
@@ -688,38 +688,6 @@ def get_last_completed_step(self) -> SubmissionStep | None:
submission_state = self.load_execution_state()
return submission_state.get_last_completed_step()
- def get_merged_appointment_data(self) -> dict[str, dict[str, str | dict]]:
- component_config_key_to_appointment_key = {
- "appointments.showProducts": "productIDAndName",
- "appointments.showLocations": "locationIDAndName",
- "appointments.showTimes": "appStartTime",
- "appointments.lastName": "clientLastName",
- "appointments.birthDate": "clientDateOfBirth",
- "appointments.phoneNumber": "clientPhoneNumber",
- }
-
- merged_data = self.data
- appointment_data = {}
-
- for component in self.form.iter_components(recursive=True):
- # is this component any of the keys were looking for?
- for (
- component_key,
- appointment_key,
- ) in component_config_key_to_appointment_key.items():
- is_the_right_component = glom(component, component_key, default=False)
- if not is_the_right_component:
- continue
-
- # it is the right component, get the value and store it
- appointment_data[appointment_key] = {
- "label": component["label"],
- "value": merged_data.get(component["key"]),
- }
- break
-
- return appointment_data
-
@property
def data(self) -> dict[str, Any]:
"""The filled-in data of the submission.
diff --git a/src/openforms/submissions/tasks/__init__.py b/src/openforms/submissions/tasks/__init__.py
index 38c80485a1..6fdbfe4dac 100644
--- a/src/openforms/submissions/tasks/__init__.py
+++ b/src/openforms/submissions/tasks/__init__.py
@@ -7,7 +7,7 @@
from celery import chain
from celery.result import AsyncResult
-from openforms.appointments.tasks import maybe_register_appointment
+from openforms.appointments.tasks import register_appointment
from openforms.celery import app
from openforms.config.models import GlobalConfiguration
@@ -33,9 +33,8 @@ def on_post_submission_event(submission_id: int, event: PostSubmissionEvents) ->
# this can run any time because they have been claimed earlier
cleanup_temporary_files_for.delay(submission_id)
- # If the form involves appointments and no appointment has been scheduled yet, schedule it.
- # Todo: deprecated => Not needed with the new appointment flow
- register_appointment_task = maybe_register_appointment.si(submission_id)
+ # Register an appointment if the submission is for a form which is configured to create appointments.
+ register_appointment_task = register_appointment.si(submission_id)
# Perform any pre-registration task specified by the registration plugin. If no registration plugin is configured,
# just set a submission reference (if it hasn't already been set)