app/models/billing/account.rb in billing-0.0.3 vs app/models/billing/account.rb in billing-0.0.4a
- old
+ new
@@ -1,25 +1,51 @@
module Billing
class Account < ActiveRecord::Base
+ acts_as_paranoid if respond_to?(:acts_as_paranoid)
+ has_paper_trail class_name: 'Billing::Version' if respond_to?(:has_paper_trail)
+
monetize :charges_sum_cents
monetize :discounts_sum_cents
monetize :surcharges_sum_cents
monetize :payments_sum_cents
monetize :total_cents
monetize :balance_cents
belongs_to :billable, polymorphic: true
- has_many :charges, inverse_of: :account
- has_many :modifiers, inverse_of: :account
- has_many :payments, inverse_of: :account
+ has_many :charges, inverse_of: :account, dependent: :destroy
+ has_many :modifiers, inverse_of: :account, dependent: :destroy
+ has_many :payments, inverse_of: :account, dependent: :restrict_with_error
+ belongs_to :origin, inverse_of: :accounts
+ belongs_to :report, inverse_of: :accounts
+ if defined? Extface
+ belongs_to :extface_job, class_name: 'Extface::Job'
+ end
+
accepts_nested_attributes_for :charges, :modifiers, :payments
+ delegate :payment_model, to: :origin, prefix: :origin, allow_nil: true
+
+ scope :unpaid, -> { where(arel_table[:balance_cents].lt(0)) }
+ scope :open, -> { where.not(balance_cents: 0) }
+ scope :partially_paid, -> { where.not( payments_sum_cents: 0, balance_cents: 0 ) }
+
before_validation :update_sumaries
+ before_save on: :create do
+ self.number = "#{billable.id}:#{billable.billing_accounts.count}"
+ self.name = "B:#{number}" if name.nil?
+ end
+ before_save :perform_autofin, if: :becomes_paid?
+
validates_numericality_of :total, greater_than_or_equal_to: 0
+ validates_numericality_of :balance, less_than_or_equal_to: 0
+ validates_presence_of :origin, if: :has_payments?
+ validates_absence_of :payments_of_diff_models?,
+ :payments_of_diff_fiscalization?, :multiple_cash_payments?, if: :has_payments?
+
def charge(*args)
c = charges.new Charge.args(*args)
c if c.save
end
@@ -27,28 +53,50 @@
m = modifiers.new Modifier.args(*args)
m if m.save
end
def pay(*args)
- p = payments.new Payment.args(*args)
+ p = build_typed_payment Payment.args(*args)
p if p.save
end
def modifier_items
calculate_modifiers
end
def payment_types
- billable.try(:billing_payment_types) || billable.try(:payment_types) || []
+ billable.try(:billing_payment_types) || Billing::PaymentType.all
end
+
+ def origins
+ billable.try(:billing_origins) || Billing::Origin.all
+ end
+
+ def has_payments?
+ payments.any?
+ end
+
+ def paid?
+ has_payments? && balance.zero?
+ end
+
+ def build_typed_payment(attributes = {})
+ payments.new(attributes.merge(type: origin.try(:payment_model) || 'Billing::PaymentWithType'))
+ end
+
+ def fiscalize #TODO test
+ extface_job = origin.fiscal_device.fiscalize(self) if fiscalizable? && origin.try(:fiscal_device)
+ extface_job if save
+ end
private
def calculate_modifiers
@modifier_items = ModifierItems.new.tap() do |items|
modifiers.each do |modifier|
if charge = modifier.charge
- items << Charge.new(price: modifier.percent_ratio.nil? ? modifier.fixed_value : (charge.price * modifier.percent_ratio), chargable: charge)
+ charge.value = modifier.percent_ratio.nil? ? modifier.fixed_value : (charge.price * modifier.percent_ratio)
+ items << Charge.new(price: charge.value, chargable: charge)
else
items << Charge.new(price: modifier.percent_ratio.nil? ? modifier.fixed_value : (charges.to_a.sum(&:price).to_money * modifier.percent_ratio))
end
end
end
@@ -59,8 +107,38 @@
self.discounts_sum = -@modifier_items.discounts.sum(&:price).to_money
self.surcharges_sum = @modifier_items.surcharges.sum(&:price).to_money
self.payments_sum = payments.to_a.sum(&:value).to_money
self.total = charges_sum + surcharges_sum - discounts_sum
self.balance = payments_sum - total
+ end
+
+ def payments_of_diff_models?
+ payments.to_a.group_by(&:type).many?
+ end
+
+ def payments_of_diff_fiscalization?
+ payments.to_a.group_by(&:fiscal?).many?
+ end
+
+ def multiple_cash_payments?
+ payments.to_a.select(&:cash?).many?
+ end
+
+ def becomes_paid?
+ finalized_at.nil? && has_payments? && balance.zero?
+ end
+
+ def perform_autofin
+ if autofin
+ self.finalized_at = Time.now
+ if defined? Extface
+ self.extface_job = origin.fiscal_device.fiscalize(self) if fiscalizable? && origin.try(:fiscal_device)
+ end
+ end
+ true
+ end
+
+ def fiscalizable?
+ payments.select(&:fiscal?).any?
end
end
end