xero_gateway-float 2.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/Gemfile +12 -0
  2. data/LICENSE +14 -0
  3. data/README.textile +357 -0
  4. data/Rakefile +14 -0
  5. data/examples/oauth.rb +25 -0
  6. data/examples/partner_app.rb +36 -0
  7. data/init.rb +1 -0
  8. data/lib/oauth/oauth_consumer.rb +14 -0
  9. data/lib/xero_gateway.rb +39 -0
  10. data/lib/xero_gateway/account.rb +95 -0
  11. data/lib/xero_gateway/accounts_list.rb +87 -0
  12. data/lib/xero_gateway/address.rb +96 -0
  13. data/lib/xero_gateway/bank_transaction.rb +178 -0
  14. data/lib/xero_gateway/ca-certificates.crt +2560 -0
  15. data/lib/xero_gateway/contact.rb +206 -0
  16. data/lib/xero_gateway/credit_note.rb +222 -0
  17. data/lib/xero_gateway/currency.rb +56 -0
  18. data/lib/xero_gateway/dates.rb +30 -0
  19. data/lib/xero_gateway/error.rb +18 -0
  20. data/lib/xero_gateway/exceptions.rb +46 -0
  21. data/lib/xero_gateway/gateway.rb +622 -0
  22. data/lib/xero_gateway/http.rb +138 -0
  23. data/lib/xero_gateway/http_encoding_helper.rb +49 -0
  24. data/lib/xero_gateway/invoice.rb +236 -0
  25. data/lib/xero_gateway/line_item.rb +125 -0
  26. data/lib/xero_gateway/line_item_calculations.rb +55 -0
  27. data/lib/xero_gateway/money.rb +16 -0
  28. data/lib/xero_gateway/oauth.rb +87 -0
  29. data/lib/xero_gateway/organisation.rb +75 -0
  30. data/lib/xero_gateway/partner_app.rb +30 -0
  31. data/lib/xero_gateway/payment.rb +40 -0
  32. data/lib/xero_gateway/phone.rb +77 -0
  33. data/lib/xero_gateway/private_app.rb +17 -0
  34. data/lib/xero_gateway/response.rb +41 -0
  35. data/lib/xero_gateway/tax_rate.rb +63 -0
  36. data/lib/xero_gateway/tracking_category.rb +87 -0
  37. data/test/integration/accounts_list_test.rb +109 -0
  38. data/test/integration/create_bank_transaction_test.rb +38 -0
  39. data/test/integration/create_contact_test.rb +66 -0
  40. data/test/integration/create_credit_note_test.rb +49 -0
  41. data/test/integration/create_invoice_test.rb +49 -0
  42. data/test/integration/get_accounts_test.rb +23 -0
  43. data/test/integration/get_bank_transaction_test.rb +51 -0
  44. data/test/integration/get_bank_transactions_test.rb +88 -0
  45. data/test/integration/get_contact_test.rb +28 -0
  46. data/test/integration/get_contacts_test.rb +40 -0
  47. data/test/integration/get_credit_note_test.rb +48 -0
  48. data/test/integration/get_credit_notes_test.rb +90 -0
  49. data/test/integration/get_currencies_test.rb +25 -0
  50. data/test/integration/get_invoice_test.rb +48 -0
  51. data/test/integration/get_invoices_test.rb +92 -0
  52. data/test/integration/get_organisation_test.rb +24 -0
  53. data/test/integration/get_tax_rates_test.rb +25 -0
  54. data/test/integration/get_tracking_categories_test.rb +27 -0
  55. data/test/integration/update_bank_transaction_test.rb +31 -0
  56. data/test/integration/update_contact_test.rb +31 -0
  57. data/test/integration/update_invoice_test.rb +31 -0
  58. data/test/test_helper.rb +179 -0
  59. data/test/unit/account_test.rb +47 -0
  60. data/test/unit/bank_transaction_test.rb +126 -0
  61. data/test/unit/contact_test.rb +97 -0
  62. data/test/unit/credit_note_test.rb +284 -0
  63. data/test/unit/currency_test.rb +31 -0
  64. data/test/unit/gateway_test.rb +119 -0
  65. data/test/unit/invoice_test.rb +326 -0
  66. data/test/unit/oauth_test.rb +116 -0
  67. data/test/unit/organisation_test.rb +38 -0
  68. data/test/unit/tax_rate_test.rb +38 -0
  69. data/test/unit/tracking_category_test.rb +52 -0
  70. data/xero_gateway.gemspec +15 -0
  71. metadata +164 -0
