Skip to content

Commit 0fe6dcc

Browse files
committed
PPHA-529: Add smoked total years for cigarette type
1 parent 7a7501d commit 0fe6dcc

22 files changed

Lines changed: 739 additions & 159 deletions

features/questionnaire.feature

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ Feature: Questionnaire
7070
And I check "Pipe"
7171
And I submit the form
7272

73+
Then I am on "/cigarettes-smoked-total-years"
74+
When I fill in "Roughly how many years have you smoked cigarettes?" with "10"
75+
And I submit the form
76+
7377
Then I am on "/check-your-answers"
7478
And I see "Yes, I used to smoke" as a response to "Have you ever smoked tobacco?" under "Eligibility"
7579
And I see a date 55 years ago as a response to "Date of birth" under "Eligibility"
@@ -90,5 +94,7 @@ Feature: Questionnaire
9094
And I see "18" as a response to "Age you started smoking" under "Smoking history"
9195
And I see "Yes (10 years)" as a response to "Have you ever stopped smoking for periods of 1 year or longer?" under "Smoking history"
9296

97+
And I see "10" as a response to "Total number of years you have smoked cigarettes" under "Smoking history"
98+
9399
When I click "Submit"
94100
Then I am on "/confirmation"
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
@SmokedTotalYears
2+
Feature: Smoked total years page
3+
Scenario: The page is accessible
4+
Given I am logged in
5+
And I have answered questions showing I am eligible
6+
And I have answered questions showing I have smoked "Cigarettes"
7+
When I go to "/cigarettes-smoked-total-years"
8+
Then there are no accessibility violations
9+
10+
Scenario: Form errors
11+
Given I am logged in
12+
And I have answered questions showing I am eligible
13+
And I have answered questions showing I have smoked "Cigarettes"
14+
When I go to "/cigarettes-smoked-total-years"
15+
And I click "Continue"
16+
Then I am on "/cigarettes-smoked-total-years"
17+
And I see a form error "Enter the number of years you have smoked cigarettes"
18+
And there are no accessibility violations
19+
20+
Scenario: Navigating backwards and forwards
21+
Given I am logged in
22+
And I have answered questions showing I am eligible
23+
And I have answered questions showing I have smoked "Cigarettes"
24+
When I go to "/cigarettes-smoked-total-years"
25+
Then I see a back link to "/types-tobacco-smoking"
26+
When I fill in "Roughly how many years have you smoked cigarettes?" with "10"
27+
And I submit the form
28+
Then I am on "/check-your-answers"
29+
30+
Scenario: Checking responses and changing them
31+
Given I am logged in
32+
And I have answered questions showing I am eligible
33+
And I have answered questions showing I have smoked "Cigarettes"
34+
When I go to "/cigarettes-smoked-total-years"
35+
When I fill in "Roughly how many years have you smoked cigarettes?" with "10"
36+
And I submit the form
37+
When I go to "/check-your-answers"
38+
Then I see "10" as a response to "Total number of years you have smoked cigarettes" under "Smoking history"
39+
And I see "/cigarettes-smoked-total-years?change=True" as a link to change "Total number of years you have smoked cigarettes" under "Smoking history"
40+
When I click the link to change "Total number of years you have smoked cigarettes" under "Smoking history"
41+
Then I am on "/cigarettes-smoked-total-years?change=True"
42+
And I see "10" filled in for "Roughly how many years have you smoked cigarettes?"
43+
When I fill in "Roughly how many years have you smoked cigarettes?" with "20"
44+
And I click "Continue"
45+
Then I am on "/check-your-answers"
46+
And I see "20" as a response to "Total number of years you have smoked cigarettes" under "Smoking history"

