Skip to content

Instantly share code, notes, and snippets.

@guipdutra
Created July 9, 2013 17:37
Show Gist options
  • Save guipdutra/5959431 to your computer and use it in GitHub Desktop.
Save guipdutra/5959431 to your computer and use it in GitHub Desktop.
class BudgetAllocation < Accounting::Model
include Accountable
extend ActiveRecord::DescriptorScope
attr_accessible :budget_structure_id, :date, :subfunction_id,
:government_program_id, :personal,
:government_action_id, :foresight, :education,
:expense_nature_id, :kind, :debt_type,
:budget_allocation_type_id, :refinancing, :health,
:alienation_appeal, :function_id, :year,
:budget_allocation_capabilities_attributes, :months_values
serialize :months_values, Hash
attr_readonly :code, :descriptor_id
attr_modal :code, :balance_with_currency
auto_increment :code, :by => :descriptor_id
has_enumeration_for :debt_type
has_enumeration_for :kind, :with => BudgetAllocationKind, :create_helpers => true
belongs_to :descriptor
belongs_to :budget_structure
belongs_to :function
belongs_to :subfunction
belongs_to :government_program
belongs_to :government_action
belongs_to :expense_nature
belongs_to :budget_allocation_type
has_many :pledges, :dependent => :restrict
has_many :reserve_funds, :dependent => :restrict
has_many :extra_credit_moviment_types, :dependent => :restrict
has_many :pledge_liquidations, :through => :pledges
has_many :pledge_cancellations, :through => :pledges
has_many :payments, :through => :pledges
has_many :budget_allocation_capabilities, :dependent => :destroy, :inverse_of => :budget_allocation
has_many :capabilities, :through => :budget_allocation_capabilities
accepts_nested_attributes_for :budget_allocation_capabilities, :allow_destroy => true
delegate :expense_nature, :description, :kind, :to => :expense_nature, :allow_nil => true, :prefix => true
delegate :code, :budget_structure, :structure_sequence, :to => :budget_structure, :prefix => true, :allow_nil => true
delegate :code, :to => :function, :prefix => true, :allow_nil => true
delegate :code, :to => :subfunction, :prefix => true, :allow_nil => true
delegate :code, :to => :government_program, :prefix => true, :allow_nil => true
delegate :code, :action_type, :to => :government_action, :prefix => true, :allow_nil => true
validates :descriptor, :budget_structure, :subfunction, :date,
:government_program, :government_action, :budget_allocation_type,
:expense_nature, :function, :year, :presence => true
validates :amount, :presence => true, :if => :divide?
validates :code, :uniqueness => { :scope => [:descriptor_id, :year] }, :allow_blank => true
validates :budget_allocation_capabilities, :presence => true, :if => :divide?
validates :date, :blockage_period => true
validates :date, :accountable_date => true
validates :year, :mask => "9999", :allow_blank => true
validate :year_less_than_or_equal_to_descriptor_year
validate :structure_kind_must_be_analytical
validate :capability_total_equals_amount, :if => :divide?
validate :months_values_equals_amount, :if => :divide?
validate :budget_structure_year_equal_year
validate :function_year_equal_year
validate :subfunction_year_equal_year
validate :government_program_year_equal_year
validate :government_action_year_equal_year
validate :expense_nature_year_equal_year
validate :date_year_must_be_equal_year
before_create :set_default_months_values
after_create :insert_in_date_controls
orderize :code
scope :by_year, lambda { |year| where(year: year) if year.present? }
def self.filter(options)
query = scoped
query = query.where { code.eq(options[:code]) } if options[:code].present?
query = query.where { budget_structure_id.eq(options[:budget_structure_id]) } if options[:budget_structure_id].present?
query = query.where { subfunction_id.eq(options[:subfunction_id]) } if options[:subfunction_id].present?
query = query.where { government_program_id.eq(options[:government_program_id]) } if options[:government_program_id].present?
query = query.where { government_action_id.eq(options[:government_action_id]) } if options[:government_action_id].present?
query = query.where { expense_nature_id.eq(options[:expense_nature_id]) } if options[:expense_nature_id].present?
query = query.where { function_id.eq(options[:function_id]) } if options[:function_id].present?
query = query.where { descriptor_id.eq(options[:descriptor_id]) } if options[:descriptor_id].present?
query = query.where { year.eq(params[:year]) } if options[:year].present?
query
end
def self.search(params)
includes(:function,
:subfunction,
:government_program,
:government_action,
:capabilities,
:expense_nature).
where(params)
end
def destroyable?
false
end
def updateable?
false
end
def structure_kind_must_be_analytical
return unless budget_structure
unless budget_structure.analytical?
errors.add(:budget_structure, :must_be_analytical)
end
end
def reserved_value
reserve_funds.sum(&:balance)
end
def balance
total_by_extra_credit - reserved_value - pledges_balance
end
def to_s
"#{code} - #{expense_nature.to_s}"
end
def add_extra_credit_sum
extra_credit_moviment_types.add.sum(:value)
end
def subtract_extra_credit_sum
extra_credit_moviment_types.subtract.sum(:value)
end
def total_by_extra_credit
amount + add_extra_credit_sum - subtract_extra_credit_sum
end
def amount_for_period(period)
return 0 if period.year != year || amount.nil?
(amount / 12) * period.months
end
def pledged_amount(period)
pledges.by_date(period.range).inject(0) { |sum, pledge| sum + pledge.net_amount }
end
def total_pledged_amount(period)
pledges.by_date(period.range).sum(:amount)
end
def total_pledged_amount_until(period)
range = (Date.new(period.year, 1, 1)..period.initial_date)
pledges.by_date(range).sum(:amount)
end
def liquidations_amount(period)
pledge_liquidations.by_date(period.range).sum(:amount)
end
def liquidations_amount_until(period)
range = (Date.new(period.year, 1, 1)..period.initial_date)
pledge_liquidations.paid.by_date(range).sum(:amount)
end
def cancellations_amount(period)
pledge_cancellations.by_date(period.range).sum(:amount)
end
def cancellations_and_subtract_extra_credit
pledge_cancellations.sum(:amount) + subtract_extra_credit_sum
end
def total_by_extra_credit
(amount + add_extra_credit_sum) - cancellations_and_subtract_extra_credit
end
def cancellations_amount_until(period)
range = (Date.new(period.year, 1, 1)..period.initial_date)
pledge_cancellations.by_date(range).sum(:amount)
end
def payments_amount(period)
payments.by_issuing_date(period.range).sum(:amount)
end
def payments_amount_until(period)
range = (Date.new(period.year, 1, 1)..period.initial_date)
payments.by_issuing_date(range).sum(:amount)
end
def functional_code
"#{function.code}.#{subfunction.code}.#{government_program.code}.#{government_action.code}"
end
def capability_source
capabilities.map(&:capability_source).map(&:to_s).uniq.join(', ')
end
def capability
capabilities.map(&:to_s).uniq.join(', ')
end
def months_sum
months_values.values.map{ |i| pt_to_en_float(i) }.sum
end
def amount
capability_total
end
def balance_by_capability(capability)
return if capability.blank?
capability_amount(capability) + capability.extra_credit_balance_by_capability - capability.pledges_balance_by_capability
end
private
def capability_amount(capability)
return 0 if budget_allocation_capabilities.empty?
budget_allocation_capabilities.by_capability(capability).first.amount
end
def insert_in_date_controls
DateControl.create!(:date => date,
:descriptor => descriptor)
end
def date_year_must_be_equal_year
return unless date.present? && year.present?
unless date.year == year
errors.add(:date, :must_have_same_year_budget_allocation, :year => year)
end
end
def budget_structure_year_equal_year
return unless year.present? && budget_structure.present?
unless budget_structure.budget_structure_configuration.year == year
errors.add(:budget_structure, :must_have_same_year_budget_allocation, :year => year)
end
end
def function_year_equal_year
return unless year.present? && function.present?
unless function.year == year
errors.add(:function, :must_have_same_year_budget_allocation, :year => year)
end
end
def subfunction_year_equal_year
return unless year.present? && subfunction.present?
unless subfunction.year == year
errors.add(:subfunction, :must_have_same_year_budget_allocation, :year => year)
end
end
def government_program_year_equal_year
return unless year.present? && government_program.present?
unless government_program.year == year
errors.add(:government_program, :must_have_same_year_budget_allocation, :year => year)
end
end
def government_action_year_equal_year
return unless year.present? && government_action.present?
unless government_action.year == year
errors.add(:government_action, :must_have_same_year_budget_allocation, :year => year)
end
end
def expense_nature_year_equal_year
return unless year.present? && expense_nature.present?
unless expense_nature.year == year
errors.add(:expense_nature, :must_have_same_year_budget_allocation, :year => year)
end
end
def pledged_value
pledges.sum(:amount)
end
def pledges_balance
pledges.sum(&:balance)
end
def capability_total_equals_amount
return unless amount.present?
if capability_total != amount
errors.add(:amount, :should_equal_capability_total)
end
end
def months_values_equals_amount
return if months_values.empty?
if months_sum != amount
errors.add(:months_sum, :should_equal_to_total_value)
end
end
def year_less_than_or_equal_to_descriptor_year
return unless year.present?
if year > descriptor.year
errors.add(:year, :less_than_or_equal_to, :count => descriptor.year)
end
end
def capability_total
budget_allocation_capabilities.reject{ |capability|
capability.marked_for_destruction? || capability.amount.blank?
}.map(&:amount).sum
end
def set_default_months_values
if self.months_values.empty?
self.months_values = { "1" => "0,00", "2" => "0,00", "3" => "0,00",
"4" => "0,00", "5" => "0,00", "6" => "0,00",
"7" => "0,00", "8" => "0,00", "9" => "0,00",
"10" => "0,00", "11" => "0,00", "12" => "0,00" }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment