Skip to content

Commit 898c632

Browse files
committed
Move WeightResponse to its own model
1 parent 58ece43 commit 898c632

File tree

11 files changed

+275
-122
lines changed

11 files changed

+275
-122
lines changed
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
from django import forms
22

33
from ...nhsuk_forms.imperial_weight_field import ImperialWeightField
4-
from ..models.response_set import ResponseSet
4+
from ..models.weight_response import WeightResponse
55

66

77
class ImperialWeightForm(forms.ModelForm):
88

99
def __init__(self, *args, **kwargs):
1010
super().__init__(*args, **kwargs)
1111

12-
self.fields["weight_imperial"] = ImperialWeightField(
12+
self.fields["imperial"] = ImperialWeightField(
1313
label="Weight",
1414
required=True,
1515
require_all_fields=False,
@@ -18,9 +18,9 @@ def __init__(self, *args, **kwargs):
1818
}
1919
)
2020

21-
def clean_weight_metric(self):
21+
def clean_metric(self):
2222
return None
2323

2424
class Meta:
25-
model = ResponseSet
26-
fields = ['weight_imperial', 'weight_metric']
25+
model = WeightResponse
26+
fields = ['imperial', 'metric']
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from django import forms
22

33
from ...nhsuk_forms.decimal_field import DecimalField
4-
from ..models.response_set import ResponseSet
4+
from ..models.weight_response import WeightResponse
55

66

77
class MetricWeightForm(forms.ModelForm):
@@ -10,10 +10,10 @@ def __init__(self, *args, **kwargs):
1010
super().__init__(*args, **kwargs)
1111

1212
# Convert hundreds of grams to kg for display
13-
if self.instance and self.instance.weight_metric is not None:
14-
self.initial['weight_metric'] = self.instance.weight_metric / 10
13+
if self.instance and self.instance.metric is not None:
14+
self.initial['metric'] = self.instance.metric / 10
1515

16-
self.fields["weight_metric"] = DecimalField(
16+
self.fields["metric"] = DecimalField(
1717
decimal_places=1,
1818
label="Kilograms",
1919
classes="nhsuk-input--width-4",
@@ -28,12 +28,12 @@ def __init__(self, *args, **kwargs):
2828
suffix="kg"
2929
)
3030

31-
def clean_weight_metric(self):
32-
return self.cleaned_data['weight_metric'] * 10
31+
def clean_metric(self):
32+
return int(self.cleaned_data['metric'] * 10)
3333

34-
def clean_weight_imperial(self):
34+
def clean_imperial(self):
3535
return None
3636

3737
class Meta:
38-
model = ResponseSet
39-
fields = ['weight_metric', 'weight_imperial']
38+
model = WeightResponse
39+
fields = ['metric', 'imperial']

lung_cancer_screening/questions/jinja2/weight.jinja

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@
4343
}) %}
4444

4545
{% if unit == "imperial" %}
46-
{{ form.weight_imperial.as_field_group() }}
46+
{{ form.imperial.as_field_group() }}
4747
{% else %}
48-
{{ form.weight_metric.as_field_group() }}
48+
{{ form.metric.as_field_group() }}
4949
{% endif %}
5050

