Class: Edi::Walmart::Orchestrator

Inherits:
BaseOrchestrator show all
Defined in:
app/services/edi/walmart/orchestrator.rb

Constant Summary collapse

GOLIVE_DATE_STR =
'July 25, 2025'
EARLY_LABEL_PURCHASE_ENABLED_US =

Enable early label purchase for Walmart orders (labels purchased at order release, not ship-label time)
Set to true to enable, false to disable

false
EARLY_LABEL_PURCHASE_ENABLED_CA =
false

Constants inherited from BaseOrchestrator

BaseOrchestrator::DEFAULT_PENDING_DISCONTINUE_LIFETIME, BaseOrchestrator::ORCHESTRATORS, BaseOrchestrator::RECOMMENDED_EXECUTE_FLOW_EVERY_X_HOUR

Instance Attribute Summary

Attributes inherited from BaseOrchestrator

#config, #logger, #options

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from BaseOrchestrator

all_orchestrators_class, build, cached_build, cached_orchestrators, catalog_id_to_pending_discontinue_lifetime, catalog_ids_edi_enabled, #customer, #customer_catalog, customer_id_to_partner_key_map, #customer_ids, customer_ids_edi_enabled, customer_ids_with_invoice_message_enabled, #customers, execute_discontinue_flow, execute_flow, execute_inventory_flow, execute_listing_message_feed_flow, execute_order_flow, execute_price_flow, execute_product_data_flow, #execute_product_data_flow, #ignore_back_orders, #initialize, orchestrator_for_customer_id, orchestrators, #pending_discontinue_lifetime, #product_data_enabled?, #should_execute_flow?, #should_execute_order_flow?, #should_execute_product_data_flow?, #test_mode?

Constructor Details

This class inherits a constructor from Edi::BaseOrchestrator

Class Method Details

.execute_feed_submission_result_processor(options = {}) ⇒ Object



75
76
77
# File 'app/services/edi/walmart/orchestrator.rb', line 75

def self.execute_feed_submission_result_processor(options = {})
  orchestrators(options).each { |o| o.feed_submission_result_processor.process }
end

.partnersObject



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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
# File 'app/services/edi/walmart/orchestrator.rb', line 14

def self.partners
  {
    walmart_seller_us: {
      active: true,
      partner: :walmart_seller_us,
      customer_id: 23_041_827,
      fulfillment_center_id: '10002649057',
      locales: ['en_US'],
      business_unit: 'WALMART_US',
      default_locale: 'en',
      inventory_message_enabled: true,
      support_contact: 'Soumitro.Biswas0@walmart.com',
      price_message_enabled: true,
      ship_with_walmart_enabled: true, # Enable "Ship with Walmart" discounted shipping rates
      early_label_purchase_enabled: EARLY_LABEL_PURCHASE_ENABLED_US,
      transporter: :http_walmart_seller_api,
      transporter_profile: :walmart_seller_us_api,
      inventory_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_us_api, :api_host)}/v3/inventory",
      feed_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_us_api, :api_host)}/v3/feeds",
      order_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_us_api, :api_host)}/v3/orders",
      items_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_us_api, :api_host)}/v3/items",
      ship_with_walmart_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_us_api, :api_host)}/v3/shipping/labels",
      failure_timeout_in_minutes: 1440,
      execute_inventory_flow_every_x_hour: 1,
      execute_price_flow_every_x_hour: 24,
      execute_order_flow_every_x_hour: 1,
      listing_message_feed_enabled: false,
      currency: 'USD'
    },
    walmart_seller_ca: {
      active: true,
      partner: :walmart_seller_ca,
      customer_id: 21_009_368,
      fulfillment_center_id: '10001201755',
      locales: %w[en_CA fr_CA],
      business_unit: 'WALMART_CA',
      default_locale: 'en',
      inventory_message_enabled: true,
      support_contact: 'Soumitro.Biswas0@walmart.com',
      price_message_enabled: true,
      ship_with_walmart_enabled: true, # Enable "Ship with Walmart" discounted shipping rates
      early_label_purchase_enabled: EARLY_LABEL_PURCHASE_ENABLED_CA,
      transporter: :http_walmart_seller_api,
      transporter_profile: :walmart_seller_ca_api,
      # Use global endpoints with WM_MARKET header (set via profile[:market])
      # See: https://developer.walmart.com/global-marketplace/reference/tokenapi
      inventory_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_ca_api, :api_host)}/v3/inventory",
      feed_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_ca_api, :api_host)}/v3/feeds",
      order_message_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_ca_api, :api_host)}/v3/orders",
      items_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_ca_api, :api_host)}/v3/items",
      ship_with_walmart_remote_path: "https://#{Heatwave::Configuration.fetch(:walmart_seller_ca_api, :api_host)}/v3/shipping/labels",
      failure_timeout_in_minutes: 1440,
      execute_inventory_flow_every_x_hour: 1,
      execute_price_flow_every_x_hour: 24,
      execute_order_flow_every_x_hour: 1,
      listing_message_feed_enabled: false,
      currency: 'CAD'
    }
  }
