adds Budget::Group model to group headings

many refactors through budget related models
This commit is contained in:
Juanjo Bazán
2016-06-09 18:00:06 +02:00
parent 3fae269c40
commit b5a6828e41
18 changed files with 156 additions and 110 deletions

View File

@@ -4,9 +4,11 @@ class Budget < ActiveRecord::Base
validates :phase, inclusion: { in: VALID_PHASES } validates :phase, inclusion: { in: VALID_PHASES }
has_many :investments has_many :investments, dependent: :destroy
has_many :ballots has_many :ballots, dependent: :destroy
has_many :headings has_many :groups, dependent: :destroy
has_many :headings, through: :groups
has_many :investments, through: :headings
def on_hold? def on_hold?
phase == "on_hold" phase == "on_hold"
@@ -29,7 +31,6 @@ class Budget < ActiveRecord::Base
end end
def heading_price(heading) def heading_price(heading)
return price unless heading.present?
heading_ids.include?(heading.id) ? heading.price : -1 heading_ids.include?(heading.id) ? heading.price : -1
end end
end end

View File

@@ -16,7 +16,7 @@ class Budget
end end
def amount_available(heading) def amount_available(heading)
budget.heading_price(heading) - amount_spent(heading.try(:id)) budget.heading_price(heading) - amount_spent(heading.id)
end end
end end
end end

View File

@@ -0,0 +1,10 @@
class Budget
class Group < ActiveRecord::Base
belongs_to :budget
has_many :headings, dependent: :destroy
validates :budget_id, presence: true
validates :name, presence: true
end
end

View File

@@ -1,11 +1,11 @@
class Budget class Budget
class Heading < ActiveRecord::Base class Heading < ActiveRecord::Base
belongs_to :budget belongs_to :group
belongs_to :geozone belongs_to :geozone
has_many :investments has_many :investments
validates :budget_id, presence: true validates :group_id, presence: true
validates :name, presence: true validates :name, presence: true
validates :price, presence: true validates :price, presence: true
end end

View File

@@ -10,7 +10,6 @@ class Budget
acts_as_paranoid column: :hidden_at acts_as_paranoid column: :hidden_at
include ActsAsParanoidAliases include ActsAsParanoidAliases
belongs_to :budget
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :heading belongs_to :heading
belongs_to :administrator belongs_to :administrator
@@ -43,7 +42,6 @@ class Budget
scope :with_supports, -> { where('cached_votes_up > 0') } scope :with_supports, -> { where('cached_votes_up > 0') }
scope :by_heading, -> (heading_id) { where(heading_id: heading_id) } scope :by_heading, -> (heading_id) { where(heading_id: heading_id) }
scope :by_budget, -> (budget_id) { where(budget_id: budget_id) }
scope :by_admin, -> (admin_id) { where(administrator_id: admin_id) } scope :by_admin, -> (admin_id) { where(administrator_id: admin_id) }
scope :by_tag, -> (tag_name) { tagged_with(tag_name) } 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, -> (valuator_id) { where("budget_valuator_assignments.valuator_id = ?", valuator_id).joins(:valuator_assignments) }
@@ -61,8 +59,7 @@ class Budget
end end
def self.scoped_filter(params, current_filter) def self.scoped_filter(params, current_filter)
budget = Budget.find!(params[:budget_id]) results = budget.investments
results = self.by_budget(params[:budget_id])
if params[:max_for_no_heading].present? || params[:max_per_heading].present? if params[:max_for_no_heading].present? || params[:max_per_heading].present?
results = limit_results(results, budget, params[:max_per_heading].to_i, params[:max_for_no_heading].to_i) results = limit_results(results, budget, params[:max_per_heading].to_i, params[:max_for_no_heading].to_i)
end end
@@ -118,6 +115,10 @@ class Budget
where(heading_id: heading == 'all' ? nil : heading.presence) where(heading_id: heading == 'all' ? nil : heading.presence)
end end
def budget
heading.group.budget
end
def undecided? def undecided?
feasibility == "undecided" feasibility == "undecided"
end end
@@ -139,7 +140,7 @@ class Budget
end end
def code def code
"B#{budget_id}I#{id}" "B#{budget.id}I#{id}"
end end
def reason_for_not_being_selectable_by(user) def reason_for_not_being_selectable_by(user)

View File

