Merge branch 'master' into budget-emails
This commit is contained in:
@@ -62,6 +62,10 @@ module Budgets
|
||||
def vote
|
||||
@investment.register_selection(current_user)
|
||||
load_investment_votes(@investment)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to budget_investments_path(heading_id: @investment.heading.id) }
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -34,6 +34,10 @@ class Management::Budgets::InvestmentsController < Management::BaseController
|
||||
def vote
|
||||
@investment.register_selection(managed_user)
|
||||
load_investment_votes(@investment)
|
||||
respond_to do |format|
|
||||
format.html { redirect_to management_budget_investments_path(heading_id: @investment.heading.id) }
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def print
|
||||
|
||||
@@ -155,6 +155,7 @@ class Budget
|
||||
|
||||
def reason_for_not_being_selectable_by(user)
|
||||
return permission_problem(user) if permission_problem?(user)
|
||||
return :different_heading_assigned unless valid_heading?(user)
|
||||
|
||||
return :no_selecting_allowed unless budget.selecting?
|
||||
end
|
||||
@@ -182,6 +183,24 @@ class Budget
|
||||
reason_for_not_being_selectable_by(user).blank?
|
||||
end
|
||||
|
||||
def valid_heading?(user)
|
||||
!different_heading_assigned?(user)
|
||||
end
|
||||
|
||||
def different_heading_assigned?(user)
|
||||
other_heading_ids = group.heading_ids - [heading.id]
|
||||
voted_in?(other_heading_ids, user)
|
||||
end
|
||||
|
||||
def voted_in?(heading_ids, user)
|
||||
heading_ids.include? heading_voted_by_user?(user)
|
||||
end
|
||||
|
||||
def heading_voted_by_user?(user)
|
||||
user.votes.for_budget_investments(budget.investments.where(group: group)).
|
||||
votables.map(&:heading_id).first
|
||||
end
|
||||
|
||||
def ballotable_by?(user)
|
||||
reason_for_not_being_ballotable_by(user).blank?
|
||||
end
|
||||
@@ -204,13 +223,19 @@ class Budget
|
||||
end
|
||||
|
||||
def should_show_aside?
|
||||
(budget.selecting? && !unfeasible?) || (budget.balloting? && feasible?) || budget.on_hold?
|
||||
(budget.selecting? && !unfeasible?) ||
|
||||
(budget.balloting? && feasible?) ||
|
||||
(budget.valuating? && feasible?)
|
||||
end
|
||||
|
||||
def should_show_votes?
|
||||
budget.selecting?
|
||||
end
|
||||
|
||||
def should_show_vote_count?
|
||||
budget.valuating?
|
||||
end
|
||||
|
||||
def should_show_ballots?
|
||||
budget.balloting?
|
||||
end
|
||||
|
||||
@@ -103,6 +103,10 @@ class User < ActiveRecord::Base
|
||||
comment_flags.each_with_object({}){ |f, h| h[f.flaggable_id] = true }
|
||||
end
|
||||
|
||||
def voted_in_group?(group)
|
||||
votes.for_budget_investments(Budget::Investment.where(group: group)).exists?
|
||||
end
|
||||
|
||||
def administrator?
|
||||
administrator.present?
|
||||
end
|
||||
|
||||
11
app/views/budgets/investments/_feasibility_link.html.erb
Normal file
11
app/views/budgets/investments/_feasibility_link.html.erb
Normal file
@@ -0,0 +1,11 @@
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2 class="sidebar-title"><%= t("budgets.investments.index.sidebar.by_feasibility") %></h2>
|
||||
<br>
|
||||
|
||||
<% if params[:unfeasible].present? %>
|
||||
<%= link_to t("budgets.investments.index.sidebar.feasible"),
|
||||
budget_investments_path(@budget, heading_id: @heading, unfeasible: nil) %>
|
||||
<% else %>
|
||||
<%= link_to t("budgets.investments.index.sidebar.unfeasible"),
|
||||
budget_investments_path(@budget, heading_id: @heading, unfeasible: 1) %>
|
||||
<% end %>
|
||||
@@ -46,7 +46,6 @@
|
||||
<% unless investment.unfeasible? %>
|
||||
|
||||
<% if investment.should_show_votes? %>
|
||||
|
||||
<div id="<%= dom_id(investment) %>_votes"
|
||||
class="small-12 medium-3 column text-center">
|
||||
<%= render partial: '/budgets/investments/votes', locals: {
|
||||
@@ -55,9 +54,17 @@
|
||||
vote_url: namespaced_budget_investment_vote_path(investment, value: 'yes')
|
||||
} %>
|
||||
</div>
|
||||
|
||||
<% elsif investment.should_show_vote_count? %>
|
||||
<div id="<%= dom_id(investment) %>_votes"
|
||||
class="small-12 medium-3 column text-center">
|
||||
<div class="supports js-participation">
|
||||
<span class="total-supports no-button">
|
||||
<%= t("budgets.investments.investment.supports",
|
||||
count: investment.total_votes) %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<% elsif investment.should_show_ballots? %>
|
||||
|
||||
<div id="<%= dom_id(investment) %>_ballot"
|
||||
class="small-12 medium-3 column text-center">
|
||||
<%= render partial: '/budgets/investments/ballot', locals: {
|
||||
@@ -66,7 +73,6 @@
|
||||
ballot: ballot
|
||||
} %>
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
|
||||
<% end %>
|
||||
|
||||
@@ -55,11 +55,10 @@
|
||||
|
||||
<% if investment.should_show_aside? %>
|
||||
<aside class="small-12 medium-3 column">
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("votes.supports") %></h2>
|
||||
<div class="text-center">
|
||||
|
||||
<% if investment.should_show_votes? %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("budgets.investments.show.supports") %></h2>
|
||||
<div class="text-center">
|
||||
<div id="<%= dom_id(investment) %>_votes">
|
||||
<%= render partial: '/budgets/investments/votes', locals: {
|
||||
investment: investment,
|
||||
@@ -67,7 +66,20 @@
|
||||
vote_url: vote_budget_investment_path(investment.budget, investment, value: 'yes')
|
||||
} %>
|
||||
</div>
|
||||
<% elsif investment.should_show_ballots? %>
|
||||
</div>
|
||||
<% elsif investment.should_show_vote_count? %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("budgets.investments.show.supports") %></h2>
|
||||
<div class="text-center">
|
||||
<span class="total-supports">
|
||||
<%= t("budgets.investments.investment.supports",
|
||||
count: investment.total_votes) %>
|
||||
</span>
|
||||
</div>
|
||||
<% elsif investment.should_show_ballots? %>
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("budgets.investments.show.votes") %></h2>
|
||||
<div class="text-center">
|
||||
<div id="<%= dom_id(investment) %>_ballot">
|
||||
<%= render partial: 'ballot', locals: {
|
||||
investment: investment,
|
||||
@@ -75,8 +87,8 @@
|
||||
ballot: ballot,
|
||||
} %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="sidebar-divider"></div>
|
||||
<h2><%= t("budgets.investments.show.share") %></h2>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<% if @budget.accepting? %>
|
||||
<%= render "shared/tag_cloud", taggable: 'budget/investment' %>
|
||||
<%= render 'categories' %>
|
||||
<%= render 'feasibility_link' %>
|
||||
<% end %>
|
||||
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
<%= t("budgets.investments.investment.already_supported") %>
|
||||
</div>
|
||||
<% elsif investment.should_show_votes? %>
|
||||
|
||||
<%= link_to vote_url,
|
||||
class: "button button-support small expanded",
|
||||
title: t('budgets.investments.investment.support_title'),
|
||||
method: "post",
|
||||
remote: true,
|
||||
remote: (current_user && current_user.voted_in_group?(investment.group) ? true : false),
|
||||
data: (current_user && current_user.voted_in_group?(investment.group) ? nil : { confirm: t('budgets.investments.investment.confirm_group')} ),
|
||||
"aria-hidden" => css_for_aria_hidden(reason) do %>
|
||||
<%= t("budgets.investments.investment.give_support") %>
|
||||
<% end %>
|
||||
|
||||
@@ -64,6 +64,9 @@ en:
|
||||
not_logged_in: "To create a new budget investment you must %{sign_in} or %{sign_up}."
|
||||
sign_in: "sign in"
|
||||
sign_up: "sign up"
|
||||
by_feasibility: By feasibility
|
||||
feasible: Feasible projects
|
||||
unfeasible: Unfeasible projects
|
||||
orders:
|
||||
random: random
|
||||
confidence_score: highest rated
|
||||
@@ -77,6 +80,8 @@ en:
|
||||
organization_name_html: 'Organization: <strong>%{name}</strong>'
|
||||
share: Share
|
||||
title: Investment project
|
||||
supports: Supports
|
||||
votes: Votes
|
||||
wrong_price_format: Only integer numbers
|
||||
investment:
|
||||
title: Investment project
|
||||
@@ -84,6 +89,7 @@ en:
|
||||
already_added: You have already added this investment project
|
||||
already_supported: You have already supported this. Share it!
|
||||
support_title: Support this project
|
||||
confirm_group: "You can only support investments in one district. If you continue you cannot change your decision. Are you sure?"
|
||||
supports:
|
||||
one: 1 support
|
||||
other: "%{count} supports"
|
||||
|
||||
@@ -64,6 +64,9 @@ es:
|
||||
not_logged_in: "Para crear una nueva propuesta de inversión debes %{sign_in} o %{sign_up}."
|
||||
sign_in: "iniciar sesión"
|
||||
sign_up: "registrarte"
|
||||
by_feasibility: Por viabilidad
|
||||
feasible: Ver los proyectos viables
|
||||
unfeasible: Ver los proyectos inviables
|
||||
orders:
|
||||
random: Aleatorias
|
||||
confidence_score: Mejor valoradas
|
||||
@@ -77,6 +80,8 @@ es:
|
||||
organization_name_html: 'Organización: <strong>%{name}</strong>'
|
||||
share: Compartir
|
||||
title: Propuesta de inversión
|
||||
supports: Apoyos
|
||||
votes: Votos
|
||||
wrong_price_format: Solo puede incluir caracteres numéricos
|
||||
investment:
|
||||
title: Propuesta de inversión
|
||||
@@ -84,6 +89,7 @@ es:
|
||||
already_added: "Ya has añadido esta propuesta de inversión"
|
||||
already_supported: Ya has apoyado esta propuesta. ¡Compártelo!
|
||||
support_title: Apoyar esta propuesta
|
||||
confirm_group: "Sólo puedes apoyar propuestas en un distrito. Si sigues adelante no podrás cambiar esta decisión. ¿Estás seguro?"
|
||||
supports:
|
||||
one: 1 apoyo
|
||||
other: "%{count} apoyos"
|
||||
|
||||
@@ -595,6 +595,13 @@ en:
|
||||
organization: Organizations are not permitted to vote
|
||||
unfeasible: Unfeasible investment projects can not be supported
|
||||
not_voting_allowed: Voting phase is closed
|
||||
budget_investments:
|
||||
not_logged_in: You must %{signin} or %{signup} to continue.
|
||||
not_verified: Only verified users can vote on proposals; %{verify_account}.
|
||||
organization: Organizations are not permitted to vote
|
||||
unfeasible: Unfeasible investment projects can not be supported
|
||||
not_voting_allowed: Voting phase is closed
|
||||
different_heading_assigned: You can only support proposals in one district
|
||||
welcome:
|
||||
debates:
|
||||
description: For meeting, discussing and sharing the things that matter to us in our city.
|
||||
|
||||
@@ -595,6 +595,13 @@ es:
|
||||
organization: Las organizaciones no pueden votar.
|
||||
unfeasible: No se pueden votar propuestas inviables.
|
||||
not_voting_allowed: El periodo de votación está cerrado.
|
||||
budget_investments:
|
||||
not_logged_in: Necesitas %{signin} o %{signup} para continuar.
|
||||
not_verified: Las propuestas de inversión sólo pueden ser apoyadas por usuarios verificados, %{verify_account}.
|
||||
organization: Las organizaciones no pueden votar.
|
||||
unfeasible: No se pueden votar propuestas inviables.
|
||||
not_voting_allowed: El periodo de votación está cerrado.
|
||||
different_heading_assigned: Sólo puedes apoyar propuestas en un distrito
|
||||
welcome:
|
||||
debates:
|
||||
description: Encontrarnos, debatir y compartir lo que nos parece importante en nuestra ciudad.
|
||||
|
||||
@@ -54,6 +54,7 @@ end
|
||||
|
||||
admin = create_user('admin@consul.dev', 'admin')
|
||||
admin.create_administrator
|
||||
admin.update(residence_verified_at: Time.current, confirmed_phone: Faker::PhoneNumber.phone_number, document_type: "1", verified_at: Time.current, document_number: "1111111111")
|
||||
|
||||
moderator = create_user('mod@consul.dev', 'mod')
|
||||
moderator.create_moderator
|
||||
|
||||
@@ -23,6 +23,21 @@ feature 'Budget Investments' do
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Feasibility links' do
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
expect(page).to_not have_content('Feasible projects')
|
||||
|
||||
within('#sidebar') do
|
||||
click_link 'Unfeasible projects'
|
||||
end
|
||||
expect(page).to have_current_path(budget_investments_path(budget, heading_id: heading.id, unfeasible: 1))
|
||||
|
||||
within('#sidebar') do
|
||||
click_link 'Feasible projects'
|
||||
end
|
||||
expect(page).to have_current_path(budget_investments_path(budget, heading_id: heading.id, unfeasible: nil))
|
||||
end
|
||||
|
||||
context("Search") do
|
||||
|
||||
scenario 'Search by text' do
|
||||
@@ -288,6 +303,105 @@ feature 'Budget Investments' do
|
||||
|
||||
end
|
||||
|
||||
context "Selecting Phase" do
|
||||
|
||||
background do
|
||||
budget.update(phase: "selecting")
|
||||
end
|
||||
|
||||
context "Popup alert to vote only in one heading per group" do
|
||||
|
||||
scenario "When supporting in the first heading group", :js do
|
||||
carabanchel = create(:budget_heading, group: group)
|
||||
salamanca = create(:budget_heading, group: group)
|
||||
|
||||
carabanchel_investment = create(:budget_investment, :selected, heading: carabanchel)
|
||||
salamanca_investment = create(:budget_investment, :selected, heading: salamanca)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: carabanchel.id)
|
||||
|
||||
within("#budget_investment_#{carabanchel_investment.id}") do
|
||||
expect(page).to have_css(".in-favor a[data-confirm]")
|
||||
end
|
||||
end
|
||||
|
||||
scenario "When already supported in the group", :js do
|
||||
carabanchel = create(:budget_heading, group: group)
|
||||
salamanca = create(:budget_heading, group: group)
|
||||
|
||||
carabanchel_investment = create(:budget_investment, heading: carabanchel)
|
||||
salamanca_investment = create(:budget_investment, heading: salamanca)
|
||||
|
||||
create(:vote, votable: carabanchel_investment, voter: author)
|
||||
|
||||
login_as(author)
|
||||
visit budget_investments_path(budget, heading_id: carabanchel.id)
|
||||
|
||||
within("#budget_investment_#{carabanchel_investment.id}") do
|
||||
expect(page).to_not have_css(".in-favor a[data-confirm]")
|
||||
end
|
||||
end
|
||||
|
||||
scenario "When supporting in another group", :js do
|
||||
carabanchel = create(:budget_heading, group: group)
|
||||
another_heading = create(:budget_heading, group: create(:budget_group, budget: budget))
|
||||
|
||||
carabanchel_investment = create(:budget_investment, heading: carabanchel)
|
||||
another_group_investment = create(:budget_investment, heading: another_heading)
|
||||
|
||||
create(:vote, votable: carabanchel_investment, voter: author)
|
||||
|
||||
login_as(author)
|
||||
visit budget_investments_path(budget, heading_id: another_heading.id)
|
||||
|
||||
within("#budget_investment_#{another_group_investment.id}") do
|
||||
expect(page).to have_css(".in-favor a[data-confirm]")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Sidebar in show should display support text" do
|
||||
investment = create(:budget_investment, budget: budget)
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("aside") do
|
||||
expect(page).to have_content "Supports"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Evaluating Phase" do
|
||||
|
||||
background do
|
||||
budget.update(phase: "valuating")
|
||||
end
|
||||
|
||||
scenario "Sidebar in show should display supports text and supports" do
|
||||
investment = create(:budget_investment, :selected, budget: budget)
|
||||
create(:vote, votable: investment)
|
||||
|
||||
visit budget_investment_path(budget, investment)
|
||||
|
||||
within("aside") do
|
||||
expect(page).to have_content "Supports"
|
||||
expect(page).to have_content "1 support"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Index should display supports" do
|
||||
investment = create(:budget_investment, :selected, budget: budget, heading: heading)
|
||||
create(:vote, votable: investment)
|
||||
|
||||
visit budget_investments_path(budget, heading_id: heading.id)
|
||||
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
expect(page).to have_content "1 support"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "Balloting Phase" do
|
||||
|
||||
background do
|
||||
@@ -348,6 +462,15 @@ 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)
|
||||
|
||||
within("aside") do
|
||||
expect(page).to have_content "Votes"
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Confirm", :js do
|
||||
budget.update(phase: 'balloting')
|
||||
user = create(:user, :level_two)
|
||||
|
||||
@@ -55,7 +55,7 @@ feature 'Votes' do
|
||||
|
||||
feature 'Single spending proposal' do
|
||||
background do
|
||||
@investment = create(:budget_investment, budget: budget)
|
||||
@investment = create(:budget_investment, budget: budget, heading: heading)
|
||||
end
|
||||
|
||||
scenario 'Show no votes' do
|
||||
|
||||
@@ -140,7 +140,7 @@ feature 'Budget Investments' do
|
||||
context "Supporting" do
|
||||
|
||||
scenario 'Supporting budget investments on behalf of someone in index view', :js do
|
||||
budget_investment = create(:budget_investment, budget: @budget)
|
||||
budget_investment = create(:budget_investment, budget: @budget, heading: @heading)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
@@ -273,6 +273,18 @@ describe Budget::Investment do
|
||||
budget.phase = "selecting"
|
||||
expect(district_sp.reason_for_not_being_selectable_by(user)).to be_nil
|
||||
end
|
||||
|
||||
it "rejects votes in two headings of the same group" do
|
||||
carabanchel = create(:budget_heading, group: group)
|
||||
salamanca = create(:budget_heading, group: group)
|
||||
|
||||
carabanchel_investment = create(:budget_investment, heading: carabanchel)
|
||||
salamanca_investment = create(:budget_investment, heading: salamanca)
|
||||
|
||||
create(:vote, votable: carabanchel_investment, voter: user)
|
||||
|
||||
expect(salamanca_investment.valid_heading?(user)).to eq(false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user