Class: Edi::AmazonVc::Orchestrator

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

Overview

Service object: orchestrator.

Constant Summary collapse

GOLIVE_DATE_STR =

Golive date str.

'December 31, 2020'

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, build_customer_id_to_partner_key_map, 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_price_flow, execute_product_data_flow, #execute_product_data_flow, #initialize, orchestrator_for_customer_id, orchestrators, #pending_discontinue_lifetime, #price_message_enabled?, #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_transaction_message_processor(options = {}) ⇒ Object



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

def self.execute_transaction_message_processor(options = {})
  orchestrators(options).each { |o| o.transaction_message_processor.process }
end

.partnersObject



9
10
11
12
13
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 9

def self.partners
  {
    amazon_vc_seller_api_wax7v: {
      active: true,
      partner: :amazon_vc_seller_api_wax7v,
      vendor_code: 'WAX7V',
      warehouse_code: 'DFEE', # here we are using the code, no hash
      customer_id: 4_267_467,
      locales: ['en_US'],
      marketplace: 'ATVPDKIKX0DER',
      # match existing Vendor Central Direct Fulfillment invoices exactly
      vendor_name: CompanyConstants::ADDRESS[:usa][:company_name].upcase,
      vendor_address_street1: CompanyConstants::ADDRESS[:usa][:street1],
      vendor_address_street2: CompanyConstants::ADDRESS[:usa][:street2],
      vendor_address_city: CompanyConstants::ADDRESS[:usa][:city],
      vendor_address_state: CompanyConstants::ADDRESS[:usa][:state],
      vendor_address_postal_code: CompanyConstants::ADDRESS[:usa][:postal_code],
      vendor_address_country: CompanyConstants::ADDRESS[:usa][:country],
      tax_registration_number: nil,
      transporter: :http_seller_api,
      transporter_profile: :amazon_vc_seller_api_wax7v,
      inventory_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/inventory/v1/warehouses", # POST to inventory_message_remote_path/warehouse_code/items
      order_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/orders/v1/purchaseOrders", # GET from order_message_remote_path?shipFromPartyId=warehouse_code&limit=X&createdAfter=Y&createdBefore=Z&sortOrder=DESC&includeDetails=true HERE WE USE PRODUCTION HOST TO GET REAL DATA TO PROCESS BECAUSE SANDBOX DATA IS USELESS
      packing_slip_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/shipping/v1/packingSlips", # GET from packing_slip_remote_path?shipFromPartyId=warehouse_code&limit=X&createdAfter=Y&createdBefore=Z&sortOrder=DESC HERE WE USE PRODUCTION HOST TO GET REAL DATA TO PROCESS BECAUSE SANDBOX DATA IS USELESS
      acknowledge_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/orders/v1/acknowledgements", # POST to acknowledge_message_remote_path
      shipment_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/shipping/v1/shipmentConfirmations", # Post to shipment_message_remote_path
      transaction_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/vendor/directFulfillment/transactions/v1/transactions",
      failure_timeout_in_minutes: 30,
      catalog_item_information_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/catalog/2022-04-01/items/",
      listing_message_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/listings/2021-08-01/items/",
      listing_message_feed_enabled: false,
      support_contact: 'https://vendorcentral.amazon.com/hz/vendor/members/contact'
    },
    amazon_vc_seller_api_wat4d: {
      active: true,
      partner: :amazon_vc_seller_api_wat4d,
      vendor_code: 'WAT4D',
      warehouse_code: 'AMDR', # here we are using the code, no hash
      customer_id: 2_742_665,
      locales: %w[en_CA fr_CA],
      marketplace: 'A2EUQ1WTGCTBG2',
      # match existing Vendor Central Direct Fulfillment invoices exactly
      vendor_name: 'WARMLYYOURS -DROPSHIP',
      vendor_address_street1: CompanyConstants::ADDRESS[:can][:street1],
      vendor_address_street2: CompanyConstants::ADDRESS[:can][:street2],
      vendor_address_city: CompanyConstants::ADDRESS[:can][:city],
      vendor_address_state: CompanyConstants::ADDRESS[:can][:state],
      vendor_address_postal_code: CompanyConstants::ADDRESS[:can][:postal_code],
      vendor_address_country: CompanyConstants::ADDRESS[:can][:country],
      tax_registration_type: 'VAT',
      tax_registration_number: '861387777RT0001',
      transporter: :http_seller_api,
      transporter_profile: :amazon_vc_seller_api_wat4d,
      inventory_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/inventory/v1/warehouses", # POST to inventory_message_remote_path/warehouse_code/items
      order_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/orders/v1/purchaseOrders", # GET from order_message_remote_path?shipFromPartyId=warehouse_code&limit=X&createdAfter=Y&createdBefore=Z&sortOrder=DESC&includeDetails=true
      packing_slip_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/shipping/v1/packingSlips", # GET from packing_slip_remote_path/po_number
      acknowledge_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/orders/v1/acknowledgements", # POST to acknowledge_message_remote_path
      shipment_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/shipping/v1/shipmentConfirmations", # Post to shipment_message_remote_path
      transaction_message_remote_path: nil, # "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/vendor/directFulfillment/transactions/v1/transactions",
      failure_timeout_in_minutes: 30,
      catalog_item_information_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/catalog/2022-04-01/items/",
      listing_message_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/listings/2021-08-01/items/",
      listing_message_feed_enabled: false,
      support_contact: 'https://vendorcentral.amazon.com/hz/vendor/members/contact'
    },
    amazon_vc_seller_api_wasn4: {
      active: true,
      partner: :amazon_vc_seller_api_wasn4,
      vendor_code: 'WASN4',
      warehouse_code: 'DFEE', # here we are using the code, no hash
      customer_id: 2_385_944,
      locales: ['en_US'],
      marketplace: 'ATVPDKIKX0DER',
      transporter: :http_seller_api,
      transporter_profile: :amazon_vc_seller_api_wax7v, # here we are sharing the API application and credentials that we have for amazon_vc_seller_api_wax7v
      failure_timeout_in_minutes: 30,
      catalog_item_information_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/catalog/2022-04-01/items/",
      listing_message_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wax7v, :api_host)}/listings/2021-08-01/items/",
      listing_message_feed_enabled: false,
      support_contact: 'https://vendorcentral.amazon.com/hz/vendor/members/contact'
    },
    amazon_vc_seller_api_watof: {
      active: true,
      partner: :amazon_vc_seller_api_watof,
      vendor_code: 'WAT0F',
      customer_id: 2_741_053,
      locales: %w[en_CA fr_CA],
      marketplace: 'A2EUQ1WTGCTBG2',
      transporter: :http_seller_api,
      transporter_profile: :amazon_vc_seller_api_wat4d, # here we are sharing the same API application and credentials that we have for amazon_vc_seller_api_wat4d
      failure_timeout_in_minutes: 30,
      catalog_item_information_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/catalog/2022-04-01/items/",
      listing_message_remote_path: "https://#{Heatwave::Configuration.fetch(:amazon_vc_seller_api_wat4d, :api_host)}/listings/2021-08-01/items/",
      listing_message_feed_enabled: false,
      support_contact: 'https://vendorcentral.amazon.com/hz/vendor/members/contact'
    }
  }
