Skip to content

Commit

Permalink
Add tracking support for all services.
Browse files Browse the repository at this point in the history
  • Loading branch information
wisq committed Aug 23, 2010
1 parent c37988e commit 2094c29
Show file tree
Hide file tree
Showing 14 changed files with 325 additions and 17 deletions.
55 changes: 52 additions & 3 deletions lib/active_fulfillment/fulfillment/services/amazon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ class AmazonService < Service
:outbound => {
:status => 'GetServiceStatus',
:create => 'CreateFulfillmentOrder',
:list => 'ListAllFulfillmentOrders'
:list => 'ListAllFulfillmentOrders',
:tracking => 'GetFulfillmentOrder'
},
:inventory => {
:get => 'GetInventorySupply',
Expand Down Expand Up @@ -113,6 +114,26 @@ def fetch_stock_levels(options = {})
response
end
end

def fetch_tracking_numbers(order_ids, options = {})
order_ids.inject(nil) do |previous, o_id|
response = commit :outbound, :tracking, build_tracking_request(o_id, options)

if !response.success?
if response.faultstring =~ /Reason: requested order not found./
response = Response.new(true, nil, {
:status => SUCCESS,
:tracking_numbers => {}
})
else
return response
end
end

response.tracking_numbers.merge!(previous.tracking_numbers) if previous
response
end
end

def valid_credentials?
status.success?
Expand Down Expand Up @@ -202,6 +223,15 @@ def build_next_inventory_list_request(token)
end
end

def build_tracking_request(order_id, options)
request = OPERATIONS[:outbound][:tracking]
soap_request(request) do |xml|
xml.tag! request, { 'xmlns' => SERVICES[:outbound][:xmlns] } do
xml.tag! "MerchantFulfillmentOrderId", order_id
end
end
end

def add_credentials(xml, request)
login = @options[:login]
timestamp = "#{Time.now.utc.strftime("%Y-%m-%dT%H:%M:%S")}Z"
Expand Down Expand Up @@ -264,7 +294,12 @@ def parse_response(service, op, xml)

case service
when :outbound
parse_fulfillment_response(op, document)
case op
when :tracking
parse_tracking_response(document)
else
parse_fulfillment_response(op, document)
end
when :inventory
parse_inventory_response(document)
else
Expand All @@ -288,7 +323,7 @@ def parse_inventory_response(document)

document.each_element('//ns1:MerchantSKUSupply') do |node|
# {MerchantSKU => 'SOME-ID', InStockSupplyQuantity => '101', ...}
params = node.elements.to_a.inject(Hash.new) {|h, k| h[k.name] = k.text; h}
params = node.elements.to_a.each_with_object({}) {|elem, hash| hash[elem.name] = elem.text}

response[:stock_levels][params['MerchantSKU']] = params['InStockSupplyQuantity'].to_i
end
Expand All @@ -300,6 +335,20 @@ def parse_inventory_response(document)
response
end

def parse_tracking_response(document)
response = {}
response[:tracking_numbers] = {}

track_node = REXML::XPath.first(document, '//ns1:FulfillmentShipmentPackage/ns1:TrackingNumber')
if track_node
id_node = REXML::XPath.first(document, '//ns1:MerchantFulfillmentOrderId')
response[:tracking_numbers][id_node.text] = track_node.text
end

response[:response_status] = SUCCESS
response
end

def parse_error(http_response)
response = {}
response[:http_code] = http_response.code
Expand Down
12 changes: 7 additions & 5 deletions lib/active_fulfillment/fulfillment/services/shipwire.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ def fetch_stock_levels(options = {})
commit :inventory, build_inventory_request(options)
end

def fetch_tracking_numbers(options = {})
commit :tracking, build_tracking_request(options)
def fetch_tracking_numbers(order_ids)
commit :tracking, build_tracking_request(order_ids)
end

def valid_credentials?
response = fetch_tracking_numbers
response = fetch_tracking_numbers([])
response.message !~ INVALID_LOGIN
end

Expand Down Expand Up @@ -91,14 +91,16 @@ def build_inventory_request(options)
end
end

def build_tracking_request(options)
def build_tracking_request(order_ids)
xml = Builder::XmlMarkup.new
xml.instruct!
xml.declare! :DOCTYPE, :InventoryStatus, :SYSTEM, SCHEMA_URLS[:inventory]
xml.tag! 'TrackingUpdate' do
add_credentials(xml)
xml.tag! 'Server', test? ? 'Test' : 'Production'
xml.tag! 'Bookmark', '3'
order_ids.each do |o_id|
xml.tag! 'OrderNo', o_id
end
end
end

Expand Down
55 changes: 52 additions & 3 deletions lib/active_fulfillment/fulfillment/services/webgistix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module Fulfillment
class WebgistixService < Service
SERVICE_URLS = {
:fulfillment => 'https://www.webgistix.com/XML/CreateOrder.asp',
:inventory => 'https://www.webgistix.com/XML/GetInventory.asp'
:inventory => 'https://www.webgistix.com/XML/GetInventory.asp',
:tracking => 'https://www.webgistix.com/XML/GetTracking.asp'
}
TEST_URLS = SERVICE_URLS.merge({
:fulfillment => 'https://www.webgistix.com/XML/CreateOrderTest.asp'
Expand All @@ -13,6 +14,7 @@ class WebgistixService < Service
SUCCESS_MESSAGE = 'Successfully submitted the order'
FAILURE_MESSAGE = 'Failed to submit the order'
INVALID_LOGIN = 'Access Denied'
NOT_SHIPPED = 'Not Shipped'

# The first is the label, and the last is the code
def self.shipping_methods
Expand Down Expand Up @@ -65,6 +67,10 @@ def fulfill(order_id, shipping_address, line_items, options = {})
def fetch_stock_levels(options = {})
commit :inventory, build_inventory_request(options)
end

def fetch_tracking_numbers(order_ids, options = {})
commit :tracking, build_tracking_request(order_ids, options)
end

def valid_credentials?
response = fulfill('', {}, [], :shipping_method => '')
Expand Down Expand Up @@ -124,7 +130,32 @@ def build_inventory_request(options)
add_credentials(xml)
end
end


#<?xml version="1.0"?>
# <TrackingXML>
# <Password>Webgistix</Password>
# <CustomerID>3</CustomerID>
# <Tracking>
# <Order>AB12345</Order>
# </Tracking>
# <Tracking>
# <Order>XY4567</Order>
# </Tracking>
# </TrackingXML>
def build_tracking_request(order_ids, options)
xml = Builder::XmlMarkup.new :indent => 2
xml.instruct!
xml.tag! 'TrackingXML' do
add_credentials(xml)

order_ids.each do |o_id|
xml.tag! 'Tracking' do
xml.tag! 'Order', o_id
end
end
end
end

def add_credentials(xml)
xml.tag! 'CustomerID', @options[:login]
xml.tag! 'Password', @options[:password]
Expand Down Expand Up @@ -209,6 +240,8 @@ def parse_response(action, xml)
parse_fulfillment_response(document)
when :inventory
parse_inventory_response(document)
when :tracking
parse_tracking_response(document)
else
raise ArgumentError, "Unknown action #{action}"
end
Expand Down Expand Up @@ -240,14 +273,30 @@ def parse_inventory_response(document)

document.root.each_element('//Item') do |node|
# {ItemID => 'SOME-ID', ItemQty => '101'}
params = node.elements.to_a.inject(Hash.new) {|h, k| h[k.name] = k.text; h}
params = node.elements.to_a.each_with_object({}) {|elem, hash| hash[elem.name] = elem.text}

response[:stock_levels][params['ItemID']] = params['ItemQty'].to_i
end

response[:success] = SUCCESS
response
end

def parse_tracking_response(document)
response = {}
response[:tracking_numbers] = {}

document.root.each_element('//Shipment') do |node|
# {InvoiceNumber => 'SOME-ID', ShipmentTrackingNumber => 'SOME-TRACKING-NUMBER'}
params = node.elements.to_a.each_with_object({}) {|elem, hash| hash[elem.name] = elem.text}

tracking = params['ShipmentTrackingNumber']
response[:tracking_numbers][params['InvoiceNumber']] = tracking unless tracking == NOT_SHIPPED
end

response[:success] = SUCCESS
response
end
end
end
end
Expand Down
56 changes: 56 additions & 0 deletions test/fixtures/xml/amazon/tracking_response_1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:GetFulfillmentOrderResponse
xmlns:ns1="http://fba-outbound.amazonaws.com/doc/2007-08-02/">
<ns1:GetFulfillmentOrderResult>
<ns1:FulfillmentOrder>
<ns1:MerchantFulfillmentOrderId>TEST-00000001</ns1:MerchantFulfillmentOrderId>
<ns1:ReceivedDateTime>2007-08-02T08:00:00Z</ns1:ReceivedDateTime>
<ns1:ShippingSpeedCategory>Standard</ns1:ShippingSpeedCategory>
<ns1:DisplayableOrderDateTime>2007-08-02T00:00:00Z</ns1:DisplayableOrderDateTime>
<ns1:DisplayableOrderComment>Thank you for your order!</ns1:DisplayableOrderComment>
<ns1:DisplayableOrderId>TEST-00000001</ns1:DisplayableOrderId>
<ns1:DestinationAddress>
<ns1:Name>John Smith</ns1:Name>
<ns1:Line1>2412 25th Ave NW.</ns1:Line1>
<ns1:City>Seattle</ns1:City>
<ns1:StateOrProvinceCode>WA</ns1:StateOrProvinceCode>
<ns1:CountryCode>US</ns1:CountryCode>
<ns1:PostalCode>98104</ns1:PostalCode>
<ns1:PhoneNumber>206-266-1000</ns1:PhoneNumber>
</ns1:DestinationAddress>
<ns1:FulfillmentOrderStatus>Complete</ns1:FulfillmentOrderStatus>
<ns1:StatusUpdatedDateTime>2007-08-03T16:00:00Z</ns1:StatusUpdatedDateTime>
</ns1:FulfillmentOrder>
<ns1:FulfillmentOrderItem>
<ns1:MerchantSKU>MSKU-00000001</ns1:MerchantSKU>
<ns1:MerchantFulfillmentOrderItemId>TEST-00000001-1</ns1:MerchantFulfillmentOrderItemId>
<ns1:Quantity>2</ns1:Quantity>
<ns1:CancelledQuantity>0</ns1:CancelledQuantity>
<ns1:UnfulfillableQuantity>0</ns1:UnfulfillableQuantity>
</ns1:FulfillmentOrderItem>
<ns1:FulfillmentShipment>
<ns1:AmazonShipmentId>TEST00000001</ns1:AmazonShipmentId>
<ns1:FulfillmentCenterId>TST1</ns1:FulfillmentCenterId>
<ns1:FulfillmentShipmentStatus>Shipped</ns1:FulfillmentShipmentStatus>
<ns1:ShippingDateTime>2007-08-03T16:00:00Z</ns1:ShippingDateTime>
<ns1:EstimatedArrivalDateTime>2007-08-10T16:00:00Z</ns1:EstimatedArrivalDateTime>
<ns1:FulfillmentShipmentItem>
<ns1:MerchantSKU>MSKU-00000001</ns1:MerchantSKU>
<ns1:MerchantFulfillmentOrderItemId>TEST-00000001-1</ns1:MerchantFulfillmentOrderItemId>
<ns1:Quantity>2</ns1:Quantity>
<ns1:PackageNumber>1</ns1:PackageNumber>
</ns1:FulfillmentShipmentItem>
<ns1:FulfillmentShipmentPackage>
<ns1:PackageNumber>1</ns1:PackageNumber>
<ns1:CarrierCode>UPS</ns1:CarrierCode>
<ns1:TrackingNumber>UPS00000001</ns1:TrackingNumber>
</ns1:FulfillmentShipmentPackage>
</ns1:FulfillmentShipment>
</ns1:GetFulfillmentOrderResult>
<ns1:ResponseMetadata>
<ns1:RequestId>963215ec-bec6-4ae0-84e0-19f5823ee33a</ns1:RequestId>
</ns1:ResponseMetadata>
</ns1:GetFulfillmentOrderResponse>
</soapenv:Body>
</soapenv:Envelope>
38 changes: 38 additions & 0 deletions test/fixtures/xml/amazon/tracking_response_2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Body>
<ns1:GetFulfillmentOrderResponse
xmlns:ns1="http://fba-outbound.amazonaws.com/doc/2007-08-02/">
<ns1:GetFulfillmentOrderResult>
<ns1:FulfillmentOrder>
<ns1:MerchantFulfillmentOrderId>TEST-00000002</ns1:MerchantFulfillmentOrderId>
<ns1:ReceivedDateTime>2007-08-02T08:00:00Z</ns1:ReceivedDateTime>
<ns1:ShippingSpeedCategory>Standard</ns1:ShippingSpeedCategory>
<ns1:DisplayableOrderDateTime>2007-08-02T00:00:00Z</ns1:DisplayableOrderDateTime>
<ns1:DisplayableOrderComment>Thank you for your order!</ns1:DisplayableOrderComment>
<ns1:DisplayableOrderId>TEST-00000001</ns1:DisplayableOrderId>
<ns1:DestinationAddress>
<ns1:Name>John Smith</ns1:Name>
<ns1:Line1>2412 25th Ave NW.</ns1:Line1>
<ns1:City>Seattle</ns1:City>
<ns1:StateOrProvinceCode>WA</ns1:StateOrProvinceCode>
<ns1:CountryCode>US</ns1:CountryCode>
<ns1:PostalCode>98104</ns1:PostalCode>
<ns1:PhoneNumber>206-266-1000</ns1:PhoneNumber>
</ns1:DestinationAddress>
<ns1:FulfillmentOrderStatus>Complete</ns1:FulfillmentOrderStatus>
<ns1:StatusUpdatedDateTime>2007-08-03T16:00:00Z</ns1:StatusUpdatedDateTime>
</ns1:FulfillmentOrder>
<ns1:FulfillmentOrderItem>
<ns1:MerchantSKU>MSKU-00000001</ns1:MerchantSKU>
<ns1:MerchantFulfillmentOrderItemId>TEST-00000001-1</ns1:MerchantFulfillmentOrderItemId>
<ns1:Quantity>2</ns1:Quantity>
<ns1:CancelledQuantity>0</ns1:CancelledQuantity>
<ns1:UnfulfillableQuantity>0</ns1:UnfulfillableQuantity>
</ns1:FulfillmentOrderItem>
</ns1:GetFulfillmentOrderResult>
<ns1:ResponseMetadata>
<ns1:RequestId>963215ec-bec6-4ae0-84e0-19f5823ee33a</ns1:RequestId>
</ns1:ResponseMetadata>
</ns1:GetFulfillmentOrderResponse>
</soapenv:Body>
</soapenv:Envelope>
13 changes: 13 additions & 0 deletions test/fixtures/xml/amazon/tracking_response_error.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:aws="http://webservices.amazon.com/AWSFault/2005-15-09">
<env:Body>
<env:Fault>
<faultcode>aws:Client.UnknownError</faultcode>
<faultstring>Something bad happened!</faultstring>
<detail>
<aws:RequestId xmlns:aws="http://webservices.amazon.com/AWSFault/2005-15-09">145b969c-23ec-41e4-a552-30e57fc2684f</aws:RequestId>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>
13 changes: 13 additions & 0 deletions test/fixtures/xml/amazon/tracking_response_not_found.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:aws="http://webservices.amazon.com/AWSFault/2005-15-09">
<env:Body>
<env:Fault>
<faultcode>aws:Client.InvalidParameterValue</faultcode>
<faultstring>Value #1337-1 for parameter MerchantFulfillmentOrderId is invalid. Reason: requested order not found.</faultstring>
<detail>
<aws:RequestId xmlns:aws="http://webservices.amazon.com/AWSFault/2005-15-09">145b969c-23ec-41e4-a552-30e57fc2684f</aws:RequestId>
</detail>
</env:Fault>
</env:Body>
</env:Envelope>
14 changes: 14 additions & 0 deletions test/fixtures/xml/webgistix/tracking_response.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<Orders>
<Shipment>
<InvoiceNumber>AB12345</InvoiceNumber>
<WebgistixOrderNumber>67891</WebgistixOrderNumber>
<Method>UPS Ground</Method>
<DateShipped>10/25/2009</DateShipped>
<ShipmentTrackingNumber>1Z8E5A380396682872</ShipmentTrackingNumber>
</Shipment>
<Shipment>
<InvoiceNumber>XY4567</InvoiceNumber>
<ShipmentTrackingNumber>Not Shipped</ShipmentTrackingNumber>
</Shipment>
</Orders>
12 changes: 12 additions & 0 deletions test/remote/amazon_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,18 @@ def test_list_inventory
assert_equal 0, response.stock_levels['SETTLERS']
end

def test_fetch_tracking_numbers
response = @service.fetch_tracking_numbers(['123456']) # an actual order
assert response.success?
assert_equal Hash.new, response.tracking_numbers # no tracking numbers in testing
end

def test_fetch_tracking_numbers_ignores_not_found
response = @service.fetch_tracking_numbers(['#1337-1'])
assert response.success?
assert_equal Hash.new, response.tracking_numbers
end

def test_valid_credentials
assert @service.valid_credentials?
end
Expand Down
Loading

0 comments on commit 2094c29

Please sign in to comment.