invoicexpress 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +0 -0
- data/README.md +322 -0
- data/Rakefile +19 -0
- data/invoicexpress.gemspec +26 -0
- data/lib/faraday/response/parse_xml.rb +23 -0
- data/lib/faraday/response/raise_invoicexpress_errors.rb +20 -0
- data/lib/invoicexpress.rb +26 -0
- data/lib/invoicexpress/authentication.rb +15 -0
- data/lib/invoicexpress/client.rb +56 -0
- data/lib/invoicexpress/client/cash_invoices.rb +110 -0
- data/lib/invoicexpress/client/charts.rb +57 -0
- data/lib/invoicexpress/client/clients.rb +215 -0
- data/lib/invoicexpress/client/credit_notes.rb +128 -0
- data/lib/invoicexpress/client/debit_notes.rb +129 -0
- data/lib/invoicexpress/client/invoices.rb +107 -0
- data/lib/invoicexpress/client/items.rb +82 -0
- data/lib/invoicexpress/client/purchase_orders.rb +126 -0
- data/lib/invoicexpress/client/schedules.rb +110 -0
- data/lib/invoicexpress/client/sequences.rb +71 -0
- data/lib/invoicexpress/client/simplified_invoices.rb +130 -0
- data/lib/invoicexpress/client/taxes.rb +82 -0
- data/lib/invoicexpress/client/users.rb +48 -0
- data/lib/invoicexpress/configuration.rb +51 -0
- data/lib/invoicexpress/connection.rb +40 -0
- data/lib/invoicexpress/error.rb +68 -0
- data/lib/invoicexpress/models.rb +29 -0
- data/lib/invoicexpress/models/chart.rb +41 -0
- data/lib/invoicexpress/models/client.rb +24 -0
- data/lib/invoicexpress/models/filter.rb +60 -0
- data/lib/invoicexpress/models/invoice.rb +235 -0
- data/lib/invoicexpress/models/purchase_order.rb +72 -0
- data/lib/invoicexpress/models/quarterly_result.rb +45 -0
- data/lib/invoicexpress/models/schedule.rb +87 -0
- data/lib/invoicexpress/models/sequence.rb +17 -0
- data/lib/invoicexpress/models/supplier.rb +17 -0
- data/lib/invoicexpress/models/top_client.rb +15 -0
- data/lib/invoicexpress/models/top_debtor.rb +14 -0
- data/lib/invoicexpress/models/user.rb +31 -0
- data/lib/invoicexpress/request.rb +63 -0
- data/lib/invoicexpress/version.rb +3 -0
- data/spec/fixtures/charts.invoicing.xml +21 -0
- data/spec/fixtures/charts.quarterly-results.xml +25 -0
- data/spec/fixtures/charts.top-clients.xml +10 -0
- data/spec/fixtures/charts.top-debtors.xml +10 -0
- data/spec/fixtures/charts.treasury.xml +49 -0
- data/spec/fixtures/clients.create.xml +6 -0
- data/spec/fixtures/clients.get.xml +21 -0
- data/spec/fixtures/clients.invoices.xml +11 -0
- data/spec/fixtures/clients.list.xml +18 -0
- data/spec/fixtures/clients.update.xml +1 -0
- data/spec/fixtures/credit_notes.create.xml +53 -0
- data/spec/fixtures/credit_notes.email_document.xml +9 -0
- data/spec/fixtures/credit_notes.list.xml +114 -0
- data/spec/fixtures/credit_notes.update_state.xml +7 -0
- data/spec/fixtures/invoices.create.xml +37 -0
- data/spec/fixtures/invoices.get.xml +50 -0
- data/spec/fixtures/invoices.list.xml +537 -0
- data/spec/fixtures/invoices.update_state.xml +7 -0
- data/spec/fixtures/ok.xml +0 -0
- data/spec/fixtures/po.create.xml +42 -0
- data/spec/fixtures/po.email_document.xml +0 -0
- data/spec/fixtures/po.get.xml +42 -0
- data/spec/fixtures/po.list.xml +44 -0
- data/spec/fixtures/po.update_state.xml +7 -0
- data/spec/fixtures/schedules.create.xml +48 -0
- data/spec/fixtures/schedules.get.xml +57 -0
- data/spec/fixtures/schedules.list.xml +40 -0
- data/spec/fixtures/sequences.create.xml +9 -0
- data/spec/fixtures/sequences.get.xml +10 -0
- data/spec/fixtures/sequences.list.xml +12 -0
- data/spec/fixtures/sequences.update.xml +10 -0
- data/spec/fixtures/simplified_invoices.create.xml +53 -0
- data/spec/fixtures/simplified_invoices.email_document.xml +9 -0
- data/spec/fixtures/simplified_invoices.get.xml +74 -0
- data/spec/fixtures/simplified_invoices.list.xml +114 -0
- data/spec/fixtures/simplified_invoices.update.xml +0 -0
- data/spec/fixtures/simplified_invoices.update_state.xml +7 -0
- data/spec/fixtures/taxes.create.xml +7 -0
- data/spec/fixtures/taxes.list.xml +18 -0
- data/spec/fixtures/taxes.update.xml +7 -0
- data/spec/fixtures/users.accounts.xml +12 -0
- data/spec/fixtures/users.change-account.xml +0 -0
- data/spec/fixtures/users.login.xml +11 -0
- data/spec/helper.rb +62 -0
- data/spec/invoicexpress/client/charts_spec.rb +69 -0
- data/spec/invoicexpress/client/clients_spec.rb +108 -0
- data/spec/invoicexpress/client/credit_notes_spec.rb +104 -0
- data/spec/invoicexpress/client/invoices_spec.rb +110 -0
- data/spec/invoicexpress/client/purchase_orders_spec.rb +116 -0
- data/spec/invoicexpress/client/schedules_spec.rb +111 -0
- data/spec/invoicexpress/client/sequences_spec.rb +68 -0
- data/spec/invoicexpress/client/simplified_invoices_spec.rb +116 -0
- data/spec/invoicexpress/client/taxes_spec.rb +70 -0
- data/spec/invoicexpress/client/users_spec.rb +40 -0
- data/spec/invoicexpress/client_spec.rb +24 -0
- data/spec/invoicexpress_spec.rb +19 -0
- metadata +279 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
module Invoicexpress
|
2
|
+
class Client
|
3
|
+
module Sequences
|
4
|
+
|
5
|
+
# Returns all your sequences.
|
6
|
+
#
|
7
|
+
# @return [Array<Invoicexpress::Models::Sequence>] An array with all the sequences
|
8
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
9
|
+
def sequences(options = {})
|
10
|
+
params = { :klass => Invoicexpress::Models::Sequence }
|
11
|
+
|
12
|
+
get("sequences.xml", params.merge(options))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a specific sequence.
|
16
|
+
#
|
17
|
+
# @param sequence [Invoicexpress::Models::Sequence, String] The sequence or sequence ID
|
18
|
+
# @return Invoicexpress::Models::Sequence The sequence
|
19
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
20
|
+
# @raise Invoicexpress::NotFound When the sequence doesn't exist
|
21
|
+
def sequence(sequence, options={})
|
22
|
+
params = { :klass => Invoicexpress::Models::Sequence }
|
23
|
+
|
24
|
+
get("sequences/#{id_from_sequence(sequence)}.xml", params.merge(options))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates a new sequence.
|
28
|
+
#
|
29
|
+
# @param sequence [Invoicexpress::Models::Sequence] The sequence to create
|
30
|
+
# @return Invoicexpress::Models::Sequence The sequence
|
31
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
32
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
33
|
+
def create_sequence(sequence, options={})
|
34
|
+
raise(ArgumentError, "sequence has the wrong type") unless sequence.is_a?(Invoicexpress::Models::Sequence)
|
35
|
+
|
36
|
+
params = { :klass => Invoicexpress::Models::Sequence, :body => sequence }
|
37
|
+
post("sequences.xml", params.merge(options))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Updates a specific sequence.
|
41
|
+
# Only sequences with no finalized invoices can be updated.
|
42
|
+
#
|
43
|
+
# @param sequence [Invoicexpress::Models::Sequence] The sequence to update
|
44
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
45
|
+
# @raise Invoicexpress::NotFound When the sequence doesn't exist
|
46
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
47
|
+
def update_sequence(sequence, options={})
|
48
|
+
raise(ArgumentError, "sequence has the wrong type") unless sequence.is_a?(Invoicexpress::Models::Sequence)
|
49
|
+
if !sequence.id
|
50
|
+
raise ArgumentError, "Sequence ID is required"
|
51
|
+
end
|
52
|
+
params = { :klass => Invoicexpress::Models::Sequence, :body => sequence }
|
53
|
+
put("sequences/#{sequence.id}.xml", params.merge(options))
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def id_from_sequence(item)
|
58
|
+
if item.is_a?(Invoicexpress::Models::Sequence)
|
59
|
+
item.id
|
60
|
+
elsif item.is_a?(String)
|
61
|
+
item
|
62
|
+
elsif item.is_a?(Integer)
|
63
|
+
item.to_s
|
64
|
+
else
|
65
|
+
raise ArgumentError, "Cannot get sequence id from #{item}"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'invoicexpress/models'
|
2
|
+
|
3
|
+
module Invoicexpress
|
4
|
+
class Client
|
5
|
+
module SimplifiedInvoices
|
6
|
+
|
7
|
+
# Returns all your simplified invoices
|
8
|
+
#
|
9
|
+
# @option options [Integer] page (1) You can ask a specific page of simplified invoices
|
10
|
+
#
|
11
|
+
# @return [Invoicexpress::Models::SimplifiedInvoices] A struct with results (pagination) and all the simplified invoices
|
12
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
13
|
+
def simplified_invoices(options={})
|
14
|
+
params = { :page => 1, :klass => Invoicexpress::Models::SimplifiedInvoice }
|
15
|
+
|
16
|
+
get("simplified_invoices.xml", params.merge(options))
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
# Returns all the information about a simplified invoice:
|
22
|
+
# - Basic information (date, status, sequence number)
|
23
|
+
# - Client
|
24
|
+
# - Document items
|
25
|
+
# - Document timeline
|
26
|
+
# Document timeline is composed by:
|
27
|
+
# - Date, time and the user who created it
|
28
|
+
# - Type of the event
|
29
|
+
# The complete list of timeline events is:
|
30
|
+
# - create
|
31
|
+
# - edited
|
32
|
+
# - send_email
|
33
|
+
# - canceled
|
34
|
+
# - deleted
|
35
|
+
# - settled
|
36
|
+
# - second_copy
|
37
|
+
# - archived
|
38
|
+
# - unarchived
|
39
|
+
# - comment
|
40
|
+
#
|
41
|
+
# @param simplified_invoice_id [String] Requested simplified invoice id
|
42
|
+
# @return [Invoicexpress::Models::SimplifiedInvoice] The requested simplified invoice
|
43
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
44
|
+
# @raise Invoicexpress::NotFound When the simplified_invoice doesn't exist
|
45
|
+
def simplified_invoice(simplified_invoice_id, options={})
|
46
|
+
params = { :klass => Invoicexpress::Models::SimplifiedInvoice }
|
47
|
+
|
48
|
+
get("simplified_invoices/#{simplified_invoice_id}.xml", params.merge(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
# Creates a new simplified invoice. Also allows to create a new client and/or new items in the same request.
|
52
|
+
# If the client name does not exist a new one is created.
|
53
|
+
# If items do not exist with the given names, new ones will be created.
|
54
|
+
# If item name already exists, the item is updated with the new values.
|
55
|
+
# Regarding item taxes, if the tax name is not found, no tax is applyed to that item.
|
56
|
+
# Portuguese accounts should also send the IVA exemption reason if the invoice contains exempt items(IVA 0%)
|
57
|
+
#
|
58
|
+
# @param simplified_invoice [Invoicexpress::Models::SimplifiedInvoice] The simplified invoice to create
|
59
|
+
# @return [Invoicexpress::Models::SimplifiedInvoice] The created simplified invoice
|
60
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
61
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
62
|
+
def create_simplified_invoice(simplified_invoice, options={})
|
63
|
+
raise(ArgumentError, "simplified invoice has the wrong type") unless simplified_invoice.is_a?(Invoicexpress::Models::SimplifiedInvoice)
|
64
|
+
|
65
|
+
params = { :klass => Invoicexpress::Models::SimplifiedInvoice, :body => simplified_invoice }
|
66
|
+
post("simplified_invoices.xml", params.merge(options))
|
67
|
+
end
|
68
|
+
|
69
|
+
# Updates a simplified invoice
|
70
|
+
# It also allows you to create a new client and/or items in the same request.
|
71
|
+
# If the client name does not exist a new client is created.
|
72
|
+
# Regarding item taxes, if the tax name is not found, no tax will be applied to that item.
|
73
|
+
# If item does not exist with the given name, a new one will be created.
|
74
|
+
# If item exists it will be updated with the new values
|
75
|
+
# Be careful when updating the document items, any missing items from the original document will be deleted.
|
76
|
+
#
|
77
|
+
# @param simplified_invoice [Invoicexpress::Models::SimplifiedInvoice] The cash simplified invoice to update
|
78
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
79
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
80
|
+
# @raise Invoicexpress::NotFound When the simplified invoice doesn't exist
|
81
|
+
def update_simplified_invoice(simplified_invoice, options={})
|
82
|
+
raise(ArgumentError, "simplified invoice has the wrong type") unless simplified_invoice.is_a?(Invoicexpress::Models::SimplifiedInvoice)
|
83
|
+
if !simplified_invoice.id
|
84
|
+
raise ArgumentError, "Invoice ID is required"
|
85
|
+
end
|
86
|
+
params = { :klass => Invoicexpress::Models::SimplifiedInvoice, :body => simplified_invoice.to_core }
|
87
|
+
put("simplified_invoices/#{simplified_invoice.id}.xml", params.merge(options))
|
88
|
+
end
|
89
|
+
|
90
|
+
# Changes the state of a simplified invoice.
|
91
|
+
# Possible state transitions:
|
92
|
+
# - draft to final – finalized
|
93
|
+
# - draft to deleted – deleted
|
94
|
+
# - settled to final – unsettled
|
95
|
+
# - final to second copy – second_copy
|
96
|
+
# - final or second copy to canceled – canceled
|
97
|
+
# - final or second copy to settled – settled
|
98
|
+
# Any other transitions will fail.
|
99
|
+
# When canceling a simplified invoice you must specify a reason.
|
100
|
+
#
|
101
|
+
# @param simplified_invoice_id [String] The simplified invoice id to change
|
102
|
+
# @param simplified_invoice_state [Invoicexpress::Models::InvoiceState] The new state
|
103
|
+
# @return [Invoicexpress::Models::SimplifiedInvoice] The updated simplified invoice
|
104
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
105
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
106
|
+
# @raise Invoicexpress::NotFound When the simplified invoice doesn't exist
|
107
|
+
def update_simplified_invoice_state(simplified_invoice_id, simplified_invoice_state, options={})
|
108
|
+
raise(ArgumentError, "simplified invoice state has the wrong type") unless simplified_invoice_state.is_a?(Invoicexpress::Models::InvoiceState)
|
109
|
+
|
110
|
+
params = { :klass => Invoicexpress::Models::SimplifiedInvoice, :body => simplified_invoice_state }
|
111
|
+
put("simplified_invoices/#{simplified_invoice_id}/change-state.xml", params.merge(options))
|
112
|
+
end
|
113
|
+
|
114
|
+
# Sends the simplified invoice through email
|
115
|
+
#
|
116
|
+
# @param simplified_invoice_id [String] The simplified invoice id to send
|
117
|
+
# @param message [Invoicexpress::Models::Message] The message to send
|
118
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
119
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
120
|
+
# @raise Invoicexpress::NotFound When the simplified invoice doesn't exist
|
121
|
+
def simplified_invoice_mail(simplified_invoice_id, message, options={})
|
122
|
+
raise(ArgumentError, "message has the wrong type") unless message.is_a?(Invoicexpress::Models::Message)
|
123
|
+
|
124
|
+
params = { :body => message, :klass => Invoicexpress::Models::SimplifiedInvoice }
|
125
|
+
put("simplified_invoices/#{simplified_invoice_id}/email-document.xml", params.merge(options))
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Invoicexpress
|
2
|
+
class Client
|
3
|
+
module Taxes
|
4
|
+
|
5
|
+
# Returns all your taxes (lol)
|
6
|
+
#
|
7
|
+
# @return [Array<Invoicexpress::Models::Tax>] An array with all your taxes
|
8
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
9
|
+
def taxes(options = {})
|
10
|
+
params = { :klass => Invoicexpress::Models::Tax }
|
11
|
+
|
12
|
+
get("taxes.xml", params.merge(options))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a specific tax.
|
16
|
+
#
|
17
|
+
# @param tax [Invoicexpress::Models::Tax, String] The tax or tax ID
|
18
|
+
# @return Invoicexpress::Models::Tax The tax
|
19
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
20
|
+
# @raise Invoicexpress::NotFound When the tax doesn't exist
|
21
|
+
def tax(tax, options={})
|
22
|
+
params = { :klass => Invoicexpress::Models::Tax }
|
23
|
+
|
24
|
+
get("taxes/#{id_from_tax(tax)}.xml", params.merge(options))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates a tax.
|
28
|
+
#
|
29
|
+
# @param tax [Invoicexpress::Models::Tax] The tax to create
|
30
|
+
# @return Invoicexpress::Models::Tax The tax created
|
31
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
32
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
33
|
+
def create_tax(tax, options={})
|
34
|
+
raise(ArgumentError, "tax has the wrong type") unless tax.is_a?(Invoicexpress::Models::Tax)
|
35
|
+
|
36
|
+
params = { :klass => Invoicexpress::Models::Tax, :body => tax }
|
37
|
+
post("taxes.xml", params.merge(options))
|
38
|
+
end
|
39
|
+
|
40
|
+
# Updates a tax.
|
41
|
+
#
|
42
|
+
# @param tax [Invoicexpress::Models::Tax] The tax to update
|
43
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
44
|
+
# @raise Invoicexpress::NotFound When the tax doesn't exist
|
45
|
+
# @raise Invoicexpress::UnprocessableEntity When there are errors on the submission
|
46
|
+
def update_tax(tax, options={})
|
47
|
+
raise(ArgumentError, "tax has the wrong type") unless tax.is_a?(Invoicexpress::Models::Tax)
|
48
|
+
|
49
|
+
if !tax.id
|
50
|
+
raise ArgumentError, "Tax ID is required"
|
51
|
+
end
|
52
|
+
params = { :klass => Invoicexpress::Models::Tax, :body => tax }
|
53
|
+
put("taxes/#{tax.id}.xml", params.merge(options))
|
54
|
+
end
|
55
|
+
|
56
|
+
# Deletes a tax.
|
57
|
+
#
|
58
|
+
# @param tax [Invoicexpress::Models::Tax, String] The tax or tax ID
|
59
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
60
|
+
# @raise Invoicexpress::NotFound When the tax doesn't exist
|
61
|
+
def delete_tax(tax, options={})
|
62
|
+
params = { :klass => Invoicexpress::Models::Tax }
|
63
|
+
|
64
|
+
delete("taxes/#{id_from_tax(tax)}.xml", params.merge(options))
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
def id_from_tax(item)
|
69
|
+
if item.is_a?(Invoicexpress::Models::Tax)
|
70
|
+
item.id
|
71
|
+
elsif item.is_a?(String)
|
72
|
+
item
|
73
|
+
elsif item.is_a?(Integer)
|
74
|
+
item.to_s
|
75
|
+
else
|
76
|
+
raise ArgumentError, "Cannot get tax id from #{item}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Invoicexpress
|
2
|
+
class Client
|
3
|
+
module Users
|
4
|
+
|
5
|
+
# This endpoint does not require an API KEY to be acessible.
|
6
|
+
# Instead it requires your current login and password.
|
7
|
+
# Upon successful login it will return all the accounts which belong to you
|
8
|
+
#
|
9
|
+
# @param login [String] Login email
|
10
|
+
# @param password [String] Your password
|
11
|
+
# @return [Array<Invoicexpress::Models::Account>] The list of your accounts
|
12
|
+
# @raise Invoicexpress::Unauthorized When the login/password combination is wrong
|
13
|
+
def login(login, password, options={})
|
14
|
+
credentials = Invoicexpress::Models::Credentials.new(
|
15
|
+
:login => login,
|
16
|
+
:password => password
|
17
|
+
)
|
18
|
+
|
19
|
+
params = { :klass => Invoicexpress::Models::Account, :body => credentials }
|
20
|
+
post("login.xml", params.merge(options))
|
21
|
+
end
|
22
|
+
|
23
|
+
# This method allows you to view your accounts.
|
24
|
+
#
|
25
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
26
|
+
# @return [Array<Invoicexpress::Models::Account>] The list of accounts
|
27
|
+
def accounts(options = {})
|
28
|
+
params = { :klass => Invoicexpress::Models::Account }
|
29
|
+
get("users/accounts.xml", params.merge(options))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Changes the current account to the account id submitte
|
33
|
+
#
|
34
|
+
# @param account_id [String] The account ID to change to
|
35
|
+
# @raise Invoicexpress::Unauthorized When the client is unauthorized
|
36
|
+
# @raise Invoicexpress::NotFound When the account doesn't exist
|
37
|
+
def change_account(account_id, options={})
|
38
|
+
change_account_to = Invoicexpress::Models::ChangeAccountTo.new(
|
39
|
+
:id => account_id
|
40
|
+
)
|
41
|
+
|
42
|
+
params = { :klass => Invoicexpress::Models::Account, :body => change_account_to }
|
43
|
+
put("users/change-account.xml", params.merge(options))
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'invoicexpress/version'
|
3
|
+
|
4
|
+
module Invoicexpress
|
5
|
+
module Configuration
|
6
|
+
VALID_OPTIONS_KEYS = [
|
7
|
+
:adapter,
|
8
|
+
:faraday_config_block,
|
9
|
+
:api_endpoint,
|
10
|
+
:screen_name,
|
11
|
+
:proxy,
|
12
|
+
:api_key,
|
13
|
+
:user_agent
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
DEFAULT_ADAPTER = Faraday.default_adapter
|
17
|
+
DEFAULT_API_ENDPOINT = ENV['INVOICEXPRESS_API_ENDPOINT'] || 'https://%s.invoicexpress.net/'
|
18
|
+
DEFAULT_USER_AGENT = "Invoicexpress Ruby Gem #{Invoicexpress::VERSION}".freeze
|
19
|
+
|
20
|
+
attr_accessor(*VALID_OPTIONS_KEYS)
|
21
|
+
|
22
|
+
def self.extended(base)
|
23
|
+
base.reset
|
24
|
+
end
|
25
|
+
|
26
|
+
def configure
|
27
|
+
yield self
|
28
|
+
end
|
29
|
+
|
30
|
+
def options
|
31
|
+
VALID_OPTIONS_KEYS.inject({}) { |o,k| o.merge!(k => send(k)) }
|
32
|
+
end
|
33
|
+
|
34
|
+
def api_endpoint=(value)
|
35
|
+
@api_endpoint = File.join(value, "")
|
36
|
+
end
|
37
|
+
|
38
|
+
def faraday_config(&block)
|
39
|
+
@faraday_config_block = block
|
40
|
+
end
|
41
|
+
|
42
|
+
def reset
|
43
|
+
self.adapter = DEFAULT_ADAPTER
|
44
|
+
self.api_endpoint = DEFAULT_API_ENDPOINT
|
45
|
+
self.user_agent = DEFAULT_USER_AGENT
|
46
|
+
self.api_key = nil
|
47
|
+
self.screen_name = nil
|
48
|
+
self.proxy = nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'faraday_middleware'
|
2
|
+
require 'faraday/response/parse_xml'
|
3
|
+
require 'faraday/response/raise_invoicexpress_errors'
|
4
|
+
|
5
|
+
module Invoicexpress
|
6
|
+
# @private
|
7
|
+
module Connection
|
8
|
+
private
|
9
|
+
|
10
|
+
def connection(options={})
|
11
|
+
klass = options.delete(:klass)
|
12
|
+
|
13
|
+
options = {
|
14
|
+
:raw => false,
|
15
|
+
:ssl => { :verify => false }
|
16
|
+
}.merge(options)
|
17
|
+
|
18
|
+
if !proxy.nil?
|
19
|
+
options.merge!(:proxy => proxy)
|
20
|
+
end
|
21
|
+
|
22
|
+
options.merge!(:params => authentication)
|
23
|
+
|
24
|
+
connection = Faraday.new(options) do |builder|
|
25
|
+
builder.request :url_encoded
|
26
|
+
|
27
|
+
builder.use FaradayMiddleware::FollowRedirects
|
28
|
+
builder.use Faraday::Response::ParseXML, klass
|
29
|
+
builder.use Faraday::Response::RaiseInvoicexpressErrors
|
30
|
+
|
31
|
+
faraday_config_block.call(builder) if faraday_config_block
|
32
|
+
builder.adapter *adapter
|
33
|
+
end
|
34
|
+
|
35
|
+
connection.headers[:user_agent] = user_agent
|
36
|
+
connection
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'happymapper'
|
2
|
+
|
3
|
+
module Invoicexpress
|
4
|
+
module Models
|
5
|
+
class Errors
|
6
|
+
include HappyMapper
|
7
|
+
|
8
|
+
has_many :error, String
|
9
|
+
alias :errors :error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Custom error class for rescuing from all Invoicexpress errors
|
14
|
+
#
|
15
|
+
class Error < StandardError
|
16
|
+
attr_accessor :messages
|
17
|
+
|
18
|
+
def initialize(response=nil)
|
19
|
+
@response = response
|
20
|
+
@messages = []
|
21
|
+
|
22
|
+
super(build_error_message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def response_body
|
26
|
+
@response_body ||=
|
27
|
+
if (body = @response[:body]) && !body.empty?
|
28
|
+
if body.is_a?(String) and body.start_with?("<")
|
29
|
+
Invoicexpress::Models::Errors.parse(body)
|
30
|
+
else
|
31
|
+
body
|
32
|
+
end
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def build_error_message
|
41
|
+
return nil if @response.nil?
|
42
|
+
|
43
|
+
message = if response_body
|
44
|
+
if response_body.respond_to?(:errors)
|
45
|
+
": " + response_body.errors.join(", ")
|
46
|
+
else
|
47
|
+
": " + response_body
|
48
|
+
end
|
49
|
+
else
|
50
|
+
''
|
51
|
+
end
|
52
|
+
|
53
|
+
"#{@response[:method].to_s.upcase} #{@response[:url].to_s}: #{@response[:status]}#{message}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Raised when Invoicexpress returns a 401 HTTP status code
|
58
|
+
class Unauthorized < Error; end
|
59
|
+
|
60
|
+
# Raised when Invoicexpress returns a 404 HTTP status code
|
61
|
+
class NotFound < Error; end
|
62
|
+
|
63
|
+
# Raised when Invoicexpress returns a 422 HTTP status code
|
64
|
+
class UnprocessableEntity < Error; end
|
65
|
+
|
66
|
+
# Raised when Invoicexpress server goes dark (500 HTTP status code)
|
67
|
+
class InternalServerError < Error; end
|
68
|
+
end
|