@@ -300,18 +300,21 @@ puts "Creating Budgets"
(1..10).each do |i| (1..10).each do |i|
budget = Budget.create!(name: (Date.today.year - 10 + i).to_s, budget = Budget.create!(name: (Date.today.year - 10 + i).to_s,
description: "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>", description: "<p>#{Faker::Lorem.paragraphs.join('</p><p>')}</p>",
price: rand(1 .. 100) * 100000,
phase: %w{on_hold accepting selecting balloting finished}.sample, phase: %w{on_hold accepting selecting balloting finished}.sample,
valuating: [false, true].sample) valuating: [false, true].sample)
puts budget.name puts budget.name
puts " "
geozones = Geozone.reorder("RANDOM()").limit(10) (1..[1,2,3].sample).each do |i|
geozones.each do |geozone| group = budget.groups.create!(name: Faker::StarWars.planet)
heading = budget.headings.create!(name: geozone.name,
geozone: geozone, geozones = Geozone.reorder("RANDOM()").limit([2,5,6,7].sample)
price: rand(1 .. 100) * 10000) geozones.each do |geozone|
budget.headings << heading group.headings << group.headings.create!(name: geozone.name,
print "heading.name " geozone: geozone,
price: rand(1 .. 100) * 10000)
end
print "#{group.name} "
end end
puts "" puts ""
end end

View File

@@ -1,9 +1,9 @@
class CreateBudgetHeading < ActiveRecord::Migration class CreateBudgetHeading < ActiveRecord::Migration
def change def change
create_table :budget_headings do |t| create_table :budget_headings do |t|
t.references :budget t.references :group, index: true
t.references :geozone t.references :geozone
t.string :name, limit: 50 t.string :name, limit: 50
t.integer :price, limit: 8 t.integer :price, limit: 8
end end
end end

View File

@@ -0,0 +1,10 @@
class CreateBudgetGroup < ActiveRecord::Migration
def change
create_table :budget_groups do |t|
t.references :budget
t.string :name, limit: 50
end
add_index :budget_groups, :budget_id
end
end

View File

@@ -0,0 +1,5 @@
class RemovePriceFromBudget < ActiveRecord::Migration
def change
remove_column :budgets, :price, :integer
end
end

View File