end

Instance Method Details

#acknowledge_message_enabled?Boolean

Returns:

  • (Boolean)


125
126
127
# File 'app/services/edi/walmart/orchestrator.rb', line 125

def acknowledge_message_enabled?
  try(:order_message_remote_path).present?
end

#acknowledge_message_senderObject



129
130
131
132
133
# File 'app/services/edi/walmart/orchestrator.rb', line 129

def acknowledge_message_sender
  return Edi::NullProcessor.new(self, :acknowledge_message_sender, options) unless acknowledge_message_enabled?

  AcknowledgeMessageSender.new(self, options)
end

#buy_box_status_enabled?Boolean

Returns:

  • (Boolean)


213
214
215
# File 'app/services/edi/walmart/orchestrator.rb', line 213

def buy_box_status_enabled?
  try(:product_pricing_remote_path).present?
end

#buy_box_status_retrieverObject



217
218
219
220
221
# File 'app/services/edi/walmart/orchestrator.rb', line 217

def buy_box_status_retriever
  return Edi::NullProcessor.new(self, :buy_box_status_retriever, options) unless buy_box_status_enabled?

  BuyBoxStatusRetriever.new(self, options)
end

#catalog_item_information_enabled?Boolean

Returns:

  • (Boolean)


203
204
205
# File 'app/services/edi/walmart/orchestrator.rb', line 203

def catalog_item_information_enabled?
  try(:items_remote_path).present?
end

#catalog_item_information_processorObject



247
248
249
250
251
# File 'app/services/edi/walmart/orchestrator.rb', line 247

def catalog_item_information_processor
  return Edi::NullProcessor.new(self, :catalog_item_information_processor, options) unless catalog_item_information_enabled?

  CatalogItemInformationProcessor.new(self, options)
end

#catalog_item_information_retrieverObject



207
208
209
210
211
# File 'app/services/edi/walmart/orchestrator.rb', line 207

def catalog_item_information_retriever
  return Edi::NullProcessor.new(self, :catalog_item_information_retriever, options) unless catalog_item_information_enabled?

  CatalogItemInformationRetriever.new(self, options)
end

#confirm_message_enabled?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'app/services/edi/walmart/orchestrator.rb', line 95

def confirm_message_enabled?
  try(:order_message_remote_path).present?
end

#confirm_message_processorObject



113
114
115
116
117
# File 'app/services/edi/walmart/orchestrator.rb', line 113

def confirm_message_processor
  return Edi::NullProcessor.new(self, :confirm_message_processor, options) unless confirm_message_enabled?

  ConfirmMessageProcessor.new(self, options)
end

#confirm_message_senderObject



119
120
121
122
123
# File 'app/services/edi/walmart/orchestrator.rb', line 119

def confirm_message_sender
  return Edi::NullProcessor.new(self, :confirm_message_sender, options) unless confirm_message_enabled?

  ConfirmMessageSender.new(self, options)
end

#confirm_outbound_processing?Boolean

Walmart is a two stage process on feeds (processing -> complete)

Returns:

  • (Boolean)


325
326
327
# File 'app/services/edi/walmart/orchestrator.rb', line 325

