decidim-forms 0.23.6 → 0.24.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/decidim/forms/forms.js.es6 +4 -4
  3. data/app/commands/decidim/forms/admin/update_questionnaire.rb +2 -1
  4. data/app/commands/decidim/forms/answer_questionnaire.rb +43 -1
  5. data/app/controllers/decidim/forms/admin/concerns/has_questionnaire.rb +10 -2
  6. data/app/controllers/decidim/forms/concerns/has_questionnaire.rb +10 -4
  7. data/app/forms/decidim/forms/admin/question_form.rb +2 -0
  8. data/app/forms/decidim/forms/answer_form.rb +27 -0
  9. data/app/helpers/decidim/forms/admin/application_helper.rb +1 -6
  10. data/app/helpers/decidim/forms/admin/concerns/has_questionnaire_answers_url_helper.rb +3 -3
  11. data/app/jobs/decidim/forms/export_questionnaire_answers_job.rb +1 -1
  12. data/app/models/decidim/forms/answer.rb +8 -0
  13. data/app/models/decidim/forms/question.rb +9 -3
  14. data/app/presenters/decidim/forms/admin/questionnaire_answer_presenter.rb +20 -0
  15. data/app/presenters/decidim/forms/admin/questionnaire_participant_presenter.rb +4 -4
  16. data/app/queries/decidim/forms/questionnaire_user_answers.rb +2 -1
  17. data/app/views/decidim/forms/admin/questionnaires/_form.html.erb +3 -3
  18. data/app/views/decidim/forms/admin/questionnaires/_question.html.erb +11 -0
  19. data/app/views/decidim/forms/admin/questionnaires/edit.html.erb +1 -1
  20. data/app/views/decidim/forms/questionnaires/_answer.html.erb +1 -1
  21. data/app/views/decidim/forms/questionnaires/answers/_files.html.erb +1 -0
  22. data/app/views/decidim/forms/questionnaires/answers/_long_answer.html.erb +1 -1
  23. data/app/views/decidim/forms/questionnaires/answers/_matrix_multiple.html.erb +2 -1
  24. data/app/views/decidim/forms/questionnaires/answers/_matrix_single.html.erb +2 -1
  25. data/app/views/decidim/forms/questionnaires/answers/_multiple_option.html.erb +2 -1
  26. data/app/views/decidim/forms/questionnaires/answers/_short_answer.html.erb +1 -1
  27. data/app/views/decidim/forms/questionnaires/answers/_single_option.html.erb +2 -1
  28. data/app/views/decidim/forms/questionnaires/show.html.erb +1 -1
  29. data/config/initializers/wicked_pdf.rb +2 -0
  30. data/config/locales/ca.yml +4 -2
  31. data/config/locales/cs.yml +8 -2
  32. data/config/locales/de.yml +8 -2
  33. data/config/locales/el.yml +1 -1
  34. data/config/locales/en.yml +8 -2
  35. data/config/locales/es-MX.yml +2 -2
  36. data/config/locales/es-PY.yml +2 -2
  37. data/config/locales/es.yml +2 -2
  38. data/config/locales/fi-plain.yml +8 -2
  39. data/config/locales/fi.yml +8 -2
  40. data/config/locales/fr-CA.yml +8 -2
  41. data/config/locales/fr.yml +8 -2
  42. data/config/locales/gl.yml +0 -3
  43. data/config/locales/it.yml +1 -2
  44. data/config/locales/ja.yml +2 -2
  45. data/config/locales/lv.yml +1 -1
  46. data/config/locales/nl.yml +4 -5
  47. data/config/locales/no.yml +1 -2
  48. data/config/locales/pl.yml +8 -2
  49. data/config/locales/pt.yml +1 -2
  50. data/config/locales/ro-RO.yml +1 -7
  51. data/config/locales/sv.yml +1 -4
  52. data/config/locales/tr-TR.yml +2 -2
  53. data/config/locales/zh-CN.yml +1 -2
  54. data/db/migrate/20210208094442_add_max_characters_to_decidim_forms_questions.rb +7 -0
  55. data/lib/decidim/api/answer_option_type.rb +13 -0
  56. data/lib/decidim/api/question_type.rb +21 -0
  57. data/lib/decidim/api/questionnaire_entity_interface.rb +5 -5
  58. data/lib/decidim/api/questionnaire_type.rb +19 -0
  59. data/lib/decidim/exporters/form_pdf_controller_helper.rb +2 -0
  60. data/lib/decidim/forms/api.rb +3 -0
  61. data/lib/decidim/forms/data_portability_user_answers_serializer.rb +7 -1
  62. data/lib/decidim/forms/test/factories.rb +12 -2
  63. data/lib/decidim/forms/test/shared_examples/has_questionnaire.rb +38 -5
  64. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_display_conditions.rb +7 -3
  65. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/add_questions.rb +1 -1
  66. data/lib/decidim/forms/test/shared_examples/manage_questionnaires/update_questions.rb +5 -0
  67. data/lib/decidim/forms/test/shared_examples/manage_questionnaires.rb +5 -4
  68. data/lib/decidim/forms/user_answers_serializer.rb +9 -1
  69. data/lib/decidim/forms/version.rb +1 -1
  70. data/lib/decidim/forms.rb +1 -1
  71. metadata +17 -15
  72. data/app/types/decidim/forms/answer_option_type.rb +0 -14
  73. data/app/types/decidim/forms/question_type.rb +0 -23
  74. data/app/types/decidim/forms/questionnaire_type.rb +0 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22d31db03a32b73c8aea6bc2fe8d1f4c31e09156db13c9507e7bad3abddc1bfc
