rafter-fulfillment 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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