diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 3e1b78d31..495a25314 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -114,4 +114,10 @@ class ApplicationController < ActionController::Base store_location_for(:user, request.path) end end + + def set_default_budget_filter + if @budget.try(:balloting?) + params[:filter] ||= "selected" + end + end end diff --git a/app/controllers/budgets/groups_controller.rb b/app/controllers/budgets/groups_controller.rb index e55974a6a..d84eb2fdd 100644 --- a/app/controllers/budgets/groups_controller.rb +++ b/app/controllers/budgets/groups_controller.rb @@ -3,6 +3,9 @@ module Budgets load_and_authorize_resource :budget load_and_authorize_resource :group, class: "Budget::Group" + before_action :set_default_budget_filter, only: :show + has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:show] + def show end diff --git a/app/controllers/budgets/investments_controller.rb b/app/controllers/budgets/investments_controller.rb index 7f9c6e7ee..7eb1b1291 100644 --- a/app/controllers/budgets/investments_controller.rb +++ b/app/controllers/budgets/investments_controller.rb @@ -14,18 +14,20 @@ module Budgets before_action :load_heading, only: [:index, :show] before_action :set_random_seed, only: :index before_action :load_categories, only: [:index, :new, :create] + before_action :set_default_budget_filter, only: :index feature_flag :budgets has_orders %w{most_voted newest oldest}, only: :show has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index + has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: [:index, :show] invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment respond_to :html, :js def index - @investments = @investments.apply_filters_and_search(@budget, params).send("sort_by_#{@current_order}").page(params[:page]).per(10).for_render + @investments = @investments.apply_filters_and_search(@budget, params, @current_filter).send("sort_by_#{@current_order}").page(params[:page]).per(10).for_render @investment_ids = @investments.pluck(:id) load_investment_votes(@investments) @tag_cloud = tag_cloud @@ -107,6 +109,7 @@ module Budgets def tag_cloud TagCloud.new(Budget::Investment, params[:search]) end + end end diff --git a/app/controllers/budgets_controller.rb b/app/controllers/budgets_controller.rb index ee26f3223..2a53c410b 100644 --- a/app/controllers/budgets_controller.rb +++ b/app/controllers/budgets_controller.rb @@ -3,6 +3,9 @@ class BudgetsController < ApplicationController feature_flag :budgets load_and_authorize_resource + before_action :set_default_budget_filter, only: :show + has_filters %w{not_unfeasible feasible unfeasible unselected selected}, only: :show + respond_to :html, :js def show diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 7f0150293..64adbaddf 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -46,7 +46,8 @@ class Budget scope :not_unfeasible, -> { where.not(feasibility: "unfeasible") } scope :undecided, -> { where(feasibility: "undecided") } scope :with_supports, -> { where('cached_votes_up > 0') } - scope :selected, -> { where(selected: true) } + scope :selected, -> { feasible.where(selected: true) } + scope :unselected, -> { feasible.where(selected: false) } scope :last_week, -> { where("created_at >= ?", 7.days.ago)} scope :by_group, -> (group_id) { where(group_id: group_id) } @@ -217,6 +218,12 @@ class Budget budget.balloting? end + def should_show_price? + feasible? && + selected? && + (budget.reviewing_ballots? || budget.finished?) + end + def should_show_price_info? feasible? && price_explanation.present? && @@ -227,13 +234,9 @@ class Budget budget.formatted_amount(price) end - def self.apply_filters_and_search(budget, params) + def self.apply_filters_and_search(budget, params, current_filter=nil) investments = all - if budget.balloting? - investments = investments.selected - else - investments = params[:unfeasible].present? ? investments.unfeasible : investments.not_unfeasible - end + investments = investments.send(current_filter) if current_filter.present? investments = investments.by_heading(params[:heading_id]) if params[:heading_id].present? investments = investments.search(params[:search]) if params[:search].present? investments @@ -245,5 +248,6 @@ class Budget self.group_id = self.heading.try(:group_id) if self.heading_id_changed? self.budget_id ||= self.heading.try(:group).try(:budget_id) end + end end diff --git a/app/views/budgets/groups/show.html.erb b/app/views/budgets/groups/show.html.erb index 73fb3288f..d2e1c01fc 100644 --- a/app/views/budgets/groups/show.html.erb +++ b/app/views/budgets/groups/show.html.erb @@ -7,15 +7,21 @@ -<% if params[:unfeasible] %> +<% if @current_filter == "unfeasible" %>