def confirm_outbound_processing?
  true
end

#delete_listing_message_processorObject



273
274
275
276
277
# File 'app/services/edi/walmart/orchestrator.rb', line 273

def delete_listing_message_processor
  return Edi::NullProcessor.new(self, :delete_listing_message_processor, options) unless listing_message_enabled?

  DeleteListingMessageProcessor.new(self, options)
end

#discontinue_flow_processorObject



320
321
322
# File 'app/services/edi/walmart/orchestrator.rb', line 320

def discontinue_flow_processor
  DiscontinueFlowProcessor.new(self, options)
end

#early_label_purchase_enabled?Boolean

Check if early label purchase is enabled for this partner
When enabled, labels are purchased at order release instead of at ship-label time
Set to false to disable the feature; set to true to enable it

Returns:

  • (Boolean)

    true if early label purchase is enabled



109
110
111
# File 'app/services/edi/walmart/orchestrator.rb', line 109

def early_label_purchase_enabled?
  try(:early_label_purchase_enabled) == true && ship_with_walmart_enabled?
end

#execute_discontinue_flowObject



314
315
316
317
318
# File 'app/services/edi/walmart/orchestrator.rb', line 314

def execute_discontinue_flow
  return false unless active

  discontinue_flow_processor.process
end

#execute_inventory_flow(use_delta_since_last_message: false) ⇒ Object



293
294
295
296
297
298
# File 'app/services/edi/walmart/orchestrator.rb', line 293

def execute_inventory_flow(use_delta_since_last_message: false)
  return false unless active

  inventory_message_processor.process(use_delta_since_last_message:) # Generate an inventory feed message
  inventory_message_sender.process # Send it
end

#execute_listing_message_feed_flowObject



307
308
309
310
311
312
# File 'app/services/edi/walmart/orchestrator.rb', line 307

def execute_listing_message_feed_flow
  return false unless active

  listing_message_feed_processor.process # Generate a listing message feed message
  listing_message_feed_sender.process # Send it
end

#execute_order_flowObject



279
280
281
282
283
284
285
286
287
288
289
290
291
# File 'app/services/edi/walmart/orchestrator.rb', line 279

def execute_order_flow
  return unless active

  order_message_retriever.process
  sleep(1)
  order_message_processor.process
  sleep(1)
  acknowledge_message_sender.process
  sleep(1)
  confirm_message_sender.process
  # sleep(1)
  # execute_fba_order_flow # need this to run less frequently or to remove ECLs where we skip all the processed fba_orders
end

#execute_price_flow(use_delta_since_last_message: false) ⇒ Object



300
301
302
303
304
305
# File 'app/services/edi/walmart/orchestrator.rb', line 300

def execute_price_flow(use_delta_since_last_message: false)
  return false unless active

  price_message_processor.process(use_delta_since_last_message:) # Generate a price feed message
  price_message_sender.process # Send it
end

#feed_submission_result_processorObject



199
200
201
# File 'app/services/edi/walmart/orchestrator.rb', line 199

def feed_submission_result_processor
  FeedSubmissionResultProcessor.new(self, options)
end

#inventory_message_enabled?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'app/services/edi/walmart/orchestrator.rb', line 151

def inventory_message_enabled?
  inventory_message_enabled
end

#inventory_message_processorObject



155
156
157
158
159
# File 'app/services/edi/walmart/orchestrator.rb', line 155

def inventory_message_processor
  return Edi::NullProcessor.new(self, :inventory_message_processor, options) unless inventory_message_enabled?

  InventoryMessageProcessor.new(self, options)
end

#inventory_message_senderObject



161
162
163
164
165
# File 'app/services/edi/walmart/orchestrator.rb', line 161

def inventory_message_sender
  return Edi::NullProcessor.new(self, :inventory_message_sender, options) unless inventory_message_enabled?

  InventoryMessageSender.new(self, options)
end

#invoice_message_enabled?Boolean

Returns:

  • (Boolean)


135
136
137
# File 'app/services/edi/walmart/orchestrator.rb', line 135

def invoice_message_enabled?
  false
end

#invoice_message_processorObject



