Merge branch 'master' into 1647-locale_site_customization

This commit is contained in:
Raimond Garcia
2017-07-04 12:11:07 +02:00
committed by GitHub
24 changed files with 175 additions and 82 deletions

View File

@@ -15,6 +15,11 @@ App.Forms =
toggleLink: ->
$('.js-toggle-link').unbind('click').on('click', ->
$($(this).data('toggle-selector')).toggle("down")
if $(this).data('toggle-text') isnt undefined
toggle_txt = $(this).text()
$(this).text( $(this).data('toggle-text') )
$(this).data('toggle-text', toggle_txt)
false
)
@@ -22,4 +27,4 @@ App.Forms =
App.Forms.disableEnter()
App.Forms.submitOnChange()
App.Forms.toggleLink()
false
false

View File

@@ -51,7 +51,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController
def budget_investment_params
params.require(:budget_investment)
.permit(:title, :description, :external_url, :heading_id, :administrator_id, :valuation_tag_list, valuator_ids: [])
.permit(:title, :description, :external_url, :heading_id, :administrator_id, :valuation_tag_list, :incompatible, valuator_ids: [])
end
def load_budget

View File

@@ -5,7 +5,8 @@ module Budgets
def show
authorize! :read_results, @budget
@result = load_result
@investments = load_result.investments
@heading = heading
end
private
@@ -19,4 +20,4 @@ module Budgets
end
end
end
end

View File

@@ -83,7 +83,12 @@ class Legislation::ProcessesController < Legislation::BaseController
private
def member_method?
params[:id].present?
end
def set_process
return if member_method?
@process = ::Legislation::Process.find(params[:process_id])
end
end

View File

@@ -50,7 +50,9 @@ class Budget
scope :undecided, -> { where(feasibility: "undecided") }
scope :with_supports, -> { where('cached_votes_up > 0') }
scope :selected, -> { feasible.where(selected: true) }
scope :winners, -> { selected.where(winner: true) }
scope :compatible, -> { where(incompatible: false) }
scope :incompatible, -> { where(incompatible: true) }
scope :winners, -> { selected.compatible.where(winner: true) }
scope :unselected, -> { not_unfeasible.where(selected: false) }
scope :last_week, -> { where("created_at >= ?", 7.days.ago)}
@@ -63,6 +65,7 @@ class Budget
scope :for_render, -> { includes(:heading) }
before_save :calculate_confidence_score
after_save :recalculate_heading_winners if :incompatible_changed?
before_validation :set_responsible_name
before_validation :set_denormalized_ids
@@ -200,6 +203,10 @@ class Budget
self.confidence_score = ScoreCalculator.confidence_score(total_votes, total_votes)
end
def recalculate_heading_winners
Budget::Result.new(budget, heading).calculate_winners if incompatible_changed? && winner? && incompatible?
end
def set_responsible_name
self.responsible_name = author.try(:document_number) if author.try(:document_number).present?
end

View File

@@ -10,7 +10,7 @@ class Budget
def calculate_winners
reset_winners
investments.each do |investment|
investments.compatible.each do |investment|
@current_investment = investment
set_winner if inside_budget?
end

View File

@@ -12,7 +12,9 @@
<th><%= t("admin.budget_investments.index.table_feasibility") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_valuation_finished") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_selection") %></th>
<th class="text-center"><%= t("admin.budget_investments.index.table_winner") %></th>
<% if params[:filter] == 'selected' %>
<th class="text-center"><%= t("admin.budget_investments.index.table_incompatible") %></th>
<% end %>
</tr>
</thead>
@@ -75,9 +77,11 @@
<% end %>
<% end %>
</td>
<td class="small text-center">
<%= investment.winner? ? t('shared.yes'): t('shared.no') %>
</td>
<% if params[:filter] == 'selected' %>
<td class="small text-center">
<%= investment.incompatible? ? t('shared.yes'): t('shared.no') %>
</td>
<% end %>
</tr>
<% end %>
</table>

View File

