Created
May 30, 2014 14:21
-
-
Save ksob/af9031dd6525b3e96258 to your computer and use it in GitHub Desktop.
sageone_pl/sopl_accounts/app/models/sopl_accounts/fixed_asset.rb --- after refactoring - duplication removed - flog/flay
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module SoplAccounts | |
class FixedAsset < ActiveRecord::Base | |
self.table_name = :fixed_assets | |
belongs_to :business | |
has_one :sales_invoice, class_name: 'FujiInvoicing::SalesInvoice' | |
has_many :fixed_assets_amortizations, class_name: 'SoplAccounts::FixedAssetsAmortization', dependent: :delete_all | |
after_initialize :set_placed_in_service_date_defaults, | |
:set_acquisition_date_defaults, | |
:set_amortization_date_defaults, | |
:set_amortization_method_defaults, | |
:set_accumulated_depreciation_defaults, | |
:set_starting_value_defaults, | |
:set_amortization_rate_defaults | |
before_save :build_amortization_plan | |
scope :filter_by_name, ->(term) { where('UPPER(name) LIKE ?', "%#{term}%") } | |
scope :filter_by_service_date, | |
->(term) { where('MONTH(placed_in_service_date) = ?', "#{term}") } | |
scope :sort_by_liquidation_or_sale_date, ->(order) { order("coalesce(liquidation_date, sale_date) #{order}") } | |
validates :name, presence: true | |
validates :placed_in_service_date, presence: true | |
validates :acquisition_date, presence: true | |
validates :amortization_date, presence: true | |
validates :classification, presence: true | |
validates :amortization_rate, presence: true | |
validates :starting_value, presence: true | |
validates :amortization_rate, :numericality => | |
{ :greater_than => 0.00, :less_than_or_equal_to => 100.00 } | |
validates :starting_value, :numericality => | |
{ :greater_than => 0.00, :less_than => 10000000000000.00 } | |
validates :accumulated_depreciation, :numericality => | |
{ :less_than => 10000000000000.00 } | |
validate :ensure_placed_in_service_date_grater_or_equal_acquisition_date | |
validate :ensure_amortization_date_grater_or_equal_placed_in_service_date | |
validate :ensure_starting_value_grater_or_equal_accumulated_depreciation | |
validates :liquidation_date, presence: true, if: ->(r) { r.liquidation_date.present? } | |
validates :liquidation_reason, presence: true, if: ->(r) { r.liquidation_date.present? } | |
attr_accessible :accumulated_depreciation, :acquisition_date, :amortization_date, | |
:amortization_method, :amortization_rate, :classification, | |
:description, :invoice_number, :name, | |
:placed_in_service_date, :starting_value, | |
:liquidation_date, :liquidation_reason | |
grid_data_is :name, :placed_in_service_date, :acquisition_date, | |
:starting_value, :accumulated_depreciation, | |
:liquidation_or_sale_date | |
def formatted | |
name | |
end | |
def liquidation_or_sale_date | |
liquidation_date.presence || sale_date.presence | |
end | |
def depreciations_this_month | |
0 # TODO | |
end | |
def depreciations_cumulatively_this_year | |
0 # TODO | |
end | |
def left_to_depreciate | |
fixed_assets_amortizations.sum(:amount) - fixed_assets_amortizations.where(accounted: true).sum(:amount) | |
end | |
def updated_starting_value | |
0 # TODO | |
end | |
def liquidated? | |
liquidation_date? | |
end | |
def sold? | |
sales_invoice.present? | |
end | |
def editable? | |
!liquidated? && !sold? | |
end | |
def recalculate_amortization_plan(attrs) | |
FixedAsset.transaction do | |
base = (starting_value - accumulated_depreciation) | |
total = 0 | |
fixed_assets_amortizations.where(accounted: false).each do |record| | |
new_val = attrs[record.id.to_s] | |
record.amount = new_val | |
total += record.amount | |
if record.amount_changed? && total > base | |
raise "incorrect" | |
end | |
end | |
total = 0 | |
yearly_total = 0 | |
fixed_assets_amortizations.where(accounted: true).each do |record| | |
total += record.amount | |
end | |
year = amortization_date.year | |
month = amortization_date.month | |
yearly_amount = (starting_value * amortization_rate / 100.0).round(2) | |
monthly_amount = (yearly_amount / 12.0).round(2) | |
# we can't use monthly amount here because calculations don't match algorithm | |
first_year_amount = ((yearly_amount / 12.0) * (12 - month + 1)).round(2) | |
fixed_assets_amortizations.where(accounted: false).each do |record| | |
new_val = attrs[record.id.to_s] | |
total += new_val.to_f | |
if total > base | |
record.destroy | |
else | |
record.amount = new_val | |
record.modified = true if record.amount_changed? | |
record.save | |
end | |
end | |
last_record = fixed_assets_amortizations.where(accounted: false).order('id DESC').first | |
last_record.destroy # remove record without full amount | |
last_record = fixed_assets_amortizations.where(accounted: false).order('id DESC').first | |
total = 0 | |
fixed_assets_amortizations.each do |record| | |
total += record.amount | |
end | |
year = last_record.year | |
month = last_record.month + 1 | |
if month > 12 | |
month = 1 | |
year += 1 | |
end | |
fixed_assets_amortizations.where(year: year).each do |record| | |
yearly_total += record.amount | |
end | |
eval common_amortization_code "create!" | |
true | |
end | |
rescue | |
false | |
end | |
def reset_amortization_plan | |
FixedAsset.transaction do | |
fixed_assets_amortizations.where(accounted: false).delete_all | |
total = 0 | |
yearly_total = 0 | |
fixed_assets_amortizations.each do |record| | |
total += record.amount | |
end | |
last_record = fixed_assets_amortizations.order('id DESC').first | |
year = amortization_date.year | |
month = amortization_date.month | |
base = (starting_value - accumulated_depreciation) | |
yearly_amount = (starting_value * amortization_rate / 100.0).round(2) | |
monthly_amount = (yearly_amount / 12.0).round(2) | |
# we can't use monthly amount here because calculations don't match algorithm | |
first_year_amount = ((yearly_amount / 12.0) * (12 - month + 1)).round(2) | |
if last_record | |
year = last_record.year | |
month = last_record.month + 1 | |
if month > 12 | |
month = 1 | |
year += 1 | |
end | |
end | |
fixed_assets_amortizations.where(year: year).each do |record| | |
yearly_total += record.amount | |
end | |
eval common_amortization_code "create!" | |
end | |
end | |
private | |
def common_amortization_code(create_or_build) | |
<<-eos | |
while base > total | |
yearly_total += monthly_amount | |
amount = monthly_amount | |
if month == 12 | |
if year == amortization_date.year | |
amount += first_year_amount - yearly_total | |
else | |
amount += yearly_amount - yearly_total | |
end | |
end | |
total += amount | |
amount += (base - total) if total > base | |
fixed_assets_amortizations.#{create_or_build} year: year, | |
month: month, | |
amount: amount | |
month += 1 | |
if month > 12 | |
month = 1 | |
year += 1 | |
yearly_total = 0 | |
end | |
end | |
eos | |
end | |
def set_placed_in_service_date_defaults | |
self.placed_in_service_date ||= Date.today if new_record? | |
end | |
def set_acquisition_date_defaults | |
self.acquisition_date ||= Date.today if new_record? | |
end | |
def set_amortization_date_defaults | |
if new_record? | |
date = Date.today.end_of_month + 1 | |
self.amortization_date ||= date | |
end | |
end | |
def set_amortization_method_defaults | |
self.amortization_method ||= "liniowa" if new_record? | |
self.acquisition_date ||= Date.today if new_record? | |
end | |
def set_accumulated_depreciation_defaults | |
self.accumulated_depreciation ||= 0.00 if new_record? | |
end | |
def set_starting_value_defaults | |
self.starting_value ||= 0.00 if new_record? | |
end | |
def set_amortization_rate_defaults | |
self.amortization_rate ||= 0 if new_record? | |
end | |
def ensure_placed_in_service_date_grater_or_equal_acquisition_date | |
return if !placed_in_service_date || !acquisition_date | |
if placed_in_service_date < acquisition_date | |
errors.add :placed_in_service_date, :earlier_than_aquisition | |
end | |
end | |
def ensure_amortization_date_grater_or_equal_placed_in_service_date | |
return if !placed_in_service_date || !amortization_date | |
if amortization_date < placed_in_service_date | |
errors.add :amortization_date, :earlier_than_placed_in_service | |
end | |
end | |
def ensure_starting_value_grater_or_equal_accumulated_depreciation | |
return if !starting_value || !accumulated_depreciation | |
if starting_value < accumulated_depreciation | |
errors.add :accumulated_depreciation, :bigger_than_starting_value | |
end | |
end | |
def build_amortization_plan | |
return unless amortization_rate_changed? | |
fixed_assets_amortizations.delete_all | |
base = (starting_value - accumulated_depreciation) | |
year = amortization_date.year | |
month = amortization_date.month | |
yearly_amount = (starting_value * amortization_rate / 100.0).round(2) | |
monthly_amount = (yearly_amount / 12.0).round(2) | |
# we can't use monthly amount here because calculations don't match algorithm | |
first_year_amount = ((yearly_amount / 12.0) * (12 - month + 1)).round(2) | |
total = 0 | |
yearly_total = 0 | |
eval common_amortization_code "build" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment