Skip to content

Commit

Permalink
Merge pull request #59 from City-of-Turku/feature/mailing-list-changes
Browse files Browse the repository at this point in the history
Feature/mailing list changes
  • Loading branch information
juuso-j authored Apr 30, 2024
2 parents 59fc260 + 0c461e5 commit 2ff6c9f
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 7 deletions.
2 changes: 1 addition & 1 deletion account/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class Meta:


class MailingListAdmin(DisableDeleteAdminMixin, DisableAddAdminMixin, admin.ModelAdmin):
list_display = ("result", "csv_emails")
list_display = ("result", "number_of_emails")

readonly_fields = ("result",)
form = MailingListAdminForm
Expand Down
13 changes: 9 additions & 4 deletions account/api/views.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django import db
from django.core.exceptions import ValidationError
from django.core.validators import validate_email
from django.db.utils import IntegrityError
from drf_spectacular.utils import extend_schema, OpenApiResponse
from rest_framework import status, viewsets
from rest_framework.decorators import action
Expand Down Expand Up @@ -93,8 +94,7 @@ def subscribe(self, request):
email = request.data.get("email", None)
if not email:
return Response("No 'email' provided", status=status.HTTP_400_BAD_REQUEST)
if MailingListEmail.objects.filter(email=email).count() > 0:
return Response("'email' exists", status=status.HTTP_400_BAD_REQUEST)

try:
validate_email(email)
except ValidationError as e:
Expand All @@ -103,8 +103,13 @@ def subscribe(self, request):
if not mailing_list:
# In case mailing list is not created for the result, it is created.
mailing_list = MailingList.objects.create(result=result)

MailingListEmail.objects.create(mailing_list=mailing_list, email=email)
try:
MailingListEmail.objects.create(mailing_list=mailing_list, email=email)
except IntegrityError:
return Response(
"'email' and 'result' must be jointly null",
status=status.HTTP_400_BAD_REQUEST,
)
user.has_subscribed = True
user.save()
return Response("subscribed", status=status.HTTP_201_CREATED)
Expand Down
25 changes: 25 additions & 0 deletions account/migrations/0015_email_and_mailing_list_jointly_unique.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 4.1.13 on 2024-04-30 07:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("account", "0014_remove_profile_is_filled_for_fun"),
]

operations = [
migrations.AlterField(
model_name="mailinglistemail",
name="email",
field=models.EmailField(max_length=254),
),
migrations.AddConstraint(
model_name="mailinglistemail",
constraint=models.UniqueConstraint(
fields=("email", "mailing_list"),
name="email_and_mailing_list_must_be_jointly:unique",
),
),
]
15 changes: 13 additions & 2 deletions account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,23 @@ def __str__(self):
def csv_emails(self):
return ",".join([e.email for e in self.emails.all()])

def number_of_emails(self):
return self.emails.count()


class MailingListEmail(models.Model):
email = models.EmailField(unique=True)
email = models.EmailField()
mailing_list = models.ForeignKey(
MailingList, related_name="emails", on_delete=models.CASCADE
)

def __str__(self):
return self.email
return f"{self.email} {self.mailing_list}"

class Meta:
constraints = [
models.UniqueConstraint(
fields=["email", "mailing_list"],
name="email_and_mailing_list_must_be_jointly:unique",
)
]
31 changes: 31 additions & 0 deletions account/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,34 @@ def test_mailing_list_unsubscribe_email_not_provided(
url = reverse("account:profiles-unsubscribe")
response = api_client_with_custom_ip_address.post(url)
assert response.status_code == 400


@pytest.mark.django_db
@pytest.mark.parametrize(
"ip_address",
[
("100.19.91.40"),
],
)
def test_mailing_list_unique_constraints(api_client_with_custom_ip_address, users):
url = reverse("account:profiles-subscribe")
user = users.get(username="test1")
response = api_client_with_custom_ip_address.post(
url, {"email": "[email protected]", "user": user.id}
)
assert response.status_code == 201
assert MailingListEmail.objects.count() == 1
# Subscribed as the result (MailingList) is different than for user 'test1'
user = users.get(username="test2")
response = api_client_with_custom_ip_address.post(
url, {"email": "[email protected]", "user": user.id}
)
assert response.status_code == 201
assert MailingListEmail.objects.count() == 2
# Fails, as the email and result are not jointly unique.
user = users.get(username="test3")
response = api_client_with_custom_ip_address.post(
url, {"email": "[email protected]", "user": user.id}
)
assert response.status_code == 400
assert MailingListEmail.objects.count() == 2

0 comments on commit 2ff6c9f

Please sign in to comment.