diff --git a/app/controllers/valuation/spending_proposals_controller.rb b/app/controllers/valuation/spending_proposals_controller.rb index 21389d4a2..309a12a37 100644 --- a/app/controllers/valuation/spending_proposals_controller.rb +++ b/app/controllers/valuation/spending_proposals_controller.rb @@ -9,4 +9,16 @@ class Valuation::SpendingProposalsController < Valuation::BaseController def index @spending_proposals = SpendingProposal.search(params, @current_filter).order(created_at: :desc).page(params[:page]) end + + def valuate + @spending_proposal.update_attributes(valuation_params) + redirect_to valuation_spending_proposal_path(@spending_proposal), notice: t('valuation.spending_proposals.notice.valuate') + end + + private + + def valuation_params + params.require(:spending_proposal).permit(:price, :price_first_year, :price_explanation, :feasible, :feasible_explanation, :time_scope, :valuation_finished, :internal_comments) + end + end diff --git a/app/views/valuation/spending_proposals/edit.html.erb b/app/views/valuation/spending_proposals/edit.html.erb new file mode 100644 index 000000000..eb8c275d4 --- /dev/null +++ b/app/views/valuation/spending_proposals/edit.html.erb @@ -0,0 +1,138 @@ +<%= link_to "#{t('valuation.spending_proposals.show.heading')} #{@spending_proposal.id}", valuation_spending_proposal_path(@spending_proposal), class: 'back' %> +

<%= t("valuation.spending_proposals.edit.dossier") %>

+ +<%= form_for(@spending_proposal, url: valuate_valuation_spending_proposal_path(@spending_proposal)) do |f| %> + <%= render 'shared/errors', resource: @spending_proposal %> +
+
+ <%= f.label :price, "#{t('valuation.spending_proposals.edit.price')} (#{t('valuation.spending_proposals.edit.currency')})" %> + <%= f.text_field :price, label: false %> +
+ +
+ <%= f.label :price_first_year, "#{t('valuation.spending_proposals.edit.price_first_year')} ( #{t('valuation.spending_proposals.edit.currency')})" %> + <%= f.text_field :price_first_year, label: false %> +
+
+ +
+
+ <%= f.label :price_explanation, t("valuation.spending_proposals.edit.price_explanation") %> + <%= f.text_area :price_explanation, label: false, rows: 3 %> +
+
+ +
+
+
+ <%= t('valuation.spending_proposals.edit.feasibility') %> +
+ + <%= f.radio_button :feasible, true, value: true, label: false %> + <%= f.label :feasible_true, t('valuation.spending_proposals.edit.feasible') %> + +
+ +
+ + <%= f.radio_button :feasible, false, value: false, label: false %> + <%= f.label :feasible_false, t('valuation.spending_proposals.edit.not_feasible') %> + +
+
+
+
+ +
+
+ <%= f.label :feasible_explanation, t("valuation.spending_proposals.edit.feasible_explanation") %> + <%= f.text_area :feasible_explanation, label: false, rows: 3 %> +
+
+ +
+
+ <%= f.label :time_scope, t("valuation.spending_proposals.edit.time_scope") %> + <%= f.text_field :time_scope, label: false %> +
+
+ +
+
+ <%= f.label :valuation_finished do %> + <%= f.check_box :valuation_finished, label: false %> + <%= t("valuation.spending_proposals.edit.valuation_finished") %> + <% end %> +
+
+ +
+
+ <%= f.label :internal_comments, t("valuation.spending_proposals.edit.internal_comments") %> + <%= f.text_area :internal_comments, label: false, rows: 3 %> +
+
+ +
+
+ <%= f.submit(class: "button expanded large", value: t("valuation.spending_proposals.edit.save")) %> +
+
+<% end %> + +

<%= @spending_proposal.title %>

+ +<%= safe_html_with_links @spending_proposal.description %> + +<% if @spending_proposal.external_url.present? %> +

<%= text_with_links @spending_proposal.external_url %>

+<% end %> + +

<%= t("valuation.spending_proposals.show.info") %>

+ +

<%= t("valuation.spending_proposals.show.by") %>: + <%= link_to @spending_proposal.author.name, user_path(@spending_proposal.author) %> +

+ +<% if @spending_proposal.association_name.present? %> +

