Skip to content

Commit

Permalink
Merge pull request #1963 from open-dynaMIX/fix_table_calc_questions
Browse files Browse the repository at this point in the history
fix: fix calc answer evaluation when adding new table rows
  • Loading branch information
winged authored Feb 17, 2023
2 parents e48dd35 + cb668ba commit f0cd65a
Show file tree
Hide file tree
Showing 9 changed files with 227 additions and 66 deletions.
2 changes: 1 addition & 1 deletion caluma/caluma_analytics/tests/test_migrate_form_slugs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from caluma.caluma_analytics import simple_table


def test_migrate_rename_form_slugs(transactional_db):
def test_migrate_rename_form_slugs(post_migrate_to_current_state):
executor = MigrationExecutor(connection)
migrate_from = [
("caluma_analytics", "0005_analytics_field_ordering"),
Expand Down
54 changes: 54 additions & 0 deletions caluma/caluma_form/migrations/0047_recalculate_calc_answers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from django.db import migrations

from caluma.caluma_form.jexl import QuestionJexl
from caluma.caluma_form.structure import FieldSet


def recalculate_answer(answer):
"""
Recalculate a single calc-answer.
This is more or less a copy/paste from `_update_or_create_calc_answer` in order to
use the old models.
"""
root_doc = answer.document.family

struc = FieldSet(root_doc, root_doc.form)
field = struc.get_field(answer.question.slug)

# skip if question doesn't exist in this document structure
if field is None: # pragma: no cover
return

jexl = QuestionJexl(
{"form": field.form, "document": field.document, "structure": field.parent()}
)

# Ignore errors because we might evaluate partially built forms. So we might be
# missing some answers or the expression might be invalid, in which case we return
# None
value = jexl.evaluate(field.question.calc_expression, raise_on_error=False)

answer.value = value
answer.save()


def recalculate_all_answers(apps, _):
AnswerModel = apps.get_model("caluma_form.Answer")

calc_answers = AnswerModel.objects.filter(
question__type="calculated_float", document__isnull=False
)
for answer in calc_answers.iterator():
recalculate_answer(answer)


class Migration(migrations.Migration):

dependencies = [
("caluma_form", "0046_file_answer_reverse_keys"),
]

operations = [
migrations.RunPython(recalculate_all_answers, migrations.RunPython.noop),
]
10 changes: 5 additions & 5 deletions caluma/caluma_form/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ def update_calc_from_answer(sender, instance, **kwargs):

@receiver(post_save, sender=models.Document)
@disable_raw
@filter_events(lambda created: created)
# We're only interested in table row forms
@filter_events(lambda instance, created: instance.pk != instance.family_id or created)
def update_calc_from_document(sender, instance, created, **kwargs):

for question in instance.form.questions.filter(
type=models.Question.TYPE_CALCULATED_FLOAT
):
for question in models.Form.get_all_questions(
[(instance.family or instance).form_id]
).filter(type=models.Question.TYPE_CALCULATED_FLOAT):
_update_or_create_calc_answer(question, instance)


Expand Down
Loading

0 comments on commit f0cd65a

Please sign in to comment.