xeroizer 2.16.5 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +21 -27
  3. data/lib/class_level_inheritable_attributes.rb +3 -0
  4. data/lib/xeroizer.rb +13 -1
  5. data/lib/xeroizer/exceptions.rb +1 -1
  6. data/lib/xeroizer/generic_application.rb +13 -1
  7. data/lib/xeroizer/http.rb +128 -120
  8. data/lib/xeroizer/models/account.rb +1 -0
  9. data/lib/xeroizer/models/address.rb +18 -9
  10. data/lib/xeroizer/models/attachment.rb +1 -1
  11. data/lib/xeroizer/models/balances.rb +1 -0
  12. data/lib/xeroizer/models/bank_transaction.rb +2 -2
  13. data/lib/xeroizer/models/bank_transfer.rb +28 -0
  14. data/lib/xeroizer/models/contact.rb +11 -4
  15. data/lib/xeroizer/models/credit_note.rb +9 -4
  16. data/lib/xeroizer/models/from_bank_account.rb +12 -0
  17. data/lib/xeroizer/models/invoice.rb +11 -3
  18. data/lib/xeroizer/models/invoice_reminder.rb +19 -0
  19. data/lib/xeroizer/models/line_item.rb +21 -9
  20. data/lib/xeroizer/models/manual_journal.rb +6 -0
  21. data/lib/xeroizer/models/organisation.rb +4 -0
  22. data/lib/xeroizer/models/overpayment.rb +40 -0
  23. data/lib/xeroizer/models/payroll/bank_account.rb +23 -0
  24. data/lib/xeroizer/models/payroll/employee.rb +45 -0
  25. data/lib/xeroizer/models/payroll/home_address.rb +24 -0
  26. data/lib/xeroizer/models/prepayment.rb +1 -0
  27. data/lib/xeroizer/models/tax_rate.rb +5 -4
  28. data/lib/xeroizer/models/to_bank_account.rb +12 -0
  29. data/lib/xeroizer/oauth.rb +8 -8
  30. data/lib/xeroizer/partner_application.rb +4 -8
  31. data/lib/xeroizer/payroll_application.rb +28 -0
  32. data/lib/xeroizer/private_application.rb +2 -4
  33. data/lib/xeroizer/record/base_model.rb +137 -122
  34. data/lib/xeroizer/record/base_model_http_proxy.rb +1 -1
  35. data/lib/xeroizer/record/payroll_base.rb +25 -0
  36. data/lib/xeroizer/record/payroll_base_model.rb +29 -0
  37. data/lib/xeroizer/record/record_association_helper.rb +13 -14
  38. data/lib/xeroizer/record/validation_helper.rb +1 -1
  39. data/lib/xeroizer/record/xml_helper.rb +10 -8
  40. data/lib/xeroizer/report/aged_receivables_by_contact.rb +0 -1
  41. data/lib/xeroizer/report/base.rb +0 -1
  42. data/lib/xeroizer/report/factory.rb +3 -3
  43. data/lib/xeroizer/report/row/header.rb +4 -4
  44. data/lib/xeroizer/report/row/xml_helper.rb +2 -2
  45. data/lib/xeroizer/version.rb +1 -1
  46. data/test/acceptance/about_creating_prepayment_test.rb +46 -0
  47. data/test/acceptance/about_fetching_bank_transactions_test.rb +21 -21
  48. data/test/acceptance/acceptance_test.rb +4 -4
  49. data/test/acceptance/bank_transaction_reference_data.rb +3 -1
  50. data/test/acceptance/bank_transfer_test.rb +26 -0
  51. data/test/test_helper.rb +6 -4
  52. data/test/unit/models/address_test.rb +92 -0
  53. data/test/unit/models/bank_transaction_validation_test.rb +1 -1
  54. data/test/unit/models/contact_test.rb +20 -4
  55. data/test/unit/models/line_item_test.rb +20 -6
  56. data/test/unit/models/tax_rate_test.rb +52 -1
  57. data/test/unit/record/base_model_test.rb +1 -1
  58. data/test/unit/record/base_test.rb +9 -6
  59. data/test/unit/record/model_definition_test.rb +2 -2
  60. data/test/unit/report_test.rb +19 -21
  61. metadata +20 -3
