Class: XeroGateway::Invoice

Inherits:
Object
  • Object
show all
Includes:
Dates, LineItemCalculations, Money
Defined in:
lib/xero_gateway/invoice.rb

Constant Summary collapse

INVOICE_TYPE =
{
  'ACCREC' =>           'Accounts Receivable',
  'ACCPAY' =>           'Accounts Payable'
}
LINE_AMOUNT_TYPES =
{
  "Inclusive" =>        'Invoice lines are inclusive tax',
  "Exclusive" =>        'Invoice lines are exclusive of tax (default)',
  "NoTax"     =>        'Invoices lines have no tax'
}
INVOICE_STATUS =
{
  'AUTHORISED' =>       'Approved invoices awaiting payment',
  'DELETED' =>          'Draft invoices that are deleted',
  'DRAFT' =>            'Invoices saved as draft or entered via API',
  'PAID' =>             'Invoices approved and fully paid',
  'SUBMITTED' =>        'Invoices entered by an employee awaiting approval',
  'VOID' =>             'Approved invoices that are voided'
}
GUID_REGEX =
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from LineItemCalculations

#add_line_item, #sub_total, #sub_total=, #total, #total=, #total_tax, #total_tax=

Methods included from Money

included

Methods included from Dates

included

Constructor Details

#initialize(params = {}) ⇒ Invoice

Returns a new instance of Invoice.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/xero_gateway/invoice.rb', line 42

def initialize(params = {})
  @errors ||= []
  @payments ||= []
  
  # Check if the line items have been downloaded.
  @line_items_downloaded = (params.delete(:line_items_downloaded) == true)
  
  params = {
    :line_amount_types => "Exclusive"
  }.merge(params)
  
  params.each do |k,v|
    self.send("#{k}=", v)
  end
  
  @line_items ||= []
end

Instance Attribute Details

#amount_creditedObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def amount_credited
  @amount_credited
end

#amount_dueObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def amount_due
  @amount_due
end

#amount_paidObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def amount_paid
  @amount_paid
end

#contactObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def contact
  @contact
end

#currency_codeObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def currency_code
  @currency_code
end

#dateObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def date
  @date
end

#due_dateObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def due_date
  @due_date
end

#errorsObject (readonly)

Any errors that occurred when the #valid? method called.



33
34
35
# File 'lib/xero_gateway/invoice.rb', line 33

def errors
  @errors
end

#fully_paid_onObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def fully_paid_on
  @fully_paid_on
end

#gatewayObject

Xero::Gateway associated with this invoice.



30
31
32
# File 'lib/xero_gateway/invoice.rb', line 30

def gateway
  @gateway
end

#invoice_idObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def invoice_id
  @invoice_id
end

#invoice_numberObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def invoice_number
  @invoice_number
end

#invoice_statusObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def invoice_status
  @invoice_status
end

#invoice_typeObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def invoice_type
  @invoice_type
end

#line_amount_typesObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def line_amount_types
  @line_amount_types
end

#line_itemsObject

If line items are not downloaded, then attempt a download now (if this record was found to begin with).



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def line_items
  @line_items
end

#line_items_downloadedObject

Represents whether the line_items have been downloaded when getting from GET /API.XRO/2.0/INVOICES



36
37
38
# File 'lib/xero_gateway/invoice.rb', line 36

def line_items_downloaded
  @line_items_downloaded
end

#paymentsObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def payments
  @payments
end

#referenceObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def reference
  @reference
end

#sent_to_contactObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def sent_to_contact
  @sent_to_contact
end

#urlObject

All accessible fields



39
40
41
# File 'lib/xero_gateway/invoice.rb', line 39

def url
  @url
end

Class Method Details

.from_xml(invoice_element, gateway = nil, options = {}) ⇒ Object

TODO UpdatedDateUTC



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'lib/xero_gateway/invoice.rb', line 201

def self.from_xml(invoice_element, gateway = nil, options = {})
  invoice = Invoice.new(options.merge({:gateway => gateway}))
  invoice_element.children.each do |element|
    case(element.name)
      when "InvoiceID" then invoice.invoice_id = element.text
      when "InvoiceNumber" then invoice.invoice_number = element.text            
      when "Type" then invoice.invoice_type = element.text
      when "CurrencyCode" then invoice.currency_code = element.text
      when "Contact" then invoice.contact = Contact.from_xml(element)
      when "Date" then invoice.date = parse_date(element.text)
      when "DueDate" then invoice.due_date = parse_date(element.text)
      when "Status" then invoice.invoice_status = element.text
      when "Reference" then invoice.reference = element.text
      when "LineAmountTypes" then invoice.line_amount_types = element.text
      when "LineItems" then element.children.each {|line_item| invoice.line_items_downloaded = true; invoice.line_items << LineItem.from_xml(line_item) }
      when "SubTotal" then invoice.sub_total = BigDecimal.new(element.text)
      when "TotalTax" then invoice.total_tax = BigDecimal.new(element.text)
      when "Total" then invoice.total = BigDecimal.new(element.text)
      when "InvoiceID" then invoice.invoice_id = element.text
      when "InvoiceNumber" then invoice.invoice_number = element.text            
      when "Payments" then element.children.each { | payment | invoice.payments << Payment.from_xml(payment) }
      when "AmountDue" then invoice.amount_due = BigDecimal.new(element.text)
      when "AmountPaid" then invoice.amount_paid = BigDecimal.new(element.text)
      when "AmountCredited" then invoice.amount_credited = BigDecimal.new(element.text)
      when "SentToContact" then invoice.sent_to_contact = (element.text.strip.downcase == "true")
      when "Url" then invoice.url = element.text
    end
  end      
  invoice
