xeroizer 2.15.5 → 2.15.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +14 -3
- data/lib/xeroizer.rb +5 -0
- data/lib/xeroizer/generic_application.rb +15 -9
- data/lib/xeroizer/http.rb +44 -34
- data/lib/xeroizer/models/account.rb +15 -11
- data/lib/xeroizer/models/allocation.rb +13 -0
- data/lib/xeroizer/models/attachment.rb +93 -0
- data/lib/xeroizer/models/bank_transaction.rb +3 -2
- data/lib/xeroizer/models/contact.rb +20 -12
- data/lib/xeroizer/models/contact_person.rb +20 -0
- data/lib/xeroizer/models/credit_note.rb +2 -0
- data/lib/xeroizer/models/expense_claim.rb +29 -0
- data/lib/xeroizer/models/invoice.rb +42 -29
- data/lib/xeroizer/models/line_item.rb +1 -0
- data/lib/xeroizer/models/organisation.rb +6 -1
- data/lib/xeroizer/models/payment.rb +16 -11
- data/lib/xeroizer/models/receipt.rb +39 -0
- data/lib/xeroizer/models/tax_component.rb +13 -0
- data/lib/xeroizer/models/tax_rate.rb +14 -3
- data/lib/xeroizer/models/user.rb +26 -0
- data/lib/xeroizer/oauth.rb +3 -3
- data/lib/xeroizer/record/base.rb +40 -31
- data/lib/xeroizer/record/base_model.rb +31 -25
- data/lib/xeroizer/record/base_model_http_proxy.rb +4 -1
- data/lib/xeroizer/record/record_association_helper.rb +35 -35
- data/lib/xeroizer/record/xml_helper.rb +1 -1
- data/lib/xeroizer/report/factory.rb +2 -1
- data/lib/xeroizer/version.rb +3 -0
- data/test/stub_responses/organisation.xml +30 -0
- data/test/stub_responses/tax_rates.xml +81 -1
- data/test/stub_responses/users.xml +17 -0
- data/test/unit/generic_application_test.rb +21 -0
- data/test/unit/http_test.rb +18 -0
- data/test/unit/models/bank_transaction_test.rb +1 -4
- data/test/unit/models/line_item_sum_test.rb +3 -2
- data/test/unit/models/tax_rate_test.rb +81 -0
- data/test/unit/oauth_test.rb +4 -2
- data/test/unit/record/base_test.rb +1 -1
- data/test/unit/record/model_definition_test.rb +9 -3
- data/test/unit/record/record_association_test.rb +1 -1
- data/test/unit/record_definition_test.rb +1 -1
- metadata +540 -205
- data/.bundle/config +0 -2
- data/.gitattributes +0 -22
- data/Gemfile +0 -20
- data/Gemfile.lock +0 -59
- data/Rakefile +0 -55
- data/VERSION +0 -1
- data/xeroizer.gemspec +0 -409
@@ -29,6 +29,7 @@ module Xeroizer
|
|
29
29
|
|
30
30
|
datetime_utc :updated_date_utc, :api_name => "UpdatedDateUTC"
|
31
31
|
date :fully_paid_on_date
|
32
|
+
string :url
|
32
33
|
string :reference
|
33
34
|
string :bank_transaction_id, :api_name => "BankTransactionID"
|
34
35
|
boolean :is_reconciled
|
@@ -45,8 +46,8 @@ module Xeroizer
|
|
45
46
|
:in => Xeroizer::Record::LINE_AMOUNT_TYPES, :allow_blanks => false
|
46
47
|
|
47
48
|
validates_inclusion_of :type,
|
48
|
-
:in => %w{SPEND RECEIVE}, :allow_blanks => false,
|
49
|
-
:message => "Invalid type. Expected either SPEND or RECEIVE."
|
49
|
+
:in => %w{SPEND RECEIVE RECEIVE-PREPAYMENT RECEIVE-OVERPAYMENT}, :allow_blanks => false,
|
50
|
+
:message => "Invalid type. Expected either SPEND, RECEIVE, RECEIVE-PREPAYMENT or RECEIVE-OVERPAYMENT."
|
50
51
|
validates_inclusion_of :status, :in => BANK_TRANSACTION_STATUSES, :unless => :new_record?
|
51
52
|
|
52
53
|
validates_presence_of :contact, :bank_account, :allow_blanks => false
|
@@ -1,23 +1,26 @@
|
|
1
|
+
require "xeroizer/models/contact_person"
|
2
|
+
|
1
3
|
module Xeroizer
|
2
4
|
module Record
|
3
|
-
|
5
|
+
|
4
6
|
class ContactModel < BaseModel
|
5
|
-
|
7
|
+
|
6
8
|
set_permissions :read, :write, :update
|
7
|
-
|
9
|
+
|
8
10
|
end
|
9
|
-
|
11
|
+
|
10
12
|
class Contact < Base
|
11
|
-
|
13
|
+
|
12
14
|
CONTACT_STATUS = {
|
13
15
|
'ACTIVE' => 'Active',
|
14
|
-
'DELETED' => 'Deleted'
|
16
|
+
'DELETED' => 'Deleted',
|
17
|
+
'ARCHIVED' => 'Archived'
|
15
18
|
} unless defined?(CONTACT_STATUS)
|
16
|
-
|
19
|
+
|
17
20
|
set_primary_key :contact_id
|
18
21
|
set_possible_primary_keys :contact_id, :contact_number
|
19
22
|
list_contains_summary_only true
|
20
|
-
|
23
|
+
|
21
24
|
guid :contact_id
|
22
25
|
string :contact_number
|
23
26
|
string :contact_status
|
@@ -35,15 +38,20 @@ module Xeroizer
|
|
35
38
|
datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
|
36
39
|
boolean :is_supplier
|
37
40
|
boolean :is_customer
|
38
|
-
|
41
|
+
|
39
42
|
has_many :addresses, :list_complete => true
|
40
43
|
has_many :phones, :list_complete => true
|
41
44
|
has_many :contact_groups
|
42
|
-
|
45
|
+
has_many :contact_persons, :internal_name => :contact_people
|
46
|
+
|
43
47
|
validates_presence_of :name
|
44
48
|
validates_inclusion_of :contact_status, :in => CONTACT_STATUS.keys, :allow_blanks => true
|
45
|
-
|
49
|
+
|
50
|
+
def email_address?
|
51
|
+
email_address.present?
|
52
|
+
end
|
53
|
+
|
46
54
|
end
|
47
|
-
|
55
|
+
|
48
56
|
end
|
49
57
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'xeroizer/models/account'
|
2
|
+
require 'xeroizer/models/line_amount_type'
|
3
|
+
|
4
|
+
module Xeroizer
|
5
|
+
module Record
|
6
|
+
class ContactPersonModel < BaseModel
|
7
|
+
set_xml_root_name "ContactPersons"
|
8
|
+
end
|
9
|
+
|
10
|
+
class ContactPerson < Base
|
11
|
+
|
12
|
+
string :first_name
|
13
|
+
string :last_name
|
14
|
+
string :email_address
|
15
|
+
boolean :include_in_emails
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -62,11 +62,13 @@ module Xeroizer
|
|
62
62
|
|
63
63
|
belongs_to :contact
|
64
64
|
has_many :line_items
|
65
|
+
has_many :allocations
|
65
66
|
|
66
67
|
validates_inclusion_of :type, :in => CREDIT_NOTE_TYPES
|
67
68
|
validates_inclusion_of :status, :in => CREDIT_NOTE_STATUSES, :allow_blanks => true
|
68
69
|
validates_associated :contact
|
69
70
|
validates_associated :line_items
|
71
|
+
validates_associated :allocations, :allow_blanks => true
|
70
72
|
|
71
73
|
public
|
72
74
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Xeroizer
|
2
|
+
module Record
|
3
|
+
|
4
|
+
class ExpenseClaimModel < BaseModel
|
5
|
+
|
6
|
+
set_permissions :read, :write, :update
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class ExpenseClaim < Base
|
11
|
+
|
12
|
+
set_primary_key :expense_claim_id
|
13
|
+
|
14
|
+
guid :expense_claim_id
|
15
|
+
string :status
|
16
|
+
decimal :total
|
17
|
+
decimal :amount_due
|
18
|
+
decimal :amount_paid
|
19
|
+
date :payment_due_date
|
20
|
+
date :reporting_date
|
21
|
+
datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
|
22
|
+
|
23
|
+
belongs_to :user
|
24
|
+
has_many :receipts
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -1,32 +1,36 @@
|
|
1
|
+
require "xeroizer/models/attachment"
|
2
|
+
|
1
3
|
module Xeroizer
|
2
4
|
module Record
|
3
|
-
|
5
|
+
|
4
6
|
class InvoiceModel < BaseModel
|
5
7
|
# To create a new invoice, use the folowing
|
6
8
|
# $xero_client.Invoice.build(type: 'ACCREC', ..., contact: {name: 'Foo Bar'},...)
|
7
9
|
# Note that we are not making an api request to xero just to get the contact
|
8
|
-
|
10
|
+
|
9
11
|
set_permissions :read, :write, :update
|
10
|
-
|
12
|
+
|
13
|
+
include AttachmentModel::Extensions
|
14
|
+
|
11
15
|
public
|
12
|
-
|
16
|
+
|
13
17
|
# Retrieve the PDF version of the invoice matching the `id`.
|
14
18
|
# @param [String] id invoice's ID.
|
15
19
|
# @param [String] filename optional filename to store the PDF in instead of returning the data.
|
16
20
|
def pdf(id, filename = nil)
|
17
21
|
pdf_data = @application.http_get(@application.client, "#{url}/#{CGI.escape(id)}", :response => :pdf)
|
18
22
|
if filename
|
19
|
-
File.open(filename, "
|
23
|
+
File.open(filename, "wb") { | fp | fp.write pdf_data }
|
20
24
|
nil
|
21
25
|
else
|
22
26
|
pdf_data
|
23
27
|
end
|
24
28
|
end
|
25
|
-
|
29
|
+
|
26
30
|
end
|
27
|
-
|
31
|
+
|
28
32
|
class Invoice < Base
|
29
|
-
|
33
|
+
|
30
34
|
INVOICE_TYPE = {
|
31
35
|
'ACCREC' => 'Accounts Receivable',
|
32
36
|
'ACCPAY' => 'Accounts Payable'
|
@@ -42,11 +46,13 @@ module Xeroizer
|
|
42
46
|
'VOIDED' => 'Approved invoices that are voided'
|
43
47
|
} unless defined?(INVOICE_STATUS)
|
44
48
|
INVOICE_STATUSES = INVOICE_STATUS.keys.sort
|
45
|
-
|
49
|
+
|
50
|
+
include Attachment::Extensions
|
51
|
+
|
46
52
|
set_primary_key :invoice_id
|
47
53
|
set_possible_primary_keys :invoice_id, :invoice_number
|
48
54
|
list_contains_summary_only true
|
49
|
-
|
55
|
+
|
50
56
|
guid :invoice_id
|
51
57
|
string :invoice_number
|
52
58
|
string :reference
|
@@ -65,14 +71,16 @@ module Xeroizer
|
|
65
71
|
decimal :amount_credited
|
66
72
|
datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
|
67
73
|
string :currency_code
|
74
|
+
decimal :currency_rate
|
68
75
|
datetime :fully_paid_on_date
|
69
76
|
boolean :sent_to_contact
|
70
|
-
|
77
|
+
boolean :has_attachments
|
78
|
+
|
71
79
|
belongs_to :contact
|
72
80
|
has_many :line_items
|
73
81
|
has_many :payments
|
74
82
|
has_many :credit_notes
|
75
|
-
|
83
|
+
|
76
84
|
validates_presence_of :date, :due_date, :unless => :new_record?
|
77
85
|
validates_inclusion_of :type, :in => INVOICE_TYPES
|
78
86
|
validates_inclusion_of :status, :in => INVOICE_STATUSES, :unless => :new_record?
|
@@ -80,9 +88,9 @@ module Xeroizer
|
|
80
88
|
validates_associated :contact
|
81
89
|
validates_associated :line_items, :allow_blanks => true, :unless => :approved?
|
82
90
|
validates_associated :line_items, :if => :approved?
|
83
|
-
|
91
|
+
|
84
92
|
public
|
85
|
-
|
93
|
+
|
86
94
|
# Access the contact name without forcing a download of
|
87
95
|
# an incomplete, summary invoice.
|
88
96
|
def contact_name
|
@@ -94,12 +102,12 @@ module Xeroizer
|
|
94
102
|
def contact_id
|
95
103
|
attributes[:contact] && attributes[:contact][:contact_id]
|
96
104
|
end
|
97
|
-
|
105
|
+
|
98
106
|
# Helper method to check if the invoice has been approved.
|
99
107
|
def approved?
|
100
108
|
[ 'AUTHORISED', 'PAID', 'VOIDED' ].include? status
|
101
109
|
end
|
102
|
-
|
110
|
+
|
103
111
|
# Helper method to check if the invoice is accounts payable.
|
104
112
|
def accounts_payable?
|
105
113
|
type == 'ACCPAY'
|
@@ -109,12 +117,12 @@ module Xeroizer
|
|
109
117
|
def accounts_receivable?
|
110
118
|
type == 'ACCREC'
|
111
119
|
end
|
112
|
-
|
120
|
+
|
113
121
|
def sub_total=(sub_total)
|
114
122
|
@sub_total_is_set = true
|
115
123
|
attributes[:sub_total] = sub_total
|
116
124
|
end
|
117
|
-
|
125
|
+
|
118
126
|
def total_tax=(total_tax)
|
119
127
|
@total_tax_is_set = true
|
120
128
|
attributes[:total_tax] = total_tax
|
@@ -129,9 +137,9 @@ module Xeroizer
|
|
129
137
|
def sub_total(always_summary = false)
|
130
138
|
if !@sub_total_is_set && not_summary_or_loaded_record(always_summary)
|
131
139
|
sum = (line_items || []).inject(BigDecimal.new('0')) { | sum, line_item | sum + line_item.line_amount }
|
132
|
-
|
140
|
+
|
133
141
|
# If the default amount types are inclusive of 'tax' then remove the tax amount from this sub-total.
|
134
|
-
sum -= total_tax if line_amount_types == 'Inclusive'
|
142
|
+
sum -= total_tax if line_amount_types == 'Inclusive'
|
135
143
|
sum
|
136
144
|
else
|
137
145
|
attributes[:sub_total]
|
@@ -155,16 +163,16 @@ module Xeroizer
|
|
155
163
|
attributes[:total]
|
156
164
|
end
|
157
165
|
end
|
158
|
-
|
166
|
+
|
159
167
|
def not_summary_or_loaded_record(always_summary)
|
160
168
|
!always_summary && loaded_record?
|
161
169
|
end
|
162
170
|
|
163
171
|
def loaded_record?
|
164
|
-
new_record? ||
|
172
|
+
new_record? ||
|
165
173
|
(!new_record? && line_items && line_items.size > 0)
|
166
174
|
end
|
167
|
-
|
175
|
+
|
168
176
|
# Retrieve the PDF version of this invoice.
|
169
177
|
# @param [String] filename optional filename to store the PDF in instead of returning the data.
|
170
178
|
def pdf(filename = nil)
|
@@ -173,23 +181,28 @@ module Xeroizer
|
|
173
181
|
|
174
182
|
# Delete an approved invoice with no payments.
|
175
183
|
def delete!
|
176
|
-
|
184
|
+
change_status!('DELETED')
|
177
185
|
end
|
178
186
|
|
179
187
|
# Void an approved invoice with no payments.
|
180
188
|
def void!
|
181
|
-
|
189
|
+
change_status!('VOIDED')
|
190
|
+
end
|
191
|
+
|
192
|
+
# Approve a draft invoice
|
193
|
+
def approve!
|
194
|
+
change_status!('AUTHORISED')
|
182
195
|
end
|
183
196
|
|
184
197
|
protected
|
185
198
|
|
186
|
-
def
|
187
|
-
raise CannotChangeInvoiceStatus.new(
|
199
|
+
def change_status!(new_status)
|
200
|
+
raise CannotChangeInvoiceStatus.new(self, new_status) unless self.payments.size == 0
|
188
201
|
self.status = new_status
|
189
202
|
self.save
|
190
203
|
end
|
191
|
-
|
204
|
+
|
192
205
|
end
|
193
|
-
|
206
|
+
|
194
207
|
end
|
195
208
|
end
|
@@ -13,6 +13,7 @@ module Xeroizer
|
|
13
13
|
string :api_key, :api_name => 'APIKey'
|
14
14
|
string :name
|
15
15
|
string :legal_name
|
16
|
+
string :short_code
|
16
17
|
boolean :pays_tax
|
17
18
|
string :version
|
18
19
|
string :organisation_type
|
@@ -26,9 +27,13 @@ module Xeroizer
|
|
26
27
|
date :end_of_year_lock_date
|
27
28
|
string :tax_number
|
28
29
|
string :registration_number
|
30
|
+
string :timezone
|
29
31
|
datetime :created_date_utc, :api_name => 'CreatedDateUTC'
|
30
32
|
|
33
|
+
has_many :addresses
|
34
|
+
has_many :phones
|
35
|
+
|
31
36
|
end
|
32
37
|
|
33
38
|
end
|
34
|
-
end
|
39
|
+
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module Xeroizer
|
2
2
|
module Record
|
3
|
-
|
3
|
+
|
4
4
|
class PaymentModel < BaseModel
|
5
|
-
|
5
|
+
|
6
6
|
set_xml_root_name 'Payments'
|
7
7
|
set_permissions :read, :write
|
8
|
-
|
8
|
+
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
class Payment < Base
|
12
|
-
|
12
|
+
|
13
13
|
set_primary_key :payment_id
|
14
|
-
|
14
|
+
|
15
15
|
guid :payment_id
|
16
16
|
date :date
|
17
17
|
decimal :amount
|
@@ -23,20 +23,25 @@ module Xeroizer
|
|
23
23
|
|
24
24
|
belongs_to :account
|
25
25
|
belongs_to :invoice
|
26
|
-
|
26
|
+
belongs_to :credit_note
|
27
|
+
|
27
28
|
def invoice_id
|
28
29
|
invoice.id if invoice
|
29
30
|
end
|
30
|
-
|
31
|
+
|
32
|
+
def credit_note_id
|
33
|
+
credit_note.id if credit_note
|
34
|
+
end
|
35
|
+
|
31
36
|
def account_id
|
32
37
|
account.id if account
|
33
38
|
end
|
34
|
-
|
39
|
+
|
35
40
|
def account_code
|
36
41
|
account.code if account
|
37
42
|
end
|
38
|
-
|
43
|
+
|
39
44
|
end
|
40
|
-
|
45
|
+
|
41
46
|
end
|
42
47
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Xeroizer
|
2
|
+
module Record
|
3
|
+
|
4
|
+
class ReceiptModel < BaseModel
|
5
|
+
|
6
|
+
set_permissions :read, :write, :update
|
7
|
+
|
8
|
+
include AttachmentModel::Extensions
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
class Receipt < Base
|
13
|
+
|
14
|
+
include Attachment::Extensions
|
15
|
+
|
16
|
+
set_primary_key :receipt_id
|
17
|
+
set_possible_primary_keys :receipt_id, :receipt_number
|
18
|
+
|
19
|
+
guid :receipt_id
|
20
|
+
string :receipt_number
|
21
|
+
string :reference
|
22
|
+
string :status
|
23
|
+
string :line_amount_types
|
24
|
+
decimal :sub_total, :calculated => true
|
25
|
+
decimal :total_tax, :calculated => true
|
26
|
+
decimal :total, :calculated => true
|
27
|
+
date :date
|
28
|
+
string :url
|
29
|
+
boolean :has_attachments
|
30
|
+
datetime_utc :updated_date_utc, :api_name => 'UpdatedDateUTC'
|
31
|
+
|
32
|
+
belongs_to :user
|
33
|
+
belongs_to :contact
|
34
|
+
has_many :line_items
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|