@@ -0,0 +1,5 @@
class RemoveBudgetIdFromInvestments < ActiveRecord::Migration
def change
remove_column :budget_investments, :budget_id, :integer
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160531102008) do ActiveRecord::Schema.define(version: 20160609152026) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -63,6 +63,21 @@ ActiveRecord::Schema.define(version: 20160531102008) do
add_index "annotations", ["legislation_id"], name: "index_annotations_on_legislation_id", using: :btree add_index "annotations", ["legislation_id"], name: "index_annotations_on_legislation_id", using: :btree
add_index "annotations", ["user_id"], name: "index_annotations_on_user_id", using: :btree add_index "annotations", ["user_id"], name: "index_annotations_on_user_id", using: :btree
create_table "banners", force: :cascade do |t|
t.string "title", limit: 80
t.string "description"
t.string "target_url"
t.string "style"
t.string "image"
t.date "post_started_at"
t.date "post_ended_at"
t.datetime "hidden_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "banners", ["hidden_at"], name: "index_banners_on_hidden_at", using: :btree
create_table "budget_ballot_lines", force: :cascade do |t| create_table "budget_ballot_lines", force: :cascade do |t|
t.integer "ballot_id" t.integer "ballot_id"
t.integer "investment_id" t.integer "investment_id"
@@ -83,13 +98,22 @@ ActiveRecord::Schema.define(version: 20160531102008) do
add_index "budget_ballots", ["heading_id"], name: "index_budget_ballots_on_heading_id", using: :btree add_index "budget_ballots", ["heading_id"], name: "index_budget_ballots_on_heading_id", using: :btree
create_table "budget_headings", force: :cascade do |t| create_table "budget_groups", force: :cascade do |t|
t.integer "budget_id" t.integer "budget_id"
t.string "name", limit: 50
end
add_index "budget_groups", ["budget_id"], name: "index_budget_groups_on_budget_id", using: :btree
create_table "budget_headings", force: :cascade do |t|
t.integer "group_id"
t.integer "geozone_id" t.integer "geozone_id"
t.string "name", limit: 50 t.string "name", limit: 50
t.integer "price", limit: 8 t.integer "price", limit: 8
end end
add_index "budget_headings", ["group_id"], name: "index_budget_headings_on_group_id", using: :btree
create_table "budget_investments", force: :cascade do |t| create_table "budget_investments", force: :cascade do |t|
t.integer "author_id" t.integer "author_id"
t.integer "administrator_id" t.integer "administrator_id"
@@ -114,13 +138,11 @@ ActiveRecord::Schema.define(version: 20160531102008) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "heading_id" t.integer "heading_id"
t.integer "budget_id"
t.string "responsible_name" t.string "responsible_name"
end end
add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree
add_index "budget_investments", ["author_id"], name: "index_budget_investments_on_author_id", using: :btree add_index "budget_investments", ["author_id"], name: "index_budget_investments_on_author_id", using: :btree
add_index "budget_investments", ["budget_id"], name: "index_budget_investments_on_budget_id", using: :btree
add_index "budget_investments", ["heading_id"], name: "index_budget_investments_on_heading_id", using: :btree add_index "budget_investments", ["heading_id"], name: "index_budget_investments_on_heading_id", using: :btree
add_index "budget_investments", ["tsv"], name: "index_budget_investments_on_tsv", using: :gin add_index "budget_investments", ["tsv"], name: "index_budget_investments_on_tsv", using: :gin
@@ -141,24 +163,8 @@ ActiveRecord::Schema.define(version: 20160531102008) do
t.boolean "valuating", default: false t.boolean "valuating", default: false
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.integer "price"
end end
create_table "banners", force: :cascade do |t|
t.string "title", limit: 80
t.string "description"
t.string "target_url"
t.string "style"
t.string "image"
t.date "post_started_at"
t.date "post_ended_at"
t.datetime "hidden_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "banners", ["hidden_at"], name: "index_banners_on_hidden_at", using: :btree
create_table "campaigns", force: :cascade do |t| create_table "campaigns", force: :cascade do |t|
t.string "name" t.string "name"
t.string "track_id" t.string "track_id"
@@ -204,10 +210,10 @@ ActiveRecord::Schema.define(version: 20160531102008) do
t.string "visit_id" t.string "visit_id"
t.datetime "hidden_at" t.datetime "hidden_at"
t.integer "flags_count", default: 0 t.integer "flags_count", default: 0
t.datetime "ignored_flag_at"
t.integer "cached_votes_total", default: 0 t.integer "cached_votes_total", default: 0
t.integer "cached_votes_up", default: 0 t.integer "cached_votes_up", default: 0
t.integer "cached_votes_down", default: 0 t.integer "cached_votes_down", default: 0
t.datetime "ignored_flag_at"
t.integer "comments_count", default: 0 t.integer "comments_count", default: 0
t.datetime "confirmed_hide_at" t.datetime "confirmed_hide_at"
t.integer "cached_anonymous_votes_total", default: 0 t.integer "cached_anonymous_votes_total", default: 0

View File

@@ -191,7 +191,6 @@ FactoryGirl.define do
factory :budget do factory :budget do
sequence(:name) { |n| "Budget #{n}" } sequence(:name) { |n| "Budget #{n}" }
currency_symbol "" currency_symbol ""
price 10000
phase 'on_hold' phase 'on_hold'
trait :selecting do trait :selecting do
@@ -207,15 +206,20 @@ FactoryGirl.define do
end end
end end
factory :budget_heading, class: 'Budget::Heading' do factory :budget_group, class: 'Budget::Group' do
budget budget
sequence(:name) { |n| "Group #{n}" }
end
factory :budget_heading, class: 'Budget::Heading' do
association :group, factory: :budget_group
sequence(:name) { |n| "Heading #{n}" } sequence(:name) { |n| "Heading #{n}" }
price 1000000 price 1000000
end end
factory :budget_investment, class: 'Budget::Investment' do factory :budget_investment, class: 'Budget::Investment' do
sequence(:title) { |n| "Budget Investment #{n} title" } sequence(:title) { |n| "Budget Investment #{n} title" }
association :budget association :heading, factory: :budget_heading
association :author, factory: :user association :author, factory: :user
description 'Spend money on this' description 'Spend money on this'
unfeasibility_explanation '' unfeasibility_explanation ''

View File

