xeroizer 0.3.5 → 0.4.0
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.
- data/.bundle/config +2 -2
- data/Gemfile +5 -0
- data/Rakefile +17 -1
- data/VERSION +1 -1
- data/lib/xeroizer.rb +5 -1
- data/lib/xeroizer/configuration.rb +19 -0
- data/lib/xeroizer/generic_application.rb +2 -1
- data/lib/xeroizer/logging.rb +8 -0
- data/lib/xeroizer/models/account.rb +2 -1
- data/lib/xeroizer/models/bank_account.rb +12 -0
- data/lib/xeroizer/models/bank_transaction.rb +74 -0
- data/lib/xeroizer/models/invoice.rb +17 -12
- data/lib/xeroizer/models/item.rb +3 -3
- data/lib/xeroizer/models/item_purchase_details.rb +19 -0
- data/lib/xeroizer/models/{item_purchase_sale_details.rb → item_sales_details.rb} +5 -3
- data/lib/xeroizer/models/line_amount_type.rb +11 -0
- data/lib/xeroizer/models/line_item.rb +2 -12
- data/lib/xeroizer/models/line_item_sum.rb +21 -0
- data/lib/xeroizer/models/payment.rb +2 -6
- data/lib/xeroizer/oauth.rb +1 -1
- data/lib/xeroizer/record/base.rb +21 -2
- data/lib/xeroizer/record/validation_helper.rb +14 -2
- data/lib/xeroizer/record/validators/block_validator.rb +22 -0
- data/lib/xeroizer/record/validators/validator.rb +14 -5
- data/lib/xeroizer/record/xml_helper.rb +24 -7
- data/test/acceptance/about_creating_bank_transactions_test.rb +162 -0
- data/test/acceptance/about_fetching_bank_transactions_test.rb +56 -0
- data/test/acceptance/acceptance_test.rb +53 -0
- data/test/acceptance/bank_transaction_reference_data.rb +31 -0
- data/test/test_helper.rb +11 -1
- data/test/unit/models/bank_transaction_model_parsing_test.rb +131 -0
- data/test/unit/models/bank_transaction_test.rb +47 -0
- data/test/unit/models/bank_transaction_validation_test.rb +87 -0
- data/test/unit/models/contact_test.rb +2 -2
- data/test/unit/models/credit_note_test.rb +2 -2
- data/test/unit/models/invoice_test.rb +43 -17
- data/test/unit/models/line_item_sum_test.rb +24 -0
- data/test/unit/models/line_item_test.rb +54 -0
- data/test/unit/oauth_config_test.rb +20 -0
- data/test/unit/oauth_test.rb +1 -1
- data/test/unit/private_application_test.rb +2 -2
- data/test/unit/record/base_model_test.rb +2 -2
- data/test/unit/record/base_test.rb +38 -1
- data/test/unit/record/block_validator_test.rb +125 -0
- data/test/unit/record/model_definition_test.rb +2 -2
- data/test/unit/record/parse_where_hash_test.rb +2 -2
- data/test/unit/record/record_association_test.rb +1 -1
- data/test/unit/record/validators_test.rb +51 -3
- data/test/unit/record_definition_test.rb +2 -2
- data/test/unit/report_definition_test.rb +2 -2
- data/test/unit/report_test.rb +1 -1
- data/xeroizer.gemspec +60 -6
- metadata +124 -66
- data/lib/.DS_Store +0 -0
@@ -0,0 +1,131 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class BankTransactionModelParsingTest < Test::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
# See lib/xeroizer/record/base_model.rb
|
6
|
+
@instance = Xeroizer::Record::BankTransactionModel.new(nil, "BankTransaction")
|
7
|
+
end
|
8
|
+
|
9
|
+
must "parse all the root elements except sub_total, total_tax and total" do
|
10
|
+
some_xml = "
|
11
|
+
<Response>
|
12
|
+
<BankTransactions>
|
13
|
+
<BankTransaction>
|
14
|
+
<Date>2010-07-30T00:00:00</Date>
|
15
|
+
<LineAmountTypes>Inclusive</LineAmountTypes>
|
16
|
+
<SubTotal>15.00</SubTotal>
|
17
|
+
<TotalTax>0.00</TotalTax>
|
18
|
+
<Total>15.00</Total>
|
19
|
+
<UpdatedDateUTC>2008-02-20T12:19:56.657</UpdatedDateUTC>
|
20
|
+
<FullyPaidOnDate>2010-07-30T00:00:00</FullyPaidOnDate>
|
21
|
+
<BankTransactionID>d20b6c54-7f5d-4ce6-ab83-55f609719126</BankTransactionID>
|
22
|
+
<Type>SPEND</Type>
|
23
|
+
<IsReconciled>true</IsReconciled>
|
24
|
+
</BankTransaction>
|
25
|
+
</BankTransactions>
|
26
|
+
</Response>"
|
27
|
+
|
28
|
+
result = @instance.parse_response(some_xml)
|
29
|
+
|
30
|
+
the_bank_transaction = result.response_items.first
|
31
|
+
|
32
|
+
assert_equal Date.parse("2010-07-30T00:00:00"), the_bank_transaction.date
|
33
|
+
assert_equal "Inclusive", the_bank_transaction.line_amount_types
|
34
|
+
assert_equal Date.parse("2008-02-20T12:19:56.657"), the_bank_transaction.updated_date_utc
|
35
|
+
assert_equal Date.parse("2010-07-30T00:00:00"), the_bank_transaction.fully_paid_on_date
|
36
|
+
assert_equal "d20b6c54-7f5d-4ce6-ab83-55f609719126", the_bank_transaction.bank_transaction_id
|
37
|
+
assert_equal "SPEND", the_bank_transaction.type
|
38
|
+
assert the_bank_transaction.reconciled?, "Expected reconciled to be true"
|
39
|
+
end
|
40
|
+
|
41
|
+
must "parse the contact" do
|
42
|
+
some_xml_with_a_contact = "
|
43
|
+
<Response>
|
44
|
+
<BankTransactions>
|
45
|
+
<BankTransaction>
|
46
|
+
<Contact>
|
47
|
+
<ContactID>c09661a2-a954-4e34-98df-f8b6d1dc9b19</ContactID>
|
48
|
+
<ContactStatus>ACTIVE</ContactStatus>
|
49
|
+
<Name>BNZ</Name>
|
50
|
+
<Addresses>
|
51
|
+
<Address>
|
52
|
+
<AddressType>POBOX</AddressType>
|
53
|
+
</Address>
|
54
|
+
<Address>
|
55
|
+
<AddressType>STREET</AddressType>
|
56
|
+
</Address>
|
57
|
+
</Addresses>
|
58
|
+
<Phones>
|
59
|
+
<Phone>
|
60
|
+
<PhoneType>MOBILE</PhoneType>
|
61
|
+
</Phone>
|
62
|
+
</Phones>
|
63
|
+
<UpdatedDateUTC>2010-09-17T19:26:39.157</UpdatedDateUTC>
|
64
|
+
</Contact>
|
65
|
+
</BankTransaction>
|
66
|
+
</BankTransactions>
|
67
|
+
</Response>"
|
68
|
+
|
69
|
+
result = @instance.parse_response(some_xml_with_a_contact)
|
70
|
+
the_bank_transaction = result.response_items.first
|
71
|
+
the_contact = the_bank_transaction.contact
|
72
|
+
|
73
|
+
assert_equal(
|
74
|
+
"c09661a2-a954-4e34-98df-f8b6d1dc9b19",
|
75
|
+
the_contact.contact_id,
|
76
|
+
"Mismatched contact id for contact: #{the_contact.inspect}"
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
must "parse the correct number of line items" do
|
81
|
+
some_xml_with_a_line_item = "
|
82
|
+
<Response>
|
83
|
+
<BankTransactions>
|
84
|
+
<BankTransaction>
|
85
|
+
<LineItems>
|
86
|
+
<LineItem>
|
87
|
+
<Description>Monthly account fee</Description>
|
88
|
+
<UnitAmount>15</UnitAmount>
|
89
|
+
<TaxType>NONE</TaxType>
|
90
|
+
<TaxAmount>0.00</TaxAmount>
|
91
|
+
<LineAmount>15.00</LineAmount>
|
92
|
+
<AccountCode>404</AccountCode>
|
93
|
+
<Quantity>1.0000</Quantity>
|
94
|
+
</LineItem>
|
95
|
+
</LineItems>
|
96
|
+
</BankTransaction>
|
97
|
+
</BankTransactions>
|
98
|
+
</Response>"
|
99
|
+
|
100
|
+
result = @instance.parse_response(some_xml_with_a_line_item)
|
101
|
+
the_bank_transaction = result.response_items.first
|
102
|
+
|
103
|
+
assert_equal(1, the_bank_transaction.line_items.size,
|
104
|
+
"Mismatched number of line items: #{the_bank_transaction.inspect}"
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
must "parse the bank account" do
|
109
|
+
some_xml_with_a_bank_account = "
|
110
|
+
<Response>
|
111
|
+
<BankTransactions>
|
112
|
+
<BankTransaction>
|
113
|
+
<BankAccount>
|
114
|
+
<AccountID>297c2dc5-cc47-4afd-8ec8-74990b8761e9</AccountID>
|
115
|
+
<Code>BANK</Code>
|
116
|
+
</BankAccount>
|
117
|
+
</BankTransaction>
|
118
|
+
</BankTransactions>
|
119
|
+
</Response>"
|
120
|
+
|
121
|
+
result = @instance.parse_response(some_xml_with_a_bank_account)
|
122
|
+
the_bank_transaction = result.response_items.first
|
123
|
+
|
124
|
+
assert_not_nil(the_bank_transaction.bank_account,
|
125
|
+
"Missing bank_account: #{the_bank_transaction.inspect}"
|
126
|
+
)
|
127
|
+
|
128
|
+
assert_equal "297c2dc5-cc47-4afd-8ec8-74990b8761e9", the_bank_transaction.bank_account.account_id,
|
129
|
+
"Unexpected bank account id: #{the_bank_transaction.inspect}"
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class BankTransactionTest < Test::Unit::TestCase
|
4
|
+
include Xeroizer::Record
|
5
|
+
|
6
|
+
def setup
|
7
|
+
fake_parent = Class.new do
|
8
|
+
attr_accessor :application
|
9
|
+
end.new
|
10
|
+
|
11
|
+
the_line_items = [
|
12
|
+
LineItem.build({:quantity => 1, :tax_amount => 0.15, :unit_amount => 1.00, :tax_amount => 0.50}, nil),
|
13
|
+
LineItem.build({:quantity => 1, :tax_amount => 0.15, :unit_amount => 1.00, :tax_amount => 0.50}, nil)
|
14
|
+
]
|
15
|
+
|
16
|
+
@the_bank_transaction = BankTransaction.new fake_parent
|
17
|
+
@the_bank_transaction.line_items = the_line_items
|
18
|
+
end
|
19
|
+
|
20
|
+
context "given a bank_transaction with line_amount_types set to \"Exclusive\"" do
|
21
|
+
setup do
|
22
|
+
@the_bank_transaction.line_amount_types = "Exclusive"
|
23
|
+
end
|
24
|
+
|
25
|
+
must "calculate the total as the sum of its line item line_amount and tax_amount" do
|
26
|
+
assert_equal "3.0", @the_bank_transaction.total.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
must "calculate the sub_total as the sum of the line_amounts" do
|
30
|
+
assert_equal "2.0", @the_bank_transaction.sub_total.to_s
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "given a bank_transaction with line_amount_types set to \"Inclusive\"" do
|
35
|
+
setup do
|
36
|
+
@the_bank_transaction.line_amount_types = "Inclusive"
|
37
|
+
end
|
38
|
+
|
39
|
+
must "calculate the total as the sum of its line item line_amount and tax_amount" do
|
40
|
+
assert_equal "2.0", @the_bank_transaction.total.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
must "calculate the sub_total as the sum of the line_amounts minus the total tax" do
|
44
|
+
assert_equal "1.0", @the_bank_transaction.sub_total.to_s
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class BankTransactionValidationTest < Test::Unit::TestCase
|
4
|
+
include Xeroizer::Record
|
5
|
+
|
6
|
+
must "supply either SPEND or RECEIVE as the type" do
|
7
|
+
instance = BankTransaction.build({:type => "xxx"}, nil)
|
8
|
+
|
9
|
+
assert false == instance.valid?, "Expected invalid because of invalid type"
|
10
|
+
|
11
|
+
expected_error = "Invalid type. Expected either SPEND or RECEIVE."
|
12
|
+
|
13
|
+
assert_equal expected_error, instance.errors_for(:type).first, "Expected an error about type"
|
14
|
+
|
15
|
+
instance = BankTransaction.build({:type => "SPEND"}, nil)
|
16
|
+
|
17
|
+
instance.valid?
|
18
|
+
|
19
|
+
assert_empty instance.errors_for(:type), "Expected no error about type"
|
20
|
+
|
21
|
+
instance = BankTransaction.build({:type => "RECEIVE"}, nil)
|
22
|
+
|
23
|
+
instance.valid?
|
24
|
+
|
25
|
+
assert_empty instance.errors_for(:type), "Expected no error about type"
|
26
|
+
end
|
27
|
+
|
28
|
+
must "supply a non-blank contact" do
|
29
|
+
instance = BankTransaction.build({}, nil)
|
30
|
+
|
31
|
+
assert false == instance.valid?, "Expected invalid because of missing contact"
|
32
|
+
|
33
|
+
assert_equal "can't be blank", instance.errors_for(:contact).first,
|
34
|
+
"Expected an error about blank contact"
|
35
|
+
end
|
36
|
+
|
37
|
+
must "supply at least one line item" do
|
38
|
+
zero_line_items = []
|
39
|
+
|
40
|
+
instance = BankTransaction.build({:line_items => zero_line_items}, nil)
|
41
|
+
|
42
|
+
assert false == instance.valid?, "Expected invalid because of empty line items"
|
43
|
+
|
44
|
+
assert_equal "Invalid line items. Must supply at least one.", instance.errors_for(:line_items).first,
|
45
|
+
"Expected an error about blank line items"
|
46
|
+
|
47
|
+
one_line_item = [LineItem.build({}, nil)]
|
48
|
+
|
49
|
+
instance.errors.clear
|
50
|
+
instance.line_items = one_line_item
|
51
|
+
|
52
|
+
assert_empty instance.errors_for(:line_items), "expected no errors for one line item, #{instance.errors_for(:line_items)}"
|
53
|
+
|
54
|
+
more_than_one_line_item = [LineItem.build({}, nil), LineItem.build({}, nil)]
|
55
|
+
|
56
|
+
instance.errors.clear
|
57
|
+
instance.line_items = more_than_one_line_item
|
58
|
+
|
59
|
+
assert_empty instance.errors_for(:line_items), "expected no errors for more than one line item, #{instance.errors_for(:line_items)}"
|
60
|
+
end
|
61
|
+
|
62
|
+
must "supply a non-blank bank account" do
|
63
|
+
instance = BankTransaction.build({}, nil)
|
64
|
+
|
65
|
+
assert false == instance.valid?, "Expected invalid because of missing bank account"
|
66
|
+
|
67
|
+
assert_equal "can't be blank", instance.errors_for(:bank_account).first,
|
68
|
+
"Expected an error about blank contact"
|
69
|
+
end
|
70
|
+
|
71
|
+
must "supply valid line_amount_types value" do
|
72
|
+
instance = BankTransaction.build({
|
73
|
+
:line_amount_types => "XXX_ANYTHING_INVALID_XXX"
|
74
|
+
}, nil)
|
75
|
+
|
76
|
+
assert false == instance.valid?, "Expected invalid because of missing bank account"
|
77
|
+
|
78
|
+
assert_equal "not one of Exclusive, Inclusive, NoTax", instance.errors_for(:line_amount_types).first,
|
79
|
+
"Expected an error about blank contact"
|
80
|
+
end
|
81
|
+
|
82
|
+
must "line_amount_type defaults to \"Exclusive\"" do
|
83
|
+
instance = BankTransaction.build({}, nil)
|
84
|
+
|
85
|
+
assert_equal "Exclusive", instance.line_amount_types
|
86
|
+
end
|
87
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require 'test_helper'
|
2
2
|
|
3
3
|
class InvoiceTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
@@ -8,7 +8,23 @@ class InvoiceTest < Test::Unit::TestCase
|
|
8
8
|
mock_api('Invoices')
|
9
9
|
@invoice = @client.Invoice.first
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
|
+
def build_valid_authorised_invoice
|
13
|
+
@client.Invoice.build({
|
14
|
+
:type => "ACCREC",
|
15
|
+
:contact => { :name => "ABC Limited" },
|
16
|
+
:status => "AUTHORISED",
|
17
|
+
:date => Date.today,
|
18
|
+
:due_date => Date.today,
|
19
|
+
:line_items => [{
|
20
|
+
:description => "Consulting services as agreed",
|
21
|
+
:quantity => 0.005,
|
22
|
+
:unit_amount => 1,
|
23
|
+
:account_code => 200
|
24
|
+
}]
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
12
28
|
context "invoice types" do
|
13
29
|
|
14
30
|
should "have helpers to determine invoice type" do
|
@@ -45,7 +61,7 @@ class InvoiceTest < Test::Unit::TestCase
|
|
45
61
|
assert_equal(invoice.attributes[:total], invoice.total)
|
46
62
|
end
|
47
63
|
end
|
48
|
-
|
64
|
+
|
49
65
|
end
|
50
66
|
|
51
67
|
context "invoice validations" do
|
@@ -65,22 +81,32 @@ class InvoiceTest < Test::Unit::TestCase
|
|
65
81
|
end
|
66
82
|
|
67
83
|
should "build a valid AUTHORISED invoice with complete attributes" do
|
68
|
-
invoice =
|
69
|
-
:type => "ACCREC",
|
70
|
-
:contact => { :name => "ABC Limited" },
|
71
|
-
:status => "AUTHORISED",
|
72
|
-
:date => Date.today,
|
73
|
-
:due_date => Date.today,
|
74
|
-
:line_items => [{
|
75
|
-
:description => "Consulting services as agreed",
|
76
|
-
:quantity => 5,
|
77
|
-
:unit_amount => 120,
|
78
|
-
:account_code => 200
|
79
|
-
}]
|
80
|
-
})
|
84
|
+
invoice = build_valid_authorised_invoice
|
81
85
|
assert_equal(true, invoice.valid?)
|
82
86
|
end
|
83
87
|
|
84
88
|
end
|
85
89
|
|
86
|
-
|
90
|
+
context "line items" do
|
91
|
+
|
92
|
+
should "round line item amounts to two decimal places" do
|
93
|
+
invoice = build_valid_authorised_invoice
|
94
|
+
assert_equal(0.01, invoice.line_items.first.line_amount)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
context "contact shortcuts" do
|
100
|
+
|
101
|
+
should "have valid #contact_name and #contact_id without downloading full invoice" do
|
102
|
+
invoices = @client.Invoice.all
|
103
|
+
invoices.each do |invoice|
|
104
|
+
assert_not_equal("", invoice.contact_name)
|
105
|
+
assert_not_equal("", invoice.contact_id)
|
106
|
+
assert_equal(false, invoice.complete_record_downloaded?)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class LineItemSumTest < Test::Unit::TestCase
|
4
|
+
include Xeroizer::Record
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@the_line_items = [
|
8
|
+
LineItem.build({:quantity => 1, :unit_amount => 1.00, :tax_amount => 0.15}, nil),
|
9
|
+
LineItem.build({:quantity => 1, :unit_amount => 1.00, :tax_amount => 0.30}, nil)
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "sub_total is the sum of the line_amounts" do
|
14
|
+
assert_equal BigDecimal("2.00"), LineItemSum.sub_total(@the_line_items)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "total_tax is the sum of the tax_amounts" do
|
18
|
+
assert_equal BigDecimal("0.45"), LineItemSum.total_tax(@the_line_items)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "total is the sum of sub_total and total_tax" do
|
22
|
+
assert_equal BigDecimal("2.45"), LineItemSum.total(@the_line_items)
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class LineItemTest < Test::Unit::TestCase
|
4
|
+
include Xeroizer::Record
|
5
|
+
|
6
|
+
it "line_amount equals unit_price times quantity" do
|
7
|
+
line_item = LineItem.new(nil)
|
8
|
+
|
9
|
+
line_item.quantity = 1
|
10
|
+
line_item.unit_amount = BigDecimal("1337.00")
|
11
|
+
line_item.tax_amount = BigDecimal("0.15")
|
12
|
+
|
13
|
+
expected = BigDecimal((line_item.quantity * (line_item.unit_amount)).to_s).round(2)
|
14
|
+
|
15
|
+
assert_equal expected.to_s, line_item.line_amount.to_s
|
16
|
+
end
|
17
|
+
|
18
|
+
it "line_amount is zero when quantity is nil or zero" do
|
19
|
+
line_item = LineItem.new(nil)
|
20
|
+
|
21
|
+
line_item.quantity = nil
|
22
|
+
line_item.unit_amount = BigDecimal("1.00")
|
23
|
+
line_item.tax_amount = BigDecimal("0.15")
|
24
|
+
|
25
|
+
assert_equal "0.0", line_item.line_amount.to_s, "expected line amount zero when quantity is nil"
|
26
|
+
|
27
|
+
line_item.quantity = 0
|
28
|
+
assert_equal "0.0", line_item.line_amount.to_s, "expected line amount zero when quantity is zero"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "is not possible to set unit_amount to zero" do
|
32
|
+
line_item = LineItem.new(nil)
|
33
|
+
|
34
|
+
line_item.quantity = 1
|
35
|
+
line_item.unit_amount = nil
|
36
|
+
line_item.tax_amount = BigDecimal("0.15")
|
37
|
+
|
38
|
+
assert_equal 0.0, line_item.unit_amount,
|
39
|
+
"Expected setting unit_amount to nil to be ignored, i.e., it should remain zero"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "line_amount is zero when unit_amount is nil or zero" do
|
43
|
+
line_item = LineItem.new(nil)
|
44
|
+
|
45
|
+
line_item.quantity = 1
|
46
|
+
line_item.unit_amount = nil
|
47
|
+
line_item.tax_amount = BigDecimal("0.15")
|
48
|
+
|
49
|
+
assert_equal "0.0", line_item.line_amount.to_s, "expected line amount zero when unit_amount is nil"
|
50
|
+
|
51
|
+
line_item.unit_amount = BigDecimal("0.00")
|
52
|
+
assert_equal "0.0", line_item.line_amount.to_s, "expected line amount zero when unit_amount is zero"
|
53
|
+
end
|
54
|
+
end
|