@@ -64,6 +64,7 @@ module Xeroizer
64
64
  string :bank_account_number
65
65
  string :reporting_code
66
66
  string :reporting_code_name
67
+ datetime_utc :updated_date_utc, api_name: 'UpdatedDateUTC'
67
68
 
68
69
  end
69
70
 
@@ -1,18 +1,18 @@
1
1
  module Xeroizer
2
2
  module Record
3
-
3
+
4
4
  class AddressModel < BaseModel
5
-
5
+
6
6
  end
7
-
7
+
8
8
  class Address < Base
9
-
9
+
10
10
  ADDRESS_TYPE = {
11
11
  'STREET' => 'Street',
12
12
  'POBOX' => 'PO Box',
13
13
  'DEFAULT' => 'Default address type'
14
14
  } unless defined?(ADDRESS_TYPE)
15
-
15
+
16
16
  string :address_type, :internal_name => :type
17
17
  string :attention_to
18
18
  string :address_line1, :internal_name => :line1
@@ -23,10 +23,19 @@ module Xeroizer
23
23
  string :region
24
24
  string :postal_code
25
25
  string :country
26
-
26
+
27
27
  validates_inclusion_of :type, :in => ADDRESS_TYPE.keys
28
-
28
+ validates_length_of :address_line1, :max => 500
29
+ validates_length_of :address_line2, :max => 500
30
+ validates_length_of :address_line3, :max => 500
31
+ validates_length_of :address_line4, :max => 500
32
+ validates_length_of :city, :max => 255
33
+ validates_length_of :region, :max => 255
34
+ validates_length_of :postal_code, :max => 50
35
+ validates_length_of :country, :max => 50
36
+ validates_length_of :attention_to, :max => 255
37
+
29
38
  end
30
-
39
+
31
40
  end
32
- end
41
+ end
@@ -82,7 +82,7 @@ module Xeroizer
82
82
  def get(filename = nil)
83
83
  data = parent.application.http_get(parent.application.client, url)
84
84
  if filename
85
- File.open(filename, "w") { | fp | fp.write data }
85
+ File.open(filename, "wb") { | fp | fp.write data }
86
86
  nil
87
87
  else
88
88
  data
@@ -6,6 +6,7 @@ module Xeroizer
6
6
 
7
7
  class BalancesModel < BaseModel
8
8
  set_permissions :read
9
+ set_api_controller_name 'Balances'
9
10
  end
10
11
 
11
12
  class Balances < Base
@@ -52,8 +52,8 @@ module Xeroizer
52
52
  :in => Xeroizer::Record::LINE_AMOUNT_TYPES, :allow_blanks => false
53
53
 
54
54
  validates_inclusion_of :type,
55
- :in => %w{SPEND RECEIVE RECEIVE-PREPAYMENT RECEIVE-OVERPAYMENT}, :allow_blanks => false,
56
- :message => "Invalid type. Expected either SPEND, RECEIVE, RECEIVE-PREPAYMENT or RECEIVE-OVERPAYMENT."
55
+ :in => %w{RECEIVE RECEIVE-OVERPAYMENT RECEIVE-PREPAYMENT SPEND SPEND-OVERPAYMENT SPEND-PREPAYMENT}, :allow_blanks => false,
56
+ :message => "Invalid type. Expected one of https://developer.xero.com/documentation/api/types#BankTransactionTypes"
57
57
  validates_inclusion_of :status, :in => BANK_TRANSACTION_STATUSES, :allow_blanks => true
58
58
 
59
59
  validates_presence_of :contact, :bank_account, :allow_blanks => false
@@ -0,0 +1,28 @@
1
+ module Xeroizer
2
+ module Record
3
+ class BankTransferModel < BaseModel
4
+ set_permissions :read, :write, :update
5
+ end
6
+
7
+ class BankTransfer < Base
8
+
9
+ def initialize(parent)
10
+ super parent
11
+ end
12
+
13
+ set_primary_key :bank_transfer_id
14
+
15
+ string :bank_transfer_id, :api_name => "BankTransferID"
16
+ datetime_utc :created_date_utc, :api_name => "CreatedDateUTC"
17
+ date :date
18
+ decimal :amount
19
+ decimal :currency_rate
20
+ string :from_bank_transaction_id, :api_name => "FromBankTransactionID"
21
+ string :to_bank_transaction_id, :api_name => "ToBankTransactionID"
22
+
23
+ validates_presence_of :from_bank_account, :to_bank_account, :allow_blanks => false
24
+ belongs_to :from_bank_account, :model_name => 'FromBankAccount'
25
+ belongs_to :to_bank_account, :model_name => 'ToBankAccount'
26
+ end
27
+ end
28
+ end
@@ -10,6 +10,8 @@ module Xeroizer
10
10
 
