Confirm Vaccination
After user has selected vaccine, campaign and their desired slot, we have to show a confirm page where user can review the details and confirm their vaccination. In this video, we are going to create this confirm vaccination page.
Resources
Reserve Vaccine
Before, creating confirm-vaccination page, we need to create a function to reserve the vaccine. Because, in our models we have certain fields that needs to be check and updated before confirming the vaccination.
So, open your models.py and in the slot model we will create a method named reserve_vaccine.
# This method will take campaign_id and slot_id
def reserve_vaccine(campaign_id, slot_id):
# In this method, we are basically going to do two things parallelly whenever the user try to schedule a new vaccination.
# At first we will update the value of booked_quantity of storage model by 1 unit.
# And then will update the value of reserved of slot model by 1 unit.
# Now, import the storage model
from center.models import Storage
# At first, get the slot instance
slot = Slot.objects.get(id=slot_id)
# Then, get the campaign instance
campaign = Campaign.objects.get(id=campaign_id)
# After that get the storage instance
storage = Storage.objects.get(center=campaign.center, vaccine=campaign.vaccine)
# Now, to reserve a vaccine there are some criterias which is required to be fulfilled.
# The first criteria is, the total quantity of vaccine storage instance should be greater than 0.
# The second criteria is, the booked quantity of vaccine storage instance should be less than the total quantity
# And the last criteria is, the reserved value of slot instance should be less than the max_capacity of slot.
if (storage.total_quantity > 0 and storage.booked_quantity < storage.total_quantity and slot.reserved < slot.max_capacity):
# Once all this three criteria is fullfilled, we can increament the value of reserved and booked_quantity by 1 unit.
# To increment the value of reserved and booked_quantity we will use F expression, so lets import it.
from django.db.models import F
# Using F expression, we can increment the value of database field based on the current value of that field in database.
# So, using F expression, we are increment the value based on value stored in database not based on value stored in python memory during the request handling.
slot.reserved = F("reserved") + 1
storage.booked_quantity = F("booked_quantity") + 1
slot.save()
storage.save()
return True
return False
In this way, we have created a method that we can use while reserving a vaccine for a patient.
Now, lets create a view that to confirm the vaccination request of the user.
Forms
At first, create a forms.py file. And in this file, we will create a VaccinationForm that will be used in the confirm-vaccination page.
from django import forms
from django.forms import ModelForm
from vaccination.models import Vaccination
# Now, create a modelform named VaccinationForm
class VaccinationForm(ModelForm):
# This form will be a little unique than the forms which we have created earlier.
# Because I am going hide all the fields of this form.
# I am doing this because I only want to use this form internally. I don't want user to manipulate this form.
def __init__(self, *args, **kwargs):
super(VaccinationForm, self).__init__(*args, **kwargs)
for visible in self.visible_fields():
visible.field.widget = forms.HiddenInput()
class Meta:
model = Vaccination
fields = ["patient", "campaign", "slot"]
labels = {"campaign": "Vaccine / Center Name", "slot": "Date / Slot"}
Views
# Now, open your views.py file and import the VaccinationForm.
from vaccination.forms import VaccinationForm
# Also, import the HTTPResponse and HttpResponseBadRequest because we will use it later in this video.
from django.http import HttpResponse, HttpResponseBadRequest
# Now, create a confirm vaccination view.
# Then, import the View from django.views
from django.views import View
class ConfirmVaccination(View):
# Now, specify the form class
form_class = VaccinationForm
# After that, at first, we will handle the get request.
def get(self, request, *args, **kwargs):
# Whenever, the user completes the choose vaccine, choose campaign, choose slot process,
# then at last, we will show user to review all the final details like which vaccine you have choosed, which campaign and slot you have choosed.
# So, lets handle this data in this get request.
# At first, get the campaign instance
campaign = Campaign.objects.get(id=self.kwargs["campaign_id"])
# Then get the slot instance.
slot = Slot.objects.get(id=self.kwargs["slot_id"])
# After that, we will instantiate the form
form = self.form_class(initial={"patient": request.user, "campaign": campaign, "slot": slot})
# Now, we will create a context to pass all these informations to the user.
context = {
"patient": request.user,
"campaign": campaign,
"slot": slot,
"form": form
}
return render(request, "vaccination/confirm-vaccination.html", context)
Templates
Now, lets create a template named confirm-vaccination.html.
I have attached a file named confirm-vaccination.html in the resources section. Please download it and paste its content in the html file.
{% extends 'mysite/base.html' %}
{% block title %}
<title>Confirm Vaccination</title>
{% endblock title %}
{% block content %}
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title mb-4">
<i class="fas fa-calendar"></i> Review the vaccination details
</h5>
<div class="container">
<div class="row">
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Patient Name
</div>
<div class="col-7 col-md-8">
{{ patient.get_full_name }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Email
</div>
<div class="col-7 col-md-8">
{{ patient.email }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Gender
</div>
<div class="col-7 col-md-8">
{{ patient.gender }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Date of Birth
</div>
<div class="col-7 col-md-8">
{{ patient.date_of_birth }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Blood Group
</div>
<div class="col-7 col-md-8">
{{ patient.blood_group }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
{{ patient.identity_document_type }}
</div>
<div class="col-7 col-md-8">
{{ patient.identity_document_number }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Vaccine
</div>
<div class="col-7 col-md-8">
{{ campaign.vaccine.name }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Scheduled Date
</div>
<div class="col-7 col-md-8">
{{ slot.date }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Reporting Time
</div>
<div class="col-7 col-md-8">
{{ slot.start_time }} - {{ slot.end_time}}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Center Name
</div>
<div class="col-7 col-md-8">
{{ campaign.center.name }}
</div>
</div>
<div class="row mb-1">
<div class="col-5 col-md-4 fw-bold">
Center Address
</div>
<div class="col-7 col-md-8">
{{ campaign.center.address}}
</div>
</div>
<div class="row mb-1">
<form method="POST" action="">
{% csrf_token %} {{ form.as_p }}
<button type="submit" class="btn btn-success m-3">
<i class="fas fa-clock"></i> Schedule
</button>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
URLS
At last, lets create a url path to access the view.
path("confirm-vaccination/<int:campaign_id>/<int:slot_id>/", views.ConfirmVaccination.as_view(), name="confirm-vaccination"),
Now, add this url path in the choose-slot.html
<td><a href="{% url 'vaccination:confirm-vaccination' slot.campaign.id slot.id %}" class="btn-sm btn-outline-primary">Choose</a></td>
[Run the development server and see the changes]
Post request
At last, lets handle the confirm vaccination logic on post request.
def post(self, request, *args, **kwargs):
# So, basically, when the user completes reviewing the final details, we have to confirm the vaccination request.
# Confirming the vaccination request means that we have to save this Vaccination form.
form = self.form_class(request.POST)
# At first, lets check whether the form is valid or not.
if form.is_valid():
# Now before saving the form, we need to use the reserve vaccine function which we created at the starting of this video.
is_reserved = Slot.reserve_vaccine(self.kwargs["campaign_id"], self.kwargs["slot_id"])
# If the value of is_reserved is True then only we have to save the form.
if is_reserved:
form.save()
# After saving the form, we will send a congratulation message.
return HttpResponse("Congratulations! Your vaccination has been scheduled")
# If the value of is_reserved is False, then one or more criteria is not fulfilled and we are not able to reserve the vaccine for that patient. So, we need to return a sorry message
return HttpResponse("Sorry! We are unable to reserve vaccine for you at this moment")
# If the form is invalid, we will return HttpResponseBadRequest
return HttpResponseBadRequest("Invalid form data")
[Run the development server and see the changes]