diff --git a/back/app/controllers/web_api/v1/ideas_controller.rb b/back/app/controllers/web_api/v1/ideas_controller.rb index d39c43dbb639..52a8d84b1806 100644 --- a/back/app/controllers/web_api/v1/ideas_controller.rb +++ b/back/app/controllers/web_api/v1/ideas_controller.rb @@ -32,6 +32,7 @@ def index :idea_trending_info, :topics, :phases, + :idea_status, :creation_phase, :manual_votes_last_updated_by, { diff --git a/back/app/models/idea_status.rb b/back/app/models/idea_status.rb index fa82997e9916..e175bcfffd09 100644 --- a/back/app/models/idea_status.rb +++ b/back/app/models/idea_status.rb @@ -19,6 +19,7 @@ class IdeaStatus < ApplicationRecord CODES = %w[prescreening proposed threshold_reached expired viewed under_consideration accepted implemented rejected answered ineligible custom].freeze LOCKED_CODES = %w[prescreening proposed threshold_reached expired].freeze MANUAL_TRANSITION_NOT_ALLOWED_CODES = %w[prescreening threshold_reached expired].freeze + REACTING_NOT_ALLOWED_CODES = %w[prescreening expired ineligible].freeze NON_PUBLIC_CODES = %w[prescreening].freeze scope :for_public_posts, -> { where.not(code: NON_PUBLIC_CODES) } diff --git a/back/app/services/permissions/idea_permissions_service.rb b/back/app/services/permissions/idea_permissions_service.rb index b4e905109e57..57187d5c397e 100644 --- a/back/app/services/permissions/idea_permissions_service.rb +++ b/back/app/services/permissions/idea_permissions_service.rb @@ -4,7 +4,8 @@ class IdeaPermissionsService < ProjectPermissionsService idea_not_in_current_phase: 'idea_not_in_current_phase', votes_exist: 'votes_exist', published_after_screening: 'published_after_screening', - not_author: 'not_author' + not_author: 'not_author', + not_reactable_status_code: 'not_reactable_status_code' }.freeze def initialize(idea, user, user_requirements_service: nil) @@ -39,7 +40,11 @@ def denied_reason_for_action(action, reaction_mode: nil, delete_action: false) # We preserved the behaviour that was already there, but we're not # sure if this is the desired behaviour. current_phase = @timeline_service.current_phase_not_archived project - IDEA_DENIED_REASONS[:idea_not_in_current_phase] if current_phase && !idea_in_current_phase?(current_phase) + return IDEA_DENIED_REASONS[:idea_not_in_current_phase] if current_phase && !idea_in_current_phase?(current_phase) + + if action == 'reacting_idea' && IdeaStatus::REACTING_NOT_ALLOWED_CODES.include?(idea.idea_status.code) + IDEA_DENIED_REASONS[:not_reactable_status_code] + end end end diff --git a/back/spec/services/permissions/idea_permissions_service_spec.rb b/back/spec/services/permissions/idea_permissions_service_spec.rb index 7829d8871a64..f8c686893601 100644 --- a/back/spec/services/permissions/idea_permissions_service_spec.rb +++ b/back/spec/services/permissions/idea_permissions_service_spec.rb @@ -125,6 +125,42 @@ expect(reason).to be_nil end + context "when idea has 'proposed' status" do + let(:proposed_status) { create(:idea_status, code: 'proposed') } + let(:input) { create(:idea, project: project, phases: [project.phases[2]], idea_status: proposed_status) } + + it "does not return 'not_reactable_status_code'" do + expect(reason).to be_nil + end + end + + context "when idea has 'prescreening' status" do + let(:prescreening_status) { create(:idea_status, code: 'prescreening') } + let(:input) { create(:idea, project: project, phases: [project.phases[2]], publication_status: 'submitted', idea_status: prescreening_status) } + + it "returns 'not_reactable_status_code'" do + expect(reason).to eq 'not_reactable_status_code' + end + end + + context "when idea has 'ineligible' status" do + let(:ineligible_status) { create(:idea_status, code: 'ineligible') } + let(:input) { create(:idea, project: project, phases: [project.phases[2]], idea_status: ineligible_status) } + + it "returns 'not_reactable_status_code'" do + expect(reason).to eq 'not_reactable_status_code' + end + end + + context "when idea has 'expired' status" do + let(:expired_status) { create(:idea_status, code: 'ineligible') } + let(:input) { create(:idea, project: project, phases: [project.phases[2]], idea_status: expired_status) } + + it "returns 'not_reactable_status_code'" do + expect(reason).to eq 'not_reactable_status_code' + end + end + context 'when the idea is not in the current phase' do let(:input) { create(:idea, project: project, phases: [project.phases[1]]) } @@ -471,6 +507,7 @@ :idea_images, :idea_trending_info, :topics, :idea_import, :phases, + :idea_status, { project: [:admin_publication, { phases: { permissions: [:groups] } }, { custom_form: [:custom_fields] }], author: [:unread_notifications]