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