diff --git a/addons/product_expiry/wizard/confirm_expiry.py b/addons/product_expiry/wizard/confirm_expiry.py index 2746fc314b..5dec459b7d 100644 --- a/addons/product_expiry/wizard/confirm_expiry.py +++ b/addons/product_expiry/wizard/confirm_expiry.py @@ -35,8 +35,10 @@ class ConfirmExpiry(models.TransientModel): def process(self): picking_to_validate = self.env.context.get('button_validate_picking_ids') if picking_to_validate: - picking_to_validate = self.env['stock.picking'].browse(picking_to_validate).with_context(skip_expired=True) - return picking_to_validate.button_validate() + picking_to_validate = self.env['stock.picking'].browse(picking_to_validate) + ctx = dict(self.env.context, skip_expired=True) + ctx.pop('default_lot_ids') + return picking_to_validate.with_context(ctx).button_validate() return True def process_no_expired(self): diff --git a/addons/product_margin/models/product_product.py b/addons/product_margin/models/product_product.py index f11f613560..3620c0e618 100644 --- a/addons/product_margin/models/product_product.py +++ b/addons/product_margin/models/product_product.py @@ -94,13 +94,13 @@ class ProductProduct(models.Model): payment_states = () if invoice_state == 'paid': states = ('posted',) - payment_states = ('paid',) + payment_states = ('in_payment', 'paid',) elif invoice_state == 'open_paid': states = ('posted',) - payment_states = ('not_paid', 'paid') + payment_states = ('not_paid', 'in_payment', 'paid') elif invoice_state == 'draft_open_paid': states = ('posted', 'draft') - payment_states = ('not_paid', 'paid') + payment_states = ('not_paid', 'in_payment', 'paid') if "force_company" in self.env.context: company_id = self.env.context['force_company'] else: diff --git a/addons/survey/models/survey_question.py b/addons/survey/models/survey_question.py index 27a4f043ab..f8420a5537 100644 --- a/addons/survey/models/survey_question.py +++ b/addons/survey/models/survey_question.py @@ -393,6 +393,7 @@ class SurveyQuestion(models.Model): if question.question_type in ['simple_choice', 'multiple_choice', 'matrix']: answer_lines = all_lines.filtered( lambda line: line.answer_type == 'suggestion' or ( + line.skipped and not line.answer_type) or ( line.answer_type == 'char_box' and question.comment_count_as_answer) ) comment_line_ids = all_lines.filtered(lambda line: line.answer_type == 'char_box') diff --git a/addons/survey/models/survey_user.py b/addons/survey/models/survey_user.py index 9d00bf4f26..d8ed5e5216 100644 --- a/addons/survey/models/survey_user.py +++ b/addons/survey/models/survey_user.py @@ -268,6 +268,12 @@ class SurveyUserInput(models.Model): def _save_line_choice(self, question, old_answers, answers, comment): if not (isinstance(answers, list)): answers = [answers] + + if not answers: + # add a False answer to force saving a skipped line + # this will make this question correctly considered as skipped in statistics + answers = [False] + vals_list = [] if question.question_type == 'simple_choice': @@ -285,6 +291,11 @@ class SurveyUserInput(models.Model): def _save_line_matrix(self, question, old_answers, answers, comment): vals_list = [] + if not answers and question.matrix_row_ids: + # add a False answer to force saving a skipped line + # this will make this question correctly considered as skipped in statistics + answers = {question.matrix_row_ids[0].id: [False]} + if answers: for row_key, row_answer in answers.items(): for answer in row_answer: diff --git a/addons/survey/static/src/js/survey_result.js b/addons/survey/static/src/js/survey_result.js index eacbba1134..e40bd30fdf 100644 --- a/addons/survey/static/src/js/survey_result.js +++ b/addons/survey/static/src/js/survey_result.js @@ -94,22 +94,24 @@ publicWidget.registry.SurveyResultChart = publicWidget.Widget.extend({ return this._super.apply(this, arguments).then(function () { self.graphData = self.$el.data("graphData"); - switch (self.$el.data("graphType")) { - case 'multi_bar': - self.chartConfig = self._getMultibarChartConfig(); - break; - case 'bar': - self.chartConfig = self._getBarChartConfig(); - break; - case 'pie': - self.chartConfig = self._getPieChartConfig(); - break; - case 'doughnut': - self.chartConfig = self._getDoughnutChartConfig(); - break; - } + if (self.graphData && self.graphData.length !== 0) { + switch (self.$el.data("graphType")) { + case 'multi_bar': + self.chartConfig = self._getMultibarChartConfig(); + break; + case 'bar': + self.chartConfig = self._getBarChartConfig(); + break; + case 'pie': + self.chartConfig = self._getPieChartConfig(); + break; + case 'doughnut': + self.chartConfig = self._getDoughnutChartConfig(); + break; + } - self._loadChart(); + self._loadChart(); + } }); }, diff --git a/addons/survey/tests/common.py b/addons/survey/tests/common.py index 6ed08b0e25..2e73f17ca0 100644 --- a/addons/survey/tests/common.py +++ b/addons/survey/tests/common.py @@ -147,7 +147,7 @@ class SurveyCase(common.SavepointCase): return self.env['survey.user_input.line'].create(base_alvals) # ------------------------------------------------------------ - # UTILS + # UTILS / CONTROLLER ENDPOINTS FLOWS # ------------------------------------------------------------ def _access_start(self, survey): @@ -218,6 +218,36 @@ class SurveyCase(common.SavepointCase): post_data.update(**additional_post_data) return post_data + # ------------------------------------------------------------ + # UTILS / TOOLS + # ------------------------------------------------------------ + + def _assert_skipped_question(self, question, survey_user): + statistics = question._prepare_statistics(survey_user.user_input_line_ids) + question_data = next( + (question_data + for question_data in statistics + if question_data.get('question') == question), + False + ) + self.assertTrue(bool(question_data)) + self.assertEqual(len(question_data.get('answer_input_skipped_ids')), 1) + + def _create_one_question_per_type(self): + all_questions = self.env['survey.question'] + for (question_type, text) in self.env['survey.question']._fields['question_type'].selection: + kwargs = {} + if question_type == 'multiple_choice': + kwargs['labels'] = [{'value': 'MChoice0'}, {'value': 'MChoice1'}] + elif question_type == 'simple_choice': + kwargs['labels'] = [] + elif question_type == 'matrix': + kwargs['labels'] = [{'value': 'Column0'}, {'value': 'Column1'}] + kwargs['labels_2'] = [{'value': 'Row0'}, {'value': 'Row1'}] + all_questions |= self._add_question(self.page_0, 'Q0', question_type, **kwargs) + + return all_questions + class TestSurveyCommon(SurveyCase): def setUp(self): diff --git a/addons/survey/tests/test_survey.py b/addons/survey/tests/test_survey.py index 3919fa3a54..6d40e4ddfb 100644 --- a/addons/survey/tests/test_survey.py +++ b/addons/survey/tests/test_survey.py @@ -11,17 +11,7 @@ class TestSurveyInternals(common.TestSurveyCommon): @users('survey_manager') def test_answer_validation_mandatory(self): """ For each type of question check that mandatory questions correctly check for complete answers """ - for (question_type, text) in self.env['survey.question']._fields['question_type'].selection: - kwargs = {} - if question_type == 'multiple_choice': - kwargs['labels'] = [{'value': 'MChoice0'}, {'value': 'MChoice1'}] - elif question_type == 'simple_choice': - kwargs['labels'] = [] - elif question_type == 'matrix': - kwargs['labels'] = [{'value': 'Column0'}, {'value': 'Column1'}] - kwargs['labels_2'] = [{'value': 'Row0'}, {'value': 'Row1'}] - question = self._add_question(self.page_0, 'Q0', question_type, **kwargs) - + for question in self._create_one_question_per_type(): self.assertDictEqual( question.validate_question(''), {question.id: 'TestError'} @@ -113,3 +103,19 @@ class TestSurveyInternals(common.TestSurveyCommon): question.validate_question('valid'), {} ) + + @users('survey_manager') + def test_skipped_values(self): + """ Create one question per type of questions. + Make sure they are correctly registered as 'skipped' after saving an empty answer for each + of them. """ + + questions = self._create_one_question_per_type() + survey_user = self.survey._create_answer(user=self.survey_user) + + for question in questions: + answer = '' if question.question_type in ['char_box', 'text_box'] else None + survey_user.save_lines(question, answer) + + for question in questions: + self._assert_skipped_question(question, survey_user) diff --git a/addons/survey/views/survey_templates_statistics.xml b/addons/survey/views/survey_templates_statistics.xml index d6c67eee94..d362507381 100644 --- a/addons/survey/views/survey_templates_statistics.xml +++ b/addons/survey/views/survey_templates_statistics.xml @@ -352,7 +352,7 @@