Merge pull request #2518 from consul/valuator_cannot_reopen_valuations
Valuators cannot reopen finished valuations
This commit is contained in:
@@ -5,7 +5,8 @@ module Abilities
|
||||
def initialize(user)
|
||||
valuator = user.valuator
|
||||
can [:read, :update, :valuate], SpendingProposal
|
||||
can [:read, :update, :valuate, :comment_valuation], Budget::Investment, id: valuator.investment_ids
|
||||
can [:read, :update, :comment_valuation], Budget::Investment, id: valuator.investment_ids
|
||||
can [:valuate], Budget::Investment, { id: valuator.investment_ids, valuation_finished: false }
|
||||
cannot [:update, :valuate, :comment_valuation], Budget::Investment, budget: { phase: 'finished' }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,96 +4,125 @@
|
||||
<% end %>
|
||||
|
||||
<h2><%= t("valuation.budget_investments.edit.dossier") %></h2>
|
||||
|
||||
<%= form_for(@investment, url: valuate_valuation_budget_budget_investment_path(@budget, @investment), html: {id: "valuation_budget_investment_edit_form"}) do |f| %>
|
||||
<%= render 'shared/errors', resource: @investment %>
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<fieldset class="fieldset">
|
||||
<legend><%= t('valuation.budget_investments.edit.feasibility') %></legend>
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'undecided', label: false %>
|
||||
<%= f.label :feasibility_undecided, t('valuation.budget_investments.edit.undefined_feasible') %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'feasible', label: false %>
|
||||
<%= f.label :feasibility_feasible, t('valuation.budget_investments.edit.feasible') %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'unfeasible', label: false %>
|
||||
<%= f.label :feasibility_unfeasible, t('valuation.budget_investments.edit.unfeasible') %>
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="unfeasible_fields" >
|
||||
|
||||
<% if can?(:valuate, @investment) %>
|
||||
<%= form_for(@investment, url: valuate_valuation_budget_budget_investment_path(@budget, @investment), html: {id: "valuation_budget_investment_edit_form"}) do |f| %>
|
||||
<%= render 'shared/errors', resource: @investment %>
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<%= f.label :unfeasibility_explanation, t("valuation.budget_investments.edit.feasible_explanation_html") %>
|
||||
<%= f.text_area :unfeasibility_explanation, label: false, rows: 3 %>
|
||||
<fieldset class="fieldset">
|
||||
<legend><%= t('valuation.budget_investments.edit.feasibility') %></legend>
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'undecided', label: false %>
|
||||
<%= f.label :feasibility_undecided, t('valuation.budget_investments.edit.undefined_feasible') %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'feasible', label: false %>
|
||||
<%= f.label :feasibility_feasible, t('valuation.budget_investments.edit.feasible') %>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="small-4 column">
|
||||
<span class="radio">
|
||||
<%= f.radio_button :feasibility, 'unfeasible', label: false %>
|
||||
<%= f.label :feasibility_unfeasible, t('valuation.budget_investments.edit.unfeasible') %>
|
||||
</span>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div id="unfeasible_fields" >
|
||||
|
||||
<div id="feasible_fields">
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.label :price, "#{t('valuation.budget_investments.edit.price_html', currency: @budget.currency_symbol)}" %>
|
||||
<%= f.number_field :price, label: false, max: 1000000000000000 %>
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<%= f.label :unfeasibility_explanation, t("valuation.budget_investments.edit.feasible_explanation_html") %>
|
||||
<%= f.text_area :unfeasibility_explanation, label: false, rows: 3 %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column end">
|
||||
<%= f.label :price_first_year, "#{t('valuation.budget_investments.edit.price_first_year_html', currency: @budget.currency_symbol)}" %>
|
||||
<%= f.number_field :price_first_year, label: false, max: 1000000000000000 %>
|
||||
</div>
|
||||
|
||||
<div id="feasible_fields">
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.label :price, "#{t('valuation.budget_investments.edit.price_html', currency: @budget.currency_symbol)}" %>
|
||||
<%= f.number_field :price, label: false, max: 1000000000000000 %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-6 column end">
|
||||
<%= f.label :price_first_year, "#{t('valuation.budget_investments.edit.price_first_year_html', currency: @budget.currency_symbol)}" %>
|
||||
<%= f.number_field :price_first_year, label: false, max: 1000000000000000 %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<%= f.label :price_explanation, t("valuation.budget_investments.edit.price_explanation_html") %>
|
||||
<%= f.text_area :price_explanation, label: false, rows: 3 %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.label :duration, t("valuation.budget_investments.edit.duration_html") %>
|
||||
<%= f.text_field :duration, label: false %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-8 column">
|
||||
<%= f.label :valuation_finished do %>
|
||||
<%= f.check_box :valuation_finished,
|
||||
title: t('valuation.budget_investments.edit.valuation_finished'),
|
||||
label: false, id: 'js-investment-report-alert',
|
||||
"data-alert": t("valuation.budget_investments.edit.valuation_finished_alert"),
|
||||
"data-not-feasible-alert": t("valuation.budget_investments.edit.not_feasible_alert") %>
|
||||
<span class="checkbox"><%= t("valuation.budget_investments.edit.valuation_finished") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<%= f.label :price_explanation, t("valuation.budget_investments.edit.price_explanation_html") %>
|
||||
<%= f.text_area :price_explanation, label: false, rows: 3 %>
|
||||
<div class="actions small-12 medium-4 column">
|
||||
<%= f.submit(class: "button expanded large", value: t("valuation.budget_investments.edit.save")) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.label :duration, t("valuation.budget_investments.edit.duration_html") %>
|
||||
<%= f.text_field :duration, label: false %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="small-12 medium-8 column">
|
||||
<%= f.label :valuation_finished do %>
|
||||
<%= f.check_box :valuation_finished,
|
||||
title: t('valuation.budget_investments.edit.valuation_finished'),
|
||||
label: false, id: 'js-investment-report-alert',
|
||||
"data-alert": t("valuation.budget_investments.edit.valuation_finished_alert"),
|
||||
"data-not-feasible-alert": t("valuation.budget_investments.edit.not_feasible_alert") %>
|
||||
<span class="checkbox"><%= t("valuation.budget_investments.edit.valuation_finished") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="actions small-12 medium-4 column">
|
||||
<%= f.submit(class: "button expanded large", value: t("valuation.budget_investments.edit.save")) %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<p>
|
||||
<h3><%= t('valuation.budget_investments.edit.valuation_finished') %></h3>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t('valuation.budget_investments.edit.feasibility') %>:</strong>
|
||||
<%= t("admin.budget_investments.index.feasibility.#{@investment.feasibility}") %>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t("valuation.budget_investments.edit.feasible_explanation_html") %>:</strong>
|
||||
<%= @investment.unfeasibility_explanation.presence || '-' %>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t('valuation.budget_investments.edit.price_html', currency: @budget.currency_symbol) %>:</strong>
|
||||
<%= @investment.price.presence || '-' %>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t('valuation.budget_investments.show.price_first_year', currency: @budget.currency_symbol) %>:</strong>
|
||||
<%= @investment.price_first_year.presence || '-' %>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t('valuation.budget_investments.edit.price_explanation_html') %>:</strong>
|
||||
<%= @investment.price_explanation.presence || '-'%>
|
||||
</p>
|
||||
<p>
|
||||
<strong><%= t('valuation.budget_investments.edit.duration_html') %>:</strong>
|
||||
<%= @investment.duration.presence || '-' %>
|
||||
</p>
|
||||
<% end %>
|
||||
|
||||
<%= render 'valuation/budget_investments/valuation_comments' %>
|
||||
|
||||
@@ -352,6 +352,47 @@ feature 'Valuation budget investments' do
|
||||
expect(page).to have_content('Valuation finished')
|
||||
end
|
||||
|
||||
context 'Reopen valuation' do
|
||||
background do
|
||||
investment.update(
|
||||
valuation_finished: true,
|
||||
feasibility: 'feasible',
|
||||
unfeasibility_explanation: 'Explanation is explanatory',
|
||||
price: 999,
|
||||
price_first_year: 666,
|
||||
price_explanation: 'Democracy is not cheap',
|
||||
duration: '1 light year'
|
||||
)
|
||||
end
|
||||
|
||||
scenario 'Admins can reopen & modify finished valuation' do
|
||||
logout
|
||||
login_as(admin.user)
|
||||
visit edit_valuation_budget_budget_investment_path(budget, investment)
|
||||
|
||||
expect(page).to have_selector("input[id='budget_investment_feasibility_undecided']")
|
||||
expect(page).to have_selector("textarea[id='budget_investment_unfeasibility_explanation']")
|
||||
expect(page).to have_selector("input[name='budget_investment[valuation_finished]']")
|
||||
expect(page).to have_button('Save changes')
|
||||
end
|
||||
|
||||
scenario 'Valuators that are not admins cannot reopen or modify a finished valuation' do
|
||||
visit edit_valuation_budget_budget_investment_path(budget, investment)
|
||||
|
||||
expect(page).not_to have_selector("input[id='budget_investment_feasibility_undecided']")
|
||||
expect(page).not_to have_selector("textarea[id='budget_investment_unfeasibility_explanation']")
|
||||
expect(page).not_to have_selector("input[name='budget_investment[valuation_finished]']")
|
||||
expect(page).to have_content('Valuation finished')
|
||||
expect(page).to have_content('Feasibility: Feasible')
|
||||
expect(page).to have_content('Feasibility explanation: Explanation is explanatory')
|
||||
expect(page).to have_content('Price (€): 999')
|
||||
expect(page).to have_content('Cost during the first year: 666')
|
||||
expect(page).to have_content('Price explanation: Democracy is not cheap')
|
||||
expect(page).to have_content('Time scope: 1 light year')
|
||||
expect(page).not_to have_button('Save changes')
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Validates price formats' do
|
||||
visit valuation_budget_budget_investments_path(budget)
|
||||
within("#budget_investment_#{investment.id}") do
|
||||
|
||||
@@ -19,6 +19,12 @@ describe Abilities::Valuator do
|
||||
it { should be_able_to(:update, SpendingProposal) }
|
||||
it { should be_able_to(:valuate, SpendingProposal) }
|
||||
|
||||
it "cannot valuate an assigned investment with a finished valuation" do
|
||||
assigned_investment.update(valuation_finished: true)
|
||||
|
||||
should_not be_able_to(:valuate, assigned_investment)
|
||||
end
|
||||
|
||||
it { should_not be_able_to(:update, non_assigned_investment) }
|
||||
it { should_not be_able_to(:valuate, non_assigned_investment) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user