simple_shipping 0.4.6
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 +7 -0
- data/.document +5 -0
- data/.metrics +6 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +43 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +201 -0
- data/LICENSE.txt +21 -0
- data/README.markdown +207 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/coverage/.resultset.json +1579 -0
- data/lib/colorized_text.rb +34 -0
- data/lib/simple_shipping.rb +27 -0
- data/lib/simple_shipping/abstract.rb +11 -0
- data/lib/simple_shipping/abstract/builder.rb +47 -0
- data/lib/simple_shipping/abstract/client.rb +111 -0
- data/lib/simple_shipping/abstract/model.rb +40 -0
- data/lib/simple_shipping/abstract/request.rb +27 -0
- data/lib/simple_shipping/abstract/response.rb +26 -0
- data/lib/simple_shipping/address.rb +22 -0
- data/lib/simple_shipping/contact.rb +24 -0
- data/lib/simple_shipping/demo.rb +9 -0
- data/lib/simple_shipping/demo/base.rb +71 -0
- data/lib/simple_shipping/demo/fedex.rb +46 -0
- data/lib/simple_shipping/demo/ups.rb +68 -0
- data/lib/simple_shipping/exceptions.rb +40 -0
- data/lib/simple_shipping/fedex.rb +14 -0
- data/lib/simple_shipping/fedex/client.rb +41 -0
- data/lib/simple_shipping/fedex/package_builder.rb +24 -0
- data/lib/simple_shipping/fedex/party_builder.rb +50 -0
- data/lib/simple_shipping/fedex/request.rb +54 -0
- data/lib/simple_shipping/fedex/response.rb +5 -0
- data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
- data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
- data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
- data/lib/simple_shipping/package.rb +43 -0
- data/lib/simple_shipping/party.rb +21 -0
- data/lib/simple_shipping/shipment.rb +42 -0
- data/lib/simple_shipping/ups.rb +24 -0
- data/lib/simple_shipping/ups/client.rb +46 -0
- data/lib/simple_shipping/ups/package_builder.rb +101 -0
- data/lib/simple_shipping/ups/party_builder.rb +38 -0
- data/lib/simple_shipping/ups/request.rb +27 -0
- data/lib/simple_shipping/ups/response.rb +63 -0
- data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
- data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
- data/lib/simple_shipping/ups/ship_client.rb +70 -0
- data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
- data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
- data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
- data/lib/simple_shipping/ups/shipment_request.rb +22 -0
- data/lib/simple_shipping/ups/shipment_response.rb +6 -0
- data/lib/simple_shipping/ups/void_client.rb +50 -0
- data/lib/simple_shipping/ups/void_request.rb +42 -0
- data/lib/simple_shipping/ups/void_response.rb +6 -0
- data/lib/tasks/demo.rake +58 -0
- data/script/ups_certification.rb +140 -0
- data/simple_shipping.gemspec +168 -0
- data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
- data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
- data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
- data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
- data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
- data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
- data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
- data/spec/lib/simple_shipping/address_spec.rb +19 -0
- data/spec/lib/simple_shipping/contact_spec.rb +28 -0
- data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
- data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
- data/spec/lib/simple_shipping/package_spec.rb +32 -0
- data/spec/lib/simple_shipping/party_spec.rb +18 -0
- data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
- data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
- data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
- data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
- data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
- data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
- data/spec/requests/fedex_spec.rb +47 -0
- data/spec/requests/ups_spec.rb +75 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/custom_matchers/basic_matcher.rb +13 -0
- data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
- data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
- data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
- data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
- data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
- data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
- data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
- data/tmp/metric_fu/_data/20131210.yml +9964 -0
- data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
- data/wsdl/ups/Ship.wsdl +120 -0
- data/wsdl/ups/Void.wsdl +58 -0
- metadata +308 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# Helper object to send demo requests to FedEx in order to test credentials
|
2
|
+
# and the library.
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# demo = SimpleShipping::Demo::Fedex.new(credentials)
|
6
|
+
# response = demo.shipment_request
|
7
|
+
class SimpleShipping::Demo::Fedex < SimpleShipping::Demo::Base
|
8
|
+
attr_reader :credentials
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@options = options.reverse_merge(:log => false)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Build the package object.
|
15
|
+
#
|
16
|
+
# @return [SimpleShipping::Package]
|
17
|
+
def package
|
18
|
+
@package ||= SimpleShipping::Package.new(
|
19
|
+
:weight => 1,
|
20
|
+
:length => 2,
|
21
|
+
:height => 3,
|
22
|
+
:dimension_units => :in, # you can use :kg as well
|
23
|
+
:weight_units => :lb, # you can use :cm as well
|
24
|
+
:width => 4,
|
25
|
+
:packaging_type => :your
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Initialize the FedEx client.
|
30
|
+
#
|
31
|
+
# @return [SimpleShipping::Fedex::Client]
|
32
|
+
def fedex_client
|
33
|
+
@fedex_client ||= SimpleShipping::Fedex::Client.new(
|
34
|
+
:credentials => options.slice(:key, :password, :account_number, :meter_number),
|
35
|
+
:log => options[:log],
|
36
|
+
:live => options[:live]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Send the shipment request to FedEx.
|
41
|
+
#
|
42
|
+
# @return [SimpleShipping::Fedex::Response]
|
43
|
+
def shipment_request
|
44
|
+
fedex_client.shipment_request(shipper, recipient, package)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Helper object to send demo requests to UPS in order to test credentials
|
2
|
+
# and the library.
|
3
|
+
#
|
4
|
+
# @example
|
5
|
+
# demo = SimpleShipping::Demo::Ups.new(credentials)
|
6
|
+
# response = demo.shipment_request
|
7
|
+
class SimpleShipping::Demo::Ups < SimpleShipping::Demo::Base
|
8
|
+
attr_reader :credentials
|
9
|
+
|
10
|
+
def initialize(options = {})
|
11
|
+
@options = options.reverse_merge(
|
12
|
+
:log => false,
|
13
|
+
:service_type => :second_day_air
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Build the package object.
|
18
|
+
#
|
19
|
+
# @return [SimpleShipping::Package]
|
20
|
+
def package
|
21
|
+
@package ||= SimpleShipping::Package.new(
|
22
|
+
:weight => 0.5,
|
23
|
+
:packaging_type => :envelope
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Initialize the UPS client for shipment requests.
|
28
|
+
#
|
29
|
+
# @return [SimpleShipping::Ups::ShipClient]
|
30
|
+
def ship_client
|
31
|
+
@ship_client ||= SimpleShipping::Ups::ShipClient.new(
|
32
|
+
:credentials => options.slice(:username, :password, :access_license_number),
|
33
|
+
:log => options[:log]
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Initialize the UPS client for void requests.
|
38
|
+
#
|
39
|
+
# @return [SimpleShipping::Ups::VoidClient]
|
40
|
+
def void_client
|
41
|
+
@void_client ||= SimpleShipping::Ups::VoidClient.new(
|
42
|
+
:credentials => options.slice(:username, :password, :access_license_number),
|
43
|
+
:log => options[:log],
|
44
|
+
:live => options[:live]
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Shipment Id. The number is picked randomly.
|
49
|
+
#
|
50
|
+
# @return [String]
|
51
|
+
def shipment_identification_number
|
52
|
+
@shipment_identification_number ||= '1234567890'
|
53
|
+
end
|
54
|
+
|
55
|
+
# Send a shipment request.
|
56
|
+
#
|
57
|
+
# @return [ShipClient::Ups::ShipmentResponse]
|
58
|
+
def shipment_request
|
59
|
+
ship_client.shipment_request(shipper, recipient, package, :service_type => options[:service_type])
|
60
|
+
end
|
61
|
+
|
62
|
+
# Send a request to void a shipment.
|
63
|
+
#
|
64
|
+
# @return [ShipClient::Ups::VoidResponse]
|
65
|
+
def void_request
|
66
|
+
void_client.void_request(shipment_identification_number)
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Parent error for all SimpleShipping errors.
|
3
|
+
class Error < StandardError; end
|
4
|
+
|
5
|
+
# Error raises when response does not contain a label.
|
6
|
+
class NoLabelError < Error ; end
|
7
|
+
|
8
|
+
# Raises when some data is invalid or missing to build a request.
|
9
|
+
class ValidationError < Error
|
10
|
+
# @param model_or_msg [Abstract::Model, String]
|
11
|
+
def initialize(model_or_msg)
|
12
|
+
@message = case model_or_msg
|
13
|
+
when Abstract::Model
|
14
|
+
"Invalid model #{model_or_msg.class}. Validation errors: #{model_or_msg.errors.full_messages.join(', ')}"
|
15
|
+
when String
|
16
|
+
model_or_msg
|
17
|
+
end
|
18
|
+
|
19
|
+
super(@message)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Raised when a remote request fails.
|
24
|
+
class RequestError < Error
|
25
|
+
# @param [Savon::SOAPFault] savon_fault Savon exception
|
26
|
+
def initialize(savon_fault)
|
27
|
+
fault = savon_fault.to_hash[:fault]
|
28
|
+
|
29
|
+
@message =
|
30
|
+
if fault[:faultcode] # SOAP 1.1 fault.
|
31
|
+
detail = fault[:detail][:errors][:error_detail][:primary_error_code]
|
32
|
+
"#{fault[:faultstring]} (#{detail[:code]}) #{detail[:description]}"
|
33
|
+
elsif fault[:code] # SOAP 1.2 fault.
|
34
|
+
"(#{fault[:code][:value]}) #{fault[:reason][:text]}"
|
35
|
+
end
|
36
|
+
|
37
|
+
super(@message)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Namespace for FedEx provider.
|
2
|
+
module SimpleShipping::Fedex
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
|
5
|
+
autoload :Client
|
6
|
+
autoload :Request
|
7
|
+
autoload :Response
|
8
|
+
autoload :ShipmentBuilder
|
9
|
+
autoload :PackageBuilder
|
10
|
+
autoload :PartyBuilder
|
11
|
+
|
12
|
+
autoload :ShipmentRequest
|
13
|
+
autoload :ShipmentResponse
|
14
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# Required credentials:
|
3
|
+
# * _key_
|
4
|
+
# * _password_
|
5
|
+
# * _account_number_
|
6
|
+
# * _meter_number_
|
7
|
+
#
|
8
|
+
# = Usage
|
9
|
+
# client = SimpleShipping::Fedex::Client.new(:key => "KEY",
|
10
|
+
# :password => "PASSWORD",
|
11
|
+
# :account_number => "ACCOUNT NUMBER",
|
12
|
+
# :METER_NUMBER => "METER NUMBER")
|
13
|
+
# client.request(shipper, recipient, package) # => #<SimpleShipping::Fedex::Response ...>
|
14
|
+
class Client < SimpleShipping::Abstract::Client
|
15
|
+
set_required_credentials :key, :password, :account_number, :meter_number
|
16
|
+
|
17
|
+
set_wsdl_document File.join(SimpleShipping::WSDL_DIR, "fedex/ship_service_v10.wsdl")
|
18
|
+
set_testing_address "https://wsbeta.fedex.com:443/web-services/ship"
|
19
|
+
set_production_address "https://wsbeta.fedex.com:443/web-services/ship" # Not configured
|
20
|
+
|
21
|
+
# Send the shipment request to FedEx.
|
22
|
+
def shipment_request(shipper, recipient, package, opts = {})
|
23
|
+
shipment = create_shipment(shipper, recipient, package, opts)
|
24
|
+
request = ShipmentRequest.new(@credentials, shipment)
|
25
|
+
execute(request)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Send the shipment confirmation request.
|
29
|
+
def ship_confirm_request(shipper, recipient, package, opts = {})
|
30
|
+
fail "Not Implemented"
|
31
|
+
end
|
32
|
+
|
33
|
+
# Send the ProcessShipmentRequest request to the FedEx service and return
|
34
|
+
# the response wrapped in a {Fedex::Response} object.
|
35
|
+
def execute(request)
|
36
|
+
savon_response = @client.call(request.type, :message => request.body)
|
37
|
+
request.response(savon_response)
|
38
|
+
end
|
39
|
+
private :execute
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# Knows how to convert {Package} model to SOAP element for FedEx.
|
3
|
+
class PackageBuilder < SimpleShipping::Abstract::Builder
|
4
|
+
# FedEx mapping for weight units.
|
5
|
+
WEIGHT_UNITS = {:kg => 'KG',
|
6
|
+
:lb => 'LB'}
|
7
|
+
# FedEx mapping for dimension units.
|
8
|
+
DIMENSION_UNITS = {:in => 'IN',
|
9
|
+
:cm => 'CM'}
|
10
|
+
|
11
|
+
# Build a SOAP package element as a hash for Savon.
|
12
|
+
def build
|
13
|
+
{ 'Weight' => {'Units' => WEIGHT_UNITS[@model.weight_units],
|
14
|
+
'Value' => @model.weight,
|
15
|
+
:order! => ['Units', 'Value']},
|
16
|
+
'Dimensions' => {'Length' => @model.length,
|
17
|
+
'Width' => @model.width,
|
18
|
+
'Height' => @model.height,
|
19
|
+
'Units' => DIMENSION_UNITS[@model.dimension_units],
|
20
|
+
:order! => ['Length', 'Width', 'Height', 'Units']},
|
21
|
+
:order! => ['Weight', 'Dimensions']}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# Knows how to convert {Party} model to SOAP element for FedEx.
|
3
|
+
class PartyBuilder < SimpleShipping::Abstract::Builder
|
4
|
+
# Build a SOAP party element as a hash for Savon.
|
5
|
+
def build
|
6
|
+
{'Contact' => build_contact,
|
7
|
+
'Address' => build_address,
|
8
|
+
:order! => ['Contact', 'Address']}
|
9
|
+
end
|
10
|
+
|
11
|
+
# Build the body for a Contact element.
|
12
|
+
#
|
13
|
+
# @return [Hash]
|
14
|
+
def build_contact
|
15
|
+
result = {:order! => []}
|
16
|
+
contact = @model.contact
|
17
|
+
if contact.company_name
|
18
|
+
result['CompanyName'] = contact.company_name
|
19
|
+
result[:order!] << 'CompanyName'
|
20
|
+
end
|
21
|
+
if contact.person_name
|
22
|
+
result['PersonName'] = contact.person_name
|
23
|
+
result[:order!] << 'PersonName'
|
24
|
+
end
|
25
|
+
result['PhoneNumber'] = contact.phone_number
|
26
|
+
result[:order!] << 'PhoneNumber'
|
27
|
+
result
|
28
|
+
end
|
29
|
+
private :build_contact
|
30
|
+
|
31
|
+
# Build body for Address element.
|
32
|
+
#
|
33
|
+
# @return [Hash]
|
34
|
+
def build_address
|
35
|
+
addr = @model.address
|
36
|
+
{'StreetLines' => addr.street_line,
|
37
|
+
'City' => addr.city,
|
38
|
+
'StateOrProvinceCode' => addr.state_code,
|
39
|
+
'PostalCode' => addr.postal_code,
|
40
|
+
'CountryCode' => addr.country_code,
|
41
|
+
:order! => [ 'StreetLines',
|
42
|
+
'City',
|
43
|
+
'StateOrProvinceCode',
|
44
|
+
'PostalCode',
|
45
|
+
'CountryCode' ]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
private :build_address
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# Builds a complete request for the FedEx service.
|
3
|
+
class Request < SimpleShipping::Abstract::Request
|
4
|
+
extend ActiveSupport::Autoload
|
5
|
+
|
6
|
+
autoload :ShipmentRequest
|
7
|
+
|
8
|
+
def initialize(credentials, shipment)
|
9
|
+
super(credentials)
|
10
|
+
@shipment = shipment
|
11
|
+
end
|
12
|
+
|
13
|
+
# Build a complete request from a {Shipment shipment} object.
|
14
|
+
def body(opts = {})
|
15
|
+
{'WebAuthenticationDetail' => web_authentication_detail,
|
16
|
+
'ClientDetail' => client_detail,
|
17
|
+
'Version' => version,
|
18
|
+
'RequestedShipment' => ShipmentBuilder.build(@shipment, opts),
|
19
|
+
:order! => ['WebAuthenticationDetail', 'ClientDetail', 'Version', 'RequestedShipment'] }
|
20
|
+
end
|
21
|
+
|
22
|
+
# Build the body for the WebAuthenticationDetail element.
|
23
|
+
#
|
24
|
+
# @return [Hash]
|
25
|
+
def web_authentication_detail
|
26
|
+
{ 'UserCredential' => {'Key' => @credentials.key,
|
27
|
+
'Password' => @credentials.password,
|
28
|
+
:order! => ['Key', 'Password']}}
|
29
|
+
end
|
30
|
+
private :web_authentication_detail
|
31
|
+
|
32
|
+
# Build the body for the UserCredential element.
|
33
|
+
#
|
34
|
+
# @return [Hash]
|
35
|
+
def client_detail
|
36
|
+
{'AccountNumber' => @credentials.account_number,
|
37
|
+
'MeterNumber' => @credentials.meter_number,
|
38
|
+
:order! => ['AccountNumber', 'MeterNumber']}
|
39
|
+
end
|
40
|
+
private :client_detail
|
41
|
+
|
42
|
+
# Build the body for the Version element.
|
43
|
+
#
|
44
|
+
# @return [Hash]
|
45
|
+
def version
|
46
|
+
{'ServiceId' => 'ship',
|
47
|
+
'Major' => '10',
|
48
|
+
'Intermediate' => '0',
|
49
|
+
'Minor' => '0',
|
50
|
+
:order! => ['ServiceId', 'Major', 'Intermediate', 'Minor']}
|
51
|
+
end
|
52
|
+
private :version
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# Builds a shipment element for FedEx SOAP service.
|
3
|
+
class ShipmentBuilder < SimpleShipping::Abstract::Builder
|
4
|
+
# Value for RateRequestTypes XML element.
|
5
|
+
RATE_REQUEST_TYPE = 'ACCOUNT'
|
6
|
+
|
7
|
+
# Number of packages.
|
8
|
+
PACKAGE_COUNT = '1'
|
9
|
+
|
10
|
+
# Mapping for package types
|
11
|
+
PACKAGING_TYPES = {
|
12
|
+
:box_10kg => 'FEDEX_10KG_BOX',
|
13
|
+
:box_25kg => 'FEDEX_25KG_BOX',
|
14
|
+
:box => 'FEDEX_BOX',
|
15
|
+
:envelope => 'FEDEX_ENVELOPE',
|
16
|
+
:pak => 'FEDEX_PAK',
|
17
|
+
:tube => 'FEDEX_TUBE',
|
18
|
+
:your => 'YOUR_PACKAGING'
|
19
|
+
}
|
20
|
+
|
21
|
+
# Mapping for service types
|
22
|
+
SERVICE_TYPES = {
|
23
|
+
:europe_first_international_priority => 'EUROPE_FIRST_INTERNATIONAL_PRIORITY',
|
24
|
+
:fedex_1_day_freight => 'FEDEX_1_DAY_FREIGHT',
|
25
|
+
:fedex_2_day_am => 'FEDEX_2_DAY',
|
26
|
+
:fedex_2_day_freight => 'FEDEX_2_DAY_AM',
|
27
|
+
:fedex_3_day_freight => 'FEDEX_2_DAY_FREIGHT',
|
28
|
+
:fedex_3_day_freight => 'FEDEX_3_DAY_FREIGHT',
|
29
|
+
:fedex_express_saver => 'FEDEX_EXPRESS_SAVER',
|
30
|
+
:fedex_freight_economy => 'FEDEX_FIRST_FREIGHT',
|
31
|
+
:fedex_freight_economy => 'FEDEX_FREIGHT_ECONOMY',
|
32
|
+
:fedex_freight_priority => 'FEDEX_FREIGHT_PRIORITY',
|
33
|
+
:fedex_ground => 'FEDEX_GROUND',
|
34
|
+
:first_overnight => 'FIRST_OVERNIGHT',
|
35
|
+
:ground_home_delivery => 'GROUND_HOME_DELIVERY',
|
36
|
+
:international_economy => 'INTERNATIONAL_ECONOMY',
|
37
|
+
:international_economy_freight => 'INTERNATIONAL_ECONOMY_FREIGHT',
|
38
|
+
:international_first => 'INTERNATIONAL_FIRST',
|
39
|
+
:international_priority => 'INTERNATIONAL_PRIORITY',
|
40
|
+
:international_priority_freight => 'INTERNATIONAL_PRIORITY_FREIGHT',
|
41
|
+
:priority_overnight => 'PRIORITY_OVERNIGHT',
|
42
|
+
:smart_post => 'SMART_POST',
|
43
|
+
:standard_overnight => 'STANDARD_OVERNIGHT'
|
44
|
+
}
|
45
|
+
|
46
|
+
# Mapping for dropoff types.
|
47
|
+
DROPOFF_TYPES = {
|
48
|
+
:business_service_center => 'BUSINESS_SERVICE_CENTER',
|
49
|
+
:drop_box => 'DROP_BOX',
|
50
|
+
:regular_pickup => 'REGULAR_PICKUP',
|
51
|
+
:request_courier => 'REQUEST_COURIER',
|
52
|
+
:station => 'STATION'
|
53
|
+
}
|
54
|
+
|
55
|
+
set_default_opts :dropoff_type => :business_service_center,
|
56
|
+
:service_type => :fedex_ground
|
57
|
+
|
58
|
+
# Build the shipment representation as a hash for the Savon client.
|
59
|
+
def build
|
60
|
+
{'ShipTimestamp' => ship_timestamp,
|
61
|
+
'DropoffType' => DROPOFF_TYPES[@opts[:dropoff_type]],
|
62
|
+
'ServiceType' => SERVICE_TYPES[@opts[:service_type]],
|
63
|
+
'PackagingType' => PACKAGING_TYPES[@model.package.packaging_type],
|
64
|
+
'Shipper' => PartyBuilder.build(@model.shipper),
|
65
|
+
'Recipient' => PartyBuilder.build(@model.recipient),
|
66
|
+
'ShippingChargesPayment' => shipping_charges_payment,
|
67
|
+
'LabelSpecification' => label_specification,
|
68
|
+
'RateRequestTypes' => RATE_REQUEST_TYPE,
|
69
|
+
'PackageCount' => PACKAGE_COUNT,
|
70
|
+
'RequestedPackageLineItems' => PackageBuilder.build(@model.package),
|
71
|
+
:order! => ['ShipTimestamp' , 'DropoffType' , 'ServiceType' , 'PackagingType',
|
72
|
+
'Shipper' , 'Recipient' , 'ShippingChargesPayment', 'LabelSpecification',
|
73
|
+
'RateRequestTypes', 'PackageCount' , 'RequestedPackageLineItems']
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
# Perform validations.
|
78
|
+
def validate
|
79
|
+
validate_inclusion_of(:dropoff_type , DROPOFF_TYPES)
|
80
|
+
validate_inclusion_of(:service_type , SERVICE_TYPES)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Get the shipping timestamps in a specific format.
|
84
|
+
#
|
85
|
+
# @example
|
86
|
+
# ship_timestamp # => "2014-01-08T14:41:53+02:00"
|
87
|
+
#
|
88
|
+
# @return [String]
|
89
|
+
def ship_timestamp
|
90
|
+
Time.new.strftime('%Y-%m-%dT%H:%M:%S%z').tap{|str| str[-2,0] = ':' }
|
91
|
+
end
|
92
|
+
private :ship_timestamp
|
93
|
+
|
94
|
+
# Build the hash for the ShippingChargesPayment element.
|
95
|
+
#
|
96
|
+
# @return [Hash]
|
97
|
+
def shipping_charges_payment
|
98
|
+
{'PaymentType' => payment_type,
|
99
|
+
'Payor' => {'AccountNumber' => @model.payor_account_number},
|
100
|
+
:order! => ['PaymentType', 'Payor']}
|
101
|
+
end
|
102
|
+
private :shipping_charges_payment
|
103
|
+
|
104
|
+
# Get the payment type.
|
105
|
+
#
|
106
|
+
# @return [String]
|
107
|
+
def payment_type
|
108
|
+
(@model.payor == :shipper) ? 'SENDER' : 'RECIPIENT'
|
109
|
+
end
|
110
|
+
private :payment_type
|
111
|
+
|
112
|
+
# Build the label parameters according to FedEx's API.
|
113
|
+
#
|
114
|
+
# @return [Hash]
|
115
|
+
def label_specification
|
116
|
+
{ 'LabelFormatType' => 'COMMON2D',
|
117
|
+
'ImageType' => 'PNG',
|
118
|
+
'LabelStockType' => 'PAPER_4X6',
|
119
|
+
:order! => ['LabelFormatType', 'ImageType', 'LabelStockType'] }
|
120
|
+
end
|
121
|
+
private :label_specification
|
122
|
+
end
|
123
|
+
end
|