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.



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

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 NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def amount_credited
  @amount_credited
end

#amount_dueObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def amount_due
  @amount_due
end

#amount_paidObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def amount_paid
  @amount_paid
end

#branding_theme_idObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def branding_theme_id
  @branding_theme_id
end

#contactObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def contact
  @contact
end

#currency_codeObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def currency_code
  @currency_code
end

#dateObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def date
  @date
end

#due_dateObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

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 NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

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 NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def invoice_id
  @invoice_id
end

#invoice_numberObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def invoice_number
  @invoice_number
end

#invoice_statusObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def invoice_status
  @invoice_status
end

#invoice_typeObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def invoice_type
  @invoice_type
end

#line_amount_typesObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

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).



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

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 NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def payments
  @payments
end

#referenceObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def reference
  @reference
end

#sent_to_contactObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def sent_to_contact
  @sent_to_contact
end

#urlObject

All accessible fields NICKEDIT - added BrandingThemeID



41
42
43
# File 'lib/xero_gateway/invoice.rb', line 41

def url
  @url
end

Class Method Details

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

TODO UpdatedDateUTC



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
231
232
233
234
235
236
# File 'lib/xero_gateway/invoice.rb', line 205

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
      #NICKEDIT - adding BrandingThemeID
      when "BrandingThemeID" then invoice.branding_theme_id = 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



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

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)


110
111
112
# File 'lib/xero_gateway/invoice.rb', line 110

def accounts_payable?
  invoice_type == 'ACCPAY'
end

#accounts_receivable?Boolean

Helper method to check if the invoice is accounts receivable.

Returns:

  • (Boolean)


115
116
117
# File 'lib/xero_gateway/invoice.rb', line 115

def accounts_receivable?
  invoice_type == 'ACCREC'
end

#build_contact(params = {}) ⇒ Object

Helper method to create the associated contact object.



101
102
103
# File 'lib/xero_gateway/invoice.rb', line 101

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:



169
170
171
172
# File 'lib/xero_gateway/invoice.rb', line 169

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)


120
121
122
# File 'lib/xero_gateway/invoice.rb', line 120

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.



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

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

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



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

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
    #NICKEDIT - adding BrandingThemeID
    b.BrandingThemeID self.branding_theme_id if self.branding_theme_id
    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:



176
177
178
179
# File 'lib/xero_gateway/invoice.rb', line 176

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)


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
97
98
# File 'lib/xero_gateway/invoice.rb', line 68

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