Show only available budget stats phases

This way we can show statistics for the supports phase before the vote
phase is over.
This commit is contained in:
Javi Martín
2019-03-20 20:36:42 +01:00
parent bf2292ba18
commit 66ecb2835b
10 changed files with 150 additions and 50 deletions

View File

@@ -190,12 +190,10 @@ table {
tr th { tr th {
border: 1px solid $border; border: 1px solid $border;
padding-left: 0;
padding-right: 0;
text-align: center; text-align: center;
} }
.tiny { .phase-subheader {
font-size: rem-calc(11); font-size: rem-calc(11);
font-weight: normal; font-weight: normal;
} }

View File

@@ -66,7 +66,6 @@ module Abilities
can [:hide, :update, :toggle_selection], Budget::Investment can [:hide, :update, :toggle_selection], Budget::Investment
can [:valuate, :comment_valuation], Budget::Investment can [:valuate, :comment_valuation], Budget::Investment
can :create, Budget::ValuatorAssignment can :create, Budget::ValuatorAssignment
can :read_stats, Budget, phase: "reviewing_ballots"
can [:search, :edit, :update, :create, :index, :destroy], Banner can [:search, :edit, :update, :create, :index, :destroy], Banner

View File

@@ -21,7 +21,7 @@ module Abilities
can [:read], Budget::Group can [:read], Budget::Group
can [:read, :print, :json_data], Budget::Investment can [:read, :print, :json_data], Budget::Investment
can [:read_results, :read_executions], Budget, phase: "finished" can [:read_results, :read_executions], Budget, phase: "finished"
can :read_stats, Budget, phase: "finished" can(:read_stats, Budget) { |budget| budget.valuating_or_later? }
can :new, DirectMessage can :new, DirectMessage
can [:read, :debate, :draft_publication, :allegations, :result_publication, can [:read, :debate, :draft_publication, :allegations, :result_publication,
:proposals, :milestones], Legislation::Process, published: true :proposals, :milestones], Legislation::Process, published: true

View File

@@ -3,14 +3,42 @@ class Budget::Stats
alias_method :budget, :resource alias_method :budget, :resource
def self.stats_methods def self.stats_methods
super + super + support_phase_methods + vote_phase_methods
%i[total_participants_support_phase total_participants_vote_phase end
total_budget_investments total_votes total_selected_investments
total_unfeasible_investments headings] def self.support_phase_methods
%i[total_participants_support_phase total_budget_investments
total_selected_investments total_unfeasible_investments headings]
end
def self.vote_phase_methods
%i[total_votes total_participants_vote_phase]
end
def stats_methods
base_stats_methods + participation_methods + phase_methods
end
def phases
%w[support vote].select { |phase| send("#{phase}_phase_finished?") }
end
def all_phases
return phases unless phases.many?
[*phases, "every"]
end
def support_phase_finished?
budget.valuating_or_later?
end
def vote_phase_finished?
budget.finished?
end end
def participants def participants
User.where(id: (authors + voters + balloters + poll_ballot_voters).uniq.compact) User.where(id: phases.map { |phase| send("participant_ids_#{phase}_phase") }.flatten.uniq)
end end
def total_participants def total_participants
@@ -66,6 +94,18 @@ class Budget::Stats
private private
def phase_methods
phases.map { |phase| self.class.send("#{phase}_phase_methods") }.flatten
end
def participant_ids_support_phase
(authors + voters).uniq
end
def participant_ids_vote_phase
(balloters + poll_ballot_voters).uniq
end
def authors def authors
budget.investments.pluck(:author_id) budget.investments.pluck(:author_id)
end end

View File

@@ -80,11 +80,12 @@
<div id="stats_by_phase" class="stats-group"> <div id="stats_by_phase" class="stats-group">
<h4><%= t("stats.budgets.by_phase") %></h4> <h4><%= t("stats.budgets.by_phase") %></h4>
<%= number_with_info_tags(@stats.total_participants_support_phase, <% @stats.phases.each do |phase| %>
t("stats.budgets.participants_support_phase")) %> <%= number_with_info_tags(
<%= number_with_info_tags(@stats.total_participants_vote_phase, @stats.send("total_participants_#{phase}_phase"),
t("stats.budgets.participants_voting_phase")) %> t("stats.budgets.participants_#{phase}_phase")
) %>
<% end %>
</div> </div>
<div id="stats_by_heading" class="stats-group"> <div id="stats_by_heading" class="stats-group">
@@ -95,20 +96,19 @@
<tr> <tr>
<th scope="col" rowspan="2"><%= t("stats.budgets.heading") %></th> <th scope="col" rowspan="2"><%= t("stats.budgets.heading") %></th>
<th scope="col" rowspan="2"><%= t("stats.budgets.investments_sent_html") %></th> <th scope="col" rowspan="2"><%= t("stats.budgets.investments_sent_html") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_support_phase") %></th>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_voting_phase") %></th> <% @stats.all_phases.each do |phase| %>
<th scope="col" colspan="3"><%= t("stats.budgets.participants_total") %></th> <th scope="col" colspan="3">
<%= t("stats.budgets.participants_#{phase}_phase") %>
</th>
<% end %>
</tr> </tr>
<tr> <tr>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th> <% @stats.all_phases.each do %>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th> <th scope="col" class="phase-subheader"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th> <th scope="col" class="phase-subheader"><%= t("stats.budgets.percent_total_participants") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th> <th scope="col" class="phase-subheader"><%= t("stats.budgets.percent_heading_census") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th> <% end %>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.total") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_total_participants_html") %></th>
<th scope="col" class="tiny"><%= t("stats.budgets.percent_heading_census_html") %></th>
</tr> </tr>
</thead> </thead>
<tbody id="headings"> <tbody id="headings">
@@ -122,7 +122,7 @@
<%= @stats.headings[heading.id][:total_investments_count] %> <%= @stats.headings[heading.id][:total_investments_count] %>
</td> </td>
<% ["support", "vote", "every"].each do |phase| %> <% @stats.all_phases.each do |phase| %>
<td id="total_participants_<%= phase %>_phase_heading_<%= heading.id %>" <td id="total_participants_<%= phase %>_phase_heading_<%= heading.id %>"
class="border-left text-center"> class="border-left text-center">
<%= @stats.headings[heading.id]["total_participants_#{phase}_phase".to_sym] %> <%= @stats.headings[heading.id]["total_participants_#{phase}_phase".to_sym] %>