11
11
  set_permissions :read, :write, :update
12
12
 
13
+ include AttachmentModel::Extensions
14
+
13
15
  end
14
16
 
15
17
  class Contact < Base
@@ -20,6 +22,8 @@ module Xeroizer
20
22
  'ARCHIVED' => 'Archived'
21
23
  } unless defined?(CONTACT_STATUS)
22
24
 
25
+ include Attachment::Extensions
26
+
23
27
  set_primary_key :contact_id
24
28
  set_possible_primary_keys :contact_id, :contact_number
25
29
  list_contains_summary_only true
@@ -37,13 +41,15 @@ module Xeroizer
37
41
  string :last_name
38
42
  string :email_address
39
43
  string :skype_user_name
40
- string :contact_groups
41
44
  string :default_currency
42
45
  string :purchases_default_account_code
43
46
  string :sales_default_account_code
44
47
  datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
45
48
  boolean :is_supplier
46
49
  boolean :is_customer
50
+ string :website # read only
51
+ decimal :discount # read only
52
+ boolean :has_attachments
47
53
 
48
54
  has_many :addresses, :list_complete => true
49
55
  has_many :phones, :list_complete => true
@@ -53,12 +59,13 @@ module Xeroizer
53
59
  has_many :sales_tracking_categories, :model_name => 'ContactSalesTrackingCategory'
54
60
  has_many :purchases_tracking_categories, :model_name => 'ContactPurchasesTrackingCategory'
55
61
 
56
- has_one :balances ,:model_name => 'Balances', :list_complete => true
57
- has_one :batch_payments ,:model_name => 'BatchPayments', :list_complete => true
58
- has_one :payment_terms ,:model_name => 'PaymentTerms', :list_complete => true
62
+ has_one :balances, :model_name => 'Balances', :list_complete => true
63
+ has_one :batch_payments, :model_name => 'BatchPayments', :list_complete => true
64
+ has_one :payment_terms, :model_name => 'PaymentTerms', :list_complete => true
59
65
 
60
66
  validates_presence_of :name, :unless => Proc.new { | contact | contact.contact_id.present?}
61
67
  validates_inclusion_of :contact_status, :in => CONTACT_STATUS.keys, :allow_blanks => true
68
+ validates_associated :addresses, allow_blanks: true
62
69
 
63
70
  def email_address?
64
71
  email_address.present?
@@ -5,6 +5,8 @@ module Xeroizer
5
5
 
6
6
  set_permissions :read, :write, :update
7
7
 
8
+ include AttachmentModel::Extensions
9
+
8
10
  public
9
11
 
10
12
  # Retrieve the PDF version of the credit matching the `id`.
@@ -39,6 +41,8 @@ module Xeroizer
39
41
  'ACCPAYCREDIT' => 'Accounts Payable'
40
42
  } unless defined?(CREDIT_NOTE_TYPE)
41
43
  CREDIT_NOTE_TYPES = CREDIT_NOTE_TYPE.keys.sort
44
+
45
+ include Attachment::Extensions
42
46
 
43
47
  set_primary_key :credit_note_id
44
48
  set_possible_primary_keys :credit_note_id, :credit_note_number
@@ -60,7 +64,8 @@ module Xeroizer
60
64
  decimal :currency_rate
61
65
  datetime :fully_paid_on_date
62
66
  boolean :sent_to_contact
63
- decimal :remaining_credit
67
+ decimal :remaining_credit
68
+ boolean :has_attachments
64
69
 
65
70
  belongs_to :contact
66
71
  has_many :line_items
@@ -94,11 +99,11 @@ module Xeroizer
94
99
  # Calculate sub_total from line_items.
95
100
  def sub_total(always_summary = false)
