diff --git a/app/controllers/admin/budget_investments_controller.rb b/app/controllers/admin/budget_investments_controller.rb index 9f885f474..416799535 100644 --- a/app/controllers/admin/budget_investments_controller.rb +++ b/app/controllers/admin/budget_investments_controller.rb @@ -7,11 +7,12 @@ class Admin::BudgetInvestmentsController < Admin::BaseController has_orders %w{oldest}, only: [:show, :edit] has_filters(%w{all without_admin without_valuator under_valuation valuation_finished winners}, - only: [:index, :toggle_selection]) + only: [:index, :toggle_selection]) before_action :load_budget before_action :load_investment, only: [:show, :edit, :update, :toggle_selection] before_action :load_ballot, only: [:show, :index] + before_action :parse_valuation_filters before_action :load_investments, only: [:index, :toggle_selection] def index @@ -32,6 +33,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController def edit load_admins load_valuators + load_valuator_groups load_tags end @@ -45,6 +47,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController else load_admins load_valuators + load_valuator_groups load_tags render :edit end @@ -93,7 +96,7 @@ class Admin::BudgetInvestmentsController < Admin::BaseController def budget_investment_params params.require(:budget_investment) .permit(:title, :description, :external_url, :heading_id, :administrator_id, :tag_list, - :valuation_tag_list, :incompatible, :selected, valuator_ids: []) + :valuation_tag_list, :incompatible, :selected, valuator_ids: [], valuator_group_ids: []) end def load_budget @@ -112,6 +115,10 @@ class Admin::BudgetInvestmentsController < Admin::BaseController @valuators = Valuator.includes(:user).all.order(description: :asc).order("users.email ASC") end + def load_valuator_groups + @valuator_groups = ValuatorGroup.all.order(name: :asc) + end + def load_tags @tags = Budget::Investment.tags_on(:valuation).order(:name).uniq end @@ -126,4 +133,16 @@ class Admin::BudgetInvestmentsController < Admin::BaseController params[:budget_investment] = params[:budget_investment].except(:valuation_tag_list) end + def parse_valuation_filters + if params[:valuator_or_group_id] + model, id = params[:valuator_or_group_id].split("_") + + if model == "group" + params[:valuator_group_id] = id + else + params[:valuator_id] = id + end + end + end + end diff --git a/app/controllers/admin/valuator_groups_controller.rb b/app/controllers/admin/valuator_groups_controller.rb new file mode 100644 index 000000000..6e8930122 --- /dev/null +++ b/app/controllers/admin/valuator_groups_controller.rb @@ -0,0 +1,52 @@ +class Admin::ValuatorGroupsController < Admin::BaseController + + def index + @groups = ValuatorGroup.all.page(params[:page]) + end + + def show + @group = ValuatorGroup.find(params[:id]) + end + + def new + @group = ValuatorGroup.new + end + + def edit + @group = ValuatorGroup.find(params[:id]) + end + + def create + @group = ValuatorGroup.new(group_params) + if @group.save + notice = t("flash.actions.create.valuator_group") + redirect_to [:admin, :valuator_groups], notice: notice + else + render :new + end + end + + def update + @group = ValuatorGroup.find(params[:id]) + if @group.update(group_params) + notice = t("flash.actions.update.valuator_group") + redirect_to [:admin, @group], notice: notice + else + render :edit + end + end + + def destroy + @group = ValuatorGroup.find(params[:id]) + @group.destroy + notice = t("flash.actions.destroy.valuator_group") + redirect_to [:admin, :valuator_groups], notice: notice + end + + private + + def group_params + params.require(:valuator_group).permit(:name) + end + +end \ No newline at end of file diff --git a/app/controllers/admin/valuators_controller.rb b/app/controllers/admin/valuators_controller.rb index 8b454a1a2..cb1960529 100644 --- a/app/controllers/admin/valuators_controller.rb +++ b/app/controllers/admin/valuators_controller.rb @@ -1,6 +1,10 @@ class Admin::ValuatorsController < Admin::BaseController load_and_authorize_resource + def show + @valuator = Valuator.find(params[:id]) + end + def index @valuators = @valuators.page(params[:page]) end @@ -13,12 +17,27 @@ class Admin::ValuatorsController < Admin::BaseController end def create - @valuator = Valuator.new(create_params) + @valuator = Valuator.new(valuator_params) @valuator.save redirect_to admin_valuators_path end + def edit + @valuator = Valuator.find(params[:id]) + @valuator_groups = ValuatorGroup.all + end + + def update + @valuator = Valuator.find(params[:id]) + if @valuator.update(valuator_params) + notice = t("admin.valuators.form.updated") + redirect_to [:admin, @valuator], notice: notice + else + render :edit + end + end + def destroy @valuator.destroy redirect_to admin_valuators_path @@ -30,9 +49,9 @@ class Admin::ValuatorsController < Admin::BaseController private - def create_params + def valuator_params params[:valuator][:description] = nil if params[:valuator][:description].blank? - params.require(:valuator).permit(:user_id, :description) + params.require(:valuator).permit(:user_id, :description, :valuator_group_id) end end diff --git a/app/helpers/valuation_helper.rb b/app/helpers/valuation_helper.rb index cc6a8e741..311f8e6ec 100644 --- a/app/helpers/valuation_helper.rb +++ b/app/helpers/valuation_helper.rb @@ -1,13 +1,21 @@ module ValuationHelper - def valuator_select_options(valuator = nil) - if valuator.present? - Valuator.where.not(id: valuator.id).order("description ASC").order("users.email ASC") - .includes(:user).collect { |v| [ v.description_or_email, v.id ] } - .prepend([valuator.description_or_email, valuator.id]) - else - Valuator.all.order("description ASC").order("users.email ASC").includes(:user).collect { |v| [ v.description_or_email, v.id ] } - end + def valuator_or_group_select_options + valuator_group_select_options + valuator_select_options + end + + def valuator_select_options + Valuator.order("description ASC").order("users.email ASC").includes(:user). + collect { |v| [ v.description_or_email, "valuator_#{v.id}"] } + end + + def valuator_group_select_options + ValuatorGroup.order("name ASC").collect { |g| [ g.name, "group_#{g.id}"] } + end + + def assigned_valuators(investment) + [investment.valuator_groups.collect(&:name) + + investment.valuators.collect(&:description_or_name)].flatten.join(', ') end def assigned_valuators_info(valuators) diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 07c9d158d..6f8a70b5e 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -43,7 +43,7 @@ module Abilities can [:search, :create, :index, :destroy], ::Administrator can [:search, :create, :index, :destroy], ::Moderator - can [:search, :create, :index, :destroy, :summary], ::Valuator + can [:search, :show, :edit, :update, :create, :index, :destroy, :summary], ::Valuator can [:search, :create, :index, :destroy], ::Manager can [:search, :index], ::User diff --git a/app/models/abilities/valuator.rb b/app/models/abilities/valuator.rb index 3c12f2089..ade0a42b7 100644 --- a/app/models/abilities/valuator.rb +++ b/app/models/abilities/valuator.rb @@ -4,9 +4,10 @@ module Abilities def initialize(user) valuator = user.valuator + can [:read, :update, :valuate], SpendingProposal - can [:read, :update, :comment_valuation], Budget::Investment, id: valuator.investment_ids - can [:valuate], Budget::Investment, { id: valuator.investment_ids, valuation_finished: false } + can [:read, :update, :comment_valuation], Budget::Investment, id: valuator.assigned_investment_ids + can [:valuate], Budget::Investment, { id: valuator.assigned_investment_ids, valuation_finished: false } cannot [:update, :valuate, :comment_valuation], Budget::Investment, budget: { phase: 'finished' } end end diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb index 53d27a741..c8c12e0f8 100644 --- a/app/models/budget/investment.rb +++ b/app/models/budget/investment.rb @@ -35,6 +35,9 @@ class Budget has_many :valuator_assignments, dependent: :destroy has_many :valuators, through: :valuator_assignments + has_many :valuator_group_assignments, dependent: :destroy + has_many :valuator_groups, through: :valuator_group_assignments + has_many :comments, -> {where(valuation: false)}, as: :commentable, class_name: 'Comment' has_many :valuations, -> {where(valuation: true)}, as: :commentable, class_name: 'Comment' @@ -59,9 +62,9 @@ class Budget scope :valuation_open, -> { where(valuation_finished: false) } scope :without_admin, -> { valuation_open.where(administrator_id: nil) } scope :without_valuator, -> { valuation_open.where(valuator_assignments_count: 0) } - scope :under_valuation, -> { valuation_open.where("valuator_assignments_count > 0 AND administrator_id IS NOT ?", nil) } + scope :under_valuation, -> { valuation_open.valuating.where("administrator_id IS NOT ?", nil) } scope :managed, -> { valuation_open.where(valuator_assignments_count: 0).where("administrator_id IS NOT ?", nil) } - scope :valuating, -> { valuation_open.where("valuator_assignments_count > 0") } + scope :valuating, -> { valuation_open.where("valuator_assignments_count > 0 OR valuator_group_assignments_count > 0" ) } scope :valuation_finished, -> { where(valuation_finished: true) } scope :valuation_finished_feasible, -> { where(valuation_finished: true, feasibility: "feasible") } scope :feasible, -> { where(feasibility: "feasible") } @@ -76,12 +79,13 @@ class Budget scope :unselected, -> { not_unfeasible.where(selected: false) } scope :last_week, -> { where("created_at >= ?", 7.days.ago)} - scope :by_group, ->(group_id) { where(group_id: group_id) } - scope :by_heading, ->(heading_id) { where(heading_id: heading_id) } - scope :by_admin, ->(admin_id) { where(administrator_id: admin_id) } - scope :by_tag, ->(tag_name) { tagged_with(tag_name) } - scope :by_valuator, ->(valuator_id) { where("budget_valuator_assignments.valuator_id = ?", valuator_id).joins(:valuator_assignments) } - scope :by_budget, ->(budget) { where(budget: budget) } + scope :by_budget, ->(budget) { where(budget: budget) } + scope :by_group, ->(group_id) { where(group_id: group_id) } + scope :by_heading, ->(heading_id) { where(heading_id: heading_id) } + scope :by_admin, ->(admin_id) { where(administrator_id: admin_id) } + scope :by_tag, ->(tag_name) { tagged_with(tag_name) } + scope :by_valuator, ->(valuator_id) { where("budget_valuator_assignments.valuator_id = ?", valuator_id).joins(:valuator_assignments) } + scope :by_valuator_group, ->(valuator_group_id) { where("budget_valuator_group_assignments.valuator_group_id = ?", valuator_group_id).joins(:valuator_group_assignments) } scope :for_render, -> { includes(:heading) } @@ -106,13 +110,14 @@ class Budget budget = Budget.find_by(slug: params[:budget_id]) || Budget.find_by(id: params[:budget_id]) results = Investment.by_budget(budget) - results = limit_results(budget, params, results) if params[:max_per_heading].present? - results = results.where(group_id: params[:group_id]) if params[:group_id].present? - results = results.by_tag(params[:tag_name]) if params[:tag_name].present? - results = results.by_heading(params[:heading_id]) if params[:heading_id].present? - results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present? - results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present? - results = advanced_filters(params, results) if params[:advanced_filters].present? + results = limit_results(budget, params, results) if params[:max_per_heading].present? + results = results.where(group_id: params[:group_id]) if params[:group_id].present? + results = results.by_tag(params[:tag_name]) if params[:tag_name].present? + results = results.by_heading(params[:heading_id]) if params[:heading_id].present? + results = results.by_valuator(params[:valuator_id]) if params[:valuator_id].present? + results = results.by_valuator_group(params[:valuator_group_id]) if params[:valuator_group_id].present? + results = results.by_admin(params[:administrator_id]) if params[:administrator_id].present? + results = advanced_filters(params, results) if params[:advanced_filters].present? results = results.send(current_filter) if current_filter.present? results.includes(:heading, :group, :budget, administrator: :user, valuators: :user) diff --git a/app/models/budget/valuator_group_assignment.rb b/app/models/budget/valuator_group_assignment.rb new file mode 100644 index 000000000..88a04ae1a --- /dev/null +++ b/app/models/budget/valuator_group_assignment.rb @@ -0,0 +1,6 @@ +class Budget + class ValuatorGroupAssignment < ActiveRecord::Base + belongs_to :valuator_group, counter_cache: :budget_investments_count + belongs_to :investment, counter_cache: true + end +end \ No newline at end of file diff --git a/app/models/valuator.rb b/app/models/valuator.rb index 5df6ea030..30b171823 100644 --- a/app/models/valuator.rb +++ b/app/models/valuator.rb @@ -1,5 +1,7 @@ class Valuator < ActiveRecord::Base belongs_to :user, touch: true + belongs_to :valuator_group + delegate :name, :email, :name_and_email, to: :user has_many :valuation_assignments, dependent: :destroy @@ -16,4 +18,9 @@ class Valuator < ActiveRecord::Base def description_or_name description.present? ? description : name end + + def assigned_investment_ids + investment_ids + [valuator_group.try(:investment_ids)].flatten + end + end diff --git a/app/models/valuator_group.rb b/app/models/valuator_group.rb new file mode 100644 index 000000000..c5bf8d29b --- /dev/null +++ b/app/models/valuator_group.rb @@ -0,0 +1,5 @@ +class ValuatorGroup < ActiveRecord::Base + has_many :valuators + has_many :valuator_group_assignments, dependent: :destroy, class_name: 'Budget::ValuatorGroupAssignment' + has_many :investments, through: :valuator_group_assignments, class_name: 'Budget::Investment' +end \ No newline at end of file diff --git a/app/views/admin/budget_investments/_investments.html.erb b/app/views/admin/budget_investments/_investments.html.erb index 4522ce48e..9d52f78d6 100644 --- a/app/views/admin/budget_investments/_investments.html.erb +++ b/app/views/admin/budget_investments/_investments.html.erb @@ -60,10 +60,10 @@ <% end %> - <% if investment.valuators.size.zero? %> + <% if investment.valuators.size == 0 && investment.valuator_groups.size == 0 %> <%= t("admin.budget_investments.index.no_valuators_assigned") %> <% else %> - <%= investment.valuators.collect(&:description_or_name).join(", ") %> + <%= assigned_valuators(investment) %> <% end %> diff --git a/app/views/admin/budget_investments/edit.html.erb b/app/views/admin/budget_investments/edit.html.erb index f750c021b..fc56f88df 100644 --- a/app/views/admin/budget_investments/edit.html.erb +++ b/app/views/admin/budget_investments/edit.html.erb @@ -9,7 +9,7 @@ <%= hidden_field_tag filter_name, filter_value %> <% end %> -
+
<%= f.text_field :title, maxlength: Budget::Investment.title_max_length %>
@@ -26,22 +26,26 @@
- <%= f.text_field :external_url %> -
+
+ <%= f.text_field :external_url %> +
-
- <%= f.select :heading_id, budget_heading_select_options(@budget), include_blank: t("admin.budget_investments.edit.select_heading") %> +
+ <%= f.select :heading_id, budget_heading_select_options(@budget), include_blank: t("admin.budget_investments.edit.select_heading") %> +
-

