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
# File lib/skr/invoice.rb, line 77 def initialize(attributes = {}) super self.invoice_date = Date.today end
Public Instance Methods
@return [Boolean] is the invoice paid in full
# File lib/skr/invoice.rb, line 88 def fully_paid? unpaid_amount <= 0 end
@return [BigDecimal] total - amount_paid
# File lib/skr/invoice.rb, line 83 def unpaid_amount self.total - amount_paid end
Private Instance Methods
# 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 GlTransaction
# File lib/skr/invoice.rb, line 95 def attributes_for_gl_transaction { location: location, source: self, description: "INV #{self.visible_id}" } end
# 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
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
# 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