end

.populate_items_from_all_partners(limit: nil, skus: nil, force: false) ⇒ Object



578
579
580
581
582
583
584
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 578

def self.populate_items_from_all_partners(limit: nil, skus: nil, force: false)
  res = {}
  orchestrators.each do |orchestrator|
    res[orchestrator.partner] = orchestrator.populate_items_from_catalog(limit:, skus:, force:)
  end
  res
end

Instance Method Details

#acknowledge_message_enabled?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 193

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

#acknowledge_message_senderObject



197
198
199
200
201
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 197

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

  AcknowledgeMessageSender.new(self, options)
end

#catalog_item_information_enabled?Boolean

Returns:

  • (Boolean)


249
250
251
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 249

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

#catalog_item_information_processorObject



271
272
273
274
275
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 271

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



253
254
255
256
257
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 253

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)


176
177
178
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 176

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

#confirm_message_processorObject



180
181
182
183
184
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 180

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 Also known as: shipment_message_sender



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

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

Amazon VC is a two stage process on , processing

Returns:

  • (Boolean)


335
336
337
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 335

def confirm_outbound_processing?
  true
end

#delete_listing_from_catalog_item(catalog_item: nil, amazon_variation: nil, http_method: 'DELETE', attribute_actions: nil, use_fba_sku: false) ⇒ Array