@@ -65,7 +65,13 @@ describe "Abilities::Administrator" do
it { should be_able_to(:update, Budget::Investment) } it { should be_able_to(:update, Budget::Investment) }
it { should be_able_to(:hide, Budget::Investment) } it { should be_able_to(:hide, Budget::Investment) }
it { should be_able_to(:valuate, create(:budget_investment, budget: create(:budget, valuating: true))) } it { should be_able_to(:valuate, create(:budget_investment,
it { should_not be_able_to(:valuate, create(:budget_investment, budget: create(:budget, valuating: false))) } heading: create(:budget_heading,
group: create(:budget_group,
budget: create(:budget, valuating: true))))) }
it { should_not be_able_to(:valuate, create(:budget_investment,
heading: create(:budget_heading,
group: create(:budget_group,
budget: create(:budget, valuating: false))))) }
end end

View File

@@ -12,9 +12,16 @@ describe "Abilities::Common" do
let(:accepting_budget) { create(:budget, phase: 'accepting') } let(:accepting_budget) { create(:budget, phase: 'accepting') }
let(:selecting_budget) { create(:budget, phase: 'selecting') } let(:selecting_budget) { create(:budget, phase: 'selecting') }
let(:balloting_budget) { create(:budget, phase: 'balloting') } let(:balloting_budget) { create(:budget, phase: 'balloting') }
let(:investment_in_accepting_budget) { create(:budget_investment, budget: accepting_budget) } let(:accepting_budget_group) { create(:budget_group, budget: accepting_budget) }
let(:investment_in_selecting_budget) { create(:budget_investment, budget: selecting_budget) } let(:selecting_budget_group) { create(:budget_group, budget: selecting_budget) }
let(:investment_in_balloting_budget) { create(:budget_investment, budget: balloting_budget) } let(:balloting_budget_group) { create(:budget_group, budget: balloting_budget) }
let(:accepting_budget_heading) { create(:budget_heading, group: accepting_budget_group) }
let(:selecting_budget_heading) { create(:budget_heading, group: selecting_budget_group) }
let(:balloting_budget_heading) { create(:budget_heading, group: balloting_budget_group) }
let(:investment_in_accepting_budget) { create(:budget_investment, heading: accepting_budget_heading) }
let(:investment_in_selecting_budget) { create(:budget_investment, heading: selecting_budget_heading) }
let(:investment_in_balloting_budget) { create(:budget_investment, heading: balloting_budget_heading) }
let(:ballot_in_accepting_budget) { create(:budget_ballot, budget: accepting_budget) } let(:ballot_in_accepting_budget) { create(:budget_ballot, budget: accepting_budget) }
let(:ballot_in_selecting_budget) { create(:budget_ballot, budget: selecting_budget) } let(:ballot_in_selecting_budget) { create(:budget_ballot, budget: selecting_budget) }
let(:ballot_in_balloting_budget) { create(:budget_ballot, budget: balloting_budget) } let(:ballot_in_balloting_budget) { create(:budget_ballot, budget: balloting_budget) }

View File

@@ -7,10 +7,16 @@ describe "Abilities::Valuator" do
let(:valuator) { create(:valuator) } let(:valuator) { create(:valuator) }
let(:non_assigned_investment) { create(:budget_investment) } let(:non_assigned_investment) { create(:budget_investment) }
let(:assigned_investment) { create(:budget_investment, budget: create(:budget, valuating: true)) } let(:assigned_investment) { create(:budget_investment,
heading: create(:budget_heading,
group: create(:budget_group,
budget: create(:budget, valuating: true)))) }
before(:each) { assigned_investment.valuators << valuator } before(:each) { assigned_investment.valuators << valuator }
let(:assigned_investment_not_valuating) { create(:budget_investment, budget: create(:budget, valuating: false)) } let(:assigned_investment_not_valuating) { create(:budget_investment,
heading: create(:budget_heading,
group: create(:budget_group,
budget: create(:budget, valuating: false)))) }
before(:each) { assigned_investment_not_valuating.valuators << valuator } before(:each) { assigned_investment_not_valuating.valuators << valuator }
it { should be_able_to(:read, SpendingProposal) } it { should be_able_to(:read, SpendingProposal) }

View File