View File

@@ -194,6 +194,7 @@ ignore_unused:
- "admin.site_customization.pages.page.status_*" - "admin.site_customization.pages.page.status_*"
- "admin.legislation.processes.process.*" - "admin.legislation.processes.process.*"
- "legislation.processes.index.*" - "legislation.processes.index.*"
- "stats.budgets.participants_*_phase"
- "votes.budget_investments.different_heading_assigned*" - "votes.budget_investments.different_heading_assigned*"
- "*.form.map_skip_checkbox" - "*.form.map_skip_checkbox"
# - "{devise,kaminari,will_paginate}.*" # - "{devise,kaminari,will_paginate}.*"

View File

@@ -29,10 +29,10 @@ en:
heading: "Heading" heading: "Heading"
investments_sent_html: "Investment proposals sent" investments_sent_html: "Investment proposals sent"
participants_support_phase: "Participants support phase" participants_support_phase: "Participants support phase"
participants_voting_phase: "Participants voting phase" participants_vote_phase: "Participants voting phase"
participants_total: "Total Participants" participants_every_phase: "Total Participants"
percent_total_participants_html: "% <br>Total<br>Participants" percent_total_participants: "% Total Participants"
percent_heading_census_html: "% <br>Heading<br>Census" percent_heading_census: "% Heading Census"
participatory_disclaimer: "** The numbers of total participants refer to persons that created, supported or voted investment proposals." participatory_disclaimer: "** The numbers of total participants refer to persons that created, supported or voted investment proposals."
heading_disclaimer: "*** Data about headings refer to the heading where each user voted, not necessarily the one that person is registered on." heading_disclaimer: "*** Data about headings refer to the heading where each user voted, not necessarily the one that person is registered on."
polls: polls:

View File

