Skip to content

Commit 288722e

Browse files
committed
Move DateOfBirthResponse to its own model
1 parent da40fd3 commit 288722e

File tree

8 files changed

+152
-54
lines changed

8 files changed

+152
-54
lines changed

lung_cancer_screening/questions/forms/date_of_birth_form.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django import forms
22
from datetime import date
33

4-
from ..models.response_set import ResponseSet
4+
from ..models.date_of_birth_response import DateOfBirthResponse
55
from ...nhsuk_forms.split_date_field import SplitDateField
66

77

@@ -10,7 +10,7 @@ def __init__(self, *args, **kwargs):
1010
super().__init__(*args, **kwargs)
1111

1212
invalid_error_message = 'Date of birth must be a real date'
13-
self.fields["date_of_birth"] = SplitDateField(
13+
self.fields["value"] = SplitDateField(
1414
max_value=date.today(),
1515
required=True,
1616
require_all_fields=False,
@@ -28,5 +28,5 @@ def __init__(self, *args, **kwargs):
2828
)
2929

3030
class Meta:
31-
model = ResponseSet
32-
fields = ['date_of_birth']
31+
model = DateOfBirthResponse
32+
fields = ['value']
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Generated manually to create DateOfBirthResponse and copy data
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
def copy_date_of_birth_data(apps, schema_editor):
8+
with schema_editor.connection.cursor() as cursor:
9+
cursor.execute("""
10+
INSERT INTO questions_dateofbirthresponse (created_at, updated_at, value, response_set_id)
11+
SELECT NOW(), NOW(), date_of_birth, id
12+
FROM questions_responseset
13+
WHERE date_of_birth IS NOT NULL
14+
ON CONFLICT (response_set_id) DO NOTHING
15+
""")
16+
17+
18+
def reverse_copy_date_of_birth_data(apps, schema_editor):
19+
with schema_editor.connection.cursor() as cursor:
20+
cursor.execute("""
21+
UPDATE questions_responseset rs
22+
SET date_of_birth = d.value
23+
FROM questions_dateofbirthresponse d
24+
WHERE rs.id = d.response_set_id
25+
""")
26+
27+
28+
class Migration(migrations.Migration):
29+
30+
dependencies = [
31+
('questions', '0026_asbestosexposureresponse'),
32+
]
33+
34+
operations = [
35+
migrations.CreateModel(
36+
name='DateOfBirthResponse',
37+
fields=[
38+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
39+
('created_at', models.DateTimeField(auto_now_add=True)),
40+
('updated_at', models.DateTimeField(auto_now=True)),
41+
('value', models.DateField()),
42+
('response_set', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='date_of_birth_response', to='questions.responseset')),
43+
],
44+
options={
45+
'abstract': False,
46+
},
47+
),
48+
migrations.RunPython(copy_date_of_birth_data, reverse_copy_date_of_birth_data),
49+
migrations.RemoveField(
50+
model_name='responseset',
51+
name='date_of_birth',
52+
),
53+
]

lung_cancer_screening/questions/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from .user import User # noqa: F401
33
from .have_you_ever_smoked_response import HaveYouEverSmokedResponse # noqa: F401
44
from .asbestos_exposure_response import AsbestosExposureResponse # noqa: F401
5+
from .date_of_birth_response import DateOfBirthResponse # noqa: F401
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from django.db import models
2+
3+
from .base import BaseModel
4+
from .response_set import ResponseSet
5+
6+
7+
class DateOfBirthResponse(BaseModel):
8+
response_set = models.OneToOneField(ResponseSet, on_delete=models.CASCADE, related_name='date_of_birth_response')
9+
value = models.DateField()
Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,86 @@
11
from django.test import TestCase
22
from datetime import date
33

4-
from ...factories.user_factory import UserFactory
5-
from ....models.response_set import ResponseSet
4+
from ...factories.response_set_factory import ResponseSetFactory
5+
from ....models.date_of_birth_response import DateOfBirthResponse
66
from ....forms.date_of_birth_form import DateOfBirthForm
77

88

99
class TestDateOfBirthForm(TestCase):
1010
def setUp(self):
11-
self.user = UserFactory()
12-
self.response_set = ResponseSet(user=self.user)
11+
self.response_set = ResponseSetFactory()
12+
self.response = DateOfBirthResponse.objects.create(
13+
response_set=self.response_set,
14+
value=date(2000, 1, 1)
15+
)
1316

1417
def test_is_valid_when_a_valid_date_is_provided(self):
1518
form = DateOfBirthForm(
16-
instance=self.response_set,
19+
instance=self.response,
1720
data={
18-
"date_of_birth_0": 1,
19-
"date_of_birth_1": 1,
20-
"date_of_birth_2": 2025
21+
"value_0": 1,
22+
"value_1": 1,
23+
"value_2": 2025
2124
}
2225
)
2326
self.assertTrue(form.is_valid())
2427

