adds dossier editing of investments to valuation

This commit is contained in:
Juanjo Bazán
2016-09-09 15:09:06 +02:00
parent 0fc31b1259
commit 42c705e1e3
9 changed files with 503 additions and 13 deletions

View File

@@ -42,6 +42,7 @@
//= require suggest
//= require forms
//= require tracks
//= require valuation_budget_investment_form
//= require valuation_spending_proposal_form
//= require embed_video
//= require banners
@@ -63,6 +64,7 @@ var initialize_modules = function() {
App.Suggest.initialize();
App.Forms.initialize();
App.Tracks.initialize();
App.ValuationBudgetInvestmentForm.initialize();
App.ValuationSpendingProposalForm.initialize();
App.EmbedVideo.initialize();
App.Banners.initialize();

View File

@@ -0,0 +1,32 @@
App.ValuationBudgetInvestmentForm =
showFeasibleFields: ->
$('#valuation_budget_investment_edit_form #unfeasible_fields').hide('down')
$('#valuation_budget_investment_edit_form #feasible_fields').show()
showNotFeasibleFields: ->
$('#valuation_budget_investment_edit_form #feasible_fields').hide('down')
$('#valuation_budget_investment_edit_form #unfeasible_fields').show()
showAllFields: ->
$('#valuation_budget_investment_edit_form #feasible_fields').show('down')
$('#valuation_budget_investment_edit_form #unfeasible_fields').show('down')
showFeasibilityFields: ->
feasibility = $("#valuation_budget_investment_edit_form input[type=radio][name='budget_investment[feasibility]']:checked").val()
if feasibility == 'feasible'
App.ValuationBudgetInvestmentForm.showFeasibleFields()
else if feasibility == 'unfeasible'
App.ValuationBudgetInvestmentForm.showNotFeasibleFields()
showFeasibilityFieldsOnChange: ->
$("#valuation_budget_investment_edit_form input[type=radio][name='budget_investment[feasibility]']").change ->
App.ValuationBudgetInvestmentForm.showAllFields()
App.ValuationBudgetInvestmentForm.showFeasibilityFields()
initialize: ->
App.ValuationBudgetInvestmentForm.showFeasibilityFields()
App.ValuationBudgetInvestmentForm.showFeasibilityFieldsOnChange()
false

View File

@@ -4,6 +4,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
before_action :restrict_access_to_assigned_items, only: [:show, :edit, :valuate]
before_action :load_budget
before_action :load_investment, only: [:show, :edit, :valuate]
has_filters %w{valuating valuation_finished}, only: :index
@@ -20,12 +21,7 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
def valuate
if valid_price_params? && @investment.update(valuation_params)
if @investment.unfeasible_email_pending?
@investment.send_unfeasible_email
end
redirect_to valuation_budget_investment_path(@investment), notice: t('valuation.budget_investments.notice.valuate')
redirect_to valuation_budget_budget_investment_path(@budget, @investment), notice: t('valuation.budget_investments.notice.valuate')
else
render action: :edit
end
@@ -37,6 +33,10 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
@budget = Budget.find(params[:budget_id])
end
def load_investment
@investment = @budget.investments.find params[:id]
end
def heading_filters
investments = @budget.investments.by_valuator(current_user.valuator.try(:id)).valuation_open.select(:heading_id).all.to_a
@@ -57,13 +57,11 @@ class Valuation::BudgetInvestmentsController < Valuation::BaseController
end
def valuation_params
params[:budget_investment][:feasible] = nil if params[:budget_investment][:feasible] == 'nil'
params.require(:budget_investment).permit(:price, :price_first_year, :price_explanation, :feasible, :feasible_explanation, :duration, :valuation_finished, :internal_comments)
params.require(:budget_investment).permit(:price, :price_first_year, :price_explanation, :feasibility, :unfeasibility_explanation, :duration, :valuation_finished, :internal_comments)
end
def restrict_access_to_assigned_items
raise ActionController::RoutingError.new('Not Found') unless current_user.administrator? || ValuatorAssignment.exists?(investment_id: params[:id], valuator_id: current_user.valuator.id)
raise ActionController::RoutingError.new('Not Found') unless current_user.administrator? || Budget::ValuatorAssignment.exists?(investment_id: params[:id], valuator_id: current_user.valuator.id)
end
def valid_price_params?

View File

@@ -44,6 +44,6 @@
<%= render 'valuation/budget_investments/written_by_valuators' %>
<p>
<%= link_to t("admin.budget_investments.show.edit_dossier"), edit_valuation_spending_proposal_path(@investment) %>
<%= link_to t("admin.budget_investments.show.edit_dossier"), edit_valuation_budget_budget_investment_path(@budget, @investment) %>
</p>

View File

@@ -0,0 +1,141 @@
<%= link_to "#{t('valuation.budget_investments.show.title')} #{@investment.id}", valuation_budget_budget_investment_path(@budget, @investment), class: 'back' %>
<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 medium-8 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" >
<div class="row">
<div class="small-12 medium-8 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>
<div id="feasible_fields">
<div class="row">
<div class="small-12 medium-4 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-4 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 medium-8 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-8 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 %>
<span class="checkbox"><%= t("valuation.budget_investments.edit.valuation_finished") %></span>
<% end %>
</div>
</div>
<div class="row">
<div class="small-12 medium-8 column">
<%= f.label :internal_comments, t("valuation.budget_investments.edit.internal_comments_html") %>
<%= f.text_area :internal_comments, label: false, rows: 3 %>
</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 %>
<h1><%= @investment.title %></h1>
<%= safe_html_with_links @investment.description %>
<% if @investment.external_url.present? %>
<p><%= text_with_links @investment.external_url %></p>
<% end %>
<h2><%= t("valuation.budget_investments.show.info") %></h2>
<p><strong><%= t("valuation.budget_investments.show.by") %>:</strong>
<%= link_to @investment.author.name, user_path(@investment.author) %>
</p>
<p><strong><%= t("valuation.budget_investments.show.heading") %>:</strong>
<%= @investment.heading.name %>
</p>
<p><strong><%= t("valuation.budget_investments.show.sent") %>:</strong>
<%= l @investment.created_at, format: :datetime %>
</p>
<h2><%= t("valuation.budget_investments.show.responsibles") %></h2>
<p><strong><%= t("valuation.budget_investments.show.assigned_admin") %>:</strong>
<% if @investment.administrator.present? %>
<%= @investment.administrator.name %> (<%= @investment.administrator.email %>)
<% else %>
<%= t("valuation.budget_investments.show.undefined") %></li>
<% end %>
</p>
<p><strong><%= t("valuation.budget_investments.show.assigned_valuators") %>:</strong></p>
<div id="assigned_valuators">
<ul>
<% @investment.valuators.each do |valuator| %>
<li><%= valuator.name %> (<%= valuator.email %>)</li>
<% end %>
<% if @investment.valuators.empty? %>
<li><%= t("valuation.budget_investments.show.undefined") %></li>
<% end %>
</ul>
</div>

View File

@@ -0,0 +1,55 @@
<%= render "shared/back_link" %>
<h2><%= t("valuation.budget_investments.show.title") %> <%= @investment.id %> </h2>
<h1><%= @investment.title %></h1>
<%= safe_html_with_links @investment.description %>
<% if @investment.external_url.present? %>
<p><%= text_with_links @investment.external_url %></p>
<% end %>
<h2><%= t("valuation.budget_investments.show.info") %></h2>
<p><strong><%= t("valuation.budget_investments.show.by") %>:</strong>
<%= link_to @investment.author.name, user_path(@investment.author) %>
</p>
<p><strong><%= t("valuation.budget_investments.show.heading") %>:</strong>
<%= @investment.heading.name %>
</p>
<p><strong><%= t("valuation.budget_investments.show.sent") %>:</strong>
<%= l @investment.created_at, format: :datetime %>
</p>
<h2><%= t("valuation.budget_investments.show.responsibles") %></h2>
<p><strong><%= t("valuation.budget_investments.show.assigned_admin") %>:</strong>
<% if @investment.administrator.present? %>
<%= @investment.administrator.name_and_email %>
<% else %>
<%= t("valuation.budget_investments.show.undefined") %></li>
<% end %>
</p>
<p><strong><%= t("valuation.budget_investments.show.assigned_valuators") %>:</strong></p>
<div id="assigned_valuators">
<ul>
<% @investment.valuators.each do |valuator| %>
<li><%= valuator.name_and_email %></li>
<% end %>
<% if @investment.valuators.empty? %>
<li><%= t("valuation.budget_investments.show.undefined") %></li>
<% end %>
</ul>
</div>
<h2><%= t("valuation.budget_investments.show.dossier") %></h2>
<p>
<%= link_to t("valuation.budget_investments.show.edit_dossier"), edit_valuation_budget_budget_investment_path(@budget, @investment) %>
</p>
<%= render 'written_by_valuators' %>

View File

@@ -26,7 +26,7 @@ en:
no_valuators_assigned: No valuators assigned
show:
back: Back
heading: Investment project
title: Investment project
info: Author info
by: Sent by
sent: Sent at
@@ -46,6 +46,20 @@ en:
responsibles: Responsibles
assigned_admin: Assigned admin
assigned_valuators: Assigned valuators
edit:
dossier: Dossier
price_html: "Price (%{currency})"
price_first_year_html: "Cost during the first year (%{currency})"
price_explanation_html: Price explanation
feasibility: Feasibility
feasible: Feasible
unfeasible: Not feasible
undefined_feasible: Pending
feasible_explanation_html: Feasibility explanation
valuation_finished: Valuation finished
duration_html: Time scope
internal_comments_html: Internal comments
save: Save changes
notice:
valuate: "Dossier updated"
spending_proposals:

View File

@@ -26,7 +26,7 @@ es:
no_valuators_assigned: Sin evaluador
show:
back: Volver
heading: Propuesta de inversión
title: Propuesta de inversión
info: Datos de envío
by: Enviada por
sent: Fecha de creación
@@ -46,6 +46,20 @@ es:
responsibles: Responsables
assigned_admin: Administrador asignado
assigned_valuators: Evaluadores asignados
edit:
dossier: Informe
price_html: "Coste (%{currency}) <small>(dato público)</small>"
price_first_year_html: "Coste en el primer año (%{currency}) <small>(opcional, privado)</small>"
price_explanation_html: "Informe de coste <small>(opcional, dato público)</small>"
feasibility: Viabilidad
feasible: Viable
unfeasible: Inviable
undefined_feasible: Sin decidir
feasible_explanation_html: "Informe de inviabilidad <small>(en caso de que lo sea, dato público)</small>"
valuation_finished: Informe finalizado
duration_html: "Plazo de ejecución <small>(opcional, dato no público)</small>"
internal_comments_html: "Comentarios y observaciones <small>(para responsables internos, dato no público)</small>"
save: Guardar cambios
notice:
valuate: "Dossier actualizado"
spending_proposals:

View File

@@ -158,4 +158,238 @@ feature 'Valuation budget investments' do
expect(page).to have_content("Old idea")
end
feature 'Show' do
scenario 'visible for assigned valuators' do
administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
investment = create(:budget_investment,
budget: @budget,
price: 1234,
feasibility: 'unfeasible',
unfeasibility_explanation: 'It is impossible',
administrator: administrator)
investment.valuators << [@valuator, valuator2]
visit valuation_budget_budget_investments_path(@budget)
click_link investment.title
expect(page).to have_content(investment.title)
expect(page).to have_content(investment.description)
expect(page).to have_content(investment.author.name)
expect(page).to have_content(investment.heading.name)
expect(page).to have_content('1234')
expect(page).to have_content('Unfeasible')
expect(page).to have_content('It is impossible')
expect(page).to have_content('Ana (ana@admins.org)')
within('#assigned_valuators') do
expect(page).to have_content('Rachel (rachel@valuators.org)')
expect(page).to have_content('Rick (rick@valuators.org)')
end
end
scenario 'visible for admins' do
logout
login_as create(:administrator).user
administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
investment = create(:budget_investment,
budget: @budget,
price: 1234,
feasibility: 'unfeasible',
unfeasibility_explanation: 'It is impossible',
administrator: administrator)
investment.valuators << [@valuator, valuator2]
visit valuation_budget_budget_investment_path(@budget, investment)
expect(page).to have_content(investment.title)
expect(page).to have_content(investment.description)
expect(page).to have_content(investment.author.name)
expect(page).to have_content(investment.heading.name)
expect(page).to have_content('1234')
expect(page).to have_content('Unfeasible')
expect(page).to have_content('It is impossible')
expect(page).to have_content('Ana (ana@admins.org)')
within('#assigned_valuators') do
expect(page).to have_content('Rachel (rachel@valuators.org)')
expect(page).to have_content('Rick (rick@valuators.org)')
end
end
scenario 'not visible for not assigned valuators' do
logout
login_as create(:valuator).user
valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org'))
investment = create(:budget_investment,
budget: @budget,
price: 1234,
feasibility: 'unfeasible',
unfeasibility_explanation: 'It is impossible',
administrator: create(:administrator))
investment.valuators << [@valuator, valuator2]
expect { visit valuation_budget_budget_investment_path(@budget, investment) }.to raise_error "Not Found"
end
end
feature 'Valuate' do
background do
@investment = create(:budget_investment,
budget: @budget,
price: nil,
administrator: create(:administrator))
@investment.valuators << @valuator
end
scenario 'Dossier empty by default' do
visit valuation_budget_budget_investments_path(@budget)
click_link @investment.title
within('#price') { expect(page).to have_content('Undefined') }
within('#price_first_year') { expect(page).to have_content('Undefined') }
within('#duration') { expect(page).to have_content('Undefined') }
within('#feasibility') { expect(page).to have_content('Undecided') }
expect(page).to_not have_content('Valuation finished')
expect(page).to_not have_content('Internal comments')
end
scenario 'Edit dossier' do
visit valuation_budget_budget_investments_path(@budget)
within("#budget_investment_#{@investment.id}") do
click_link "Edit"
end
fill_in 'budget_investment_price', with: '12345'
fill_in 'budget_investment_price_first_year', with: '9876'
fill_in 'budget_investment_price_explanation', with: 'Very cheap idea'
choose 'budget_investment_feasibility_feasible'
fill_in 'budget_investment_duration', with: '19 months'
fill_in 'budget_investment_internal_comments', with: 'Should be double checked by the urbanism area'
click_button 'Save changes'
expect(page).to have_content "Dossier updated"
visit valuation_budget_budget_investments_path(@budget)
click_link @investment.title
within('#price') { expect(page).to have_content('12345') }
within('#price_first_year') { expect(page).to have_content('9876') }
expect(page).to have_content('Very cheap idea')
within('#duration') { expect(page).to have_content('19 months') }
within('#feasibility') { expect(page).to have_content('Feasible') }
expect(page).to_not have_content('Valuation finished')
expect(page).to have_content('Internal comments')
expect(page).to have_content('Should be double checked by the urbanism area')
end
scenario 'Feasibility can be marked as pending' do
visit valuation_budget_budget_investment_path(@budget, @investment)
click_link 'Edit dossier'
expect(find "#budget_investment_feasibility_undecided").to be_checked
choose 'budget_investment_feasibility_feasible'
click_button 'Save changes'
visit edit_valuation_budget_budget_investment_path(@budget, @investment)
expect(find "#budget_investment_feasibility_undecided").to_not be_checked
expect(find "#budget_investment_feasibility_feasible").to be_checked
choose 'budget_investment_feasibility_undecided'
click_button 'Save changes'
visit edit_valuation_budget_budget_investment_path(@budget, @investment)
expect(find "#budget_investment_feasibility_undecided").to be_checked
end
scenario 'Feasibility selection makes proper fields visible', :js do
feasible_fields = ['Price (€)','Cost during the first year (€)','Price explanation','Time scope']
unfeasible_fields = ['Feasibility explanation']
any_feasibility_fields = ['Valuation finished','Internal comments']
undecided_fields = feasible_fields + unfeasible_fields + any_feasibility_fields
visit edit_valuation_budget_budget_investment_path(@budget, @investment)
expect(find "#budget_investment_feasibility_undecided").to be_checked
undecided_fields.each do |field|
expect(page).to have_content(field)
end
choose 'budget_investment_feasibility_feasible'
unfeasible_fields.each do |field|
expect(page).to_not have_content(field)
end
(feasible_fields + any_feasibility_fields).each do |field|
expect(page).to have_content(field)
end
choose 'budget_investment_feasibility_unfeasible'
feasible_fields.each do |field|
expect(page).to_not have_content(field)
end
(unfeasible_fields + any_feasibility_fields).each do |field|
expect(page).to have_content(field)
end
click_button 'Save changes'
visit edit_valuation_budget_budget_investment_path(@budget, @investment)
expect(find "#budget_investment_feasibility_unfeasible").to be_checked
feasible_fields.each do |field|
expect(page).to_not have_content(field)
end
(unfeasible_fields + any_feasibility_fields).each do |field|
expect(page).to have_content(field)
end
choose 'budget_investment_feasibility_undecided'
undecided_fields.each do |field|
expect(page).to have_content(field)
end
end
scenario 'Finish valuation' do
visit valuation_budget_budget_investment_path(@budget, @investment)
click_link 'Edit dossier'
check 'budget_investment_valuation_finished'
click_button 'Save changes'
visit valuation_budget_budget_investments_path(@budget)
expect(page).to_not have_content @investment.title
click_link 'Valuation finished'
expect(page).to have_content @investment.title
click_link @investment.title
expect(page).to have_content('Valuation finished')
end
scenario 'Validates price formats' do
visit valuation_budget_budget_investments_path(@budget)
within("#budget_investment_#{@investment.id}") do
click_link "Edit"
end
fill_in 'budget_investment_price', with: '12345,98'
fill_in 'budget_investment_price_first_year', with: '9876.6'
click_button 'Save changes'
expect(page).to have_content('2 errors')
expect(page).to have_content('Only integer numbers', count: 2)
end
end
end