4
- data.tar.gz: e0bd6174d6b1516268d6da9f96f4c3db806a9861cc56cd6675dd13b52d7e9f88
3
+ metadata.gz: 1f06c183113352ec8c74d0d958b1f1936a71f81ddd55c890e7254e1480b044f2
4
+ data.tar.gz: aafe2af6840afd6e2c757916bd44e185bbb2b4474380860e6c0d08641d246cb0
5
5
  SHA512:
6
- metadata.gz: ff6c2524b6eba8f4f26c568f2c91c2b33d5aa30ea53bbaff4b4e5ff8cf70cc4e7e6612bcd29cdadca20dfc76bc28bd2618867253d4aead32c2cc747731840342
7
- data.tar.gz: 684a2b52c6524f6ce2f9abc12e3ecebbf21586254c002bc222e4b294394c21e0bec4217afe9b9f2096954781383624321b84a04c05b6ee219670e29a9d6cc5ef
6
+ metadata.gz: 5ed91cbe536d809e93dd5a7b4f8723b04d982f25cc98aca21eca9b4a7c4a31d4c7f9c78f9aca9c7eeed8c139bdcc33dee163f0838d84c009f6d8d081585bdaa0
7
+ data.tar.gz: c0eadff0a39fcd19d392dbc4b49db1c7f0715f378a9e4287e4af562e8a008fcac3dc70c281376c00fb83f02d177cb5f1e5b89376af2cc5921288a56bf202330f
@@ -53,16 +53,16 @@
53
53
  window.exitUrl = event.currentTarget.action;
54
54
  });
55
55
 
56
- window.onbeforeunload = () => {
56
+ window.addEventListener("beforeunload", (event) => {
57
57
  const exitUrl = window.exitUrl;
58
58
  const hasChanged = $form.data("changed");
59
59
  window.exitUrl = null;
60
60
 
61
61
  if (!hasChanged || (exitUrl && exitUrl.includes(safePath))) {
62
- return null;
62
+ return;
63
63
  }
64
64
 
65
- return "";
66
- }
65
+ event.returnValue = true;
66
+ });
67
67
  }
68
68
  })(window);
@@ -48,7 +48,8 @@ module Decidim
48
48
  position: form_question.position,
49
49
  mandatory: form_question.mandatory,
50
50
  question_type: form_question.question_type,
51
- max_choices: form_question.max_choices
51
+ max_choices: form_question.max_choices,
52
+ max_characters: form_question.max_characters
52
53
  }
53
54
 
54
55
  update_nested_model(form_question, question_attributes, @questionnaire.questions) do |question|
@@ -4,6 +4,8 @@ module Decidim
4
4
  module Forms
5
5
  # This command is executed when the user answers a Questionnaire.
6
6
  class AnswerQuestionnaire < Rectify::Command
7
+ include ::Decidim::MultipleAttachmentsMethods
8
+
7
9
  # Initializes a AnswerQuestionnaire Command.
8
10
  #
9
11
  # form - The form from which to get the data.
@@ -21,14 +23,34 @@ module Decidim
21
23
  return broadcast(:invalid) if @form.invalid?
22
24
 
23
25
  answer_questionnaire