Builds and sends an Amazon Vendor Central listing delete message for a catalog item or variation.

Parameters:

  • catalog_item (CatalogItem, nil) (defaults to: nil)

    the catalog item to delete (mutually exclusive with amazon_variation)

  • amazon_variation (AmazonVariation, nil) (defaults to: nil)

    the variation to delete

  • http_method (String) (defaults to: 'DELETE')

    SP-API verb, defaults to 'DELETE'

  • attribute_actions (Hash, nil) (defaults to: nil)

    optional per-attribute patch actions

  • use_fba_sku (Boolean) (defaults to: false)

    target the FBA SKU variant

Returns:

  • (Array)

    sender results, or [false] when the processor yields a non-Result/failure

Raises:

  • (RuntimeError)

    if neither argument is given, or the catalog item is not an Amazon item



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 527

def delete_listing_from_catalog_item(catalog_item: nil, amazon_variation: nil, http_method: 'DELETE', attribute_actions: nil, use_fba_sku: false)
  raise 'Must provide either a catalog_item or an amazon_variation' unless catalog_item || amazon_variation
  raise 'Catalog Item not an amazon item or not in the right state' if catalog_item && !catalog_item.amazon_catalog_item?

  listing = catalog_item || amazon_variation
  res = []
  result = delete_listing_message_processor.process(listing, http_method:, attribute_actions:, use_fba_sku:)
  if result.try(:success?)
    Rails.logger.debug { "orchestrator#delete_listing_from_catalog_item for #{listing}, ecl: #{result.data}" }
    res << listing_message_sender.process(result.data, catalog_item_or_variation: listing, http_method:, use_fba_sku:)
  else
    Rails.logger.error "orchestrator#delete_listing_from_catalog_item for #{listing} failed: #{result.try(:error) || 'listing messages not enabled for this partner'}"
    res << false
  end
  res
end

#delete_listing_message_processorObject



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

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

  DeleteListingMessageProcessor.new(self, options)
end

#execute_inventory_flowObject



319
320
321
322
323
324
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 319

def execute_inventory_flow
  return unless active

  inventory_message_processor.process
  inventory_message_sender.process
end

#execute_order_flowObject



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 299

def execute_order_flow
  return unless active

  order_message_retriever.process
  sleep(1)
  order_message_processor.process
  sleep(1)
  packing_slip_retriever.process
  sleep(1)
  packing_slip_processor.process
  sleep(1)
  acknowledge_message_sender.process
  sleep(1)
  confirm_message_sender.process
  sleep(1)
  invoice_message_sender.process
  sleep(1)
  return_notification_message_sender.process
end

#ignore_back_ordersObject



330
331
332
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 330

def ignore_back_orders
  true
end

#inventory_message_enabled?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 112

def inventory_message_enabled?
  try(:inventory_message_remote_path).present?
end

#inventory_message_processorObject



116
117
118
119
120
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 116

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



122
123
124
125
126
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 122

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)


144
145
146
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 144

def invoice_message_enabled?
  try(:invoice_message_remote_path).present?
end

#invoice_message_processorObject



148
149
150
151
152
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 148

def invoice_message_processor
  return Edi::NullProcessor.new(self, :invoice_message_processor, options) unless invoice_message_enabled?

  InvoiceMessageProcessor.new(self, options)
end

#invoice_message_senderObject



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

def invoice_message_sender
  return Edi::NullProcessor.new(self, :invoice_message_sender, options) unless invoice_message_enabled?

  InvoiceMessageSender.new(self, options)
end

#listing_item_information_processorObject



265
266
267
268
269
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 265

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



259
260
261
262
263
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 259

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_message_enabled?Boolean

Returns:

  • (Boolean)


277
278
279
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 277

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

#listing_message_feed_enabled?Boolean

Returns:

  • (Boolean)


233
234
235
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 233

def listing_message_feed_enabled?
  listing_message_feed_enabled