<%= t("admin.budget_investments.edit.classification") %>

- -
+
- <%= f.select(:administrator_id, - @admins.collect{ |a| [a.name_and_email, a.id ] }, - { include_blank: t("admin.budget_investments.edit.undefined") }) %> +

<%= t("admin.budget_investments.edit.classification") %>

+ +
+ <%= f.select(:administrator_id, + @admins.collect{ |a| [a.name_and_email, a.id ] }, + { include_blank: t("admin.budget_investments.edit.undefined") }) %> +
@@ -59,17 +63,27 @@ class: 'js-tag-list' %>
-
- <%= f.label :valuator_ids, t("admin.budget_investments.edit.assigned_valuators") %> - - <%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> - <%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %> +
+ <%= f.label :valuator_ids, t("admin.budget_investments.edit.user_groups") %> +
    + <%= f.collection_check_boxes :valuator_group_ids, @valuator_groups, :id, :name do |group| %> +
  • <%= group.label(title: group.object.name) { group.check_box + truncate(group.object.name, length: 60) } %>
  • <% end %> +
+
+ +
+
+ <%= f.label :valuator_ids, t("admin.budget_investments.edit.assigned_valuators") %> +
    + <%= f.collection_check_boxes :valuator_ids, @valuators, :id, :email do |b| %> +
  • <%= b.label(title: valuator_label(b.object)) { b.check_box + truncate(b.object.description_or_email, length: 60) } %>
  • + <% end %> +
