Skip to content
This repository has been archived by the owner on Jun 13, 2018. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
sometimes fedex gives us a transit time in words and no delivery time…
…stamp. in this case, we parse the transit time and calculate a delivery date range from that.
  • Loading branch information
orenmazor committed Nov 22, 2012
1 parent 3e5b411 commit 57cc101
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 5 deletions.
33 changes: 30 additions & 3 deletions lib/active_shipping/shipping/carriers/fedex.rb
@@ -1,6 +1,7 @@
# FedEx module by Jimmy Baker
# http://github.com/jimmyebaker

require 'date'
module ActiveMerchant
module Shipping

Expand Down Expand Up @@ -85,6 +86,9 @@ class FedEx < Carrier
'express_mps_master' => 'EXPRESS_MPS_MASTER'
}


TransitTimes = ["UNKNOWN","ONE_DAYS","TWO_DAYS","THREE_DAYS","FOUR_DAYS","FIVE_DAYS","SIX_DAYS","SEVEN_DAYS","EIGHT_DAYS","NINE_DAYS","TEN_DAYS","ELEVEN_DAYS","TWELVE_DAYS","THIRTEEN_DAYS","FOURTEEN_DAYS","FIFTEEN_DAYS","SIXTEEN_DAYS","SEVENTEEN_DAYS","EIGHTEEN_DAYS"]

