Skip to content
Browse files

Added CanadaPost as a Carrier

  • Loading branch information...
1 parent 86c03ff commit 25dd829772f592aeded6ac6d7a296eef2fa4c35c William Lang committed with jamesmacaulay Aug 4, 2010
View
3 lib/active_shipping/shipping/carriers.rb
@@ -4,13 +4,14 @@
require 'active_shipping/shipping/carriers/fedex'
require 'active_shipping/shipping/carriers/shipwire'
require 'active_shipping/shipping/carriers/kunaki'
+require 'active_shipping/shipping/carriers/canada_post'
module ActiveMerchant
module Shipping
module Carriers
class <<self
def all
- [BogusCarrier, UPS, USPS, FedEx, Shipwire, Kunaki]
+ [BogusCarrier, UPS, USPS, FedEx, Shipwire, Kunaki, CanadaPost]
end
end
end
View
254 lib/active_shipping/shipping/carriers/canada_post.rb
@@ -0,0 +1,254 @@
+require 'cgi'
+
+module ActiveMerchant
+ module Shipping
+
+ class CanadaPost < Carrier
+
+ # NOTE!
+ # A Merchant CPC Id must be assigned to you by Canada Post
+ # CPC_DEMO_XML is just a public domain account for testing
+
+ class CanadaPostRateResponse < RateResponse
+
+ attr_reader :boxes, :postal_outlets
+
+ def initialize(success, message, params = {}, options = {})
+ @boxes = options[:boxes]
+ @postal_outlets = options[:postal_outlets]
+ super
+ end
+
+ end
+
+ cattr_reader :name, :name_french
+ @@name = "Canada Post"
+ @@name_french = "Postes Canada"
+
+ Box = Struct.new(:name, :weight, :expediter_weight, :length, :width, :height, :packedItems)
+ PackedItem = Struct.new(:quantity, :description)
+ PostalOutlet = Struct.new(:sequence_no, :distance, :name, :business_name, :postal_address, :business_hours)
+
+ DEFAULT_TURN_AROUND_TIME = 24
+ URL = "http://sellonline.canadapost.ca:30000"
+ DOCTYPE = '<!DOCTYPE eparcel SYSTEM "http://sellonline.canadapost.ca/DevelopersResources/protocolV3/eParcel.dtd">'
+
+ RESPONSE_CODES = {
+ '1' => "All calculation was done",
+ '2' => "Default shipping rates are returned due to a problem during the processing of the request.",
+ '-2' => "Missing argument when calling module",
+ '-5' => "No Item to ship",
+ '-6' => "Illegal Item weight",
+ '-7' => "Illegal item dimension",
+ '-12' => "Can't open IM config file",
+ '-13' => "Can't create log files",
+ '-15' => "Invalid config file format",
+ '-102' => "Invalid socket connection",
+ '-106' => "Can't connect to server",
+ '-1000' => "Unknow request type sent by client",
+ '-1002' => "MAS Timed out",
+ '-1004' => "Socket communication break",
+ '-1005' => "Did not receive required data on socket.",
+ '-2000' => "Unable to estabish socket connection with RSSS",
+ '-2001' => "Merchant Id not found on server",
+ '-2002' => "One or more parameter was not sent by the IM to the MAS",
+ '-2003' => "Did not receive required data on socket.",
+ '-2004' => "The request contains to many items to process it.",
+ '-2005' => "The request received on socket is larger than the maximum allowed.",
+ '-3000' => "Origin Postal Code is illegal",
+ '-3001' => "Destination Postal Code/State Name/ Country is illegal",
+ '-3002' => "Parcel too large to be shipped with CPC",
+ '-3003' => "Parcel too small to be shipped with CPC",
+ '-3004' => "Parcel too heavy to be shipped with CPC",
+ '-3005' => "Internal error code returned by the rating DLL",
+ '-3006' => "The pick up time format is invalid or not defined.",
+ '-4000' => "Volumetric internal error",
+ '-4001' => "Volumetric time out calculation error.",
+ '-4002' => "No bins provided to the volumetric engine.",
+ '-4003' => "No items provided to the volumetric engine.",
+ '-4004' => "Item is too large to be packed",
+ '-4005' => "Number of item more than maximum allowed",
+ '-5000' => "XML Parsing error",
+ '-5001' => "XML Tag not found",
+ '-5002' => "Node Value Number format error",
+ '-5003' => "Node value is empty",
+ '-5004' => "Unable to create/parse XML Document",
+ '-6000' => "Unable to open the database",
+ '-6001' => "Unable to read from the database",
+ '-6002' => "Unable to write to the database",
+ '-50000' => "Internal problem - Please contact Sell Online Help Desk"
+ }
+
+ def requirements
+ [:login]
+ end
+
+ def find_rates(origin, destination, line_items = [], options = {})
+ rate_request = build_rate_request(origin, destination, line_items, options)
+ commit(rate_request, origin, destination, options)
+ end
+
+ def maximum_weight
+ Mass.new(30, :kilograms)
+ end
+
+ def self.default_location
+ {
+ :country => 'CA',
+ :province => 'ON',
+ :city => 'Ottawa',
+ :address1 => '61A York St',
+ :postal_code => 'K1N5T2'
+ }
+ end
+
+ protected
+
+ def commit(request, origin, destination, options = {})
+ response = parse_rate_response(ssl_post(URL, request), origin, destination, options)
+ end
+
+ private
+
+ def build_rate_request(origin, destination, line_items = [], options = {})
+ line_items = [line_items] if !line_items.is_a?(Array)
+ origin = origin.is_a?(Location) ? origin : Location.new(origin)
+ destination = destination.is_a?(Location) ? destination : Location.new(destination)
+
+ xml_request = XmlNode.new('eparcel') do |root_node|
+ root_node << XmlNode.new('language', @options[:french] ? 'fr' : 'en')
+ root_node << XmlNode.new('ratesAndServicesRequest') do |request|
+
+ request << XmlNode.new('merchantCPCID', @options[:login])
+ request << XmlNode.new('fromPostalCode', origin.postal_code)
+ request << XmlNode.new('turnAroundTime', options[:turn_around_time] ? options[:turn_around_time] : DEFAULT_TURN_AROUND_TIME)
+ request << XmlNode.new('itemsPrice', line_items.sum(&:value))
+
+ #line items
+ request << build_line_items(line_items)
+
+ #delivery info
+ #NOTE: These tags MUST be after line items
+ request << XmlNode.new('city', destination.city)
+ request << XmlNode.new('provOrState', destination.province)
+ request << XmlNode.new('country', destination.country)
+ request << XmlNode.new('postalCode', destination.postal_code)
+ end
+ end
+
+ DOCTYPE + xml_request.to_s
+ end
+
+ def parse_rate_response(response, origin, destination, options = {})
+ xml = REXML::Document.new(response)
+ success = response_success?(xml)
+ message = response_message(xml)
+
+ rate_estimates = []
+ boxes = []
+ if success
+ xml.elements.each('eparcel/ratesAndServicesResponse/product') do |product|
+ service_name = (@options[:french] ? @@name_french : @@name) + product.get_text('name').to_s
+ service_code = product.attribute('id').to_s
+ delivery_date = date_for(product.get_text('deliveryDate').to_s)
+
+ rate_estimates << RateEstimate.new(origin, destination, @@name, service_name,
+ :service_code => service_code,
+ :total_price => product.get_text('rate').to_s,
+ :delivery_date => delivery_date,
+ :currency => 'CAD'
+ )
+ end
+
+ boxes = xml.elements.collect('eparcel/ratesAndServicesResponse/packing/box') do |box|
+ b = Box.new
+ b.packedItems = []
+ b.name = box.get_text('name').to_s
+ b.weight = box.get_text('weight').to_s.to_f
+ b.expediter_weight = box.get_text('expediterWeight').to_s.to_f
+ b.length = box.get_text('length').to_s.to_f
+ b.width = box.get_text('width').to_s.to_f
+ b.height = box.get_text('height').to_s.to_f
+ b.packedItems = box.elements.collect('packedItem') do |item|
+ p = PackedItem.new
+ p.quantity = item.get_text('quantity').to_s.to_i
+ p.description = item.get_text('description').to_s
+ p
+ end
+ b
+ end
+
+ postal_outlets = xml.elements.collect('eparcel/ratesAndServicesResponse/nearestPostalOutlet') do |outlet|
+ postal_outlet = PostalOutlet.new
+ postal_outlet.sequence_no = outlet.get_text('postalOutletSequenceNo').to_s
+ postal_outlet.distance = outlet.get_text('distance').to_s
+ postal_outlet.name = outlet.get_text('outletName').to_s
+ postal_outlet.business_name = outlet.get_text('businessName').to_s
+
+ postal_outlet.postal_address = Location.new({
+ :address1 => outlet.get_text('postalAddress/addressLine').to_s,
+ :postal_code => outlet.get_text('postalAddress/postal_code').to_s,
+ :city => outlet.get_text('postalAddress/municipality').to_s,
+ :province => outlet.get_text('postalAddress/province').to_s,
+ :country => 'Canada',
+ :phone_number => outlet.get_text('phoneNumber').to_s
+ })
+
+ postal_outlet.business_hours = outlet.elements.collect('businessHours') do |hour|
+ { :day_of_week => hour.get_text('dayOfWeek').to_s, :time => hour.get_text('time').to_s }
+ end
+
+ postal_outlet
+ end
+ end
+
+ CanadaPostRateResponse.new(success, message, Hash.from_xml(response), :rates => rate_estimates, :xml => response, :boxes => boxes, :postal_outlets => postal_outlets)
+ end
+
+ def date_for(string)
+ return if !string
+ return Time.parse(string)
+ end
+
+ def response_success?(xml)
+ value = xml.get_text('eparcel/ratesAndServicesResponse/statusCode').to_s
+ value == '1' || value == '2'
+ end
+
+ def response_message(xml)
+ xml.get_text('eparcel/ratesAndServicesResponse/statusMessage').to_s
+ end
+
+ # <!-- List of items in the shopping -->
+ # <!-- cart -->
+ # <!-- Each item is defined by : -->
+ # <!-- - quantity (mandatory) -->
+ # <!-- - size (mandatory) -->
+ # <!-- - weight (mandatory) -->
+ # <!-- - description (mandatory) -->
+ # <!-- - ready to ship (optional) -->
+
+ def build_line_items(line_items)
+ xml_line_items = XmlNode.new('lineItems') do |line_items_node|
+
+ line_items.each do |line_item|
+
+ line_items_node << XmlNode.new('item') do |item|
+ item << XmlNode.new('quantity', 1)
+ item << XmlNode.new('weight', line_item.kilograms)
+ item << XmlNode.new('length', line_item.cm(:length).to_s)
+ item << XmlNode.new('width', line_item.cm(:width).to_s)
+ item << XmlNode.new('height', line_item.cm(:height).to_s)
+ item << XmlNode.new('description', line_item.options[:description] || ' ')
+ item << XmlNode.new('readyToShip', line_item.options[:ready_to_ship] || nil)
+
+ # By setting the 'readyToShip' tag to true, Sell Online will not pack this item in the boxes defined in the merchant profile.
+ end
+ end
+ end
+
+ xml_line_items
+ end
+ end
+ end
+end
View
111 lib/certs/eParcel.dtd
@@ -0,0 +1,111 @@
+<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
+<!ELEMENT eparcel (language?,
+ ( ratesAndServicesRequest |
+ ratesAndServicesResponse |
+ error
+ )+)>
+
+<!ELEMENT language (#PCDATA)>
+<!ELEMENT comment (#PCDATA)>
+
+
+<!-- Standard request to ask for rates and services -->
+<!ELEMENT ratesAndServicesRequest ( merchantCPCID,
+ fromPostalCode?,
+ turnAroundTime?,
+ itemsPrice?,
+ lineItems,
+ city?,
+ provOrState,
+ country,
+ postalCode)>
+ <!ELEMENT merchantID (#PCDATA)>
+ <!ELEMENT fromPostalCode (#PCDATA)>
+ <!ELEMENT turnAroundTime (#PCDATA)>
+ <!ELEMENT itemsPrice (#PCDATA)>
+ <!ELEMENT merchantCPCID (#PCDATA)>
+ <!ELEMENT lineItems (item)+>
+ <!ELEMENT item (quantity, weight, length, width, height, description, imageURL?, readyToShip)>
+ <!ELEMENT quantity (#PCDATA)>
+ <!ELEMENT weight (#PCDATA)>
+ <!ELEMENT length (#PCDATA)>
+ <!ELEMENT width (#PCDATA)>
+ <!ELEMENT height (#PCDATA)>
+ <!ELEMENT description (#PCDATA)>
+ <!ELEMENT imageURL (#PCDATA)>
+ <!ELEMENT readyToShip (#PCDATA)>
+ <!ELEMENT city (#PCDATA)>
+ <!ELEMENT provOrState (#PCDATA)>
+ <!ELEMENT country (#PCDATA)>
+ <!ELEMENT postalCode (#PCDATA)>
+
+<!-- Standard response for request for rates and services -->
+<!ELEMENT ratesAndServicesResponse (statusCode,
+ statusMessage+,
+ requestID,
+ handling,
+ language,
+ product+,
+ packing*,
+ emptySpace*,
+ shippingOptions,
+ comment,
+ nearestPostalOutlet*)>
+
+ <!ELEMENT statusCode (#PCDATA)>
+ <!ELEMENT statusMessage (#PCDATA)>
+ <!ELEMENT requestID (#PCDATA)>
+ <!ELEMENT handling (#PCDATA)>
+
+ <!ELEMENT product (name, rate, shippingDate, deliveryDate, deliveryDayOfWeek, nextDayAM?, packingID)>
+ <!ATTLIST product id CDATA #REQUIRED>
+ <!ATTLIST product sequence CDATA #REQUIRED>
+ <!ELEMENT name (#PCDATA)>
+ <!ELEMENT rate (#PCDATA)>
+ <!ELEMENT shippingDate (#PCDATA)>
+ <!ELEMENT deliveryDate (#PCDATA)>
+ <!ELEMENT deliveryDayOfWeek (#PCDATA)>
+ <!ELEMENT nextDayAM (#PCDATA)>
+ <!ELEMENT packingID (#PCDATA)>
+
+ <!ELEMENT packing (packingID, box+)>
+ <!ELEMENT box (name, weight, expediterWeight, length, width, height, packedItem+)>
+ <!ELEMENT expediterWeight (#PCDATA)>
+ <!ELEMENT packedItem (quantity, description)>
+
+ <!ELEMENT emptySpace (length, width, height, weight)>
+
+ <!ELEMENT shippingOptions (insurance, deliveryConfirmation, signature)>
+ <!ELEMENT insurance (#PCDATA)>
+ <!ELEMENT deliveryConfirmation (#PCDATA)>
+ <!ELEMENT signature (#PCDATA)>
+
+
+ <!-- ********************************************************* -->
+ <!-- * 'nearestPostalOutlet' is optional and is returned * -->
+ <!-- * only if the merchant profile has this option enabled * -->
+ <!-- ********************************************************* -->
+ <!ELEMENT nearestPostalOutlet (postalOutletSequenceNo,
+ distance,
+ outletName,
+ businessName ,
+ postalAddress,
+ phoneNumber,
+ businessHours+)>
+ <!ELEMENT postalOutletSequenceNo (#PCDATA)>
+ <!ELEMENT distance (#PCDATA)>
+ <!ELEMENT outletName (#PCDATA)>
+ <!ELEMENT businessName (#PCDATA)>
+ <!ELEMENT postalAddress (addressLine+, postalCode , municipality)>
+ <!ELEMENT addressLine (#PCDATA)>
+ <!ELEMENT municipality (#PCDATA)>
+ <!ELEMENT phoneNumber (#PCDATA)>
+ <!ELEMENT businessHours (dayId, dayOfWeek, time)>
+ <!ELEMENT dayId (#PCDATA)>
+ <!ELEMENT dayOfWeek (#PCDATA)>
+ <!ELEMENT time (#PCDATA)>
+
+
+<!-- Standard error format returned -->
+<!ELEMENT error (statusCode,statusMessage*)>
+
View
2 test/fixtures.yml
@@ -11,3 +11,5 @@ fedex:
shipwire:
login: EmailAddress
password: Password
+canada_post:
+ login: CPC_DEMO_XML
View
1 test/fixtures/xml/canadapost/example_request.xml
@@ -0,0 +1 @@
+<!DOCTYPE eparcel SYSTEM "http://sellonline.canadapost.ca/DevelopersResources/protocolV3/eParcel.dtd"><eparcel><language>en</language><ratesAndServicesRequest><merchantCPCID>CPC_DEMO_XML</merchantCPCID><fromPostalCode>K1N 5T2</fromPostalCode><turnAroundTime>24</turnAroundTime><itemsPrice>25</itemsPrice><lineItems><item><quantity>1</quantity><weight>0.5</weight><length>4</length><width>3</width><height>2</height><description>a box full of stuff</description><readyToShip/></item></lineItems><city>Beverly Hills</city><provOrState>CA</provOrState><country>United States</country><postalCode>90210</postalCode></ratesAndServicesRequest></eparcel>
View
130 test/fixtures/xml/canadapost/example_response.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0"?>
+<!DOCTYPE eparcel [
+<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
+<!ELEMENT eparcel (ratesAndServicesResponse)>
+<!-- ********************************************************* -->
+<!-- * Standard response for request for rates and services * -->
+<!-- ********************************************************* -->
+<!ELEMENT ratesAndServicesResponse (statusCode , statusMessage+ , requestID , handling , language , product+ , packing* , emptySpace* , shippingOptions , comment , nearestPostalOutlet*)>
+<!ELEMENT statusCode (#PCDATA)>
+<!ELEMENT statusMessage (#PCDATA)>
+<!ELEMENT requestID (#PCDATA)>
+<!ELEMENT handling (#PCDATA)>
+<!ELEMENT language (#PCDATA)>
+<!ELEMENT product (name , rate , shippingDate , deliveryDate , deliveryDayOfWeek , nextDayAM? , packingID)>
+<!ATTLIST product id CDATA #REQUIRED>
+<!ATTLIST product sequence CDATA #REQUIRED>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT rate (#PCDATA)>
+<!ELEMENT shippingDate (#PCDATA)>
+<!ELEMENT deliveryDate (#PCDATA)>
+<!ELEMENT deliveryDayOfWeek (#PCDATA)>
+<!ELEMENT nextDayAM (#PCDATA)>
+<!ELEMENT packingID (#PCDATA)>
+<!ELEMENT packing (packingID , box+)>
+<!ELEMENT box (name , weight , expediterWeight , length , width , height , packedItem+)>
+<!ELEMENT weight (#PCDATA)>
+<!ELEMENT expediterWeight (#PCDATA)>
+<!ELEMENT length (#PCDATA)>
+<!ELEMENT width (#PCDATA)>
+<!ELEMENT height (#PCDATA)>
+<!ELEMENT packedItem (quantity , description)>
+<!ELEMENT quantity (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT emptySpace (length , width , height , weight)>
+<!ELEMENT shippingOptions (insurance , deliveryConfirmation , signature , flexiblePaymentAvailable?)>
+<!ELEMENT insurance (#PCDATA)>
+<!ELEMENT deliveryConfirmation (#PCDATA)>
+<!ELEMENT signature (#PCDATA)>
+<!ELEMENT flexiblePaymentAvailable EMPTY>
+<!ELEMENT comment (#PCDATA)>
+<!-- ********************************************************* -->
+<!-- * 'nearestPostalOutlet' is optional and is returned * -->
+<!-- * only if the merchant profile has this option enabled * -->
+<!-- ********************************************************* -->
+<!ELEMENT nearestPostalOutlet (postalOutletSequenceNo , distance , outletName , businessName , postalAddress , phoneNumber , businessHours+)>
+<!ELEMENT postalOutletSequenceNo (#PCDATA)>
+<!ELEMENT distance (#PCDATA)>
+<!ELEMENT outletName (#PCDATA)>
+<!ELEMENT businessName (#PCDATA)>
+<!ELEMENT postalAddress (addressLine+ , postalCode , municipality , province?)>
+<!ELEMENT addressLine (#PCDATA)>
+<!ELEMENT postalCode (#PCDATA)>
+<!ELEMENT municipality (#PCDATA)>
+<!ELEMENT province (#PCDATA)>
+<!ELEMENT phoneNumber (#PCDATA)>
+<!ELEMENT businessHours (dayId , dayOfWeek , time)>
+<!ELEMENT dayId (#PCDATA)>
+<!ELEMENT dayOfWeek (#PCDATA)>
+<!ELEMENT time (#PCDATA)>
+]>
+<eparcel>
+ <ratesAndServicesResponse>
+ <statusCode>1</statusCode>
+ <statusMessage>OK</statusMessage>
+ <requestID>6877575</requestID>
+ <handling>0.0</handling>
+ <language>0</language>
+ <product id="1040" sequence="1">
+ <name>Priority Courier</name>
+ <rate>40.28</rate>
+ <shippingDate>2010-08-03</shippingDate>
+ <deliveryDate>2010-08-04</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>true</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1020" sequence="2">
+ <name>Expedited</name>
+ <rate>17.16</rate>
+ <shippingDate>2010-08-03</shippingDate>
+ <deliveryDate>2010-08-04</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1010" sequence="3">
+ <name>Regular</name>
+ <rate>17.16</rate>
+ <shippingDate>2010-08-03</shippingDate>
+ <deliveryDate>2010-08-06</deliveryDate>
+ <deliveryDayOfWeek>6</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <packing>
+ <packingID>P_0</packingID>
+ <box>
+ <name>Small Box</name>
+ <weight>1.691</weight>
+ <expediterWeight>1.691</expediterWeight>
+ <length>25.0</length>
+ <width>17.0</width>
+ <height>16.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+ <description>KAO Diskettes</description>
+ </packedItem>
+ </box>
+ <box>
+ <name>My Ready To Ship Item</name>
+ <weight>2.0</weight>
+ <expediterWeight>1.5</expediterWeight>
+ <length>30.0</length>
+ <width>20.0</width>
+ <height>20.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+ <description>My Ready To Ship Item</description>
+ </packedItem>
+ </box>
+ </packing>
+ <shippingOptions>
+ <insurance>No</insurance>
+ <deliveryConfirmation>No</deliveryConfirmation>
+ <signature>No</signature>
+ </shippingOptions>
+ <comment/>
+ </ratesAndServicesResponse>
+</eparcel>
+<!--END_OF_EPARCEL-->
View
76 test/fixtures/xml/canadapost/example_response_error.xml
@@ -0,0 +1,76 @@
+<?xml version="1.0"?>
+<!DOCTYPE eparcel [
+<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
+<!ELEMENT eparcel (ratesAndServicesResponse)>
+<!-- ********************************************************* -->
+<!-- * Standard response for request for rates and services * -->
+<!-- ********************************************************* -->
+<!ELEMENT ratesAndServicesResponse (statusCode , statusMessage+ , requestID , handling , language , product+ , packing* , emptySpace* , shippingOptions , comment , nearestPostalOutlet*)>
+<!ELEMENT statusCode (#PCDATA)>
+<!ELEMENT statusMessage (#PCDATA)>
+<!ELEMENT requestID (#PCDATA)>
+<!ELEMENT handling (#PCDATA)>
+<!ELEMENT language (#PCDATA)>
+<!ELEMENT product (name , rate , shippingDate , deliveryDate , deliveryDayOfWeek , nextDayAM? , packingID)>
+<!ATTLIST product id CDATA #REQUIRED>
+<!ATTLIST product sequence CDATA #REQUIRED>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT rate (#PCDATA)>
+<!ELEMENT shippingDate (#PCDATA)>
+<!ELEMENT deliveryDate (#PCDATA)>
+<!ELEMENT deliveryDayOfWeek (#PCDATA)>
+<!ELEMENT nextDayAM (#PCDATA)>
+<!ELEMENT packingID (#PCDATA)>
+<!ELEMENT packing (packingID , box+)>
+<!ELEMENT box (name , weight , expediterWeight , length , width , height , packedItem+)>
+<!ELEMENT weight (#PCDATA)>
+<!ELEMENT expediterWeight (#PCDATA)>
+<!ELEMENT length (#PCDATA)>
+<!ELEMENT width (#PCDATA)>
+<!ELEMENT height (#PCDATA)>
+<!ELEMENT packedItem (quantity , description)>
+<!ELEMENT quantity (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT emptySpace (length , width , height , weight)>
+<!ELEMENT shippingOptions (insurance , deliveryConfirmation , signature , flexiblePaymentAvailable?)>
+<!ELEMENT insurance (#PCDATA)>
+<!ELEMENT deliveryConfirmation (#PCDATA)>
+<!ELEMENT signature (#PCDATA)>
+<!ELEMENT flexiblePaymentAvailable EMPTY>
+<!ELEMENT comment (#PCDATA)>
+<!-- ********************************************************* -->
+<!-- * 'nearestPostalOutlet' is optional and is returned * -->
+<!-- * only if the merchant profile has this option enabled * -->
+<!-- ********************************************************* -->
+<!ELEMENT nearestPostalOutlet (postalOutletSequenceNo , distance , outletName , businessName , postalAddress , phoneNumber , businessHours+)>
+<!ELEMENT postalOutletSequenceNo (#PCDATA)>
+<!ELEMENT distance (#PCDATA)>
+<!ELEMENT outletName (#PCDATA)>
+<!ELEMENT businessName (#PCDATA)>
+<!ELEMENT postalAddress (addressLine+ , postalCode , municipality , province?)>
+<!ELEMENT addressLine (#PCDATA)>
+<!ELEMENT postalCode (#PCDATA)>
+<!ELEMENT municipality (#PCDATA)>
+<!ELEMENT province (#PCDATA)>
+<!ELEMENT phoneNumber (#PCDATA)>
+<!ELEMENT businessHours (dayId , dayOfWeek , time)>
+<!ELEMENT dayId (#PCDATA)>
+<!ELEMENT dayOfWeek (#PCDATA)>
+<!ELEMENT time (#PCDATA)>
+]>
+<eparcel>
+ <ratesAndServicesResponse>
+ <statusCode>-2</statusCode>
+ <statusMessage>Missing argument when calling module</statusMessage>
+ <requestID>6877575</requestID>
+ <handling>0.0</handling>
+ <language>0</language>
+ <shippingOptions>
+ <insurance>No</insurance>
+ <deliveryConfirmation>No</deliveryConfirmation>
+ <signature>No</signature>
+ </shippingOptions>
+ <comment/>
+ </ratesAndServicesResponse>
+</eparcel>
+<!--END_OF_EPARCEL-->
View
122 test/fixtures/xml/canadapost/example_response_french.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!DOCTYPE eparcel [
+<!-- EVERY REQUEST CONTAIN THE eparcel TAG --><!ELEMENT eparcel (ratesAndServicesResponse)>
+<!-- ********************************************************* --><!-- * Standard response for request for rates and services * --><!-- ********************************************************* --><!ELEMENT ratesAndServicesResponse (statusCode , statusMessage+ , requestID , handling , language , product+ , packing* , emptySpace* , shippingOptions , comment , nearestPostalOutlet*)>
+<!ELEMENT statusCode (#PCDATA)>
+<!ELEMENT statusMessage (#PCDATA)>
+<!ELEMENT requestID (#PCDATA)>
+<!ELEMENT handling (#PCDATA)>
+<!ELEMENT language (#PCDATA)>
+<!ELEMENT product (name , rate , shippingDate , deliveryDate , deliveryDayOfWeek , nextDayAM? , packingID)>
+<!ATTLIST product id CDATA #REQUIRED>
+<!ATTLIST product sequence CDATA #REQUIRED>
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT rate (#PCDATA)>
+<!ELEMENT shippingDate (#PCDATA)>
+<!ELEMENT deliveryDate (#PCDATA)>
+<!ELEMENT deliveryDayOfWeek (#PCDATA)>
+<!ELEMENT nextDayAM (#PCDATA)>
+<!ELEMENT packingID (#PCDATA)>
+<!ELEMENT packing (packingID , box+)>
+<!ELEMENT box (name , weight , expediterWeight , length , width , height , packedItem+)>
+<!ELEMENT weight (#PCDATA)>
+<!ELEMENT expediterWeight (#PCDATA)>
+<!ELEMENT length (#PCDATA)>
+<!ELEMENT width (#PCDATA)>
+<!ELEMENT height (#PCDATA)>
+<!ELEMENT packedItem (quantity , description)>
+<!ELEMENT quantity (#PCDATA)>
+<!ELEMENT description (#PCDATA)>
+<!ELEMENT emptySpace (length , width , height , weight)>
+<!ELEMENT shippingOptions (insurance , deliveryConfirmation , signature , flexiblePaymentAvailable?)>
+<!ELEMENT insurance (#PCDATA)>
+<!ELEMENT deliveryConfirmation (#PCDATA)>
+<!ELEMENT signature (#PCDATA)>
+<!ELEMENT flexiblePaymentAvailable EMPTY>
+<!ELEMENT comment (#PCDATA)>
+<!-- ********************************************************* --><!-- * 'nearestPostalOutlet' is optional and is returned * --><!-- * only if the merchant profile has this option enabled * --><!-- ********************************************************* --><!ELEMENT nearestPostalOutlet (postalOutletSequenceNo , distance , outletName , businessName , postalAddress , phoneNumber , businessHours+)>
+<!ELEMENT postalOutletSequenceNo (#PCDATA)>
+<!ELEMENT distance (#PCDATA)>
+<!ELEMENT outletName (#PCDATA)>
+<!ELEMENT businessName (#PCDATA)>
+<!ELEMENT postalAddress (addressLine+ , postalCode , municipality , province?)>
+<!ELEMENT addressLine (#PCDATA)>
+<!ELEMENT postalCode (#PCDATA)>
+<!ELEMENT municipality (#PCDATA)>
+<!ELEMENT province (#PCDATA)>
+<!ELEMENT phoneNumber (#PCDATA)>
+<!ELEMENT businessHours (dayId , dayOfWeek , time)>
+<!ELEMENT dayId (#PCDATA)>
+<!ELEMENT dayOfWeek (#PCDATA)>
+<!ELEMENT time (#PCDATA)>
+]>
+<eparcel>
+ <ratesAndServicesResponse>
+ <statusCode>1</statusCode>
+ <statusMessage>OK</statusMessage>
+ <requestID>7838534</requestID>
+ <handling>0.0</handling>
+ <language>1</language>
+ <product id="1040" sequence="1">
+ <name>Messageries prioritaires</name>
+ <rate>40.46</rate>
+ <shippingDate>2010-09-07</shippingDate>
+ <deliveryDate>2010-09-08</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>true</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1020" sequence="2">
+ <name>Colis acc&#xE9;l&#xE9;r&#xE9;s</name>
+ <rate>17.24</rate>
+ <shippingDate>2010-09-07</shippingDate>
+ <deliveryDate>2010-09-08</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1010" sequence="3">
+ <name>Colis standard</name>
+ <rate>17.24</rate>
+ <shippingDate>2010-09-07</shippingDate>
+ <deliveryDate>2010-09-10</deliveryDate>
+ <deliveryDayOfWeek>6</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <packing>
+ <packingID>P_0</packingID>
+ <box>
+ <name>Small Box</name>
+ <weight>1.691</weight>
+ <expediterWeight>1.691</expediterWeight>
+ <length>25.0</length>
+ <width>17.0</width>
+ <height>16.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+ <description>KAO Diskettes</description>
+ </packedItem>
+ </box>
+ <box>
+ <name>My Ready To Ship Item</name>
+ <weight>2.0</weight>
+ <expediterWeight>1.5</expediterWeight>
+ <length>30.0</length>
+ <width>20.0</width>
+ <height>20.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+ <description>My Ready To Ship Item</description>
+ </packedItem>
+ </box>
+ </packing>
+ <shippingOptions>
+ <insurance>No</insurance>
+ <deliveryConfirmation>No</deliveryConfirmation>
+ <signature>No</signature>
+ </shippingOptions>
+ <comment/>
+ </ratesAndServicesResponse>
+</eparcel>
+<!--END_OF_EPARCEL-->
View
155 test/fixtures/xml/canadapost/example_response_with_postal_outlet.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0"?>
+<eparcel>
+ <ratesAndServicesResponse>
+ <statusCode>1</statusCode>
+ <statusMessage>OK</statusMessage>
+ <requestID>7251987</requestID>
+ <handling>3.0</handling>
+ <language>0</language>
+ <product id="1040" sequence="1">
+ <name>Priority Courier</name>
+ <rate>20.17</rate>
+ <shippingDate>2010-08-16</shippingDate>
+ <deliveryDate>2010-08-17</deliveryDate>
+ <deliveryDayOfWeek>3</deliveryDayOfWeek>
+ <nextDayAM>true</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1020" sequence="2">
+ <name>Expedited</name>
+ <rate>9.2</rate>
+ <shippingDate>2010-08-16</shippingDate>
+ <deliveryDate>2010-08-17</deliveryDate>
+ <deliveryDayOfWeek>3</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1010" sequence="3">
+ <name>Regular</name>
+ <rate>9.2</rate>
+ <shippingDate>2010-08-16</shippingDate>
+ <deliveryDate>2010-08-18</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <packing>
+ <packingID>P_0</packingID>
+ <box>
+ <name>a box full of stuff</name>
+ <weight>5.0</weight>
+ <expediterWeight>5.0</expediterWeight>
+ <length>4.0</length>
+ <width>3.0</width>
+ <height>2.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+ <description>a box full of stuff</description>
+ </packedItem>
+ </box>
+ </packing>
+ <shippingOptions>
+ <insurance>No</insurance>
+ <deliveryConfirmation>No</deliveryConfirmation>
+ <signature>No</signature>
+ </shippingOptions>
+ <comment/>
+ <nearestPostalOutlet>
+ <postalOutletSequenceNo>1</postalOutletSequenceNo>
+ <distance>0.2</distance>
+ <outletName>C/O: OTTAWA SOUTH PO</outletName>
+ <businessName>7-ELEVEN FOOD STORES #23739</businessName>
+ <postalAddress>
+ <addressLine>1166 BANK ST</addressLine>
+ <postalCode>K1S3X0</postalCode>
+ <municipality>OTTAWA</municipality>
+ <province>ON</province>
+ </postalAddress>
+ <phoneNumber>613-730-3022</phoneNumber>
+ <businessHours>
+ <dayId>1</dayId>
+ <dayOfWeek>SUN</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>2</dayId>
+ <dayOfWeek>MON</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>3</dayId>
+ <dayOfWeek>TUE</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>4</dayId>
+ <dayOfWeek>WED</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>5</dayId>
+ <dayOfWeek>THU</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>6</dayId>
+ <dayOfWeek>FRI</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>7</dayId>
+ <dayOfWeek>SAT</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ </nearestPostalOutlet>
+ <nearestPostalOutlet>
+ <postalOutletSequenceNo>2</postalOutletSequenceNo>
+ <distance>0.8</distance>
+ <outletName>C/O: BILLINGS PO</outletName>
+ <businessName>DAVIS AGENCY</businessName>
+ <postalAddress>
+ <addressLine>2265 RIVERSIDE DR</addressLine>
+ <postalCode>K1H7X0</postalCode>
+ <municipality>OTTAWA</municipality>
+ <province>ON</province>
+ </postalAddress>
+ <phoneNumber>613-521-8240</phoneNumber>
+ <businessHours>
+ <dayId>1</dayId>
+ <dayOfWeek>SUN</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>2</dayId>
+ <dayOfWeek>MON</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>3</dayId>
+ <dayOfWeek>TUE</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>4</dayId>
+ <dayOfWeek>WED</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>5</dayId>
+ <dayOfWeek>THU</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>6</dayId>
+ <dayOfWeek>FRI</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>7</dayId>
+ <dayOfWeek>SAT</dayOfWeek>
+ <time>07:00-21:00</time>
+ </businessHours>
+ </nearestPostalOutlet>
+ </ratesAndServicesResponse>
+</eparcel>
+<!--END_OF_EPARCEL-->
View
274 test/fixtures/xml/canadapost/example_response_with_postal_outlet_french.xml
@@ -0,0 +1,274 @@
+<?xml version="1.0"?>
+<!DOCTYPE eparcel [
+<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
+<!ELEMENT eparcel (ratesAndServicesResponse)>
+ <!-- ********************************************************* -->
+ <!-- * Standard response for request for rates and services * -->
+ <!-- ********************************************************* -->
+ <!ELEMENT ratesAndServicesResponse (statusCode, statusMessage+, requestID, handling, language, product+, packing*, emptySpace*, shippingOptions, comment, nearestPostalOutlet*)>
+ <!ELEMENT statusCode (#PCDATA)>
+ <!ELEMENT statusMessage (#PCDATA)>
+ <!ELEMENT requestID (#PCDATA)>
+
+ <!ELEMENT handling (#PCDATA)>
+ <!ELEMENT language (#PCDATA)>
+ <!ELEMENT product (name, rate, shippingDate, deliveryDate, deliveryDayOfWeek, nextDayAM?, packingID)>
+ <!ATTLIST product
+ id CDATA #REQUIRED
+ sequence CDATA #REQUIRED
+ >
+ <!ELEMENT name (#PCDATA)>
+ <!ELEMENT rate (#PCDATA)>
+ <!ELEMENT shippingDate (#PCDATA)>
+ <!ELEMENT deliveryDate (#PCDATA)>
+ <!ELEMENT deliveryDayOfWeek (#PCDATA)>
+
+ <!ELEMENT nextDayAM (#PCDATA)>
+ <!ELEMENT packingID (#PCDATA)>
+ <!ELEMENT packing (packingID, box+)>
+ <!ELEMENT box (name, weight, expediterWeight, length, width, height, packedItem+)>
+ <!ELEMENT weight (#PCDATA)>
+ <!ELEMENT expediterWeight (#PCDATA)>
+ <!ELEMENT length (#PCDATA)>
+ <!ELEMENT width (#PCDATA)>
+ <!ELEMENT height (#PCDATA)>
+
+ <!ELEMENT packedItem (quantity, description)>
+ <!ELEMENT quantity (#PCDATA)>
+ <!ELEMENT description (#PCDATA)>
+ <!ELEMENT emptySpace (length, width, height, weight)>
+ <!ELEMENT shippingOptions (insurance, deliveryConfirmation, signature, flexiblePaymentAvailable?)>
+ <!ELEMENT insurance (#PCDATA)>
+ <!ELEMENT deliveryConfirmation (#PCDATA)>
+ <!ELEMENT signature (#PCDATA)>
+ <!ELEMENT flexiblePaymentAvailable EMPTY>
+
+ <!ELEMENT comment (#PCDATA)>
+ <!-- ********************************************************* -->
+ <!-- * 'nearestPostalOutlet' is optional and is returned * -->
+ <!-- * only if the merchant profile has this option enabled * -->
+ <!-- ********************************************************* -->
+ <!ELEMENT nearestPostalOutlet (postalOutletSequenceNo, distance, outletName, businessName, postalAddress, phoneNumber, businessHours+)>
+ <!ELEMENT postalOutletSequenceNo (#PCDATA)>
+ <!ELEMENT distance (#PCDATA)>
+ <!ELEMENT outletName (#PCDATA)>
+
+ <!ELEMENT businessName (#PCDATA)>
+ <!ELEMENT postalAddress (addressLine+, postalCode, municipality, province?)>
+ <!ELEMENT addressLine (#PCDATA)>
+ <!ELEMENT postalCode (#PCDATA)>
+ <!ELEMENT municipality (#PCDATA)>
+ <!ELEMENT province (#PCDATA)>
+ <!ELEMENT phoneNumber (#PCDATA)>
+ <!ELEMENT businessHours (dayId, dayOfWeek, time)>
+ <!ELEMENT dayId (#PCDATA)>
+
+ <!ELEMENT dayOfWeek (#PCDATA)>
+ <!ELEMENT time (#PCDATA)>
+
+]>
+<eparcel>
+ <ratesAndServicesResponse>
+
+ <statusCode>1</statusCode>
+ <statusMessage>OK</statusMessage>
+ <requestID>7838448</requestID>
+
+ <handling>3.0</handling>
+ <language>1</language>
+ <product id="1040" sequence="1">
+ <name>Messageries prioritaires</name>
+ <rate>38.68</rate>
+ <shippingDate>2010-09-07</shippingDate>
+
+ <deliveryDate>2010-09-08</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>true</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+ <product id="1020" sequence="2">
+ <name>Colis acc&#xE9;l&#xE9;r&#xE9;s</name>
+
+ <rate>17.84</rate>
+ <shippingDate>2010-09-07</shippingDate>
+ <deliveryDate>2010-09-08</deliveryDate>
+ <deliveryDayOfWeek>4</deliveryDayOfWeek>
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+
+ </product>
+ <product id="1010" sequence="3">
+ <name>Colis standard</name>
+ <rate>17.84</rate>
+ <shippingDate>2010-09-07</shippingDate>
+ <deliveryDate>2010-09-10</deliveryDate>
+ <deliveryDayOfWeek>6</deliveryDayOfWeek>
+
+ <nextDayAM>false</nextDayAM>
+ <packingID>P_0</packingID>
+ </product>
+
+
+ <packing>
+ <packingID>P_0</packingID>
+ <box>
+ <name>Dummy box - Change me</name>
+
+ <weight>4.5</weight>
+ <expediterWeight>1.991</expediterWeight>
+ <length>30.0</length>
+ <width>30.0</width>
+ <height>30.0</height>
+ <packedItem>
+
+ <quantity>1</quantity>
+ <description>KAO Diskettes</description>
+ </packedItem>
+
+
+ </box>
+ <box>
+ <name>My Ready To Ship Item</name>
+ <weight>2.0</weight>
+
+ <expediterWeight>1.5</expediterWeight>
+ <length>30.0</length>
+ <width>20.0</width>
+ <height>20.0</height>
+ <packedItem>
+ <quantity>1</quantity>
+
+ <description>My Ready To Ship Item</description>
+ </packedItem>
+
+
+ </box>
+
+ </packing>
+
+ <shippingOptions>
+ <insurance>No</insurance>
+ <deliveryConfirmation>No</deliveryConfirmation>
+
+ <signature>No</signature>
+
+ </shippingOptions>
+
+ <comment></comment>
+
+ <nearestPostalOutlet >
+ <postalOutletSequenceNo>1</postalOutletSequenceNo>
+ <distance>0.7</distance>
+ <outletName>A/S: CP ATWATER</outletName>
+
+ <businessName>BRUNET ATWATER</businessName>
+ <postalAddress>
+ <addressLine>151 ATWATER</addressLine>
+ <postalCode>H3J2J0</postalCode>
+ <municipality>MONTR?AL</municipality>
+ <province>QC</province>
+ </postalAddress>
+ <phoneNumber>514-935-5637</phoneNumber>
+
+ <businessHours>
+ <dayId>1</dayId>
+ <dayOfWeek>DIM</dayOfWeek>
+ <time>ferm&#xE9;</time>
+ </businessHours>
+ <businessHours>
+ <dayId>2</dayId>
+
+ <dayOfWeek>LUN</dayOfWeek>
+ <time>09:00-19:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>3</dayId>
+ <dayOfWeek>MAR</dayOfWeek>
+ <time>09:00-19:00</time>
+
+ </businessHours>
+ <businessHours>
+ <dayId>4</dayId>
+ <dayOfWeek>MER</dayOfWeek>
+ <time>09:00-19:00</time>
+ </businessHours>
+ <businessHours>
+
+ <dayId>5</dayId>
+ <dayOfWeek>JEU</dayOfWeek>
+ <time>09:00-19:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>6</dayId>
+ <dayOfWeek>VEN</dayOfWeek>
+
+ <time>09:00-19:00</time>
+ </businessHours>
+ <businessHours>
+ <dayId>7</dayId>
+ <dayOfWeek>SAM</dayOfWeek>
+ <time>10:00-15:00</time>
+ </businessHours>
+
+</nearestPostalOutlet>
+<nearestPostalOutlet >
+ <postalOutletSequenceNo>2</postalOutletSequenceNo>
+ <distance>0.9</distance>
+ <outletName>A/S: BP MONTREAL D</outletName>
+ <businessName>BP MONTREAL D</businessName>
+ <postalAddress>
+ <addressLine>1695 GRAND TRUNK</addressLine>
+ <postalCode>H3K1J0</postalCode>
+
+ <municipality>MONTREAL</municipality>
+ <province>QC</province>
+ </postalAddress>
+ <phoneNumber>514-846-5391</phoneNumber>
+ <businessHours>
+ <dayId>1</dayId>
+ <dayOfWeek>DIM</dayOfWeek>
+
+ <time>ferm&#xE9;</time>
+ </businessHours>
+ <businessHours>
+ <dayId>2</dayId>
+ <dayOfWeek>LUN</dayOfWeek>
+ <time>09:30-17:30</time>
+ </businessHours>
+
+ <businessHours>
+ <dayId>3</dayId>
+ <dayOfWeek>MAR</dayOfWeek>
+ <time>09:30-17:30</time>
+ </businessHours>
+ <businessHours>
+ <dayId>4</dayId>
+
+ <dayOfWeek>MER</dayOfWeek>
+ <time>09:30-17:30</time>
+ </businessHours>
+ <businessHours>
+ <dayId>5</dayId>
+ <dayOfWeek>JEU</dayOfWeek>
+ <time>09:30-17:30</time>
+
+ </businessHours>
+ <businessHours>
+ <dayId>6</dayId>
+ <dayOfWeek>VEN</dayOfWeek>
+ <time>09:30-17:30</time>
+ </businessHours>
+ <businessHours>
+
+ <dayId>7</dayId>
+ <dayOfWeek>SAM</dayOfWeek>
+ <time>ferm&#xE9;</time>
+ </businessHours>
+
+</nearestPostalOutlet>
+
+ </ratesAndServicesResponse>
+</eparcel>
+
+<!--END_OF_EPARCEL-->
+
View
62 test/remote/canada_post_test.rb
@@ -0,0 +1,62 @@
+require 'test_helper'
+
+class CanadaPostTest < Test::Unit::TestCase
+
+ def setup
+ @packages = TestFixtures.packages
+ @locations = TestFixtures.locations
+ login = fixtures(:canada_post)
+
+ @request = xml_fixture('canadapost/example_request')
+ @response_with_postal_outlets = xml_fixture('canadapost/example_response_with_postal_outlet')
+ @response_with_postal_outlets_french = xml_fixture('canadapost/example_response_with_postal_outlet_french')
+ @carrier = CanadaPost.new(login)
+ @french_carrier = CanadaPost.new(login.merge(:french => true))
+
+ @origin = {:address1 => "61A York St", :city => "Ottawa", :province => "Ontario", :country => "Canada", :postal_code => "K1N 5T2"}
+ @destination = {:city => "Beverly Hills", :state => "CA", :country => "United States", :postal_code => "90210"}
+ @line_items = [Package.new(500, [2, 3, 4], :description => "a box full of stuff", :value => 25)]
+ end
+
+ def test_valid_credentials
+ @carrier.expects(:build_rate_request).returns(@request)
+ assert @carrier.valid_credentials?
+ end
+
+ def test_find_rates_french
+ rates = @french_carrier.find_rates(@origin, @destination, @line_items)
+ assert_instance_of CanadaPost::CanadaPostRateResponse, rates
+ end
+
+ def test_postal_outlets_french
+ @french_carrier.expects(:ssl_post).returns(@response_with_postal_outlets)
+ rates = @french_carrier.find_rates(@origin, @destination, @line_items)
+
+ rates.postal_outlets.each do |outlet|
+ assert_instance_of CanadaPost::PostalOutlet, outlet
+ end
+ end
+
+ def test_find_rates
+ rates = @carrier.find_rates(@origin, @destination, @line_items)
+ assert_instance_of CanadaPost::CanadaPostRateResponse, rates
+ end
+
+ def test_postal_outlets
+ @carrier.expects(:ssl_post).returns(@response_with_postal_outlets_french)
+ rates = @carrier.find_rates(@origin, @destination, @line_items)
+
+ rates.postal_outlets.each do |outlet|
+ assert_instance_of CanadaPost::PostalOutlet, outlet
+ end
+ end
+
+ def test_illegal_origin
+ @origin = @destination
+
+ assert_raise ActiveMerchant::Shipping::ResponseError do
+ rates = @carrier.find_rates(@origin, @destination, @line_items)
+ assert !rates.success?
+ end
+ end
+end
View
107 test/unit/carriers/canada_post_test.rb
@@ -0,0 +1,107 @@
+require 'test_helper'
+
+class CanadaPostTest < Test::Unit::TestCase
+
+ def setup
+ login = fixtures(:canada_post)
+
+ @carrier = CanadaPost.new(login)
+ @french_carrier = CanadaPost.new(login.merge(:french => true))
+
+ @request = xml_fixture('canadapost/example_request')
+ @response = xml_fixture('canadapost/example_response')
+ @response_french = xml_fixture('canadapost/example_response_french')
+ @bad_response = xml_fixture('canadapost/example_response_error')
+
+ @origin = {:address1 => "61A York St", :city => "Ottawa", :province => "ON", :country => "Canada", :postal_code => "K1N 5T2"}
+ @destination = {:city => "Beverly Hills", :state => "CA", :country => "United States", :postal_code => "90210"}
+ @line_items = [Package.new(500, [2, 3, 4], :description => "a box full of stuff", :value => 25)]
+ end
+
+ def test_parse_rate_response_french
+ assert_equal @request, @french_carrier.build_rate_request(@origin, @destination, 24, @line_items)
+ end
+
+ def test_parse_rate_response_french
+ @french_carrier.expects(:ssl_post).returns(@response_french)
+ rate_estimates = @french_carrier.find_rates(@origin, @destination, @line_items)
+ # rate_response = @french_carrier.send :parse_rate_response, @response_french, @origin, @desination
+
+ rate_estimates.rates.each do |rate|
+ assert_instance_of RateEstimate, rate
+ assert_instance_of Time, rate.delivery_date
+ assert_instance_of String, rate.service_name
+ assert_instance_of Fixnum, rate.total_price
+ end
+
+ rate_estimates.boxes.each do |box|
+ assert_instance_of CanadaPost::Box, box
+ assert_instance_of String, box.name
+ assert_instance_of Float, box.weight
+ assert_instance_of Float, box.expediter_weight
+ assert_instance_of Float, box.length
+ assert_instance_of Float, box.height
+ assert_instance_of Float, box.width
+
+ box.packedItems.each do |p|
+ assert_instance_of Fixnum, p.quantity
+ assert_instance_of String, p.description
+ end
+ end
+
+ end
+
+ def test_build_rate_request
+ @carrier.expects(:commit).with(@request, @origin, @destination, {})
+ @carrier.find_rates(@origin, @destination, @line_items)
+ end
+
+ def test_parse_rate_response
+ @carrier.expects(:ssl_post).returns(@response)
+ rate_estimates = @carrier.find_rates(@origin, @destination, @line_items)
+
+ rate_estimates.rates.each do |rate|
+ assert_instance_of RateEstimate, rate
+ assert_instance_of Time, rate.delivery_date
+ assert_instance_of String, rate.service_name
+ assert_instance_of Fixnum, rate.total_price
+ end
+
+ rate_estimates.boxes.each do |box|
+ assert_instance_of CanadaPost::Box, box
+ assert_instance_of String, box.name
+ assert_instance_of Float, box.weight
+ assert_instance_of Float, box.expediter_weight
+ assert_instance_of Float, box.length
+ assert_instance_of Float, box.height
+ assert_instance_of Float, box.width
+
+ box.packedItems.each do |p|
+ assert_instance_of Fixnum, p.quantity
+ assert_instance_of String, p.description
+ end
+ end
+ end
+
+ def test_non_success_parse_rate_response
+ assert_raise ActiveMerchant::Shipping::ResponseError do
+ @carrier.expects(:ssl_post).returns(@bad_response)
+ rate_estimates = @carrier.find_rates(@origin, @destination, @line_items)
+
+ assert_equal [], rate_estimates.rates
+ assert_equal [], rate_estimates.boxes
+ end
+ end
+
+ def test_date_for_nil_string
+ assert_nil @carrier.send(:date_for, nil)
+ end
+
+ def test_build_line_items
+ xml_line_items = @carrier.send(:build_line_items, @line_items)
+ assert_instance_of XmlNode, xml_line_items
+
+ xml_string = xml_line_items.to_s
+ assert_match /a box full of stuff/, xml_string
+ end
+end

0 comments on commit 25dd829

Please sign in to comment.
Something went wrong with that request. Please try again.