- <%= f.number_field :price,
- label: t("valuation.budget_investments.edit.price", currency: budget.currency_symbol),
- max: 1000000000000000 %>
+ <% if budget.show_money? %>
+
+ <% else %>
+ <%= f.hidden_field :price, value: 0 %>
+ <% end %>
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index 973455a05..d02d6499c 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -160,6 +160,7 @@ en:
voting_style: "Final voting style"
voting_style_knapsack: "Knapsack"
voting_style_approval: "Approval"
+ hide_money: "Hide money amount for this budget"
budget/translation:
main_link_text: "Text on the link"
main_link_url: "The link takes you to (add a link)"
diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml
index a740a897a..e26670d17 100644
--- a/config/locales/en/admin.yml
+++ b/config/locales/en/admin.yml
@@ -136,6 +136,8 @@ en:
info:
budget_settings: "General participatory budget settings"
staff_settings: "Administrators and Valuators assigned to the budget"
+ hide_money: "Hide money"
+ hide_money_help_text: "If this option is checked, all fields showing the amount of money will be hidden throughout the process."
destroy:
success_notice: Budget deleted successfully
unable_notice: You cannot delete a budget that has associated investments
diff --git a/config/locales/en/budgets.yml b/config/locales/en/budgets.yml
index 99a49af9a..1e3c6b41a 100644
--- a/config/locales/en/budgets.yml
+++ b/config/locales/en/budgets.yml
@@ -75,6 +75,7 @@ en:
form:
title: "Create a budget investment"
subtitle: "%{heading} (%{price})"
+ subtitle_without_price: "%{heading}"
tag_category_label: "Categories"
tags_instructions: "Tag this proposal. You can choose from proposed categories or add your own"
tags_label: Tags
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index 82c682edf..b7cf2fc07 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -160,6 +160,7 @@ es:
voting_style: "Estilo de la votación final"
voting_style_knapsack: Bolsa de dinero
voting_style_approval: Por aprobación
+ hide_money: "Ocultar la cantidad de dinero para este presupuesto"
budget/translation:
main_link_text: "Texto del enlace"
main_link_url: "El enlace te lleva a (añade un enlace)"
diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml
index 9ff38ec50..fd7a0d28c 100644
--- a/config/locales/es/admin.yml
+++ b/config/locales/es/admin.yml
@@ -136,6 +136,8 @@ es:
info:
budget_settings: "Configuración genérica del presupuesto participativo"
staff_settings: "Administradores y Evaluadores asigandos al presupuesto"
+ hide_money: "Ocultar dinero"
+ hide_money_help_text: "Si esta opción está marcada, todos los campos que muestran la cantidad de dinero se ocultarán durante todo el proceso."
destroy:
success_notice: Presupuesto eliminado correctamente
unable_notice: No se puede eliminar un presupuesto con proyectos asociados
diff --git a/config/locales/es/budgets.yml b/config/locales/es/budgets.yml
index 1fea405b4..5cf78e3d4 100644
--- a/config/locales/es/budgets.yml
+++ b/config/locales/es/budgets.yml
@@ -75,6 +75,7 @@ es:
form:
title: "Crear nuevo proyecto"
subtitle: "%{heading} (%{price})"
+ subtitle_without_price: "%{heading}"
tag_category_label: "Categorías"
tags_instructions: "Etiqueta este proyecto. Puedes elegir entre las categorías propuestas o introducir las que desees"
tags_label: Etiquetas
diff --git a/db/migrate/20210311110036_add_hide_money_to_budgets.rb b/db/migrate/20210311110036_add_hide_money_to_budgets.rb
new file mode 100644
index 000000000..636c70d4a
--- /dev/null
+++ b/db/migrate/20210311110036_add_hide_money_to_budgets.rb
@@ -0,0 +1,5 @@
+class AddHideMoneyToBudgets < ActiveRecord::Migration[5.1]
+ def change
+ add_column :budgets, :hide_money, :boolean, default: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 050cb482f..9b9355562 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -394,6 +394,7 @@ ActiveRecord::Schema.define(version: 2021_11_03_112944) do
t.text "description_informing"
t.string "voting_style", default: "knapsack"
t.boolean "published"
+ t.boolean "hide_money", default: false
end
create_table "campaigns", id: :serial, force: :cascade do |t|
diff --git a/spec/factories/budgets.rb b/spec/factories/budgets.rb
index 81f2089ec..59ae4b977 100644
--- a/spec/factories/budgets.rb
+++ b/spec/factories/budgets.rb
@@ -68,6 +68,10 @@ FactoryBot.define do
trait :with_winner do
after(:create) { |budget| create(:budget_investment, :winner, budget: budget) }
end
+
+ trait :hide_money do
+ hide_money { true }
+ end
end
factory :budget_group, class: "Budget::Group" do
diff --git a/spec/models/budget/heading_spec.rb b/spec/models/budget/heading_spec.rb
index a5cc098b4..185b88084 100644
--- a/spec/models/budget/heading_spec.rb
+++ b/spec/models/budget/heading_spec.rb
@@ -333,6 +333,12 @@ describe Budget::Heading do
end
end
+ describe "price" do
+ it "can't be blank" do
+ expect(build(:budget_heading, group: group, price: nil)).not_to be_valid
+ end
+ end
+
describe "#name_scoped_by_group" do
it "returns heading name in budgets with a single heading" do
heading = create(:budget_heading, group: group, name: "One and only")
diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb
index 854bb1d9c..fa8bb73f8 100644
--- a/spec/models/budget/investment_spec.rb
+++ b/spec/models/budget/investment_spec.rb
@@ -245,6 +245,12 @@ describe Budget::Investment do
expect(investment.should_show_price?).to eq(false)
end
+
+ it "returns false if budget hide money is active" do
+ budget.update!(hide_money: true)
+
+ expect(investment.should_show_price?).to eq(false)
+ end
end
describe "#should_show_price_explanation?" do
diff --git a/spec/models/budget_spec.rb b/spec/models/budget_spec.rb
index f6d9818d5..79415f512 100644
--- a/spec/models/budget_spec.rb
+++ b/spec/models/budget_spec.rb
@@ -287,6 +287,16 @@ describe Budget do
expect(budget.investments_orders).to eq(["random", "price"])
end
+ it "is random when ballotting and reviewing ballots if hide money" do
+ budget.update!(voting_style: "approval", hide_money: true)
+ budget.phase = "publishing_prices"
+ expect(budget.investments_orders).to eq(["random"])
+ budget.phase = "balloting"
+ expect(budget.investments_orders).to eq(["random"])
+ budget.phase = "reviewing_ballots"
+ expect(budget.investments_orders).to eq(["random"])
+ end
+
it "is random and confidence_score in all other cases" do
budget.phase = "selecting"
expect(budget.investments_orders).to eq(["random", "confidence_score"])
diff --git a/spec/system/admin/budget_headings_spec.rb b/spec/system/admin/budget_headings_spec.rb
index 9adff8ed1..f6076f574 100644
--- a/spec/system/admin/budget_headings_spec.rb
+++ b/spec/system/admin/budget_headings_spec.rb
@@ -123,6 +123,19 @@ describe "Admin budget headings", :admin do
expect(page).to have_content "can't be blank"
end
+ scenario "Heading money field is hidden if hide money is true" do
+ budget_hide_money = create(:budget, :hide_money)
+ group = create(:budget_group, budget: budget_hide_money)
+
+ visit new_admin_budget_group_heading_path(budget_hide_money, group)
+
+ fill_in "Heading name", with: "Heading without money"
+ click_button "Create new heading"
+
+ expect(page).to have_content "Heading created successfully!"
+ expect(page).not_to have_content "Money amount"
+ end
+
describe "Max votes is optional" do
scenario "do no show max_ballot_lines field for knapsack budgets" do
visit new_admin_budget_group_heading_path(budget, group)
diff --git a/spec/system/admin/budget_investments_spec.rb b/spec/system/admin/budget_investments_spec.rb
index 333ea691d..fd0d8779e 100644
--- a/spec/system/admin/budget_investments_spec.rb
+++ b/spec/system/admin/budget_investments_spec.rb
@@ -30,6 +30,19 @@ describe "Admin budget investments", :admin do
expect(page).to have_content(budget_investment.total_votes)
end
+ scenario "Do not show price column on budgets with hide money" do
+ budget_hide_money = create(:budget, :hide_money)
+ budget_investment = create(:budget_investment, budget: budget_hide_money)
+
+ visit admin_budget_budget_investments_path(budget_hide_money)
+
+ expect(page).to have_content(budget_investment.title)
+ expect(page).to have_content(budget_investment.heading.name)
+ expect(page).to have_content(budget_investment.id)
+ expect(page).not_to have_content("Price")
+ expect(page).not_to have_content("€")
+ end
+
scenario "If budget is finished do not show 'Selected' button" do
finished_budget = create(:budget, :finished)
budget_investment = create(:budget_investment, budget: finished_budget, cached_votes_up: 77)
diff --git a/spec/system/admin/budgets_spec.rb b/spec/system/admin/budgets_spec.rb
index db39f419f..207d40a0e 100644
--- a/spec/system/admin/budgets_spec.rb
+++ b/spec/system/admin/budgets_spec.rb
@@ -94,6 +94,78 @@ describe "Admin budgets", :admin do
end
end
+ context "Create" do
+ scenario "Create budget - Approval voting with hide money" do
+ visit admin_budgets_path
+ click_button "Create new budget"
+ click_link "Create multiple headings budget"
+
+ expect(page).to have_select("Final voting style", selected: "Knapsack")
+ expect(page).not_to have_selector("#budget_hide_money")
+
+ fill_in "Name", with: "Budget hide money"
+ select "Approval", from: "Final voting style"
+ check "Hide money amount for this budget"
+ click_button "Continue to groups"
+
+ expect(page).to have_content "New participatory budget created successfully!"
+ expect(page).to have_content "Budget hide money"
+
+ click_link "Go back to edit budget"
+
+ expect(page).to have_select("Final voting style", selected: "Approval")
+ expect(page).to have_field "Hide money amount for this budget", checked: true
+ end
+
+ scenario "Create a budget with hide money by steps" do
+ visit admin_budgets_path
+ click_button "Create new budget"
+ click_link "Create multiple headings budget"
+
+ fill_in "Name", with: "Multiple headings budget with hide money"
+ select "Approval", from: "Final voting style"
+ check "Hide money amount for this budget"
+ click_button "Continue to groups"
+
+ expect(page).to have_content "New participatory budget created successfully!"
+ expect(page).to have_content "There are no groups."
+
+ click_button "Add new group"
+ fill_in "Group name", with: "All city"
+ click_button "Create new group"
+
+ expect(page).to have_content "Group created successfully!"
+
+ click_button "Add new group"
+ fill_in "Group name", with: "District A"
+ click_button "Create new group"
+
+ expect(page).to have_content "Group created successfully!"
+
+ within("table") do
+ expect(page).to have_content "All city"
+ expect(page).to have_content "District A"
+ end
+ expect(page).not_to have_content "There are no groups."
+
+ click_link "Continue to headings"
+
+ expect(page).to have_content "Showing headings from the All city group."
+ expect(page).to have_link "Manage headings from the District A group."
+
+ click_button "Add new heading"
+ fill_in "Heading name", with: "All city"
+ click_button "Create new heading"
+
+ expect(page).to have_content "Heading created successfully!"
+ expect(page).to have_content "All city"
+ expect(page).to have_link "Continue to phases"
+ expect(page).not_to have_content "There are no headings."
+ expect(page).not_to have_content "Money amount"
+ expect(page).not_to have_content "€"
+ end
+ end
+
context "Publish" do
let(:budget) { create(:budget, :drafting) }
@@ -260,6 +332,78 @@ describe "Admin budgets", :admin do
expect(page).to have_content "New English Name"
end
+
+ scenario "Hide money active" do
+ budget_hide_money = create(:budget, :approval, :hide_money)
+ group = create(:budget_group, budget: budget_hide_money)
+ heading = create(:budget_heading, group: group)
+ heading_2 = create(:budget_heading, group: group)
+
+ visit admin_budget_path(budget_hide_money)
+
+ expect(page).to have_content heading.name
+ expect(page).to have_content heading_2.name
+ expect(page).not_to have_content "Money amount"
+ expect(page).not_to have_content "€"
+
+ visit edit_admin_budget_path(budget_hide_money)
+
+ expect(page).to have_field "Hide money amount for this budget", checked: true
+ expect(page).to have_select("Final voting style", selected: "Approval")
+ end
+
+ scenario "Change voting style uncheck hide money" do
+ budget_hide_money = create(:budget, :approval, :hide_money)
+ hide_money_help_text = "If this option is checked, all fields showing the amount of money "\
+ "will be hidden throughout the process."
+
+ visit edit_admin_budget_path(budget_hide_money)
+
+ expect(page).to have_field "Hide money amount for this budget", checked: true
+ expect(page).to have_content hide_money_help_text
+
+ select "Knapsack", from: "Final voting style"
+
+ expect(page).not_to have_field "Hide money amount for this budget"
+ expect(page).not_to have_content hide_money_help_text
+
+ select "Approval", from: "Final voting style"
+
+ expect(page).to have_field "Hide money amount for this budget", checked: false
+ expect(page).to have_content hide_money_help_text
+ end
+
+ scenario "Edit knapsack budget do not show hide money info" do
+ budget = create(:budget, :knapsack)
+ hide_money_help_text = "If this option is checked, all fields showing the amount of money "\
+ "will be hidden throughout the process."
+
+ visit edit_admin_budget_path(budget)
+
+ expect(page).not_to have_field "Hide money amount for this budget"
+ expect(page).not_to have_content hide_money_help_text
+
+ select "Approval", from: "Final voting style"
+
+ expect(page).to have_field "Hide money amount for this budget", checked: false
+ expect(page).to have_content hide_money_help_text
+ end
+
+ scenario "Edit approval budget show hide money info" do
+ budget = create(:budget, :approval)
+ hide_money_help_text = "If this option is checked, all fields showing the amount of money "\
+ "will be hidden throughout the process."
+
+ visit edit_admin_budget_path(budget)
+
+ expect(page).to have_field "Hide money amount for this budget", checked: false
+ expect(page).to have_content hide_money_help_text
+
+ select "Knapsack", from: "Final voting style"
+
+ expect(page).not_to have_field "Hide money amount for this budget"
+ expect(page).not_to have_content hide_money_help_text
+ end
end
context "Update" do
diff --git a/spec/system/budgets/ballots_spec.rb b/spec/system/budgets/ballots_spec.rb
index f824ef956..872ced135 100644
--- a/spec/system/budgets/ballots_spec.rb
+++ b/spec/system/budgets/ballots_spec.rb
@@ -659,4 +659,33 @@ describe "Ballots" do
end
end
end
+
+ context "Hide money" do
+ scenario "Do not show prices on sidebar or ballot show" do
+ budget_hide_money = create(:budget, :balloting, :approval, :hide_money)
+ group_no_price = create(:budget_group, budget: budget_hide_money)
+ heading_no_price = create(:budget_heading, group: group_no_price, max_ballot_lines: 2)
+ investment_1 = create(:budget_investment, :selected, heading: heading_no_price, price: 3000)
+ investment_2 = create(:budget_investment, :selected, heading: heading_no_price, price: 4000)
+ user = create(:user, :level_two, ballot_lines: [investment_1, investment_2])
+
+ login_as(user)
+ visit budget_investments_path(budget_hide_money, heading_id: heading_no_price.id)
+
+ within("#sidebar") do
+ expect(page).to have_content investment_1.title
+ expect(page).to have_content investment_2.title
+ expect(page).not_to have_content investment_1.price
+ expect(page).not_to have_content investment_2.price
+ expect(page).not_to have_content "€"
+ click_link "Submit my ballot"
+ end
+
+ expect(page).to have_content investment_1.title
+ expect(page).to have_content investment_2.title
+ expect(page).not_to have_content investment_1.price
+ expect(page).not_to have_content investment_2.price
+ expect(page).not_to have_content "€"
+ end
+ end
end
diff --git a/spec/system/budgets/budgets_spec.rb b/spec/system/budgets/budgets_spec.rb
index 3e49b59c9..b0a8ce7f9 100644
--- a/spec/system/budgets/budgets_spec.rb
+++ b/spec/system/budgets/budgets_spec.rb
@@ -119,6 +119,34 @@ describe "Budgets" do
end
end
+ scenario "Hide money on single heading budget" do
+ budget = create(:budget, :finished, :hide_money)
+ heading = create(:budget_heading, budget: budget)
+
+ visit budgets_path
+
+ within("#budget_info") do
+ expect(page).to have_content heading.name
+ expect(page).not_to have_content "€"
+ end
+ end
+
+ scenario "Hide money on multiple headings budget" do
+ budget = create(:budget, :finished, :hide_money)
+ heading1 = create(:budget_heading, budget: budget)
+ heading2 = create(:budget_heading, budget: budget)
+ heading3 = create(:budget_heading, budget: budget)
+
+ visit budgets_path
+
+ within("#budget_info") do
+ expect(page).to have_content heading1.name
+ expect(page).to have_content heading2.name
+ expect(page).to have_content heading3.name
+ expect(page).not_to have_content "€"
+ end
+ end
+
scenario "No budgets" do
Budget.destroy_all
diff --git a/spec/system/budgets/investments_spec.rb b/spec/system/budgets/investments_spec.rb
index a48bbb1f2..0dec3fd34 100644
--- a/spec/system/budgets/investments_spec.rb
+++ b/spec/system/budgets/investments_spec.rb
@@ -598,6 +598,19 @@ describe "Budget Investments" do
expect(page).to have_content "Build a skyscraper"
end
+ scenario "Create with single heading and hidden money" do
+ budget_hide_money = create(:budget, :hide_money)
+ group = create(:budget_group, budget: budget_hide_money)
+ create(:budget_heading, name: "Heading without money", group: group)
+
+ login_as(author)
+
+ visit new_budget_investment_path(budget_hide_money)
+
+ expect(page).to have_content "Heading without money"
+ expect(page).not_to have_content "€"
+ end
+
scenario "Create with single group and multiple headings" do
create(:budget_heading, group: group, name: "Medical supplies")
create(:budget_heading, group: group, name: "Even more hospitals")
diff --git a/spec/system/budgets/results_spec.rb b/spec/system/budgets/results_spec.rb
index 41d84fbf1..7c6b5f1c1 100644
--- a/spec/system/budgets/results_spec.rb
+++ b/spec/system/budgets/results_spec.rb
@@ -67,6 +67,41 @@ describe "Results" do
end
end
+ scenario "Does not show price and available budget when hide money" do
+ budget.update!(voting_style: "approval", hide_money: true)
+ visit budget_path(budget)
+ click_link "See results"
+
+ expect(page).to have_content investment1.title
+ expect(page).to have_content investment2.title
+ expect(page).not_to have_content investment1.price
+ expect(page).not_to have_content investment2.price
+ expect(page).not_to have_content "Price"
+ expect(page).not_to have_content "Available budget"
+ expect(page).not_to have_content "€"
+ end
+
+ scenario "Does not have in account the price on hide money budgets" do
+ budget.update!(voting_style: "approval", hide_money: true)
+ heading.update!(price: 0)
+
+ inv1 = create(:budget_investment, :selected, heading: heading, price: 2000, ballot_lines_count: 1000)
+ inv2 = create(:budget_investment, :selected, heading: heading, price: 5000, ballot_lines_count: 1000)
+
+ Budget::Result.new(budget, heading).calculate_winners
+
+ visit budget_path(budget)
+ click_link "See results"
+
+ expect(page).to have_content inv1.title
+ expect(page).to have_content inv2.title
+ expect(page).not_to have_content inv1.price
+ expect(page).not_to have_content inv2.price
+ expect(page).not_to have_content "Price"
+ expect(page).not_to have_content "Available budget"
+ expect(page).not_to have_content "€"
+ end
+
scenario "Does not raise error if budget (slug or id) is not found" do
visit budget_results_path("wrong budget")
diff --git a/spec/system/valuation/budget_investments_spec.rb b/spec/system/valuation/budget_investments_spec.rb
index 0bfc0bb51..69a5188d0 100644
--- a/spec/system/valuation/budget_investments_spec.rb
+++ b/spec/system/valuation/budget_investments_spec.rb
@@ -381,6 +381,35 @@ describe "Valuation budget investments" do
end
end
+ scenario "Dossier hide price on hide money budgets" do
+ budget = create(:budget, :valuating, :hide_money)
+ investment = create(:budget_investment, budget: budget, administrator: admin, valuators: [valuator])
+ investment.update!(visible_to_valuators: true)
+
+ visit valuation_budget_budget_investments_path(budget)
+ within("#budget_investment_#{investment.id}") do
+ click_link "Edit dossier"
+ end
+
+ expect(page).not_to have_content "Price (€)"
+ expect(page).not_to have_content "Cost during the first year (€)"
+ expect(page).not_to have_content "Price explanation"
+
+ choose "budget_investment_feasibility_feasible"
+ fill_in "budget_investment_duration", with: "12 months"
+ click_button "Save changes"
+
+ expect(page).to have_content "Dossier updated"
+
+ visit valuation_budget_budget_investments_path(budget)
+ click_link investment.title
+
+ within("#duration") { expect(page).to have_content("12 months") }
+ within("#feasibility") { expect(page).to have_content("Feasible") }
+ expect(page).not_to have_selector "#price"
+ expect(page).not_to have_selector "#price_first_year"
+ end
+
scenario "Finish valuation" do
investment.update!(visible_to_valuators: true)