end

#listing_message_feed_processorObject



243
244
245
246
247
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 243

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



237
238
239
240
241
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 237

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



287
288
289
290
291
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 287

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



281
282
283
284
285
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 281

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

  ListingMessageSender.new(self, options)
end

#merchant_idObject



108
109
110
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 108

def merchant_id
  vendor_code
end

#old_catalog_item_information_enabled?Boolean

Returns:

  • (Boolean)


339
340
341
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 339

def old_catalog_item_information_enabled?
  try(:catalog_item_information_remote_path).present?
end

#old_catalog_item_information_processorObject



359
360
361
362
363
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 359

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

  CatalogItemInformationProcessor.new(self, options)
end

#old_catalog_item_information_retrieverObject



343
344
345
346
347
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 343

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

  CatalogItemInformationRetriever.new(self, options)
end

#old_listing_item_validation_errors_retrieverObject



353
354
355
356
357
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 353

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

  ListingItemValidationErrorsRetriever.new(self, options)
end

#old_listing_item_validation_errors_retriever?Boolean

Returns:

  • (Boolean)


349
350
351
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 349

def old_listing_item_validation_errors_retriever?
  try(:catalog_item_information_remote_path).present?
end

#old_pull_catalog_information(catalog_item) ⇒ Object



365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 365

def old_pull_catalog_information(catalog_item)
  item = catalog_item.item
  asin = catalog_item.amazon_asin

  raise "No ASIN for catalog_item #{catalog_item.id}" if asin.blank?

  res = []
  ecl_cii = nil
  ecl_ve = nil
  locales.each do |locale| # en_US en_CA fr_CA
    ecl_cii = catalog_item_information_retriever.process(
      sku: item.sku, # here we use SKU because we are using the listing item endpoint which needs SKU vs the catalog item endpoint which needs ASIN
      locale:,
      file_info: {
        asin: asin,
        item_id: item.id,
        locale:
      }
    )
    if ecl_cii
      ecl_ve = listing_item_validation_errors_retriever.process(
        sku: item.sku, # here we use SKU because we are using the listing item endpoint which needs SKU vs the catalog item endpoint which needs ASIN
        product_type: catalog_item.amazon_reported_product_type || catalog_item.amazon_desired_product_type,
        locale:,
        file_info: {
          asin: asin,
          item_id: item.id,
          locale:
        }
      )
    end
    if ecl_cii && ecl_ve
      Rails.logger.debug { "orchestrator#pull_catalog_information, ecl_cii: #{ecl_cii}" }
      Rails.logger.debug { "orchestrator#pull_catalog_information, ecl_ve: #{ecl_ve}" }
      res << { locale => catalog_item_information_processor.process(ecl_cii, catalog_item:, locale:, ecl_ve:) }
    else
      Rails.logger.error "orchestrator#pull_catalog_information for catalog item #{catalog_item.id} yielded no ecl_cii or ecl_ve (asin #{asin} not found?)"
      res << { locale => false }
    end
  end
  res
end

#order_message_enabled?Boolean

Returns:

  • (Boolean)


128
129
130
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 128

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

#order_message_processorObject



138
139
140
141
142
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 138

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



132
133
134
135
136
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 132

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

  OrderMessageRetriever.new(self, options)
end

#packing_slip_enabled?Boolean

Returns:

  • (Boolean)


160
161
162
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 160

def packing_slip_enabled?
  try(:packing_slip_remote_path).present?
end

#packing_slip_processorObject



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

def packing_slip_processor
  return Edi::NullProcessor.new(self, :packing_slip_processor, options) unless packing_slip_enabled?

  PackingSlipProcessor.new(self, options)
end

#packing_slip_retrieverObject



164
165
166
167
168
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 164

def packing_slip_retriever
  return Edi::NullProcessor.new(self, :packing_slip_retriever, options) unless packing_slip_enabled?

  PackingSlipRetriever.new(self, options)
end

#populate_items_from_catalog(limit: nil, skus: nil, force: false) ⇒ Object

A method to populate our item data with amazon's catalog data
limit: how many records to process
skus: specific skus to process
force: normally we only will pull if the information is not present, use this to force a reset



566
567
568
569
570
571
572
573
574
575
576
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 566

def populate_items_from_catalog(limit: nil, skus: nil, force: false)
  catalog = customer_catalog
  catalog_items = catalog.catalog_items.amazons_with_asins.available_for_edi_feeds
  # Note that this should probably be specific to the locale so leverage mobility TODO
  catalog_items = catalog_items.where(items: { amazon_title: [nil, ''] }) unless force
  catalog_items = catalog_items.limit(limit) if limit
  catalog_items = catalog_items.where(items: { sku: skus }) if skus.present?
  catalog_items.map do |catalog_item|
    { name: catalog_item.to_s, catalog_item_id: catalog_item.id, res: pull_catalog_information(catalog_item) }
  end
end

#pull_amazon_variation_listing_information(amazon_variation) ⇒ Object



462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 462

def pull_amazon_variation_listing_information(amazon_variation)
  sku = amazon_variation.reported_vendor_sku(partner)

  # Listing info is marketplace-specific, not locale-specific.
  # The API call doesn't use the locale parameter, so we only need one call per marketplace.
  primary_locale = locales.first
  ecl = listing_item_information_retriever.process(
    sku: sku,
    locale: primary_locale,
    file_info: {
      sku: sku,
      locale: primary_locale
    }
  )
  if ecl
    Rails.logger.debug { "orchestrator#pull_amazon_variation_listing_information, ecl: #{ecl}" }
    [{ primary_locale => listing_item_information_processor.process(ecl, catalog_item_or_amazon_variation: amazon_variation, locale: primary_locale) }]
  else
    Rails.logger.error "orchestrator#pull_amazon_variation_listing_information for amazon variation #{amazon_variation.id} yielded no ecl (sku #{sku} not found?)"
    [{ primary_locale => false }]
  end
end

#pull_catalog_information(catalog_item) ⇒ Object



408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 408

def pull_catalog_information(catalog_item)
  item = catalog_item.item
  asin = catalog_item.amazon_asin

  raise "No ASIN for catalog_item #{catalog_item.id}" if asin.blank?

  res = []
  locales.each do |locale| # en_US en_CA fr_CA
    ecl = catalog_item_information_retriever.process(
      asin: asin,
      locale:,
      file_info: {
        asin: asin,
        item_id: item.id,
        locale:
      }
    )
    if ecl
      Rails.logger.debug { "orchestrator#pull_catalog_information, ecl: #{ecl}" }
      res << { locale => catalog_item_information_processor.process(ecl, catalog_item:, locale:) }
    else
      Rails.logger.error "orchestrator#pull_catalog_information for catalog item #{catalog_item.id} yielded no ecl (asin #{asin} not found?)"
      res << { locale => false }
    end
  end
  res
end

#pull_listing_information(catalog_item) ⇒ Object



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 436

def pull_listing_information(catalog_item)
  item = catalog_item.item
  sku = catalog_item.reported_vendor_sku

  # Listing info is marketplace-specific, not locale-specific.
  # The API call doesn't use the locale parameter, so we only need one call per marketplace.
  primary_locale = locales.first
  ecl = listing_item_information_retriever.process(
    sku: sku,
    locale: primary_locale,
    file_info: {
      sku: sku,
      item_id: item.id,
      catalog_item_id: catalog_item.id,
      locale: primary_locale
    }
  )
  if ecl
    Rails.logger.debug { "orchestrator#pull_listing_information, ecl: #{ecl}" }
    [{ primary_locale => listing_item_information_processor.process(ecl, catalog_item_or_amazon_variation: catalog_item, locale: primary_locale) }]
  else
    Rails.logger.error "orchestrator#pull_listing_information for catalog item #{catalog_item.id} yielded no ecl (sku #{sku} not found?)"
    [{ primary_locale => false }]
  end
end

#push_listing_from_amazon_variation(amazon_variation) ⇒ Array

Builds and sends an Amazon Vendor Central listing PUT message for a single variation.

Parameters:

Returns:

  • (Array)

    sender results, or [false] when the processor yields a non-Result/failure



548
549
550
551
552
553
554
555
556
557
558
559
560
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 548