2528
def test_is_invalid_when_no_date_is_provided(self):
2629
form = DateOfBirthForm(
27-
instance=self.response_set,
30+
instance=self.response,
2831
data={
29-
"date_of_birth_0": "",
30-
"date_of_birth_1": "",
31-
"date_of_birth_2": ""
32+
"value_0": "",
33+
"value_1": "",
34+
"value_2": ""
3235
}
3336
)
3437

3538
self.assertFalse(form.is_valid())
3639
self.assertEqual(
37-
form.errors["date_of_birth"],
40+
form.errors["value"],
3841
["Enter your date of birth"]
3942
)
4043

4144
def test_is_invalid_when_a_partial_date_is_provided(self):
4245
form = DateOfBirthForm(
43-
instance=self.response_set,
46+
instance=self.response,
4447
data={
45-
"date_of_birth_0": "10",
46-
"date_of_birth_1": "",
47-
"date_of_birth_2": ""
48+
"value_0": "10",
49+
"value_1": "",
50+
"value_2": ""
4851
}
4952
)
5053

5154
self.assertFalse(form.is_valid())
5255
self.assertEqual(
53-
form.errors["date_of_birth"],
56+
form.errors["value"],
5457
["Enter your full date of birth"]
5558
)
5659

5760
def test_is_invalid_when_an_invalid_date_is_provided(self):
5861
form = DateOfBirthForm(
59-
instance=self.response_set,
62+
instance=self.response,
6063
data={
61-
"date_of_birth_0": "31",
62-
"date_of_birth_1": "02",
63-
"date_of_birth_2": "2025"
64+
"value_0": "31",
65+
"value_1": "02",
66+
"value_2": "2025"
6467
}
6568
)
6669

6770
self.assertFalse(form.is_valid())
6871
self.assertEqual(
69-
form.errors["date_of_birth"],
72+
form.errors["value"],
7073
["Date of birth must be a real date"]
7174
)
7275

7376
def test_returns_a_date_type(self):
7477
form = DateOfBirthForm(
75-
instance=self.response_set,
78+
instance=self.response,
7679
data={
77-
"date_of_birth_0": 1,
78-
"date_of_birth_1": 1,
79-
"date_of_birth_2": 2025
80+
"value_0": 1,
81+
"value_1": 1,
82+
"value_2": 2025
8083
}
8184
)
8285
form.is_valid()
83-
self.assertIsInstance(form.cleaned_data["date_of_birth"], date)
86+
self.assertIsInstance(form.cleaned_data["value"], date)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from django.test import TestCase
2+
from datetime import date
3+
4+
from ...factories.response_set_factory import ResponseSetFactory
5+
from ....models.date_of_birth_response import DateOfBirthResponse
6+
7+
8+
class TestDateOfBirthResponse(TestCase):
9+
def test_has_response_set_as_foreign_key(self):
10+
response_set = ResponseSetFactory()
11+
response = DateOfBirthResponse.objects.create(
12+
response_set=response_set,
13+
value=date(2000, 9, 8)
14+
)
15+
16+
self.assertEqual(response.response_set, response_set)
17+
18+
def test_has_value_as_date(self):
19+
response_set = ResponseSetFactory()
20+
response = DateOfBirthResponse.objects.create(
21+
response_set=response_set,
22+
value=date(2000, 9, 8)
23+
)
24+
25+
self.assertIsInstance(response.value, date)

lung_cancer_screening/questions/tests/unit/views/test_date_of_birth.py

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from django.utils import timezone
66

77
from .helpers.authentication import login_user
8+
from lung_cancer_screening.questions.models.date_of_birth_response import DateOfBirthResponse
89

910

1011
class TestGetDateOfBirth(TestCase):
@@ -49,16 +50,16 @@ def setUp(self):
4950

5051
self.valid_age = date.today() - relativedelta(years=55)
5152
self.valid_params = {
52-
"date_of_birth_0": self.valid_age.day,
53-
"date_of_birth_1": self.valid_age.month,
54-
"date_of_birth_2": self.valid_age.year
53+
"value_0": self.valid_age.day,
54+
"value_1": self.valid_age.month,
55+
"value_2": self.valid_age.year
5556
}
5657

5758
self.invalid_age = date.today() - relativedelta(years=20)
5859
self.invalid_params = {
59-
"date_of_birth_0": self.invalid_age.day,
60-
"date_of_birth_1": self.invalid_age.month,
61-
"date_of_birth_2": self.invalid_age.year
60+
"value_0": self.invalid_age.day,
61+
"value_1": self.invalid_age.month,
62+
"value_2": self.invalid_age.year
6263
}
6364