@@ -0,0 +1,47 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class AccountTest < Test::Unit::TestCase
4
+ # Tests that an account can be converted into XML that Xero can understand, and then converted back to an account
5
+ def test_build_and_parse_xml
6
+ account = create_test_account
7
+
8
+ # Generate the XML message
9
+ account_as_xml = account.to_xml
10
+
11
+ # Parse the XML message and retrieve the account element
12
+ account_element = REXML::XPath.first(REXML::Document.new(account_as_xml), "/Account")
13
+
14
+ # Build a new account from the XML
15
+ result_account = XeroGateway::Account.from_xml(account_element)
16
+
17
+ # Check the account details
18
+ assert_equal account, result_account
19
+ end
20
+
21
+ def test_build_and_parse_xml_for_bank_accounts
22
+ account = create_test_account(:type => 'BANK', :currency_code => 'NZD')
23
+ account_as_xml = account.to_xml
24
+ assert_match 'CurrencyCode', account_as_xml.to_s
25
+
26
+ account_element = REXML::XPath.first(REXML::Document.new(account_as_xml), "/Account")
27
+ result_account = XeroGateway::Account.from_xml(account_element)
28
+ assert_equal 'BANK', result_account.type
29
+ assert_equal 'NZD', result_account.currency_code
30
+ assert_equal account, result_account
31
+ end
32
+
33
+ private
34
+
35
+ def create_test_account(options={})
36
+ account = XeroGateway::Account.new(:account_id => "57cedda9")
37
+ account.code = "200"
38
+ account.name = "Sales"
39
+ account.type = options[:type] || "REVENUE"
40
+ account.tax_type = "OUTPUT"
41
+ account.description = "Income from any normal business activity"
42
+ account.enable_payments_to_account = false
43
+ account.currency_code = options[:currency_code] if options[:currency_code]
44
+
45
+ account
46
+ end
47
+ end
@@ -0,0 +1,126 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class BankTransactionTest < Test::Unit::TestCase
4
+ include TestHelper
5
+
6
+ context "creating test bank transactions" do
7
+ should "work" do
8
+ bank_transaction = create_test_bank_transaction
9
+
10
+ # test transaction defaults
11
+ assert_equal 'RECEIVE', bank_transaction.type
12
+ assert_kind_of Date, bank_transaction.date
13
+ assert_equal '12345', bank_transaction.reference
14
+ assert_equal 'ACTIVE', bank_transaction.status
15
+
16
+ # Test the contact defaults.
17
+ contact = bank_transaction.contact
18
+ assert_equal '00000000-0000-0000-0000-000000000000', contact.contact_id
19
+ assert_equal 'CONTACT NAME', contact.name
20
+
21
+ # Test address defaults.
22
+ assert_equal 'STREET', contact.address.address_type
23
+ assert_equal 'LINE 1 OF THE ADDRESS', contact.address.line_1
24
+
25
+ # Test phone defaults.
26
+ assert_equal('DEFAULT', contact.phone.phone_type)
27
+ assert_equal('12345678', contact.phone.number)
28
+
29
+ # Test the line_item defaults.
30
+ line_item = bank_transaction.line_items.first
31
+ assert_equal('A LINE ITEM', line_item.description)
32
+ assert_equal('200', line_item.account_code)
33
+ assert_equal(BigDecimal.new('100'), line_item.unit_amount)
34
+ assert_equal(BigDecimal.new('12.5'), line_item.tax_amount)
35
+ end
36
+
37
+ should "allow overriding transaction defaults" do
38
+ assert_equal 'SPEND', create_test_bank_transaction(:type => 'SPEND').type
39
+ end
40
+ end
41
+
42
+ context "adding line items" do
43
+ setup do
44
+ @bank_transaction = create_test_bank_transaction({}, {}, nil) # no line_items
45
+ end
46
+
47
+ should "work" do
48
+ assert_equal(0, @bank_transaction.line_items.size)
49
+
50
+ line_item_params = {:description => "Test Item 1", :unit_amount => 100}
51
+
52
+ # Test adding line item by hash
53
+ line_item = @bank_transaction.add_line_item(line_item_params)
54
+ assert_kind_of(XeroGateway::LineItem, line_item)
55
+ assert_equal(line_item_params[:description], line_item.description)
56
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
57
+ assert_equal(1, @bank_transaction.line_items.size)
58
+
59
+ # Test adding line item by XeroGateway::LineItem
60
+ line_item = @bank_transaction.add_line_item(line_item_params)
61
+ assert_kind_of(XeroGateway::LineItem, line_item)
62
+ assert_equal(line_item_params[:description], line_item.description)
63
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
64
+ assert_equal(2, @bank_transaction.line_items.size)
65
+
66
+ # Test that pushing anything else into add_line_item fails.
67
+ ["invalid", 100, nil, []].each do | invalid_object |
68
+ assert_raise(XeroGateway::Invoice::InvalidLineItemError) { @bank_transaction.add_line_item(invalid_object) }
69
+ assert_equal(2, @bank_transaction.line_items.size)
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ context "building and parsing XML" do
76
+ should "work vice versa" do
77
+ bank_transaction = create_test_bank_transaction
78
+ bank_transaction_as_xml = bank_transaction.to_xml
79
+ bank_transaction_element = REXML::XPath.first(REXML::Document.new(bank_transaction_as_xml), "/BankTransaction")
80
+
81
+ # checking for mandatory fields
82
+ assert_xml_field bank_transaction_element, 'Type', :value => 'RECEIVE'
83
+ assert_xml_field bank_transaction_element, 'Date'
84
+ assert_xml_field bank_transaction_element, 'Reference', :value => '12345'
85
+ assert_xml_field bank_transaction_element, 'Status', :value => 'ACTIVE'
86
+ assert_xml_field bank_transaction_element, 'Contact', :value => 'CONTACT NAME'
87
+ assert_xml_field bank_transaction_element, 'LineItems', :value => 'A LINE ITEM'
88
+ assert_xml_field bank_transaction_element, 'BankAccount'
89
+
90
+ parsed_bank_transaction = XeroGateway::BankTransaction.from_xml(bank_transaction_element)
91
+ assert_equal(bank_transaction, parsed_bank_transaction)
92
+ end
93
+
94
+ should "work for optional params" do
95
+ bank_transaction = create_test_bank_transaction(:url => 'http://example.com?with=params&and=more')
96
+ bank_transaction_element = REXML::XPath.first(REXML::Document.new(bank_transaction.to_xml), "/BankTransaction")
97
+
98
+ assert_xml_field bank_transaction_element, 'Url', :value => 'http://example.com\?with=params&amp;and=more'
99
+
100
+ parsed_bank_transaction = XeroGateway::BankTransaction.from_xml(bank_transaction_element)
101
+ assert_equal 'http://example.com?with=params&and=more', parsed_bank_transaction.url
102
+ end
103
+
104
+ should "ignore missing contact" do
105
+ bank_transaction = create_test_bank_transaction
106
+ bank_transaction.contact = nil
107
+ bank_transaction.to_xml
108
+ end
109
+
110
+ should "ignore missing bank account" do
111
+ bank_transaction = create_test_bank_transaction
112
+ bank_transaction.bank_account = nil
113
+ bank_transaction.to_xml
114
+ end
115
+ end
116
+
117
+ private
118
+
119
+ def assert_xml_field(xml, field_name, options={})
120
+ assert_match /#{field_name}/, xml.to_s, "Didn't find the field #{field_name} in the XML document!"
121
+ if options[:value]
122
+ assert_match /#{field_name}.*#{options[:value]}.*#{field_name}/, xml.to_s, "The field #{field_name} was expected to be '#{options[:value]}'!"
123
+ end
124
+ end
125
+
126
+ end
@@ -0,0 +1,97 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class ContactTest < Test::Unit::TestCase
4
+ def setup
5
+ @schema = LibXML::XML::Schema.document(LibXML::XML::Document.file(File.join(File.dirname(__FILE__), '../xsd/create_contact.xsd')))
6
+ end
7
+
8
+ # Tests that the XML generated from a contact object validates against the Xero XSD
9
+ def test_build_xml
10
+ contact = create_test_contact
11
+
12
+ message = contact.to_xml
13
+
14
+ # Check that the document matches the XSD
15
+ assert LibXML::XML::Parser.string(message).parse.validate_schema(@schema), "The XML document generated did not validate against the XSD"
16
+ end
17
+
18
+ # Tests that a contact can be converted into XML that Xero can understand, and then converted back to a contact
19
+ def test_build_and_parse_xml
20
+ contact = create_test_contact
21
+
22
+ # Generate the XML message
23
+ contact_as_xml = contact.to_xml
24
+
25
+ # Parse the XML message and retrieve the contact element
26
+ contact_element = REXML::XPath.first(REXML::Document.new(contact_as_xml), "/Contact")
27
+
28
+ # Build a new contact from the XML
29
+ result_contact = XeroGateway::Contact.from_xml(contact_element)
30
+
31
+ # Check the contact details
32
+ assert_equal contact, result_contact
33
+ end
34
+
35
+ # Test Contact#add_address helper creates a valid XeroGateway::Contact object with the passed in values
36
+ # and appends it to the Contact#addresses attribute.
37
+ def test_add_address_helper
38
+ contact = create_test_contact
39
+ assert_equal(1, contact.addresses.size)
40
+
41
+ new_values = {
42
+ :address_type => 'POBOX',
43
+ :line_1 => 'NEW LINE 1',
44
+ :line_2 => 'NEW LINE 2',
45
+ :line_3 => 'NEW LINE 3',
46
+ :line_4 => 'NEW LINE 4',
47
+ :city => 'NEW CITY',
48
+ :region => 'NEW REGION',
49
+ :post_code => '5555',
50
+ :country => 'Australia'
51
+ }
52
+ contact.add_address(new_values)
53
+
54
+ assert_equal(2, contact.addresses.size)
55
+ assert_kind_of(XeroGateway::Address, contact.addresses.last)
56
+ new_values.each { |k,v| assert_equal(v, contact.addresses.last.send("#{k}")) }
57
+ end
58
+
59
+ # Test Contact#add_phone helper creates a valid XeroGateway::Phone object with the passed in values
60
+ # and appends it to the Contact#phones attribute.
61
+ def test_add_address_helper
62
+ contact = create_test_contact
63
+ assert_equal(1, contact.phones.size)
64
+
65
+ new_values = {
66
+ :phone_type => 'MOBILE',
67
+ :country_code => '61',
68
+ :area_code => '406',
69
+ :number => '123456'
70
+ }
71
+ contact.add_phone(new_values)
72
+
73
+ assert_equal(2, contact.phones.size)
74
+ assert_kind_of(XeroGateway::Phone, contact.phones.last)
75
+ new_values.each { |k,v| assert_equal(v, contact.phones.last.send("#{k}")) }
76
+ end
77
+
78
+
79
+ private
80
+
81
+ def create_test_contact
82
+ contact = XeroGateway::Contact.new(:contact_id => "55555")
83
+ contact.contact_number = "aaa111"
84
+ contact.name = "CONTACT NAME"
85
+ contact.email = "someone@somewhere.com"
86
+ contact.address.address_type = "THE ADDRESS TYPE FOR THE CONTACT"
87
+ contact.address.line_1 = "LINE 1 OF THE ADDRESS"
88
+ contact.address.line_2 = "LINE 2 OF THE ADDRESS"
89
+ contact.address.line_3 = "LINE 3 OF THE ADDRESS"
90
+ contact.address.line_4 = "LINE 4 OF THE ADDRESS"
91
+ contact.phone.number = "12345"
92
+ contact.is_customer = true
93
+ contact.is_supplier = true
94
+
95
+ contact
96
+ end
97
+ end
@@ -0,0 +1,284 @@
1
+ require File.join(File.dirname(__FILE__), '../test_helper.rb')
2
+
3
+ class CreditNoteTest < Test::Unit::TestCase
4
+
5
+ # Tests that a credit note can be converted into XML that Xero can understand, and then converted back to a credit note
6
+ def test_build_and_parse_xml
7
+ credit_note = create_test_credit_note
8
+
9
+ # Generate the XML message
10
+ credit_note_as_xml = credit_note.to_xml
11
+
12
+ # Parse the XML message and retrieve the credit_note element
13
+ credit_note_element = REXML::XPath.first(REXML::Document.new(credit_note_as_xml), "/CreditNote")
14
+
15
+ # Build a new credit_note from the XML
16
+ result_credit_note = XeroGateway::CreditNote.from_xml(credit_note_element)
17
+
18
+ assert_equal(credit_note, result_credit_note)
19
+ end
20
+
21
+ # Tests the sub_total calculation and that setting it manually doesn't modify the data.
22
+ def test_credit_note_sub_total_calculation
23
+ credit_note = create_test_credit_note
24
+ line_item = credit_note.line_items.first
25
+
26
+ # Make sure that everything adds up to begin with.
27
+ expected_sub_total = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
28
+ assert_equal(expected_sub_total, credit_note.sub_total)
29
+
30
+ # Change the sub_total and check that it doesn't modify anything.
31
+ credit_note.sub_total = expected_sub_total * 10
32
+ assert_equal(expected_sub_total, credit_note.sub_total)
33
+
34
+ # Change the amount of the first line item and make sure that
35
+ # everything still continues to add up.
36
+ line_item.unit_amount = line_item.unit_amount + 10
37
+ assert_not_equal(expected_sub_total, credit_note.sub_total)
38
+ expected_sub_total = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.line_amount }
39
+ assert_equal(expected_sub_total, credit_note.sub_total)
40
+ end
41
+
42
+ # Tests the total_tax calculation and that setting it manually doesn't modify the data.
43
+ def test_credit_note_sub_total_calculation
44
+ credit_note = create_test_credit_note
45
+ line_item = credit_note.line_items.first
46
+
47
+ # Make sure that everything adds up to begin with.
48
+ expected_total_tax = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
49
+ assert_equal(expected_total_tax, credit_note.total_tax)
50
+
51
+ # Change the total_tax and check that it doesn't modify anything.
52
+ credit_note.total_tax = expected_total_tax * 10
53
+ assert_equal(expected_total_tax, credit_note.total_tax)
54
+
55
+ # Change the tax_amount of the first line item and make sure that
56
+ # everything still continues to add up.
57
+ line_item.tax_amount = line_item.tax_amount + 10
58
+ assert_not_equal(expected_total_tax, credit_note.total_tax)
59
+ expected_total_tax = credit_note.line_items.inject(BigDecimal.new('0')) { | sum, line_item | line_item.tax_amount }
60
+ assert_equal(expected_total_tax, credit_note.total_tax)
61
+ end
62
+
63
+ # Tests the total calculation and that setting it manually doesn't modify the data.
64
+ def test_credit_note_sub_total_calculation
65
+ credit_note = create_test_credit_note
66
+ line_item = credit_note.line_items.first
67
+
68
+ # Make sure that everything adds up to begin with.
69
+ expected_total = credit_note.sub_total + credit_note.total_tax
70
+ assert_equal(expected_total, credit_note.total)
71
+
72
+ # Change the total and check that it doesn't modify anything.
73
+ credit_note.total = expected_total * 10
74
+ assert_equal(expected_total, credit_note.total)
75
+
76
+ # Change the quantity of the first line item and make sure that
77
+ # everything still continues to add up.
78
+ line_item.quantity = line_item.quantity + 5
79
+ assert_not_equal(expected_total, credit_note.total)
80
+ expected_total = credit_note.sub_total + credit_note.total_tax
81
+ assert_equal(expected_total, credit_note.total)
82
+ end
83
+
84
+ # Tests that the LineItem#line_amount calculation is working correctly.
85
+ def test_line_amount_calculation
86
+ credit_note = create_test_credit_note
87
+ line_item = credit_note.line_items.first
88
+
89
+ # Make sure that everything adds up to begin with.
90
+ expected_amount = line_item.quantity * line_item.unit_amount
91
+ assert_equal(expected_amount, line_item.line_amount)
92
+
93
+ # Change the line_amount and check that it doesn't modify anything.
94
+ line_item.line_amount = expected_amount * 10
95
+ assert_equal(expected_amount, line_item.line_amount)
96
+
97
+ # Change the quantity and check that the line_amount has been updated.
98
+ quantity = line_item.quantity + 2
99
+ line_item.quantity = quantity
100
+ assert_not_equal(expected_amount, line_item.line_amount)
101
+ assert_equal(quantity * line_item.unit_amount, line_item.line_amount)
102
+ end
103
+
104
+ # Ensure that the totalling methods don't raise exceptions, even when
105
+ # credit_note.line_items is empty.
106
+ def test_totalling_methods_when_line_items_empty
107
+ credit_note = create_test_credit_note
108
+ credit_note.line_items = []
109
+
110
+ assert_nothing_raised(Exception) {
111
+ assert_equal(BigDecimal.new('0'), credit_note.sub_total)
112
+ assert_equal(BigDecimal.new('0'), credit_note.total_tax)
113
+ assert_equal(BigDecimal.new('0'), credit_note.total)
114
+ }
115
+ end
116
+
117
+ def test_type_helper_methods
118
+ # Test accounts receivable credit_notes.
119
+ credit_note = create_test_credit_note({:type => 'ACCRECCREDIT'})
120
+ assert_equal(true, credit_note.accounts_receivable?, "Accounts RECEIVABLE credit_note doesn't think it is.")
121
+ assert_equal(false, credit_note.accounts_payable?, "Accounts RECEIVABLE credit_note thinks it's payable.")
122
+
123
+ # Test accounts payable credit_notes.
124
+ credit_note = create_test_credit_note({:type => 'ACCPAYCREDIT'})
125
+ assert_equal(false, credit_note.accounts_receivable?, "Accounts PAYABLE credit_note doesn't think it is.")
126
+ assert_equal(true, credit_note.accounts_payable?, "Accounts PAYABLE credit_note thinks it's receivable.")
127
+ end
128
+
129
+
130
+ # Make sure that the create_test_credit_note method is working correctly
131
+ # with all the defaults and overrides.
132
+ def test_create_test_credit_note_defaults_working
133
+ credit_note = create_test_credit_note
134
+
135
+ # Test credit_note defaults.
136
+ assert_equal('ACCRECCREDIT', credit_note.type)
137
+ assert_kind_of(Date, credit_note.date)
138
+ assert_equal('12345', credit_note.credit_note_number)
139
+ assert_equal('MY REFERENCE FOR THIS CREDIT NOTE', credit_note.reference)
140
+ assert_equal("Exclusive", credit_note.line_amount_types)
141
+
142
+ # Test the contact defaults.
143
+ assert_equal('00000000-0000-0000-0000-000000000000', credit_note.contact.contact_id)
144
+ assert_equal('CONTACT NAME', credit_note.contact.name)
145
+
146
+ # Test address defaults.
147
+ assert_equal('DEFAULT', credit_note.contact.address.address_type)
148
+ assert_equal('LINE 1 OF THE ADDRESS', credit_note.contact.address.line_1)
149
+
150
+ # Test phone defaults.
151
+ assert_equal('DEFAULT', credit_note.contact.phone.phone_type)
152
+ assert_equal('12345678', credit_note.contact.phone.number)
153
+
154
+ # Test the line_item defaults.
155
+ assert_equal('A LINE ITEM', credit_note.line_items.first.description)
156
+ assert_equal('200', credit_note.line_items.first.account_code)
157
+ assert_equal(BigDecimal.new('100'), credit_note.line_items.first.unit_amount)
158
+ assert_equal(BigDecimal.new('12.5'), credit_note.line_items.first.tax_amount)
159
+
160
+ # Test overriding an credit_note parameter (assume works for all).
161
+ credit_note = create_test_credit_note({:type => 'ACCPAYCREDIT'})
162
+ assert_equal('ACCPAYCREDIT', credit_note.type)
163
+
164
+ # Test overriding a contact/address/phone parameter (assume works for all).
165
+ credit_note = create_test_credit_note({}, {:name => 'OVERRIDDEN NAME', :address => {:line_1 => 'OVERRIDDEN LINE 1'}, :phone => {:number => '999'}})
166
+ assert_equal('OVERRIDDEN NAME', credit_note.contact.name)
167
+ assert_equal('OVERRIDDEN LINE 1', credit_note.contact.address.line_1)
168
+ assert_equal('999', credit_note.contact.phone.number)
169
+
170
+ # Test overriding line_items with hash.
171
+ credit_note = create_test_credit_note({}, {}, {:description => 'OVERRIDDEN LINE ITEM'})
172
+ assert_equal(1, credit_note.line_items.size)
173
+ assert_equal('OVERRIDDEN LINE ITEM', credit_note.line_items.first.description)
174
+ assert_equal(BigDecimal.new('100'), credit_note.line_items.first.unit_amount)
175
+
176
+ # Test overriding line_items with array of 2 line_items.
177
+ credit_note = create_test_credit_note({}, {}, [
178
+ {:description => 'OVERRIDDEN ITEM 1'},
179
+ {:description => 'OVERRIDDEN ITEM 2', :account_code => '200', :unit_amount => BigDecimal.new('200'), :tax_amount => '25.0'}
180
+ ])
181
+ assert_equal(2, credit_note.line_items.size)
182
+ assert_equal('OVERRIDDEN ITEM 1', credit_note.line_items[0].description)
183
+ assert_equal(BigDecimal.new('100'), credit_note.line_items[0].unit_amount)
184
+ assert_equal('OVERRIDDEN ITEM 2', credit_note.line_items[1].description)
185
+ assert_equal(BigDecimal.new('200'), credit_note.line_items[1].unit_amount)
186
+ end
187
+
188
+ def test_auto_creation_of_associated_contact
189
+ credit_note = create_test_credit_note({}, nil) # no contact
190
+ assert_nil(credit_note.instance_variable_get("@contact"))
191
+
192
+ new_contact = credit_note.contact
193
+ assert_kind_of(XeroGateway::Contact, new_contact)
194
+ end
195
+
196
+ def test_add_line_item
197
+ credit_note = create_test_credit_note({}, {}, nil) # no line_items
198
+ assert_equal(0, credit_note.line_items.size)
199
+
200
+ line_item_params = {:description => "Test Item 1", :unit_amount => 100}
201
+
202
+ # Test adding line item by hash
203
+ line_item = credit_note.add_line_item(line_item_params)
204
+ assert_kind_of(XeroGateway::LineItem, line_item)
205
+ assert_equal(line_item_params[:description], line_item.description)
206
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
207
+ assert_equal(1, credit_note.line_items.size)
208
+
209
+ # Test adding line item by XeroGateway::LineItem
210
+ line_item = credit_note.add_line_item(line_item_params)
211
+ assert_kind_of(XeroGateway::LineItem, line_item)
212
+ assert_equal(line_item_params[:description], line_item.description)
213
+ assert_equal(line_item_params[:unit_amount], line_item.unit_amount)
214
+ assert_equal(2, credit_note.line_items.size)
215
+
216
+ # Test that pushing anything else into add_line_item fails.
217
+ ["invalid", 100, nil, []].each do | invalid_object |
218
+ assert_raise(XeroGateway::CreditNote::InvalidLineItemError) { credit_note.add_line_item(invalid_object) }
219
+ assert_equal(2, credit_note.line_items.size)
220
+ end
221
+ end
222
+
223
+ private
224
+
225
+ def create_test_credit_note(credit_note_params = {}, contact_params = {}, line_item_params = [])
226
+ unless credit_note_params.nil?
227
+ credit_note_params = {
228
+ :type => 'ACCRECCREDIT',
229
+ :date => Date.today,
230
+ :credit_note_number => '12345',
231
+ :reference => "MY REFERENCE FOR THIS CREDIT NOTE",
232
+ :line_amount_types => "Exclusive"
233
+ }.merge(credit_note_params)
234
+ end
235
+ credit_note = XeroGateway::CreditNote.new(credit_note_params || {})
236
+
237
+ unless contact_params.nil?
238
+ # Strip out :address key from contact_params to use as the default address.
239
+ stripped_address = {
240
+ :address_type => 'DEFAULT',
241
+ :line_1 => 'LINE 1 OF THE ADDRESS'
242
+ }.merge(contact_params.delete(:address) || {})
243
+
244
+ # Strip out :phone key from contact_params to use at the default phone.
245
+ stripped_phone = {
246
+ :phone_type => 'DEFAULT',
247
+ :number => '12345678'
248
+ }.merge(contact_params.delete(:phone) || {})
249
+
250
+ contact_params = {
251
+ :contact_id => '00000000-0000-0000-0000-000000000000', # Just any valid GUID
252
+ :name => "CONTACT NAME",
253
+ :first_name => "Bob",
254
+ :last_name => "Builder"
255
+ }.merge(contact_params)
256
+
257
+ # Create credit_note.contact from contact_params.
258
+ credit_note.contact = XeroGateway::Contact.new(contact_params)
259
+ credit_note.contact.address = XeroGateway::Address.new(stripped_address)
260
+ credit_note.contact.phone = XeroGateway::Phone.new(stripped_phone)
261
+ end
262
+
263
+ unless line_item_params.nil?
264
+ line_item_params = [line_item_params].flatten # always use an array, even if only a single hash passed in
265
+
266
+ # At least one line item, make first have some defaults.
267
+ line_item_params << {} if line_item_params.size == 0
268
+ line_item_params[0] = {
269
+ :description => "A LINE ITEM",
270
+ :account_code => "200",
271
+ :unit_amount => BigDecimal.new("100"),
272
+ :tax_amount => BigDecimal.new("12.5"),
273
+ :tracking => XeroGateway::TrackingCategory.new(:name => "blah", :options => "hello")
274
+ }.merge(line_item_params[0])
275
+
276
+ # Create credit_note.line_items from line_item_params
277
+ line_item_params.each do | line_item |
278
+ credit_note.add_line_item(line_item)
279
+ end
280
+ end
281
+
282
+ credit_note
283
+ end
284
+ end