<%= t("budgets.groups.show.unfeasible_title") %>

+<% elsif @current_filter == "unselected" %> +
+
+

<%= t("budgets.groups.show.unselected_title") %>

+
+
<% end %> -
+
<% @group.headings.each_slice(7) do |slice| %> @@ -25,7 +31,7 @@ class="<%= css_for_ballot_heading(heading) %>"> <%= link_to heading.name, budget_investments_path(heading_id: heading.id, - unfeasible: params[:unfeasible]), + filter: @current_filter), data: { no_turbolink: true } %>
<% end %> @@ -39,11 +45,24 @@
-<% if params[:unfeasible].blank? %> -
+<% unless @current_filter == "unfeasible" %> +
- <%= link_to t("budgets.groups.show.unfeasible"), - budget_path(@budget, unfeasible: 1) %> + + <%= link_to t("budgets.groups.show.unfeasible"), + budget_path(@budget, filter: "unfeasible") %> + +
+
+<% end %> + +<% unless @current_filter == "unselected" %> +
+
+ + <%= link_to t("budgets.groups.show.unselected"), + budget_path(@budget, filter: "unselected") %> +
<% end %> diff --git a/app/views/budgets/investments/_investment.html.erb b/app/views/budgets/investments/_investment.html.erb index c9391cbe5..3155853cd 100644 --- a/app/views/budgets/investments/_investment.html.erb +++ b/app/views/budgets/investments/_investment.html.erb @@ -73,6 +73,13 @@ ballot: ballot } %>
+ <% elsif investment.should_show_price? %> +
+

+ <%= investment.formatted_price %> +

+
<% end %> <% end %> diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb index e0822145b..f9a371585 100644 --- a/app/views/budgets/investments/_investment_show.html.erb +++ b/app/views/budgets/investments/_investment_show.html.erb @@ -98,6 +98,15 @@

<% end %> + <% if investment.should_show_price? %> + +

<%= t("budgets.investments.show.price") %>

+
+

+ <%= investment.formatted_price %> +

+
+ <% end %>

<%= t("budgets.investments.show.share") %>

diff --git a/app/views/budgets/investments/index.html.erb b/app/views/budgets/investments/index.html.erb index 50a2866f9..95b60f55b 100644 --- a/app/views/budgets/investments/index.html.erb +++ b/app/views/budgets/investments/index.html.erb @@ -16,7 +16,7 @@
- <% if params[:unfeasible].present? %> + <% if @current_filter == "unfeasible" %>

<%= t("budgets.investments.index.unfeasible") %>: <%= @heading.name %>

