Skip to content

Commit

Permalink
Merge pull request #1 from adamjk/account_for_nil_time_events_usps
Browse files Browse the repository at this point in the history
enable nil time event processing in usps
  • Loading branch information
adamjk committed Mar 3, 2015
2 parents ba6aac3 + 2320f2e commit 89c408c
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 23 deletions.
50 changes: 33 additions & 17 deletions lib/active_shipping/shipping/carriers/usps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class USPS < Carrier

cattr_reader :name
@@name = "USPS"
@@ip_addr = IPSocket.getaddress(Socket.gethostname)

LIVE_DOMAIN = 'production.shippingapis.com'
LIVE_RESOURCE = 'ShippingAPI.dll'
Expand Down Expand Up @@ -144,6 +143,11 @@ class USPS < Carrier
/That's not a valid number\./
]

def initialize(options = {})
super
@ip_addr = @options[:ip_address] || IPSocket.getaddress(Socket.gethostname)
end

def find_tracking_info(tracking_number, options={})
options = @options.update(options)
tracking_request = build_tracking_request(tracking_number, options)
Expand Down Expand Up @@ -242,7 +246,7 @@ def build_tracking_with_fields_request(tracking_numbers)
xml_request = XmlNode.new('TrackFieldRequest', 'USERID' => @options[:login]) do |root_node|
root_node << XmlNode.new('Revision', 1)
# NOTE not sure of purpose and use of the client ip address
root_node << XmlNode.new('ClientIp', @@ip_addr)
root_node << XmlNode.new('ClientIp', @ip_addr)
root_node << XmlNode.new('SourceId', @options[:login]) # usps login as internal user
tracking_numbers.each { |track_num| root_node << XmlNode.new('TrackID', :ID => track_num) }
end
Expand Down Expand Up @@ -578,22 +582,25 @@ def parse_tracking_with_fields_response(response)
success = !(tracking_info.elements['Error'] || summary_no_record?(tracking_summary))
message = response_message(tracking_info)
shipment_events = []
status, expected_delivery_date, actual_delivery_date = nil
status, status_category, expected_delivery_date, actual_delivery_date = nil, nil, nil, nil

if success
previous_event_time = Time.now
tracking_details.each do |event|
ship_event = extract_track_with_fields_event(event)
shipment_events << ship_event if !ship_event.nil?
ship_event = extract_track_with_fields_event(event, previous_event_time)
previous_event_time = ship_event.time
shipment_events << ship_event
end
summary_ship_event = extract_track_with_fields_event(tracking_summary)
summary_ship_event = extract_track_with_fields_event(tracking_summary, previous_event_time)
if !summary_ship_event.nil?
shipment_events << summary_ship_event
status = summary_ship_event.status
actual_delivery_date = summary_ship_event.time if summary_ship_event.delivered?
end

shipment_events = shipment_events.sort_by(&:time)
status = tracking_info.elements['StatusCategory'].get_text.to_s
status = status.downcase.gsub("\s", "_").to_sym
status_category = tracking_info.elements['StatusCategory'].get_text.to_s
status_category = status_category.downcase.gsub("\s", "_").to_sym

if tracking_info.elements['ExpectedDeliveryDate']
if tracking_info.elements['ExpectedDeliveryTime']
Expand All @@ -612,6 +619,7 @@ def parse_tracking_with_fields_response(response)
:shipment_events => shipment_events,
:tracking_number => tracking_number,
:status => status,
:status_category => status_category,
:actual_delivery_date => actual_delivery_date,
:scheduled_delivery_date => expected_delivery_date
)
Expand All @@ -620,19 +628,27 @@ def parse_tracking_with_fields_response(response)
tracking_responses
end

def extract_track_with_fields_event(track_event_node)
# pass default event_time to fill if none available in event in order to maintain sort order
def extract_track_with_fields_event(track_event_node, default_event_time)
event = nil
status_name = track_event_node.elements['Event'].get_text.to_s
if !status_name.nil? && !status_name.empty?
time = Time.parse("#{track_event_node.elements['EventDate'].get_text.to_s} #{track_event_node.elements['EventTime'].get_text.to_s}")
datetime_str = "#{track_event_node.elements['EventDate'].get_text.to_s} #{track_event_node.elements['EventTime'].get_text.to_s}"

