lib/omniship/carriers/ups.rb in omniship-0.3.2.2 vs lib/omniship/carriers/ups.rb in omniship-0.4.0

- old
+ new

@@ -13,11 +13,12 @@ :rates => 'ups.app/xml/Rate', :track => 'ups.app/xml/Track', :shipconfirm => 'ups.app/xml/ShipConfirm', :shipaccept => 'ups.app/xml/ShipAccept', :shipvoid => 'ups.app/xml/Void', - :valid_address => 'ups.app/xml/XAV' + :valid_address => 'ups.app/xml/AV', + :valid_address_street => 'ups.app/xml/XAV' } PICKUP_CODES = HashWithIndifferentAccess.new({ :daily_pickup => "01", :customer_counter => "03", @@ -98,67 +99,75 @@ [:key, :login, :password] end def find_rates(origin, destination, packages, options={}) origin, destination = upsified_location(origin), upsified_location(destination) - options = @options.merge(options) - options[:test] = options[:test].nil? ? false : options[:test] - packages = Array(packages) - access_request = build_access_request - rate_request = build_rate_request(origin, destination, packages, options) - response = commit(:rates, save_request(access_request.gsub("\n", "") + rate_request.gsub("\n", "")), options[:test]) + options = @options.merge(options) + options[:test] = options[:test].nil? ? false : options[:test] + packages = Array(packages) + access_request = build_access_request + rate_request = build_rate_request(origin, destination, packages, options) + response = commit(:rates, save_request(access_request.gsub("\n", "") + rate_request.gsub("\n", "")), options[:test]) parse_rate_response(origin, destination, packages, response, options) end def find_tracking_info(tracking_number, options={}) - options = @options.update(options) - options[:test] = options[:test].nil? ? false : options[:test] - access_request = build_access_request + options = @options.update(options) + options[:test] = options[:test].nil? ? false : options[:test] + access_request = build_access_request tracking_request = build_tracking_request(tracking_number, options) - response = commit(:track, save_request(access_request.gsub("\n", "") + tracking_request.gsub("\n", "")), options[:test]) - parse_tracking_response(response, options) + response = commit(:track, save_request(access_request.gsub("\n", "") + tracking_request.gsub("\n", "")), options[:test]) + # parse_tracking_response(response, options) end # Creating shipping functionality for UPS def create_shipment(origin, destination, packages, options={}) - @options = @options.merge(options) - origin, destination = upsified_location(origin), upsified_location(destination) - options = @options.merge(options) - options[:test] = options[:test].nil? ? true : options[:test] - packages = Array(packages) - access_request = build_access_request + @options = @options.merge(options) + origin, destination = upsified_location(origin), upsified_location(destination) + options = @options.merge(options) + options[:test] = options[:test].nil? ? true : options[:test] + packages = Array(packages) + access_request = build_access_request ship_confirm_request = build_ship_confirm(origin, destination, packages, options) - response = commit(:shipconfirm, save_request(access_request.gsub("\n", "") + ship_confirm_request.gsub("\n", "")), options[:test]) + response = commit(:shipconfirm, save_request(access_request.gsub("\n", "") + ship_confirm_request.gsub("\n", "")), options[:test]) parse_ship_confirm_response(origin, destination, packages, response, options) end def accept_shipment(digest, options={}) - options[:test] = options[:test].nil? ? true : options[:test] - access_request = build_access_request + options[:test] = options[:test].nil? ? true : options[:test] + access_request = build_access_request ship_accept_request = build_ship_accept(digest) - response = commit(:shipaccept, save_request(access_request.gsub("\n", "") + ship_accept_request.gsub("\n", "")), options[:test]) + response = commit(:shipaccept, save_request(access_request.gsub("\n", "") + ship_accept_request.gsub("\n", "")), options[:test]) parse_ship_accept_response(response, options) end - def void_shipment(ups_shipment_id,tracking_number, options={}) - @options = @options.merge(options) - options = @options.merge(options) - options[:test] = options[:test].nil? ? true : options[:test] - access_request = build_access_request + def void_shipment(ups_shipment_id, tracking_number, options={}) + @options = @options.merge(options) + options = @options.merge(options) + options[:test] = options[:test].nil? ? true : options[:test] + access_request = build_access_request ship_void_request = build_void_request(ups_shipment_id,tracking_number) - response = commit(:shipvoid, save_request(access_request.gsub("\n", "") + ship_void_request.gsub("\n", "")), options[:test]) + response = commit(:shipvoid, save_request(access_request.gsub("\n", "") + ship_void_request.gsub("\n", "")), options[:test]) parse_ship_void_response(response, options) end - - def validate_address(address,city,state,zip_code,country_code, options={}) + + def validate_address(city, state, zip_code, country_code, options={}) + @options = @options.merge(options) + access_request = build_access_request + validate_address_request = build_valid_address_request(city,state,zip_code,country_code) + options[:test] = options[:test].nil? ? true : options[:test] + response = commit(:valid_address, save_request(access_request.gsub("\n", "") + validate_address_request.gsub("\n", "")), options[:test]) + parse_ship_valid_address(response) + end + + def validate_address_street(address, city, state, zip_code, country_code, options={}) @options = @options.merge(options) access_request = build_access_request - validate_address_request = build_valid_address_request(address,city,state,zip_code,country_code) + validate_address_street_request = build_valid_address_street_request(address,city,state,zip_code,country_code) options[:test] = options[:test].nil? ? true : options[:test] - response = commit(:valid_address, save_request(access_request.gsub("\n", "") + validate_address_request.gsub("\n", "")), options[:test]) - parse_response = parse_ship_valid_address(response) - parse_response + response = commit(:valid_address_street, save_request(access_request.gsub("\n", "") + validate_address_street_request.gsub("\n", "")), options[:test]) + parse_ship_valid_address_street(response) end protected def upsified_location(location) @@ -170,29 +179,24 @@ Address.new(atts) else location end end - + def build_access_request builder = Nokogiri::XML::Builder.new do |xml| xml.AccessRequest { xml.AccessLicenseNumber @options[:key].nil? ? @config['ups']['key'] : @options[:key] xml.UserId @options[:login].nil? ? @config['ups']['username'] : @options[:login] xml.Password @options[:password].nil? ? @config['ups']['password'] : @options[:password] - - - xml.AccessLicenseNumber @config['ups']['key'] unless @options[:key] - xml.UserId @config['ups']['username'] unless @options[:login] - xml.Password @config['ups']['password'] unless @options[:password] } end builder.to_xml end - # Build the ship_confirm XML request + # Build the ship_confirm XML request def build_ship_confirm(origin, destination, packages, options={}) #Return Service types: #‘2’ = UPS Print and Mail (PNM) #‘3’ = UPS Return Service 1- Attempt (RS1) @@ -204,11 +208,11 @@ packages = Array(packages) builder = Nokogiri::XML::Builder.new do |xml| xml.ShipmentConfirmRequest { xml.Request { xml.RequestAction 'ShipConfirm' - xml.RequestOption 'validate' + xml.RequestOption options[:nonvalidate] ? 'nonvalidate' : 'validate' } xml.Shipment { build_location_node(['Shipper'], (options[:shipper] || origin), options, xml) build_location_node(['ShipTo'], destination, options, xml) if options[:shipper] && options[:shipper] != origin @@ -268,10 +272,21 @@ xml.DeliveryConfirmation { xml.DCISType package.options[:delivery_confirmation_type] } end } + if package.options[:references].present? + package.options[:references].each do |reference| + xml.ReferenceNumber { + xml.Code reference[:code] + xml.Value reference[:value] + if reference[:barcode] + xml.BarCodeIndicator + end + } + end + end } end xml.LabelSpecification { xml.LabelPrintMethod { xml.Code 'GIF' @@ -310,31 +325,48 @@ } } end builder.to_xml end - - def build_valid_address_request(address,city,state,zip_code,country_code) + + def build_valid_address_street_request(address,city,state,zip_code,country_code) builder = Nokogiri::XML::Builder.new do |xml| - xml.AddressValidationRequest { - xml.Request{ - xml.RequestAction 'XAV' - xml.RequestOption 3 - } - - xml.AddressKeyFormat{ - xml.AddressLine address - xml.PoliticalDivision2 city - xml.PoliticalDivision1 state - xml.PostcodePrimaryLow zip_code - xml.CountryCode country_code - } + xml.AddressValidationRequest { + xml.Request { + xml.RequestAction "XAV" } + + xml.AddressKeyFormat { + xml.AddressLine address + xml.PoliticalDivision2 city + xml.PoliticalDivision1 state + xml.PostcodePrimaryLow zip_code + xml.CountryCode country_code + } + } end builder.to_xml end + def build_valid_address_request(city,state,zip_code,country_code) + builder = Nokogiri::XML::Builder.new do |xml| + xml.AddressValidationRequest { + xml.Request{ + xml.RequestAction 'AV' + } + + xml.Address{ + xml.City city + xml.StateProvinceCode state + xml.CountryCode country_code + xml.PostalCode zip_code + } + } + end + builder.to_xml + end + def build_rate_request(origin, destination, packages, options={}) packages = Array(packages) builder = Nokogiri::XML::Builder.new do |xml| xml.RatingServiceSelectionRequest { xml.Request { @@ -412,15 +444,18 @@ def build_tracking_request(tracking_number, options={}) builder = Nokogiri::XML::Builder.new do |xml| xml.TrackRequest { xml.Request { - xml.RequestAction 'Track' - xml.RequestOption '7' - } - xml.TrackingNumber tracking_number.to_s - xml.TrackingOption '02' + xml.TransactionReference { + } + xml.RequestAction "Track" + } + xml.TrackingNumber tracking_number.to_s + xml.ShipmentType { + xml.Code "01" + } } end builder.to_xml end @@ -478,51 +513,51 @@ end end RateResponse.new(success, message, Hash.from_xml(response).values.first, :rates => rate_estimates, :xml => response, :request => last_request) end - def parse_tracking_response(response, options={}) + def parse_tracking_response(response, options={}) xml = Nokogiri::XML(response) success = response_success?(xml) message = response_message(xml) - + puts "response :" + xml.to_s - + if success tracking_number, origin, destination = nil shipment_details = Hash.new - - tracking_number = xml.xpath('/*/Shipment/Package/TrackingNumber').text + + tracking_number = xml.xpath('/*/Shipment/Package/TrackingNumber').text shipment_details[:tracking_number] = tracking_number - - estimated_delivery_date = xml.xpath('/*/Shipment/ScheduledDeliveryDate').text - if !estimated_delivery_date.blank? + + estimated_delivery_date = xml.xpath('/*/Shipment/ScheduledDeliveryDate').text + if !estimated_delivery_date.blank? estimated_delivery_date = Date.strptime(estimated_delivery_date,'%Y%m%d') shipment_details[:estimated_delivery_date] = estimated_delivery_date else - reschedule_delivery_date = xml.xpath('/*/Shipment/Package/RescheduledDeliveryDate').text - if !reschedule_delivery_date.blank? + reschedule_delivery_date = xml.xpath('/*/Shipment/Package/RescheduledDeliveryDate').text + if !reschedule_delivery_date.blank? reschedule_delivery_date = Date.strptime(reschedule_delivery_date,'%Y%m%d') shipment_details[:estimated_delivery_date] = reschedule_delivery_date end end - + puts 'tracking_number: ' + tracking_number - puts 'estimated_delivery_date: ' + estimated_delivery_date.to_s - + puts 'estimated_delivery_date: ' + estimated_delivery_date.to_s + activities = [] xml.xpath('/*/Shipment/Package/Activity').each do |activity| - status_code = activity.xpath('Status/StatusCode').text - status_dsc = activity.xpath('Status/StatusType/Description').text - date = activity.xpath('Date').text - time = activity.xpath('Time').text + status_code = activity.xpath('Status/StatusCode').text + status_dsc = activity.xpath('Status/StatusType/Description').text + date = activity.xpath('Date').text + time = activity.xpath('Time').text hour, minute, second = time.scan(/\d{2}/) year, month, day = date[0..3], date[4..5], date[6..7] - date_time = Time.utc(year, month, day, hour, minute, second) - location = activity.xpath('ActivityLocation/Address/City').text + ' ' + activity.xpath('ActivityLocation/Address/StateProvinceCode').text + ' ' + activity.xpath('ActivityLocation/Address/CountryCode').text + date_time = Time.utc(year, month, day, hour, minute, second) + location = activity.xpath('ActivityLocation/Address/City').text + ' ' + activity.xpath('ActivityLocation/Address/StateProvinceCode').text + ' ' + activity.xpath('ActivityLocation/Address/CountryCode').text activities << {:status_code => status_code, :status_dsc => status_dsc, :date => date_time, :location => location} - end + end shipment_details[:activities] = activities #first_shipment = xml.gelements['/*/Shipment'] #first_package = first_shipment.elements['Package'] #tracking_number = first_shipment.get_text('ShipmentIdentificationNumber | Package/TrackingNumber').to_s @@ -543,13 +578,13 @@ # Time.utc(year, month, day, hour, minute, second) # end # location = location_from_address_node(activity.elements['ActivityLocation/Address']) # ShipmentEvent.new(description, zoneless_time, location) # end - # + # # shipment_events = shipment_events.sort_by(&:time) - # + # # if origin # first_event = shipment_events[0] # same_country = origin.country_code(:alpha2) == first_event.location.country_code(:alpha2) # same_or_blank_city = first_event.location.city.blank? or first_event.location.city == origin.city # origin_event = ShipmentEvent.new(first_event.name, first_event.time, origin) @@ -631,29 +666,55 @@ @void = "Voiding shipment failed!" end return @void end - + def parse_ship_valid_address(response, options={}) xml = Nokogiri::XML(response) + puts xml success = response_success?(xml) - suggested_addresses = Array.new + response_text = Array.new if success - addresses = xml.xpath('/*/AddressKeyFormat').each do |address_data| - address_hash = Hash.new - address_hash[:address] = address_data.xpath('AddressLine').text - address_hash[:city] = address_data.xpath('PoliticalDivision2').text - address_hash[:state] = address_data.xpath('PoliticalDivision1').text - address_hash[:zip_code] = address_data.xpath('PostcodePrimaryLow').text - address_hash[:country_code] = address_data.xpath('CountryCode').text - suggested_addresses << address_hash + addresses = xml.xpath('/*/AddressValidationResult').each do |address_data| + response_text = Hash.new + response_text[:rank] = address_data.xpath('Rank').text + response_text[:quality] = address_data.xpath('Quality').text + response_text[:city] = address_data.xpath('Address/City').text + response_text[:state] = address_data.xpath('Address/StateProvinceCode').text + response_text[:postal_code_low] = address_data.xpath('PostalCodeLowEnd').text + response_text[:postal_code_high] = address_data.xpath('PostalCodeHighEnd').text end else return "Address validation failed!" end + return response_text + end - return suggested_addresses + def parse_ship_valid_address_street(response, options={}) + n = 1 + xml = Nokogiri::XML(response) + puts xml + success = response_success?(xml) + response_text = Array.new + if success + addresses = xml.xpath('/*/AddressKeyFormat').each do |address_data| + response_text = Hash.new + address_data.xpath('AddressLine').each do |address_line| + response_text["address_#{n}".to_sym] = address_line.text + n += 1 + end + response_text[:region] = address_data.xpath('Region').text + response_text[:city] = address_data.xpath('PoliticalDivision2').text + response_text[:state] = address_data.xpath('PoliticalDivision1').text + response_text[:postal_code] = address_data.xpath('PostcodePrimaryLow').text + response_text[:postal_code_extended] = address_data.xpath('PostcodeExtendedLow').text + response_text[:country_code] = address_data.xpath("CountryCode").text + end + else + return "Address validation failed!" + end + return response_text end def location_from_address_node(address) return nil unless address Address.new(