Skip to content

Commit

Permalink
Merge pull request #429 from con2/feat/forms-sequence-numbers
Browse files Browse the repository at this point in the history
feat(forms): add intra-Survey sequence numbers to Responses
  • Loading branch information
japsu committed Feb 12, 2024
2 parents 2ab11b8 + 4c15e20 commit 957fdf3
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 62 deletions.
12 changes: 10 additions & 2 deletions backend/forms/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,17 @@ class ResponseDimensionValueInline(admin.TabularInline):
@admin.register(Response)
class ResponseAdmin(admin.ModelAdmin):
model = Response
list_display = ("created_at", "form", "created_by")
list_display = ("created_at", "form", "sequence_number", "created_by")
list_filter = ("form__event", "form")
readonly_fields = ("form", "form_data", "created_by", "ip_address", "created_at", "updated_at")
readonly_fields = (
"form",
"form_data",
"created_by",
"ip_address",
"created_at",
"updated_at",
"sequence_number",
)
fields = readonly_fields
inlines = (ResponseDimensionValueInline,)

Expand Down
17 changes: 10 additions & 7 deletions backend/forms/graphql/mutations/create_survey_response.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import graphene
from django.db import transaction
from graphene.types.generic import GenericScalar

from core.utils import get_ip
Expand Down Expand Up @@ -54,13 +55,15 @@ def mutate(
created_by = None
ip_address = ""

response = Response.objects.create(
form=form,
form_data=input.form_data,
created_by=created_by,
ip_address=ip_address,
)
with transaction.atomic():
response = Response.objects.create(
form=form,
form_data=input.form_data,
created_by=created_by,
ip_address=ip_address,
sequence_number=survey.get_next_sequence_number(),
)

response.lift_dimension_values()
response.lift_dimension_values()

return CreateSurveyResponse(response=response) # type: ignore
8 changes: 7 additions & 1 deletion backend/forms/graphql/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,12 @@ def resolve_cached_dimensions(response: Response, info, key_dimensions_only: boo

class Meta:
model = Response
fields = ("id", "form_data", "created_at")
fields = (
"id",
"form_data",
"created_at",
"sequence_number",
)


class FullResponseType(LimitedResponseType):
Expand Down Expand Up @@ -125,6 +130,7 @@ class Meta:
"id",
"form_data",
"created_at",
"sequence_number",
)


Expand Down
34 changes: 34 additions & 0 deletions backend/forms/migrations/0023_response_sequence_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Generated by Django 5.0.2 on 2024-02-12 18:25

from django.db import migrations, models


def number_existing_responses(apps, schema_editor):
Response = apps.get_model("forms", "Response")
Survey = apps.get_model("forms", "Survey")

for survey in Survey.objects.all():
responses = Response.objects.filter(
form__in=survey.languages.all(),
sequence_number=0,
).order_by("created_at")
for i, response in enumerate(responses):
response.sequence_number = i + 1
response.save(update_fields=["sequence_number"])


class Migration(migrations.Migration):
dependencies = [
("forms", "0022_dimension_is_shown_to_respondent"),
]

operations = [
migrations.AddField(
model_name="response",
name="sequence_number",
field=models.PositiveIntegerField(
default=0, help_text="Sequence number of this response within the use case (eg. survey)."
),
),
migrations.RunPython(number_existing_responses, reverse_code=migrations.RunPython.noop),
]
5 changes: 5 additions & 0 deletions backend/forms/models/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class Response(models.Model):
verbose_name=_("IP address"),
)

sequence_number = models.PositiveIntegerField(
default=0,
help_text="Sequence number of this response within the use case (eg. survey).",
)

# denormalized fields
cached_dimensions = models.JSONField(
default=dict,
Expand Down
3 changes: 3 additions & 0 deletions backend/forms/models/survey.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ def responses(self):

return Response.objects.filter(form__in=self.languages.all()).order_by("created_at")

def get_next_sequence_number(self):
return (self.responses.all().aggregate(models.Max("sequence_number"))["sequence_number__max"] or 0) + 1

def preload_dimensions(self, dimension_values: Mapping[str, Collection[str]] | None = None):
dimensions = self.dimensions.all().prefetch_related("values")
if dimension_values is not None:
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/__generated__/gql.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 957fdf3

Please sign in to comment.