adamspd / django-appointment

A Django app for managing appointment scheduling with ease and flexibility.
Apache License 2.0
95 stars 34 forks source link

Integrity error: prevent user to resubmit same appointment form #96

Closed adamspd closed 6 months ago

adamspd commented 6 months ago

Describe the bug Don't allow user to re-submit appointment information after the appointment has been successfully created.

To Reproduce Steps to reproduce the behavior: Created an appointment request on the page to select date and stuff, then send user info on the next page to create appointment. Aftewards, instead of creating a new appointment request, I used the arrow back button to come back to the page and then resend user information thus the same appointment request for the new appointment.

Expected behavior Prevent the users from going back and resubmitting the same information for an appointment after it's been successfully created.

Additional context

Environment:

Request Method: POST
Request URL: http://127.0.0.1:8000/en/verification-code/92/170765011615498819679753da1ee4e2db40b6bcac897ee20/

Django Version: 4.2.8
Python Version: 3.11.0
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'appointment.apps.AppointmentConfig',
 'django_q']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.locale.LocaleMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']

Traceback (most recent call last):
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/venv/lib/python3.11/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/venv/lib/python3.11/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute
    return super().execute(query, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The above exception (UNIQUE constraint failed: appointment_appointment.appointment_request_id) was the direct cause of the following exception:
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/venv/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/venv/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/appointment/views.py", line 400, in enter_verification_code
    response = create_appointment(request=request, appointment_request_obj=appointment_request_object,
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/appointment/views.py", line 278, in create_appointment
    appointment = create_and_save_appointment(appointment_request_obj, client_data, appointment_data)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/adamspierredavid/developer/PycharmProjects/django-appointment/appointment/utils/db_helpers.py", line 100, in create_and_save_appointment
    appointment = Appointment.objects.create(

Exception Type: IntegrityError at /en/verification-code/92/170765011615498819679753da1ee4e2db40b6bcac897ee20/
Exception Value: UNIQUE constraint failed: appointment_appointment.appointment_request_id

Possible Solution

  1. Use Session to Store Submission State: After the form is successfully submitted and the appointment is created, store a flag in the user's session to indicate that the submission has already occurred.

  2. Check Session on Form Page Load: On the page where the user fills out the form, check the session flag at the beginning of the request. If the flag indicates a submission has already occurred, redirect the user to a page that explains they cannot resubmit the form.

  3. Clear Session on Start of a New Appointment Process: Ensure that the flag in the session is cleared or reset when the user starts the process of creating a new appointment. This could be when they first load the form page under a new session or click a button to start a new appointment.