24
- broadcast(:ok)
26
+
27
+ if @errors
28
+ reset_form_attachments
29
+ broadcast(:invalid)
30
+ else
31
+ broadcast(:ok)
32
+ end
25
33
  end
26
34
 
27
35
  attr_reader :form
28
36
 
29
37
  private
30
38
 
39
+ # This method will add an error to the `add_documents` field only if there's
40
+ # any error in any other field or an error in another answer in the
41
+ # questionnaire. This is needed because when the form has
42
+ # an error, the attachments are lost, so we need a way to inform the user
43
+ # of this problem.
44
+ def reset_form_attachments
45
+ @form.responses.each do |answer|
46
+ answer.errors.add(:add_documents, :needs_to_be_reattached) if answer.has_attachments?
47
+ end
48
+ end
49
+
31
50
  def answer_questionnaire
51
+ @main_form = @form
52
+ @errors = nil
53
+
32
54
  Answer.transaction do
33
55
  form.responses_by_step.flatten.select(&:display_conditions_fulfilled?).each do |form_answer|
34
56
  answer = Answer.new(
@@ -51,7 +73,27 @@ module Decidim
51
73
  end
52
74
 
53
75
  answer.save!
76
+
77
+ next unless form_answer.question.has_attachments?
78
+
79
+ # The attachments module expects `@form` to be the form with the
80
+ # attachments
81
+ @form = form_answer
82
+ @attached_to = answer
83
+
84
+ build_attachments
85
+
86
+ if attachments_invalid?
87
+ @errors = true
88
+ next
89
+ end
90
+
91
+ create_attachments if process_attachments?
92
+ document_cleanup!
54
93
  end
94
+
95
+ @form = @main_form
96
+ raise ActiveRecord::Rollback if @errors
55
97
  end
56
98
  end
57
99
  end
@@ -15,8 +15,10 @@ module Decidim
15
15
 
16
16
  included do
17
17
  helper Decidim::Forms::Admin::ApplicationHelper
18
+ include Decidim::TranslatableAttributes
19
+
18
20
  helper_method :questionnaire_for, :questionnaire, :blank_question, :blank_answer_option, :blank_matrix_row,
19
- :blank_display_condition, :question_types, :display_condition_types, :update_url, :public_url, :answer_options_url
21
+ :blank_display_condition, :question_types, :display_condition_types, :update_url, :public_url, :answer_options_url, :edit_questionnaire_title
20
22
 
21
23
  if defined? Decidim::Templates::Admin
22
24
  include Decidim::Templates::Admin::Concerns::Templatable
@@ -97,7 +99,13 @@ module Decidim
97
99
  # Returns the url to get the answer options json (for the display conditions form)
98
100
  # for the question with id = params[:id]
99
101
  def answer_options_url(params)
100
- url_for([questionnaire.questionnaire_for, action: :answer_options, format: :json, **params])
102
+ url_for([questionnaire.questionnaire_for, { action: :answer_options, format: :json, **params }])
103
+ end
104
+
105
+ # Implement this method in your controller to set the title
106
+ # of the edit form.
107
+ def edit_questionnaire_title
108
+ t(:title, scope: "decidim.forms.admin.questionnaires.form", questionnaire_for: translated_attribute(questionnaire_for.try(:title)))
101
109
  end
102
110
 
103
111
  private
@@ -26,7 +26,7 @@ module Decidim
26
26
  end
27
27
 
28
28
  def answer
29
- enforce_permission_to :answer, :questionnaire
29
+ enforce_permission_to_answer_questionnaire
30
30
 
31
31
  @form = form(Decidim::Forms::QuestionnaireForm).from_params(params, session_token: session_token, ip_hash: ip_hash)
32
32
 
@@ -78,7 +78,7 @@ module Decidim
78
78
  # You can implement this method in your controller to change the URL
79
79
  # where the questionnaire will be submitted.
80
80
  def update_url
81
- url_for([questionnaire_for, action: :answer])
81
+ url_for([questionnaire_for, { action: :answer }])
82
82
  end
83
83
 
84
84
  # Points to the shortest path accessing the current form. This will be
@@ -87,7 +87,7 @@ module Decidim
87
87
  #
88
88
  # Overwrite this method at the controller.
89
89
  def form_path
90
- url_for([questionnaire_for, only_path: true])
90
+ url_for([questionnaire_for, { only_path: true }])
91
91
  end
92
92
 
93
93
  # Public: Method to be implemented at the controller. You need to
@@ -107,7 +107,7 @@ module Decidim
107
107
  end
108
108
 
109
109
  def spam_detected
110
- enforce_permission_to :answer, :questionnaire
110
+ enforce_permission_to_answer_questionnaire
111
111
 
112
112
  @form = form(Decidim::Forms::QuestionnaireForm).from_params(params)
113
113
 
@@ -115,6 +115,12 @@ module Decidim
115
115
  render template: "decidim/forms/questionnaires/show"
116
116
  end
117
117
 
118
+ # You can implement this method in your controller to change the
119
+ # enforce_permission_to arguments.
120
+ def enforce_permission_to_answer_questionnaire
121
+ enforce_permission_to :answer, :questionnaire
122
+ end
123
+
118
124
  def ip_hash
119
125
  return nil unless request&.remote_ip
120
126
 
@@ -14,6 +14,7 @@ module Decidim
14
14
  attribute :display_conditions, Array[DisplayConditionForm]
15
15
  attribute :matrix_rows, Array[QuestionMatrixRowForm]
16
16
  attribute :max_choices, Integer
17
+ attribute :max_characters, Integer, default: 0
17
18
  attribute :deleted, Boolean, default: false
18
19
 
19
20
  translatable_attribute :body, String
@@ -22,6 +23,7 @@ module Decidim
22
23
  validates :position, numericality: { greater_than_or_equal_to: 0 }
23
24
  validates :question_type, inclusion: { in: Decidim::Forms::Question::TYPES }
24
25
  validates :max_choices, numericality: { only_integer: true, greater_than: 1, less_than_or_equal_to: ->(form) { form.number_of_options } }, allow_blank: true
26
+ validates :max_characters, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
25
27
  validates :body, translatable_presence: true, if: :requires_body?
26
28
  validates :matrix_rows, presence: true, if: :matrix?
27
29
  validates :answer_options, presence: true, if: :matrix?
@@ -5,18 +5,23 @@ module Decidim
5
5
  # This class holds a Form to save the questionnaire answers from Decidim's public page
6
6
  class AnswerForm < Decidim::Form
7
7
  include Decidim::TranslationsHelper
8
+ include Decidim::AttachmentAttributes
8
9
 
9
10
  attribute :question_id, String
10
11
  attribute :body, String
11
12
  attribute :choices, Array[AnswerChoiceForm]
12
13
  attribute :matrix_choices, Array[AnswerChoiceForm]
13
14
 
15
+ attachments_attribute :documents
16
+
14
17
  validates :body, presence: true, if: :mandatory_body?
15
18
  validates :selected_choices, presence: true, if: :mandatory_choices?
16
19
 
17
20
  validate :max_choices, if: -> { question.max_choices }
18
21
  validate :all_choices, if: -> { question.question_type == "sorting" }
19
22
  validate :min_choices, if: -> { question.matrix? && question.mandatory? }
23
+ validate :documents_present, if: -> { question.question_type == "files" && question.mandatory? }
24
+ validate :max_characters, if: -> { question.max_characters.positive? }
20
25
 
21
26
  delegate :mandatory_body?, :mandatory_choices?, :matrix?, to: :question
22
27
 
@@ -49,6 +54,10 @@ module Decidim
49
54
  choices.select(&:body)
50
55
  end
51
56
 
57
+ def custom_choices
58
+ choices.select(&:custom_body)
59
+ end
60
+
52
61
  def display_conditions_fulfilled?
53
62
  question.display_conditions.all? do |condition|
54
63
  answer = context.responses&.find { |r| r.question_id&.to_i == condition.condition_question.id }
@@ -56,6 +65,10 @@ module Decidim
56
65
  end
57
66
  end
58
67
 
68
+ def has_attachments?
69
+ question.has_attachments? && errors[:add_documents].empty? && add_documents.present?
70
+ end
71
+
59
72
  private
60
73
 
61
74
  def mandatory_body?
@@ -78,6 +91,16 @@ module Decidim
78
91
  end
79
92
  end
80
93
 
94
+ def max_characters
95
+ if body.present?
96
+ errors.add(:body, :too_long) if body.size > question.max_characters
97
+ elsif custom_choices.any?
98
+ custom_choices.each do |choice|
99
+ errors.add(:body, :too_long) if choice.custom_body.size > question.max_characters
100
+ end
101
+ end
102
+ end
103
+
81
104
  def min_choices
82
105
  errors.add(:choices, :missing) if grouped_choices.count != question.matrix_rows.count
83
106
  end
@@ -93,6 +116,10 @@ module Decidim
93
116
  def max_choices_label
94
117
  I18n.t("questionnaires.question.max_choices", scope: "decidim.forms", n: question.max_choices)
95
118
  end
119
+
120
+ def documents_present
121
+ errors.add(:add_documents, :blank) if add_documents.empty? && errors[:add_documents].empty?
122
+ end
96
123
  end
97
124
  end
98
125
  end
@@ -31,7 +31,7 @@ module Decidim
31
31
  "placeholder" => options[:placeholder],
32
32
  "locale" => I18n.locale
33
33
  }