<%= t("valuation.spending_proposals.show.association_name") %>: + <%= @spending_proposal.association_name %> +

+<% end %> + +

<%= t("valuation.spending_proposals.show.geozone") %>: + <%= geozone_name(@spending_proposal) %> +

+ +

<%= t("valuation.spending_proposals.show.sent") %>: + <%= l @spending_proposal.created_at, format: :datetime %> +

+ +

<%= t("valuation.spending_proposals.show.responsibles") %>

+ +

<%= t("valuation.spending_proposals.show.assigned_admin") %>: + <% if @spending_proposal.administrator.present? %> + <%= @spending_proposal.administrator.name %> (<%= @spending_proposal.administrator.email %>) + <% else %> + <%= t("valuation.spending_proposals.show.undefined") %> + <% end %> +

+ +

<%= t("valuation.spending_proposals.show.assigned_valuators") %>:

+
+ +
+ + + + + + diff --git a/app/views/valuation/spending_proposals/index.html.erb b/app/views/valuation/spending_proposals/index.html.erb index 5aa486677..ddc4003e8 100644 --- a/app/views/valuation/spending_proposals/index.html.erb +++ b/app/views/valuation/spending_proposals/index.html.erb @@ -33,11 +33,7 @@ <%= link_to spending_proposal.title, valuation_spending_proposal_path(spending_proposal) %> - <% if spending_proposal.administrator.present? %> - <%= spending_proposal.administrator.name %> - <% else %> - <%= t("valuation.spending_proposals.index.no_admin_assigned") %> - <% end %> + <%= link_to t("valuation.spending_proposals.index.edit"), edit_valuation_spending_proposal_path(spending_proposal) %> <% case spending_proposal.valuators.size %> diff --git a/app/views/valuation/spending_proposals/show.html.erb b/app/views/valuation/spending_proposals/show.html.erb index 636249d31..9ebaa0c24 100644 --- a/app/views/valuation/spending_proposals/show.html.erb +++ b/app/views/valuation/spending_proposals/show.html.erb @@ -1,5 +1,5 @@ <%= link_to t("valuation.spending_proposals.show.back"), :back, class: 'back' %> -

<%= t("valuation.spending_proposals.show.heading") %> <%= @spending_proposal.id %>

+

<%= t("valuation.spending_proposals.show.heading") %> <%= @spending_proposal.id %>

<%= @spending_proposal.title %>

<%= safe_html_with_links @spending_proposal.description %> @@ -51,18 +51,23 @@ -

<%= t("valuation.spending_proposals.show.dossier") %>

-

<%= t("valuation.spending_proposals.show.price") %> (<%= t("valuation.spending_proposals.show.currency") %>): +

<%= link_to t("valuation.spending_proposals.show.edit_dossier"), edit_valuation_spending_proposal_path(@spending_proposal) %>

+ +

<%= t("valuation.spending_proposals.show.price") %> (<%= t("valuation.spending_proposals.show.currency") %>): <%= @spending_proposal.price.present? ? @spending_proposal.price : t("valuation.spending_proposals.show.undefined") %>

-

<%= t("valuation.spending_proposals.show.price_first_year") %> (<%= t("valuation.spending_proposals.show.currency") %>): +

<%= t("valuation.spending_proposals.show.price_first_year") %> (<%= t("valuation.spending_proposals.show.currency") %>): <%= @spending_proposal.price_first_year.present? ? @spending_proposal.price_first_year : t("valuation.spending_proposals.show.undefined") %>

<%= simple_format(safe_html_with_links(@spending_proposal.price_explanation.html_safe), {}, sanitize: false) if @spending_proposal.price_explanation.present? %> -

<%= t("valuation.spending_proposals.show.feasibility") %>: +

<%= t("valuation.spending_proposals.show.time_scope") %>: + <%= @spending_proposal.time_scope.present? ? @spending_proposal.time_scope : t("valuation.spending_proposals.show.undefined") %> +

+ +

<%= t("valuation.spending_proposals.show.feasibility") %>: <%= t("valuation.spending_proposals.show.#{@spending_proposal.feasibility}") %>