@@ -21,18 +21,15 @@ describe Budget::Ballot do
heading = create(:budget_heading) heading = create(:budget_heading)
inv1 = create(:budget_investment, :feasible, price: 10000, heading: heading) inv1 = create(:budget_investment, :feasible, price: 10000, heading: heading)
inv2 = create(:budget_investment, :feasible, price: 20000, heading: create(:budget_heading)) inv2 = create(:budget_investment, :feasible, price: 20000, heading: create(:budget_heading))
inv3 = create(:budget_investment, :feasible, price: 25000) inv3 = create(:budget_investment, :feasible, price: 40000, heading: heading)
inv4 = create(:budget_investment, :feasible, price: 40000, heading: heading)
ballot = create(:budget_ballot) ballot = create(:budget_ballot)
ballot.investments << inv1 ballot.investments << inv1
ballot.investments << inv2 ballot.investments << inv2
ballot.investments << inv3
expect(ballot.amount_spent(heading.id)).to eq 10000 expect(ballot.amount_spent(heading.id)).to eq 10000
expect(ballot.amount_spent(nil)).to eq 25000
ballot.investments << inv4 ballot.investments << inv3
expect(ballot.amount_spent(heading.id)).to eq 50000 expect(ballot.amount_spent(heading.id)).to eq 50000
end end
@@ -40,28 +37,22 @@ describe Budget::Ballot do
describe "#amount_available" do describe "#amount_available" do
it "returns how much is left after taking some investments" do it "returns how much is left after taking some investments" do
budget = create(:budget, price: 200000) budget = create(:budget)
heading = create(:budget_heading, budget: budget) group = create(:budget_group, budget: budget)
inv1 = create(:budget_investment, :feasible, price: 10000, heading: heading) heading = create(:budget_heading, group: group, price: 1000)
inv2 = create(:budget_investment, :feasible, price: 20000, heading: create(:budget_heading)) inv1 = create(:budget_investment, :feasible, price: 100, heading: heading)
inv3 = create(:budget_investment, :feasible, price: 25000) inv2 = create(:budget_investment, :feasible, price: 200, heading: create(:budget_heading))
inv4 = create(:budget_investment, :feasible, price: 40000, heading: heading) inv3 = create(:budget_investment, :feasible, price: 400, heading: heading)
inv1 = create(:budget_investment, :feasible, price: 10000)
inv2 = create(:budget_investment, :feasible, price: 20000)
ballot = create(:budget_ballot, budget: budget) ballot = create(:budget_ballot, budget: budget)
ballot.investments << inv1 ballot.investments << inv1
ballot.investments << inv2 ballot.investments << inv2
expect(ballot.amount_available(heading)).to eq 1000000 expect(ballot.amount_available(heading)).to eq 900
expect(ballot.amount_available(nil)).to eq 170000
ballot.investments << inv3 ballot.investments << inv3
ballot.investments << inv4
expect(ballot.amount_available(heading)).to eq 960000 expect(ballot.amount_available(heading)).to eq 500
expect(ballot.amount_available(nil)).to eq 145000
end end
end end

View File