<%= t("budgets.investments.index.unfeasible_text", @@ -34,7 +34,7 @@ <% end %>
- <%= render('shared/order_links', i18n_namespace: "budgets.investments.index") unless params[:unfeasible].present? %> + <%= render('shared/order_links', i18n_namespace: "budgets.investments.index") unless @current_filter == "unfeasible" %> <% @investments.each do |investment| %> <%= render partial: '/budgets/investments/investment', locals: { diff --git a/app/views/budgets/show.html.erb b/app/views/budgets/show.html.erb index e49cd4252..f67b3ca9d 100644 --- a/app/views/budgets/show.html.erb +++ b/app/views/budgets/show.html.erb @@ -35,10 +35,12 @@
-
+
- <% if params[:unfeasible] %> + <% if @current_filter == "unfeasible" %>

<%= t("budgets.show.unfeasible_title") %>

+ <% elsif @current_filter == "unselected" %> +

<%= t("budgets.show.unselected_title") %>

<% end %> @@ -52,12 +54,12 @@ <%= link_to group.name, budget_investments_path(@budget, heading_id: group.headings.first.id, - unfeasible: params[:unfeasible]), + filter: @current_filter), data: { no_turbolink: true } %> <% else %> <%= link_to group.name, budget_group_path(@budget, group, - unfeasible: params[:unfeasible]) %> + filter: @current_filter) %> <% end %>
@@ -68,11 +70,24 @@ -<% unless params[:unfeasible] %> -
+<% unless @current_filter == "unfeasible" %> +
- <%= link_to t("budgets.show.unfeasible"), - budget_path(@budget, unfeasible: 1) %> + + <%= link_to t("budgets.show.unfeasible"), + budget_path(@budget, filter: "unfeasible") %> + +
+
+<% end %> + +<% unless @current_filter == "unselected" %> +
+
+ + <%= link_to t("budgets.show.unselected"), + budget_path(@budget, filter: "unselected") %> +
<% end %> diff --git a/config/locales/budgets.en.yml b/config/locales/budgets.en.yml index 7b3251ad4..49d1558cf 100644 --- a/config/locales/budgets.en.yml +++ b/config/locales/budgets.en.yml @@ -24,6 +24,8 @@ en: title: Select an option unfeasible_title: Unfeasible investments unfeasible: See unfeasible investments + unselected_title: Investments not selected for balloting phase + unselected: See investments not selected for balloting phase phase: accepting: Accepting projects reviewing: Reviewing projects @@ -84,6 +86,7 @@ en: title: Investment project supports: Supports votes: Votes + price: Price wrong_price_format: Only integer numbers investment: title: Investment project @@ -106,4 +109,6 @@ en: group: Group phase: Actual phase unfeasible_title: Unfeasible investments - unfeasible: See unfeasible investments \ No newline at end of file + unfeasible: See unfeasible investments + unselected_title: Investments not selected for balloting phase + unselected: See investments not selected for balloting phase \ No newline at end of file diff --git a/config/locales/budgets.es.yml b/config/locales/budgets.es.yml index 44b748698..98ef4ad4e 100644 --- a/config/locales/budgets.es.yml +++ b/config/locales/budgets.es.yml @@ -24,6 +24,8 @@ es: title: Selecciona una opción unfeasible_title: Propuestas inviables unfeasible: Ver propuestas inviables + unselected_title: Propuestas que no pasan a la votación final + unselected: Ver las propuestas que no pasan a la votación final phase: accepting: Presentación de proyectos reviewing: Revisión interna de proyectos @@ -84,6 +86,7 @@ es: title: Propuesta de inversión supports: Apoyos votes: Votos + price: Coste wrong_price_format: Solo puede incluir caracteres numéricos investment: title: Propuesta de inversión @@ -107,3 +110,5 @@ es: phase: Fase actual unfeasible_title: Propuestas inviables unfeasible: Ver las propuestas inviables + unselected_title: Propuestas que no pasan a la votación final + unselected: Ver las propuestas que no pasan a la votación final \ No newline at end of file diff --git a/spec/factories.rb b/spec/factories.rb index b295fd60c..f0a4fc5a2 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -284,6 +284,12 @@ FactoryGirl.define do feasibility "feasible" valuation_finished true end + + trait :unselected do + selected false + feasibility "feasible" + valuation_finished true + end end factory :budget_ballot, class: 'Budget::Ballot' do diff --git a/spec/features/budgets/ballots_spec.rb b/spec/features/budgets/ballots_spec.rb index b79d3c468..e932b577f 100644 --- a/spec/features/budgets/ballots_spec.rb +++ b/spec/features/budgets/ballots_spec.rb @@ -469,10 +469,12 @@ feature 'Ballots' do end scenario 'Unselected investments' do - investment = create(:budget_investment, heading: new_york) + investment = create(:budget_investment, heading: new_york, title: "WTF asdfasfd") login_as(user) - visit budget_investments_path(budget, heading_id: new_york.id, unfeasible: 1) + visit budget_path(budget) + click_link states.name + click_link new_york.name expect(page).to_not have_css("#budget_investment_#{investment.id}") end @@ -481,7 +483,9 @@ feature 'Ballots' do investment = create(:budget_investment, feasibility: "undecided", heading: new_york) login_as(user) - visit budget_investments_path(budget, heading_id: new_york.id) + visit budget_path(budget) + click_link states.name + click_link new_york.name within("#budget-investments") do expect(page).to_not have_css("div.ballot") diff --git a/spec/features/budgets/investments_spec.rb b/spec/features/budgets/investments_spec.rb index 8a817a805..0df280fd3 100644 --- a/spec/features/budgets/investments_spec.rb +++ b/spec/features/budgets/investments_spec.rb @@ -8,10 +8,14 @@ feature 'Budget Investments' do let!(:heading) { create(:budget_heading, name: "More hospitals", group: group) } scenario 'Index' do - investments = [create(:budget_investment, heading: heading), create(:budget_investment, heading: heading), create(:budget_investment, :feasible, heading: heading)] + investments = [create(:budget_investment, heading: heading), + create(:budget_investment, heading: heading), + create(:budget_investment, :feasible, heading: heading)] + unfeasible_investment = create(:budget_investment, :unfeasible, heading: heading) - visit budget_investments_path(budget, heading_id: heading.id) + visit budget_path(budget) + click_link "Health" expect(page).to have_selector('#budget-investments .budget-investment', count: 3) investments.each do |investment| @@ -56,7 +60,7 @@ feature 'Budget Investments' do investment3 = create(:budget_investment, heading: heading) investment4 = create(:budget_investment, :feasible, heading: heading) - visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, unfeasible: 1) + visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, filter: "unfeasible") within("#budget-investments") do expect(page).to have_css('.budget-investment', count: 1) @@ -77,7 +81,7 @@ feature 'Budget Investments' do click_link "All City" - expected_path = budget_investments_path(budget, heading_id: heading.id, unfeasible: 1) + expected_path = budget_investments_path(budget, heading_id: heading.id, filter: "unfeasible") expect(page).to have_current_path(expected_path) end @@ -93,7 +97,7 @@ feature 'Budget Investments' do click_link 'Districts' click_link 'Carabanchel' - expected_path = budget_investments_path(budget, heading_id: heading1.id, unfeasible: 1) + expected_path = budget_investments_path(budget, heading_id: heading1.id, filter: "unfeasible") expect(page).to have_current_path(expected_path) end end @@ -516,8 +520,6 @@ feature 'Budget Investments' do expect(page).to have_content "€10,000" end - - scenario "Sidebar in show should display vote text" do investment = create(:budget_investment, :selected, budget: budget) visit budget_investment_path(budget, investment) @@ -537,7 +539,6 @@ feature 'Budget Investments' do carabanchel_heading = create(:budget_heading, group: group, name: "Carabanchel") new_york_heading = create(:budget_heading, group: group, name: "New York") - sp1 = create(:budget_investment, :selected, price: 1, heading: global_heading) sp2 = create(:budget_investment, :selected, price: 10, heading: global_heading) sp3 = create(:budget_investment, :selected, price: 100, heading: global_heading) @@ -602,5 +603,52 @@ feature 'Budget Investments' do end end + scenario 'Show unselected budget investments' do + investment1 = create(:budget_investment, :unselected, :feasible, heading: heading, valuation_finished: true) + investment2 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) + investment3 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) + investment4 = create(:budget_investment, :selected, :feasible, heading: heading, valuation_finished: true) + + visit budget_investments_path(budget_id: budget.id, heading_id: heading.id, filter: "unselected") + + within("#budget-investments") do + expect(page).to have_css('.budget-investment', count: 1) + + expect(page).to have_content(investment1.title) + expect(page).to_not have_content(investment2.title) + expect(page).to_not have_content(investment3.title) + expect(page).to_not have_content(investment4.title) + end + end + + scenario "Shows unselected link for group with one heading" do + group = create(:budget_group, name: 'All City', budget: budget) + heading = create(:budget_heading, name: "Madrid", group: group) + + visit budget_path(budget) + click_link 'See investments not selected for balloting phase' + + click_link "All City" + + expected_path = budget_investments_path(budget, heading_id: heading.id, filter: "unselected") + expect(page).to have_current_path(expected_path) + end + + scenario "Shows unselected link for group with many headings" do + group = create(:budget_group, name: 'Districts', budget: budget) + heading1 = create(:budget_heading, name: 'Carabanchel', group: group) + heading2 = create(:budget_heading, name: 'Barajas', group: group) + + visit budget_path(budget) + + click_link 'See investments not selected for balloting phase' + + click_link 'Districts' + click_link 'Carabanchel' + + expected_path = budget_investments_path(budget, heading_id: heading1.id, filter: "unselected") + expect(page).to have_current_path(expected_path) + end + end end diff --git a/spec/features/tags/budget_investments_spec.rb b/spec/features/tags/budget_investments_spec.rb index 28d19333f..4c978c740 100644 --- a/spec/features/tags/budget_investments_spec.rb +++ b/spec/features/tags/budget_investments_spec.rb @@ -199,11 +199,12 @@ feature 'Tags' do if budget.balloting? [investment1, investment2, investment3].each do |investment| - investment.update(selected: true) + investment.update(selected: true, feasibility: "feasible") end end - visit budget_investments_path(budget, heading_id: heading.id) + visit budget_path(budget) + click_link group.name within "#tag-cloud" do click_link "Medio Ambiente" @@ -246,11 +247,12 @@ feature 'Tags' do if budget.balloting? [investment1, investment2, investment3].each do |investment| - investment.update(selected: true) + investment.update(selected: true, feasibility: "feasible") end end - visit budget_investments_path(budget, heading_id: heading.id, search: 'Economía') + visit budget_path(budget) + click_link group.name within "#categories" do click_link "Medio Ambiente" diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb index e9d5ccd13..2c5f03738 100644 --- a/spec/models/budget/investment_spec.rb +++ b/spec/models/budget/investment_spec.rb @@ -337,6 +337,92 @@ describe Budget::Investment do end end + describe "apply_filters_and_search" do + + let(:budget) { create(:budget) } + + it "returns feasible investments" do + investment1 = create(:budget_investment, :feasible, budget: budget) + investment2 = create(:budget_investment, :feasible, budget: budget) + investment3 = create(:budget_investment, :unfeasible, budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, {}, :feasible) + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + + it "returns unfeasible investments" do + investment1 = create(:budget_investment, :unfeasible, budget: budget) + investment2 = create(:budget_investment, :unfeasible, budget: budget) + investment3 = create(:budget_investment, :feasible, budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, {}, :unfeasible) + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + + it "returns selected investments" do + budget.update(phase: "balloting") + + investment1 = create(:budget_investment, :feasible, :selected, budget: budget) + investment2 = create(:budget_investment, :feasible, :selected, budget: budget) + investment3 = create(:budget_investment, :feasible, :unselected, budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, {}, :selected) + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + + it "returns unselected investments" do + budget.update(phase: "balloting") + + investment1 = create(:budget_investment, :feasible, :unselected, budget: budget) + investment2 = create(:budget_investment, :feasible, :unselected, budget: budget) + investment3 = create(:budget_investment, :feasible, :selected, budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, {}, :unselected) + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + + it "returns investmens by heading" do + group = create(:budget_group, budget: budget) + + heading1 = create(:budget_heading, group: group) + heading2 = create(:budget_heading, group: group) + + investment1 = create(:budget_investment, heading: heading1, budget: budget) + investment2 = create(:budget_investment, heading: heading1, budget: budget) + investment3 = create(:budget_investment, heading: heading2, budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, heading_id: heading1.id) + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + + it "returns investments by search string" do + investment1 = create(:budget_investment, title: "health for all", budget: budget) + investment2 = create(:budget_investment, title: "improved health", budget: budget) + investment3 = create(:budget_investment, title: "finance", budget: budget) + + results = Budget::Investment::apply_filters_and_search(budget, search: "health") + + expect(results).to include investment1 + expect(results).to include investment2 + expect(results).to_not include investment3 + end + end + describe "search" do context "tags" do