6465
def test_post_redirects_if_the_user_is_not_logged_in(self):
@@ -86,7 +87,7 @@ def test_post_creates_unsubmitted_response_set_when_no_response_set_exists(
8687
response_set = self.user.responseset_set.first()
8788
self.assertEqual(self.user.responseset_set.count(), 1)
8889
self.assertEqual(response_set.submitted_at, None)
89-
self.assertEqual(response_set.date_of_birth, self.valid_age)
90+
self.assertEqual(DateOfBirthResponse.objects.get(response_set=response_set).value, self.valid_age)
9091
self.assertEqual(response_set.user, self.user)
9192

9293
def test_post_updates_unsubmitted_response_set_when_one_exists(self):
@@ -100,7 +101,7 @@ def test_post_updates_unsubmitted_response_set_when_one_exists(self):
100101
response_set.refresh_from_db()
101102
self.assertEqual(self.user.responseset_set.count(), 1)
102103
self.assertEqual(response_set.submitted_at, None)
103-
self.assertEqual(response_set.date_of_birth, self.valid_age)
104+
self.assertEqual(DateOfBirthResponse.objects.get(response_set=response_set).value, self.valid_age)
104105
self.assertEqual(response_set.user, self.user)
105106

106107
def test_post_creates_new_unsubmitted_response_set_when_submitted_exists_over_year_ago( # noqa: E501
@@ -120,7 +121,7 @@ def test_post_creates_new_unsubmitted_response_set_when_submitted_exists_over_ye
120121

121122
response_set = self.user.responseset_set.last()
122123
self.assertEqual(response_set.submitted_at, None)
123-
self.assertEqual(response_set.date_of_birth, self.valid_age)
124+
self.assertEqual(DateOfBirthResponse.objects.get(response_set=response_set).value, self.valid_age)
124125
self.assertEqual(response_set.user, self.user)
125126

126127
def test_post_redirects_when_submitted_response_set_exists_within_last_year(
@@ -144,7 +145,7 @@ def test_post_stores_a_valid_response_set_for_the_user(self):
144145
)
145146

146147
response_set = self.user.responseset_set.first()
147-
self.assertEqual(response_set.date_of_birth, self.valid_age)
148+
self.assertEqual(DateOfBirthResponse.objects.get(response_set=response_set).value, self.valid_age)
148149
self.assertEqual(response_set.user, self.user)
149150

150151
def test_post_redirects_to_height_path(self):
@@ -159,9 +160,9 @@ def test_post_responds_with_422_if_the_resource_is_invalid(self):
159160
response = self.client.post(
160161
reverse("questions:date_of_birth"),
161162
{
162-
"date_of_birth_0": "80000",
163-
"date_of_birth_1": "90000",
164-
"date_of_birth_2": "20000000"
163+
"value_0": "80000",
164+
"value_1": "90000",
165+
"value_2": "20000000"
165166
}
166167
)
167168

@@ -175,9 +176,9 @@ def test_post_does_not_set_date_of_birth_if_user_not_in_correct_age_range(
175176
self.invalid_params
176177
)
177178

178-
self.assertEqual(
179-
self.user.responseset_set.first().date_of_birth, None
180-
)
179+
response_set = self.user.responseset_set.first()
180+
if response_set:
181+
self.assertFalse(DateOfBirthResponse.objects.filter(response_set=response_set).exists())
181182

182183
def test_post_redirects_if_user_not_in_correct_age_range(self):
183184
response = self.client.post(

lung_cancer_screening/questions/views/date_of_birth.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,39 @@
77

88
from .mixins.ensure_response_set import EnsureResponseSet
99
from ..forms.date_of_birth_form import DateOfBirthForm
10+
from ..models.date_of_birth_response import DateOfBirthResponse
1011

1112

1213
class DateOfBirthView(LoginRequiredMixin, EnsureResponseSet, View):
1314
def get(self, request):
15+
response, _ = DateOfBirthResponse.objects.get_or_build(
16+
response_set=request.response_set
17+
)
1418
return render_template(
1519
request,
16-
DateOfBirthForm(instance=request.response_set)
20+
DateOfBirthForm(instance=response)
1721
)
1822

1923
def post(self, request):
24+
response, _ = DateOfBirthResponse.objects.get_or_build(
25+
response_set=request.response_set
26+
)
2027
form = DateOfBirthForm(
21-
instance=request.response_set,
28+
instance=response,
2229
data=request.POST
2330
)
2431

2532
if form.is_valid():
2633
fifty_five_years_ago = date.today() - relativedelta(years=55)
2734
seventy_five_years_ago = date.today() - relativedelta(years=75)
28-
date_of_birth = form.cleaned_data["date_of_birth"]
35+
date_of_birth = form.cleaned_data["value"]
2936

3037
age_in_range = (
3138
seventy_five_years_ago < date_of_birth <= fifty_five_years_ago
3239
)
3340
if age_in_range:
34-
response_set = request.response_set
35-
response_set.date_of_birth = date_of_birth
36-
response_set.save()
41+
response.value = date_of_birth
42+
response.save()
3743

3844
return redirect(reverse("questions:height"))
3945
else:

0 commit comments

Comments
 (0)