class Skr::Invoice

Invoices constitute a demand for payment for goods that have been delivered to a {Customer}. A invoice contains:

* Customer contact information
* An inventory location that goods will be taken from.
* The customer provided {PurchaseOrder} Number
* The Payment Terms that were extended. This will control how much time the Customer has to pay the invoice in full.
* One or more SKUs, the quantity desired for each and the selling price for them.

While an {Invoice} often originates with a {SalesOrder}, it does not have to. Sales that take place in a retail environment where the customer selects the goods and pays for them immediately do not require a sales order record.

Once an invoice is saved, it immediately removes the SKUs from the {SkuLoc} and generates corresponding General Ledger entries debiting the asset account and crediting the customers receivables account.

When payment is received against the Invoice, the receivables account is debited and the payments holding account is credited.

invoice = Invoice.new( customer: Customer.find_by_code("ACME")
invoice.lines.build({ sku: Sku.find_by_code('LABOR'), qty: 1, price: 8.27 })
invoice.save

Public Class Methods

new(attributes = {}) click to toggle source
Calls superclass method
# File lib/skr/invoice.rb, line 77
def initialize(attributes = {})
    super
    self.invoice_date = Date.today
end

Public Instance Methods

fully_paid?() click to toggle source

@return [Boolean] is the invoice paid in full

# File lib/skr/invoice.rb, line 88
def fully_paid?
    unpaid_amount <= 0
end
unpaid_amount() click to toggle source

@return [BigDecimal] total - amount_paid

# File lib/skr/invoice.rb, line 83
def unpaid_amount
    self.total - amount_paid
end

Private Instance Methods

apply_balances() click to toggle source
# File lib/skr/invoice.rb, line 110
def apply_balances
    return unless amount_paid_changed?
    change = amount_paid - amount_paid_was

    Skr::Core.logger.debug "Applying payment #{amount_paid} changed: #{change}"

    return if change.zero?

    GlTransaction.push_or_save(
      owner: self, amount: change,
      debit: customer.gl_receivables_account, credit: GlAccount.default_for(:deposit_holding)
    )
    fire_event( :amount_paid_change )
    true
end
attributes_for_gl_transaction() click to toggle source

attributes for GlTransaction

# File lib/skr/invoice.rb, line 95
def attributes_for_gl_transaction
    {   location: location, source: self,
        description: "INV #{self.visible_id}" }
end
ensure_location_matches_so() click to toggle source
# File lib/skr/invoice.rb, line 150
def ensure_location_matches_so
    if sales_order && location != sales_order.location
        self.errors.add(:location, "#{location.code} must match location that order was taken on (#{sales_order.location.code})")
    end
end
maybe_mark_paid() click to toggle source

set the state if the amount_paid was changed

# File lib/skr/invoice.rb, line 101
def maybe_mark_paid
    return unless amount_paid_changed?
    if self.fully_paid? && self.may_mark_paid?
        self.state_event = 'mark_paid'
    elsif self.amount_paid > 0 && self.may_mark_partial?
        self.state_event = 'mark_partial'
    end
end
set_defaults() click to toggle source
# File lib/skr/invoice.rb, line 127
def set_defaults

    if pick_ticket
        self.location    = pick_ticket.location
        self.sales_order = pick_ticket.sales_order
    end

    if sales_order
        self.terms          ||= sales_order.terms
        self.customer         = sales_order.customer
        self.po_num           = sales_order.po_num if self.po_num.blank?
        self.billing_address  = sales_order.billing_address   if self.billing_address.blank?
        self.shipping_address = sales_order.shipping_address  if self.shipping_address.blank?
        self.options.merge!(sales_order.options)
    end

    if customer
        self.billing_address = customer.billing_address   if self.billing_address.blank?
        self.shipping_address = customer.shipping_address if self.shipping_address.blank?
    end

end