Class: Shipping::PackageShipmentTracking

Inherits:
BaseService show all
Defined in:
app/services/shipping/package_shipment_tracking.rb

Defined Under Namespace

Classes: Result

Constant Summary collapse

TRACKING_STATUS_CODES =

status_code
Value Description
UN Unknown
AC Accepted
IT In Transit
DE Delivered
EX Exception
AT Delivery Attempt
NY Not Yet In System
SP Delivered To Collection Location

{
  UN: 'unknown',
  AC: 'accepted',
  IT: 'in_transit',
  DE: 'delivered',
  EX: 'exception',
  AT: 'delivery_attempt',
  NY: 'not_yet_in_system',
  SP: 'delivered_to_collection_location'
}.freeze
RETRYABLE_EXCEPTIONS =

Exceptions to retry on - includes timeouts and transient ShipEngine errors

(Retryable::TIMEOUT_CLASSES + [ShipEngineRb::Exceptions::ShipEngineError]).freeze

Instance Method Summary collapse

Methods inherited from BaseService

#log_debug, #log_error, #log_info, #log_warning, #logger, #options, #tagged_logger

Constructor Details

#initialize(options = {}) ⇒ PackageShipmentTracking

Returns a new instance of PackageShipmentTracking.



32
# File 'app/services/shipping/package_shipment_tracking.rb', line 32

def initialize(options = {}); end

Instance Method Details

#process(shipments) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/services/shipping/package_shipment_tracking.rb', line 37

def process(shipments)
  shipments_tracking_succeeded = []
  shipments_tracking_failed = []
  shipments_tracking_failed_msgs = []
  shipments.each do |shipment|
    res = {}
    begin
      # Adding a bit of retry juice to throttle things
      # Retries on timeouts AND ShipEngine carrier errors (which can be transient)
      Retryable.retryable(tries: 3, sleep: lambda { |n| 4**n }, on: RETRYABLE_EXCEPTIONS) do |attempt_number, _exception|
        Rails.logger.warn "WyShipping.track_shipment(#{shipment.id}) attempt #{attempt_number}" if attempt_number > 1
        res = WyShipping.track_shipment(shipment)
      end
      Rails.logger.info { "Shipping::PackageShipmentTracking process: shipment, ID: #{shipment.id}, WyShipping.track_shipment(shipment): #{res}" }
      if res[:status_code] == :ok
        tracking_result = res.dig(:tracking_result)
        tracking_state = TRACKING_STATUS_CODES[tracking_result.dig(:status_code).to_sym]
        if tracking_state && shipment.update(tracking_state: tracking_state)
          tracking_result_hash = {
            tracking_status: tracking_result.dig(:status_code),
            tracking_description: tracking_result.dig(:status_description),
            tracking_carrier_status: tracking_result.dig(:carrier_status_code),
            tracking_carrier_description: tracking_result.dig(:carrier_status_description)
          }
          tracking_result_hash[:estimated_delivery_date] = Date.parse(tracking_result.dig(:estimated_delivery_date)) if tracking_result.dig(:estimated_delivery_date)
          tracking_result_hash[:actual_delivery_date] = Date.parse(tracking_result.dig(:actual_delivery_date)) if tracking_result.dig(:actual_delivery_date)
          shipment.update(tracking_result_hash)
          shipments_tracking_succeeded << shipment
        else
          shipments_tracking_failed << shipment
          msg = shipment.errors_to_s
          msg += "tracking status of #{tracking_result.dig(:status_code)} not in defined shipping tracking states" unless tracking_state
          shipments_tracking_failed_msgs << msg
        end
      else
        shipments_tracking_failed << shipment
        shipments_tracking_failed_msgs << res[:status_message]
      end
    rescue StandardError => e
      # Catch ALL errors for this shipment - don't let one failure stop the batch
      Rails.logger.error "[PackageShipmentTracking] Failed to track shipment #{shipment.id}: #{e.class.name}: #{e.message}"
      shipments_tracking_failed << shipment
      shipments_tracking_failed_msgs << "Shipment #{shipment.id}: #{e.class.name}: #{e.message}"
    end
  end
  Result.new(shipments_tracking_succeeded:, shipments_tracking_failed:, shipments_tracking_failed_msgs:)
end