Class: Edi::MarketplaceLabelPurchaser
- Inherits:
-
Object
- Object
- Edi::MarketplaceLabelPurchaser
- Defined in:
- app/services/edi/marketplace_label_purchaser.rb
Overview
Base class for marketplace-specific shipping label purchasers
Each marketplace (Walmart, Amazon, Wayfair, etc.) that offers discounted
shipping labels through their platform should have a subclass that handles:
- Purchasing labels via the marketplace's API
- Downloading label PDFs
- Attaching labels to shipments
- Voiding/canceling labels
Direct Known Subclasses
Amazon::ShippingLabelPurchaser, Walmart::ShippingLabelPurchaser
Defined Under Namespace
Classes: PurchaseResult
Instance Attribute Summary collapse
-
#delivery ⇒ Object
readonly
Returns the value of attribute delivery.
-
#logger ⇒ Object
readonly
Returns the value of attribute logger.
-
#order ⇒ Object
readonly
Returns the value of attribute order.
-
#shipment ⇒ Object
readonly
Returns the value of attribute shipment.
Class Method Summary collapse
-
.for_delivery(delivery) ⇒ Class?
Factory method to get the appropriate purchaser class for a delivery.
-
.for_order(order) ⇒ Class?
Factory method to get the appropriate purchaser class for an order.
-
.for_shipment(shipment) ⇒ Class?
Factory method to get the appropriate purchaser class for a shipment.
-
.marketplace_carrier?(carrier) ⇒ Boolean
Check if the carrier is a marketplace-provided carrier.
-
.marketplace_name(order) ⇒ String?
Get the marketplace name for display.
-
.supports_marketplace_labels?(delivery) ⇒ Boolean
Check if a delivery supports marketplace label purchasing.
Instance Method Summary collapse
-
#attach_label_pdf(label_data, filename) ⇒ Upload?
protected
Download a label PDF and attach it to the shipment Uses 'ship_label_pdf' category since it's a carrier-generated label (purchased through marketplace API, but still a real carrier label).
-
#failure_result(error, api_log: []) ⇒ Object
protected
Create a failure result.
-
#initialize(shipment, options = {}) ⇒ MarketplaceLabelPurchaser
constructor
A new instance of MarketplaceLabelPurchaser.
-
#map_carrier_name(marketplace_carrier) ⇒ String
protected
Map marketplace carrier codes to internal carrier names Subclasses can override for marketplace-specific mappings.
-
#marketplace_name ⇒ String
Human-readable name of this marketplace.
-
#purchase_label(_rate) ⇒ PurchaseResult
Purchase a shipping label using a marketplace rate.
-
#success_result(label_id:, tracking_number:, carrier:, service_type:, label_upload: nil, api_log: []) ⇒ Object
protected
Create a successful result.
-
#update_shipment_tracking(tracking_number, carrier, label_id) ⇒ Object
protected
Update shipment with tracking information.
-
#validate_order! ⇒ Object
protected
Validate the order is appropriate for this purchaser Subclasses should override to add marketplace-specific validation.
-
#void_label ⇒ Hash
Void/discard a previously purchased label.
Constructor Details
#initialize(shipment, options = {}) ⇒ MarketplaceLabelPurchaser
Returns a new instance of MarketplaceLabelPurchaser.
107 108 109 110 111 112 113 114 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 107 def initialize(shipment, = {}) @shipment = shipment @delivery = shipment.delivery @order = delivery.order @logger = [:logger] || Rails.logger validate_order! end |
Instance Attribute Details
#delivery ⇒ Object (readonly)
Returns the value of attribute delivery.
27 28 29 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 27 def delivery @delivery end |
#logger ⇒ Object (readonly)
Returns the value of attribute logger.
27 28 29 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 27 def logger @logger end |
#order ⇒ Object (readonly)
Returns the value of attribute order.
27 28 29 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 27 def order @order end |
#shipment ⇒ Object (readonly)
Returns the value of attribute shipment.
27 28 29 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 27 def shipment @shipment end |
Class Method Details
.for_delivery(delivery) ⇒ Class?
Factory method to get the appropriate purchaser class for a delivery
69 70 71 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 69 def self.for_delivery(delivery) for_order(delivery&.order) end |
.for_order(order) ⇒ Class?
Factory method to get the appropriate purchaser class for an order
52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 52 def self.for_order(order) return nil if order&.edi_orchestrator_partner.blank? # Map EDI partner prefixes to their label purchaser classes # Add new marketplaces here as they're implemented case order.edi_orchestrator_partner when /^walmart_seller/ then Edi::Walmart::ShippingLabelPurchaser when /^amazon_seller/ then Edi::Amazon::ShippingLabelPurchaser # Future marketplaces: # when /^wayfair/ then Edi::Wayfair::ShippingLabelPurchaser end end |
.for_shipment(shipment) ⇒ Class?
Factory method to get the appropriate purchaser class for a shipment
41 42 43 44 45 46 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 41 def self.for_shipment(shipment) order = shipment.delivery&.order return nil unless order for_order(order) end |
.marketplace_carrier?(carrier) ⇒ Boolean
Check if the carrier is a marketplace-provided carrier
91 92 93 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 91 def self.marketplace_carrier?(carrier) %w[WalmartSeller AmazonSeller WayfairShipping].include?(carrier) end |
.marketplace_name(order) ⇒ String?
Get the marketplace name for display
99 100 101 102 103 104 105 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 99 def self.marketplace_name(order) case order&.edi_orchestrator_partner when /^walmart_seller/ then 'Walmart' when /^amazon_seller/ then 'Amazon' when /^wayfair/ then 'Wayfair' end end |
.supports_marketplace_labels?(delivery) ⇒ Boolean
Check if a delivery supports marketplace label purchasing
77 78 79 80 81 82 83 84 85 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 77 def self.supports_marketplace_labels?(delivery) return false unless delivery&.order # Must have a marketplace purchaser available return false unless for_delivery(delivery) # Must have a marketplace carrier selected marketplace_carrier?(delivery.carrier) end |
Instance Method Details
#attach_label_pdf(label_data, filename) ⇒ Upload? (protected)
Download a label PDF and attach it to the shipment
Uses 'ship_label_pdf' category since it's a carrier-generated label
(purchased through marketplace API, but still a real carrier label)
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 181 def attach_label_pdf(label_data, filename) upload = Upload.uploadify_from_data( file_name: filename, data: label_data, category: 'ship_label_pdf', resource: shipment ) if upload&.persisted? shipment.uploads << upload logger.info("[#{self.class.name}] Label attached as upload #{upload.id}") end upload rescue StandardError => e logger.error("[#{self.class.name}] Error attaching label: #{e.}") nil end |
#failure_result(error, api_log: []) ⇒ Object (protected)
Create a failure result
161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 161 def failure_result(error, api_log: []) PurchaseResult.new( success: false, label_id: nil, tracking_number: nil, carrier: nil, service_type: nil, label_upload: nil, error: error, api_log: api_log ) end |
#map_carrier_name(marketplace_carrier) ⇒ String (protected)
Map marketplace carrier codes to internal carrier names
Subclasses can override for marketplace-specific mappings
220 221 222 223 224 225 226 227 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 220 def map_carrier_name(marketplace_carrier) case marketplace_carrier&.upcase when 'USPS' then 'USPS' when 'FEDEX', 'FEDEX_GROUND', 'FEDEX_EXPRESS' then 'FedEx' when 'UPS' then 'UPS' else marketplace_carrier end end |
#marketplace_name ⇒ String
Human-readable name of this marketplace
134 135 136 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 134 def marketplace_name raise NotImplementedError, "#{self.class.name} must implement #marketplace_name" end |
#purchase_label(_rate) ⇒ PurchaseResult
Purchase a shipping label using a marketplace rate
120 121 122 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 120 def purchase_label(_rate) raise NotImplementedError, "#{self.class.name} must implement #purchase_label" end |
#success_result(label_id:, tracking_number:, carrier:, service_type:, label_upload: nil, api_log: []) ⇒ Object (protected)
Create a successful result
147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 147 def success_result(label_id:, tracking_number:, carrier:, service_type:, label_upload: nil, api_log: []) PurchaseResult.new( success: true, label_id: label_id, tracking_number: tracking_number, carrier: carrier, service_type: service_type, label_upload: label_upload, error: nil, api_log: api_log ) end |
#update_shipment_tracking(tracking_number, carrier, label_id) ⇒ Object (protected)
Update shipment with tracking information
205 206 207 208 209 210 211 212 213 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 205 def update_shipment_tracking(tracking_number, carrier, label_id) shipment.update!( tracking_number: tracking_number, carrier: map_carrier_name(carrier), marketplace_label_id: label_id ) logger.info("[#{self.class.name}] Updated shipment #{shipment.id} with tracking: #{tracking_number}") end |
#validate_order! ⇒ Object (protected)
Validate the order is appropriate for this purchaser
Subclasses should override to add marketplace-specific validation
142 143 144 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 142 def validate_order! raise ArgumentError, 'Shipment must have an order' if order.blank? end |
#void_label ⇒ Hash
Void/discard a previously purchased label
127 128 129 |
# File 'app/services/edi/marketplace_label_purchaser.rb', line 127 def void_label raise NotImplementedError, "#{self.class.name} must implement #void_label" end |