tamaloa/direktkreditverwaltung

View on GitHub
app/models/year_end_closing.rb

Summary

Maintainability
A
0 mins
Test Coverage
class YearEndClosing
  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend ActiveModel::Naming

  attr_accessor :year

  validates :year, presence: true
  validates :year, :numericality => true

  def initialize(attributes = {})
    @year = attributes[:year] || Time.now.prev_year.year
    @year = @year.to_i #TODO fix this on controller side with strong params?
  end


  def close_year!
    Contract.where(add_interest_to_deposit_annually: true).each do |contract|
      close_year_for_contract(contract)
    end
  end

  def close_year_for_contract(contract)
    return false if contract.start_date.year > @year
    return false if year_closed?(contract)
    return false if contract.terminated_at.present?
    last_years_interest = InterestCalculation.new(contract, year: @year).interest_total
    contract.accounting_entries.create!(amount: last_years_interest, date: Date.new(@year).end_of_year,
                                        annually_closing_entry: true, interest_entry: true)
  end

  def year_closed?(contract)
    closing_entry_for_this_year = contract.accounting_entries.only_from_year(@year).where(annually_closing_entry: true)
    return false if closing_entry_for_this_year.empty?
    true
  end

  def revert
    raise "Overthink this ... propably better to only allow single contracts to be reverted"
    end_of_year_date = Date.new(@year).end_of_year.to_date
    AccountingEntry.where(date: end_of_year_date, annually_closing_entry: true).delete_all
    #TODO what to do with terminated contracts (should interest always be deleted)
    #Vielleicht verträge mit terminated at ausschließen
  end
  
  def self.most_recent_one
    year_closing_entry = AccountingEntry.
        order('date DESC').where(annually_closing_entry: true).
        reject{|e| e.contract.terminated_at.present?}.first
    return nil unless year_closing_entry
    year_closing_entry.date.year
  end

  def self.next_one
    return 7.years.ago.year unless most_recent_one
    most_recent_one + 1
  end

  def self.all
    AccountingEntry.where(annually_closing_entry: true).map{|entry| entry.date.year}.uniq.sort.reverse
  end

  def contracts
    AccountingEntry.only_from_year(@year).where(annually_closing_entry: true).map(&:contract)
  end

  def email_all_closing_statements
    mail_template = MailTemplate.find_by_year(@year)
    contacts_and_contracts_with_email.each do |contact, contracts|
      Email.create!(contact: contact,
                    mail_template: mail_template,
                    year: @year,
                    contracts: contracts)
    end
  end

  def contacts_and_contracts_with_email
    contracts.group_by(&:contact).reject{|contact, contract| contact.blank? || contact.email.blank?}
  end

  def contacts_and_contracts_without_email
    contracts.group_by(&:contact).select{|contact, contract| contact.blank? || contact.email.blank?}
  end

  #TODO: This really belongs some where else
  require 'csv'
  def as_csv
    CSV.generate do |csv|
      csv << ['DK#', 'DK Geber_in', 'Vorjahressaldo', 'Kontobewegungen', 'Zinsen', 'Saldo Jahresabschluss']
      contracts.each do |contract|
        row = []
        row << contract.number
        row << ApplicationController.helpers.contact_short(contract.contact)
        row << ApplicationController.helpers.currency(balance_closing_of_year_before(contract))
        row << movements_excluding_interest(contract)
        row << ApplicationController.helpers.currency(annual_interest(contract))
        row << ApplicationController.helpers.currency(balance_closing_of_year(contract))
        csv << row
      end
    end
  end

  def persisted?
    false
  end
  def to_param
    year
  end

  #We might want to move this into a separate model/presenter soon
  def balance_closing_of_year_before(contract)
    movement = InterestCalculation.new(contract, year: @year).account_movements_with_initial_balance.first
    movement[:amount]
  end
  def movements_excluding_interest(contract)
    movements = InterestCalculation.new(contract, year: @year).account_movements_with_initial_balance
    without_initial_balance = movements.drop(1) # Initial balance
    only_non_interest = without_initial_balance.reject{|m| m[:type] == :interest_entry}
    only_non_interest.map{|m| m[:date].iso8601 + ' ' + m[:amount].to_s}.to_sentence
  end
  def annual_interest(contract)
    InterestCalculation.new(contract, year: @year).interest_total
  end
  def balance_closing_of_year(contract)
    movement = InterestCalculation.new(contract, year: @year+1).account_movements_with_initial_balance.first
    movement[:amount]
  end

end