invoiced 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/Gemfile +3 -1
- data/lib/invoiced/attachment.rb +1 -1
- data/lib/invoiced/contact.rb +5 -5
- data/lib/invoiced/credit_note.rb +37 -0
- data/lib/invoiced/customer.rb +37 -37
- data/lib/invoiced/email.rb +1 -1
- data/lib/invoiced/error/api_connection_error.rb +2 -2
- data/lib/invoiced/error/api_error.rb +2 -2
- data/lib/invoiced/error/authentication_error.rb +2 -2
- data/lib/invoiced/error/error_base.rb +13 -13
- data/lib/invoiced/error/invalid_request.rb +2 -2
- data/lib/invoiced/estimate.rb +37 -0
- data/lib/invoiced/event.rb +2 -2
- data/lib/invoiced/file.rb +3 -3
- data/lib/invoiced/invoice.rb +33 -33
- data/lib/invoiced/line_item.rb +5 -5
- data/lib/invoiced/list.rb +20 -20
- data/lib/invoiced/object.rb +165 -165
- data/lib/invoiced/operations/create.rb +8 -8
- data/lib/invoiced/operations/delete.rb +10 -10
- data/lib/invoiced/operations/list.rb +12 -12
- data/lib/invoiced/operations/update.rb +19 -19
- data/lib/invoiced/subscription.rb +8 -8
- data/lib/invoiced/transaction.rb +15 -15
- data/lib/invoiced/util.rb +51 -51
- data/lib/invoiced/version.rb +1 -1
- data/lib/invoiced.rb +114 -110
- data/test/invoiced/credit_note_test.rb +126 -0
- data/test/invoiced/estimate_test.rb +126 -0
- metadata +8 -2
data/lib/invoiced/object.rb
CHANGED
@@ -1,167 +1,167 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
2
|
+
class Object
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :client
|
6
|
+
|
7
|
+
@@permanent_attributes = Set.new([:id])
|
8
|
+
|
9
|
+
def initialize(client, id=nil, values={})
|
10
|
+
@client = client
|
11
|
+
class_name = self.class.name.split('::').last
|
12
|
+
@endpoint_base = ''
|
13
|
+
@endpoint = '/' + class_name.underscore.pluralize.downcase
|
14
|
+
|
15
|
+
@id = id
|
16
|
+
@values = {}
|
17
|
+
|
18
|
+
if !id.nil?
|
19
|
+
@endpoint += "/#{id}"
|
20
|
+
@unsaved = Set.new
|
21
|
+
refresh_from(values.dup.merge({:id => id}))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_endpoint_base(base)
|
26
|
+
@endpoint_base = base
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def endpoint_base()
|
31
|
+
@endpoint_base
|
32
|
+
end
|
33
|
+
|
34
|
+
def endpoint()
|
35
|
+
@endpoint_base + @endpoint
|
36
|
+
end
|
37
|
+
|
38
|
+
def retrieve(id, opts={})
|
39
|
+
if !id
|
40
|
+
raise ArgumentError.new("Missing ID.")
|
41
|
+
end
|
42
|
+
|
43
|
+
response = @client.request(:get, "#{self.endpoint()}/#{id}", opts)
|
44
|
+
|
45
|
+
Util.convert_to_object(self, response[:body])
|
46
|
+
end
|
47
|
+
|
48
|
+
def load(opts={})
|
49
|
+
end
|
50
|
+
|
51
|
+
def to_s(*args)
|
52
|
+
JSON.pretty_generate(@values)
|
53
|
+
end
|
54
|
+
|
55
|
+
def inspect
|
56
|
+
id_string = (!@id.nil?) ? " id=#{@id}" : ""
|
57
|
+
"#<#{self.class}:0x#{self.object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values)
|
58
|
+
end
|
59
|
+
|
60
|
+
def refresh_from(values)
|
61
|
+
removed = Set.new(@values.keys - values.keys)
|
62
|
+
added = Set.new(values.keys - @values.keys)
|
63
|
+
|
64
|
+
instance_eval do
|
65
|
+
remove_accessors(removed)
|
66
|
+
add_accessors(added)
|
67
|
+
end
|
68
|
+
removed.each do |k|
|
69
|
+
@values.delete(k)
|
70
|
+
@unsaved.delete(k)
|
71
|
+
end
|
72
|
+
values.each do |k, v|
|
73
|
+
@values[k] = v
|
74
|
+
@unsaved.delete(k)
|
75
|
+
end
|
76
|
+
|
77
|
+
return self
|
78
|
+
end
|
79
|
+
|
80
|
+
def [](k)
|
81
|
+
@values[k.to_sym]
|
82
|
+
end
|
83
|
+
|
84
|
+
def []=(k, v)
|
85
|
+
send(:"#{k}=", v)
|
86
|
+
end
|
87
|
+
|
88
|
+
def keys
|
89
|
+
@values.keys
|
90
|
+
end
|
91
|
+
|
92
|
+
def values
|
93
|
+
@values.values
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_json(*a)
|
97
|
+
JSON.generate(@values)
|
98
|
+
end
|
99
|
+
|
100
|
+
def to_hash
|
101
|
+
@values.inject({}) do |acc, (key, value)|
|
102
|
+
acc[key] = value.respond_to?(:to_hash) ? value.to_hash : value
|
103
|
+
acc
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def each(&blk)
|
108
|
+
@values.each(&blk)
|
109
|
+
end
|
110
|
+
|
111
|
+
def metaclass
|
112
|
+
class << self; self; end
|
113
|
+
end
|
114
|
+
|
115
|
+
def remove_accessors(keys)
|
116
|
+
metaclass.instance_eval do
|
117
|
+
keys.each do |k|
|
118
|
+
next if @@permanent_attributes.include?(k)
|
119
|
+
k_eq = :"#{k}="
|
120
|
+
remove_method(k) if method_defined?(k)
|
121
|
+
remove_method(k_eq) if method_defined?(k_eq)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_accessors(keys)
|
127
|
+
metaclass.instance_eval do
|
128
|
+
keys.each do |k|
|
129
|
+
next if @@permanent_attributes.include?(k)
|
130
|
+
k_eq = :"#{k}="
|
131
|
+
define_method(k) { @values[k] }
|
132
|
+
define_method(k_eq) do |v|
|
133
|
+
if v == ""
|
134
|
+
raise ArgumentError.new(
|
135
|
+
"You cannot set #{k} to an empty string." \
|
136
|
+
"We interpret empty strings as nil in requests." \
|
137
|
+
"You may set #{self}.#{k} = nil to delete the property.")
|
138
|
+
end
|
139
|
+
@values[k] = v
|
140
|
+
@unsaved.add(k)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def method_missing(name, *args)
|
147
|
+
if name.to_s.end_with?('=')
|
148
|
+
attr = name.to_s[0...-1].to_sym
|
149
|
+
add_accessors([attr])
|
150
|
+
begin
|
151
|
+
mth = method(name)
|
152
|
+
rescue NameError
|
153
|
+
raise NoMethodError.new("Cannot set #{attr} on this object. HINT: you can't set: #{@@permanent_attributes.to_a.join(', ')}")
|
154
|
+
end
|
155
|
+
return mth.call(args[0])
|
156
|
+
else
|
157
|
+
return @values[name] if @values.has_key?(name)
|
158
|
+
end
|
159
|
+
|
160
|
+
begin
|
161
|
+
super
|
162
|
+
rescue NoMethodError => e
|
163
|
+
raise e
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
167
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Operations
|
3
|
+
module Create
|
4
|
+
def create(body={})
|
5
|
+
response = @client.request(:post, self.endpoint(), body)
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
Util.convert_to_object(self, response[:body])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
11
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Operations
|
3
|
+
module Delete
|
4
|
+
def delete
|
5
|
+
response = @client.request(:delete, self.endpoint())
|
6
6
|
|
7
|
-
|
7
|
+
if response[:code] == 204
|
8
8
|
refresh_from({:id => @id})
|
9
9
|
elsif response[:code] == 200
|
10
10
|
# update the local values with the response
|
11
11
|
refresh_from(response[:body].dup.merge({:id => self.id}))
|
12
|
-
|
12
|
+
end
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
return response[:code] == 204 || response[:code] == 200
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
18
|
end
|
@@ -1,17 +1,17 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Operations
|
3
|
+
module List
|
4
|
+
def list(opts={})
|
5
|
+
response = @client.request(:get, self.endpoint(), opts)
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# build objects
|
8
|
+
objects = Util.build_objects(self, response[:body])
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
# store the metadata from the list operation
|
11
|
+
metadata = Invoiced::List.new(response[:headers][:link], response[:headers][:x_total_count])
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
return objects, metadata
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
17
|
end
|
@@ -1,27 +1,27 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
module Operations
|
3
|
+
module Update
|
4
|
+
def save(params = {})
|
5
|
+
update = {}
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
@unsaved.each do |k|
|
8
|
+
update[k] = @values[k]
|
9
|
+
end
|
10
10
|
|
11
|
-
|
11
|
+
update.merge(params)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
# perform the update if there are any changes
|
14
|
+
if update.length > 0
|
15
|
+
response = @client.request(:patch, self.endpoint(), update)
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
# update the local values with the response
|
18
|
+
refresh_from(response[:body].dup.merge({:id => self.id}))
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
return response[:code] == 200
|
21
|
+
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
27
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Invoiced
|
2
2
|
class Subscription < Object
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
include Invoiced::Operations::List
|
4
|
+
include Invoiced::Operations::Create
|
5
|
+
include Invoiced::Operations::Update
|
6
|
+
include Invoiced::Operations::Delete
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def cancel
|
9
|
+
delete
|
10
|
+
end
|
11
|
+
end
|
12
12
|
end
|
data/lib/invoiced/transaction.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
module Invoiced
|
2
2
|
class Transaction < Object
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
include Invoiced::Operations::List
|
4
|
+
include Invoiced::Operations::Create
|
5
|
+
include Invoiced::Operations::Update
|
6
|
+
include Invoiced::Operations::Delete
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
def send(opts={})
|
9
|
+
response = @client.request(:post, "#{self.endpoint()}/emails", opts)
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
# build email objects
|
12
|
+
email = Email.new(@client)
|
13
|
+
Util.build_objects(email, response[:body])
|
14
|
+
end
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
def refund(opts={})
|
17
|
+
response = @client.request(:post, "#{self.endpoint()}/refunds", opts)
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
19
|
+
Util.convert_to_object(self, response[:body])
|
20
|
+
end
|
21
|
+
end
|
22
22
|
end
|
data/lib/invoiced/util.rb
CHANGED
@@ -1,60 +1,60 @@
|
|
1
1
|
module Invoiced
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
2
|
+
class Util
|
3
|
+
class << self
|
4
|
+
def auth_header(api_key)
|
5
|
+
"Basic " + Base64.strict_encode64(api_key + ":")
|
6
|
+
end
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
def uri_encode(params)
|
9
|
+
flatten_params(params).
|
10
|
+
map { |k,v| "#{k}=#{url_encode(v)}" }.join('&')
|
11
|
+
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
def build_objects(_class, objects)
|
14
|
+
objects.map {
|
15
|
+
|object| convert_to_object(_class, object)
|
16
|
+
}
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def convert_to_object(_class, values)
|
20
|
+
object = _class.class.new(_class.client, values[:id], values)
|
21
|
+
object.set_endpoint_base(_class.endpoint_base())
|
22
|
+
end
|
23
23
|
|
24
|
-
|
24
|
+
private
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
def url_encode(params)
|
27
|
+
URI.encode_www_form_component(params)
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
30
|
+
def flatten_params(params, parent_key=nil)
|
31
|
+
result = []
|
32
|
+
params.each do |key, value|
|
33
|
+
calculated_key = parent_key ? "#{parent_key}[#{url_encode(key)}]" : url_encode(key)
|
34
|
+
if value.is_a?(Hash)
|
35
|
+
result += flatten_params(value, calculated_key)
|
36
|
+
elsif value.is_a?(Array)
|
37
|
+
result += flatten_params_array(value, calculated_key)
|
38
|
+
else
|
39
|
+
result << [calculated_key, value]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
result
|
43
|
+
end
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
45
|
+
def flatten_params_array(value, calculated_key)
|
46
|
+
result = []
|
47
|
+
value.each do |elem|
|
48
|
+
if elem.is_a?(Hash)
|
49
|
+
result += flatten_params(elem, "#{calculated_key}[]")
|
50
|
+
elsif elem.is_a?(Array)
|
51
|
+
result += flatten_params_array(elem, calculated_key)
|
52
|
+
else
|
53
|
+
result << ["#{calculated_key}[]", elem]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
60
|
end
|
data/lib/invoiced/version.rb
CHANGED