@@ -61,9 +61,20 @@
</div>
</div>
<p class="clear">
<h2 id="incompatible"><%= t("admin.budget_investments.edit.compatibility") %></h2>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :incompatible do %>
<%= f.check_box :incompatible, title: t('admin.budget_investments.edit.compatibility'), label: false %>
<span class="checkbox"><%= t("admin.budget_investments.edit.mark_as_incompatible") %></span>
<% end %>
</div>
</div>
<div class="margin-top">
<%= f.submit(class: "button", value: t("admin.budget_investments.edit.submit_button")) %>
</p>
</div>
<% end %>
<hr>

View File

@@ -56,3 +56,8 @@
<p>
<%= link_to t("admin.budget_investments.show.new_milestone"), new_admin_budget_budget_investment_budget_investment_milestone_path(@budget, @investment) %>
</p>
<h2 id="incompatible"><%= t("admin.budget_investments.show.compatibility.title") %></h2>
<p id="incompatible">
<%= t("admin.budget_investments.show.compatibility.#{@investment.incompatible?}") %>
</p>

View File

@@ -1,14 +1,10 @@
<div class="small-12 medium-9 column" id="results-container">
<div class="small-12 medium-9 column <%= results_type == :compatible ? 'success' : 'js-discarded' %>" id="<%= results_type %>-container">
<h3 class="inline-block">
<%= heading.name %>
<%= title %>
</h3>
<%= link_to t("budgets.results.show_all_link"), "#",
class: "js-toggle-link button hollow margin-bottom float-right",
data: {'toggle-selector' => '.js-discarded',
'toggle-text' => t("budgets.results.hide_discarded_link")} %>
<table id="budget-investments-results" class="table-for-mobile">
<table id="budget-investments-<%= results_type %>" class="table-for-mobile">
<thead>
<tr>
<th scope="col">
@@ -20,23 +16,19 @@
<th scope="col" class="text-center">
<%= t("budgets.results.price") %>
</th>
<th scope="col" class="text-right">
<%= format_price(heading.price) %><br>
<small><%= t("budgets.results.amount_available") %></small>
</th>
<% if results_type == :compatible %>
<th scope="col" class="text-right">
<%= format_price(heading_price) %><br>
<small><%= t("budgets.results.amount_available") %></small>
</th>
<% end %>
</tr>
</thead>
<tbody>
<% amount_available = heading.price %>
<% @result.investments.each do |investment| %>
<% if investment.winner? %>
<tr id="<%= dom_id(investment) %>"
class="spending_proposal success">
<% else %>
<tr id="<%= dom_id(investment) %>"
class="spending_proposal js-discarded" style="display:none">
<% end %>
<% amount_available = heading_price %>
<% investments.each do |investment| %>
<tr id="<%= dom_id(investment) %>" class="budget-investments <%= investment.winner? ? 'success' : 'js-discarded' %>">
<td>
<% if investment.winner? %>
<span class="icon-check">
@@ -51,8 +43,7 @@
</span>
</span>
<% end %>
<%= link_to investment.title,
budget_investment_path(@budget, investment) %>
<%= link_to investment.title, budget_investment_path(@budget, investment) %>
</td>
<td class="text-center">
<%= investment.ballot_lines_count %>
@@ -60,11 +51,13 @@
<td class="text-center">
<%= format_price investment.price %>
</td>
<td class="small text-right"
title="<%= format_price(amount_available) %> - <%= format_price(investment.price) %>">
<%= format_price amount_available - investment.price %>
<% amount_available -= investment.price if investment.winner? %>
</td>
<% if results_type == :compatible %>
<td class="small text-right"
title="<%= format_price(amount_available) %> - <%= format_price(investment.price) %>">
<%= format_price amount_available - investment.price %>
<% amount_available -= investment.price if investment.winner? %>
</td>
<% end %>
</tr>
<% end %>
</tbody>

View File