@@ -29,10 +29,10 @@ es:
heading: "Distrito" heading: "Distrito"
investments_sent_html: "Propuestas<br>enviadas" investments_sent_html: "Propuestas<br>enviadas"
participants_support_phase: Participantes fase apoyos participants_support_phase: Participantes fase apoyos
participants_voting_phase: Participantes fase votación participants_vote_phase: Participantes fase votación
participants_total: Total de participantes participants_every_phase: Total de participantes
percent_total_participants_html: "% <br>Total<br>Participantes" percent_total_participants: "% Total Participantes"
percent_heading_census_html: "% <br>Censo<br>Distrito" percent_heading_census: "% Censo Distrito"
participatory_disclaimer: "** Las cifras de total de participantes se refieren a personas que han creado, apoyado o votado propuestas." participatory_disclaimer: "** Las cifras de total de participantes se refieren a personas que han creado, apoyado o votado propuestas."
heading_disclaimer: "*** Los datos de distrito se refieren al distrito en el que el usuario ha votado, no necesariamente en el que está empadronado." heading_disclaimer: "*** Los datos de distrito se refieren al distrito en el que el usuario ha votado, no necesariamente en el que está empadronado."
polls: polls:

View File

@@ -8,25 +8,16 @@ feature "Stats" do
describe "Show" do describe "Show" do
it "is not accessible to normal users if phase is not 'finished'" do it "is not accessible if supports phase is not finished" do
budget.update(phase: "reviewing_ballots") budget.update(phase: "selecting")
visit budget_stats_path(budget.id) visit budget_stats_path(budget.id)
expect(page).to have_content "You do not have permission to carry out the action "\ expect(page).to have_content "You do not have permission to carry out the action "\
"'read_stats' on budget." "'read_stats' on budget."
end end
it "is accessible to normal users if phase is 'finished'" do it "is accessible if supports phase is finished" do
budget.update(phase: "finished") budget.update(phase: "valuating")
visit budget_stats_path(budget.id)
expect(page).to have_content "Stats"
end
it "is accessible to administrators when budget has phase 'reviewing_ballots'" do
budget.update(phase: "reviewing_ballots")
login_as(create(:administrator).user)
visit budget_stats_path(budget.id) visit budget_stats_path(budget.id)
expect(page).to have_content "Stats" expect(page).to have_content "Stats"

View File

@@ -1,7 +1,7 @@
require "rails_helper" require "rails_helper"
describe Budget::Stats do describe Budget::Stats do
let(:budget) { create(:budget) } let(:budget) { create(:budget, :finished) }
let(:stats) { Budget::Stats.new(budget) } let(:stats) { Budget::Stats.new(budget) }
let(:investment) { create(:budget_investment, :selected, budget: budget) } let(:investment) { create(:budget_investment, :selected, budget: budget) }
@@ -213,4 +213,75 @@ describe Budget::Stats do
expect(heading_stats[:percentage_district_population_every_phase]).to be 0.243 expect(heading_stats[:percentage_district_population_every_phase]).to be 0.243
end end
end end
describe "#support_phase_finished?" do
context "support phase isn't finished" do
before { budget.phase = "selecting" }
it "is false" do
expect(stats.support_phase_finished?).to be false
end
end
context "support phase is finished" do
before { budget.phase = "valuating" }
it "is false" do
expect(stats.support_phase_finished?).to be true
end
end
end
describe "#vote_phase_finished" do
context "support phase isn't finished" do
before { budget.phase = "reviewing_ballots" }
it "is false" do
expect(stats.vote_phase_finished?).to be false
end
end
context "vote phase is finished" do
before { budget.phase = "finished" }
it "is false" do
expect(stats.vote_phase_finished?).to be true
end
end
end
describe "#all_phases" do
context "no phases are finished" do
before do
allow(stats).to receive(:support_phase_finished?).and_return(false)
allow(stats).to receive(:vote_phase_finished?).and_return(false)
end
it "returns an empty array" do
expect(stats.all_phases).to eq []
end
end
context "one phase is finished" do
before do
allow(stats).to receive(:support_phase_finished?).and_return(true)
allow(stats).to receive(:vote_phase_finished?).and_return(false)
end
it "returns the finished phase" do
expect(stats.all_phases).to eq ["support"]
end
end
context "all phases are finished" do
before do
allow(stats).to receive(:support_phase_finished?).and_return(true)
allow(stats).to receive(:vote_phase_finished?).and_return(true)
end
it "returns the finished phases and a total phase" do
expect(stats.all_phases).to eq ["support", "vote", "every"]
end
end
end
end end