Merge pull request #2296 from consul/feature/2278#budget_price_show_phase

New Budget's phase to publish investment prices
This commit is contained in:
BertoCQ
2018-01-10 23:46:41 +01:00
committed by GitHub
11 changed files with 167 additions and 43 deletions

View File

@@ -3,8 +3,11 @@ class Budget < ActiveRecord::Base
include Measurable include Measurable
include Sluggable include Sluggable
PHASES = %w(drafting accepting reviewing selecting valuating balloting PHASES = %w(drafting accepting reviewing selecting valuating publishing_prices
reviewing_ballots finished).freeze balloting reviewing_ballots finished).freeze
ON_HOLD_PHASES = %w(reviewing valuating publishing_prices reviewing_ballots).freeze
PUBLISHED_PRICES_PHASES = %w(publishing_prices balloting reviewing_ballots finished).freeze
CURRENCY_SYMBOLS = %w(€ $ £ ¥).freeze CURRENCY_SYMBOLS = %w(€ $ £ ¥).freeze
validates :name, presence: true, uniqueness: true validates :name, presence: true, uniqueness: true
@@ -19,17 +22,18 @@ class Budget < ActiveRecord::Base
before_validation :sanitize_descriptions before_validation :sanitize_descriptions
scope :on_hold, -> { where(phase: %w(reviewing valuating reviewing_ballots")) } scope :on_hold, -> { where(phase: ON_HOLD_PHASES) }
scope :drafting, -> { where(phase: "drafting") } scope :drafting, -> { where(phase: "drafting") }
scope :accepting, -> { where(phase: "accepting") } scope :accepting, -> { where(phase: "accepting") }
scope :reviewing, -> { where(phase: "reviewing") } scope :reviewing, -> { where(phase: "reviewing") }
scope :selecting, -> { where(phase: "selecting") } scope :selecting, -> { where(phase: "selecting") }
scope :valuating, -> { where(phase: "valuating") } scope :valuating, -> { where(phase: "valuating") }
scope :publishing_prices, -> { where(phase: "publishing_prices") }
scope :balloting, -> { where(phase: "balloting") } scope :balloting, -> { where(phase: "balloting") }
scope :reviewing_ballots, -> { where(phase: "reviewing_ballots") } scope :reviewing_ballots, -> { where(phase: "reviewing_ballots") }
scope :finished, -> { where(phase: "finished") } scope :finished, -> { where(phase: "finished") }
scope :current, -> { where.not(phase: "finished") } scope :current, -> { where.not(phase: "finished") }
def description def description
send("description_#{phase}").try(:html_safe) send("description_#{phase}").try(:html_safe)
@@ -63,6 +67,10 @@ class Budget < ActiveRecord::Base
phase == "valuating" phase == "valuating"
end end
def publishing_prices?
phase == "publishing_prices"
end
def balloting? def balloting?
phase == "balloting" phase == "balloting"
end end
@@ -75,6 +83,10 @@ class Budget < ActiveRecord::Base
phase == "finished" phase == "finished"
end end
def published_prices?
PUBLISHED_PRICES_PHASES.include?(phase)
end
def balloting_process? def balloting_process?
balloting? || reviewing_ballots? balloting? || reviewing_ballots?
end end
@@ -84,7 +96,7 @@ class Budget < ActiveRecord::Base
end end
def on_hold? def on_hold?
reviewing? || valuating? || reviewing_ballots? ON_HOLD_PHASES.include?(phase)
end end
def current? def current?
@@ -118,7 +130,7 @@ class Budget < ActiveRecord::Base
case phase case phase
when 'accepting', 'reviewing' when 'accepting', 'reviewing'
%w{random} %w{random}
when 'balloting', 'reviewing_ballots' when 'publishing_prices', 'balloting', 'reviewing_ballots'
%w{random price} %w{random price}
else else
%w{random confidence_score} %w{random confidence_score}

View File

@@ -240,15 +240,11 @@ class Budget
end end
def should_show_price? def should_show_price?
feasible? && selected? && price.present? && budget.published_prices?
selected? &&
(budget.reviewing_ballots? || budget.finished?)
end end
def should_show_price_info? def should_show_price_explanation?
feasible? && should_show_price? && price_explanation.present?
price_explanation.present? &&
(budget.balloting? || budget.reviewing_ballots? || budget.finished?)
end end
def formatted_price def formatted_price

View File

@@ -71,7 +71,7 @@
<p><%= investment.unfeasibility_explanation %></p> <p><%= investment.unfeasibility_explanation %></p>
<% end %> <% end %>
<% if investment.should_show_price_info? %> <% if investment.should_show_price_explanation? %>
<h2><%= t('budgets.investments.show.price_explanation') %></h2> <h2><%= t('budgets.investments.show.price_explanation') %></h2>
<p><%= investment.price_explanation %></p> <p><%= investment.price_explanation %></p>
<% end %> <% end %>

View File

@@ -34,6 +34,7 @@ en:
reviewing: Reviewing projects reviewing: Reviewing projects
selecting: Selecting projects selecting: Selecting projects
valuating: Valuating projects valuating: Valuating projects
publishing_prices: Publishing projects prices
balloting: Balloting projects balloting: Balloting projects
reviewing_ballots: Reviewing Ballots reviewing_ballots: Reviewing Ballots
finished: Finished budget finished: Finished budget

View File

@@ -34,6 +34,7 @@ es:
reviewing: Revisión interna de proyectos reviewing: Revisión interna de proyectos
selecting: Fase de apoyos selecting: Fase de apoyos
valuating: Evaluación de proyectos valuating: Evaluación de proyectos
publishing_prices: Publicación de precios
balloting: Votación final balloting: Votación final
reviewing_ballots: Votación finalizada reviewing_ballots: Votación finalizada
finished: Resultados finished: Resultados

View File

@@ -0,0 +1,5 @@
class AddPublishingPricesPhaseToBudget < ActiveRecord::Migration
def change
add_column :budgets, :description_publishing_prices, :text
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20180108182839) do ActiveRecord::Schema.define(version: 20180109175851) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -202,6 +202,7 @@ ActiveRecord::Schema.define(version: 20180108182839) do
t.text "description_finished" t.text "description_finished"
t.string "slug" t.string "slug"
t.text "description_drafting" t.text "description_drafting"
t.text "description_publishing_prices"
end end
create_table "campaigns", force: :cascade do |t| create_table "campaigns", force: :cascade do |t|

View File

@@ -228,6 +228,7 @@ FactoryBot.define do
description_reviewing "This budget is reviewing" description_reviewing "This budget is reviewing"
description_selecting "This budget is selecting" description_selecting "This budget is selecting"
description_valuating "This budget is valuating" description_valuating "This budget is valuating"
description_publishing_prices "This budget is publishing prices"
description_balloting "This budget is balloting" description_balloting "This budget is balloting"
description_reviewing_ballots "This budget is reviewing ballots" description_reviewing_ballots "This budget is reviewing ballots"
description_finished "This budget is finished" description_finished "This budget is finished"
@@ -252,6 +253,10 @@ FactoryBot.define do
phase 'valuating' phase 'valuating'
end end
trait :publishing_prices do
phase 'publishing_prices'
end
trait :balloting do trait :balloting do
phase 'balloting' phase 'balloting'
end end
@@ -313,7 +318,6 @@ FactoryBot.define do
selected true selected true
feasibility "feasible" feasibility "feasible"
valuation_finished true valuation_finished true
end end
trait :winner do trait :winner do
@@ -326,6 +330,12 @@ FactoryBot.define do
incompatible true incompatible true
end end
trait :selected_with_price do
selected
price 1000
price_explanation 'Because of reasons'
end
trait :unselected do trait :unselected do
selected false selected false
feasibility "feasible" feasibility "feasible"

View File

@@ -418,6 +418,64 @@ feature 'Budget Investments' do
end end
end end
context "Show Investment's price & cost explanation" do
let(:investment) { create(:budget_investment, :selected_with_price, heading: heading) }
context "When investment with price is selected" do
scenario "Price & explanation is shown when Budget is on published prices phase" do
Budget::PUBLISHED_PRICES_PHASES.each do |phase|
budget.update(phase: phase)
visit budget_investment_path(budget_id: budget.id, id: investment.id)
expect(page).to have_content(investment.formatted_price)
expect(page).to have_content(investment.price_explanation)
visit budget_investments_path(budget)
expect(page).to have_content(investment.formatted_price)
end
end
scenario "Price & explanation isn't shown when Budget is not on published prices phase" do
(Budget::PHASES - Budget::PUBLISHED_PRICES_PHASES).each do |phase|
budget.update(phase: phase)
visit budget_investment_path(budget_id: budget.id, id: investment.id)
expect(page).not_to have_content(investment.formatted_price)
expect(page).not_to have_content(investment.price_explanation)
visit budget_investments_path(budget)
expect(page).not_to have_content(investment.formatted_price)
end
end
end
context "When investment with price is unselected" do
background do
investment.update(selected: false)
end
scenario "Price & explanation isn't shown for any Budget's phase" do
Budget::PHASES.each do |phase|
budget.update(phase: phase)
visit budget_investment_path(budget_id: budget.id, id: investment.id)
expect(page).not_to have_content(investment.formatted_price)
expect(page).not_to have_content(investment.price_explanation)
visit budget_investments_path(budget)
expect(page).not_to have_content(investment.formatted_price)
end
end
end
end
scenario 'Can access the community' do scenario 'Can access the community' do
Setting['feature.community'] = true Setting['feature.community'] = true
@@ -477,13 +535,6 @@ feature 'Budget Investments' do
expect(page).not_to have_content(investment.price_explanation) expect(page).not_to have_content(investment.price_explanation)
end end
scenario "Budget in balloting phase" do
budget.update(phase: "balloting")
visit budget_investment_path(budget_id: budget.id, id: investment.id)
expect(page).to have_content("Price explanation")
expect(page).to have_content(investment.price_explanation)
end
end end
scenario "Show (unfeasible budget investment)" do scenario "Show (unfeasible budget investment)" do

View File

@@ -193,37 +193,73 @@ describe Budget::Investment do
end end
end end
describe "#should_show_price_info?" do describe "#should_show_price?" do
it "returns true for feasibles if phase is balloting or later and price_explanation is present" do let(:budget) { create(:budget, :publishing_prices) }
["balloting", "reviewing_ballots", "finished"].each do |phase| let(:investment) do
budget = create(:budget, phase: phase) create(:budget_investment, :selected, budget: budget)
investment = create(:budget_investment, :feasible, budget: budget, price_explanation: "price explanation") end
expect(investment.should_show_price_info?).to eq(true) it "returns true for selected investments which budget's phase is publishing_prices or later" do
Budget::PUBLISHED_PRICES_PHASES.each do |phase|
budget.update(phase: phase)
expect(investment.should_show_price?).to eq(true)
end end
end end
it "returns false in any other phase" do it "returns false in any other phase" do
(Budget::PHASES - ["balloting", "reviewing_ballots", "finished"]).each do |phase| (Budget::PHASES - Budget::PUBLISHED_PRICES_PHASES).each do |phase|
budget = create(:budget, phase: phase) budget.update(phase: phase)
investment = create(:budget_investment, :feasible, budget: budget, price_explanation: "price explanation")
expect(investment.should_show_price_info?).to eq(false) expect(investment.should_show_price?).to eq(false)
end end
end end
it "returns false if investment is unfeasible" do it "returns false if investment is not selected" do
budget = create(:budget, phase: "balloting") investment.selected = false
investment = create(:budget_investment, :unfeasible, budget: budget, price_explanation: "price explanation")
expect(investment.should_show_price_info?).to eq(false) expect(investment.should_show_price?).to eq(false)
end end
it "returns false if price_explanation is blank" do it "returns false if price is not present" do
budget = create(:budget, phase: "balloting") investment.price = nil
investment = create(:budget_investment, :unfeasible, budget: budget, price_explanation: "")
expect(investment.should_show_price_info?).to eq(false) expect(investment.should_show_price?).to eq(false)
end
end
describe "#should_show_price_explanation?" do
let(:budget) { create(:budget, :publishing_prices) }
let(:investment) do
create(:budget_investment, :selected, budget: budget, price_explanation: "because of reasons")
end
it "returns true for selected with price_explanation & budget in publishing_prices or later" do
Budget::PUBLISHED_PRICES_PHASES.each do |phase|
budget.update(phase: phase)
expect(investment.should_show_price_explanation?).to eq(true)
end
end
it "returns false in any other phase" do
(Budget::PHASES - Budget::PUBLISHED_PRICES_PHASES).each do |phase|
budget.update(phase: phase)
expect(investment.should_show_price_explanation?).to eq(false)
end
end
it "returns false if investment is not selected" do
investment.selected = false
expect(investment.should_show_price_explanation?).to eq(false)
end
it "returns false if price_explanation is not present" do
investment.price_explanation = ""
expect(investment.should_show_price_explanation?).to eq(false)
end end
end end

View File

@@ -55,6 +55,9 @@ describe Budget do
budget.phase = "valuating" budget.phase = "valuating"
expect(budget).to be_valuating expect(budget).to be_valuating
budget.phase = "publishing_prices"
expect(budget).to be_publishing_prices
budget.phase = "balloting" budget.phase = "balloting"
expect(budget).to be_balloting expect(budget).to be_balloting
@@ -81,6 +84,9 @@ describe Budget do
budget.phase = "valuating" budget.phase = "valuating"
expect(budget).to be_on_hold expect(budget).to be_on_hold
budget.phase = "publishing_prices"
expect(budget).to be_on_hold
budget.phase = "balloting" budget.phase = "balloting"
expect(budget).not_to be_on_hold expect(budget).not_to be_on_hold
@@ -107,6 +113,9 @@ describe Budget do
budget.phase = "valuating" budget.phase = "valuating"
expect(budget).not_to be_balloting_or_later expect(budget).not_to be_balloting_or_later
budget.phase = "publishing_prices"
expect(budget).not_to be_balloting_or_later
budget.phase = "balloting" budget.phase = "balloting"
expect(budget).to be_balloting_or_later expect(budget).to be_balloting_or_later
@@ -142,6 +151,8 @@ describe Budget do
expect(budget.investments_orders).to eq(['random']) expect(budget.investments_orders).to eq(['random'])
end end
it "is random and price when ballotting and reviewing ballots" do it "is random and price when ballotting and reviewing ballots" do
budget.phase = 'publishing_prices'
expect(budget.investments_orders).to eq(['random', 'price'])
budget.phase = 'balloting' budget.phase = 'balloting'
expect(budget.investments_orders).to eq(['random', 'price']) expect(budget.investments_orders).to eq(['random', 'price'])
budget.phase = 'reviewing_ballots' budget.phase = 'reviewing_ballots'