@@ -1,6 +1,6 @@
<% provide :title, t("budgets.results.page_title", budget: @budget.name) %>
<% content_for :canonical do %>
<%= render "shared/canonical", href: budget_results_url(@budget, heading_id: @result.heading) %>
<%= render "shared/canonical", href: budget_results_url(@budget, heading_id: @heading) %>
<% end %>
<div class="expanded budget no-margin-top">
@@ -34,5 +34,16 @@
</ul>
</div>
<%= render 'results_table', heading: @result.heading %>
<span class="float-right"><%= link_to t("budgets.results.hide_discarded_link"), "#", class: "js-toggle-link button hollow margin-bottom", data: {'toggle-selector' => '.js-discarded', 'toggle-text' => t("budgets.results.show_all_link")} %></span>
<%= render 'results_table', results_type: :compatible,
title: @heading.name,
heading_price: @heading.price,
investments: @investments.compatible %>
<%= render 'results_table', results_type: :incompatible,
title: t("budgets.results.incompatibles"),
heading_price: @heading.price,
investments: @investments.incompatible %>
</div>

View File

@@ -120,6 +120,7 @@ en:
valuation_finished: Valuation finished
valuation_finished_feasible: Val. fin. Feasible
selected: Selected
winners: Winners
all: All
title: Investment projects
assigned_admin: Assigned administrator
@@ -140,7 +141,7 @@ en:
table_feasibility: "Feasibility"
table_valuation_finished: "Val. Fin."
table_selection: "Selection"
table_winner: "Winner"
table_incompatible: "Incompatible"
show:
assigned_admin: Assigned administrator
assigned_valuators: Assigned valuators
@@ -158,8 +159,14 @@ en:
undefined: Undefined
milestone: Milestone
new_milestone: Create new milestone
compatibility:
title: Compatibility
"true": Incompatible
"false": Compatible
edit:
classification: Clasification
compatibility: Compatibility
mark_as_incompatible: Mark this investement project as incompatible
assigned_valuators: Valuators
select_heading: Select heading
submit_button: Update

View File

@@ -120,6 +120,7 @@ es:
valuation_finished: Evaluación finalizada
valuation_finished_feasible: Viables
selected: Seleccionadas
winners: Ganadoras
all: Todas
title: Propuestas de inversión
assigned_admin: Administrador asignado
@@ -140,7 +141,7 @@ es:
table_feasibility: "Viabilidad"
table_valuation_finished: "Ev. Fin."
table_selection: "Selección"
table_winner: "Ganadora"
table_incompatible: "Incompatible"
show:
assigned_admin: Administrador asignado
assigned_valuators: Evaluadores asignados
@@ -158,8 +159,14 @@ es:
undefined: Sin definir
milestone: Seguimiento
new_milestone: Crear nuevo hito
compatibility:
title: Compatibilidad
"true": Incompatible
"false": Compatible
edit:
classification: Clasificación
compatibility: Compatibilidad
mark_as_incompatible: Marcar esta propuesta de inversión como incompatible
assigned_valuators: Evaluadores
select_heading: Seleccionar partida
submit_button: Actualizar

View File

@@ -140,7 +140,7 @@ fr:
table_feasibility: "Faisabilité"
table_valuation_finished: "Ev. Ter."
table_selection: "Sélection"
table_winner: "Winner"
table_incompatible: "Incompatible"
show:
assigned_admin: Administrateur assigné
assigned_valuators: Évaluateur assigné

View File

@@ -140,7 +140,7 @@ nl:
table_feasibility: "Feasibility"
table_valuation_finished: "Val. Fin."
table_selection: "Selection"
table_winner: "Winner"
table_incompatible: "Incompatible"
show:
assigned_admin: Assigned administrator
assigned_valuators: Assigned valuators

View File

@@ -136,3 +136,4 @@ en:
amount_available: Available budget
accepted: "Accepted spending proposal: "
discarded: "Discarded spending proposal: "
incompatibles: Incompatibles

View File

@@ -136,3 +136,5 @@ es:
amount_available: Presupuesto disponible
accepted: "Propuesta de inversión aceptada: "
discarded: "Propuesta de inversión descartada: "
incompatibles: Incompatibles

View File

@@ -210,7 +210,6 @@ Rails.application.routes.draw do
end
end
resources :signature_sheets, only: [:index, :new, :create, :show]
resources :banners, only: [:index, :new, :create, :edit, :update, :destroy] do