@@ -190,38 +190,33 @@ describe Budget::Investment do
describe 'Permissions' do describe 'Permissions' do
let(:budget) { create(:budget) } let(:budget) { create(:budget) }
let(:heading) { create(:budget_heading, budget: budget) } let(:group) { create(:budget_group, budget: budget) }
let(:heading) { create(:budget_heading, group: group) }
let(:user) { create(:user, :level_two) } let(:user) { create(:user, :level_two) }
let(:luser) { create(:user) } let(:luser) { create(:user) }
let(:city_sp) { create(:budget_investment, budget: budget) } let(:district_sp) { create(:budget_investment, heading: heading) }
let(:district_sp) { create(:budget_investment, budget: budget, heading: heading) }
describe '#reason_for_not_being_selectable_by' do describe '#reason_for_not_being_selectable_by' do
it "rejects not logged in users" do it "rejects not logged in users" do
expect(city_sp.reason_for_not_being_selectable_by(nil)).to eq(:not_logged_in)
expect(district_sp.reason_for_not_being_selectable_by(nil)).to eq(:not_logged_in) expect(district_sp.reason_for_not_being_selectable_by(nil)).to eq(:not_logged_in)
end end
it "rejects not verified users" do it "rejects not verified users" do
expect(city_sp.reason_for_not_being_selectable_by(luser)).to eq(:not_verified)
expect(district_sp.reason_for_not_being_selectable_by(luser)).to eq(:not_verified) expect(district_sp.reason_for_not_being_selectable_by(luser)).to eq(:not_verified)
end end
it "rejects organizations" do it "rejects organizations" do
create(:organization, user: user) create(:organization, user: user)
expect(city_sp.reason_for_not_being_selectable_by(user)).to eq(:organization)
expect(district_sp.reason_for_not_being_selectable_by(user)).to eq(:organization) expect(district_sp.reason_for_not_being_selectable_by(user)).to eq(:organization)
end end
it "rejects selections when selecting is not allowed (via admin setting)" do it "rejects selections when selecting is not allowed (via admin setting)" do
budget.phase = "on_hold" budget.phase = "on_hold"
expect(city_sp.reason_for_not_being_selectable_by(user)).to eq(:no_selecting_allowed)
expect(district_sp.reason_for_not_being_selectable_by(user)).to eq(:no_selecting_allowed) expect(district_sp.reason_for_not_being_selectable_by(user)).to eq(:no_selecting_allowed)
end end
it "accepts valid selections when selecting is allowed" do it "accepts valid selections when selecting is allowed" do
budget.phase = "selecting" budget.phase = "selecting"
expect(city_sp.reason_for_not_being_selectable_by(user)).to be_nil
expect(district_sp.reason_for_not_being_selectable_by(user)).to be_nil expect(district_sp.reason_for_not_being_selectable_by(user)).to be_nil
end end
end end
@@ -274,7 +269,9 @@ describe Budget::Investment do
describe "total votes" do describe "total votes" do
it "takes into account physical votes in addition to web votes" do it "takes into account physical votes in addition to web votes" do
b = create(:budget, :selecting) b = create(:budget, :selecting)
sp = create(:budget_investment, budget: b) g = create(:budget_group, budget: b)
h = create(:budget_heading, group: g)
sp = create(:budget_investment, heading: h)
sp.register_selection(create(:user, :level_two)) sp.register_selection(create(:user, :level_two))
expect(sp.total_votes).to eq(1) expect(sp.total_votes).to eq(1)
@@ -299,56 +296,52 @@ describe Budget::Investment do
describe 'Permissions' do describe 'Permissions' do
let(:budget) { create(:budget) } let(:budget) { create(:budget) }
let(:heading) { create(:budget_heading, budget: budget) } let(:group) { create(:budget_group, budget: budget) }
let(:heading) { create(:budget_heading, group: group) }
let(:user) { create(:user, :level_two) } let(:user) { create(:user, :level_two) }
let(:luser) { create(:user) } let(:luser) { create(:user) }
let(:ballot) { create(:budget_ballot, budget: budget) } let(:ballot) { create(:budget_ballot, budget: budget) }
let(:city_sp) { create(:budget_investment, budget: budget) } let(:investment) { create(:budget_investment, heading: heading) }
let(:district_sp) { create(:budget_investment, budget: budget, heading: heading) }
describe '#reason_for_not_being_ballotable_by' do describe '#reason_for_not_being_ballotable_by' do
it "rejects not logged in users" do it "rejects not logged in users" do
expect(city_sp.reason_for_not_being_ballotable_by(nil, ballot)).to eq(:not_logged_in) expect(investment.reason_for_not_being_ballotable_by(nil, ballot)).to eq(:not_logged_in)
expect(district_sp.reason_for_not_being_ballotable_by(nil, ballot)).to eq(:not_logged_in)
end end
it "rejects not verified users" do it "rejects not verified users" do
expect(city_sp.reason_for_not_being_ballotable_by(luser, ballot)).to eq(:not_verified) expect(investment.reason_for_not_being_ballotable_by(luser, ballot)).to eq(:not_verified)
expect(district_sp.reason_for_not_being_ballotable_by(luser, ballot)).to eq(:not_verified)
end end
it "rejects organizations" do it "rejects organizations" do
create(:organization, user: user) create(:organization, user: user)
expect(city_sp.reason_for_not_being_ballotable_by(user, ballot)).to eq(:organization) expect(investment.reason_for_not_being_ballotable_by(user, ballot)).to eq(:organization)
expect(district_sp.reason_for_not_being_ballotable_by(user, ballot)).to eq(:organization)
end end
it "rejects votes when voting is not allowed (via admin setting)" do it "rejects votes when voting is not allowed (via admin setting)" do
budget.phase = "on_hold" budget.phase = "on_hold"
expect(city_sp.reason_for_not_being_ballotable_by(user, ballot)).to eq(:no_ballots_allowed) expect(investment.reason_for_not_being_ballotable_by(user, ballot)).to eq(:no_ballots_allowed)
expect(district_sp.reason_for_not_being_ballotable_by(user, ballot)).to eq(:no_ballots_allowed)
end end
it "accepts valid ballots when voting is allowed" do it "accepts valid ballots when voting is allowed" do
budget.phase = "balloting" budget.phase = "balloting"
expect(city_sp.reason_for_not_being_ballotable_by(user, ballot)).to be_nil expect(investment.reason_for_not_being_ballotable_by(user, ballot)).to be_nil
expect(district_sp.reason_for_not_being_ballotable_by(user, ballot)).to be_nil
end end
it "accepts valid district selections" do it "accepts valid district selections" do
budget.phase = "selecting" budget.phase = "selecting"
expect(district_sp.reason_for_not_being_selectable_by(user)).to be_nil expect(investment.reason_for_not_being_selectable_by(user)).to be_nil
ballot.heading_id = heading.id ballot.heading_id = heading.id
expect(district_sp.reason_for_not_being_selectable_by(user)).to be_nil expect(investment.reason_for_not_being_selectable_by(user)).to be_nil
end end
it "rejects users with different headings" do it "rejects users with different headings" do
budget.phase = "balloting" budget.phase = "balloting"
california = create(:budget_heading, budget: budget) group = create(:budget_group, budget: budget)
new_york = create(:budget_heading, budget: budget) california = create(:budget_heading, group: group)
new_york = create(:budget_heading, group: group)
sp1 = create(:budget_investment, :feasible, heading: california, budget: budget) sp1 = create(:budget_investment, :feasible, heading: california)
sp2 = create(:budget_investment, :feasible, heading: new_york, budget: budget) sp2 = create(:budget_investment, :feasible, heading: new_york)
b = create(:budget_ballot, user: user, heading: california, investments: [sp1]) b = create(:budget_ballot, user: user, heading: california, investments: [sp1])
expect(sp2.reason_for_not_being_ballotable_by(user, b)).to eq(:different_heading_assigned) expect(sp2.reason_for_not_being_ballotable_by(user, b)).to eq(:different_heading_assigned)
@@ -356,9 +349,10 @@ describe Budget::Investment do
it "rejects proposals with price higher than current available money" do it "rejects proposals with price higher than current available money" do
budget.phase = "balloting" budget.phase = "balloting"
carabanchel = create(:budget_heading, budget: budget, price: 35) distritos = create(:budget_group, budget: budget)
sp1 = create(:budget_investment, :feasible, heading: carabanchel, price: 30, budget: budget) carabanchel = create(:budget_heading, group: distritos, price: 35)
sp2 = create(:budget_investment, :feasible, heading: carabanchel, price: 10, budget: budget) sp1 = create(:budget_investment, :feasible, heading: carabanchel, price: 30)
sp2 = create(:budget_investment, :feasible, heading: carabanchel, price: 10)
ballot = create(:budget_ballot, user: user, heading: carabanchel, investments: [sp1]) ballot = create(:budget_ballot, user: user, heading: carabanchel, investments: [sp1])
expect(sp2.reason_for_not_being_ballotable_by(user, ballot)).to eq(:not_enough_money) expect(sp2.reason_for_not_being_ballotable_by(user, ballot)).to eq(:not_enough_money)

View File

@@ -33,14 +33,11 @@ describe Budget do
end end
describe "heading_price" do describe "heading_price" do
let(:budget) { create(:budget, price: 1000) } let(:budget) { create(:budget) }
let(:group) { create(:budget_group, budget: budget) }
it "returns the budget price if no heading is provided" do
expect(budget.heading_price(nil)).to eq(1000)
end
it "returns the heading price if the heading provided is part of the budget" do it "returns the heading price if the heading provided is part of the budget" do
heading = create(:budget_heading, price: 100, budget: budget) heading = create(:budget_heading, price: 100, group: group)
expect(budget.heading_price(heading)).to eq(100) expect(budget.heading_price(heading)).to eq(100)
end end