decidim-forms 0.23.6 → 0.24.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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