View File

@@ -0,0 +1,5 @@
class AddIncompatibleToBudgetInvestments < ActiveRecord::Migration
def change
add_column :budget_investments, :incompatible, :bool, default: false, index: true
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170702105956) do
ActiveRecord::Schema.define(version: 20170703120055) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -95,8 +95,9 @@ ActiveRecord::Schema.define(version: 20170702105956) do
create_table "budget_ballots", force: :cascade do |t|
t.integer "user_id"
t.integer "budget_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "ballot_lines_count", default: 0
end
create_table "budget_groups", force: :cascade do |t|
@@ -108,8 +109,8 @@ ActiveRecord::Schema.define(version: 20170702105956) do
create_table "budget_headings", force: :cascade do |t|
t.integer "group_id"
t.string "name", limit: 50
t.integer "price", limit: 8
t.string "name", limit: 50
t.integer "price", limit: 8
t.integer "population"
end
@@ -157,6 +158,7 @@ ActiveRecord::Schema.define(version: 20170702105956) do
t.integer "ballot_lines_count", default: 0
t.integer "previous_heading_id"
t.boolean "winner", default: false
t.boolean "incompatible", default: false
end
add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree

View File

@@ -266,6 +266,7 @@ FactoryGirl.define do
unfeasibility_explanation ''
external_url 'http://external_documention.org'
terms_of_service '1'
incompatible false
trait :with_confidence_score do
before(:save) { |i| i.calculate_confidence_score }
@@ -300,6 +301,11 @@ FactoryGirl.define do
winner true
end
trait :incompatible do
selected
incompatible true
end
trait :unselected do
selected false
feasibility "feasible"

View File

@@ -311,7 +311,7 @@ feature 'Admin budget investments' do
context "Edit" do
scenario "Change title, description or heading" do
scenario "Change title, incompatible, description or heading" do
budget_investment = create(:budget_investment)
create(:budget_heading, group: budget_investment.group, name: "Barbate")
@@ -321,12 +321,14 @@ feature 'Admin budget investments' do
fill_in 'budget_investment_title', with: 'Potatoes'
fill_in 'budget_investment_description', with: 'Carrots'
select "#{budget_investment.group.name}: Barbate", from: 'budget_investment[heading_id]'
check "budget_investment_incompatible"
click_button 'Update'
expect(page).to have_content 'Potatoes'
expect(page).to have_content 'Carrots'
expect(page).to have_content 'Barbate'
expect(page).to have_content 'Incompatible'
end
scenario "Add administrator" do

View File

@@ -8,8 +8,8 @@ feature 'Results' do
let!(:investment1) { create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 900) }
let!(:investment2) { create(:budget_investment, :selected, heading: heading, price: 300, ballot_lines_count: 800) }
let!(:investment3) { create(:budget_investment, :selected, heading: heading, price: 500, ballot_lines_count: 700) }
let!(:investment4) { create(:budget_investment, :selected, heading: heading, price: 100, ballot_lines_count: 600) }
let!(:investment3) { create(:budget_investment, :incompatible, heading: heading, price: 500, ballot_lines_count: 700) }
let!(:investment4) { create(:budget_investment, :selected, heading: heading, price: 600, ballot_lines_count: 600) }
let!(:results) { Budget::Result.new(budget, heading).calculate_winners }
@@ -17,31 +17,32 @@ feature 'Results' do
visit budget_path(budget)
click_link "See results"
within("#budget-investments-results") do
within("#budget-investments-compatible") do
expect(page).to have_content investment1.title
expect(page).to have_content investment2.title
expect(page).to have_content investment3.title
expect(page).to_not have_content investment4.title
expect(page).to have_content investment4.title
expect(investment1.title).to appear_before(investment2.title)
expect(investment2.title).to appear_before(investment3.title)
expect(investment2.title).to appear_before(investment4.title)
end
within("#budget-investments-incompatible") do
expect(page).to have_content investment3.title
end
end
scenario "Displays non winner investments", :js do
visit budget_path(budget)
click_link "See results"
click_link "Show all"
click_link "Hide discarded"
within("#budget-investments-results") do
within("#budget-investments-compatible") do
expect(page).to have_content investment1.title
expect(page).to have_content investment2.title
expect(page).to have_content investment3.title
expect(page).to have_content investment4.title
expect(page).not_to have_content investment3.title
expect(page).not_to have_content investment4.title
expect(investment1.title).to appear_before(investment2.title)
expect(investment2.title).to appear_before(investment3.title)
expect(investment3.title).to appear_before(investment4.title)
end
end

