rafter-fulfillment 1.0.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.
@@ -0,0 +1,5 @@
1
+ module Fulfillment
2
+ class SearchException < ClientException
3
+
4
+ end
5
+ end
@@ -0,0 +1,100 @@
1
+ module Fulfillment
2
+ class Shipment < ModelBase
3
+
4
+ attr_accessor :client
5
+
6
+ def initialize(client, data)
7
+ @client = client
8
+ make_getter_methods(data)
9
+ end
10
+
11
+ def shipment_items(first_page_num = 1)
12
+ Fulfillment::Shipment.shipment_items(self.client, self.public_id, first_page_num)
13
+ end
14
+
15
+ def add(shipment_items_array)
16
+ Fulfillment::Shipment.add(self.client, self.fulfillment_order['id'], self.public_id, shipment_items_array)
17
+ end
18
+
19
+ def close
20
+ Fulfillment::Shipment.close(self.client, self.fulfillment_order['id'], self.public_id)
21
+ end
22
+
23
+ class << self
24
+
25
+ def add(client, order_public_id, shipment_public_id, shipment_items_array)
26
+ shipment_payload = { "fulfillment_order_items" => shipment_items_array }
27
+ curl = Curl::Easy.http_put(client.build_auth_url("/orders/#{order_public_id}/shipments/#{shipment_public_id}/add"), shipment_payload.to_json) do |curl|
28
+ client.configure_http(curl)
29
+ end
30
+
31
+ raise Fulfillment::ClientException.new("Could not add shipment information about shipment #{shipment_public_id} to order #{order_public_id}:\n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 200
32
+
33
+ new(client, JSON.parse(curl.body_str))
34
+ end
35
+
36
+ def create(client, order_public_id, shipment_hash)
37
+ curl = Curl::Easy.http_post(client.build_auth_url("/orders/#{order_public_id}/shipments"), shipment_hash.to_json) do |curl|
38
+ client.configure_http(curl)
39
+ end
40
+
41
+ raise Fulfillment::CreationException.new("Could not create shipment for order #{order_public_id}:\n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 201
42
+
43
+ new(client, JSON.parse(curl.body_str))
44
+ end
45
+
46
+ def shipment_items(client, shipment_public_id, first_page_num = 1)
47
+ Fulfillment::PagedResult.construct(first_page_num) do |page_num|
48
+ curl = Curl::Easy.http_get(client.build_auth_url("/shipments/#{shipment_public_id}/items")) do |curl|
49
+ client.configure_http(curl)
50
+ client.set_request_page(curl, page_num)
51
+ end
52
+
53
+ raise Fulfillment::ClientException.new("Could not load index of items for shipment #{shipment_public_id}: \n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 200
54
+
55
+ shipment_items_hashes = JSON.parse(curl.body_str)
56
+ result = shipment_items_hashes.map { |sh| Fulfillment::ShipmentItem.new(client, sh) }
57
+
58
+ Fulfillment::PagingEnvelope.envelop(curl, result)
59
+ end
60
+ end
61
+
62
+ def show(client, shipment_public_id)
63
+ curl = Curl::Easy.http_get(client.build_auth_url("/shipments/#{shipment_public_id}")) do |curl|
64
+ client.configure_http(curl)
65
+ end
66
+
67
+ raise Fulfillment::ClientException.new("Could not get shipment #{shipment_public_id}:\n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 200
68
+
69
+ new(client, JSON.parse(curl.body_str))
70
+ end
71
+
72
+ def list(client, first_page_num = 1)
73
+ Fulfillment::PagedResult.construct(first_page_num) do |page_num|
74
+ curl = Curl::Easy.http_get(client.build_auth_url("/shipments")) do |curl|
75
+ client.configure_http(curl)
76
+ client.set_request_page(curl, page_num)
77
+ end
78
+
79
+ raise Fulfillment::ClientException.new("Could not get index of shipments:\n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 200
80
+
81
+ shipment_hashes = JSON.parse(curl.body_str)
82
+ result = shipment_hashes.map { |sh| new(client, sh) }
83
+
84
+ Fulfillment::PagingEnvelope.envelop(curl, result)
85
+ end
86
+ end
87
+
88
+ def close(client, order_public_id, shipment_public_id)
89
+ curl = Curl::Easy.http_put(client.build_auth_url("/orders/#{order_public_id}/shipments/#{shipment_public_id}/close"), {}.to_json) do |curl|
90
+ client.configure_http(curl)
91
+ end
92
+
93
+ raise Fulfillment::ClientException.new("Could not close shipment #{shipment_public_id} for order #{order_public_id}:\n\n Response Body:\n #{curl.body_str}") unless curl.response_code == 200
94
+
95
+ new(client, JSON.parse(curl.body_str))
96
+ end
97
+
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,9 @@
1
+ module Fulfillment
2
+ class ShipmentItem < ModelBase
3
+
4
+ def initialize(client, data)
5
+ @client = client
6
+ make_getter_methods(data)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ module Fulfillment
2
+ VERSION = "1.0.0"
3
+
4
+ API_VERSION = "application/vnd.rafter-fulfillment-v1+json"
5
+ end
@@ -0,0 +1,21 @@
1
+ require 'json'
2
+ require 'curb'
3
+ require 'openssl'
4
+ require 'active_support/core_ext/hash/indifferent_access'
5
+
6
+ %w(
7
+ client
8
+ client_exception
9
+ creation_exception
10
+ model_base
11
+ order
12
+ order_item
13
+ paged_result
14
+ paging_envelope
15
+ search_exception
16
+ shipment
17
+ shipment_item
18
+ version
19
+ ).each do |file|
20
+ require File.join(File.dirname(__FILE__), 'fulfillment', file)
21
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'fulfillment/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rafter-fulfillment"
8
+ spec.version = Fulfillment::VERSION
9
+ spec.authors = ["Michael Pearce", "Paolo Resmini", "Dudley Chamberlin", "Peter Myers", "Nick Zalabak", "Mike 'sealabcore' Taylor"]
10
+ spec.email = ["exchange-engineers@rafter.com"]
11
+ spec.homepage = "https://github.com/bkr/rafter-fulfillment"
12
+ spec.summary = "Client for the Rafter Fulfillment API"
13
+ spec.license = "Apache 2.0"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec", ["~> 2.11.0"]
23
+ spec.add_development_dependency "pry"
24
+ spec.add_development_dependency "faker"
25
+
26
+ spec.add_runtime_dependency "curb"
27
+ spec.add_runtime_dependency "json"
28
+ spec.add_runtime_dependency "activesupport"
29
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fulfillment::Client do
4
+ before :each do
5
+ @client = Fulfillment::Client.new(:host => "fulfillment-test.rafter.com", :api_key => "xyz123abc")
6
+ end
7
+
8
+ it 'makes the host and api_key a readable attribute' do
9
+ @client.host.should eq "fulfillment-test.rafter.com"
10
+ @client.api_key.should eq "xyz123abc"
11
+ end
12
+
13
+ it 'returns the base URI' do
14
+ @client.base_uri.should eq "https://fulfillment-test.rafter.com"
15
+ end
16
+
17
+ it 'raises an ArgumentError if the host argument is missing' do
18
+ lambda { Fulfillment::Client.new(:api_key => "xyz123abc") }.should raise_error(ArgumentError, ":host is a required argument")
19
+ end
20
+
21
+ it 'raises an ArgumentError if the api_key argument is missing' do
22
+ lambda { Fulfillment::Client.new(:host => "exchange-test.rafter.com") }.should raise_error(ArgumentError, ":api_key is a required argument")
23
+ end
24
+
25
+ it 'raises a TimeoutError if the timeout is exceeded' do
26
+ lambda {
27
+ @client = Fulfillment::Client.new(:host => '10.201.202.203', :api_key => @client.api_key, :timeout => 1)
28
+ Fulfillment::Order.show(@client, 'TEST42')
29
+ }.should raise_error(Curl::Err::TimeoutError)
30
+ end
31
+
32
+ describe ".build_auth_url" do
33
+ it 'builds correct auth url with api_key' do
34
+ @client.build_auth_url("/bin").should eq "https://fulfillment-test.rafter.com/bin"
35
+ end
36
+ end
37
+
38
+ describe ".set_request_page" do
39
+ it 'adds page parameter to url' do
40
+ curl = Curl::Easy.new(@client.build_auth_url("/base_url"))
41
+ @client.set_request_page(curl, 12).should eq "https://fulfillment-test.rafter.com/base_url?page=12"
42
+ curl.url.should eq "https://fulfillment-test.rafter.com/base_url?page=12"
43
+ end
44
+ end
45
+
46
+ describe ".add_query_parameter" do
47
+ it 'adds query parameter to url when no parameters existed' do
48
+ curl = Curl::Easy.new("https://fulfillment-test.rafter.com/base_url")
49
+ @client.add_query_parameter(curl, "dummy_key", "dummy_value").should eq "https://fulfillment-test.rafter.com/base_url?dummy_key=dummy_value"
50
+ curl.url.should eq "https://fulfillment-test.rafter.com/base_url?dummy_key=dummy_value"
51
+ end
52
+
53
+ it 'adds query parameter to url when parameters existed' do
54
+ curl = Curl::Easy.new(@client.build_auth_url("/base_url"))
55
+ @client.add_query_parameter(curl, "dummy_key", "dummy_value").should eq "https://fulfillment-test.rafter.com/base_url?dummy_key=dummy_value"
56
+ curl.url.should eq "https://fulfillment-test.rafter.com/base_url?dummy_key=dummy_value"
57
+ end
58
+
59
+ it 'escapes unfriendly characters' do
60
+ client = Fulfillment::Client.new(:host => "fulfillment-test.rafter.com", :api_key => "xyz123abc")
61
+ curl = Curl::Easy.new(client.build_auth_url("/base_url"))
62
+ client.add_query_parameter(curl, "dummy key", "dummy value").should eq "https://fulfillment-test.rafter.com/base_url?dummy+key=dummy+value"
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,207 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fulfillment::OrderItem do
4
+ before :each do
5
+ @client = Fulfillment::Client.new(:api_key => '12345', :host => 'localhost:3000', :scheme => 'http')
6
+
7
+ @order_public_id = 'FO-gobbledeg0123456'
8
+ end
9
+
10
+ describe ".list" do
11
+ before :each do
12
+ @response_json = <<-END
13
+ [
14
+ {
15
+ "public_id":"FOI0d9932",
16
+ "created_at":"2012-12-07T00:07:43-08:00",
17
+ "updated_at":"2012-12-07T00:09:20-08:00",
18
+ "fulfillable_id":3493,
19
+ "fulfillable_type":"BookInstance",
20
+ "rejected":false,
21
+ "rejected_code":null,
22
+ "quantity_accepted":2,
23
+ "quantity_rejected":3,
24
+ "fulfillment_shipments":[{
25
+ "public_id":"FSee4e3d829a183c21",
26
+ "location":"/shipments/FSee4e3d829a183c21"
27
+ }]
28
+ },
29
+ {
30
+ "public_id":"FOIc2da7f",
31
+ "created_at":"2012-12-07T00:07:43-08:00",
32
+ "updated_at":"2012-12-07T00:09:20-08:00",
33
+ "fulfillable_id":4611,
34
+ "fulfillable_type":"BookInstance",
35
+ "rejected":false,
36
+ "rejected_code":null,
37
+ "quantity_accepted":2,
38
+ "quantity_rejected":3,
39
+ "fulfillment_shipments":[{
40
+ "public_id":"FSee4e3d829a183c21",
41
+ "location":"/shipments/FSee4e3d829a183c21"
42
+ }]
43
+ }
44
+ ]
45
+ END
46
+ @curl = double( 'curl', :response_code => 200,
47
+ :body_str => @response_json,
48
+ :header_str => "HTTP/1.1 200 OK\r\nX-API-PAGINATION: {\"per_page\":100,\"total_pages\":1}")
49
+ end
50
+
51
+ it 'should return a list of order items' do
52
+ Curl::Easy.should_receive(:http_get).with("http://localhost:3000/orders/#{@order_public_id}/items").and_return(@curl)
53
+ order_items = Fulfillment::OrderItem.list(@client, @order_public_id)
54
+ order_items.should be_a Fulfillment::PagedResult
55
+ results = order_items.results
56
+ results.size.should eq 2
57
+ results.first.should be_a Fulfillment::OrderItem
58
+ end
59
+ end
60
+
61
+ describe ".show" do
62
+ before :each do
63
+ @order_item_public_id = "FOI1234567890"
64
+ @response_json = <<-END
65
+ {
66
+ "public_id":"#{@order_item_public_id}",
67
+ "created_at":"2012-12-07T00:07:43-08:00",
68
+ "updated_at":"2012-12-07T00:09:20-08:00",
69
+ "fulfillable_id":3493,
70
+ "fulfillable_type":"BookInstance",
71
+ "rejected":false,
72
+ "rejected_code":null,
73
+ "quantity_accepted":2,
74
+ "quantity_rejected":3,
75
+ "fulfillment_shipments":[{
76
+ "public_id":"FSee4e3d829a183c21",
77
+ "location":"/shipments/FSee4e3d829a183c21"
78
+ }]
79
+ }
80
+ END
81
+
82
+ @curl = double( 'curl', :response_code => 200,
83
+ :body_str => @response_json)
84
+ end
85
+
86
+ it 'should return an individual order item' do
87
+ Curl::Easy.should_receive(:http_get).with("http://localhost:3000/orders/#{@order_public_id}/items/#{@order_item_public_id}").and_return(@curl)
88
+ order_item_result = Fulfillment::OrderItem.show(@client, @order_public_id, @order_item_public_id)
89
+ order_item_result.should be_a Fulfillment::OrderItem
90
+ order_item_result.public_id.should eq @order_item_public_id
91
+ end
92
+ end
93
+
94
+ describe ".acknowledge" do
95
+ context "with valid keys" do
96
+ before :each do
97
+ @order_item_id = 'FOI517513'
98
+ @response_json = <<-END
99
+ {
100
+ "public_id":"#{@order_item_id}",
101
+ "created_at":"2012-12-05T16:28:23-08:00",
102
+ "updated_at":"2012-12-05T16:28:23-08:00",
103
+ "fulfillable_id":3493,
104
+ "fulfillable_type":"BookInstance",
105
+ "rejected":false,
106
+ "rejected_code":null,
107
+ "quantity_accepted":2,
108
+ "quantity_rejected":3,
109
+ "fulfillment_shipments":[]
110
+ }
111
+ END
112
+
113
+ @curl = double( 'curl', :response_code => response_code,
114
+ :body_str => @response_json,
115
+ :header_str => "HTTP/1.1 200 OK\r\nX-API-PAGINATION: {\"per_page\":100,\"total_pages\":1}")
116
+ end
117
+
118
+ context "returns 500" do
119
+ let(:response_code) { 500 }
120
+
121
+ it 'should raise error' do
122
+ Curl::Easy.should_receive(:http_put).with("http://localhost:3000/orders/#{@order_public_id}/items/#{@order_item_id}/acknowledge", {"quantity_accepted" => 2, "quantity_rejected" => 1}.to_json).and_return(@curl)
123
+ expect{Fulfillment::OrderItem.acknowledge(@client, @order_public_id, @order_item_id, {"quantity_accepted" => 2, "quantity_rejected" => 1})}.to raise_error(Fulfillment::CreationException)
124
+ end
125
+ end
126
+
127
+ context "returns 200" do
128
+ let(:response_code) { 200 }
129
+
130
+ it 'should return the order item with acknowledgements' do
131
+ Curl::Easy.should_receive(:http_put).with("http://localhost:3000/orders/#{@order_public_id}/items/#{@order_item_id}/acknowledge", {"quantity_accepted" => 2, "quantity_rejected" => 1}.to_json).and_return(@curl)
132
+ order_item = Fulfillment::OrderItem.acknowledge(@client, @order_public_id, @order_item_id, {"quantity_accepted" => 2, "quantity_rejected" => 1})
133
+ order_item.quantity_accepted.should eq 2
134
+ order_item.quantity_rejected.should eq 3
135
+ end
136
+ end
137
+ end
138
+
139
+ context "without valid keys" do
140
+ it 'should return the order item with acknowledgements' do
141
+ Curl::Easy.should_receive(:http_put).never
142
+ expect {Fulfillment::OrderItem.acknowledge(@client, @order_public_id, @order_item_id, {"quantity_accepted" => 2})}.to raise_error(ArgumentError)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe ".reject" do
148
+ before :each do
149
+ @order_item_id = 'FOI517513'
150
+ @response_json = <<-END
151
+ {
152
+ "public_id":"#{@order_item_id}",
153
+ "created_at":"2012-12-05T16:28:23-08:00",
154
+ "updated_at":"2012-12-05T16:28:23-08:00",
155
+ "fulfillable_id":2777,
156
+ "fulfillable_type":"BookInstance",
157
+ "status":"rejected",
158
+ "rejected_code":2,
159
+ "quantity_accepted":2,
160
+ "quantity_rejected":3,
161
+ "fulfillment_shipments":[]
162
+ }
163
+ END
164
+
165
+ @curl = double( 'curl', :response_code => 200,
166
+ :body_str => @response_json,
167
+ :header_str => "HTTP/1.1 200 OK\r\nX-API-PAGINATION: {\"per_page\":100,\"total_pages\":1}")
168
+ end
169
+
170
+ it 'should return the order item with a rejected status' do
171
+ Curl::Easy.should_receive(:http_put).with("http://localhost:3000/orders/#{@order_public_id}/items/#{@order_item_id}/reject", {'rejected_code' => 2}.to_json).and_return(@curl)
172
+ order_item = Fulfillment::OrderItem.reject(@client, @order_public_id, @order_item_id, 2)
173
+ order_item.status.should eq 'rejected'
174
+ order_item.rejected_code.should eq 2
175
+ end
176
+ end
177
+
178
+ describe ".process" do
179
+ before :each do
180
+ @order_item_id = 'FOI517513'
181
+ @response_json = <<-END
182
+ {
183
+ "public_id":"#{@order_item_id}",
184
+ "created_at":"2012-12-05T16:28:23-08:00",
185
+ "updated_at":"2012-12-05T16:28:23-08:00",
186
+ "fulfillable_id":2777,
187
+ "fulfillable_type":"BookInstance",
188
+ "status":"processing",
189
+ "quantity_accepted":2,
190
+ "quantity_rejected":3,
191
+ "fulfillment_shipments":[]
192
+ }
193
+ END
194
+
195
+ @curl = double( 'curl', :response_code => 200,
196
+ :body_str => @response_json,
197
+ :header_str => "HTTP/1.1 200 OK\r\nX-API-PAGINATION: {\"per_page\":100,\"total_pages\":1}")
198
+ end
199
+
200
+ it 'should return the order item with a processing status' do
201
+ Curl::Easy.should_receive(:http_put).with("http://localhost:3000/orders/#{@order_public_id}/items/#{@order_item_id}/process", {}).and_return(@curl)
202
+ order_item = Fulfillment::OrderItem.process(@client, @order_public_id, @order_item_id)
203
+ order_item.status.should eq 'processing'
204
+ end
205
+ end
206
+
207
+ end