96
101
  if !always_summary && (new_record? || (!new_record? && line_items && line_items.size > 0))
97
- sum = (line_items || []).inject(BigDecimal.new('0')) { | sum, line_item | sum + line_item.line_amount }
102
+ overall_sum = (line_items || []).inject(BigDecimal.new('0')) { | sum, line_item | sum + line_item.line_amount }
98
103
 
99
104
  # If the default amount types are inclusive of 'tax' then remove the tax amount from this sub-total.
100
- sum -= total_tax if line_amount_types == 'Inclusive'
101
- sum
105
+ overall_sum -= total_tax if line_amount_types == 'Inclusive'
106
+ overall_sum
102
107
  else
103
108
  attributes[:sub_total]
104
109
  end
@@ -0,0 +1,12 @@
1
+ module Xeroizer
2
+ module Record
3
+ class FromBankAccountModel < BaseModel
4
+ set_permissions :read
5
+ end
6
+
7
+ class FromBankAccount < Base
8
+ guid :account_id
9
+ string :code
10
+ end
11
+ end
12
+ end
@@ -69,6 +69,7 @@ module Xeroizer
69
69
  decimal :sub_total, :calculated => true
70
70
  decimal :total_tax, :calculated => true
71
71
  decimal :total, :calculated => true
72
+ decimal :total_discount
72
73
  decimal :amount_due
73
74
  decimal :amount_paid
74
75
  decimal :amount_credited
@@ -77,6 +78,7 @@ module Xeroizer
77
78
  decimal :currency_rate
78
79
  datetime :fully_paid_on_date
79
80
  datetime :expected_payment_date
81
+ datetime :planned_payment_date
80
82
  boolean :sent_to_contact
81
83
  boolean :has_attachments
82
84
 
@@ -94,6 +96,12 @@ module Xeroizer
94
96
  validates_associated :line_items, :if => :approved?
95
97
 
96
98
  public
99
+ def initialize(parent)
100
+ super(parent)
101
+ @sub_total_is_set = false
102
+ @total_tax_is_set = false
103
+ @total_is_set = false
104
+ end
97
105
 
98
106
  # Access the contact name without forcing a download of
99
107
  # an incomplete, summary invoice.
@@ -140,11 +148,11 @@ module Xeroizer
140
148
  # Calculate sub_total from line_items.
141
149
  def sub_total(always_summary = false)
142
150
  if !@sub_total_is_set && not_summary_or_loaded_record(always_summary)
143
- sum = (line_items || []).inject(BigDecimal.new('0')) { | sum, line_item | sum + line_item.line_amount }
151
+ overall_sum = (line_items || []).inject(BigDecimal.new('0')) { | sum, line_item | sum + line_item.line_amount }
144
152
 
145
153
  # If the default amount types are inclusive of 'tax' then remove the tax amount from this sub-total.
146
- sum -= total_tax if line_amount_types == 'Inclusive'
147
- sum
154
+ overall_sum -= total_tax if line_amount_types == 'Inclusive'
155
+ overall_sum
148
156
  else
149
157
  attributes[:sub_total]
150
158
  end
@@ -0,0 +1,19 @@
1
+ module Xeroizer
2
+ module Record
3
+
4
+ class InvoiceReminderModel < BaseModel
5
+
6
+ set_api_controller_name 'InvoiceReminders/Settings'
7
+
8
+ set_permissions :read
9
+
10
+ end
11
+
12
+ class InvoiceReminder < Base
13
+
14
+ boolean :enabled
15
+
16
+ end
17
+
18
+ end
19
+ end
@@ -4,12 +4,12 @@ require 'xeroizer/models/line_amount_type'
4
4
  module Xeroizer
5
5
  module Record
6
6
  class LineItemModel < BaseModel
7
-
7
+
8
8
  end
9
-
9
+
10
10
  class LineItem < Base
11
11
  TAX_TYPE = Account::TAX_TYPE unless defined?(TAX_TYPE)
12
-
12
+
13
13
  string :item_code
14
14
  string :description
15
15
  decimal :quantity
@@ -20,22 +20,34 @@ module Xeroizer
20
20
  decimal :line_amount, :calculated => true
21
21
  decimal :discount_rate
22
22
  string :line_item_id
