diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 98e378e69..aa27109d9 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -40,6 +40,7 @@
//= require advanced_search
//= require registration_form
//= require suggest
+//= require forms
var initialize_modules = function() {
App.Comments.initialize();
@@ -55,6 +56,7 @@ var initialize_modules = function() {
App.AdvancedSearch.initialize();
App.RegistrationForm.initialize();
App.Suggest.initialize();
+ App.Forms.initialize();
};
$(function(){
diff --git a/app/assets/javascripts/forms.js.coffee b/app/assets/javascripts/forms.js.coffee
new file mode 100644
index 000000000..a7d26cc02
--- /dev/null
+++ b/app/assets/javascripts/forms.js.coffee
@@ -0,0 +1,12 @@
+App.Forms =
+
+ initialize: ->
+ $('.js-submit-on-change').unbind('change').on('change', ->
+ $(this).closest('form').submit()
+ false
+ )
+
+ $('.js-toggle-link').unbind('click').on('click', ->
+ $($(this).data('toggle-selector')).toggle("down")
+ false
+ )
diff --git a/app/assets/javascripts/stat_graphs.js b/app/assets/javascripts/stat_graphs.js
index e21d88ff0..c5bc5b538 100644
--- a/app/assets/javascripts/stat_graphs.js
+++ b/app/assets/javascripts/stat_graphs.js
@@ -8,7 +8,6 @@ var initialize_stats_modules = function() {
};
$(function(){
-
$(document).ready(initialize_stats_modules);
$(document).on('page:load', initialize_stats_modules);
$(document).on('ajax:complete', initialize_stats_modules);
diff --git a/app/controllers/admin/spending_proposals_controller.rb b/app/controllers/admin/spending_proposals_controller.rb
index 559a7afda..b758bd10d 100644
--- a/app/controllers/admin/spending_proposals_controller.rb
+++ b/app/controllers/admin/spending_proposals_controller.rb
@@ -1,27 +1,27 @@
class Admin::SpendingProposalsController < Admin::BaseController
include FeatureFlags
-
- has_filters %w{unresolved accepted rejected}, only: :index
+ feature_flag :spending_proposals
load_and_authorize_resource
- feature_flag :spending_proposals
-
def index
- @spending_proposals = @spending_proposals.includes([:geozone]).send(@current_filter).order(created_at: :desc).page(params[:page])
+ @spending_proposals = @spending_proposals.includes([:geozone], [administrator: :user]).order(created_at: :desc).page(params[:page])
end
def show
+ @admins = Administrator.includes(:user).all
+ @valuators = Valuator.includes(:user).all.order("users.username ASC")
end
- def accept
- @spending_proposal.accept
- redirect_to request.query_parameters.merge(action: :index)
+ def assign_admin
+ @spending_proposal.update(params.require(:spending_proposal).permit(:administrator_id))
+ render nothing: true
end
- def reject
- @spending_proposal.reject
- redirect_to request.query_parameters.merge(action: :index)
+ def assign_valuators
+ params[:spending_proposal] ||= {}
+ params[:spending_proposal][:valuator_ids] ||= []
+ @spending_proposal.update(params.require(:spending_proposal).permit(valuator_ids: []))
end
end
diff --git a/app/models/spending_proposal.rb b/app/models/spending_proposal.rb
index c023f83f4..6339fd545 100644
--- a/app/models/spending_proposal.rb
+++ b/app/models/spending_proposal.rb
@@ -4,10 +4,11 @@ class SpendingProposal < ActiveRecord::Base
apply_simple_captcha
- RESOLUTIONS = ["accepted", "rejected"]
-
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :geozone
+ belongs_to :administrator
+ has_many :valuation_assignments, dependent: :destroy
+ has_many :valuators, through: :valuation_assignments
validates :title, presence: true
validates :author, presence: true
@@ -15,42 +16,10 @@ class SpendingProposal < ActiveRecord::Base
validates :title, length: { in: 4..SpendingProposal.title_max_length }
validates :description, length: { maximum: SpendingProposal.description_max_length }
- validates :resolution, inclusion: { in: RESOLUTIONS, allow_nil: true }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
- scope :accepted, -> { where(resolution: "accepted") }
- scope :rejected, -> { where(resolution: "rejected") }
- scope :unresolved, -> { where(resolution: nil) }
-
- def accept
- update_attribute(:resolution, "accepted")
- end
-
- def reject
- update_attribute(:resolution, "rejected")
- end
-
- def accepted?
- resolution == "accepted"
- end
-
- def rejected?
- resolution == "rejected"
- end
-
- def unresolved?
- resolution.blank?
- end
-
- def legality
- case legal
- when true
- "legal"
- when false
- "not_legal"
- else
- "undefined"
- end
+ def description
+ super.try :html_safe
end
def feasibility
@@ -64,8 +33,4 @@ class SpendingProposal < ActiveRecord::Base
end
end
- def description
- super.try :html_safe
- end
-
end
diff --git a/app/models/valuation_assignment.rb b/app/models/valuation_assignment.rb
new file mode 100644
index 000000000..c26b7087f
--- /dev/null
+++ b/app/models/valuation_assignment.rb
@@ -0,0 +1,4 @@
+class ValuationAssignment < ActiveRecord::Base
+ belongs_to :valuator
+ belongs_to :spending_proposal
+end
diff --git a/app/models/valuator.rb b/app/models/valuator.rb
index c513e997e..9e18d2cca 100644
--- a/app/models/valuator.rb
+++ b/app/models/valuator.rb
@@ -2,5 +2,8 @@ class Valuator < ActiveRecord::Base
belongs_to :user, touch: true
delegate :name, :email, to: :user
+ has_many :valuation_assignments, dependent: :destroy
+ has_many :spending_proposals, through: :valuation_assignments
+
validates :user_id, presence: true, uniqueness: true
end
diff --git a/app/views/admin/spending_proposals/_assigned_valuators.html.erb b/app/views/admin/spending_proposals/_assigned_valuators.html.erb
new file mode 100644
index 000000000..09e144dcd
--- /dev/null
+++ b/app/views/admin/spending_proposals/_assigned_valuators.html.erb
@@ -0,0 +1,9 @@
+
+ <% @spending_proposal.valuators.each do |valuator| %>
+ - <%= valuator.name %> (<%= valuator.email %>)
+ <% end %>
+
+ <% if @spending_proposal.valuators.empty? %>
+ - <%= t("admin.spending_proposals.show.undefined") %>
+ <% end %>
+
\ No newline at end of file
diff --git a/app/views/admin/spending_proposals/assign_valuators.js.coffee b/app/views/admin/spending_proposals/assign_valuators.js.coffee
new file mode 100644
index 000000000..afe581e59
--- /dev/null
+++ b/app/views/admin/spending_proposals/assign_valuators.js.coffee
@@ -0,0 +1 @@
+$('#assigned_valuators').html("<%= j(render 'assigned_valuators') %>")
\ No newline at end of file
diff --git a/app/views/admin/spending_proposals/index.html.erb b/app/views/admin/spending_proposals/index.html.erb
index 2b8cb639e..a0ed583cc 100644
--- a/app/views/admin/spending_proposals/index.html.erb
+++ b/app/views/admin/spending_proposals/index.html.erb
@@ -1,7 +1,5 @@
<%= t("admin.spending_proposals.index.title") %>
-<%= render 'shared/filter_subnav', i18n_namespace: "admin.spending_proposals.index" %>
-
<%= page_entries_info @spending_proposals %>
@@ -14,22 +12,6 @@
|
<%= geozone_name(spending_proposal) %>
|
-
- <% unless spending_proposal.accepted? %>
- <%= link_to t("admin.spending_proposals.actions.accept"),
- accept_admin_spending_proposal_path(spending_proposal, request.query_parameters),
- method: :put,
- data: { confirm: t("admin.actions.confirm") },
- class: "button radius tiny success no-margin" %>
- <% end %>
- <% unless spending_proposal.rejected? %>
- <%= link_to t("admin.spending_proposals.actions.reject"),
- reject_admin_spending_proposal_path(spending_proposal, request.query_parameters),
- method: :put,
- data: { confirm: t("admin.actions.confirm") },
- class: "button radius tiny warning right" %>
- <% end %>
- |
<% end %>
diff --git a/app/views/admin/spending_proposals/show.html.erb b/app/views/admin/spending_proposals/show.html.erb
index 4d3b57935..008921ffe 100644
--- a/app/views/admin/spending_proposals/show.html.erb
+++ b/app/views/admin/spending_proposals/show.html.erb
@@ -1,44 +1,78 @@
-<%= @spending_proposal.title %>
+<%= t("admin.spending_proposals.show.heading") %> <%= @spending_proposal.id %>
+<%= @spending_proposal.title %>
-<%= safe_html_with_links @spending_proposal.description.html_safe %>
+<%= safe_html_with_links @spending_proposal.description %>
<% if @spending_proposal.external_url.present? %>
<%= text_with_links @spending_proposal.external_url %>
<% end %>
-<%= t("admin.spending_proposals.show.by") %>:
+
<%= t("admin.spending_proposals.show.info") %>
+
+<%= t("admin.spending_proposals.show.by") %>:
<%= link_to @spending_proposal.author.name, admin_user_path(@spending_proposal.author) %>
-<%= t("admin.spending_proposals.show.association_name") %>:
- <%= @spending_proposal.association_name %>
-
-<%= t("admin.spending_proposals.show.geozone") %>:
+
+<% if @spending_proposal.association_name.present? %>
+
<%= t("admin.spending_proposals.show.association_name") %>:
+ <%= @spending_proposal.association_name %>
+
+<% end %>
+
+<%= t("admin.spending_proposals.show.geozone") %>:
<%= geozone_name(@spending_proposal) %>
-<%= l @spending_proposal.created_at, format: :datetime %>
-
- <% unless @spending_proposal.accepted? %>
- <%= link_to t("admin.spending_proposals.actions.accept"),
- accept_admin_spending_proposal_path(@spending_proposal),
- method: :put,
- data: { confirm: t("admin.actions.confirm") },
- class: "button radius tiny success no-margin" %>
- <% end %>
- <% unless @spending_proposal.rejected? %>
- <%= link_to t("admin.spending_proposals.actions.reject"),
- reject_admin_spending_proposal_path(@spending_proposal),
- method: :put,
- data: { confirm: t("admin.actions.confirm") },
- class: "button radius tiny warning" %>
- <% end %>
+
<%= t("admin.spending_proposals.show.sent") %>:
+ <%= l @spending_proposal.created_at, format: :datetime %>
+<%= t("admin.spending_proposals.show.responsibles") %>
-<%= t("admin.spending_proposals.show.dossier") %>:
+<%= t("admin.spending_proposals.show.assigned_admin") %>:
+ <%= form_for(@spending_proposal, url: assign_admin_admin_spending_proposal_path(@spending_proposal), remote: true, html: {id: 'administrator_assignment_form'}) do |f| %>
+ <%= f.select :administrator_id, @admins.collect { |a| [ "#{a.name} (#{a.email})", a.id ] }, {include_blank: t("admin.spending_proposals.show.undefined"), label: false}, class: "js-submit-on-change" %>
+ <% end %>
+
-<%= t("admin.spending_proposals.show.price") %>: <%= @spending_proposal.price %>
-<%= t("admin.spending_proposals.show.legality") %>: <%= t("admin.spending_proposals.show.#{@spending_proposal.legality}") %>
-<%= t("admin.spending_proposals.show.feasibility") %>: <%= t("admin.spending_proposals.show.#{@spending_proposal.feasibility}") %>
+<%= t("admin.spending_proposals.show.assigned_valuators") %>:
+
+ <%= render "assigned_valuators" %>
+
-<%= safe_html_with_links(@spending_proposal.explanation.html_safe) if @spending_proposal.explanation %>
+<%= link_to t("admin.spending_proposals.show.assign_valuators"), "", class: "js-toggle-link", data: {"toggle-selector" => "#valuators-assign-list"} %>
+
+
+ <%= form_for(@spending_proposal, url: assign_valuators_admin_spending_proposal_path(@spending_proposal), remote: true, html: {id: 'valuators_assignment_form'}) do |f| %>
+ <% @valuators.each do |valuator| -%>
+
+ <%= check_box_tag "valuator_ids_#{valuator.id}", valuator.id, @spending_proposal.valuators.include?(valuator),
+ name: 'spending_proposal[valuator_ids][]',
+ class: "js-submit-on-change" %>
+ <%= label_tag "valuator_ids_#{valuator.id}", valuator.name %>
+
+ <% end -%>
+ <% end -%>
+
+
+
+<%= t("admin.spending_proposals.show.dossier") %>
+
+<%= t("admin.spending_proposals.show.price") %> (<%= t("admin.spending_proposals.show.currency") %>):
+ <%= @spending_proposal.price.present? ? @spending_proposal.price : t("admin.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("admin.spending_proposals.show.feasibility") %>:
+ <%= t("admin.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? %>
+
+<% if @spending_proposal.valuation_finished %>
+ <%= t("admin.spending_proposals.show.valuation_finished") %>
+<% end %>
+
+<% if @spending_proposal.internal_comments.present? %>
+
<%= t("admin.spending_proposals.show.internal_comments") %>
+ <%= simple_format(safe_html_with_links(@spending_proposal.internal_comments.html_safe), {}, sanitize: false) %>
+<% end %>
diff --git a/app/views/spending_proposals/show.html.erb b/app/views/spending_proposals/show.html.erb
index 95432fba9..987118a6a 100644
--- a/app/views/spending_proposals/show.html.erb
+++ b/app/views/spending_proposals/show.html.erb
@@ -23,11 +23,6 @@
<% end %>
- <% if @spending_proposal.resolution.present? %>
-
- <%= @spending_proposal.resolution %>
-
- <% end %>
diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml
index 1711c9221..7d3aef540 100755
--- a/config/locales/admin.en.yml
+++ b/config/locales/admin.en.yml
@@ -137,9 +137,6 @@ en:
button: Search
placeholder: Search user by name or email'
spending_proposals:
- actions:
- accept: Accept
- reject: Reject
index:
filter: Filter
filters:
@@ -148,18 +145,26 @@ en:
unresolved: Unresolved
title: Spending proposals for participatory budgeting
show:
+ heading: Investment project
+ info: Author info
association_name: Asociación
by: Sent by
+ sent: Sent at
geozone: Scope
dossier: Dossier
price: Price
- legality: Legality
- legal: Legal
- not_legal: Not legal
+ currency: "€"
feasibility: Feasibility
feasible: Feasible
not_feasible: Not feasible
undefined: Undefined
+ valuation_finished: Valuation finished
+ internal_comments: Internal comments
+ responsibles: Responsibles
+ assigned_admin: Assigned admin
+ assigned_valuators: Assigned valuators
+ assign_valuators: Assign valuators
+ assign: Assign
stats:
show:
stats_title: Stats
diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml
index 4ccdba39e..8d2815423 100644
--- a/config/locales/admin.es.yml
+++ b/config/locales/admin.es.yml
@@ -57,7 +57,7 @@ es:
officials: Cargos públicos
organizations: Organizaciones
settings: Configuración global
- spending_proposals: Propuestas de gasto
+ spending_proposals: Propuestas de inversión
stats: Estadísticas
moderators:
index:
@@ -137,9 +137,6 @@ es:
button: Buscar
placeholder: Buscar usuario por nombre o email
spending_proposals:
- actions:
- accept: Aceptar
- reject: Rechazar
index:
filter: Filtro
filters:
@@ -148,18 +145,26 @@ es:
unresolved: Sin resolver
title: Propuestas de gasto para presupuestos participativos
show:
+ heading: Propuesta de inversión
+ info: Datos de envío
association_name: Asociación
by: Enviada por
+ sent: Fecha de creación
geozone: Ámbito
dossier: Informe
price: Coste
- legality: Legalidad
- legal: Legal
- not_legal: No legal
+ currency: "€"
feasibility: Viabilidad
feasible: Viable
not_feasible: No viable
undefined: Sin definir
+ valuation_finished: Informe finalizado
+ internal_comments: Commentarios internos
+ responsibles: Responsables
+ assigned_admin: Administrador asignado
+ assigned_valuators: Evaluadores asignados
+ assign_valuators: Asignar evaluadores
+ assign: Asignar
stats:
show:
stats_title: Estadísticas
diff --git a/config/routes.rb b/config/routes.rb
index 7a8a99881..302ce602c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -131,10 +131,10 @@ Rails.application.routes.draw do
end
end
- resources :spending_proposals, only: [:index, :show], path: 'investment_projects' do
+ resources :spending_proposals, only: [:index, :show] do
member do
- put :accept
- put :reject
+ patch :assign_admin
+ patch :assign_valuators
end
end
diff --git a/db/dev_seeds.rb b/db/dev_seeds.rb
index 0bee91cb2..f36ed5b36 100644
--- a/db/dev_seeds.rb
+++ b/db/dev_seeds.rb
@@ -41,6 +41,9 @@ admin.create_administrator
moderator = create_user('mod@madrid.es', 'mod')
moderator.create_moderator
+valuator = create_user('valuator@madrid.es', 'valuator')
+valuator.create_valuator
+
(1..10).each do |i|
org_name = Faker::Company.name
org_user = create_user("org#{i}@madrid.es", org_name)
@@ -247,8 +250,6 @@ end
puts "Creating Spending Proposals"
-resolutions = ["accepted", "rejected", nil]
-
(1..30).each do |i|
geozone = Geozone.reorder("RANDOM()").first
author = User.reorder("RANDOM()").first
@@ -258,12 +259,17 @@ resolutions = ["accepted", "rejected", nil]
external_url: Faker::Internet.url,
description: description,
created_at: rand((Time.now - 1.week) .. Time.now),
- resolution: resolutions.sample,
geozone: [geozone, nil].sample,
terms_of_service: "1")
puts " #{spending_proposal.title}"
end
+puts "Creating Valuation Assignments"
+
+(1..17).to_a.sample.times do
+ SpendingProposal.reorder("RANDOM()").first.valuators << valuator.valuator
+end
+
puts "Creating Legislation"
Legislation.create!(title: 'Participatory Democracy', body: 'In order to achieve...')
diff --git a/db/migrate/20160224101038_change_spending_proposals_fields.rb b/db/migrate/20160224101038_change_spending_proposals_fields.rb
new file mode 100644
index 000000000..22a7270cb
--- /dev/null
+++ b/db/migrate/20160224101038_change_spending_proposals_fields.rb
@@ -0,0 +1,16 @@
+class ChangeSpendingProposalsFields < ActiveRecord::Migration
+ def change
+ remove_index :spending_proposals, column: :resolution
+
+ remove_column :spending_proposals, :legal, :boolean
+ remove_column :spending_proposals, :resolution, :string
+ remove_column :spending_proposals, :explanation, :text
+
+ add_column :spending_proposals, :price_explanation, :text
+ add_column :spending_proposals, :feasible_explanation, :text
+ add_column :spending_proposals, :internal_comments, :text
+ add_column :spending_proposals, :valuation_finished, :boolean, default: false
+ add_column :spending_proposals, :explanations_log, :text
+ add_column :spending_proposals, :administrator_id, :integer
+ end
+end
diff --git a/db/migrate/20160224123110_create_valuation_assignments.rb b/db/migrate/20160224123110_create_valuation_assignments.rb
new file mode 100644
index 000000000..7ec9a9df4
--- /dev/null
+++ b/db/migrate/20160224123110_create_valuation_assignments.rb
@@ -0,0 +1,9 @@
+class CreateValuationAssignments < ActiveRecord::Migration
+ def change
+ create_table :valuation_assignments do |t|
+ t.belongs_to :valuator
+ t.belongs_to :spending_proposal
+ t.timestamps null: false
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2c948febc..fd1e0e484 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160222145100) do
+ActiveRecord::Schema.define(version: 20160224123110) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -108,10 +108,10 @@ ActiveRecord::Schema.define(version: 20160222145100) do
t.string "visit_id"
t.datetime "hidden_at"
t.integer "flags_count", default: 0
- t.datetime "ignored_flag_at"
t.integer "cached_votes_total", default: 0
t.integer "cached_votes_up", default: 0
t.integer "cached_votes_down", default: 0
+ t.datetime "ignored_flag_at"
t.integer "comments_count", default: 0
t.datetime "confirmed_hide_at"
t.integer "cached_anonymous_votes_total", default: 0
@@ -129,6 +129,7 @@ ActiveRecord::Schema.define(version: 20160222145100) do
add_index "debates", ["cached_votes_total"], name: "index_debates_on_cached_votes_total", using: :btree
add_index "debates", ["cached_votes_up"], name: "index_debates_on_cached_votes_up", using: :btree
add_index "debates", ["confidence_score"], name: "index_debates_on_confidence_score", using: :btree
+ add_index "debates", ["description"], name: "index_debates_on_description", using: :btree
add_index "debates", ["geozone_id"], name: "index_debates_on_geozone_id", using: :btree
add_index "debates", ["hidden_at"], name: "index_debates_on_hidden_at", using: :btree
add_index "debates", ["hot_score"], name: "index_debates_on_hot_score", using: :btree
@@ -205,7 +206,7 @@ ActiveRecord::Schema.define(version: 20160222145100) do
create_table "locks", force: :cascade do |t|
t.integer "user_id"
t.integer "tries", default: 0
- t.datetime "locked_until", default: '2000-01-01 07:01:01', null: false
+ t.datetime "locked_until", default: '2000-01-01 00:01:01', null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
@@ -265,6 +266,7 @@ ActiveRecord::Schema.define(version: 20160222145100) do
add_index "proposals", ["author_id"], name: "index_proposals_on_author_id", using: :btree
add_index "proposals", ["cached_votes_up"], name: "index_proposals_on_cached_votes_up", using: :btree
add_index "proposals", ["confidence_score"], name: "index_proposals_on_confidence_score", using: :btree
+ add_index "proposals", ["description"], name: "index_proposals_on_description", using: :btree
add_index "proposals", ["geozone_id"], name: "index_proposals_on_geozone_id", using: :btree
add_index "proposals", ["hidden_at"], name: "index_proposals_on_hidden_at", using: :btree
add_index "proposals", ["hot_score"], name: "index_proposals_on_hot_score", using: :btree
@@ -294,20 +296,22 @@ ActiveRecord::Schema.define(version: 20160222145100) do
t.text "description"
t.integer "author_id"
t.string "external_url"
- 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 "geozone_id"
- t.string "resolution"
t.float "price"
- t.boolean "legal"
t.boolean "feasible"
- t.text "explanation"
t.string "association_name"
+ t.text "price_explanation"
+ t.text "feasible_explanation"
+ t.text "internal_comments"
+ t.boolean "valuation_finished", default: false
+ t.text "explanations_log"
+ t.integer "administrator_id"
end
add_index "spending_proposals", ["author_id"], name: "index_spending_proposals_on_author_id", using: :btree
add_index "spending_proposals", ["geozone_id"], name: "index_spending_proposals_on_geozone_id", using: :btree
- add_index "spending_proposals", ["resolution"], name: "index_spending_proposals_on_resolution", using: :btree
create_table "taggings", force: :cascade do |t|
t.integer "tag_id"
@@ -328,8 +332,8 @@ ActiveRecord::Schema.define(version: 20160222145100) do
t.boolean "featured", default: false
t.integer "debates_count", default: 0
t.integer "proposals_count", default: 0
- t.string "kind"
t.integer "spending_proposals_count", default: 0
+ t.string "kind"
end
add_index "tags", ["debates_count"], name: "index_tags_on_debates_count", using: :btree
@@ -405,8 +409,8 @@ ActiveRecord::Schema.define(version: 20160222145100) do
t.boolean "public_activity", default: true
t.boolean "newsletter", default: false
t.integer "notifications_count", default: 0
- t.string "locale"
t.boolean "registering_with_oauth", default: false
+ t.string "locale"
t.string "oauth_email"
t.integer "geozone_id"
t.string "redeemable_code"
@@ -418,6 +422,13 @@ ActiveRecord::Schema.define(version: 20160222145100) do
add_index "users", ["hidden_at"], name: "index_users_on_hidden_at", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
+ create_table "valuation_assignments", force: :cascade do |t|
+ t.integer "valuator_id"
+ t.integer "spending_proposal_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ end
+
create_table "valuators", force: :cascade do |t|
t.integer "user_id"
end
diff --git a/spec/factories.rb b/spec/factories.rb
index 0e5831556..6cfe2779b 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -1,4 +1,5 @@
FactoryGirl.define do
+
sequence(:document_number) { |n| "#{n.to_s.rjust(8, '0')}X" }
factory :user do
diff --git a/spec/features/admin/spending_proposals_spec.rb b/spec/features/admin/spending_proposals_spec.rb
index 3b619dc3e..a3a844d94 100644
--- a/spec/features/admin/spending_proposals_spec.rb
+++ b/spec/features/admin/spending_proposals_spec.rb
@@ -19,97 +19,18 @@ feature 'Admin spending proposals' do
expect(page).to have_content(spending_proposal.title)
end
- scenario 'Accept from index' do
- spending_proposal = create(:spending_proposal)
- visit admin_spending_proposals_path
-
- click_link 'Accept'
-
- expect(page).to_not have_content(spending_proposal.title)
-
- click_link 'Accepted'
- expect(page).to have_content(spending_proposal.title)
-
- expect(spending_proposal.reload).to be_accepted
- end
-
- scenario 'Reject from index' do
- spending_proposal = create(:spending_proposal)
- visit admin_spending_proposals_path
-
- click_link 'Reject'
-
- expect(page).to_not have_content(spending_proposal.title)
-
- click_link('Rejected')
- expect(page).to have_content(spending_proposal.title)
-
- expect(spending_proposal.reload).to be_rejected
- end
-
- scenario "Current filter is properly highlighted" do
- visit admin_spending_proposals_path
- expect(page).to_not have_link('Unresolved')
- expect(page).to have_link('Accepted')
- expect(page).to have_link('Rejected')
-
- visit admin_spending_proposals_path(filter: 'unresolved')
- expect(page).to_not have_link('Unresolved')
- expect(page).to have_link('Accepted')
- expect(page).to have_link('Rejected')
-
- visit admin_spending_proposals_path(filter: 'accepted')
- expect(page).to have_link('Unresolved')
- expect(page).to_not have_link('Accepted')
- expect(page).to have_link('Rejected')
-
- visit admin_spending_proposals_path(filter: 'rejected')
- expect(page).to have_link('Accepted')
- expect(page).to have_link('Unresolved')
- expect(page).to_not have_link('Rejected')
- end
-
- scenario "Filtering proposals" do
- create(:spending_proposal, title: "Recent spending proposal")
- create(:spending_proposal, title: "Good spending proposal", resolution: "accepted")
- create(:spending_proposal, title: "Bad spending proposal", resolution: "rejected")
-
- visit admin_spending_proposals_path(filter: 'unresolved')
- expect(page).to have_content('Recent spending proposal')
- expect(page).to_not have_content('Good spending proposal')
- expect(page).to_not have_content('Bad spending proposal')
-
- visit admin_spending_proposals_path(filter: 'accepted')
- expect(page).to have_content('Good spending proposal')
- expect(page).to_not have_content('Recent spending proposal')
- expect(page).to_not have_content('Bad spending proposal')
-
- visit admin_spending_proposals_path(filter: 'rejected')
- expect(page).to have_content('Bad spending proposal')
- expect(page).to_not have_content('Good spending proposal')
- expect(page).to_not have_content('Recent spending proposal')
- end
-
- scenario "Action links remember the pagination setting and the filter" do
- per_page = Kaminari.config.default_per_page
- (per_page + 2).times { create(:spending_proposal, resolution: "accepted") }
-
- visit admin_spending_proposals_path(filter: 'accepted', page: 2)
-
- click_on('Reject', match: :first, exact: true)
-
- expect(current_url).to include('filter=accepted')
- expect(current_url).to include('page=2')
- end
-
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'))
spending_proposal = create(:spending_proposal,
geozone: create(:geozone),
association_name: 'People of the neighbourhood',
price: 1234.56,
- legal: true,
feasible: false,
- explanation: "It's impossible")
+ feasible_explanation: 'It is impossible',
+ administrator: administrator)
+ spending_proposal.valuators << valuator
+
visit admin_spending_proposals_path
click_link spending_proposal.title
@@ -119,38 +40,71 @@ feature 'Admin spending proposals' do
expect(page).to have_content(spending_proposal.author.name)
expect(page).to have_content(spending_proposal.association_name)
expect(page).to have_content(spending_proposal.geozone.name)
- expect(page).to have_content("1234.56")
- expect(page).to have_content("Legal")
- expect(page).to have_content("Not feasible")
- expect(page).to have_content("It's impossible")
+ expect(page).to have_content('1234.56')
+ expect(page).to have_content('Not feasible')
+ expect(page).to have_content('It is impossible')
+ expect(page).to have_select('spending_proposal[administrator_id]', selected: 'Ana (ana@admins.org)')
+
+ within('#assigned_valuators') do
+ expect(page).to have_content('Rachel (rachel@valuators.org)')
+ end
end
- scenario 'Accept from show' do
+ scenario 'Administrator assigment', :js do
spending_proposal = create(:spending_proposal)
+
+ administrator = create(:administrator, user: create(:user, username: 'Ana', email: 'ana@admins.org'))
+
visit admin_spending_proposal_path(spending_proposal)
- click_link 'Accept'
+ expect(page).to have_select('spending_proposal[administrator_id]', selected: 'Undefined')
+ select 'Ana (ana@admins.org)', from: 'spending_proposal[administrator_id]'
- expect(page).to_not have_content(spending_proposal.title)
+ visit admin_spending_proposal_path(spending_proposal)
- click_link 'Accepted'
- expect(page).to have_content(spending_proposal.title)
-
- expect(spending_proposal.reload).to be_accepted
+ expect(page).to have_select('spending_proposal[administrator_id]', selected: 'Ana (ana@admins.org)')
end
- scenario 'Reject from show' do
+ scenario 'Valuators assigments', :js do
spending_proposal = create(:spending_proposal)
+
+ valuator1 = create(:valuator, user: create(:user, username: 'Valentina', email: 'v1@valuators.org'))
+ valuator2 = create(:valuator, user: create(:user, username: 'Valerian', email: 'v2@valuators.org'))
+ valuator3 = create(:valuator, user: create(:user, username: 'Val', email: 'v3@valuators.org'))
+
visit admin_spending_proposal_path(spending_proposal)
- click_link 'Reject'
+ within('#assigned_valuators') do
+ expect(page).to have_content('Undefined')
+ expect(page).to_not have_content('Valentina (v1@valuators.org)')
+ expect(page).to_not have_content('Valerian (v2@valuators.org)')
+ expect(page).to_not have_content('Val (v3@valuators.org)')
+ end
- expect(page).to_not have_content(spending_proposal.title)
+ visit admin_spending_proposal_path(spending_proposal)
- click_link('Rejected')
- expect(page).to have_content(spending_proposal.title)
+ click_link "Assign valuators"
- expect(spending_proposal.reload).to be_rejected
+ within('#valuators-assign-list') do
+ check "valuator_ids_#{valuator1.id}"
+ check "valuator_ids_#{valuator3.id}"
+ end
+
+ within('#assigned_valuators') do
+ expect(page).to have_content('Valentina (v1@valuators.org)')
+ expect(page).to have_content('Val (v3@valuators.org)')
+ expect(page).to_not have_content('Undefined')
+ expect(page).to_not have_content('Valerian (v2@valuators.org)')
+ end
+
+ visit admin_spending_proposal_path(spending_proposal)
+
+ within('#assigned_valuators') do
+ expect(page).to have_content('Valentina (v1@valuators.org)')
+ expect(page).to have_content('Val (v3@valuators.org)')
+ expect(page).to_not have_content('Undefined')
+ expect(page).to_not have_content('Valerian (v2@valuators.org)')
+ end
end
end
diff --git a/spec/models/spending_proposal_spec.rb b/spec/models/spending_proposal_spec.rb
index 3d12b9489..d0b6973a4 100644
--- a/spec/models/spending_proposal_spec.rb
+++ b/spec/models/spending_proposal_spec.rb
@@ -43,23 +43,6 @@ describe SpendingProposal do
end
describe "dossier info" do
- describe "#legality" do
- it "can be legal" do
- spending_proposal.legal = true
- expect(spending_proposal.legality).to eq "legal"
- end
-
- it "can be not-legal" do
- spending_proposal.legal = false
- expect(spending_proposal.legality).to eq "not_legal"
- end
-
- it "can be undefined" do
- spending_proposal.legal = nil
- expect(spending_proposal.legality).to eq "undefined"
- end
- end
-
describe "#feasibility" do
it "can be feasible" do
spending_proposal.feasible = true
@@ -78,99 +61,4 @@ describe SpendingProposal do
end
end
- describe "resolution status" do
- it "should be valid" do
- spending_proposal.resolution = "accepted"
- expect(spending_proposal).to be_valid
- spending_proposal.resolution = "rejected"
- expect(spending_proposal).to be_valid
- spending_proposal.resolution = "wrong"
- expect(spending_proposal).to_not be_valid
- end
-
- it "can be accepted" do
- spending_proposal.accept
- expect(spending_proposal.reload.resolution).to eq("accepted")
- end
-
- it "can be rejected" do
- spending_proposal.reject
- expect(spending_proposal.reload.resolution).to eq("rejected")
- end
-
- describe "#accepted?" do
- it "should be true if resolution equals 'accepted'" do
- spending_proposal.resolution = "accepted"
- expect(spending_proposal.accepted?).to eq true
- end
-
- it "should be false otherwise" do
- spending_proposal.resolution = "rejected"
- expect(spending_proposal.accepted?).to eq false
- spending_proposal.resolution = nil
- expect(spending_proposal.accepted?).to eq false
- end
- end
-
- describe "#rejected?" do
- it "should be true if resolution equals 'rejected'" do
- spending_proposal.resolution = "rejected"
- expect(spending_proposal.rejected?).to eq true
- end
-
- it "should be false otherwise" do
- spending_proposal.resolution = "accepted"
- expect(spending_proposal.rejected?).to eq false
- spending_proposal.resolution = nil
- expect(spending_proposal.rejected?).to eq false
- end
- end
-
- describe "#unresolved?" do
- it "should be true if resolution is blank" do
- spending_proposal.resolution = nil
- expect(spending_proposal.unresolved?).to eq true
- end
-
- it "should be false otherwise" do
- spending_proposal.resolution = "accepted"
- expect(spending_proposal.unresolved?).to eq false
- spending_proposal.resolution = "rejected"
- expect(spending_proposal.unresolved?).to eq false
- end
- end
- end
-
- describe "scopes" do
- before(:each) do
- 2.times { create(:spending_proposal, resolution: "accepted") }
- 2.times { create(:spending_proposal, resolution: "rejected") }
- 2.times { create(:spending_proposal, resolution: nil) }
- end
-
- describe "unresolved" do
- it "should return all spending proposals without resolution" do
- unresolved = SpendingProposal.all.unresolved
- expect(unresolved.size).to eq(2)
- unresolved.each {|u| expect(u.resolution).to be_nil}
- end
- end
-
- describe "accepted" do
- it "should return all accepted spending proposals" do
- accepted = SpendingProposal.all.accepted
- expect(accepted.size).to eq(2)
- accepted.each {|a| expect(a.resolution).to eq("accepted")}
- end
- end
-
- describe "rejected" do
- it "should return all rejected spending proposals" do
- rejected = SpendingProposal.all.rejected
- expect(rejected.size).to eq(2)
- rejected.each {|r| expect(r.resolution).to eq("rejected")}
- end
- end
- end
-
end