View File

@@ -7,29 +7,48 @@ describe Budget::Result do
let(:group) { create(:budget_group, budget: budget) }
let(:heading) { create(:budget_heading, group: group, price: 1000) }
it "calculates a budget's winner investments" do
investment1 = create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 900)
investment2 = create(:budget_investment, :selected, heading: heading, price: 300, ballot_lines_count: 800)
investment3 = create(:budget_investment, :selected, heading: heading, price: 500, ballot_lines_count: 700)
investment4 = create(:budget_investment, :selected, heading: heading, price: 100, ballot_lines_count: 600)
context "When there is no winners" do
it "calculates the correct winner set" do
investment1 = create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 900, winner: false)
investment2 = create(:budget_investment, :selected, heading: heading, price: 300, ballot_lines_count: 800, winner: false)
investment3 = create(:budget_investment, :incompatible, heading: heading, price: 500, ballot_lines_count: 700, winner: false)
investment4 = create(:budget_investment, :selected, heading: heading, price: 500, ballot_lines_count: 600, winner: false)
investment5 = create(:budget_investment, :selected, heading: heading, price: 100, ballot_lines_count: 500, winner: false)
result = Budget::Result.new(budget, heading)
result.calculate_winners
Budget::Result.new(budget, heading).calculate_winners
expect(result.winners).to eq([investment1, investment2, investment3])
expect(heading.investments.winners.pluck(:id)).to match_array([investment1.id, investment2.id, investment4.id])
end
end
it "resets winners before recalculating" do
investment1 = create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 900, winner: true)
investment2 = create(:budget_investment, :selected, heading: heading, price: 300, ballot_lines_count: 800, winner: true)
investment3 = create(:budget_investment, :selected, heading: heading, price: 500, ballot_lines_count: 700, winner: true)
investment4 = create(:budget_investment, :selected, heading: heading, price: 100, ballot_lines_count: 600, winner: true)
context "When there are winners" do
it "removes winners and recalculates" do
investment1 = create(:budget_investment, :winner, heading: heading, price: 200, ballot_lines_count: 900)
investment2 = create(:budget_investment, :winner, heading: heading, price: 300, ballot_lines_count: 800)
investment3 = create(:budget_investment, :incompatible, heading: heading, price: 500, ballot_lines_count: 700, winner: true)
investment4 = create(:budget_investment, :winner, heading: heading, price: 500, ballot_lines_count: 600)
investment5 = create(:budget_investment, :winner, heading: heading, price: 100, ballot_lines_count: 500)
result = Budget::Result.new(budget, heading)
result.calculate_winners
Budget::Result.new(budget, heading).calculate_winners
expect(result.winners).to eq([investment1, investment2, investment3])
expect(heading.investments.winners.pluck(:id)).to match_array([investment1.id, investment2.id, investment4.id])
end
end
context "When a winner is flagged as incompatible" do
it "recalculates winners leaving it out" do
investment1 = create(:budget_investment, :winner, heading: heading, price: 200, ballot_lines_count: 900)
investment2 = create(:budget_investment, :winner, heading: heading, price: 300, ballot_lines_count: 800)
investment3 = create(:budget_investment, :winner, heading: heading, price: 500, ballot_lines_count: 700)
investment4 = create(:budget_investment, :winner, heading: heading, price: 500, ballot_lines_count: 600)
investment5 = create(:budget_investment, :winner, heading: heading, price: 100, ballot_lines_count: 500)
investment3.incompatible = true
investment3.save
expect(heading.investments.winners.pluck(:id)).to match_array([investment1.id, investment2.id, investment4.id])
end
end
end
end
end