Class: Booking
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Booking
- Defined in:
- app/models/booking.rb
Constant Summary collapse
- SELECT_ACCOUNTED_AMOUNT =
Accounted bookings
'CASE WHEN credit_account_id = debit_account_id THEN 0.0 WHEN credit_account_id = %{account_id} THEN -bookings.amount WHEN debit_account_id = %{account_id} THEN bookings.amount ELSE 0 END'
Class Method Summary collapse
-
.accounts ⇒ Object
All involved accounts.
-
.balance_by(account_or_id) ⇒ Object
Balance of bookings for the specified account.
-
.balance_by_grouped_reference(account_or_id) ⇒ Object
Balance of bookings for the specified account, grouped by reference.
-
.balances ⇒ Object
Accounts with balances.
-
.fiscal_years ⇒ Object
Returns array of all years we have bookings for.
-
.unbalanced_by_grouped_reference(account_or_id) ⇒ Object
Balance of bookings for the specified account with 0 balance, grouped by reference.
Instance Method Summary collapse
-
#accounted_amount(account) ⇒ Object
Helpers.
- #amount_as_string ⇒ Object
- #amount_as_string=(value) ⇒ Object
- #balance_account ⇒ Object
- #contra_account(account = nil) ⇒ Object
- #credit_account_code ⇒ Object
- #credit_account_code=(value) ⇒ Object
- #debit_account_code ⇒ Object
- #debit_account_code=(value) ⇒ Object
- #direct_account ⇒ Object
- #profit_account ⇒ Object
-
#reference_type=(value) ⇒ Object
Safety net for form assignments.
- #rounded_amount ⇒ Object
-
#split(amount, params = {}) ⇒ Object
Helpers.
-
#to_s(format = :default) ⇒ Object
Standard methods.
- #touch_previous_reference ⇒ Object
Class Method Details
.accounts ⇒ Object
All involved accounts
100 101 102 |
# File 'app/models/booking.rb', line 100 def self.accounts Account.where(id: pluck(:debit_account_id).uniq + pluck(:credit_account_id).uniq) end |
.balance_by(account_or_id) ⇒ Object
Balance of bookings for the specified account
143 144 145 |
# File 'app/models/booking.rb', line 143 def self.balance_by(account_or_id) BigDecimal.new(sum(SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }), 2) end |
.balance_by_grouped_reference(account_or_id) ⇒ Object
Balance of bookings for the specified account, grouped by reference
165 166 167 168 169 170 |
# File 'app/models/booking.rb', line 165 def self.balance_by_grouped_reference(account_or_id) grouped = group(:reference_type, :reference_id).sum(SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }) # Convert value to BigDecimal Hash[grouped.map { |reference, value| [reference, BigDecimal.new(value, 2)] }] end |
.balances ⇒ Object
Accounts with balances
107 108 109 110 111 112 113 |
# File 'app/models/booking.rb', line 107 def self.balances account_balances = accounts.map do |account| [account, balance_by(account)] end Hash[account_balances] end |
.fiscal_years ⇒ Object
Returns array of all years we have bookings for
190 191 192 193 194 |
# File 'app/models/booking.rb', line 190 def self.fiscal_years with_exclusive_scope do select('DISTINCT year(value_date) AS year').all.map(&:year) end end |
.unbalanced_by_grouped_reference(account_or_id) ⇒ Object
Balance of bookings for the specified account with 0 balance, grouped by reference
150 151 152 153 154 155 156 157 158 159 160 |
# File 'app/models/booking.rb', line 150 def self.unbalanced_by_grouped_reference(account_or_id) # Do a manual sum using select() to be able to give it an alias we can use in having() balance_select = "sum(#{SELECT_ACCOUNTED_AMOUNT % { account_id: get_account_id(account_or_id) }})" summs = group(:reference_type, :reference_id).having("#{balance_select} != 0.0").select("reference_type, reference_id, #{balance_select} AS balance").reorder(nil) # Simulate Rails grouped summing result format grouped = Hash[summs.map { |group| [[group[:reference_type], group[:reference_id]], group[:balance]] }] # Convert value to BigDecimal Hash[grouped.map { |reference, value| [reference, BigDecimal.new(value, 2)] }] end |
Instance Method Details
#accounted_amount(account) ⇒ Object
Helpers
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'app/models/booking.rb', line 219 def accounted_amount(account) if credit_account == account balance = -(amount) elsif debit_account == account balance = amount else return BigDecimal.new('0') end if account.asset_account? return balance else return -(balance) end end |
#amount_as_string ⇒ Object
235 236 237 |
# File 'app/models/booking.rb', line 235 def amount_as_string '%0.2f' % amount end |
#amount_as_string=(value) ⇒ Object
239 240 241 |
# File 'app/models/booking.rb', line 239 def amount_as_string=(value) self.amount = value end |
#balance_account ⇒ Object
56 57 58 59 |
# File 'app/models/booking.rb', line 56 def balance_account return credit_account if credit_account.balance_account? return debit_account if debit_account.balance_account? end |
#contra_account(account = nil) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'app/models/booking.rb', line 41 def contra_account(account = nil) # Derive from direct_account if available account ||= direct_account return unless account if debit_account == account return credit_account elsif credit_account == account return debit_account else return nil end end |
#credit_account_code ⇒ Object
27 28 29 |
# File 'app/models/booking.rb', line 27 def credit_account_code credit_account.code end |
#credit_account_code=(value) ⇒ Object
31 32 33 |
# File 'app/models/booking.rb', line 31 def credit_account_code=(value) credit_account = Account.find_by_code(value) end |
#debit_account_code ⇒ Object
19 20 21 |
# File 'app/models/booking.rb', line 19 def debit_account_code debit_account.code end |
#debit_account_code=(value) ⇒ Object
23 24 25 |
# File 'app/models/booking.rb', line 23 def debit_account_code=(value) debit_account = Account.find_by_code(value) end |
#direct_account ⇒ Object
35 36 37 38 39 |
# File 'app/models/booking.rb', line 35 def direct_account return nil unless reference return reference.direct_account if reference.respond_to? :direct_account end |
#profit_account ⇒ Object
61 62 63 64 |
# File 'app/models/booking.rb', line 61 def profit_account return credit_account if credit_account.profit_account? return debit_account if debit_account.profit_account? end |
#reference_type=(value) ⇒ Object
Safety net for form assignments
290 291 292 |
# File 'app/models/booking.rb', line 290 def reference_type=(value) write_attribute(:reference_type, value) unless value.blank? end |
#rounded_amount ⇒ Object
243 244 245 246 247 248 249 |
# File 'app/models/booking.rb', line 243 def rounded_amount if amount.nil? return 0 else return (amount * 20).round / 20.0 end end |
#split(amount, params = {}) ⇒ Object
Helpers
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'app/models/booking.rb', line 252 def split(amount, params = {}) # Clone new_booking = clone # Set amount new_booking[:amount] = amount self.amount -= amount # Update attributes params.each do|key, value| new_booking[key] = value end [self, new_booking] end |
#to_s(format = :default) ⇒ Object
Standard methods
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 |
# File 'app/models/booking.rb', line 197 def to_s(format = :default) case format when :long '%s: %s an %s CHF %s, %s (%s)' % [ value_date ? value_date : '?', debit_account ? "#{debit_account.title} (#{debit_account.code})" : '?', credit_account ? "#{credit_account.title} (#{credit_account.code})" : '?', amount ? '%0.2f' % amount : '?', title.present? ? title : '?', comments.present? ? comments : '?' ] else '%s: %s / %s CHF %s' % [ value_date ? value_date : '?', debit_account ? debit_account.code : '?', credit_account ? credit_account.code : '?', amount ? '%0.2f' % amount : '?' ] end end |
#touch_previous_reference ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'app/models/booking.rb', line 273 def touch_previous_reference # TODO: support reference_type for polymorphic changes reference_id_changes = changes[:reference_id] if reference_id_changes && (previous_reference_id = reference_id_changes[0]) # Guard against disappeared previous reference begin previous_reference = reference_type.constantize.find(previous_reference_id) previous_reference.touch if previous_reference != reference rescue end end end |