<%= simple_format(safe_html_with_links(@spending_proposal.feasible_explanation.html_safe), {}, sanitize: false) if @spending_proposal.feasible_explanation.present? %> @@ -74,4 +79,4 @@ <% if @spending_proposal.internal_comments.present? %>

<%= t("valuation.spending_proposals.show.internal_comments") %>

<%= simple_format(safe_html_with_links(@spending_proposal.internal_comments.html_safe), {}, sanitize: false) %> -<% end %> \ No newline at end of file +<% end %> diff --git a/config/locales/valuation.en.yml b/config/locales/valuation.en.yml index c48153516..826f70db7 100644 --- a/config/locales/valuation.en.yml +++ b/config/locales/valuation.en.yml @@ -13,8 +13,7 @@ en: valuating: Under valuation valuation_finished: Valuation finished title: Investment projects for participatory budgeting - admin_assigned: Assigned administrator - no_admin_assigned: No admin assigned + edit: Edit valuators_assigned: one: Assigned valuator other: "%{count} valuators assigned" @@ -28,6 +27,7 @@ en: sent: Sent at geozone: Scope dossier: Dossier + edit_dossier: Edit dossier price: Price price_first_year: Cost during the first year currency: "€" @@ -36,7 +36,26 @@ en: not_feasible: Not feasible undefined: Undefined valuation_finished: Valuation finished + time_scope: Time scope internal_comments: Internal comments responsibles: Responsibles assigned_admin: Assigned admin assigned_valuators: Assigned valuators + edit: + dossier: Dossier + price: Price + price_first_year: Cost during the first year + currency: "€" + price_explanation: Price explanation + feasibility: Feasibility + feasible: Feasible + not_feasible: Not feasible + feasible_explanation: Feasibility explanation + valuation_finished: Valuation finished + time_scope: Time scope + internal_comments: Internal comments + save: Save changes + notice: + valuate: "Dossier updated" + + diff --git a/config/locales/valuation.es.yml b/config/locales/valuation.es.yml index 81c082c87..8f3804ccb 100644 --- a/config/locales/valuation.es.yml +++ b/config/locales/valuation.es.yml @@ -13,8 +13,7 @@ es: valuating: En evaluación valuation_finished: Evaluación finalizada title: Propuestas de inversión para presupuestos participativos - admin_assigned: Administrador asignado - no_admin_assigned: Sin admin asignado + edit: Editar valuators_assigned: one: Evaluador asignado other: "%{count} evaluadores asignados" @@ -28,6 +27,7 @@ es: sent: Fecha de creación geozone: Ámbito dossier: Informe + edit_dossier: Editar informe price: Coste price_first_year: Coste en el primer año currency: "€" @@ -36,7 +36,24 @@ es: not_feasible: No viable undefined: Sin definir valuation_finished: Informe finalizado - internal_comments: Commentarios internos + time_scope: Plazo de ejecución + internal_comments: Comentarios internos responsibles: Responsables assigned_admin: Administrador asignado assigned_valuators: Evaluadores asignados + edit: + dossier: Informe + price: Coste + price_first_year: Coste en el primer año + currency: "€" + price_explanation: Justificación del precio + feasibility: Viabilidad + feasible: Viable + not_feasible: No viable + feasible_explanation: Justificación de la viabilidad + valuation_finished: Informe finalizado + time_scope: Plazo de ejecución + internal_comments: Comentarios internos + save: Guardar cambios + notice: + valuate: "Informe actualizado" diff --git a/config/routes.rb b/config/routes.rb index 2e1cbce68..77491bb5e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -211,7 +211,7 @@ Rails.application.routes.draw do namespace :valuation do root to: "spending_proposals#index" - resources :spending_proposals, only: [:index, :show] do + resources :spending_proposals, only: [:index, :show, :edit] do member do patch :valuate end diff --git a/spec/features/valuation/spending_proposals_spec.rb b/spec/features/valuation/spending_proposals_spec.rb index 78ce2e08d..e500c8f8d 100644 --- a/spec/features/valuation/spending_proposals_spec.rb +++ b/spec/features/valuation/spending_proposals_spec.rb @@ -3,8 +3,8 @@ require 'rails_helper' feature 'Valuation spending proposals' do background do - valuator = create(:valuator) - login_as(valuator.user) + @valuator = create(:valuator, user: create(:user, username: 'Rachel', email: 'rachel@valuators.org')) + login_as(@valuator.user) end scenario 'Disabled with a feature flag' do @@ -35,17 +35,14 @@ feature 'Valuation spending proposals' do visit valuation_spending_proposals_path within("#spending_proposal_#{spending_proposal1.id}") do - expect(page).to have_content("No admin assigned") expect(page).to have_content("Olga") end within("#spending_proposal_#{spending_proposal2.id}") do - expect(page).to have_content("No admin assigned") expect(page).to have_content("2 valuators assigned") end within("#spending_proposal_#{spending_proposal3.id}") do - expect(page).to have_content("Gema") expect(page).to have_content("No valuators assigned") end end @@ -76,10 +73,10 @@ feature 'Valuation spending proposals' do scenario "Index filtering by valuator", :js do user = create(:user, username: 'Karnak') - valuator = create(:valuator, user: user) + valuator1 = create(:valuator, user: user) spending = create(:spending_proposal, title: "Realocate visitors") - spending.valuators << valuator + spending.valuators << valuator1 create(:spending_proposal, title: "Destroy the city") visit valuation_spending_proposals_path @@ -142,7 +139,7 @@ feature 'Valuation spending proposals' do scenario 'Show' do administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org')) - valuator = create(:valuator, user: create(:user, username: 'Rachel', email: 'rachel@valuators.org')) + valuator2 = create(:valuator, user: create(:user, username: 'Rick', email: 'rick@valuators.org')) spending_proposal = create(:spending_proposal, geozone: create(:geozone), association_name: 'People of the neighbourhood', @@ -150,7 +147,7 @@ feature 'Valuation spending proposals' do feasible: false, feasible_explanation: 'It is impossible', administrator: administrator) - spending_proposal.valuators << valuator + spending_proposal.valuators << [@valuator, valuator2] visit valuation_spending_proposals_path @@ -168,6 +165,74 @@ feature 'Valuation spending proposals' do within('#assigned_valuators') do expect(page).to have_content('Rachel (rachel@valuators.org)') + expect(page).to have_content('Rick (rick@valuators.org)') + end + end + + feature 'Valuate' do + background do + @spending_proposal = create(:spending_proposal, + geozone: create(:geozone), + administrator: create(:administrator)) + @spending_proposal.valuators << @valuator + end + + scenario 'Dossier empty by default' do + visit valuation_spending_proposals_path + click_link @spending_proposal.title + + within('#price') { expect(page).to have_content('Undefined') } + within('#price_first_year') { expect(page).to have_content('Undefined') } + within('#time_scope') { expect(page).to have_content('Undefined') } + within('#feasibility') { expect(page).to have_content('Undefined') } + expect(page).to_not have_content('Valuation finished') + expect(page).to_not have_content('Internal comments') + end + + scenario 'Edit dossier' do + visit valuation_spending_proposals_path + within("#spending_proposal_#{@spending_proposal.id}") do + click_link "Edit" + end + + fill_in 'spending_proposal_price', with: '12345.67' + fill_in 'spending_proposal_price_first_year', with: '8910.11' + fill_in 'spending_proposal_price_explanation', with: 'Very cheap idea' + choose 'spending_proposal_feasible_true' + fill_in 'spending_proposal_feasible_explanation', with: 'Everything is legal and easy to do' + fill_in 'spending_proposal_time_scope', with: '19 months' + fill_in 'spending_proposal_internal_comments', with: 'Should be double checked by the urbanism area' + click_button 'Save changes' + + expect(page).to have_content "Dossier updated" + + visit valuation_spending_proposals_path + click_link @spending_proposal.title + + within('#price') { expect(page).to have_content('12345.67') } + within('#price_first_year') { expect(page).to have_content('8910.11') } + expect(page).to have_content('Very cheap idea') + within('#time_scope') { 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 'Finish valuation' do + visit valuation_spending_proposal_path(@spending_proposal) + click_link 'Edit dossier' + + check 'spending_proposal_valuation_finished' + click_button 'Save changes' + + visit valuation_spending_proposals_path + expect(page).to_not have_content @spending_proposal.title + click_link 'Valuation finished' + + expect(page).to have_content @spending_proposal.title + click_link @spending_proposal.title + expect(page).to have_content('Valuation finished') end end