139
140
141
# File 'app/services/edi/walmart/orchestrator.rb', line 139

def invoice_message_processor
  Edi::NullProcessor.new(self, :invoice_message_processor, options)
end

#listing_item_information_processorObject



229
230
231
232
233
# File 'app/services/edi/walmart/orchestrator.rb', line 229

def listing_item_information_processor
  return Edi::NullProcessor.new(self, :listing_item_information_processor, options) unless listing_message_enabled?

  ListingItemInformationProcessor.new(self, options)
end

#listing_item_information_retrieverObject



223
224
225
226
227
# File 'app/services/edi/walmart/orchestrator.rb', line 223

def listing_item_information_retriever
  return Edi::NullProcessor.new(self, :listing_item_information_retriever, options) unless listing_message_enabled?

  ListingItemInformationRetriever.new(self, options)
end

#listing_item_schema_processorObject



241
242
243
244
245
# File 'app/services/edi/walmart/orchestrator.rb', line 241

def listing_item_schema_processor
  return Edi::NullProcessor.new(self, :listing_item_schema_processor, options) unless listing_schema_message_enabled?

  ListingItemSchemaProcessor.new(self, options)
end

#listing_item_schema_retrieverObject



235
236
237
238
239
# File 'app/services/edi/walmart/orchestrator.rb', line 235

def listing_item_schema_retriever
  return Edi::NullProcessor.new(self, :listing_item_schema_retriever, options) unless listing_schema_message_enabled?

  ListingItemSchemaRetriever.new(self, options)
end

#listing_message_enabled?Boolean

Returns:

  • (Boolean)


253
254
255
# File 'app/services/edi/walmart/orchestrator.rb', line 253

def listing_message_enabled?
  try(:listing_message_remote_path).present?
end

#listing_message_feed_enabled?Boolean

Returns:

  • (Boolean)


183
184
185
# File 'app/services/edi/walmart/orchestrator.rb', line 183

def listing_message_feed_enabled?
  listing_message_feed_enabled
end

#listing_message_feed_processorObject



193
194
195
196
197
# File 'app/services/edi/walmart/orchestrator.rb', line 193

def listing_message_feed_processor
  return Edi::NullProcessor.new(self, :listing_message_feed_processor, options) unless listing_message_feed_enabled?

  ListingMessageFeedProcessor.new(self, options)
end

#listing_message_feed_senderObject



187
188
189
190
191
# File 'app/services/edi/walmart/orchestrator.rb', line 187

def listing_message_feed_sender
  return Edi::NullProcessor.new(self, :listing_message_feed_sender, options) unless listing_message_feed_enabled?

  ListingMessageFeedSender.new(self, options)
end

#listing_message_processorObject



267
268
269
270
271
# File 'app/services/edi/walmart/orchestrator.rb', line 267

def listing_message_processor
  return Edi::NullProcessor.new(self, :listing_message_processor, options) unless listing_message_enabled?

  ListingMessageProcessor.new(self, options)
end

#listing_message_senderObject



261
262
263
264
265
# File 'app/services/edi/walmart/orchestrator.rb', line 261

def listing_message_sender
  return Edi::NullProcessor.new(self, :listing_message_sender, options) unless listing_message_enabled?

  ListingMessageSender.new(self, options)
end

#listing_schema_message_enabled?Boolean

Returns:

  • (Boolean)


257
258
259
# File 'app/services/edi/walmart/orchestrator.rb', line 257

def listing_schema_message_enabled?
  try(:listing_schema_message_enabled).present?
end

#order_message_enabled?Boolean

Returns:

  • (Boolean)


79
80
81
# File 'app/services/edi/walmart/orchestrator.rb', line 79

def order_message_enabled?
  try(:order_message_remote_path).present?
end

#order_message_processorObject



89
90
91
92
93
# File 'app/services/edi/walmart/orchestrator.rb', line 89

def order_message_processor
  return Edi::NullProcessor.new(self, :order_message_processor, options) unless order_message_enabled?

  OrderMessageProcessor.new(self, options)
end

#order_message_retrieverObject