23
-
23
+
24
24
  has_many :tracking, :model_name => 'TrackingCategoryChild'
25
-
25
+
26
+ def initialize(parent)
27
+ super(parent)
28
+ @line_amount_set = false
29
+ end
30
+
26
31
  def line_amount=(line_amount)
27
32
  @line_amount_set = true
28
33
  attributes[:line_amount] = line_amount
29
34
  end
30
-
35
+
31
36
  # Calculate the line_total (if there is a quantity and unit_amount).
32
37
  # Description-only lines have been allowed since Xero V2.09.
33
38
  def line_amount(summary_only = false)
34
39
  return attributes[:line_amount] if summary_only || @line_amount_set
35
-
36
- BigDecimal((quantity * unit_amount).to_s).round(2) if quantity && unit_amount
40
+
41
+ if quantity && unit_amount
42
+ total = quantity * unit_amount
43
+ if discount_rate
44
+ BigDecimal((total * ((100 - discount_rate) / 100)).to_s).round(2)
45
+ else
46
+ BigDecimal(total.to_s).round(2)
47
+ end
48
+ end
37
49
  end
38
-
50
+
39
51
  end
40
52
 
41
53
  end
@@ -1,9 +1,13 @@
1
+ require "xeroizer/models/attachment"
2
+
1
3
  module Xeroizer
2
4
  module Record
3
5
 
4
6
  class ManualJournalModel < BaseModel
5
7
 
6
8
  set_permissions :read, :write, :update
9
+
10
+ include AttachmentModel::Extensions
7
11
 
8
12
  end
9
13
 
@@ -14,6 +18,8 @@ module Xeroizer
14
18
  'POSTED' => 'Posted'
15
19
  } unless defined?(JOURNAL_STATUS)
16
20
  JOURNAL_STATUSES = JOURNAL_STATUS.keys.sort
21
+
22
+ include Attachment::Extensions
17
23
 
18
24
  set_primary_key :manual_journal_id
19
25
  set_possible_primary_keys :manual_journal_id
@@ -36,9 +36,12 @@ module Xeroizer
36
36
  string :name
37
37
  string :legal_name
38
38
  string :short_code
39
+ string :organisation_id
39
40
  boolean :pays_tax
40
41
  string :version
41
42
  string :organisation_type
43
+ string :organisation_entity_type
44
+ string :line_of_business
42
45
  string :base_currency
43
46
  string :country_code
44
47
  boolean :is_demo_company
@@ -58,6 +61,7 @@ module Xeroizer
58
61
 
59
62
  has_many :addresses
60
63
  has_many :phones
64
+ has_many :external_links
61
65
 
62
66
  validates :sales_tax_basis, :message => "is not a valid option" do
63
67
  valid = true
@@ -0,0 +1,40 @@
1
+ module Xeroizer
2
+ module Record
3
+
4
+ class OverpaymentModel < BaseModel
5
+
6
+ set_xml_root_name 'Overpayments'
7
+ set_api_controller_name 'Overpayment'
8
+ set_permissions :read
9
+
10
+ end
11
+
12
+ class Overpayment < Base
13
+ set_primary_key :overpayment_id
14
+
15
+ guid :overpayment_id
16
+ date :date
17
+ string :status
18
+ string :line_amount_types
19
+ decimal :sub_total
20
+ decimal :total_tax
21
+ decimal :total
22
+ datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
23
+ string :currency_code
24
+ string :type
25
+ decimal :remaining_credit
26
+ boolean :has_attachments
27
+
28
+ belongs_to :contact
29
+ belongs_to :invoice
30
+ has_many :allocations
31
+ has_many :line_items
32
+ has_many :payments
33
+
34
+ def contact_id
35
+ contact.id if contact
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,23 @@
1
+ module Xeroizer
2
+ module Record
3
+ module Payroll
4
+
5
+ class BankAccountModel < PayrollBaseModel
6
+
7
+ end
8
+
9
+ class BankAccount < PayrollBase
10
+
11
+ string :statement_text
12
+ string :account_name
13
+ string :bsb
14
+ string :account_number
15
+ boolean :remainder
16
+ string :percentage
17
+ decimal :amount
18
+
19
+ end
20
+
21
+ end
22
+ end
23
+ end