[FIX] survey_record_generation: questions without answer no longer empty fields

When a question was not displayed (conditional question) or skipped, its
field was still given to create() with a None value. The field was then
emptied instead of keeping its default or computed value.

Since the link to an already created record is given at creation, this
also made sale.subscription.line price_unit equal to 0 when the "free
amount" question was not displayed, instead of the product price.

Fields without value are now left out of the values, which also allows
several conditional questions to fill up the same field (e.g. one list
of amounts per periodicity).

Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 12:22:01 +02:00
committed by mondot
parent bfe59096db
commit 0020f35399
3 changed files with 93 additions and 1 deletions

View File

@@ -61,6 +61,11 @@ class SurveyUserInput(models.Model):
)
field_name: str = field_value.field_id.name
if value is None:
# No value (e.g. question not displayed or skipped):
# keep the default/computed value of the field, and
# let another question fill up the same field.
continue
vals[field_name] = value
existing_record = self.find_existing_record(record_creation, vals)
@@ -195,7 +200,7 @@ class SurveyUserInput(models.Model):
if unique_fields:
uniq_domain = []
for uniq_field in unique_fields:
uniq_domain.append((uniq_field, "=", vals[uniq_field]))
uniq_domain.append((uniq_field, "=", vals.get(uniq_field, False)))
duplicate = self.env[model].search(uniq_domain, limit=1)
return duplicate

View File

@@ -110,3 +110,11 @@ class TestComputedFields(SurveyCase):
self.assertEqual(len(line), 1)
self.assertEqual(line.price_unit, 33.0)
def test_computed_field_applies_when_question_is_not_displayed(self):
# E.g. the "free amount" question is only displayed when the user
# chose "Other amount": otherwise the line keeps the computed price.
line = self._submit()
self.assertEqual(len(line), 1)
self.assertEqual(line.price_unit, 20.0)

View File

@@ -1072,3 +1072,82 @@ class TestSurveyRecordCreation(SurveyCase):
self.assertEqual(self.answer.partner_id, jean)
self.assertNotEqual(self.answer.partner_id, jeanne)
self.assertEqual(self.answer.email, jean.email)
def test_question_not_displayed_does_not_override_default_value(self):
# When a question is not displayed to the user (e.g. a conditional
# question), the field must keep its default (or computed) value
# instead of being emptied.
question_type = self._add_question(
page=None,
name="Type",
qtype="simple_choice",
labels=[{"value": "contact"}, {"value": "other"}],
survey_id=self.survey.id,
sequence=2,
answer_values_type="value",
)
for suggested_answer in question_type.suggested_answer_ids:
suggested_answer.value_char = suggested_answer.value
type_field = self.env["ir.model.fields"]._get("res.partner", "type")
self.env["survey.record.creation.field.values"].create(
{
"survey_record_creation_id": self.survey_record_creation.id,
"survey_id": self.survey.id,
"model_id": self.res_partner_model.id,
"field_id": type_field.id,
"value_origin": "question",
"question_id": question_type.id,
}
)
self.answer = self._add_answer(
survey=self.survey, partner=False, email="jean@test.fr"
)
self._add_answer_line(
question=self.question_name, answer=self.answer, answer_value="Jean"
)
self.answer._mark_done()
partner = self.env["res.partner"].search([("name", "=", "Jean")])
self.assertEqual(partner.type, "contact")
def test_several_conditional_questions_on_the_same_field(self):
# Several questions can fill up the same field (e.g. one list of
# amounts per periodicity, displayed conditionally): the answered
# question wins, the questions not displayed are ignored.
street_field = self.env["ir.model.fields"]._get("res.partner", "street")
questions = self.env["survey.question"]
for sequence, name in enumerate(["Street (France)", "Street (abroad)"], 2):
question = self._add_question(
page=None,
name=name,
qtype="char_box",
survey_id=self.survey.id,
sequence=sequence,
)
self.env["survey.record.creation.field.values"].create(
{
"survey_record_creation_id": self.survey_record_creation.id,
"survey_id": self.survey.id,
"model_id": self.res_partner_model.id,
"field_id": street_field.id,
"value_origin": "question",
"question_id": question.id,
}
)
questions |= question
self.answer = self._add_answer(
survey=self.survey, partner=False, email="jean@test.fr"
)
self._add_answer_line(
question=self.question_name, answer=self.answer, answer_value="Jean"
)
# Only the first question is displayed and answered
self._add_answer_line(
question=questions[0], answer=self.answer, answer_value="1 rue de Paris"
)
self.answer._mark_done()
partner = self.env["res.partner"].search([("name", "=", "Jean")])
self.assertEqual(partner.street, "1 rue de Paris")