Class: Edi::Amazon::ShipCodeMapper

Inherits:
Object
  • Object
show all
Defined in:
app/services/edi/amazon/ship_code_mapper.rb

Overview

Class that translates shipping codes from Amazon Seller Central to Heatwave shipping options.
Handles both legacy direct-carrier mapping (ShipmentServiceLevelCategory → FedEx/UPS options)
and Amazon Buy Shipping (AmazonSeller carrier with AMZBS_* service codes).

Constant Summary collapse

CARRIER_CODE_MAP =

Maps internal carrier names to Amazon carrierCode values for ship confirmations
https://images-na.ssl-images-amazon.com/images/G/01/rainier/help/xsd/release_1_9/amzn-base._TTH_.xsd

{
  'UPS' => 'UPS',
  'Ups' => 'UPS',
  'USPS' => 'USPS',
  'Usps' => 'USPS',
  'FedEx' => 'FedEx',
  'Fedex' => 'FedEx',
  'FEDEX' => 'FedEx',
  'Canadapost' => 'Canada Post',
  'Canpar' => 'Canpar',
  'Purolator' => 'PUROLATOR',
  'RlCarriers' => 'R+L',
  'AmazonSeller' => 'Amazon',
  # ShipEngine LTL — verified against Amazon's acceptable-CarrierCode
  # enumeration (amzn-base release_1_9 XSD, 2026-07-18). SCACs are not listed.
  'ShipengineXpo' => 'Conway',
  'ShipengineSaia' => 'Saia',
  'ShipengineRlCarriers' => 'R+L',
  'ShipengineRoadrunner' => 'Roadrunner',
  'ShipengineFedExFreight' => 'Fedex Freight',
  'ShipengineFedExFreightEconomy' => 'Fedex Freight'
}.freeze
PRIMARY_CARRIER_PREFIXES =

Primary carrier prefixes.

{
  'fedex' => 'FedEx',
  'ups' => 'UPS',
  'usps' => 'USPS'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(orchestrator) ⇒ ShipCodeMapper

Returns a new instance of ShipCodeMapper.



42
43
44
45
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 42

def initialize(orchestrator)
  @orchestrator = orchestrator
  build_shipping_map
end

Instance Attribute Details

#orchestratorObject (readonly)

Returns the value of attribute orchestrator.



40
41
42
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 40

def orchestrator
  @orchestrator
end

#shipping_mapObject (readonly)

Returns the value of attribute shipping_map.



40
41
42
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 40

def shipping_map
  @shipping_map
end

Instance Method Details

#az_to_hw(shipping_code) ⇒ Object

Pass an Amazon shipping code (either ShipmentServiceLevelCategory or AutomatedShipMethod)
and retrieve a shipping option result object



126
127
128
129
130
131
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 126

def az_to_hw(shipping_code)
  match = shipping_map.find { |sor| sor.code == shipping_code }
  match ||= shipping_map.find { |sor| sor.code.downcase == shipping_code.to_s.downcase }
  match ||= shipping_map.find { |sor| sor.code == 'UNSP' }
  match
end

#carrier_code(carrier) ⇒ Object

Map internal carrier name to Amazon carrier code for ship confirmations



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 53

def carrier_code(carrier)
  return nil if carrier.blank?

  carrier_str = carrier.to_s.strip
  return CARRIER_CODE_MAP[carrier_str] if CARRIER_CODE_MAP.key?(carrier_str)

  _key, value = CARRIER_CODE_MAP.find { |k, _v| k.casecmp?(carrier_str) }
  return value if value

  carrier_lower = carrier_str.downcase
  PRIMARY_CARRIER_PREFIXES.each do |prefix, amazon_code|
    return amazon_code if carrier_lower.start_with?(prefix)
  end

  nil
end

#carrier_info(shipment) ⇒ Object

Build carrier info hash for ship confirmation, matching Walmart SWW pattern.
For Amazon Buy Shipping shipments, uses the actual carrier from amz_metadata.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 72

def carrier_info(shipment)
  is_amzbs = shipment.carrier == 'AmazonSeller'
  actual_carrier = if is_amzbs && shipment.amz_carrier.present?
                     shipment.amz_carrier
                   else
                     shipment.carrier
                   end

  carrier = carrier_code(actual_carrier)
  {
    carrierCode: carrier || 'Other',
    # Echo the mapped code as the name; for unmapped carriers strip the
    # 'Shipengine' integration prefix (it's our internal naming, not the carrier's).
    carrierName: carrier || actual_carrier.to_s.delete_prefix('Shipengine'),
    shippingMethod: shipment.delivery&.shipping_method_friendly,
    trackingNumber: shipment.display_tracking_number
  }.compact
end

#ch_to_hw(shipping_code) ⇒ Object

Map Amazon shipping code to Heatwave shipping option



48
49
50
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 48

def ch_to_hw(shipping_code)
  @shipping_map.find { |result| result.code.casecmp?(shipping_code.to_s) }
end

#hw_to_az(shipping_method_name) ⇒ Object

Translates a heatwave shipping option name to an Amazon shipping code



134
135
136
137
# File 'app/services/edi/amazon/ship_code_mapper.rb', line 134

def hw_to_az(shipping_method_name)
  match = shipping_map.find { |sor| sor.name == shipping_method_name }&.code
  match || 'Standard'
end