Skip to content

Commit

Permalink
Disallow duplicate user email (#44)
Browse files Browse the repository at this point in the history
* New placeholders

* Allow one email or phone per district or pincode

* transaction test

* Fix assertions

* Fix formatting issues

* Run black only on push, not PR. See issue wearerequired/lint-action#13

* Messages UI

*Alert Messages UI

* Fix test

* Test case and ago group
  • Loading branch information
zrthxn authored May 21, 2021
1 parent b680155 commit 9eb4c59
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 52 deletions.
2 changes: 0 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ on:
# Triggers the workflow on push or pull request events but only for the master branch
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
black:
Expand Down
10 changes: 9 additions & 1 deletion static/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ a {
margin: auto;

width: 20em;
height: 40em;
height: 42em;

padding: 1em 2em;
padding-bottom: 0;
Expand Down Expand Up @@ -182,6 +182,14 @@ a {
z-index: 1;
}

#search-form form .form-group {
margin-bottom: 0.5rem;
}

#search-form form .form-field:nth-of-type(2) .form-group {
margin-top: 0.5rem;
}

/* Search type selectors */
#search_type-field {
display: flex;
Expand Down
58 changes: 53 additions & 5 deletions subscribers/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ class Meta:
"search_type",
]
widgets = {
"email": forms.TextInput(attrs={"placeholder": "Email"}),
"phone_number": forms.TextInput(attrs={"placeholder": "Phone Number"}),
"pincode": forms.TextInput(attrs={"placeholder": "Pincode"}),
"email": forms.TextInput(attrs={"placeholder": "you@example.com"}),
"phone_number": forms.TextInput(
attrs={"placeholder": "10-digit number (Optional)"}
),
"pincode": forms.TextInput(attrs={"placeholder": "110006"}),
"district_id": forms.Select,
}

Expand All @@ -40,8 +42,8 @@ def clean(self):
if not cleaned_data.get("email") and not cleaned_data.get("phone_number"):
error.update(
{
"email": "Please enter at least one out of email or phone number.",
"phone_number": "Please enter at least one out of email or phone number.",
"email": "Please enter either email or phone number.",
"phone_number": "Please enter either email or phone number.",
}
)

Expand All @@ -67,6 +69,52 @@ def clean(self):
"district_id": "Please select your district",
}
)

if cleaned_data.get("email") or cleaned_data.get("phone_number"):
email = cleaned_data.get("email")
phone_number = cleaned_data.get("phone_number")

if cleaned_data.get("pincode"):
if email:
if Subscriber.objects.filter(
email=email, pincode=cleaned_data.get("pincode")
).exists():
error.update(
{
"pincode": "You have already subscribed at this pincode.",
}
)
elif phone_number:
if Subscriber.objects.filter(
phone_number=phone_number, pincode=cleaned_data.get("pincode")
).exists():
error.update(
{
"pincode": "You have already subscribed at this pincode.",
}
)

if cleaned_data.get("district_id"):
if email:
if Subscriber.objects.filter(
email=email, district_id=cleaned_data.get("district_id")
).exists():
error.update(
{
"district_id": "You have already subscribed at this district.",
}
)
elif phone_number:
if Subscriber.objects.filter(
phone_number=phone_number,
district_id=cleaned_data.get("district_id"),
).exists():
error.update(
{
"district_id": "You have already subscribed at this district.",
}
)

if cleaned_data.get("pincode") and cleaned_data.get("district_id"):
cleaned_data.pop("district_id")

Expand Down
21 changes: 16 additions & 5 deletions subscribers/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
from subscribers.utils import send_mail, send_whatsapp

AGE_CATEGORY = [
(18, "18+"),
(45, "45+"),
(18, "18 and older"),
(45, "45 and older"),
]


