We were using the same logic twice. I've moved the logic to the Ballot model, which to me is a more natural place to calculate whether there's enough money left than the Investment model. After all, the remaining money is in the ballot, and not in the investment.
50 lines
1.5 KiB
Ruby
50 lines
1.5 KiB
Ruby
class Budget
|
|
class Ballot
|
|
class Line < ApplicationRecord
|
|
belongs_to :ballot, counter_cache: :ballot_lines_count
|
|
belongs_to :investment, counter_cache: :ballot_lines_count
|
|
belongs_to :heading
|
|
belongs_to :group
|
|
belongs_to :budget
|
|
|
|
validates :ballot_id, :investment_id, :heading_id, :group_id, :budget_id, presence: true
|
|
|
|
validate :check_selected
|
|
validate :check_sufficient_funds
|
|
validate :check_valid_heading
|
|
|
|
scope :by_investment, ->(investment_id) { where(investment_id: investment_id) }
|
|
|
|
before_validation :set_denormalized_ids
|
|
after_save :store_user_heading
|
|
|
|
def check_sufficient_funds
|
|
ballot.lock!
|
|
errors.add(:money, "insufficient funds") unless ballot.enough_money?(investment)
|
|
end
|
|
|
|
def check_valid_heading
|
|
return if ballot.valid_heading?(heading)
|
|
|
|
errors.add(:heading, "This heading's budget is invalid, or a heading on the same group was already selected")
|
|
end
|
|
|
|
def check_selected
|
|
errors.add(:investment, "unselected investment") unless investment.selected?
|
|
end
|
|
|
|
private
|
|
|
|
def set_denormalized_ids
|
|
self.heading_id ||= investment&.heading_id
|
|
self.group_id ||= investment&.group_id
|
|
self.budget_id ||= investment&.budget_id
|
|
end
|
|
|
|
def store_user_heading
|
|
ballot.user.update(balloted_heading_id: heading.id) unless ballot.physical == true
|
|
end
|
|
end
|
|
end
|
|
end
|