- -
+
<% if @investment.incompatible? || @investment.winner? %>

<%= t("admin.budget_investments.edit.compatibility") %>

@@ -88,7 +102,7 @@
-
+
<%= f.submit(class: "button", value: t("admin.budget_investments.edit.submit_button")) %>
<% end %> diff --git a/app/views/admin/budget_investments/index.html.erb b/app/views/admin/budget_investments/index.html.erb index 73a06a402..4548e47c0 100644 --- a/app/views/admin/budget_investments/index.html.erb +++ b/app/views/admin/budget_investments/index.html.erb @@ -12,8 +12,8 @@
- <%= select_tag :valuator_id, - options_for_select(valuator_select_options, params[:valuator_id]), + <%= select_tag :valuator_or_group_id, + options_for_select(valuator_or_group_select_options, params[:valuator_or_group_id]), { prompt: t("admin.budget_investments.index.valuator_filter_all"), label: false, class: "js-submit-on-change" } %> diff --git a/app/views/admin/budget_investments/show.html.erb b/app/views/admin/budget_investments/show.html.erb index 939830aff..d7f905080 100644 --- a/app/views/admin/budget_investments/show.html.erb +++ b/app/views/admin/budget_investments/show.html.erb @@ -22,6 +22,15 @@ <%= @investment.tags_on(:valuation).pluck(:name).sort.join(', ') %>

+

+ <%= t("admin.budget_investments.show.valuator_groups") %>: + <% if @investment.valuator_groups.any? %> + <%= @investment.valuator_groups.collect(&:name).join(', ') %> + <% else %> + <%= t("admin.budget_investments.show.undefined") %> + <% end %> +

+