features/steps/preflight_steps.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,14 @@ def given_i_have_answered_questions_showing_i_stopped_smoking_for_years_years(co
7777
when_i_check_label(context, "Yes")
7878
when_i_fill_in_label_with_value(context, "Enter the total number of years you stopped smoking for", years)
7979
when_i_submit_the_form(context)
80+
81+
82+
@given('I have answered questions showing I have smoked "{tobacco_types}"')
83+
def given_i_have_answered_questions_showing_i_have_smoked_tobacco_type(
84+
context, tobacco_types
85+
):
86+
context.page.goto(f"{context.live_server_url}/types-tobacco-smoking")
87+
88+
for tobacco_type in tobacco_types.split(","):
89+
when_i_check_label(context, tobacco_type.strip())
90+
when_i_submit_the_form(context)

features/types_tobacco_smoking.feature

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Feature: Types tobacco smoking page
2222
Then I see a back link to "/periods-when-you-stopped-smoking"
2323
When I check "Cigarettes"
2424
And I submit the form
25-
Then I am on "/check-your-answers"
25+
Then I am on "/cigarettes-smoked-total-years"
2626

2727
Scenario: Checking responses and changing them
2828
Given I am logged in
@@ -41,5 +41,6 @@ Feature: Types tobacco smoking page
4141
And I see "Cigars" selected
4242
When I check "Pipe"
4343
And I click "Continue"
44-
Then I am on "/check-your-answers"
45-
And I see "Cigarettes, Pipe, and Cigars" as a response to "Types of tobacco smoked" under "Smoking history"
44+
Then I am on "/cigarettes-smoked-total-years"
45+
When I go to "/check-your-answers"
46+
Then I see "Cigarettes, Pipe, and Cigars" as a response to "Types of tobacco smoked" under "Smoking history"
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from django import forms
2+
3+
from ...nhsuk_forms.integer_field import IntegerField
4+
from ..models.smoked_total_years_response import SmokedTotalYearsResponse
5+
6+
7+
class SmokedTotalYearsForm(forms.ModelForm):
8+
9+
def __init__(self, *args, **kwargs):
10+
super().__init__(*args, **kwargs)
11+
12+
self.fields["value"] = IntegerField(
13+
label="Roughly how many years have you smoked cigarettes?",
14+
label_is_page_heading=True,
15+
label_classes="nhsuk-label--l",
16+
classes="nhsuk-input--width-4",
17+
hint="Give an estimate if you are not sure",
18+
required=True,
19+
suffix="years",
20+
error_messages={
21+
"required": "Enter the number of years you have smoked cigarettes",
22+
"invalid": "Years must be in whole numbers"
23+
},
24+
)
25+
26+
class Meta:
27+
model = SmokedTotalYearsResponse
28+
fields = ['value']
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Generated by Django 5.2.10 on 2026-01-28 15:38
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('questions', '0048_tobaccosmokinghistory_and_more'),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='SmokedTotalYearsResponse',
16+
fields=[
17+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('created_at', models.DateTimeField(auto_now_add=True)),
19+
('updated_at', models.DateTimeField(auto_now=True)),
20+
('value', models.IntegerField()),
21+
],
22+
options={
23+
'abstract': False,
24+
},
25+
),
26+
migrations.AlterField(
27+
model_name='tobaccosmokinghistory',
28+
name='response_set',
29+
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tobacco_smoking_history', to='questions.responseset'),
30+
),
31+
migrations.AddConstraint(
32+
model_name='tobaccosmokinghistory',
33+
constraint=models.UniqueConstraint(fields=('response_set', 'type'), name='unique_tobacco_smoking_history_per_response_set', violation_error_message='A tobacco smoking history already exists for this response set and type'),
34+
),
35+
migrations.AddField(
36+
model_name='smokedtotalyearsresponse',
37+
name='tobacco_smoking_history',
38+
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='smoked_total_years_response', to='questions.tobaccosmokinghistory'),
39+
),
40+
]
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.db import models
2+
3+
from .base import BaseModel
4+
from .tobacco_smoking_history import TobaccoSmokingHistory
5+
6+
7+
class SmokedTotalYearsResponse(BaseModel):
8+
tobacco_smoking_history = models.OneToOneField(
9+
TobaccoSmokingHistory,
10+
on_delete=models.CASCADE,
11+
related_name='smoked_total_years_response'
12+
)
13+
value = models.IntegerField()

lung_cancer_screening/questions/models/tobacco_smoking_history.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from django.db import models
2+
from django.db.models import Case, Value, When
23

3-
from .base import BaseModel
4+
from .base import BaseModel, BaseQuerySet
45
from .response_set import ResponseSet
56

67

@@ -13,6 +14,16 @@ class TobaccoSmokingHistoryTypes(models.TextChoices):
1314
SHISHA = "Shisha", "Shisha"
1415

1516