Expand All @@ -28,10 +28,17 @@ class Subscriber(models.Model):
validators=[MinValueValidator(100000), MaxValueValidator(999999)],
blank=True,
null=True,
help_text="Don't know your pincode? Use 'By District'",
)
district_id = models.IntegerField(
"district",
blank=True,
null=True,
help_text="Districts are based on voting districts",
)
district_id = models.IntegerField("district", blank=True, null=True)
age_limit = models.IntegerField(
"age limit",
help_text="Select your age category",
choices=AGE_CATEGORY,
default=AGE_CATEGORY[0][0],
null=False,
Expand All @@ -52,9 +59,13 @@ class Subscriber(models.Model):
)

def __str__(self):
s = []
if self.email:
s.append(str(self.email))
if self.phone_number:
return str(self.phone_number)
return self.email
s.append(str(self.phone_number))

return " ".join(s)

@staticmethod
def _filter_centers(centers, age_limit):
Expand Down
19 changes: 11 additions & 8 deletions subscribers/templates/subscribers/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,17 @@ <h1 class="display-3">Vaccination Notifications</h1>

<main>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
<div id="message-container"
style="position: fixed; padding: 2em 1em; max-width: 32em; margin: auto; z-index: 10; bottom: 0; right: 0;">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}

{% block content %}
Expand Down
8 changes: 4 additions & 4 deletions subscribers/templates/subscribers/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@
</div>
</div>

<div id="age_limit-field" class="form-field">
{{ form.age_limit|as_crispy_field }}
</div>

<div id="email-field" class="form-field">
{{ form.email|as_crispy_field }}
</div>
Expand All @@ -37,10 +41,6 @@
{{ form.phone_number|as_crispy_field }}
</div>

<div id="age_limit-field" class="form-field">
{{ form.age_limit|as_crispy_field }}
</div>

<div id="pincode-field" class="form-field">
{{ form.pincode|as_crispy_field }}
</div>
Expand Down
4 changes: 2 additions & 2 deletions subscribers/tests/test_forms.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from http import HTTPStatus

from django.contrib.messages import get_messages
from django.test import SimpleTestCase
from django.test import TestCase

from subscribers.forms import SubscriberForm


class TestSubscriberForm(SimpleTestCase):
class TestSubscriberForm(TestCase):
def test_valid_form_data(self):
valid_form_data = [
{
Expand Down
7 changes: 7 additions & 0 deletions subscribers/tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ def setUp(self):
self.subscriber2 = Subscriber.objects.create(
phone_number="9999999999", district_id=1
)
self.subscriber3 = Subscriber.objects.create(
email="foo@bar.com",
phone_number="9999999999",
pincode=222222,
district_id=2,
)

self.test_centers = [
{
Expand Down Expand Up @@ -149,6 +155,7 @@ def setUp(self):
def test_str_method(self):
self.assertEqual(str(self.subscriber1), "foo@bar.com")
self.assertEqual(str(self.subscriber2), "+919999999999")
self.assertEqual(str(self.subscriber3), "foo@bar.com +919999999999")

def test_filter_centers(self):
filter_18 = Subscriber._filter_centers(self.parsed_test_centers, 18)
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion subscribers/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def test_subscriber_create_view_post_valid(self):
self.assertEqual(len(messages), 1)
self.assertEqual(
str(messages[0]),
"You will be notified via email whenever a vaccinaton slot is available!",
"You will be notified when a vaccinaton slot is available!",
)

def test_unsubscriber_view_get(self):
Expand Down
4 changes: 2 additions & 2 deletions subscribers/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class SubscriberCreateView(SuccessMessageMixin, FormView):

template_name = "subscribers/index.html"
success_message = (
"You will be notified via email whenever a vaccinaton slot is available!"
"You will be notified when a vaccinaton slot is available!"
)
success_url = "/"

Expand All @@ -38,7 +38,7 @@ def unsubscribe_view(request, pk):
messages.add_message(
request,
messages.SUCCESS,
"You have unsubscribed from slot availability updates.",
"You have unsubscribed from vaccinaton slot updates.",
)
except ObjectDoesNotExist:
messages.add_message(request, messages.WARNING, "Oops! Something went wrong.")
Expand Down

0 comments on commit 9eb4c59

Please sign in to comment.