Skip to content

Commit

Permalink
Added USPS International Shipping Rate (IntlRateV2) functionality
Browse files Browse the repository at this point in the history
USPS::Request::InternationalShippingRatesLookup can be used with
USPS::Request::Package::InternationalPackage to calculate international
shipping rates.
Because of the profileration of shipping-rate-related classes, the files
have been reorganized.

Squashed commit of the following:

commit a1cd232
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 11:54:35 2012 -0400

    fixed bug related to required properties in Packages

commit 565f3d3
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 11:01:10 2012 -0400

    updated 'missing package' error messages

commit fac4887
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Tue Sep 18 10:23:34 2012 -0400

    added specs for response

commit f3b92d8
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Mon Sep 17 10:15:23 2012 -0400

    tests for international package request and lookup

commit a9e7769
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Thu Sep 13 15:34:39 2012 -0400

    allow package to be initialized in block, not just with option hash

commit 3901ddd
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Thu Sep 13 15:29:22 2012 -0400

    always include dimension elements, even if they're blank

commit 163e3d1
Author: Nicholas Yianilos <npy@reenhanced.com>
Date:   Wed Sep 12 17:00:01 2012 -0400

    Implemented RateV2 (Int'l) API. Restructured existing Shipping Rate (V2) functionality. Needs better testing
  • Loading branch information
Nicholas Yianilos committed Sep 18, 2012
1 parent 95bdba0 commit 235111b
Show file tree
Hide file tree
Showing 24 changed files with 490 additions and 62 deletions.
3 changes: 0 additions & 3 deletions lib/usps.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ module USPS
autoload :VERSION, 'usps/version' autoload :VERSION, 'usps/version'
autoload :Response, 'usps/response' autoload :Response, 'usps/response'
autoload :TrackDetail, 'usps/track_detail' autoload :TrackDetail, 'usps/track_detail'
autoload :Package, 'usps/package'
autoload :PackageResponse, 'usps/package_response'
autoload :Postage, 'usps/postage'


class << self class << self
attr_writer :config attr_writer :config
Expand Down
18 changes: 0 additions & 18 deletions lib/usps/package.rb

This file was deleted.

14 changes: 0 additions & 14 deletions lib/usps/package_response.rb

This file was deleted.

4 changes: 0 additions & 4 deletions lib/usps/postage.rb

This file was deleted.

14 changes: 8 additions & 6 deletions lib/usps/request.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,15 +1,17 @@
module USPS::Request module USPS::Request
autoload :Base, 'usps/request/base' autoload :Base, 'usps/request/base'
autoload :ZipCodeLookup, 'usps/request/zip_code_lookup' autoload :ZipCodeLookup, 'usps/request/zip_code_lookup'
autoload :CityAndStateLookup, 'usps/request/city_and_state_lookup' autoload :CityAndStateLookup, 'usps/request/city_and_state_lookup'
autoload :AddressStandardization, 'usps/request/address_standardization' autoload :AddressStandardization, 'usps/request/address_standardization'


# Delivery and Signature confirmation. # Delivery and Signature confirmation.
# DeliveryConfirmationCertify and SignatureConfirmationCertify should be used for testing # DeliveryConfirmationCertify and SignatureConfirmationCertify should be used for testing
autoload :DeliveryConfirmation, 'usps/request/delivery_confirmation' autoload :DeliveryConfirmation, 'usps/request/delivery_confirmation'
autoload :DeliveryConfirmationCertify, 'usps/request/delivery_confirmation_certify' autoload :DeliveryConfirmationCertify, 'usps/request/delivery_confirmation_certify'


autoload :TrackingLookup, 'usps/request/tracking_lookup' autoload :TrackingLookup, 'usps/request/tracking_lookup'
autoload :TrackingFieldLookup, 'usps/request/tracking_field_lookup' autoload :TrackingFieldLookup, 'usps/request/tracking_field_lookup'
autoload :ShippingRatesLookup, 'usps/request/shipping_rates_lookup' autoload :ShippingRatesLookup, 'usps/request/shipping_rates_lookup'
autoload :InternationalShippingRatesLookup, 'usps/request/international_shipping_rates_lookup'
autoload :Package, 'usps/request/package'
end end
2 changes: 1 addition & 1 deletion lib/usps/request/base.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def response_for(xml)
end end


def build(&block) def build(&block)
builder = Builder::XmlMarkup.new(:indent => 0) builder = Builder::XmlMarkup.new(:indent => 2)
builder.tag!(self.class.tag, :USERID => USPS.config.username, &block) builder.tag!(self.class.tag, :USERID => USPS.config.username, &block)
end end
end end
Expand Down
42 changes: 42 additions & 0 deletions lib/usps/request/international_shipping_rates_lookup.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,42 @@
module USPS::Request

class InternationalShippingRatesLookup < Base
config(
:api => 'IntlRateV2',
:tag => 'IntlRateV2Request',
:secure => false,
:response => USPS::Response::InternationalShippingRatesLookup
)

def initialize(*packages)
@packages = packages.flatten
if @packages.none?
raise ArgumentError, 'An IntlRateV2 shipping rate lookup requires at least one package (USPS::Request::Package::InternationalPackage)'
end
end

def build
super do |xml|
xml.Revision 2
@packages.each do |package|
xml.Package :ID => package.id do
xml.Pounds package.pounds
xml.Ounces package.ounces
xml.Machinable 'true' # for Service=ALL
xml.MailType package.mail_type
xml.ValueOfContents 103
xml.Country package.country
xml.Container package.container
xml.Size package.size
xml.Width package.width
xml.Length package.length
xml.Height package.height
xml.Girth nil
xml.CommercialFlag 'N'
end
end
end
end

end
end
5 changes: 5 additions & 0 deletions lib/usps/request/package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,5 @@
module USPS::Request::Package
autoload :Base, 'usps/request/package/base'
autoload :DomesticPackage, 'usps/request/package/domestic_package'
autoload :InternationalPackage, 'usps/request/package/international_package'
end
37 changes: 37 additions & 0 deletions lib/usps/request/package/base.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,37 @@
module USPS::Request::Package
class Base
attr_accessor :id
attr_accessor :pounds, :ounces
attr_accessor :container
attr_accessor :size
attr_accessor :width, :length, :height, :girth

@required = [:id, :pounds, :ounces, :size]

def initialize(fields)
fields.each { |name, value| send("#{name}=", value) }

yield self if block_given?

if fields[:size] == 'LARGE'
[:container, :width, :length, :height].each do |field|
error "#{field} is required when Size=LARGE" unless send(field)
end
end

self.class.required_properties.each do |field|
error "#{field} is required" unless send(field)
end
end

protected

def self.required_properties
@required + (defined?(super) ? super : [])
end

def error(message)
raise ArgumentError.new message
end
end
end
18 changes: 18 additions & 0 deletions lib/usps/request/package/domestic_package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,18 @@
module USPS::Request::Package
class DomesticPackage < Base
attr_accessor :service
attr_accessor :first_class_mail_type
attr_accessor :origin_zip, :destination_zip
attr_accessor :value
attr_accessor :amount_to_collect

@required = [:service, :origin_zip, :destination_zip]

def initialize(fields = {})
if fields[:service] == 'FIRST CLASS' and !fields[:first_class_mail_type]
error "first_class_mail_type is required when Service=FIRST Class"
end
super
end
end
end
11 changes: 11 additions & 0 deletions lib/usps/request/package/international_package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,11 @@
module USPS::Request::Package
class InternationalPackage < Base
attr_accessor :country, :mail_type

@required = [:country, :mail_type]

def initialize(fields = {})
super
end
end
end
2 changes: 1 addition & 1 deletion lib/usps/request/shipping_rates_lookup.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class ShippingRatesLookup < Base
def initialize(*packages) def initialize(*packages)
@packages = packages.flatten @packages = packages.flatten
if @packages.none? if @packages.none?
raise ArgumentError, 'A shipping rate lookup requires at least one package (USPS::Package)' raise ArgumentError, 'A RateV4 shipping rate lookup requires at least one package (USPS::Request::Package::DomesticPackage)'
end end
end end


Expand Down
16 changes: 9 additions & 7 deletions lib/usps/response.rb
Original file line number Original file line Diff line number Diff line change
@@ -1,9 +1,11 @@
module USPS::Response module USPS::Response
autoload :Base, 'usps/response/base' autoload :Base, 'usps/response/base'
autoload :CityAndStateLookup, 'usps/response/city_and_state_lookup' autoload :CityAndStateLookup, 'usps/response/city_and_state_lookup'
autoload :DeliveryConfirmation, 'usps/response/delivery_confirmation' autoload :DeliveryConfirmation, 'usps/response/delivery_confirmation'
autoload :AddressStandardization, 'usps/response/address_standardization' autoload :AddressStandardization, 'usps/response/address_standardization'
autoload :TrackingLookup, 'usps/response/tracking_lookup' autoload :TrackingLookup, 'usps/response/tracking_lookup'
autoload :TrackingFieldLookup, 'usps/response/tracking_field_lookup' autoload :TrackingFieldLookup, 'usps/response/tracking_field_lookup'
autoload :ShippingRatesLookup, 'usps/response/shipping_rates_lookup' autoload :ShippingRatesLookup, 'usps/response/shipping_rates_lookup'
autoload :InternationalShippingRatesLookup, 'usps/response/international_shipping_rates_lookup'
autoload :Package, 'usps/response/package'
end end
27 changes: 27 additions & 0 deletions lib/usps/response/international_shipping_rates_lookup.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,27 @@
module USPS::Response
class InternationalShippingRatesLookup < Base
attr_reader :packages

def initialize(xml)
@packages = []
xml.search('Package').each do |package_node|
@packages << Package::InternationalPackage.new do |package|
package.id = package_node.attr('ID')
package.services = package_node.search('Service').map do |postage|
parse_service(postage)
end
end
end
end

private

def parse_service(node)
Package::InternationalPackage::Service.new.tap do |service|
service.id = node.attr('ID')
service.description = node.search('SvcDescription').text
service.rate = node.search('Postage').text
end
end
end
end
4 changes: 4 additions & 0 deletions lib/usps/response/package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,4 @@
module USPS::Response::Package
autoload :DomesticPackage, 'usps/response/package/domestic_package'
autoload :InternationalPackage, 'usps/response/package/international_package'
end
15 changes: 15 additions & 0 deletions lib/usps/response/package/domestic_package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,15 @@
module USPS::Response::Package
class DomesticPackage
class Postage
attr_accessor :rate, :mail_service, :class_id
end

attr_accessor :postages
attr_accessor :id, :origin_zip, :destination_zip, :pounds, :ounces, :container, :size

def initialize(properties = {})
properties.each_pair { |k, v| send("#{k}=", v) }
yield self if block_given?
end
end
end
18 changes: 18 additions & 0 deletions lib/usps/response/package/international_package.rb
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,18 @@
module USPS::Response::Package
class InternationalPackage
class Service
attr_accessor :id, :description, :rate
end

attr_accessor :id
attr_accessor :origin_zip, :destination_zip
attr_accessor :pounds, :ounces, :container, :size

attr_accessor :services

def initialize(properties = {})
properties.each_pair { |k, v| send("#{k}=", v) }
yield self if block_given?
end
end
end
4 changes: 2 additions & 2 deletions lib/usps/response/shipping_rates_lookup.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ShippingRatesLookup < Base
def initialize(xml) def initialize(xml)
@packages = [] @packages = []
xml.search('Package').each do |package_node| xml.search('Package').each do |package_node|
@packages << USPS::PackageResponse.new do |package_response| @packages << Package::DomesticPackage.new do |package_response|
package_response.postages = package_node.search('Postage').map { |postage| parse_postage(postage) } package_response.postages = package_node.search('Postage').map { |postage| parse_postage(postage) }
package_response.id = package_node.attr('ID') package_response.id = package_node.attr('ID')
package_response.pounds = package_node.search('Pounds').text package_response.pounds = package_node.search('Pounds').text
Expand All @@ -21,7 +21,7 @@ def initialize(xml)
private private


def parse_postage(node) def parse_postage(node)
USPS::Postage.new.tap do |postage| Package::DomesticPackage::Postage.new.tap do |postage|
postage.class_id = node.attr('CLASSID') postage.class_id = node.attr('CLASSID')
postage.mail_service = node.search('MailService').text postage.mail_service = node.search('MailService').text
postage.rate = node.search('Rate').text postage.rate = node.search('Rate').text
Expand Down
Loading

0 comments on commit 235111b

Please sign in to comment.