if !datetime_str.nil? && datetime_str.length > 1
time = Time.parse(datetime_str)
zoneless_datetime = Time.utc(time.year, time.month, time.mday, time.hour, time.min, time.sec)
country = !!track_event_node.elements['EventCountry'] || track_event_node.elements['EventCountry'].blank? ? 'USA' : track_event_node.elements['EventCountry'].get_text.to_s
location = Location.new(city: track_event_node.elements['EventCity'].get_text.to_s,
state: track_event_node.elements['EventState'].get_text.to_s,
postal_code: track_event_node.elements['EventZIPCode'].get_text.to_s,
country: country)
event = ShipmentEvent.new(status_name, zoneless_datetime, location)
else
zoneless_datetime = default_event_time
end

country = !!track_event_node.elements['EventCountry'] || track_event_node.elements['EventCountry'].blank? ? 'USA' : track_event_node.elements['EventCountry'].get_text.to_s

location = Location.new(city: track_event_node.elements['EventCity'].get_text.to_s,
state: track_event_node.elements['EventState'].get_text.to_s,
postal_code: track_event_node.elements['EventZIPCode'].get_text.to_s,
country: country)
event = ShipmentEvent.new(status_name, zoneless_datetime, location)

event
end

Expand Down
2 changes: 2 additions & 0 deletions lib/active_shipping/shipping/tracking_response.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class TrackingResponse < Response
attr_reader :status # symbol
attr_reader :status_code # string
attr_reader :status_description #string
attr_reader :status_category #symbol
attr_reader :ship_time # time
attr_reader :scheduled_delivery_date # time
attr_reader :actual_delivery_date # time
Expand All @@ -21,6 +22,7 @@ def initialize(success, message, params = {}, options = {})
@status = options[:status]
@status_code = options[:status_code]
@status_description = options[:status_description]
@status_category = options[:status_category]
@ship_time = options[:ship_time]
@scheduled_delivery_date = options[:scheduled_delivery_date]
@actual_delivery_date = options[:actual_delivery_date]
Expand Down
2 changes: 1 addition & 1 deletion lib/active_shipping/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module ActiveShipping
VERSION = "0.16.0goodmouth"
VERSION = "0.17.0goodmouth"
end
3 changes: 2 additions & 1 deletion test/fixtures.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
usps:
login: APIKey
login: ApiKey
ip_address: 141.214.14.1
ups:
key: XmlAccessKey
login: UPSDotComLogin
Expand Down
11 changes: 8 additions & 3 deletions test/remote/usps_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ def setup

def test_tracking
assert_nothing_raised do
@carrier.find_tracking_info('9400110200882182234434', :test => true)
response = @carrier.find_tracking_info('9400110200881506616178', :test => true)
end
end

def test_tracking_w_fields
assert_nothing_raised do
response = @carrier.find_tracking_info_with_fields(['9400110200882182234434'], :test => true).first
puts response.xml
response = @carrier.find_tracking_info_with_fields(['9400110200881506616178'], :test => true).first
end
end

Expand All @@ -33,6 +32,12 @@ def test_tracking_w_field_with_bad_number
end
end

def test_tracking_for_no_status_time
assert_nothing_raised do
response = @carrier.find_tracking_info_with_fields(['9400110200882472687667'])
end
end

def test_zip_to_zip
assert_nothing_raised do
response = @carrier.find_rates(
Expand Down
4 changes: 3 additions & 1 deletion test/unit/carriers/usps_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ def test_find_tracking_info_w_fields_should_return_a_tracking_response
@carrier.expects(:commit).returns(@tracking_w_fields_response)
assert_instance_of ActiveMerchant::Shipping::TrackingResponse, @carrier.find_tracking_info_with_fields(['9102901000462189604217'], :test => true).first
@carrier.expects(:commit).returns(@tracking_w_fields_response)
assert_equal 'ActiveMerchant::Shipping::TrackingResponse', @carrier.find_tracking_info_with_fields(['EJ958083578US']).first.class.name
response = @carrier.find_tracking_info_with_fields(['EJ958083578US'])
assert_equal 'ActiveMerchant::Shipping::TrackingResponse', response.first.class.name
assert_equal :delivered, response.first.status_category
end

def test_find_tracking_info_should_parse_response_into_correct_number_of_shipment_events
Expand Down

0 comments on commit 89c408c

Please sign in to comment.