fedex_ship 0.1.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.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.idea/.rakeTasks +7 -0
  4. data/.idea/fedex_ship-0.1.0.iml +22 -0
  5. data/.idea/misc.xml +7 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.idea/workspace.xml +56 -0
  9. data/.rspec +2 -0
  10. data/Gemfile +5 -0
  11. data/Rakefile +7 -0
  12. data/Readme.md +496 -0
  13. data/fedex_ship.gemspec +28 -0
  14. data/lib/fedex_ship.rb +55 -0
  15. data/lib/fedex_ship/address.rb +31 -0
  16. data/lib/fedex_ship/credentials.rb +26 -0
  17. data/lib/fedex_ship/document.rb +51 -0
  18. data/lib/fedex_ship/ground_manifest.rb +25 -0
  19. data/lib/fedex_ship/helpers.rb +20 -0
  20. data/lib/fedex_ship/label.rb +71 -0
  21. data/lib/fedex_ship/rate.rb +38 -0
  22. data/lib/fedex_ship/request/address.rb +97 -0
  23. data/lib/fedex_ship/request/base.rb +443 -0
  24. data/lib/fedex_ship/request/delete.rb +76 -0
  25. data/lib/fedex_ship/request/document.rb +45 -0
  26. data/lib/fedex_ship/request/ground_close.rb +73 -0
  27. data/lib/fedex_ship/request/label.rb +29 -0
  28. data/lib/fedex_ship/request/logs_fedex.rb +74 -0
  29. data/lib/fedex_ship/request/pickup.rb +135 -0
  30. data/lib/fedex_ship/request/pickup_availability.rb +102 -0
  31. data/lib/fedex_ship/request/rate.rb +94 -0
  32. data/lib/fedex_ship/request/service_availability.rb +86 -0
  33. data/lib/fedex_ship/request/shipment.rb +249 -0
  34. data/lib/fedex_ship/request/tracking_information.rb +119 -0
  35. data/lib/fedex_ship/shipment.rb +115 -0
  36. data/lib/fedex_ship/tracking_information.rb +54 -0
  37. data/lib/fedex_ship/tracking_information/event.rb +24 -0
  38. data/lib/fedex_ship/version.rb +6 -0
  39. data/spec/config/fedex_credentials.example.yml +13 -0
  40. data/spec/lib/fedex_ship/address_spec.rb +59 -0
  41. data/spec/lib/fedex_ship/delete_spec.rb +26 -0
  42. data/spec/lib/fedex_ship/document_spec.rb +177 -0
  43. data/spec/lib/fedex_ship/ground_close_spec.rb +42 -0
  44. data/spec/lib/fedex_ship/label_spec.rb +73 -0
  45. data/spec/lib/fedex_ship/pickup_availability_spec.rb +19 -0
  46. data/spec/lib/fedex_ship/pickup_spec.rb +32 -0
  47. data/spec/lib/fedex_ship/rate_spec.rb +216 -0
  48. data/spec/lib/fedex_ship/service_availability_spec.rb +20 -0
  49. data/spec/lib/fedex_ship/shipment_spec.rb +86 -0
  50. data/spec/lib/fedex_ship/track_spec.rb +67 -0
  51. data/spec/spec_helper.rb +12 -0
  52. data/spec/support/credentials.rb +15 -0
  53. data/spec/support/vcr.rb +14 -0
  54. metadata +193 -0
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ module FedexShip
4
+ describe Shipment do
5
+ let (:fedex) { Shipment.new(fedex_credentials) }
6
+
7
+ let(:filename) {
8
+ require 'tmpdir'
9
+ File.join(Dir.tmpdir, "manifest#{rand(15000)}.txt")
10
+ }
11
+
12
+ context "#ground_close" do
13
+ context "with shipment ready for close", :vcr do
14
+ before do
15
+ shipper = { :name => "Sender", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Harrison", :state => "AR", :postal_code => "72601", :country_code => "US" }
16
+ recipient = { :name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Frankin Park", :state => "IL", :postal_code => "60131", :country_code => "US", :residential => true }
17
+ packages = [
18
+ {
19
+ :weight => {:units => "LB", :value => 2},
20
+ :dimensions => {:length => 10, :width => 5, :height => 4, :units => "IN" }
21
+ }
22
+ ]
23
+ # require 'tmpdir'
24
+ # filename = File.join(Dir.tmpdir, "label#{rand(15000)}.pdf")
25
+ options = { :shipper => shipper, :recipient => recipient, :packages => packages, :service_type => "FEDEX_GROUND"}#, :filename => filename }
26
+ fedex.ship(options)
27
+ end
28
+
29
+ it "completes with success result" do
30
+ # When running this spec you may need to uncomment the line below to allow shipment to be created before close request
31
+ #sleep(7)
32
+ expect{ fedex.ground_close(:up_to_time => Time.now, :filename => filename) }.to_not raise_error
33
+ end
34
+ end
35
+ context "raise an error when there aren't any existing shipments to close", :vcr do
36
+ it "raises an error" do
37
+ expect { fedex.ground_close(:up_to_time => Time.now) }.to raise_error(FedexShip::RateError, 'No Shipments to Close')
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+ require 'tmpdir'
3
+ module FedexShip
4
+ describe Label do
5
+ describe "ship service for label" do
6
+ let(:fedex) { Shipment.new(fedex_credentials) }
7
+ let(:shipper) do
8
+ {:name => "Sender", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Harrison", :state => "AR", :postal_code => "72601", :country_code => "US"}
9
+ end
10
+ let(:recipient) do
11
+ {:name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Frankin Park", :state => "IL", :postal_code => "60131", :country_code => "US", :residential => true }
12
+ end
13
+ let(:packages) do
14
+ [
15
+ {
16
+ :weight => {:units => "LB", :value => 2},
17
+ :dimensions => {:length => 10, :width => 5, :height => 4, :units => "IN" }
18
+ }
19
+ ]
20
+ end
21
+ let(:shipping_options) do
22
+ { :packaging_type => "YOUR_PACKAGING", :drop_off_type => "REGULAR_PICKUP" }
23
+ end
24
+
25
+ let(:label_specification) do
26
+ { :label_format_type => 'COMMON2D',
27
+ :image_type => 'PNG',
28
+ }
29
+ end
30
+
31
+ let(:filename) {
32
+ require 'tmpdir'
33
+ File.join(Dir.tmpdir, "label#{rand(15000)}.pdf")
34
+ }
35
+
36
+ let(:options) do
37
+ { :shipper => shipper,
38
+ :recipient => recipient,
39
+ :packages => packages,
40
+ :service_type => "FEDEX_GROUND",
41
+ :label_specification => label_specification,
42
+ :filename => filename
43
+ }
44
+ end
45
+
46
+ describe "label", :vcr do
47
+ before do
48
+ @label = fedex.label(options)
49
+ end
50
+
51
+ it "should create a label" do
52
+ expect(File).to exist(filename)
53
+ end
54
+
55
+ it "should return tracking number" do
56
+ expect(@label).to respond_to('tracking_number')
57
+ end
58
+
59
+ it "should expose complete response" do
60
+ expect(@label).to respond_to('response_details')
61
+ end
62
+ after do
63
+ require 'fileutils'
64
+ FileUtils.rm_r(filename) if File.exist?(filename)
65
+ end
66
+
67
+ it "should expose the file_name" do
68
+ expect(@label).to respond_to('file_name')
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+ require 'fedex_ship/shipment'
3
+
4
+ describe FedexShip::Request::Pickup do
5
+ describe "pickup availability service" do
6
+ let(:fedex) { FedexShip::Shipment.new(fedex_credentials) }
7
+ let(:dispatch_date) {(Date.today + 1).strftime('%Y-%m-%d')}
8
+
9
+ let(:options) do
10
+ {:country_code => 'IN', :postal_code => '400061', :request_type => 'FUTURE_DAY', :dispatch_date => dispatch_date, :carrier_code => 'FDXE'}
11
+ end
12
+
13
+ it "succeeds", :vcr do
14
+ expect {
15
+ @pickup_availability = fedex.pickup_availability(options)
16
+ }.to_not raise_error
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ require 'fedex_ship/shipment'
3
+
4
+ describe FedexShip::Request::Pickup do
5
+ describe "pickup service" do
6
+ let(:fedex) { FedexShip::Shipment.new(fedex_production_credentials) }
7
+ let(:pickup_location) do
8
+ {:name => "Sender", :company => "Company", :phone_number => "555-555-5555 ", :address => "Main Street",
9
+ :city => "Mumbai", :state => "MH", :postal_code => "400012", :country_code => "IN"}
10
+ end
11
+ let(:packages) do
12
+ {:weight => {:units => "LB", :value => 2}, :count => 2}
13
+ end
14
+ let(:ready_timestamp) { DateTime.now + 1 }
15
+ let(:close_time) { DateTime.now + 1.2 }
16
+
17
+ context "alternate address", :vcr do
18
+ let(:options) do
19
+ {:carrier_code => "FDXE", :packages => packages, :ready_timestamp => ready_timestamp,
20
+ :close_time => close_time, :pickup_location => pickup_location, :remarks => 'TEST. DO NOT PICKUP', :commodity_description => 'Ladies Item as per invoice',
21
+ :country_relationship => 'DOMESTIC'
22
+ }
23
+ end
24
+
25
+ it "succeeds" do
26
+ expect {
27
+ @pickup = fedex.pickup(options)
28
+ }.to_not raise_error
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,216 @@
1
+ require 'spec_helper'
2
+
3
+ module FedexShip
4
+ describe Shipment do
5
+ context "missing required parameters" do
6
+ it "should raise Rate exception" do
7
+ expect{ Shipment.new}.to raise_error(RateError)
8
+ end
9
+ end
10
+
11
+ context "required parameters present" do
12
+ subject { Shipment.new(fedex_credentials) }
13
+ it "should create a valid instance" do
14
+ expect(subject).to be_an_instance_of(Shipment)
15
+ end
16
+ end
17
+
18
+ describe "rate service" do
19
+ let(:fedex) { Shipment.new(fedex_credentials) }
20
+ let(:shipper) do
21
+ { :name => "Sender", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Harrison", :state => "AR", :postal_code => "72601", :country_code => "US" }
22
+ end
23
+ let(:recipient) do
24
+ { :name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Frankin Park", :state => "IL", :postal_code => "60131", :country_code => "US", :residential => true }
25
+ end
26
+ let(:packages) do
27
+ [
28
+ {
29
+ :weight => { :units => "LB", :value => 2 },
30
+ :dimensions => { :length => 10, :width => 5, :height => 4, :units => "IN" }
31
+ },
32
+ {
33
+ :weight => { :units => "LB", :value => 6 },
34
+ :dimensions => { :length => 5, :width => 5, :height => 4, :units => "IN" }
35
+ }
36
+ ]
37
+ end
38
+ let(:shipping_options) do
39
+ { :packaging_type => "YOUR_PACKAGING", :drop_off_type => "REGULAR_PICKUP" }
40
+ end
41
+
42
+ context "domestic shipment", :vcr do
43
+ it "should return a rate" do
44
+ rates = fedex.rate({ :shipper => shipper, :recipient => recipient, :packages => packages, :service_type => "FEDEX_GROUND"})
45
+ expect(rates.first).to be_an_instance_of(Rate)
46
+ end
47
+ it "should return a transit time" do
48
+ rates = fedex.rate({ :shipper => shipper, :recipient => recipient, :packages => packages, :service_type => "FEDEX_GROUND"})
49
+ expect(rates.first.transit_time).not_to be_nil
50
+ end
51
+ end
52
+
53
+ context "canadian shipment", :vcr do
54
+ it "should return a rate" do
55
+ canadian_recipient = { :name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address=>"Address Line 1", :city => "Richmond", :state => "BC", :postal_code => "V7C4V4", :country_code => "CA", :residential => "true" }
56
+ rates = fedex.rate({ :shipper => shipper, :recipient => canadian_recipient, :packages => packages, :service_type => "FEDEX_GROUND" })
57
+ expect(rates.first).to be_an_instance_of(Rate)
58
+ end
59
+ end
60
+
61
+ context "canadian shipment including customs", :vcr do
62
+ it "should return a rate including international fees" do
63
+ canadian_recipient = { :name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address=>"Address Line 1", :city => "Richmond", :state => "BC", :postal_code => "V7C4V4", :country_code => "CA", :residential => "true" }
64
+ broker = {
65
+ :account_number => "510087143",
66
+ :tins => { :tin_type => "BUSINESS_NATIONAL",
67
+ :number => "431870271",
68
+ :usage => "Usage" },
69
+ :contact => { :contact_id => "1",
70
+ :person_name => "Broker Name",
71
+ :title => "Broker",
72
+ :company_name => "Broker One",
73
+ :phone_number => "555-555-5555",
74
+ :phone_extension => "555-555-5555",
75
+ :pager_number => "555",
76
+ :fax_number=> "555-555-5555",
77
+ :e_mail_address => "contact@me.com" },
78
+ :address => { :street_lines => "Main Street",
79
+ :city => "Franklin Park",
80
+ :state_or_province_code => 'IL',
81
+ :postal_code => '60131',
82
+ :urbanization_code => '123',
83
+ :country_code => 'US',
84
+ :residential => 'false' }
85
+ }
86
+
87
+ clearance_brokerage = "BROKER_INCLUSIVE"
88
+
89
+ importer_of_record= {
90
+ :account_number => "22222",
91
+ :tins => { :tin_type => "BUSINESS_NATIONAL",
92
+ :number => "22222",
93
+ :usage => "Usage" },
94
+ :contact => { :contact_id => "1",
95
+ :person_name => "Importer Name",
96
+ :title => "Importer",
97
+ :company_name => "Importer One",
98
+ :phone_number => "555-555-5555",
99
+ :phone_extension => "555-555-5555",
100
+ :pager_number => "555",
101
+ :fax_number=> "555-555-5555",
102
+ :e_mail_address => "contact@me.com" },
103
+ :address => { :street_lines => "Main Street",
104
+ :city => "Chicago",
105
+ :state_or_province_code => 'IL',
106
+ :postal_code => '60611',
107
+ :urbanization_code => '2308',
108
+ :country_code => 'US',
109
+ :residential => 'false' }
110
+ }
111
+
112
+ recipient_customs_id = { :type => 'COMPANY',
113
+ :value => '1254587' }
114
+
115
+
116
+ duties_payment = { :payment_type => "SENDER",
117
+ :payor => { :account_number => "510087143",
118
+ :country_code => "US" } }
119
+
120
+ customs_value = { :currency => "USD",
121
+ :amount => "200" }
122
+ commodities = [{
123
+ :name => "Cotton Coat",
124
+ :number_of_pieces => "2",
125
+ :description => "Cotton Coat",
126
+ :country_of_manufacture => "US",
127
+ :harmonized_code => "6103320000",
128
+ :weight => { :units => "LB", :value => "2" },
129
+ :quantity => "3",
130
+ :unit_price => { :currency => "USD", :amount => "50" },
131
+ :customs_value => { :currency => "USD", :amount => "150" }
132
+ },
133
+ {
134
+ :name => "Poster",
135
+ :number_of_pieces => "1",
136
+ :description => "Paper Poster",
137
+ :country_of_manufacture => "US",
138
+ :harmonized_code => "4817100000",
139
+ :weight => { :units => "LB", :value => "0.2" },
140
+ :quantity => "3",
141
+ :unit_price => { :currency => "USD", :amount => "50" },
142
+ :customs_value => { :currency => "USD", :amount => "150" }
143
+ }
144
+ ]
145
+
146
+ customs_clearance = { :broker => broker, :clearance_brokerage => clearance_brokerage, :importer_of_record => importer_of_record, :recipient_customs_id => recipient_customs_id, :duties_payment => duties_payment, :commodities => commodities }
147
+ rates = fedex.rate({ :shipper => shipper, :recipient => canadian_recipient, :packages => packages, :service_type => "FEDEX_GROUND", :customs_clearance => customs_clearance })
148
+ expect(rates.first).to be_an_instance_of(Rate)
149
+ end
150
+ end
151
+
152
+ context "with service type specified", :vcr do
153
+
154
+ let(:rates) {
155
+ fedex.rate({
156
+ :shipper => shipper,
157
+ :recipient => recipient,
158
+ :packages => packages,
159
+ :service_type => "FEDEX_GROUND"
160
+ })
161
+ }
162
+
163
+ it "returns a single rate" do
164
+ expect(rates.count).to eq 1
165
+ end
166
+
167
+ it "has service_type attribute" do
168
+ rates.first.service_type == 'FEDEX_GROUND'
169
+ end
170
+
171
+ end
172
+
173
+ context "with no service type specified", :vcr do
174
+
175
+ let(:rates) {
176
+ fedex.rate({
177
+ :shipper => shipper,
178
+ :recipient => recipient,
179
+ :packages => packages
180
+ })
181
+ }
182
+
183
+ it "returns multiple rates" do
184
+ expect(rates.count).to be >= 1
185
+ end
186
+
187
+ context "each rate" do
188
+
189
+ it 'has service type attribute' do
190
+ expect(rates.first).to respond_to(:service_type)
191
+ end
192
+
193
+ end
194
+
195
+ end
196
+
197
+ context "when there are no valid services available", :vcr do
198
+
199
+ let(:bad_shipper) { shipper.merge(state: 'Anywhere') }
200
+ let(:rates) {
201
+ fedex.rate({
202
+ :shipper => bad_shipper,
203
+ :recipient => recipient,
204
+ :packages => packages
205
+ })
206
+ }
207
+
208
+ it 'returns empty array' do
209
+ expect(rates).to eq []
210
+ end
211
+
212
+ end
213
+
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module FedexShip
4
+ describe 'ServiceAvailability' do
5
+ let(:fedex) { Shipment.new(fedex_credentials) }
6
+ let(:origin) do {:postal_code => '400012', :country_code => 'IN'} end
7
+ let(:destination) do { :postal_code => '400020', :country_code => 'IN'} end
8
+ let(:options) do {:origin => origin, :destination => destination, :ship_date => '2014-06-28', :carrier_code => 'FDXE'} end
9
+
10
+ context 'Check Availability', :vcr do
11
+ it "succeeds" do
12
+ expect {
13
+ @service_availability = fedex.service_availability(options)
14
+ }.to_not raise_error
15
+
16
+ expect(@service_availability.class).not_to eq(FedexShip::RateError)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,86 @@
1
+ require 'spec_helper'
2
+ require 'fedex_ship/shipment'
3
+
4
+ describe FedexShip::Request::Shipment do
5
+ describe "ship service" do
6
+ let(:fedex) { FedexShip::Shipment.new(fedex_credentials) }
7
+ let(:shipper) do
8
+ { :name => "Sender", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Harrison", :state => "AR", :postal_code => "72601", :country_code => "US" }
9
+ end
10
+ let(:recipient) do
11
+ { :name => "Recipient", :company => "Company", :phone_number => "555-555-5555", :address => "Main Street", :city => "Frankin Park", :state => "IL", :postal_code => "60131", :country_code => "US", :residential => true }
12
+ end
13
+ let(:packages) do
14
+ [
15
+ {
16
+ :weight => {:units => "LB", :value => 2},
17
+ :dimensions => {:length => 10, :width => 5, :height => 4, :units => "IN" }
18
+ }
19
+ ]
20
+ end
21
+ let(:shipping_options) do
22
+ { :packaging_type => "YOUR_PACKAGING", :drop_off_type => "REGULAR_PICKUP" }
23
+ end
24
+ let(:payment_options) do
25
+ { :type => "SENDER", :account_number => fedex_credentials[:account_number], :name => "Sender", :company => "Company", :phone_number => "555-555-5555", :country_code => "US" }
26
+ end
27
+
28
+ let(:filename) {
29
+ require 'tmpdir'
30
+ File.join(Dir.tmpdir, "label#{rand(15000)}.pdf")
31
+ }
32
+
33
+ context "domestic shipment", :vcr do
34
+ let(:options) do
35
+ { :shipper => shipper, :recipient => recipient, :packages => packages, :service_type => "FEDEX_GROUND", :filename => filename }
36
+ end
37
+
38
+ it "succeeds" do
39
+ expect {
40
+ @shipment = fedex.ship(options)
41
+ }.to_not raise_error
42
+
43
+ expect(@shipment.class).not_to eq(FedexShip::RateError)
44
+ end
45
+
46
+ it "succeeds with payments_options" do
47
+ expect {
48
+ @shipment = fedex.ship(options.merge(:payment_options => payment_options))
49
+ }.to_not raise_error
50
+
51
+ expect(@shipment.class).not_to eq(FedexShip::RateError)
52
+ end
53
+
54
+ it "should return a transit time" do
55
+ @shipment = fedex.ship(options)
56
+ expect(@shipment[:completed_shipment_detail][:operational_detail][:transit_time]).to eql("TWO_DAYS")
57
+ end
58
+
59
+ end
60
+
61
+ context 'without service_type specified', :vcr do
62
+ let(:options) do
63
+ { :shipper => shipper, :recipient => recipient, :packages => packages, :filename => filename }
64
+ end
65
+
66
+ it 'raises error' do
67
+ expect {
68
+ @shipment = fedex.ship(options)
69
+ }.to raise_error('Missing Required Parameter service_type')
70
+ end
71
+ end
72
+
73
+ context 'with invalid payment_options' do
74
+ let(:options) do
75
+ { :shipper => shipper, :recipient => recipient, :packages => packages, :filename => filename, :payment_options => payment_options.merge(:account_number => nil) }
76
+ end
77
+
78
+ it 'raises error' do
79
+ expect {
80
+ @shipment = fedex.ship(options)
81
+ }.to raise_error('Missing Required Parameter account_number')
82
+ end
83
+ end
84
+
85
+ end
86
+ end