Class: WebhookProcessors::ShipengineProcessor
- Inherits:
-
Object
- Object
- WebhookProcessors::ShipengineProcessor
- Defined in:
- app/services/webhook_processors/shipengine_processor.rb
Overview
Processor for ShipEngine tracking webhook callbacks
Updates Shipment tracking status based on webhook events
Constant Summary collapse
- TRACKING_STATUS_CODES =
ShipEngine status codes mapped to our tracking states
Mirrors Shipping::PackageShipmentTracking::TRACKING_STATUS_CODES { '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
- MOVEMENT_STATUS_CODES =
Status codes that indicate the carrier has actually accepted the package
(i.e., the package is past the "label created" stage).
AC = Accepted/label created — we do NOT book insurance on this event. %w[IT DE EX AT SP].freeze
Class Method Summary collapse
Instance Method Summary collapse
- #call ⇒ Object
-
#initialize(webhook_log) ⇒ ShipengineProcessor
constructor
A new instance of ShipengineProcessor.
Constructor Details
#initialize(webhook_log) ⇒ ShipengineProcessor
Returns a new instance of ShipengineProcessor.
31 32 33 34 35 |
# File 'app/services/webhook_processors/shipengine_processor.rb', line 31 def initialize(webhook_log) @webhook_log = webhook_log @data = webhook_log.data @tracking_data = @data['data'] || {} end |
Class Method Details
.call(webhook_log) ⇒ Object
27 28 29 |
# File 'app/services/webhook_processors/shipengine_processor.rb', line 27 def self.call(webhook_log) new(webhook_log).call end |
Instance Method Details
#call ⇒ Object
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 |
# File 'app/services/webhook_processors/shipengine_processor.rb', line 42 def call tracking_number = @tracking_data['tracking_number'] status_code = @tracking_data['status_code'] Rails.logger.info "[ShipengineProcessor] Processing tracking update: #{tracking_number} -> #{status_code}" resource = find_resource(tracking_number) # Persist per-scan ShipmentEvent rows regardless of whether the # tracking number resolves to a known Shipment — the audit trail is # worth keeping even when we can't link it. shipment_id stays null # when resource is an Rma (return label tracking) or unresolved. shipment_for_events = resource.is_a?(Shipment) ? resource : nil events_persisted = persist_shipment_events(shipment_for_events) unless resource Rails.logger.warn "[ShipengineProcessor] No Shipment or RMA found for tracking: #{tracking_number}" return { status: 'not_found', reason: 'No Shipment or RMA found for tracking number', tracking_number: tracking_number, shipment_events_persisted: events_persisted } end if resource.is_a?(Rma) handle_rma_tracking(resource, tracking_number, status_code).merge(shipment_events_persisted: events_persisted) else result = update_shipment_tracking(resource) Rails.logger.info "[ShipengineProcessor] Updated Shipment##{resource.id} to #{result[:tracking_state]}" { status: result[:success] ? 'success' : 'failed', shipment_id: resource.id, tracking_number: tracking_number, tracking_state: result[:tracking_state], status_code: status_code, shipment_events_persisted: events_persisted, error: result[:error] }.compact end end |