83
84
85
86
87
# File 'app/services/edi/walmart/orchestrator.rb', line 83

def order_message_retriever
  return Edi::NullProcessor.new(self, :order_message_retriever, options) unless order_message_enabled?

  OrderMessageRetriever.new(self, options)
end

#orders_with_walmart_po(po_number) ⇒ Object

Find orders by Walmart PO number for duplicate checking



334
335
336
337
338
339
# File 'app/services/edi/walmart/orchestrator.rb', line 334

def orders_with_walmart_po(po_number)
  Order.joins(:customer)
       .where(customers: { id: customer_ids })
       .where(edi_po_number: po_number)
       .where('orders.created_at > ?', 13.months.ago)
end

#price_message_enabled?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'app/services/edi/walmart/orchestrator.rb', line 167

def price_message_enabled?
  price_message_enabled
end

#price_message_processorObject



177
178
179
180
181
# File 'app/services/edi/walmart/orchestrator.rb', line 177

def price_message_processor
  return Edi::NullProcessor.new(self, :price_message_processor, options) unless price_message_enabled?

  PriceMessageProcessor.new(self, options)
end

#price_message_senderObject



171
172
173
174
175
# File 'app/services/edi/walmart/orchestrator.rb', line 171

def price_message_sender
  return Edi::NullProcessor.new(self, :price_message_sender, options) unless price_message_enabled?

  PriceMessageSender.new(self, options)
end

#pull_all_catalog_information(dry_run: false) ⇒ Object

Pull all catalog items for synchronization



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'app/services/edi/walmart/orchestrator.rb', line 365

def pull_all_catalog_information(dry_run: false)
  results = []
  offset = 0
  limit = 200

  loop do
    ecl = catalog_item_information_retriever.process_all(offset: offset, limit: limit)
    break unless ecl

    result = catalog_item_information_processor.process(ecl, dry_run: dry_run)
    results << result

    # Check for more pages
    data = JSON.parse(ecl.data).with_indifferent_access
    total_items = data[:totalItems].to_i
    break if offset + limit >= total_items

    offset += limit
    sleep(0.5)
  end

  results
end

#pull_catalog_information(catalog_item) ⇒ Object

Pull catalog information for a specific catalog item by SKU



342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'app/services/edi/walmart/orchestrator.rb', line 342

def pull_catalog_information(catalog_item)
  sku = catalog_item.reported_vendor_sku || catalog_item.sku
  raise "No SKU for catalog_item #{catalog_item.id}" unless sku.present?

  ecl = catalog_item_information_retriever.process(
    sku: sku,
    file_info: {
      sku: sku,
      catalog_item_id: catalog_item.id,
      item_id: catalog_item.item_id
    }
  )

  if ecl
    Rails.logger.debug { "Walmart orchestrator#pull_catalog_information, ecl: #{ecl.id}" }
    catalog_item_information_processor.process(ecl)
  else
    Rails.logger.error "Walmart orchestrator#pull_catalog_information for catalog item #{catalog_item.id} yielded no ecl (sku #{sku} not found?)"
    nil
  end
end

#return_notification_message_enabled?Boolean

Returns:

  • (Boolean)


143
144
145
# File 'app/services/edi/walmart/orchestrator.rb', line 143

def return_notification_message_enabled?
  false
end

#return_notification_message_processorObject



147
148
149
# File 'app/services/edi/walmart/orchestrator.rb', line 147

def return_notification_message_processor
  Edi::NullProcessor.new(self, :return_notification_message_processor, options)
end

#ship_code_mapperObject



329
330
331
# File 'app/services/edi/walmart/orchestrator.rb', line 329

def ship_code_mapper
  ShipCodeMapper.new(self)
end

#ship_with_walmart_enabled?Boolean

Check if "Ship with Walmart" (SWW) discounted shipping is enabled for this partner

Returns:

  • (Boolean)

    true if SWW rates and label purchasing are enabled



101
102
103
# File 'app/services/edi/walmart/orchestrator.rb', line 101

def ship_with_walmart_enabled?
  try(:ship_with_walmart_enabled) == true && try(:ship_with_walmart_remote_path).present?
end