5151
<p><a href="?unit={{ switch_to_unit }}">Switch to {{ WEIGHT_UNIT[switch_to_unit] }}</a></p>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Generated manually to create WeightResponse and copy data
2+
3+
import django.core.validators
4+
import django.db.models.deletion
5+
from django.db import migrations, models
6+
7+
8+
def copy_weight_data(apps, schema_editor):
9+
with schema_editor.connection.cursor() as cursor:
10+
cursor.execute("""
11+
INSERT INTO questions_weightresponse (created_at, updated_at, metric, imperial, response_set_id)
12+
SELECT NOW(), NOW(), weight_metric, weight_imperial, id
13+
FROM questions_responseset
14+
WHERE weight_metric IS NOT NULL OR weight_imperial IS NOT NULL
15+
ON CONFLICT (response_set_id) DO NOTHING
16+
""")
17+
18+
19+
def reverse_copy_weight_data(apps, schema_editor):
20+
with schema_editor.connection.cursor() as cursor:
21+
cursor.execute("""
22+
UPDATE questions_responseset rs
23+
SET weight_metric = w.metric,
24+
weight_imperial = w.imperial
25+
FROM questions_weightresponse w
26+
WHERE rs.id = w.response_set_id
27+
""")
28+
29+
30+
class Migration(migrations.Migration):
31+
32+
dependencies = [
33+
('questions', '0032_sexatbirthresponse'),
34+
]
35+
36+
operations = [
37+
migrations.CreateModel(
38+
name='WeightResponse',
39+
fields=[
40+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
41+
('created_at', models.DateTimeField(auto_now_add=True)),
42+
('updated_at', models.DateTimeField(auto_now=True)),
43+
('metric', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(254, message='Weight must be between 25.4kg and 317.5kg'), django.core.validators.MaxValueValidator(3175, message='Weight must be between 25.4kg and 317.5kg')])),
44+
('imperial', models.PositiveIntegerField(blank=True, null=True, validators=[django.core.validators.MinValueValidator(56, message='Weight must be between 4 stone and 50 stone'), django.core.validators.MaxValueValidator(700, message='Weight must be between 4 stone and 50 stone')])),
45+
('response_set', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='weight_response', to='questions.responseset')),
46+
],
47+
options={
48+
'abstract': False,
49+
},
50+
),
51+
migrations.RunPython(copy_weight_data, reverse_copy_weight_data),
52+
migrations.RemoveField(
53+
model_name='responseset',
54+
name='weight_metric',
55+
),
56+
migrations.RemoveField(
57+
model_name='responseset',
58+
name='weight_imperial',
59+
),
60+
]

lung_cancer_screening/questions/models/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
from .gender_response import GenderResponse # noqa: F401
88
from .height_response import HeightResponse # noqa: F401
99
from .respiratory_conditions_response import RespiratoryConditionsResponse # noqa: F401
10+
from .sex_at_birth_response import SexAtBirthResponse # noqa: F401
11+
from .weight_response import WeightResponse # noqa: F401
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from django.db import models
2+
from django.core.exceptions import ValidationError
3+
from django.core.validators import MaxValueValidator, MinValueValidator
4+
from decimal import Decimal
5+
6+
from .base import BaseModel
7+
from .response_set import ResponseSet
8+
9+
10+
class WeightResponse(BaseModel):
11+
MIN_WEIGHT_METRIC = 254
12+
MAX_WEIGHT_METRIC = 3175
13+
MAX_WEIGHT_IMPERIAL = 700
14+
MIN_WEIGHT_IMPERIAL = 56
15+
16+
response_set = models.OneToOneField(ResponseSet, on_delete=models.CASCADE, related_name='weight_response')
17+
18+
metric = models.PositiveIntegerField(null=True, blank=True, validators=[
19+
MinValueValidator(MIN_WEIGHT_METRIC, message="Weight must be between 25.4kg and 317.5kg"),
20+
MaxValueValidator(MAX_WEIGHT_METRIC, message="Weight must be between 25.4kg and 317.5kg"),
21+
])
22+
imperial = models.PositiveIntegerField(null=True, blank=True, validators=[
23+
MinValueValidator(MIN_WEIGHT_IMPERIAL, message="Weight must be between 4 stone and 50 stone"),
24+
MaxValueValidator(MAX_WEIGHT_IMPERIAL, message="Weight must be between 4 stone and 50 stone"),
25+
])
26+
27+
def clean(self):
28+
if not self.metric and not self.imperial:
29+
raise ValidationError("Either metric or imperial weight must be provided.")
30+
if self.metric and self.imperial:
31+
raise ValidationError("Cannot provide both metric and imperial weight.")
32+
33+
@property
34+
def formatted(self):
35+
if self.metric:
36+
return f"{Decimal(self.metric) / 10}kg"
37+
elif self.imperial:
38+
value = Decimal(self.imperial)
39+
return f"{value // 14} stone {value % 14} pounds"
40+
return None

0 commit comments

Comments
 (0)