34
- content_tag :span, class: options[:class], data: data do
34
+ tag.span(class: options[:class], data: data) do
35
35
  truncate translated_attribute(title), length: options[:max_length], omission: options[:omission]
36
36
  end
37
37
  end
@@ -45,11 +45,6 @@ module Decidim
45
45
  def templates_defined?
46
46
  defined? Decidim::Templates::Admin::Concerns::Templatable
47
47
  end
48
-
49
- def title_for_questionnaire
50
- scope = templates_defined? ? "decidim.templates.admin.questionnaire_templates" : "decidim.forms.admin.questionnaires"
51
- t("form.title", scope: scope)
52
- end
53
48
  end
54
49
  end
55
50
  end
@@ -21,17 +21,17 @@ module Decidim
21
21
  # You can implement this method in your controller to change the URL
22
22
  # where the questionnaire participants' info will be shown.
23
23
  def questionnaire_participants_url
24
- url_for([:index, questionnaire.questionnaire_for, format: nil])
24
+ url_for([:index, questionnaire.questionnaire_for, { format: nil }])
25
25
  end
26
26
 
27
27
  # You can implement this method in your controller to change the URL
28
28
  # where the user's questionnaire answers will be shown.
29
29
  def questionnaire_participant_answers_url(session_token)
30
- url_for([:show, questionnaire.questionnaire_for, session_token: session_token])
30
+ url_for([:show, questionnaire.questionnaire_for, { session_token: session_token }])
31
31
  end
