module ActsAsAccount class Journal < ActiveRecord::Base self.table_name = :acts_as_account_journals has_many :postings, :class_name => 'ActsAsAccount::Posting' has_many :accounts, :through => :postings class << self private :new private :create private :create! def current Thread.current[:acts_as_account_current] ||= create! end def clear_current Thread.current[:acts_as_account_current] = nil end end def transfers postings.each_slice(2).map { |postings| Transfer.new(*postings) } end def transfer(amount, from_account, to_account, reference = nil, valuta = Time.now) transaction do if (amount < 0) # change order if amount is negative amount, from_account, to_account = -amount, to_account, from_account end if logger logger.debug( [ "ActsAsAccount::Journal.transfer", "amount: #{amount}", "from: #{from_account.id}", "to: #{to_account.id}", "reference: #{reference.class.name}(#{reference&.id})", "valuta: #{valuta}", ].join(' ') ) end # To avoid possible deadlocks we need to ensure that the locking order # is always the same therfore the sort by id. if ActsAsAccount.configuration.persist_attributes_on_account [from_account, to_account].sort_by(&:id).each(&:lock!) end posting1 = build_posting(-amount, from_account, to_account, reference, valuta) posting2 = build_posting( amount, to_account, from_account, reference, valuta) result = postings.model.insert_all([ posting1.attributes.compact, posting2.attributes.compact ]) update_attributes_on(from_account, -amount) update_attributes_on(to_account, amount) !!result end end private def build_posting(amount, account, other_account, reference, valuta) postings.build( :amount => amount, :account => account, :other_account => other_account, :reference => reference, :valuta => valuta ) end def update_attributes_on(account, amount) return unless ActsAsAccount.configuration.persist_attributes_on_account account.class.update_counters account.id, postings_count: 1, balance: amount end end end