lib/active_shipping/carriers/usps.rb in active_shipping-1.0.1 vs lib/active_shipping/carriers/usps.rb in active_shipping-1.1.0
- old
+ new
@@ -8,15 +8,12 @@
# usps.valid_credentials?
#
# This will send a test request to the USPS test servers, which they ask you
# to do before they put your API key in production mode.
class USPS < Carrier
- EventDetails = Struct.new(:description, :time, :zoneless_time, :location)
- EVENT_MESSAGE_PATTERNS = [
- /^(.*), (\w+ \d{1,2}, \d{4}, \d{1,2}:\d\d [ap]m), (.*), (\w\w) (\d{5})$/i,
- /^Your item \w{2,3} (out for delivery|delivered).* at (\d{1,2}:\d\d [ap]m on \w+ \d{1,2}, \d{4}) in (.*), (\w\w) (\d{5})\.$/i
- ]
+ EventDetails = Struct.new(:description, :time, :zoneless_time, :location, :event_code)
+ ONLY_PREFIX_EVENTS = ['DELIVERED','OUT FOR DELIVERY']
self.retry_safe = true
cattr_reader :name
@@name = "USPS"
@@ -230,30 +227,48 @@
def maximum_weight
Mass.new(70, :pounds)
end
- def extract_event_details(message)
- return EventDetails.new unless EVENT_MESSAGE_PATTERNS.any? { |pattern| message =~ pattern }
- description = $1.upcase
- timestamp = $2
- city = $3
- state = $4
- zip_code = $5
+ def extract_event_details(node)
+ description = node.at('Event').text.upcase
+ if prefix = ONLY_PREFIX_EVENTS.find { |p| description.starts_with?(p) }
+ description = prefix
+ end
+
+ timestamp = "#{node.at('EventDate').text}, #{node.at('EventTime').text}"
+ event_code = node.at('EventCode').text
+ city = node.at('EventCity').text
+ state = node.at('EventState').text
+ zip_code = node.at('EventZIPCode').text
+
+ country_node = node.at('EventCountry')
+ country = country_node ? country_node.text : ''
+ country = 'USA' if country.empty?
+
time = Time.parse(timestamp)
zoneless_time = Time.utc(time.year, time.month, time.mday, time.hour, time.min, time.sec)
- location = Location.new(city: city, state: state, postal_code: zip_code, country: 'USA')
- EventDetails.new(description, time, zoneless_time, location)
+ location = Location.new(city: city, state: state, postal_code: zip_code, country: country)
+ EventDetails.new(description, time, zoneless_time, location, event_code)
end
protected
def build_tracking_request(tracking_number, options = {})
xml_builder = Nokogiri::XML::Builder.new do |xml|
- xml.TrackRequest('USERID' => @options[:login]) do
- xml.TrackID('ID' => tracking_number)
+ xml.TrackFieldRequest('USERID' => @options[:login]) do
+ xml.Revision { xml.text('1') }
+ xml.ClientIp { xml.text(@options[:client_ip] || '127.0.0.1') }
+ xml.SourceId { xml.text(@options[:source_id] || 'active_shipping') }
+ xml.TrackID('ID' => tracking_number) do
+ xml.DestinationZipCode { xml.text(@options[:destination_zip])} if @options[:destination_zip]
+ if @options[:mailing_date]
+ formatted_date = @options[:mailing_date].strftime('%Y-%m-%d')
+ xml.MailingDate { xml.text(formatted_date)}
+ end
+ end
end
end
xml_builder.to_xml
end
@@ -527,33 +542,29 @@
end
def parse_tracking_response(response, options)
actual_delivery_date, status = nil
xml = Nokogiri.XML(response)
- root_node = xml.root
success = response_success?(xml)
message = response_message(xml)
if success
destination = nil
shipment_events = []
tracking_details = xml.root.xpath('TrackInfo/TrackDetail')
+ tracking_details << xml.root.at('TrackInfo/TrackSummary')
- tracking_summary = xml.root.at('TrackInfo/TrackSummary')
- if tracking_details.length > 0
- tracking_details << tracking_summary
- else
- success = false
- message = tracking_summary.text
- end
-
tracking_number = xml.root.at('TrackInfo').attributes['ID'].value
+ scheduled_delivery = Time.parse(xml.root.at('PredictedDeliveryDate').text)
tracking_details.each do |event|
- details = extract_event_details(event.text)
- shipment_events << ShipmentEvent.new(details.description, details.zoneless_time, details.location) if details.location
+ details = extract_event_details(event)
+ if details.location
+ shipment_events << ShipmentEvent.new(details.description, details.zoneless_time,
+ details.location, details.description, details.event_code)
+ end
end
shipment_events = shipment_events.sort_by(&:time)
if last_shipment = shipment_events.last
@@ -568,15 +579,16 @@
:request => last_request,
:shipment_events => shipment_events,
:destination => destination,
:tracking_number => tracking_number,
:status => status,
- :actual_delivery_date => actual_delivery_date
+ :actual_delivery_date => actual_delivery_date,
+ :scheduled_delivery_date => scheduled_delivery
)
end
def track_summary_node(document)
- document.root.xpath('TrackInfo/TrackSummary')
+ document.root.xpath('TrackInfo/StatusSummary')
end
def error_description_node(document)
STATUS_NODE_PATTERNS.each do |pattern|
if node = document.elements[pattern]