32
32
 
33
33
  def questionnaire_export_response_url(session_token)
34
- url_for([:export_response, questionnaire.questionnaire_for, session_token: session_token, format: "pdf"])
34
+ url_for([:export_response, questionnaire.questionnaire_for, { session_token: session_token, format: "pdf" }])
35
35
  end
36
36
  end
37
37
  end
@@ -7,7 +7,7 @@ module Decidim
7
7
 
8
8
  def perform(user, title, answers)
9
9
  return if user&.email.blank?
10
- return if answers&.blank?
10
+ return if answers.blank?
11
11
 
12
12
  serializer = Decidim::Forms::UserAnswersSerializer
13
13
  export_data = Decidim::Exporters::FormPDF.new(answers, serializer).export
@@ -6,6 +6,7 @@ module Decidim
6
6
  class Answer < Forms::ApplicationRecord
7
7
  include Decidim::DataPortability
8
8
  include Decidim::NewsletterParticipant
9
+ include Decidim::HasAttachments
9
10
 
10
11
  belongs_to :user, class_name: "Decidim::User", foreign_key: "decidim_user_id", optional: true
11
12
  belongs_to :questionnaire, class_name: "Questionnaire", foreign_key: "decidim_questionnaire_id"
@@ -20,6 +21,8 @@ module Decidim
20
21
  validate :user_questionnaire_same_organization
21
22
  validate :question_belongs_to_questionnaire
22
23
 
24
+ scope :not_separator, -> { joins(:question).where.not(decidim_forms_questions: { question_type: Decidim::Forms::Question::SEPARATOR_TYPE }) }
25
+
23
26
  def self.user_collection(user)
24
27
  where(decidim_user_id: user.id)
25
28
  end
@@ -39,6 +42,11 @@ module Decidim
39
42
  answers.pluck(:decidim_user_id).flatten.compact.uniq
40
43
  end
41
44
 
45
+ def organization
46
+ user.organization if user.present?
47
+ questionnaire&.questionnaire_for.try(:organization)
48
+ end
49
+
42
50
  private
43
51
 
44
52
  def user_questionnaire_same_organization
@@ -6,7 +6,7 @@ module Decidim
6
6
  class Question < Forms::ApplicationRecord
7
7
  include Decidim::TranslatableResource
8
8
 