17+
class TobaccoSmokingHistoryQuerySet(BaseQuerySet):
18+
def in_form_order(self):
19+
form_order = [choice[0] for choice in TobaccoSmokingHistoryTypes.choices]
20+
order = Case(
21+
*[When(type=type_val, then=Value(i)) for i, type_val in enumerate(form_order)],
22+
default=Value(len(form_order)),
23+
)
24+
return self.order_by(order)
25+
26+
1627
class TobaccoSmokingHistory(BaseModel):
1728
response_set = models.ForeignKey(
1829
ResponseSet,
@@ -23,6 +34,8 @@ class TobaccoSmokingHistory(BaseModel):
2334
choices=TobaccoSmokingHistoryTypes.choices
2435
)
2536

37+
objects = TobaccoSmokingHistoryQuerySet.as_manager()
38+
2639
class Meta:
2740
constraints = [
2841
models.UniqueConstraint(
@@ -31,3 +44,6 @@ class Meta:
3144
violation_error_message="A tobacco smoking history already exists for this response set and type"
3245
)
3346
]
47+
48+
def human_type(self):
49+
return TobaccoSmokingHistoryTypes(self.type).label

lung_cancer_screening/questions/presenters/response_set_presenter.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
import humps
2+
13
from decimal import Decimal
24
from django.urls import reverse
35

46
from ..models.education_response import EducationValues
57
from ..models.respiratory_conditions_response import RespiratoryConditionValues
68
from ..models.family_history_lung_cancer_response import FamilyHistoryLungCancerValues
7-
from ..models.tobacco_smoking_history import TobaccoSmokingHistoryTypes
89

910
class ResponseSetPresenter:
1011
DATE_FORMAT = "%-d %B %Y" # eg 8 September 2000
@@ -150,13 +151,9 @@ def respiratory_conditions(self):
150151

151152
@property
152153
def types_tobacco_smoking(self):
153-
types_smoked = self.response_set.tobacco_smoking_history.values_list('type', flat=True)
154-
155-
types_smoked_ordered = sorted(types_smoked, key=lambda x: TobaccoSmokingHistoryTypes.values.index(x))
156-
157154
return self._list_to_sentence([
158-
TobaccoSmokingHistoryTypes(code).label
159-
for code in types_smoked_ordered
155+
tobacco_smoking_history.human_type()
156+
for tobacco_smoking_history in self.response_set.tobacco_smoking_history.in_form_order()
160157
])
161158

162159

@@ -249,6 +246,17 @@ def family_history_responses_items(self):
249246
return items
250247

251248

249+
def smoking_history_types_responses_items(self):
250+
return [*[
251+
self._check_your_answer_item(
252+
f"Total number of years you have smoked {type_history.human_type().lower()}",
253+
type_history.smoked_total_years_response.value if hasattr(type_history, 'smoked_total_years_response') else None,
254+
"questions:smoked_total_years",
255+
kwargs = { "tobacco_type": humps.kebabize(type_history.type) },
256+
)
257+
for type_history in self.response_set.tobacco_smoking_history.in_form_order()
258+
]]
259+
252260
def smoking_history_responses_items(self):
253261
return [
254262
self._check_your_answer_item(
@@ -265,7 +273,8 @@ def smoking_history_responses_items(self):
265273
"Types of tobacco smoked",
266274
self.types_tobacco_smoking,
267275
"questions:types_tobacco_smoking",
268-
)
276+
),
277+
*self.smoking_history_types_responses_items()
269278
]
270279

271280

@@ -296,14 +305,14 @@ def _change_query_params(self):
296305
return { "change": "True" }
297306

298307

299-
def _check_your_answer_item(self, question, value, url_lookup_name):
308+
def _check_your_answer_item(self, question, value, url_lookup_name, kwargs = {}):
300309
return {
301310
"key": { "text": question },
302311
"value": { "text": value },
303312
"actions": {
304313
"items": [
305314
{
306-
"href": reverse(url_lookup_name, query = self._change_query_params()),
315+
"href": reverse(url_lookup_name, kwargs = kwargs, query = self._change_query_params()),
307316
"text": "Change"
308317
}
309318
]
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import factory
2+
3+
from .tobacco_smoking_history_factory import TobaccoSmokingHistoryFactory
4+
from ...models.smoked_total_years_response import SmokedTotalYearsResponse
5+
6+
7+
class SmokedTotalYearsResponseFactory(factory.django.DjangoModelFactory):
8+
class Meta:
9+
model = SmokedTotalYearsResponse
10+
11+
tobacco_smoking_history = factory.SubFactory(TobaccoSmokingHistoryFactory)
12+
value = 10

0 commit comments

Comments
 (0)