def push_listing_from_amazon_variation(amazon_variation)
  res = []
  http_method = 'PUT'
  result = listing_message_processor.process(amazon_variation, http_method:)
  if result.try(:success?)
    Rails.logger.debug { "orchestrator#push_listing_from_amazon_variation for amazon variation #{amazon_variation.id}, ecl: #{result.data}" }
    res << listing_message_sender.process(result.data, catalog_item_or_variation: amazon_variation, http_method:)
  else
    Rails.logger.error "orchestrator#push_listing_from_amazon_variation for amazon variation #{amazon_variation.id} failed: #{result.try(:error) || 'listing messages not enabled for this partner'}"
    res << false
  end
  res
end

#push_listing_from_catalog_item(catalog_item, http_method: 'PATCH', attribute_actions: nil, use_fba_sku: false) ⇒ Array

Builds and sends an Amazon Vendor Central listing-items message for a catalog item.

Runs the listing message through the processor, then hands the resulting
ECL to the sender. When the partner has no listing-message path configured
the processor is an NullProcessor whose #process returns a falsy
non-Result, so the success check is guarded with #try.

Parameters:

  • catalog_item (CatalogItem)

    the Amazon catalog item to push

  • http_method (String) (defaults to: 'PATCH')

    SP-API verb ('PUT' to create/replace, 'PATCH' to update)

  • attribute_actions (Hash, nil) (defaults to: nil)

    optional per-attribute patch actions

  • use_fba_sku (Boolean) (defaults to: false)

    push the FBA SKU variant instead of FBM

Returns:

  • (Array)

    sender results, or [false] when the processor yields a non-Result/failure

Raises:

  • (RuntimeError)

    if the catalog item is not an Amazon item in an api-ready state



498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 498

def push_listing_from_catalog_item(catalog_item, http_method: 'PATCH', attribute_actions: nil, use_fba_sku: false)
  item = catalog_item.item

  raise 'Catalog item not an amazon item or not in the right state' unless catalog_item.amazon_catalog_item? && catalog_item.api_ready_state?

  res = []
  result = listing_message_processor.process(catalog_item, http_method:, attribute_actions:, use_fba_sku:)
  if result.try(:success?)
    Rails.logger.debug { "orchestrator#push_listing_from_catalog_item for catalog item #{catalog_item.id}, ecl: #{result.data}" }
    res << listing_message_sender.process(result.data, catalog_item_or_variation: catalog_item, http_method:, use_fba_sku:)
  else
    # result is a non-Result (NullProcessor#process returns logger.debug => false) when listing
    # messages aren't configured for the partner; #try keeps that from raising NoMethodError.
    Rails.logger.error "orchestrator#push_listing_from_catalog_item for catalog item #{catalog_item.id} failed: #{result.try(:error) || 'listing messages not enabled for this partner'}. " \
                       "ASIN: #{item.amazon_asin}, SKU: #{catalog_item.sku}, Partner: #{partner}."
    res << false
  end
  res
end

#return_notification_message_enabled?Boolean

Returns:

  • (Boolean)


217
218
219
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 217

def return_notification_message_enabled?
  try(:return_notification_message_remote_path).present?
end

#return_notification_message_processorObject



221
222
223
224
225
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 221

def return_notification_message_processor
  return Edi::NullProcessor.new(self, :return_notification_message_processor, options) unless return_notification_message_enabled?

  ReturnNotificationMessageProcessor.new(self, options)
end

#return_notification_message_senderObject



227
228
229
230
231
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 227

def return_notification_message_sender
  return Edi::NullProcessor.new(self, :return_notification_message_sender, options) unless return_notification_message_enabled?

  ReturnNotificationMessageSender.new(self, options)
end

#ship_code_mapperObject



326
327
328
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 326

def ship_code_mapper
  ShipCodeMapper.new(self)
end

#transaction_message_enabled?Boolean

Returns:

  • (Boolean)


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

def transaction_message_enabled?
  try(:transaction_message_remote_path).present?
end

#transaction_message_processorObject



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

def transaction_message_processor
  return Edi::NullProcessor.new(self, :transaction_message_processor, options) unless transaction_message_enabled?

  TransactionMessageProcessor.new(self, options)
end