9
- QUESTION_TYPES = %w(short_answer long_answer single_option multiple_option sorting matrix_single matrix_multiple).freeze
9
+ QUESTION_TYPES = %w(short_answer long_answer single_option multiple_option sorting files matrix_single matrix_multiple).freeze
10
10
  SEPARATOR_TYPE = "separator"
11
11
  TYPES = (QUESTION_TYPES + [SEPARATOR_TYPE]).freeze
12
12
 
@@ -48,6 +48,8 @@ module Decidim
48
48
 
49
49
  validates :question_type, inclusion: { in: TYPES }
50
50
 
51
+ scope :not_separator, -> { where.not(question_type: SEPARATOR_TYPE) }
52
+
51
53
  scope :with_body, -> { where(question_type: %w(short_answer long_answer)) }
52
54
  scope :with_choices, -> { where.not(question_type: %w(short_answer long_answer)) }
53
55
 
@@ -63,11 +65,11 @@ module Decidim
63
65
  end
64
66
 
65
67
  def mandatory_body?
66
- mandatory? && !multiple_choice?
68
+ mandatory? && !multiple_choice? && !has_attachments?
67
69
  end
68
70
 
69
71
  def mandatory_choices?
70
- mandatory? && multiple_choice?
72
+ mandatory? && multiple_choice? && !has_attachments?
71
73
  end
72
74
 
73
75
  def number_of_options
@@ -81,6 +83,10 @@ module Decidim
81
83
  def separator?
82
84
  question_type.to_s == SEPARATOR_TYPE
83
85
  end
86
+
87
+ def has_attachments?
88
+ question_type.to_s == "files"
89
+ end
84
90
  end
85
91
  end
86
92
  end
@@ -17,6 +17,7 @@ module Decidim
17
17
 
18
18
  def body
19
19
  return answer.body if answer.body.present?
20
+ return attachments if answer.attachments.any?
20
21
  return "-" if answer.choices.empty?
21
22
 
22
23
  choices = answer.choices.map do |choice|
@@ -30,8 +31,27 @@ module Decidim
30
31
  end
31
32
  end
32
33
 
34
+ def attachments
35
+ content_tag(:ul) do
36
+ safe_join(answer.attachments.map { |a| pretty_attachment(a) })
37
+ end
38
+ end
39
+
33
40
  private
34
41
 
42
+ def pretty_attachment(attachment)
43
+ # rubocop:disable Style/StringConcatenation
44
+ # Interpolating strings that are `html_safe` is problematic with Rails.
45
+ content_tag :li do
46
+ link_to(translated_attribute(attachment.title), attachment.url) +
47
+ " " +
48
+ content_tag(:small) do
49
+ "#{attachment.file_type} #{number_to_human_size(attachment.file_size)}"
50
+ end
51
+ end
52
+ # rubocop:enable Style/StringConcatenation
53
+ end
54
+
35
55
  def choice(choice_body)
36
56
  content_tag :li do
37
57
  choice_body
@@ -36,23 +36,23 @@ module Decidim
36
36
  end
37
37
 
38
38
  def first_short_answer
39
- short = sibilings.where("decidim_forms_questions.question_type in (?)", %w(short_answer))
39
+ short = sibilings.where(decidim_forms_questions: { question_type: %w(short_answer) })
40
40
  short.first
41
41
  end
42
42
 
43
43
  def completion
44
- with_body = sibilings.where("decidim_forms_questions.question_type in (?)", %w(short_answer long_answer))
44
+ with_body = sibilings.where(decidim_forms_questions: { question_type: %w(short_answer long_answer) })
45
45
  .where.not(body: "").count
46
46
  with_choices = sibilings.where.not("decidim_forms_questions.question_type in (?)", %w(short_answer long_answer))
47
47
  .where("decidim_forms_answers.id IN (SELECT decidim_answer_id FROM decidim_forms_answer_choices)").count
48
48
 
49
- (with_body + with_choices).to_f / questionnaire.questions.count * 100
49
+ (with_body + with_choices).to_f / questionnaire.questions.not_separator.count * 100
50
50
  end
51
51
 
52
52
  private
53
53
 
54
54
  def sibilings
55
- Answer.where(questionnaire: questionnaire, session_token: participant.session_token).joins(:question).order("decidim_forms_questions.position ASC")
55
+ Answer.not_separator.where(questionnaire: questionnaire, session_token: participant.session_token).joins(:question).order("decidim_forms_questions.position ASC")
56
56
  end
57
57
  end
58
58
  end