end

Instance Method Details

#==(other) ⇒ Object



144
145
146
147
148
149
150
151
152
153
# File 'lib/xero_gateway/invoice.rb', line 144

def ==(other)
  ["invoice_number", "invoice_type", "invoice_status", "reference", "currency_code", "line_amount_types", "contact", "line_items"].each do |field|
    return false if send(field) != other.send(field)
  end
  
  ["date", "due_date"].each do |field|
    return false if send(field).to_s != other.send(field).to_s
  end
  return true
end

#accounts_payable?Boolean

Helper method to check if the invoice is accounts payable.

Returns:

  • (Boolean)


108
109
110
# File 'lib/xero_gateway/invoice.rb', line 108

def accounts_payable?
  invoice_type == 'ACCPAY'
end

#accounts_receivable?Boolean

Helper method to check if the invoice is accounts receivable.

Returns:

  • (Boolean)


113
114
115
# File 'lib/xero_gateway/invoice.rb', line 113

def accounts_receivable?
  invoice_type == 'ACCREC'
end

#build_contact(params = {}) ⇒ Object

Helper method to create the associated contact object.



99
100
101
# File 'lib/xero_gateway/invoice.rb', line 99

def build_contact(params = {})
  self.contact = gateway ? gateway.build_contact(params) : Contact.new(params)
end

#createObject

Creates this invoice record (using gateway.create_invoice) with the associated gateway. If no gateway set, raise a NoGatewayError exception.

Raises:



167
168
169
170
# File 'lib/xero_gateway/invoice.rb', line 167

def create
  raise NoGatewayError unless gateway
  gateway.create_invoice(self)
end

#line_items_downloaded?Boolean

Whether or not the line_items have been downloaded (GET/invoices does not download line items).

Returns:

  • (Boolean)


118
119
120
# File 'lib/xero_gateway/invoice.rb', line 118

def line_items_downloaded?
  @line_items_downloaded
end

#saveObject

General purpose create/save method. If invoice_id is nil then create, otherwise, attempt to save.



157
158
159
160
161
162
163
# File 'lib/xero_gateway/invoice.rb', line 157

def save
  if invoice_id.nil?
    create
  else
    update
  end
end

#to_xml(b = Builder::XmlMarkup.new) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/xero_gateway/invoice.rb', line 179

def to_xml(b = Builder::XmlMarkup.new)
  b.Invoice {
    b.InvoiceID self.invoice_id if self.invoice_id
    b.InvoiceNumber self.invoice_number if invoice_number
    b.Type self.invoice_type
    b.CurrencyCode self.currency_code if self.currency_code
    contact.to_xml(b)
    b.Date Invoice.format_date(self.date || Date.today)
    b.DueDate Invoice.format_date(self.due_date) if self.due_date
    b.Status self.invoice_status if self.invoice_status
    b.Reference self.reference if self.reference
    b.LineAmountTypes self.line_amount_types
    b.LineItems {
      self.line_items.each do |line_item|
        line_item.to_xml(b)
      end
    }
    b.Url url if url
  }
end

#updateObject

Updates this invoice record (using gateway.update_invoice) with the associated gateway. If no gateway set, raise a NoGatewayError exception.

Raises:



174
175
176
177
# File 'lib/xero_gateway/invoice.rb', line 174

def update
  raise NoGatewayError unless gateway
  gateway.update_invoice(self)
end

#valid?Boolean

Validate the Address record according to what will be valid by the gateway.

Usage:

address.valid?     # Returns true/false

Additionally sets address.errors array to an array of field/error.

Returns:

  • (Boolean)


66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/xero_gateway/invoice.rb', line 66

def valid?
  @errors = []
  
  if !invoice_id.nil? && invoice_id !~ GUID_REGEX
    @errors << ['invoice_id', 'must be blank or a valid Xero GUID']
  end
        
  if invoice_status && !INVOICE_STATUS[invoice_status]
    @errors << ['invoice_status', "must be one of #{INVOICE_STATUS.keys.join('/')}"]
  end

  if line_amount_types && !LINE_AMOUNT_TYPES[line_amount_types]
    @errors << ['line_amount_types', "must be one of #{LINE_AMOUNT_TYPES.keys.join('/')}"]
  end
  
  unless date
    @errors << ['invoice_date', "can't be blank"]
  end
  
  # Make sure contact is valid.
  unless @contact && @contact.valid?
    @errors << ['contact', 'is invalid']
  end
  
  # Make sure all line_items are valid.
  unless line_items.all? { | line_item | line_item.valid? }
    @errors << ['line_items', "at least one line item invalid"]
  end
  
  @errors.size == 0
end