diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index 4b6bd6b3a..0208fccd8 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -1,4 +1,5 @@ class Admin::BudgetInvestmentsController < Admin::BaseController + include FeatureFlags feature_flag :budgets @@ -12,6 +13,13 @@ class Admin::BudgetInvestmentsController < Admin::BaseController before_action :load_investments, only: [:index, :toggle_selection] def index + respond_to do |format| + format.html + format.csv do + send_data Budget::Investment.to_csv(@investments, {headers: true}), + filename: 'budget_investments.csv' + end + end end def show @@ -46,7 +54,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController def load_investments @investments = Budget::Investment.scoped_filter(params, @current_filter) .order(cached_votes_up: :desc, created_at: :desc) - .page(params[:page]) + @investments = @investments.page(params[:page]) unless request.format.csv? end def budget_investment_params diff --git a/app/helpers/budgets_helper.rb b/app/helpers/budgets_helper.rb index 3b4c81f7e..a14b86538 100644 --- a/app/helpers/budgets_helper.rb +++ b/app/helpers/budgets_helper.rb @@ -1,5 +1,31 @@ module BudgetsHelper + def csv_params + csv_params = params.clone.merge(format: :csv).symbolize_keys + csv_params.delete(:page) + csv_params + end + + def investment_selected_link(investment) + options = investment_selected_link_options(investment) + path = toggle_selection_admin_budget_budget_investment_path(@budget, + investment, filter: params[:filter], page: params[:page]) + link_options = {method: :patch, remote: true, class: options[:link_class]} + link_to options[:text], path, link_options + end + + def investment_selected_link_options(investment) + if investment.selected? + {link_class: "button small expanded", + text: t("admin.budget_investments.index.selected") } + elsif investment.feasible? && investment.valuation_finished? + {link_class: "button small hollow expanded", + text: t("admin.budget_investments.index.select")} + else + {} + end + end + def budget_phases_select_options Budget::PHASES.map { |ph| [ t("budgets.phase.#{ph}"), ph ] } end diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index f40878702..4e2e5d0b0 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -1,5 +1,6 @@ class Budget class Investment < ActiveRecord::Base + require 'csv' include Measurable include Sanitizable include Taggable @@ -262,6 +263,46 @@ class Budget investments end + def self.to_csv(investments, options = {}) + attrs = [I18n.t("admin.budget_investments.index.table_id"), + I18n.t("admin.budget_investments.index.table_title"), + I18n.t("admin.budget_investments.index.table_supports"), + I18n.t("admin.budget_investments.index.table_admin"), + I18n.t("admin.budget_investments.index.table_valuator"), + I18n.t("admin.budget_investments.index.table_geozone"), + I18n.t("admin.budget_investments.index.table_feasibility"), + I18n.t("admin.budget_investments.index.table_valuation_finished"), + I18n.t("admin.budget_investments.index.table_selection")] + csv_string = CSV.generate(options) do |csv| + csv << attrs + investments.each do |investment| + id = investment.id.to_s + title = investment.title + total_votes = investment.total_votes.to_s + admin = if investment.administrator.present? + investment.administrator.name + else + I18n.t("admin.budget_investments.index.no_admin_assigned") + end + vals = if investment.valuators.empty? + I18n.t("admin.budget_investments.index.no_valuators_assigned") + else + investment.valuators.collect(&:description_or_name).join(', ') + end + heading_name = investment.heading.name + price_string = "admin.budget_investments.index.feasibility"\ + ".#{investment.feasibility}" + price = I18n.t(price_string, price: investment.formatted_price) + valuation_finished = investment.valuation_finished? ? + I18n.t('shared.yes') : + I18n.t('shared.no') + csv << [id, title, total_votes, admin, vals, heading_name, price, + valuation_finished] + end + end + csv_string + end + private def set_denormalized_ids diff --git a/app/views/admin/budget_investments/_investments.html.erb b/app/views/admin/budget_investments/_investments.html.erb index f90c75ac7..75bde7002 100644 --- a/app/views/admin/budget_investments/_investments.html.erb +++ b/app/views/admin/budget_investments/_investments.html.erb @@ -1,4 +1,7 @@ -

<%= page_entries_info @investments %>

+
+ <%= link_to 'download current selecction',admin_budget_budget_investments_path(csv_params), class: 'advanced-search small' %> +

<%= page_entries_info @investments %>

+
@@ -55,25 +58,7 @@ <%= investment.valuation_finished? ? t('shared.yes'): t('shared.no') %> <% if params[:filter] == 'selected' %>
- <% if investment.selected? %> - <%= link_to_unless investment.budget.finished?, t("admin.budget_investments.index.selected"), - toggle_selection_admin_budget_budget_investment_path(@budget, - investment, - filter: params[:filter], - page: params[:page]), - method: :patch, - remote: true, - class: "button small expanded" %> - <% elsif investment.feasible? && investment.valuation_finished? %> - <%= link_to_unless investment.budget.finished?, t("admin.budget_investments.index.select"), - toggle_selection_admin_budget_budget_investment_path(@budget, - investment, - filter: params[:filter], - page: params[:page]), - method: :patch, - remote: true, - class: "button small hollow expanded" %> - <% end %> + <%= investment_selected_link(investment) %> diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 2bc1dabf2..c3fc69473 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -625,7 +625,57 @@ feature 'Admin budget investments' do expect(page).not_to have_link('Selected') end end + end + context "Selecting csv" do + + scenario "Downloading CSV file" do + investment = create(:budget_investment, :feasible, budget: @budget, + price: 100) + valuator = create(:valuator, user: create(:user, username: 'Rachel', + email: 'rachel@val.org')) + investment.valuators << valuator + + admin = create(:administrator, user: create(:user, username: 'Gema')) + investment.update(administrator_id: admin.id) + + visit admin_budget_budget_investments_path(@budget, format: :csv) + + header = page.response_headers['Content-Disposition'] + expect(header).to match(/^attachment/) + expect(header).to match(/filename="budget_investments.csv"$/) + + valuators = investment.valuators.collect(&:description_or_name).join(', ') + feasibility_string = "admin.budget_investments.index"\ + ".feasibility.#{investment.feasibility}" + price = I18n.t(feasibility_string, price: investment.formatted_price) + + expect(page).to have_content investment.title + expect(page).to have_content investment.total_votes.to_s + expect(page).to have_content investment.id.to_s + expect(page).to have_content investment.heading.name + + expect(page).to have_content investment.administrator.name + expect(page).to have_content valuators + expect(page).to have_content price + expect(page).to have_content I18n.t('shared.no') + end + + scenario "Downloading CSV file with applied filter" do + investment1 = create(:budget_investment, :unfeasible, budget: @budget, + title: 'compatible') + investment2 = create(:budget_investment, :finished, budget: @budget, + title: 'finished') + visit admin_budget_budget_investments_path(@budget, format: :csv, + filter: :valuation_finished) + + header = page.response_headers['Content-Disposition'] + header.should match(/^attachment/) + header.should match(/filename="budget_investments.csv"$/) + + expect(page).to have_content investment2.title + expect(page).to_not have_content investment1.title + end end end