# FedEx tracking codes as described in the FedEx Tracking Service WSDL Guide
# All delays also have been marked as exceptions
TRACKING_STATUS_CODES = HashWithIndifferentAccess.new({
Expand Down Expand Up @@ -136,7 +140,7 @@ def find_rates(origin, destination, packages, options = {})
rate_request = build_rate_request(origin, destination, packages, options)

response = commit(save_request(rate_request), (options[:test] || false)).gsub(/<(\/)?.*?\:(.*?)>/, '<\1\2>')

parse_rate_response(origin, destination, packages, response, options)
end

Expand Down Expand Up @@ -272,15 +276,29 @@ def parse_rate_response(origin, destination, packages, response, options)
is_saturday_delivery = rated_shipment.get_text('AppliedOptions').to_s == 'SATURDAY_DELIVERY'
service_type = is_saturday_delivery ? "#{service_code}_SATURDAY_DELIVERY" : service_code

transit_time = rated_shipment.get_text('TransitTime').to_s if service_code == "FEDEX_GROUND"
max_transit_time = rated_shipment.get_text('MaximumTransitTime').to_s if service_code == "FEDEX_GROUND"

delivery_timestamp = rated_shipment.get_text('DeliveryTimestamp').to_s

delivery_range = []
#if there's no delivery timestamp but we do have a transit time, use it
if delivery_timestamp.blank? and transit_time.present?
transit_range = parse_transit_times([transit_time,max_transit_time.presence || transit_time])
delivery_range = [Date.today + transit_range[0], Date.today + transit_range[1]]
else
delivery_range = [delivery_timestamp,delivery_timestamp]
end

currency = handle_incorrect_currency_codes(rated_shipment.get_text('RatedShipmentDetails/ShipmentRateDetail/TotalNetCharge/Currency').to_s)
rate_estimates << RateEstimate.new(origin, destination, @@name,
self.class.service_name_for_code(service_type),
:service_code => service_code,
:total_price => rated_shipment.get_text('RatedShipmentDetails/ShipmentRateDetail/TotalNetCharge/Amount').to_s.to_f,
:currency => currency,
:packages => packages,
:delivery_range => [rated_shipment.get_text('DeliveryTimestamp').to_s] * 2)
end
:delivery_range => delivery_range)
end

if rate_estimates.empty?
success = false
Expand Down Expand Up @@ -390,6 +408,15 @@ def handle_incorrect_currency_codes(currency)
else currency
end
end

def parse_transit_times(times)
results = []
times.each do |day_count|
days = TransitTimes.index(day_count.to_s.chomp)
results << days.to_i
end
results
end
end
end
end
6 changes: 4 additions & 2 deletions test/fixtures.yml
Expand Up @@ -5,9 +5,11 @@ ups:
login: UPSDotComLogin
password: UPSDotComPassword
fedex:
login: FedExAccountNumber
password: FedExMeterNumber
account: FedExAccountNumber
login: FedExMeterNumber
password: FedExMeterPassword
test: true
key: FedExDeveloperKey
shipwire:
login: EmailAddress
password: Password
Expand Down
213 changes: 213 additions & 0 deletions test/fixtures/xml/fedex/raterequest_reply.xml
@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<v6:RateReply xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v6="http://fedex.com/ws/rate/v6">
<v6:HighestSeverity>WARNING</v6:HighestSeverity>
<v6:Notifications>
<v6:Severity>WARNING</v6:Severity>
<v6:Source>crs</v6:Source>
<v6:Code>872</v6:Code>
<v6:Message>Rating is temporarily unavailable for one or more services:
INTERNATIONAL_FIRST; INTERNATIONAL_PRIORITY; INTERNATIONAL_ECONOMY; ; ; ; ; ; ; ; . Please try again later. </v6:Message>
<v6:LocalizedMessage>Rating is temporarily unavailable for one or more services:
INTERNATIONAL_FIRST; INTERNATIONAL_PRIORITY; INTERNATIONAL_ECONOMY; ; ; ; ; ; ; ; . Please try again later. </v6:LocalizedMessage>
<v6:MessageParameters>
<v6:Id>SERVICE_TYPE_1</v6:Id>
<v6:Value>INTERNATIONAL_FIRST</v6:Value>
</v6:MessageParameters>
<v6:MessageParameters>
<v6:Id>SERVICE_TYPE_2</v6:Id>
<v6:Value>INTERNATIONAL_PRIORITY</v6:Value>
</v6:MessageParameters>
<v6:MessageParameters>
<v6:Id>SERVICE_TYPE_3</v6:Id>
<v6:Value>INTERNATIONAL_ECONOMY</v6:Value>
</v6:MessageParameters>
</v6:Notifications>
<v6:Notifications>
<v6:Severity>NOTE</v6:Severity>
<v6:Source>crs</v6:Source>
<v6:Code>886</v6:Code>
<v6:Message>Money Back Guarantee is not eligible for this pick up/delivery postal/zip code</v6:Message>
<v6:LocalizedMessage>Money Back Guarantee is not eligible for this pick up/delivery postal/zip code</v6:LocalizedMessage>
</v6:Notifications>
<v6:TransactionDetail>
<v6:CustomerTransactionId>ActiveShipping</v6:CustomerTransactionId>
</v6:TransactionDetail>
<v6:Version>
<v6:ServiceId>crs</v6:ServiceId>
<v6:Major>6</v6:Major>
<v6:Intermediate>0</v6:Intermediate>
<v6:Minor>0</v6:Minor>
</v6:Version>
<v6:RateReplyDetails>
<v6:ServiceType>FEDEX_GROUND</v6:ServiceType>
<v6:PackagingType>YOUR_PACKAGING</v6:PackagingType>
<v6:DeliveryStation>CCDA </v6:DeliveryStation>
<v6:CommitDetails>
<v6:ServiceType>FEDEX_GROUND</v6:ServiceType>
<v6:TransitTime>FIVE_DAYS</v6:TransitTime>
<v6:BrokerToDestinationDays>0</v6:BrokerToDestinationDays>
</v6:CommitDetails>
<v6:DestinationAirportId>LAX</v6:DestinationAirportId>
<v6:IneligibleForMoneyBackGuarantee>true</v6:IneligibleForMoneyBackGuarantee>
<v6:OriginServiceArea>A1</v6:OriginServiceArea>
<v6:DestinationServiceArea>A1</v6:DestinationServiceArea>
<v6:TransitTime>FIVE_DAYS</v6:TransitTime>
<v6:SignatureOption>SERVICE_DEFAULT</v6:SignatureOption>
<v6:ActualRateType>PAYOR_ACCOUNT</v6:ActualRateType>
<v6:RatedShipmentDetails>
<v6:ShipmentRateDetail>
<v6:RateType>PAYOR_ACCOUNT</v6:RateType>
<v6:RateZone>53</v6:RateZone>
<v6:DimDivisor>0</v6:DimDivisor>
<v6:FuelSurchargePercent>5.25</v6:FuelSurchargePercent>
<v6:TotalBillingWeight>
<v6:Units>LB</v6:Units>
<v6:Value>10.0</v6:Value>
</v6:TotalBillingWeight>
<v6:TotalBaseCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>36.45</v6:Amount>
</v6:TotalBaseCharge>
<v6:TotalFreightDiscounts>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalFreightDiscounts>
<v6:TotalNetFreight>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>36.45</v6:Amount>
</v6:TotalNetFreight>
<v6:TotalSurcharges>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>1.91</v6:Amount>
</v6:TotalSurcharges>
<v6:TotalNetFedExCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>38.36</v6:Amount>
</v6:TotalNetFedExCharge>
<v6:TotalTaxes>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalTaxes>
<v6:TotalNetCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>38.36</v6:Amount>
</v6:TotalNetCharge>
<v6:TotalRebates>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalRebates>
<v6:Surcharges>
<v6:SurchargeType>FUEL</v6:SurchargeType>
<v6:Level>PACKAGE</v6:Level>
<v6:Description>FedEx Ground Fuel</v6:Description>
<v6:Amount>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>1.91</v6:Amount>
</v6:Amount>
</v6:Surcharges>
</v6:ShipmentRateDetail>
<v6:RatedPackages>
<v6:PackageRateDetail>
<v6:RateType>PAYOR_ACCOUNT</v6:RateType>
<v6:RatedWeightMethod>ACTUAL</v6:RatedWeightMethod>
<v6:BillingWeight>
<v6:Units>KG</v6:Units>
<v6:Value>1.0</v6:Value>
</v6:BillingWeight>
<v6:BaseCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>14.31</v6:Amount>
</v6:BaseCharge>
<v6:TotalFreightDiscounts>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalFreightDiscounts>
<v6:NetFreight>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>14.31</v6:Amount>
</v6:NetFreight>
<v6:TotalSurcharges>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.75</v6:Amount>
</v6:TotalSurcharges>
<v6:NetFedExCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>15.06</v6:Amount>
</v6:NetFedExCharge>
<v6:TotalTaxes>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalTaxes>
<v6:NetCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>15.06</v6:Amount>
</v6:NetCharge>
<v6:TotalRebates>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalRebates>
<v6:Surcharges>
<v6:SurchargeType>FUEL</v6:SurchargeType>
<v6:Level>PACKAGE</v6:Level>
<v6:Description>FedEx Ground Fuel</v6:Description>
<v6:Amount>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.75</v6:Amount>
</v6:Amount>
</v6:Surcharges>
</v6:PackageRateDetail>
</v6:RatedPackages>
<v6:RatedPackages>
<v6:PackageRateDetail>
<v6:RateType>PAYOR_ACCOUNT</v6:RateType>
<v6:RatedWeightMethod>ACTUAL</v6:RatedWeightMethod>
<v6:BillingWeight>
<v6:Units>KG</v6:Units>
<v6:Value>4.0</v6:Value>
</v6:BillingWeight>
<v6:BaseCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>22.14</v6:Amount>
</v6:BaseCharge>
<v6:TotalFreightDiscounts>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalFreightDiscounts>
<v6:NetFreight>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>22.14</v6:Amount>
</v6:NetFreight>
<v6:TotalSurcharges>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>1.16</v6:Amount>
</v6:TotalSurcharges>
<v6:NetFedExCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>23.3</v6:Amount>
</v6:NetFedExCharge>
<v6:TotalTaxes>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalTaxes>
<v6:NetCharge>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>23.3</v6:Amount>
</v6:NetCharge>
<v6:TotalRebates>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>0.0</v6:Amount>
</v6:TotalRebates>
<v6:Surcharges>
<v6:SurchargeType>FUEL</v6:SurchargeType>
<v6:Level>PACKAGE</v6:Level>
<v6:Description>FedEx Ground Fuel</v6:Description>
<v6:Amount>
<v6:Currency>CAD</v6:Currency>
<v6:Amount>1.16</v6:Amount>
</v6:Amount>
</v6:Surcharges>
</v6:PackageRateDetail>
</v6:RatedPackages>
</v6:RatedShipmentDetails>
</v6:RateReplyDetails>
</v6:RateReply>
14 changes: 14 additions & 0 deletions test/unit/carriers/fedex_test.rb
Expand Up @@ -204,4 +204,18 @@ def test_delivery_range_based_on_delivery_date
assert_equal delivery_date, rate_estimates.rates[0].delivery_date
assert_equal [delivery_date] * 2, rate_estimates.rates[0].delivery_range
end

def test_delivery_date_from_transit_time
mock_response = xml_fixture('fedex/raterequest_reply').gsub('CAD', 'UKL')

@carrier.expects(:commit).returns(mock_response)
rate_estimates = @carrier.find_rates( @locations[:ottawa],
@locations[:beverly_hills],
@packages.values_at(:book, :wii), :test => true)

#the above fixture will specify a transit time of 5 days
delivery_date = Date.today + 5
assert_equal delivery_date, rate_estimates.rates[0].delivery_date
end

end

0 comments on commit 57cc101

Please sign in to comment.