Skip to content

Commit

Permalink
Merge pull request #4872 from open-formulieren/cleanup/3283-remove-ol…
Browse files Browse the repository at this point in the history
…dstyle-appointments-flow

[#3283] Remove oldstyle appointments flow
  • Loading branch information
sergei-maertens authored Dec 11, 2024
2 parents 53bf9d8 + b956f22 commit beb73a0
Show file tree
Hide file tree
Showing 56 changed files with 165 additions and 4,236 deletions.
7 changes: 3 additions & 4 deletions docs/developers/backend/core/submissions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Globally, the various actions and plugin categories are processed in order:

#. If applicable, an :ref:`appointment <developers_appointment_plugins>` is
created. If this fails, the submission is blocked and the user sees an error
message and can try again (note: this step is deprecated and not needed for the new appointment flow).
message and can try again.
#. Pre-registration step. Each :ref:`registration plugin <developers_registration_plugins>` can perform
pre-registration task, like for example generating and setting a submission reference ID. If no registration backend
is configured, then an internal ID is generated and set on the submission.
Expand All @@ -39,9 +39,8 @@ Globally, the various actions and plugin categories are processed in order:
the previous actions, the confirmation email shows different contents.

The confirmation email can show submission details, appointment details
(including links to cancel or change the appointment), payment details
(including a link to pay if not done so already), cosign details and custom information as part
of the form.
(including links to cancel the appointment), payment details(including a link to pay if not done so already),
cosign details and custom information as part of the form.

Under the hood
--------------
Expand Down
Binary file not shown.
83 changes: 0 additions & 83 deletions docs/manual/forms/examples/appointment_creation.rst

This file was deleted.

12 changes: 0 additions & 12 deletions docs/manual/forms/examples/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,3 @@ Voorbeelden
suwinet
form_with_geometry
camunda7

======================
Verouderde voorbeelden
======================

Deze voorbeelden beschrijven functionaliteit die uitgefaseerd wordt. We raden af om nog
nieuwe formulieren hiermee te bouwen.

.. toctree::
:maxdepth: 1

appointment_creation
3 changes: 1 addition & 2 deletions docs/manual/templates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,9 +337,8 @@ Voorbeeld
*Opmerkingen*
Geen opmerkingen
Als u uw afspraak wilt annuleren of wijzigen kunt u dat hieronder doen.
Als u uw afspraak wilt annuleren kunt u dat hieronder doen.
Afspraak annuleren: https://example.com/...
Afspraak wijzigen: https://example.com/...
**Betaalinformatie**
Expand Down
21 changes: 4 additions & 17 deletions src/openforms/appointments/admin.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from copy import copy
from typing import Literal

from django.contrib import admin
from django.contrib.admin.widgets import AdminTextInputWidget
from django.utils import timezone
from django.utils.html import format_html_join
from django.utils.translation import gettext, gettext_lazy as _
from django.utils.html import format_html
from django.utils.translation import gettext_lazy as _

from solo.admin import SingletonModelAdmin

Expand Down Expand Up @@ -86,20 +85,8 @@ def get_object_actions(self, obj: AppointmentInfo) -> str:
if obj.start_time and obj.start_time <= timezone.now():
return "-"

actions: list[tuple[Literal["cancel", "change"], str]] = [
("cancel", gettext("Cancel")),
]

# legacy appointments have the change option
is_legacy = not obj.submission.form.is_appointment
if is_legacy:
actions.append(("change", gettext("Change")))

links = (
(BasePlugin.get_link(obj.submission, verb=action), label)
for action, label in actions
)
return format_html_join(" | ", '<a href="{}">{}</a>', links)
link = BasePlugin.get_cancel_link(obj.submission)
return format_html('<a href="{}">{}</a>', link, _("Cancel"))

get_object_actions.short_description = _("Appointment actions")

Expand Down
46 changes: 5 additions & 41 deletions src/openforms/appointments/api/views.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import warnings
from copy import copy

from django.db import transaction
Expand Down Expand Up @@ -52,14 +51,6 @@
logger = logging.getLogger(__name__)


def warn_serializer_validation_deprecation():
warnings.warn(
"Starting with Open Forms 3.0, input validation will raise HTTP 400 instead "
"of returning an empty result list.",
DeprecationWarning,
)


# TODO: see openforms.validations.api.serializers.ValidatorsFilterSerializer.as_openapi_params
# and https://github.com/open-formulieren/open-forms/issues/611

Expand Down Expand Up @@ -99,14 +90,7 @@ class ProductsListView(ListMixin, APIView):

def get_objects(self):
serializer = ProductInputSerializer(data=self.request.query_params)
is_valid = serializer.is_valid()
# TODO: ideally we want to use raise_exception=True, but the SDK and the way
# that Formio work is that we can't prevent the invalid request from firing.
# Instead, we just return an empty result list which populates dropdowns with
# empty options.
if not is_valid:
warn_serializer_validation_deprecation()
return []
serializer.is_valid(raise_exception=True)

plugin = get_plugin()
config = AppointmentsConfig().get_solo()
Expand Down Expand Up @@ -141,14 +125,8 @@ class LocationsListView(ListMixin, APIView):

def get_objects(self):
serializer = LocationInputSerializer(data=self.request.query_params)
is_valid = serializer.is_valid()
# TODO: ideally we want to use raise_exception=True, but the SDK and the way
# that Formio work is that we can't prevent the invalid request from firing.
# Instead, we just return an empty result list which populates dropdowns with
# empty options.
if not is_valid:
warn_serializer_validation_deprecation()
return []
serializer.is_valid(raise_exception=True)

products = serializer.validated_data["product_id"]
plugin = get_plugin()
with elasticapm.capture_span(
Expand Down Expand Up @@ -178,14 +156,7 @@ class DatesListView(ListMixin, APIView):

def get_objects(self):
serializer = DateInputSerializer(data=self.request.query_params)
is_valid = serializer.is_valid()
# TODO: ideally we want to use raise_exception=True, but the SDK and the way
# that Formio work is that we can't prevent the invalid request from firing.
# Instead, we just return an empty result list which populates dropdowns with
# empty options.
if not is_valid:
warn_serializer_validation_deprecation()
return []
serializer.is_valid(raise_exception=True)

products = serializer.validated_data["product_id"]
location = serializer.validated_data["location_id"]
Expand Down Expand Up @@ -226,14 +197,7 @@ class TimesListView(ListMixin, APIView):

def get_objects(self):
serializer = TimeInputSerializer(data=self.request.query_params)
is_valid = serializer.is_valid()
# TODO: ideally we want to use raise_exception=True, but the SDK and the way
# that Formio work is that we can't prevent the invalid request from firing.
# Instead, we just return an empty result list which populates dropdowns with
# empty options.
if not is_valid:
warn_serializer_validation_deprecation()
return []
serializer.is_valid(raise_exception=True)

products = serializer.validated_data["product_id"]
location = serializer.validated_data["location_id"]
Expand Down
31 changes: 4 additions & 27 deletions src/openforms/appointments/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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:
"""
Expand All @@ -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.
Expand Down Expand Up @@ -249,23 +234,15 @@ def get_appointment_details(self, identifier: str) -> AppointmentDetails:
# cosmetics

@staticmethod
def get_link(submission: Submission, verb: str) -> str:
def get_cancel_link(submission: Submission) -> str:
token = submission_appointment_token_generator.make_token(submission)

path = reverse(
f"appointments:appointments-verify-{verb.lower()}-appointment-link",
"appointments:appointments-verify-cancel-appointment-link",
kwargs={
"token": token,
"submission_uuid": submission.uuid,
},
)

return build_absolute_uri(path)

@classmethod
def get_cancel_link(cls, submission: Submission) -> str:
return cls.get_link(submission, "cancel")

@classmethod
def get_change_link(cls, submission: Submission) -> str:
return cls.get_link(submission, "change")
2 changes: 1 addition & 1 deletion src/openforms/appointments/contrib/demo/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def test_times_list(self):

self.assertEqual(response.status_code, status.HTTP_200_OK)
times = response.json()
self.assertEqual(len(times), 3)
self.assertEqual(len(times), 4)

def test_required_customer_fields_list(self):
endpoint = reverse("api:appointments-customer-fields")
Expand Down
30 changes: 2 additions & 28 deletions src/openforms/appointments/contrib/jcc/plugin.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import logging
import warnings
from collections import Counter
from contextlib import contextmanager
from datetime import date, datetime
Expand All @@ -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,
Expand Down Expand Up @@ -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()
}
Expand Down
Loading

0 comments on commit beb73a0

Please sign in to comment.