<%= t("admin.budget_investments.show.assigned_valuators") %>: <% if @investment.valuators.any? %> diff --git a/app/views/admin/valuator_groups/_group.html.erb b/app/views/admin/valuator_groups/_group.html.erb new file mode 100644 index 000000000..ea69515f7 --- /dev/null +++ b/app/views/admin/valuator_groups/_group.html.erb @@ -0,0 +1,17 @@ + + + <%= link_to group.name, admin_valuator_group_path(group) %> + + + <%= group.valuators.count %> + + + <%= link_to t("admin.actions.delete"), + admin_valuator_group_path(group), + method: :delete, class: "button hollow alert" %> + + <%= link_to t("admin.actions.edit"), + edit_admin_valuator_group_path(group), + class: "button hollow" %> + + diff --git a/app/views/admin/valuator_groups/_valuator.html.erb b/app/views/admin/valuator_groups/_valuator.html.erb new file mode 100644 index 000000000..8f98a8173 --- /dev/null +++ b/app/views/admin/valuator_groups/_valuator.html.erb @@ -0,0 +1,4 @@ +

  • + <%= link_to valuator.description_or_email, + admin_valuator_path(valuator) %> +
  • \ No newline at end of file diff --git a/app/views/admin/valuator_groups/edit.html.erb b/app/views/admin/valuator_groups/edit.html.erb new file mode 100644 index 000000000..fe57117b6 --- /dev/null +++ b/app/views/admin/valuator_groups/edit.html.erb @@ -0,0 +1,9 @@ +<%= back_link_to admin_valuator_groups_path %> + +
    + <%= form_for [:admin, @group] do |f| %> + <%= f.label :name, t("admin.valuator_groups.form.name") %> + <%= f.text_field :name, label: false %> + <%= f.submit t("admin.valuator_groups.form.edit"), class: "button success" %> + <% end %> +
    \ No newline at end of file diff --git a/app/views/admin/valuator_groups/index.html.erb b/app/views/admin/valuator_groups/index.html.erb new file mode 100644 index 000000000..eada85e25 --- /dev/null +++ b/app/views/admin/valuator_groups/index.html.erb @@ -0,0 +1,24 @@ +

    <%= t("admin.valuator_groups.index.title") %>

    + +<%= link_to t("admin.valuator_groups.index.new"), new_admin_valuator_group_path, class: "button float-right" %> + +<% if @groups.any? %> +

    <%= page_entries_info @groups %>

    + + + + + + + + + <%= render partial: 'group', collection: @groups %> + +
    <%= t("admin.valuator_groups.index.name") %><%= t("admin.valuator_groups.index.members") %><%= t("admin.shared.actions") %>
    + + <%= paginate @groups %> +<% else %> +
    + <%= t("admin.valuator_groups.index.no_groups") %> +
    +<% end %> diff --git a/app/views/admin/valuator_groups/new.html.erb b/app/views/admin/valuator_groups/new.html.erb new file mode 100644 index 000000000..d79f22d85 --- /dev/null +++ b/app/views/admin/valuator_groups/new.html.erb @@ -0,0 +1,9 @@ +<%= back_link_to admin_valuator_groups_path %> + +
    + <%= form_for [:admin, @group] do |f| %> + <%= f.label :name, t("admin.valuator_groups.form.name") %> + <%= f.text_field :name, label: false %> + <%= f.submit t("admin.valuator_groups.form.new"), class: "button success" %> + <% end %> +
    diff --git a/app/views/admin/valuator_groups/show.html.erb b/app/views/admin/valuator_groups/show.html.erb new file mode 100644 index 000000000..f75490c1b --- /dev/null +++ b/app/views/admin/valuator_groups/show.html.erb @@ -0,0 +1,13 @@ +<%= back_link_to admin_valuator_groups_path %> + +

    <%= t("admin.valuator_groups.show.title", group: @group.name) %>

    + +
      + <% if @group.valuators.any? %> + <%= render partial: 'valuator', collection: @group.valuators %> + <% else %> +
      + <%= t("admin.valuator_groups.show.no_valuators") %> +
      + <% end %> +
    diff --git a/app/views/admin/valuators/edit.html.erb b/app/views/admin/valuators/edit.html.erb new file mode 100644 index 000000000..89b583d85 --- /dev/null +++ b/app/views/admin/valuators/edit.html.erb @@ -0,0 +1,20 @@ +<%= back_link_to admin_valuators_path %> + +

    <%= t("admin.valuators.form.edit_title") %>

    + +
    + <%= @valuator.name %>
    + <%= @valuator.email %> +
    + +
    + <%= form_for [:admin, @valuator] do |f| %> + <%= f.text_field :description %> +
    + <%= f.select :valuator_group_id, + @valuator_groups.map {|group| [group.name, group.id] }, + { include_blank: true } %> +
    + <%= f.submit t("admin.valuators.form.update"), class: "button success" %> + <% end %> +
    diff --git a/app/views/admin/valuators/index.html.erb b/app/views/admin/valuators/index.html.erb index dfb93ed80..902067588 100644 --- a/app/views/admin/valuators/index.html.erb +++ b/app/views/admin/valuators/index.html.erb @@ -1,4 +1,6 @@ -

    <%= t("admin.valuators.index.title") %>

    +

    <%= t("admin.valuators.index.title") %>

    + +<%= link_to t("admin.valuators.index.valuator_groups"), admin_valuator_groups_path, class: "button hollow float-right" %> <%= render "admin/shared/user_search", url: search_admin_valuators_path %> @@ -11,12 +13,13 @@ <%= t("admin.valuators.index.name") %> <%= t("admin.valuators.index.email") %> <%= t("admin.valuators.index.description") %> + <%= t("admin.valuators.index.group") %> <%= t("admin.actions.actions") %> <% @valuators.each do |valuator| %> - <%= valuator.name %> + <%= link_to valuator.name, admin_valuator_path(valuator) %> <%= valuator.email %> <% if valuator.description.present? %> @@ -26,10 +29,20 @@ <% end %> + <% if valuator.valuator_group.present? %> + <%= valuator.valuator_group.try(:name) %> + <% else %> + <%= t("admin.valuators.index.no_group") %> + <% end %> + + + <%= link_to t("admin.actions.edit"), + edit_admin_valuator_path(valuator), + class: "button hollow" %> <%= link_to t("admin.valuators.valuator.delete"), admin_valuator_path(valuator), method: :delete, - class: "button hollow alert expanded" %> + class: "button hollow alert" %> <% end %> diff --git a/app/views/admin/valuators/search.html.erb b/app/views/admin/valuators/search.html.erb index b383e554d..93907ceb9 100644 --- a/app/views/admin/valuators/search.html.erb +++ b/app/views/admin/valuators/search.html.erb @@ -30,17 +30,19 @@ <% end %> <% if user.valuator? %> + <%= link_to t("admin.actions.edit"), + edit_admin_valuator_path(user.valuator), + class: "button hollow" %> + <%= link_to t("admin.valuators.valuator.delete"), admin_valuator_path(user), method: :delete, class: "button hollow alert expanded" %> <% else %> <%= form_for Valuator.new(user: user), url: admin_valuators_path do |f| %> - <%= f.text_field :description, - label: false, - placeholder: t("admin.valuators.valuator.description_placeholder") %> <%= f.hidden_field :user_id %> - <%= f.submit t("admin.valuators.valuator.add"), class: "button success expanded" %> + <%= f.submit t("admin.valuators.valuator.add"), + class: "button success expanded" %> <% end %> <% end %> diff --git a/app/views/admin/valuators/show.html.erb b/app/views/admin/valuators/show.html.erb new file mode 100644 index 000000000..f1768c42f --- /dev/null +++ b/app/views/admin/valuators/show.html.erb @@ -0,0 +1,30 @@ +<%= back_link_to admin_valuators_path %> + +<%= link_to t("admin.actions.edit"), edit_admin_valuator_path(@valuator), class: "button hollow float-right" %> + +
    + +

    <%= @valuator.name %>

    + +
    +

    + <%= t("admin.valuators.show.email") %>
    + <%= @valuator.email %> +

    +

    + <%= t("admin.valuators.show.description") %>
    + <% if @valuator.description.present? %> + <%= @valuator.description %> + <% else %> + <%= t("admin.valuators.show.no_description") %> + <% end %> +

    +

    + <%= t("admin.valuators.show.group") %>
    + <% if @valuator.valuator_group.present? %> + <%= @valuator.valuator_group.try(:name) %> + <% else %> + <%= t("admin.valuators.show.no_group") %> + <% end %> +

    +
    diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index f2a7c41a3..41bf3e604 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -42,6 +42,7 @@ data: - config/locales/%{locale}/documents.yml - config/locales/%{locale}/images.yml - config/locales/%{locale}/guides.yml + - config/locales/%{locale}/user_groups.yml # Locale files to write new keys to, based on a list of key pattern => file rules. Matched from top to bottom: # `i18n-tasks normalize -p` will force move the keys according to these rules diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index 765f92932..2d5163cb0 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -32,8 +32,11 @@ en: one: "Administrator" other: "Administrators" valuator: - one: "Evaluador" - other: "Evaluadores" + one: "Valuator" + other: "Valuators" + valuator_group: + one: "Valuator group" + other: "Valuator groups" manager: one: "Manager" other: "Managers" diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 97d00be77..f85d6a8c8 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -13,6 +13,7 @@ en: unmark_featured: Unmark featured edit: Edit configure: Configure + delete: Delete banners: index: title: Banners @@ -176,7 +177,6 @@ en: undecided: "Undecided" selected: "Selected" select: "Select" - download_current_selection: "Download current selection" table_id: "ID" table_title: "Title" table_supports: "Supports" @@ -223,6 +223,7 @@ en: documents: "Documents" see_documents: "See documents (%{count})" no_documents: "Without documents" + valuator_groups: "Valuator Groups" edit: classification: Classification compatibility: Compatibility @@ -236,6 +237,7 @@ en: tags: Tags tags_placeholder: "Write the tags you want separated by commas (,)" undefined: Undefined + user_groups: "Groups" search_unfeasible: Search unfeasible milestones: index: @@ -581,8 +583,10 @@ en: description: Description no_description: No description no_valuators: There are no valuators. + valuator_groups: "Valuator Groups" + group: "Group" + no_group: "No group" valuator: - description_placeholder: 'Description (optional)' add: Add to valuators delete: Delete search: @@ -596,6 +600,30 @@ en: in_evaluation_count: In evaluation total_count: Total cost: Cost + form: + edit_title: "Valuators: Edit valuator" + update: "Update valuator" + updated: "Valuator updated successfully" + show: + description: "Description" + email: "Email" + group: "Group" + no_description: "Without description" + no_group: "Without group" + valuator_groups: + index: + title: "Valuator groups" + new: "Create valuators group" + name: "Name" + members: "Members" + no_groups: "There are no valuator groups" + show: + title: "Valuators group: %{group}" + no_valuators: "There are no valuators assigned to this group" + form: + name: "Group name" + new: "Create valuators group" + edit: "Save valuators group" poll_officers: index: title: Poll officers diff --git a/config/locales/en/responders.yml b/config/locales/en/responders.yml index cc6d58bb0..f91cb807c 100644 --- a/config/locales/en/responders.yml +++ b/config/locales/en/responders.yml @@ -16,6 +16,7 @@ en: budget_investment: "Budget Investment created successfully." signature_sheet: "Signature sheet created successfully" topic: "Topic created successfully." + valuator_group: "Valuator group created successfully" save_changes: notice: Changes saved update: @@ -27,9 +28,11 @@ en: spending_proposal: "Investment project updated succesfully." budget_investment: "Investment project updated succesfully." topic: "Topic updated successfully." + valuator_group: "Valuator group updated successfully" destroy: spending_proposal: "Spending proposal deleted succesfully." budget_investment: "Investment project deleted succesfully." error: "Could not delete" topic: "Topic deleted successfully." poll_question_answer_video: "Answer video deleted successfully." + valuator_group: "Valuator group deleted successfully" diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index 9e195bd25..d3a0c776a 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -34,6 +34,9 @@ es: valuator: one: "Evaluador" other: "Evaluadores" + valuator_group: + one: "Grupo de Evaluadores" + other: "Grupos de Evaluadores" manager: one: "Gestor" other: "Gestores" diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index af2ee9511..64e7dafd0 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -13,6 +13,7 @@ es: unmark_featured: Quitar destacado edit: Editar configure: Configurar + delete: Borrar banners: index: title: Banners @@ -222,6 +223,7 @@ es: documents: "Documentos" see_documents: "Ver documentos (%{count})" no_documents: "Sin documentos" + valuator_groups: "Grupos de evaluadores" edit: classification: Clasificación compatibility: Compatibilidad @@ -235,6 +237,7 @@ es: tags: Etiquetas tags_placeholder: "Escribe las etiquetas que desees separadas por comas (,)" undefined: Sin definir + user_groups: "Grupos" search_unfeasible: Buscar inviables milestones: index: @@ -580,8 +583,10 @@ es: description: Descripción no_description: Sin descripción no_valuators: No hay evaluadores. + valuator_groups: "Grupo de evaluadores" + group: "Grupo" + no_group: "Sin grupo" valuator: - description_placeholder: 'Descripción (opcional)' add: Añadir como evaluador delete: Borrar search: @@ -595,6 +600,30 @@ es: in_evaluation_count: En evaluación total_count: Total cost: Coste total + form: + edit_title: "Evaluadores: Editar evaluador" + update: "Actualizar evaluador" + updated: "Evaluador actualizado correctamente" + show: + description: "Descripción" + email: "Email" + group: "Grupo" + no_description: "Sin descripción" + no_group: "Sin grupo" + valuator_groups: + index: + title: "Grupos de evaluadores" + new: "Crear grupo de evaluadores" + name: "Nombre" + members: "Miembros" + no_groups: "No hay grupos de evaluadores" + show: + title: "Grupo de evaluadores: %{group}" + no_valuators: "No hay evaluadores asigandos a este grupo" + form: + name: "Nombre del grupo" + new: "Crear grupo de evaluadores" + edit: "Guardar grupo de evaluadores" poll_officers: index: title: Presidentes de mesa diff --git a/config/locales/es/responders.yml b/config/locales/es/responders.yml index 006bcab2d..3674a0290 100644 --- a/config/locales/es/responders.yml +++ b/config/locales/es/responders.yml @@ -16,6 +16,7 @@ es: budget_investment: "Proyecto de gasto creado correctamente." signature_sheet: "Hoja de firmas creada correctamente" topic: "Tema creado correctamente." + valuator_group: "Grupo de evaluadores creado correctamente" save_changes: notice: Cambios guardados update: @@ -27,9 +28,11 @@ es: spending_proposal: "Propuesta de inversión actualizada correctamente." budget_investment: "Proyecto de gasto actualizado correctamente" topic: "Tema actualizado correctamente." + valuator_group: "Grupo de evaluadores actualizado correctamente" destroy: spending_proposal: "Propuesta de inversión eliminada." budget_investment: "Proyecto de gasto eliminado." error: "No se pudo borrar" topic: "Tema eliminado." poll_question_answer_video: "Vídeo de respuesta eliminado." + valuator_group: "Grupo de evaluadores eliminado correctamente" diff --git a/config/locales/fr/admin.yml b/config/locales/fr/admin.yml index b9cdfcfd3..7c2d63e03 100644 --- a/config/locales/fr/admin.yml +++ b/config/locales/fr/admin.yml @@ -246,7 +246,6 @@ fr: index: title: Évaluateurs valuator: - description_placeholder: 'Description (optionnel)' user_found: Utilisateur trouvé add: Ajouter un évaluateur search: diff --git a/config/locales/he/admin.yml b/config/locales/he/admin.yml index 35700ec03..c5cbdf9ac 100644 --- a/config/locales/he/admin.yml +++ b/config/locales/he/admin.yml @@ -179,7 +179,6 @@ he: index: title: Valuators valuator: - description_placeholder: 'Description (optional)' add: Add to valuators summary: title: Valuator summary for investment projects diff --git a/config/locales/nl/admin.yml b/config/locales/nl/admin.yml index 8a30b0d21..5dcb86fe6 100644 --- a/config/locales/nl/admin.yml +++ b/config/locales/nl/admin.yml @@ -246,7 +246,6 @@ nl: index: title: Valuators valuator: - description_placeholder: 'Description (optional)' user_found: User found add: Add to valuators search: diff --git a/config/locales/val/admin.yml b/config/locales/val/admin.yml index d0def6788..88e29079e 100644 --- a/config/locales/val/admin.yml +++ b/config/locales/val/admin.yml @@ -501,7 +501,6 @@ val: no_description: Sense descripció no_valuators: No hi ha avaluadors. valuator: - description_placeholder: 'Descripció (opcional)' add: Afegir com a avaluador delete: Borrar search: diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 384fb685c..6bf380f0c 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -80,10 +80,11 @@ namespace :admin do get :search, on: :collection end - resources :valuators, only: [:index, :create, :destroy] do + resources :valuators, only: [:show, :index, :edit, :update, :create, :destroy] do get :search, on: :collection get :summary, on: :collection end + resources :valuator_groups resources :managers, only: [:index, :create, :destroy] do get :search, on: :collection diff --git a/db/migrate/20180208151658_create_valuator_groups.rb b/db/migrate/20180208151658_create_valuator_groups.rb new file mode 100644 index 000000000..441478cc5 --- /dev/null +++ b/db/migrate/20180208151658_create_valuator_groups.rb @@ -0,0 +1,7 @@ +class CreateValuatorGroups < ActiveRecord::Migration + def change + create_table :valuator_groups do |t| + t.string :name + end + end +end diff --git a/db/migrate/20180208163135_add_valuator_group_to_valuators.rb b/db/migrate/20180208163135_add_valuator_group_to_valuators.rb new file mode 100644 index 000000000..93ec65e17 --- /dev/null +++ b/db/migrate/20180208163135_add_valuator_group_to_valuators.rb @@ -0,0 +1,5 @@ +class AddValuatorGroupToValuators < ActiveRecord::Migration + def change + add_column :valuators, :valuator_group_id, :integer + end +end diff --git a/db/migrate/20180208200659_create_budget_valuator_group_assignment.rb b/db/migrate/20180208200659_create_budget_valuator_group_assignment.rb new file mode 100644 index 000000000..916ed298e --- /dev/null +++ b/db/migrate/20180208200659_create_budget_valuator_group_assignment.rb @@ -0,0 +1,8 @@ +class CreateBudgetValuatorGroupAssignment < ActiveRecord::Migration + def change + create_table :budget_valuator_group_assignments do |t| + t.integer :valuator_group_id + t.integer :investment_id + end + end +end diff --git a/db/migrate/20180211182635_add_budget_valuator_group_assignments_counters.rb b/db/migrate/20180211182635_add_budget_valuator_group_assignments_counters.rb new file mode 100644 index 000000000..93619a5a9 --- /dev/null +++ b/db/migrate/20180211182635_add_budget_valuator_group_assignments_counters.rb @@ -0,0 +1,6 @@ +class AddBudgetValuatorGroupAssignmentsCounters < ActiveRecord::Migration + def change + add_column :budget_investments, :valuator_group_assignments_count, :integer, default: 0 + add_column :valuator_groups, :budget_investments_count, :integer, default: 0 + end +end diff --git a/db/schema.rb b/db/schema.rb index a85b3a0dc..5a83bebe6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -133,35 +133,36 @@ ActiveRecord::Schema.define(version: 20180320104823) do t.string "title" t.text "description" t.string "external_url" - t.integer "price", limit: 8 - t.string "feasibility", limit: 15, default: "undecided" + t.integer "price", limit: 8 + t.string "feasibility", limit: 15, default: "undecided" t.text "price_explanation" t.text "unfeasibility_explanation" - t.boolean "valuation_finished", default: false - t.integer "valuator_assignments_count", default: 0 - t.integer "price_first_year", limit: 8 + t.boolean "valuation_finished", default: false + t.integer "valuator_assignments_count", default: 0 + t.integer "price_first_year", limit: 8 t.string "duration" t.datetime "hidden_at" - t.integer "cached_votes_up", default: 0 - t.integer "comments_count", default: 0 - t.integer "confidence_score", default: 0, null: false - t.integer "physical_votes", default: 0 + t.integer "cached_votes_up", default: 0 + t.integer "comments_count", default: 0 + t.integer "confidence_score", default: 0, null: false + t.integer "physical_votes", default: 0 t.tsvector "tsv" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "heading_id" t.string "responsible_name" t.integer "budget_id" t.integer "group_id" - t.boolean "selected", default: false + t.boolean "selected", default: false t.string "location" t.string "organization_name" t.datetime "unfeasible_email_sent_at" - t.integer "ballot_lines_count", default: 0 + t.integer "ballot_lines_count", default: 0 t.integer "previous_heading_id" - t.boolean "winner", default: false - t.boolean "incompatible", default: false + t.boolean "winner", default: false + t.boolean "incompatible", default: false t.integer "community_id" + t.integer "valuator_group_assignments_count", default: 0 end add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree @@ -203,6 +204,11 @@ ActiveRecord::Schema.define(version: 20180320104823) do add_index "budget_valuator_assignments", ["investment_id"], name: "index_budget_valuator_assignments_on_investment_id", using: :btree + create_table "budget_valuator_group_assignments", force: :cascade do |t| + t.integer "valuator_group_id" + t.integer "investment_id" + end + create_table "budgets", force: :cascade do |t| t.string "name", limit: 80 t.string "currency_symbol", limit: 10 @@ -1128,11 +1134,17 @@ ActiveRecord::Schema.define(version: 20180320104823) do t.datetime "updated_at", null: false end + create_table "valuator_groups", force: :cascade do |t| + t.string "name" + t.integer "budget_investments_count", default: 0 + end + create_table "valuators", force: :cascade do |t| t.integer "user_id" t.string "description" t.integer "spending_proposals_count", default: 0 t.integer "budget_investments_count", default: 0 + t.integer "valuator_group_id" end add_index "valuators", ["user_id"], name: "index_valuators_on_user_id", using: :btree diff --git a/spec/factories.rb b/spec/factories.rb index e9f79242c..05ddd2fc0 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -61,6 +61,9 @@ FactoryBot.define do end end + factory :valuator_group, class: ValuatorGroup do + end + factory :identity do user nil provider "Twitter" diff --git a/spec/features/admin/budget_investments_spec.rb b/spec/features/admin/budget_investments_spec.rb index 9eb548c30..9a44249b4 100644 --- a/spec/features/admin/budget_investments_spec.rb +++ b/spec/features/admin/budget_investments_spec.rb @@ -54,7 +54,7 @@ feature 'Admin budget investments' do end end - scenario 'Displaying assignments info' do + scenario 'Display admin and valuator assignments' do budget_investment1 = create(:budget_investment, budget: budget) budget_investment2 = create(:budget_investment, budget: budget) budget_investment3 = create(:budget_investment, budget: budget) @@ -86,6 +86,33 @@ feature 'Admin budget investments' do end end + scenario 'Display valuator group assignments' do + budget_investment1 = create(:budget_investment, budget: budget) + budget_investment2 = create(:budget_investment, budget: budget) + budget_investment3 = create(:budget_investment, budget: budget) + + health_group = create(:valuator_group, name: "Health") + culture_group = create(:valuator_group, name: "Culture") + + budget_investment1.valuator_groups << health_group + budget_investment2.valuator_group_ids = [health_group.id, culture_group.id] + + visit admin_budget_budget_investments_path(budget_id: budget) + + within("#budget_investment_#{budget_investment1.id}") do + expect(page).to have_content("Health") + end + + within("#budget_investment_#{budget_investment2.id}") do + expect(page).to have_content("Health") + expect(page).to have_content("Culture") + end + + within("#budget_investment_#{budget_investment3.id}") do + expect(page).to have_content("No valuators assigned") + end + end + scenario "Filtering by budget heading", :js do group1 = create(:budget_group, name: "Streets", budget: budget) group2 = create(:budget_group, name: "Parks", budget: budget) @@ -171,24 +198,57 @@ feature 'Admin budget investments' do expect(page).to have_link("Realocate visitors") expect(page).to have_link("Destroy the city") - select "Valuator 1", from: "valuator_id" + select "Valuator 1", from: "valuator_or_group_id" expect(page).to have_content('There is 1 investment') expect(page).not_to have_link("Destroy the city") expect(page).to have_link("Realocate visitors") - select "All valuators", from: "valuator_id" + select "All valuators", from: "valuator_or_group_id" expect(page).to have_content('There are 2 investments') expect(page).to have_link("Destroy the city") expect(page).to have_link("Realocate visitors") - select "Valuator 1", from: "valuator_id" + select "Valuator 1", from: "valuator_or_group_id" expect(page).to have_content('There is 1 investment') expect(page).not_to have_link("Destroy the city") expect(page).to have_link("Realocate visitors") end + scenario "Filtering by valuator group", :js do + user = create(:user) + health_group = create(:valuator_group, name: "Health") + culture_group = create(:valuator_group, name: "Culture") + + budget_investment1 = create(:budget_investment, title: "Build a hospital", budget: budget) + budget_investment1.valuator_groups << health_group + + budget_investment2 = create(:budget_investment, title: "Build a theatre", budget: budget) + budget_investment2.valuator_groups << culture_group + + visit admin_budget_budget_investments_path(budget_id: budget) + expect(page).to have_link("Build a hospital") + expect(page).to have_link("Build a theatre") + + select "Health", from: "valuator_or_group_id" + + expect(page).to have_content('There is 1 investment') + expect(page).to have_link("Build a hospital") + expect(page).not_to have_link("Build a theatre") + + select "All valuators", from: "valuator_or_group_id" + + expect(page).to have_content('There are 2 investments') + expect(page).to have_link("Build a hospital") + expect(page).to have_link("Build a theatre") + + select "Culture", from: "valuator_or_group_id" + expect(page).to have_content('There is 1 investment') + expect(page).to have_link("Build a theatre") + expect(page).not_to have_link("Build a hospital") + end + scenario "Current filter is properly highlighted" do filters_links = { 'all' => 'All', 'without_admin' => 'Without assigned admin', @@ -579,6 +639,33 @@ feature 'Admin budget investments' do end end + scenario "Add valuator group" do + budget_investment = create(:budget_investment) + + health_group = create(:valuator_group, name: "Health") + economy_group = create(:valuator_group, name: "Economy") + culture_group = create(:valuator_group, name: "Culture") + + visit admin_budget_budget_investment_path(budget_investment.budget, budget_investment) + click_link 'Edit classification' + + check "budget_investment_valuator_group_ids_#{health_group.id}" + check "budget_investment_valuator_group_ids_#{culture_group.id}" + + click_button 'Update' + + expect(page).to have_content 'Investment project updated succesfully.' + + within('#assigned_valuator_groups') do + expect(page).to have_content('Health') + expect(page).to have_content('Culture') + expect(page).not_to have_content('Undefined') + expect(page).not_to have_content('Economy') + end + end + + pending "Do not display valuators of an assigned group" + scenario "Adds existing valuation tags", :js do budget_investment1 = create(:budget_investment) budget_investment1.set_tag_list_on(:valuation, 'Education, Health') diff --git a/spec/features/admin/valuator_groups_spec.rb b/spec/features/admin/valuator_groups_spec.rb new file mode 100644 index 000000000..c939922a4 --- /dev/null +++ b/spec/features/admin/valuator_groups_spec.rb @@ -0,0 +1,126 @@ +require 'rails_helper' + +feature "Valuator groups" do + + let(:admin) { create(:administrator).user } + + background do + login_as(admin) + end + + scenario "Index" do + group1 = create(:valuator_group) + group2 = create(:valuator_group) + 3.times { create(:valuator, valuator_group: group1) } + + visit admin_valuator_groups_path + + within("#valuator_group_#{group1.id}") do + expect(page).to have_content group1.name + expect(page).to have_content 3 + end + + within("#valuator_group_#{group2.id}") do + expect(page).to have_content group2.name + expect(page).to have_content 0 + end + end + + scenario "Show" do + group = create(:valuator_group) + valuator1 = create(:valuator, valuator_group: group) + valuator2 = create(:valuator, valuator_group: group) + valuator3 = create(:valuator, valuator_group: nil) + + visit admin_valuator_group_path(group) + + expect(page).to have_content group.name + + within("#valuators") do + expect(page).to have_link(valuator1.email, href: admin_valuator_path(valuator1)) + expect(page).to have_link(valuator2.email, href: admin_valuator_path(valuator2)) + end + end + + scenario "Create" do + visit admin_valuators_path + + click_link "Valuator Groups" + click_link "Create valuators group" + + fill_in "valuator_group_name", with: "Health" + click_button "Create valuators group" + + expect(page).to have_content "Valuator group created successfully" + expect(page).to have_content "There is 1 valuator group" + expect(page).to have_content "Health" + end + + scenario "Update" do + group = create(:valuator_group, name: "Health") + + visit admin_valuator_groups_path + click_link "Edit" + + fill_in "valuator_group_name", with: "Health and Sports" + click_button "Save valuators group" + + expect(page).to have_content "Valuator group updated successfully" + expect(page).to have_content "Health and Sports" + end + + scenario "Delete" do + group = create(:valuator_group) + + visit admin_valuator_groups_path + click_link "Delete" + + expect(page).to have_content "Valuator group deleted successfully" + expect(page).to have_content "There are no valuator groups" + end + + context "Assign valuators to groups" do + + scenario "Add a valuator to a group" do + valuator = create(:valuator) + group = create(:valuator_group, name: "Health") + + visit edit_admin_valuator_path(valuator) + + select "Health", from: "valuator_valuator_group_id" + click_button "Update valuator" + + expect(page).to have_content "Valuator updated successfully" + expect(page).to have_content "Health" + end + + scenario "Update a valuator's group" do + valuator = create(:valuator) + group1 = create(:valuator_group, name: "Health") + group2 = create(:valuator_group, name: "Economy") + valuator.update(valuator_group: group1) + + visit edit_admin_valuator_path(valuator) + select "Economy", from: "valuator_valuator_group_id" + click_button "Update valuator" + + expect(page).to have_content "Valuator updated successfully" + expect(page).to have_content "Economy" + end + + scenario "Remove a valuator from a group" do + valuator = create(:valuator) + group1 = create(:valuator_group, name: "Health") + valuator.update(valuator_group: group1) + + visit edit_admin_valuator_path(valuator) + select "", from: "valuator_valuator_group_id" + click_button "Update valuator" + + expect(page).to have_content "Valuator updated successfully" + expect(page).to_not have_content "Health" + end + + end + +end \ No newline at end of file diff --git a/spec/features/admin/valuators_spec.rb b/spec/features/admin/valuators_spec.rb index 25ae57a12..ba6792b49 100644 --- a/spec/features/admin/valuators_spec.rb +++ b/spec/features/admin/valuators_spec.rb @@ -1,6 +1,7 @@ require 'rails_helper' feature 'Admin valuators' do + background do @admin = create(:administrator) @user = create(:user, username: 'Jose Luis Balbin') @@ -9,27 +10,44 @@ feature 'Admin valuators' do visit admin_valuators_path end + scenario "Show" do + visit admin_valuator_path(@valuator) + + expect(page).to have_content @valuator.name + expect(page).to have_content @valuator.description + expect(page).to have_content @valuator.email + end + scenario 'Index' do expect(page).to have_content(@valuator.name) expect(page).to have_content(@valuator.email) expect(page).not_to have_content(@user.name) end - scenario 'Create Valuator', :js do + scenario 'Create', :js do fill_in 'name_or_email', with: @user.email click_button 'Search' expect(page).to have_content(@user.name) - fill_in 'valuator_description', with: 'environmental expert' click_button 'Add to valuators' within('#valuators') do expect(page).to have_content(@user.name) - expect(page).to have_content('environmental expert') end end - scenario 'Delete Valuator' do + scenario "Edit" do + visit edit_admin_valuator_path(@valuator) + + fill_in 'valuator_description', with: 'Valuator for health' + click_button "Update valuator" + + expect(page).to have_content "Valuator updated successfully" + expect(page).to have_content @valuator.email + expect(page).to have_content "Valuator for health" + end + + scenario 'Destroy' do click_link 'Delete' within('#valuators') do diff --git a/spec/models/abilities/valuator_spec.rb b/spec/models/abilities/valuator_spec.rb index 41c885421..3b40457b8 100644 --- a/spec/models/abilities/valuator_spec.rb +++ b/spec/models/abilities/valuator_spec.rb @@ -6,12 +6,18 @@ describe Abilities::Valuator do let(:user) { valuator.user } let(:valuator) { create(:valuator) } + let(:group) { create(:valuator_group) } let(:non_assigned_investment) { create(:budget_investment) } let(:assigned_investment) { create(:budget_investment, budget: create(:budget, phase: 'valuating')) } + let(:group_assigned_investment) { create(:budget_investment, budget: create(:budget, phase: 'valuating')) } let(:finished_assigned_investment) { create(:budget_investment, budget: create(:budget, phase: 'finished')) } before do assigned_investment.valuators << valuator + + group_assigned_investment.valuator_groups << group + valuator.update(valuator_group: group) + finished_assigned_investment.valuators << valuator end @@ -31,6 +37,9 @@ describe Abilities::Valuator do it { should be_able_to(:update, assigned_investment) } it { should be_able_to(:valuate, assigned_investment) } + it { should be_able_to(:update, group_assigned_investment) } + it { should be_able_to(:valuate, group_assigned_investment) } + it { should_not be_able_to(:update, finished_assigned_investment) } it { should_not be_able_to(:valuate, finished_assigned_investment) } end diff --git a/spec/models/budget/investment_spec.rb b/spec/models/budget/investment_spec.rb index cdee81087..5e0a24487 100644 --- a/spec/models/budget/investment_spec.rb +++ b/spec/models/budget/investment_spec.rb @@ -349,6 +349,20 @@ describe Budget::Investment do expect(valuating.size).to eq(1) expect(valuating.first).to eq(investment2) end + + it "returns all investments with assigned valuator groups but valuation not finished" do + investment1 = create(:budget_investment) + investment2 = create(:budget_investment) + investment3 = create(:budget_investment, valuation_finished: true) + + investment2.valuator_groups << create(:valuator_group) + investment3.valuator_groups << create(:valuator_group) + + valuating = described_class.valuating + + expect(valuating.size).to eq(1) + expect(valuating.first).to eq(investment2) + end end describe "valuation_finished" do diff --git a/spec/models/valuator_spec.rb b/spec/models/valuator_spec.rb index c905bd376..7f2ffecfa 100644 --- a/spec/models/valuator_spec.rb +++ b/spec/models/valuator_spec.rb @@ -15,4 +15,39 @@ describe Valuator do expect(valuator.description_or_email).to eq(valuator.email) end end + + describe "#assigned_investment_ids" do + + it "returns investments assigned to a valuator" do + valuator = create(:valuator) + investment1 = create(:budget_investment) + investment2 = create(:budget_investment) + investment3 = create(:budget_investment) + + investment1.valuators << valuator + investment2.valuators << valuator + + assigned_investment_ids = valuator.assigned_investment_ids + expect(assigned_investment_ids).to include investment1.id + expect(assigned_investment_ids).to include investment2.id + expect(assigned_investment_ids).to_not include investment3.id + end + + it "returns investments assigned to a valuator group" do + group = create(:valuator_group) + valuator = create(:valuator, valuator_group: group) + + investment1 = create(:budget_investment) + investment2 = create(:budget_investment) + investment3 = create(:budget_investment) + + investment1.valuator_groups << group + investment2.valuator_groups << group + + assigned_investment_ids = valuator.assigned_investment_ids + expect(assigned_investment_ids).to include investment1.id + expect(assigned_investment_ids).to include investment2.id + expect(assigned_investment_ids).to_not include investment3.id + end + end end