From 2cdebb37832267170d4ec2f54ef81617781e4e80 Mon Sep 17 00:00:00 2001 From: "Nasreddin Boulif (bon)" Date: Wed, 5 Jul 2023 02:18:36 +0000 Subject: [PATCH] [FIX] survey: copy the triggering question to the right question Steps to reproduce: - Install 'survey' module - Create a survey with 2 questions - Change the sequence of the questions - Edit the second question (last in the sequence) - Set it as conditional - Select first question as trigger (with any answer) - Duplicate the survey Issue: The triggering question is not set on the right question. Cause: When copying the survey, we map the old question to the new ones but there are by default sorted by order of creation and not by sequence and therefore the mapping is wrong. Solution: Order the questions and answers by sequence before mapping them. opw-3330476 closes odoo/odoo#127681 X-original-commit: 70f7e13c38acd07ea04324bc78e379dac6051e41 Signed-off-by: Nasreddin Boulif (bon) --- addons/survey/models/survey_survey.py | 16 +++++++---- addons/survey/tests/test_survey.py | 40 +++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py index 4bc4ede6390..4ac7d2d93fd 100644 --- a/addons/survey/models/survey_survey.py +++ b/addons/survey/models/survey_survey.py @@ -396,13 +396,19 @@ class Survey(models.Model): if default and 'question_ids' in default: return clone - questions_map = {src.id: dst.id for src, dst in zip(self.question_ids, clone.question_ids)} + src_questions = self.question_ids + dst_questions = clone.question_ids.sorted() + + questions_map = {src.id: dst.id for src, dst in zip(src_questions, dst_questions)} answers_map = { - source_answer.id: copy_answer.id - for source_answer, copy_answer - in zip(self.question_ids.suggested_answer_ids, clone.question_ids.suggested_answer_ids) + src_answer.id: dst_answer.id + for src, dst + in zip(src_questions, dst_questions) + for src_answer, dst_answer + in zip(src.suggested_answer_ids, dst.suggested_answer_ids.sorted()) } - for src, dst in zip(self.question_ids, clone.question_ids): + + for src, dst in zip(src_questions, dst_questions): if src.is_conditional: dst.is_conditional = True dst.triggering_question_id = questions_map.get(src.triggering_question_id.id) diff --git a/addons/survey/tests/test_survey.py b/addons/survey/tests/test_survey.py index 19620830ec8..0d8f9713dba 100644 --- a/addons/survey/tests/test_survey.py +++ b/addons/survey/tests/test_survey.py @@ -406,6 +406,46 @@ class TestSurveyInternals(common.TestSurveyCommon): self.assertNotEqual(q_food_not_vegetarian_cloned.triggering_answer_id.id, q_is_vegetarian.suggested_answer_ids[1].id) + @users('survey_manager') + def test_copy_conditional_question_with_sequence_changed(self): + """ Create a survey with two questions, change the sequence of the questions, + set the second question as conditional on the first one, and check that the conditional + question is still conditional on the first one after copying the survey.""" + + def get_question_by_title(survey, title): + return survey.question_ids.filtered(lambda q: q.title == title)[0] + + # Create the survey questions + q_1 = self._add_question( + self.page_0, 'Q1', 'multiple_choice', survey_id=self.survey.id, + sequence=200, labels=[{'value': 'Yes'}, {'value': 'No'}]) + q_2 = self._add_question( + self.page_0, 'Q2', 'multiple_choice', survey_id=self.survey.id, + sequence=300, labels=[{'value': 'Yes'}, {'value': 'No'}]) + + # Change the sequence of the second question to be before the first one + q_2.write({'sequence': 100}) + + # Set a conditional question on the first question + q_1.write({ + 'is_conditional': True, + 'triggering_question_id': q_2.id, + 'triggering_answer_id': q_2.suggested_answer_ids[0].id, + }) + + (q_1 | q_2).invalidate_recordset() + + # Clone the survey + cloned_survey = self.survey.copy() + + # Check that the sequence of the questions are the same as the original survey + self.assertEqual(get_question_by_title(cloned_survey, 'Q1').sequence, q_1.sequence) + self.assertEqual(get_question_by_title(cloned_survey, 'Q2').sequence, q_2.sequence) + + # Check that the conditional question is correctly copied to the right question + self.assertEqual(get_question_by_title(cloned_survey, 'Q1').triggering_question_id.title, q_1.triggering_question_id.title) + self.assertFalse(get_question_by_title(cloned_survey, 'Q2').triggering_question_id) + @users('survey_manager') def test_unlink_triggers(self): # Create the survey questions