diff --git a/.travis.yml b/.travis.yml
index cc038d895..312e56cff 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ rvm:
- "2.2.2"
- "2.3.1"
- "2.4.0"
+- "2.5.3"
gemfile:
- gemfiles/activesupport42.gemfile
@@ -24,4 +25,5 @@ env:
- ACTIVESHIPPING_CANADA_POST_PWS_CUSTOMER_NUMBER=2004381
- ACTIVESHIPPING_CANADA_POST_PWS_API_KEY=6e93d53968881714
- ACTIVESHIPPING_CANADA_POST_PWS_SECRET=0bfa9fcb9853d1f51ee57a
+ - ACTIVESHIPPING_CANADA_POST_PWS_CONTRACT=42708517
- ACTIVESHIPPING_USPS_LOGIN=677JADED7283
diff --git a/active_shipping.gemspec b/active_shipping.gemspec
index f3d9dc841..095063ba9 100644
--- a/active_shipping.gemspec
+++ b/active_shipping.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency("measured", ">= 2.0")
- s.add_dependency("activesupport", ">= 4.2", "< 5.2.0")
+ s.add_dependency("activesupport", ">= 4.2", "< 6.1.0")
s.add_dependency("active_utils", "~> 3.3.1")
s.add_dependency("nokogiri", ">= 1.6")
diff --git a/dev.yml b/dev.yml
index 50cf934ad..f93543708 100644
--- a/dev.yml
+++ b/dev.yml
@@ -1,7 +1,7 @@
name: active-shipping
up:
- - ruby: 2.3.1
+ - ruby: 2.5.3
- bundler
commands:
diff --git a/gemfiles/activesupport60.gemfile b/gemfiles/activesupport60.gemfile
new file mode 100644
index 000000000..dc3fca536
--- /dev/null
+++ b/gemfiles/activesupport60.gemfile
@@ -0,0 +1,6 @@
+source "https://rubygems.org"
+
+gemspec path: '..'
+
+gem 'activesupport', '~> 6.0.0'
+gem 'active_utils', '~> 3.3.0'
diff --git a/lib/active_shipping/carriers/canada_post_pws.rb b/lib/active_shipping/carriers/canada_post_pws.rb
index 2718aecf7..d810b0130 100644
--- a/lib/active_shipping/carriers/canada_post_pws.rb
+++ b/lib/active_shipping/carriers/canada_post_pws.rb
@@ -33,9 +33,12 @@ class CanadaPostPWS < Carrier
ENDPOINT = "https://soa-gw.canadapost.ca/" # production
SHIPMENT_MIMETYPE = "application/vnd.cpc.ncshipment+xml"
+ CONTRACT_MIMETYPE = "application/vnd.cpc.shipment-v8+xml"
RATE_MIMETYPE = "application/vnd.cpc.ship.rate+xml"
TRACK_MIMETYPE = "application/vnd.cpc.track+xml"
REGISTER_MIMETYPE = "application/vnd.cpc.registration+xml"
+ MANIFEST_MIMETYPE = "application/vnd.cpc.manifest-v8+xml"
+
LANGUAGE = {
'en' => 'en-CA',
@@ -70,10 +73,35 @@ def self.default_location
:province => 'ON',
:city => 'Ottawa',
:address1 => '61A York St',
- :postal_code => 'K1N5T2'
+ :postal_code => 'K1N5T3'
}
end
+ def list_group_ids(options ={})
+ url = endpoint + "rs/#{@customer_number}/#{@customer_number}/group"
+ response = ssl_get(url, headers(options, CONTRACT_MIMETYPE))
+ parse_group_ids_response(response)
+ rescue ActiveUtils::ResponseError, ActiveShipping::ResponseError => e
+ error_response(e.response.body, CPPWSGroupResponse)
+ end
+
+ def transmit_shipments(warehouse_location, options = {})
+ url = endpoint + "rs/#{@customer_number}/#{@customer_number}/manifest"
+ request = build_transmit_request(warehouse_location, options)
+ response = ssl_post(url, request, headers(options, MANIFEST_MIMETYPE, MANIFEST_MIMETYPE))
+ parse_transmit_response(response)
+ rescue ActiveUtils::ResponseError, ActiveShipping::ResponseError => e
+ error_response(e.response.body, CPPWSTransmitResponse) if e.response
+ end
+
+ def find_manifest(manifest_url, options = {})
+ url = manifest_url
+ response = ssl_get(url, headers(options, MANIFEST_MIMETYPE))
+ parse_manifest_response(response)
+ rescue ActiveUtils::ResponseError, ActiveShipping::ResponseError => e
+ error_response(e.response.body, CPPWSManifestResponse)
+ end
+
def find_rates(origin, destination, line_items = [], options = {}, package = nil, services = [])
url = endpoint + "rs/ship/price"
request = build_rates_request(origin, destination, line_items, options, package, services)
@@ -107,6 +135,16 @@ def create_shipment(origin, destination, package, line_items = [], options = {})
CPPWSShippingResponse.new(false, "Missing Customer Number", {}, :carrier => @@name)
end
+ def create_contract_shipment(origin, destination, package, line_items = [], options = {}, return_details = {})
+ request_body = build_contract_shipment_request(origin, destination, package, line_items, options, return_details)
+ response = ssl_post(create_contract_shipment_url(options), request_body, headers(options, CONTRACT_MIMETYPE, CONTRACT_MIMETYPE))
+ parse_contract_shipment_response(response)
+ rescue ActiveUtils::ResponseError, ActiveShipping::ResponseError => e
+ error_response(e.response.body, CPPWSShippingResponse)
+ rescue MissingCustomerNumberError
+ CPPWSShippingResponse.new(false, "Missing Customer Number", {}, :carrier => @@name)
+ end
+
def retrieve_shipment(shipping_id, options = {})
response = ssl_post(shipment_url(shipping_id, options), nil, headers(options, SHIPMENT_MIMETYPE, SHIPMENT_MIMETYPE))
parse_shipment_response(response)
@@ -122,6 +160,17 @@ def retrieve_shipping_label(shipping_response, options = {})
ssl_get(shipping_response.label_url, headers(options, "application/pdf"))
end
+ def retrieve_return_label(shipping_response, options = {})
+ raise MissingShippingNumberError unless shipping_response && shipping_response.shipping_id
+ ssl_get(shipping_response.return_label_url, headers(options, "application/pdf"))
+ end
+
+ def retrieve_manifest_document(transmit_response, options = {})
+ raise MissingTransmitError unless transmit_response
+ ssl_get(transmit_response, headers(options, "application/pdf"))
+ end
+
+
def register_merchant(options = {})
url = endpoint + "ot/token"
response = ssl_post(url, nil, headers({}, REGISTER_MIMETYPE, REGISTER_MIMETYPE).merge("Content-Length" => "0"))
@@ -294,6 +343,46 @@ def parse_rates_response(response, origin, destination, exclude_tax)
CPPWSRateResponse.new(true, "", {}, :rates => rates)
end
+ def parse_group_ids_response(response)
+ doc = Nokogiri.XML(response)
+ doc.remove_namespaces!
+ raise ActiveShipping::ResponseError, "No Group ID's" unless doc.at('groups')
+ group_ids = []
+ group_ids = doc.root.xpath('group').map do |node|
+ link = node.at("link")['href']
+ group_id = node.at("group-id").text
+ group_ids << {link: link, group_id: group_id}
+ end
+ CPPWSGroupResponse.new(true, "", {}, :group_ids => group_ids)
+ end
+
+ def parse_transmit_response(response)
+ doc = Nokogiri.XML(response)
+ doc.remove_namespaces!
+ raise ActiveShipping::ResponseError, "No manifests" unless doc.at('manifests')
+ manifests = []
+ manifests = doc.xpath('manifests').map do |node|
+ link = node.at("link")['href']
+ end
+ CPPWSTransmitResponse.new(true, "", {}, :manifests => manifests)
+ end
+
+ def parse_manifest_response(response)
+ doc = Nokogiri.XML(response)
+ doc.remove_namespaces!
+ raise ActiveShipping::ResponseError, "No manifests" unless doc.at('manifest')
+
+ po_number = doc.at("manifest/po-number").text
+ manifest_url = doc.at_xpath("manifest/links/link[@rel='self']")['href']
+ artifact_url = doc.at_xpath("manifest/links/link[@rel='artifact']")['href']
+ details_url = doc.at_xpath("manifest/links/link[@rel='details']")['href']
+ manifest_shipments_url = doc.at_xpath("manifest/links/link[@rel='manifestShipments']")['href']
+ manifest = CPPWSManifest.new(po_number, manifest_url, artifact_url, details_url, manifest_shipments_url)
+
+
+ CPPWSManifestResponse.new(true, "", {}, :manifest => manifest)
+ end
+
def price_from_node(node, exclude_tax)
price = node.at('price-details/due').text
return price unless exclude_tax
@@ -358,6 +447,7 @@ def build_tracking_events(events)
# :show_postage_rate
# :cod, :cod_amount, :insurance, :insurance_amount, :signature_required, :pa18, :pa19, :hfp, :dns, :lad
#
+ #
def build_shipment_request(origin, destination, package, line_items = [], options = {})
builder = Nokogiri::XML::Builder.new do |xml|
xml.public_send('non-contract-shipment', :xmlns => "http://www.canadapost.ca/ws/ncshipment") do
@@ -378,10 +468,120 @@ def build_shipment_request(origin, destination, package, line_items = [], option
builder.to_xml
end
+ # return_details
+ # :service_code, :return_recipient {:name, :company, :address_details {:address_line_1...}}
+
+ def build_contract_shipment_request(origin, destination, package, line_items = [], options = {}, return_details = {})
+ builder = Nokogiri::XML::Builder.new do |xml|
+ xml.public_send('shipment', :xmlns => "http://www.canadapost.ca/ws/shipment-v8") do
+ shipment_node(xml, options)
+ xml.public_send('delivery-spec') do
+ shipment_service_code_node(xml, options)
+ shipment_sender_node(xml, origin, options)
+ shipment_destination_node(xml, destination, options)
+ shipment_options_node(xml, options)
+ shipment_parcel_node(xml, package)
+ shipment_notification_node(xml, options)
+ shipment_preferences_node(xml, options)
+ references_node(xml, options) # optional > user defined custom notes
+ shipment_customs_node(xml, destination, line_items, options)
+ settlement_node(xml, options)
+ # COD Remittance defaults to sender
+ end
+ shipment_return_node(xml, return_details, options)
+ end
+ end
+ builder.to_xml
+ end
+
+ def build_transmit_request(warehouse_location, options = {})
+ builder = Nokogiri::XML::Builder.new do |xml|
+ xml.public_send('transmit-set', :xmlns => "http://www.canadapost.ca/ws/manifest-v8") do
+ group_node(xml, options)
+ unless options[:shipping_point].nil?
+ options[:postal_simple] = warehouse_location.postal_simple
+ options[:pickup_indicator] = true
+ requested_shipping_point_node(xml, options)
+ cpc_pickup_indicator_node(xml, options)
+ else
+ shipping_point_node(xml, options)
+ end
+ method_of_payment_node(xml, options)
+ manifest_address_node(warehouse_location, xml, options)
+ detailed_manifests_node(xml, options)
+ end
+ end
+ builder.to_xml
+ end
+
+ def detailed_manifests_node(xml, options)
+ xml.public_send('detailed-manifests', options[:detailed_manifest] || false)
+ end
+
+ def manifest_address_node(warehouse_location, xml, options)
+ xml.public_send('manifest-address') do
+ xml.public_send('manifest-company' , warehouse_location.company)
+ xml.public_send('phone-number' , warehouse_location.phone)
+ xml.public_send('address-details') do
+ xml.public_send('address-line-1', warehouse_location.address1)
+ xml.public_send('address-line-2', warehouse_location.address2) unless warehouse_location.address2.blank?
+ xml.public_send('city', warehouse_location.city)
+ xml.public_send('prov-state', warehouse_location.province)
+ xml.public_send('country-code', warehouse_location.country_code)
+ # pc_strip = warehouse_location.postal_code.sub(/[^a-zA-Z0-9]/,'')
+ xml.public_send('postal-zip-code', warehouse_location.postal_simple)
+ end
+ end
+ end
+
+ def method_of_payment_node(xml, options)
+ #CreditCard Account SupplierAccount
+ #default to account
+ pay_method = options[:payment_method] || "Account"
+ xml.public_send('method-of-payment', pay_method)
+ end
+
+ def requested_shipping_point_node(xml, options)
+ xml.public_send('requested-shipping-point', options[:postal_simple])
+ end
+
+ def cpc_pickup_indicator_node(xml, options)
+ xml.public_send('cpc-pickup-indicator', options[:pickup_indicator])
+ end
+
+ def shipping_point_node(xml, options)
+ xml.public_send('shipping-point-id', options[:shipping_point_id])
+ end
+
+ def group_node(xml, options)
+ raise ActiveShipping::ResponseError, "No Group ID's defined in options" unless options[:group_ids].is_a?(Array)
+ xml.public_send('group-ids') do
+ options[:group_ids].each do |grp|
+ xml.public_send('group-id' , grp)
+ end
+ end
+ end
+
+ def shipment_node(xml, options)
+ if !!options[:transmit]
+ xml.public_send('transmit-shipment', options[:transmit] || true)
+ else
+ xml.public_send('group-id', options[:group_id])
+ end
+ xml.public_send('requested-shipping-point', options[:shipping_point])
+ end
+
def shipment_service_code_node(xml, options)
xml.public_send('service-code', options[:service])
end
+ def settlement_node(xml, options)
+ xml.public_send('settlement-info') do
+ xml.public_send('contract-id', options[:contract_number])
+ xml.public_send('intended-method-of-payment', options[:payment_type] || 'Account' )
+ end
+ end
+
def shipment_sender_node(xml, sender, options)
location = location_from_hash(sender)
xml.public_send('sender') do
@@ -393,7 +593,7 @@ def shipment_sender_node(xml, sender, options)
xml.public_send('address-line-2', location.address2_and_3) unless location.address2_and_3.blank?
xml.public_send('city', location.city)
xml.public_send('prov-state', location.province)
- # xml.public_send('country-code', location.country_code)
+ xml.public_send('country-code', location.country_code) unless location.country_code.blank?
xml.public_send('postal-zip-code', get_sanitized_postal_code(location))
end
end
@@ -473,6 +673,28 @@ def shipment_customs_node(xml, destination, line_items, options)
end
end
+ # return_details
+ # :service_code, :return_recipient {:name, :company, :address_details {:address_line_1...}}
+
+ def shipment_return_node(xml, return_details, options)
+ return if return_details.blank?
+ location = location_from_hash(return_details[:return_recipient][:address_details])
+ xml.public_send('return-spec') do
+ xml.public_send('service-code', return_details[:service_code] )
+ xml.public_send('return-recipient') do
+ xml.public_send('name', return_details[:name]) if return_details[:name]
+ xml.public_send('company', return_details[:company]) if return_details[:company]
+ xml.public_send('address-details') do
+ xml.public_send('address-line-1', location.address1)
+ xml.public_send('address-line-2', location.address2_and_3) unless location.address2_and_3.blank?
+ xml.public_send('city', location.city)
+ xml.public_send('prov-state', location.province) unless location.province.blank?
+ xml.public_send('postal-zip-code', get_sanitized_postal_code(location))
+ end
+ end
+ end
+ end
+
def shipment_parcel_node(xml, package, options = {})
weight = sanitize_weight_kg(package.kilograms.to_f)
xml.public_send('parcel-characteristics') do
@@ -484,7 +706,7 @@ def shipment_parcel_node(xml, package, options = {})
xml.public_send('width', '%.1f' % ((pkg_dim[1] * 10).round / 10.0)) if pkg_dim.size >= 2
xml.public_send('height', '%.1f' % ((pkg_dim[0] * 10).round / 10.0)) if pkg_dim.size >= 1
end
- xml.public_send('document', false)
+ #xml.public_send('document', false)
else
xml.public_send('document', true)
end
@@ -494,6 +716,25 @@ def shipment_parcel_node(xml, package, options = {})
end
end
+ def parse_contract_shipment_response(response)
+ doc = Nokogiri.XML(response)
+ doc.remove_namespaces!
+ raise ActiveShipping::ResponseError, "No Shipping" unless doc.at('shipment-info')
+ receipt_url = doc.root.at_xpath("links/link[@rel='receipt']")['href'] unless doc.root.at_xpath("links/link[@rel='receipt']").blank?
+ return_label_url = doc.root.at_xpath("links/link[@rel='returnLabel']")['href'] unless doc.root.at_xpath("links/link[@rel='returnLabel']").blank?
+ options = {
+ :shipping_id => doc.root.at('shipment-id').text,
+ :details_url => doc.root.at_xpath("links/link[@rel='details']")['href'],
+ :label_url => doc.root.at_xpath("links/link[@rel='label']")['href'],
+ :receipt_url => receipt_url,
+ :return_label_url => return_label_url
+ }
+ options[:tracking_number] = doc.root.at('tracking-pin').text if doc.root.at('tracking-pin')
+ options[:return_tracking_number] = doc.root.at('return-tracking-pin').text if doc.root.at('return-tracking-pin')
+
+ CPPWSContractShippingResponse.new(true, "", {}, options)
+ end
+
def parse_shipment_response(response)
doc = Nokogiri.XML(response)
doc.remove_namespaces!
@@ -505,7 +746,6 @@ def parse_shipment_response(response)
:receipt_url => doc.root.at_xpath("links/link[@rel='receipt']")['href'],
}
options[:tracking_number] = doc.root.at('tracking-pin').text if doc.root.at('tracking-pin')
-
CPPWSShippingResponse.new(true, "", {}, options)
end
@@ -604,6 +844,15 @@ def create_shipment_url(options)
end
end
+ def create_contract_shipment_url(options)
+ raise MissingCustomerNumberError unless customer_number = options[:customer_number]
+ if @platform_id.present?
+ endpoint + "rs/#{customer_number}-#{@platform_id}/shipment"
+ else
+ endpoint + "rs/#{customer_number}/#{customer_number}/shipment"
+ end
+ end
+
def shipment_url(shipping_id, options = {})
raise MissingCustomerNumberError unless customer_number = options[:customer_number]
if @platform_id.present?
@@ -830,6 +1079,32 @@ def initialize(success, message, params = {}, options = {})
end
end
+ class CPPWSGroupResponse < Response
+ DELIVERED_EVENT_CODES = %w(404 AA003)
+ include CPPWSErrorResponse
+
+ attr_reader :group_ids
+
+ def initialize(success, message, params = {}, options = {})
+ handle_error(message, options)
+ super
+ @group_ids = options[:group_ids]
+ end
+ end
+
+ class CPPWSManifestResponse < Response
+ DELIVERED_EVENT_CODES = %w(7313 7317 9118 9119 9122 9186 9187 9188 9189)
+ include CPPWSErrorResponse
+
+ attr_reader :manifest
+
+ def initialize(success, message, params = {}, options = {})
+ handle_error(message, options)
+ super
+ @manifest = options[:manifest]
+ end
+ end
+
class CPPWSTrackingResponse < TrackingResponse
DELIVERED_EVENT_CODES = %w(1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1441 1442 1496 1497 1498 1499 5300)
include CPPWSErrorResponse
@@ -873,6 +1148,44 @@ def initialize(success, message, params = {}, options = {})
end
end
+ class CPPWSTransmitResponse < Response
+ include CPPWSErrorResponse
+ attr_reader :manifest_urls
+ def initialize(success, message, params = {}, options = {})
+ handle_error(message, options)
+ super
+ @manifest_urls = options[:manifests]
+
+ end
+ end
+
+ class CPPWSManifest < Response
+ attr_reader :po_number, :manifest_url, :artifact_url, :details_url, :manifest_shipments_url
+
+ def initialize(po_number, manifest_url, artifact_url, details_url, manifest_shipments_url)
+ @po_number = po_number
+ @manifest_url = manifest_url
+ @artifact_url = artifact_url
+ @details_url = details_url
+ @manifest_shipments_url = manifest_shipments_url
+ end
+ end
+
+ class CPPWSContractShippingResponse < ShippingResponse
+ include CPPWSErrorResponse
+ attr_reader :label_url, :details_url, :receipt_url, :return_label_url, :return_tracking_number
+
+ def initialize(success, message, params = {}, options = {})
+ handle_error(message, options)
+ super
+ @label_url = options[:label_url]
+ @details_url = options[:details_url]
+ @receipt_url = options[:receipt_url]
+ @return_label_url = options[:return_label_url]
+ @return_tracking_number = options[:return_tracking_number]
+ end
+ end
+
class CPPWSRegisterResponse < Response
include CPPWSErrorResponse
attr_reader :token_id
@@ -905,4 +1218,5 @@ class InvalidPinFormatError < StandardError; end
class MissingCustomerNumberError < StandardError; end
class MissingShippingNumberError < StandardError; end
class MissingTokenIdError < StandardError; end
+ class MissingTransmitError < StandardError; end
end
diff --git a/lib/active_shipping/location.rb b/lib/active_shipping/location.rb
index ebcf777b2..622db13b2 100644
--- a/lib/active_shipping/location.rb
+++ b/lib/active_shipping/location.rb
@@ -135,6 +135,10 @@ def to_s
prettyprint.gsub(/\n/, ' ')
end
+ def postal_simple
+ @postal_code.sub(/[^a-zA-Z0-9]/,'')
+ end
+
def prettyprint
chunks = [@name, @address1, @address2, @address3]
chunks << [@city, @province, @postal_code].reject(&:blank?).join(', ')
diff --git a/lib/active_shipping/version.rb b/lib/active_shipping/version.rb
index a1365a03d..feb9fec8e 100644
--- a/lib/active_shipping/version.rb
+++ b/lib/active_shipping/version.rb
@@ -1,3 +1,3 @@
module ActiveShipping
- VERSION = "2.2.0"
+ VERSION = "2.2.2"
end
diff --git a/test/credentials.yml b/test/credentials.yml
index 861689b83..dc706aecf 100644
--- a/test/credentials.yml
+++ b/test/credentials.yml
@@ -34,6 +34,7 @@ canada_post_pws:
customer_number: <%= ENV['ACTIVESHIPPING_CANADA_POST_PWS_CUSTOMER_NUMBER'] %>
api_key: <%= ENV['ACTIVESHIPPING_CANADA_POST_PWS_API_KEY'] %>
secret: <%= ENV['ACTIVESHIPPING_CANADA_POST_PWS_SECRET'] %>
+ contract_number: <%= ENV['ACTIVESHIPPING_CANADA_POST_PWS_CONTRACT'] %>
canada_post_pws_platform:
platform_id: <%= ENV['ACTIVESHIPPING_CANADA_POST_PWS_PLATFORM_PLATFORM_ID'] %>
diff --git a/test/fixtures/xml/canadapost_pws/group_ids_response.xml b/test/fixtures/xml/canadapost_pws/group_ids_response.xml
new file mode 100644
index 000000000..37fc7cc45
--- /dev/null
+++ b/test/fixtures/xml/canadapost_pws/group_ids_response.xml
@@ -0,0 +1,6 @@
+
+
+
+ 123456
+
+
\ No newline at end of file
diff --git a/test/fixtures/xml/canadapost_pws/manifest_details.xml b/test/fixtures/xml/canadapost_pws/manifest_details.xml
new file mode 100644
index 000000000..70de00aa9
--- /dev/null
+++ b/test/fixtures/xml/canadapost_pws/manifest_details.xml
@@ -0,0 +1,7 @@
+
+ D906367941
+
+
+
+
+
\ No newline at end of file
diff --git a/test/fixtures/xml/canadapost_pws/transmit_response.xml b/test/fixtures/xml/canadapost_pws/transmit_response.xml
new file mode 100644
index 000000000..594f533fb
--- /dev/null
+++ b/test/fixtures/xml/canadapost_pws/transmit_response.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/test/fixtures/xml/canadapost_pws/transmit_set.xml b/test/fixtures/xml/canadapost_pws/transmit_set.xml
new file mode 100644
index 000000000..f3d69c2e8
--- /dev/null
+++ b/test/fixtures/xml/canadapost_pws/transmit_set.xml
@@ -0,0 +1,20 @@
+
+
+ 1234
+
+ K1K4T3
+ true
+ true
+ Account
+
+ my company
+ MajorShop
+ 555 555 5555
+
+ 1230 Tako RD.
+ Ottawa
+ ON
+ K1A1A1
+
+
+
\ No newline at end of file
diff --git a/test/remote/canada_post_pws_test.rb b/test/remote/canada_post_pws_test.rb
index ac2d1fa72..c29b60d7d 100644
--- a/test/remote/canada_post_pws_test.rb
+++ b/test/remote/canada_post_pws_test.rb
@@ -2,6 +2,8 @@
class RemoteCanadaPostPWSTest < ActiveSupport::TestCase
# All remote tests require Canada Post development environment credentials
+ # When using an account with a contract number you should add it to the opts hash
+
include ActiveShipping::Test::Credentials
include ActiveShipping::Test::Fixtures
@@ -14,7 +16,9 @@ def setup
@line_item1 = line_item_fixture
- @shipping_opts1 = { :dc => true, :cov => true, :cov_amount => 100.00, :aban => true }
+ @shipping_opts1 = {:cod => true, :dc => true, :cov => true, :cov_amount => 100.00, :aban => true }
+
+ @shipping_opts2 = {so: true, cov: true, cov_amount: 999.99, transmit: true, shipping_point: 'R3W1S1'}
@home_params = {
:name => "John Smith",
@@ -23,11 +27,22 @@ def setup
:address1 => "123 Elm St.",
:city => 'Ottawa',
:province => 'ON',
- :country => 'CA',
:postal_code => 'K1P 1J1'
}
@home = Location.new(@home_params)
+ @contract_home_params = {
+ :name => "John Smith",
+ :company => "test",
+ :phone => "613-555-1212",
+ :address1 => "123 Elm St.",
+ :city => 'Ottawa',
+ :province => 'ON',
+ :country => 'CA',
+ :postal_code => 'K1P 1J1'
+ }
+ @contract_home = Location.new(@contract_home_params)
+
@dom_params = {
:name => "John Smith Sr.",
:company => "",
@@ -77,6 +92,7 @@ def setup
@cp.logger = Logger.new(StringIO.new)
@customer_number = @login[:customer_number]
+ @contract_number = @login[:contract_number]
@DEFAULT_RESPONSE = {
:shipping_id => "406951321983787352",
@@ -121,25 +137,51 @@ def test_tracking_when_no_tracking_info_raises_exception
end
def test_create_shipment
- skip "Failing with 'Contract Number is a required field' after API change, skipping because no clue how to fix, might need different creds"
+ skip "contract number in credentials" if @contract_number
opts = {:customer_number => @customer_number, :service => "DOM.XP"}
response = @cp.create_shipment(@home_params, @dom_params, @pkg1, @line_item1, opts)
assert_kind_of CPPWSShippingResponse, response
- assert_match /\A\d{17}\z/, response.shipping_id
+ assert_match /\A\d{18}\z/, response.shipping_id
assert_equal "123456789012", response.tracking_number
- assert_match "https://ct.soa-gw.canadapost.ca/ers/artifact/", response.label_url
+ assert_match "https://ct.soa-gw.canadapost.ca/rs/artifact/", response.label_url
assert_match @login[:api_key], response.label_url
end
def test_create_shipment_with_options
- skip "Failing with 'Contract Number is a required field' after API change, skipping because no clue how to fix, might need different creds"
+ skip "contract number in credentials" if @contract_number
opts = {:customer_number => @customer_number, :service => "USA.EP"}.merge(@shipping_opts1)
response = @cp.create_shipment(@home_params, @dest_params, @pkg1, @line_item1, opts)
-
assert_kind_of CPPWSShippingResponse, response
- assert_match /\A\d{17}\z/, response.shipping_id
+ assert_match /\A\d{18}\z/, response.shipping_id
+ assert_equal "123456789012", response.tracking_number
+ assert_match "https://ct.soa-gw.canadapost.ca/rs/artifact/", response.label_url
+ assert_match @login[:api_key], response.label_url
+ end
+
+ def test_create_contract_shipment_with_options
+ skip "no contract number in credentials" unless @contract_number
+ opts = {:customer_number => @customer_number, :service => "DOM.XP", contract_number: @contract_number}.merge(@shipping_opts2)
+ response = @cp.create_contract_shipment(@contract_home_params, @dom_params, @pkg1, @line_item1, opts)
+ assert_kind_of CPPWSContractShippingResponse, response
+ assert_match /\A\d{18}\z/, response.shipping_id
+ assert_equal "123456789012", response.tracking_number
+ assert_match "https://ct.soa-gw.canadapost.ca/rs/artifact/", response.label_url
+ assert_match @login[:api_key], response.label_url
+ end
+
+ def test_create_contract_shipment_with_return_label_and_options
+ skip "no contract number in credentials" unless @contract_number
+
+ opts = {:customer_number => @customer_number, :service => "DOM.XP", contract_number: @contract_number}.merge(@shipping_opts2)
+
+ return_details = {service_code: 'DOM.RP', return_recipient: { address_details: @contract_home_params } }
+
+ response = @cp.create_contract_shipment(@contract_home_params, @dom_params, @pkg1, @line_item1, opts, return_details)
+ assert_kind_of CPPWSContractShippingResponse, response
+ assert_match /\A\d{18}\z/, response.shipping_id
assert_equal "123456789012", response.tracking_number
- assert_match "https://ct.soa-gw.canadapost.ca/ers/artifact/", response.label_url
+ assert_match "https://ct.soa-gw.canadapost.ca/rs/artifact/", response.label_url
+ assert_match "https://ct.soa-gw.canadapost.ca/rs/artifact/", response.return_label_url
assert_match @login[:api_key], response.label_url
end
diff --git a/test/unit/carriers/canada_post_pws_shipping_test.rb b/test/unit/carriers/canada_post_pws_shipping_test.rb
index 20db669f8..7e92abaf6 100644
--- a/test/unit/carriers/canada_post_pws_shipping_test.rb
+++ b/test/unit/carriers/canada_post_pws_shipping_test.rb
@@ -63,6 +63,7 @@ def setup
:so => true, :pa18 => true}
@default_options = {:customer_number => '123456'}
+ @default_contract_options = {:customer_number => '123456', :contract_number => '42708517'}
@DEFAULT_RESPONSE = {
:shipping_id => "406951321983787352",
@@ -93,6 +94,30 @@ def test_build_shipment_request_for_domestic
refute request.blank?
end
+ def test_build_contract_shipment_request_for_domestic
+ options = @default_contract_options.dup
+ request = @cp.build_contract_shipment_request(@home_params, @dom_params, @pkg1, @line_item1, options)
+ refute request.blank?
+ end
+
+ def test_build_contract_shipment_with_return_request_for_domestic
+ options = @default_contract_options.dup
+ return_details = {service_code: 'DOM.RP', return_recipient: { address_details: @home_params } }
+
+ request = @cp.build_contract_shipment_request(@home_params, @dom_params, @pkg1, @line_item1, options, return_details)
+ refute request.blank?
+
+ doc = Nokogiri.XML(request)
+ doc.remove_namespaces!
+
+ assert root_node = doc.at('shipment')
+ assert delivery_spec = root_node.at('delivery-spec')
+ assert destination = delivery_spec.at('destination')
+ assert address_details = destination.at('address-details')
+ assert_equal 'CA', address_details.at('country-code').text
+ assert return_spec = root_node.at('return-spec')
+ end
+
def test_build_shipment_request_for_US
options = @default_options.dup
request = @cp.build_shipment_request(@home_params, @us_params, @pkg1, @line_item1, options)
@@ -255,4 +280,19 @@ def test_parse_find_shipment_receipt_doesnt_break_without_priced_options
def test_maximum_address_field_length
assert_equal 44, @cp.maximum_address_field_length
end
+
+ def test_manifest_group_ids
+ options = @default_options.dup
+ xml_response = xml_fixture('canadapost_pws/group_ids_response')
+ @cp.expects(:ssl_get).once.returns(xml_response)
+ response = @cp.list_group_ids(options)
+ assert_equal @cp.parse_group_ids_response(xml_response).group_ids, response.group_ids
+ end
+
+ def test_transmit_shipments
+ options = @default_options.dup
+ xml_response = xml_fixture('canadapost_pws/transmit_response')
+ response = @cp.transmit_shipments(Location.new(@home_params), options)
+ assert response.nil?
+ end
end
diff --git a/test/unit/carriers/canada_post_pws_test.rb b/test/unit/carriers/canada_post_pws_test.rb
index 8e844ba23..e8942b5fe 100644
--- a/test/unit/carriers/canada_post_pws_test.rb
+++ b/test/unit/carriers/canada_post_pws_test.rb
@@ -10,17 +10,17 @@ def setup
def test_get_sanitized_postal_code_location_nil
postal_code = @cp.send(:get_sanitized_postal_code, nil)
- assert_equal nil, postal_code
+ assert_nil postal_code
end
def test_get_sanitized_postal_code_postal_code_nil
location = Location.new(name: 'Test test')
- assert_equal nil, location.postal_code
+ assert_nil location.postal_code
postal_code = @cp.send(:get_sanitized_postal_code, location)
- assert_equal nil, postal_code
+ assert_nil postal_code
end
def test_get_sanitized_postal_code_spaces