Class: Edi::AmazonVc::Orchestrator

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

Overview

Orchestrates Amazon Vendor Central Seller API EDI message flows.

See Also:

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?, #supports_flow?, #test_mode?

Constructor Details

This class inherits a constructor from Edi::BaseOrchestrator

Class Method Details

.execute_transaction_message_processor(options = {}) ⇒ void

This method returns an undefined value.

Parameters:

Options Hash (options):

  • logger (Logger)

    logger to use (defaults to Rails.logger)



268
269
270
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 268

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

.partnersHash{Symbol => Hash}

Returns partner key => configuration hash.

Returns:

  • (Hash{Symbol => Hash})

    partner key => configuration hash



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
107
108
109
110
111
112
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 15

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) ⇒ Hash{Symbol => Array<Hash>}

Returns partner key => per-partner results.

Parameters:

  • limit (Integer, nil) (defaults to: nil)

    maximum number of records to process per partner

  • skus (Array<String>, nil) (defaults to: nil)

    specific SKUs to process

  • force (Boolean) (defaults to: false)

    pull even when information is already present

Returns:

  • (Hash{Symbol => Array<Hash>})

    partner key => per-partner results



717
718
719
720
721
722
723
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 717

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 true when order acknowledgements are configured for this partner.

Returns:

  • (Boolean)

    true when order acknowledgements are configured for this partner



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

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

#acknowledge_message_senderEdi::AmazonVc::AcknowledgeMessageSender, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:



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

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 true when catalog item information is configured for this partner.

Returns:

  • (Boolean)

    true when catalog item information is configured for this partner



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

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

#catalog_item_information_processorEdi::AmazonVc::CatalogItemInformationProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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_retrieverEdi::AmazonVc::CatalogItemInformationRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



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

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 true when shipment confirmations are configured for this partner.

Returns:

  • (Boolean)

    true when shipment confirmations are configured for this partner



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

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

#confirm_message_processorEdi::AmazonVc::ConfirmMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  ConfirmMessageProcessor.new(self, options)
end

#confirm_message_senderEdi::AmazonVc::ConfirmMessageSender, Edi::NullProcessor Also known as: shipment_message_sender

Returns the sender, or a null processor when disabled.

Returns:



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

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

Returns true because Amazon VC uses two-stage outbound processing.

Returns:

  • (Boolean)

    true because Amazon VC uses two-stage outbound processing



437
438
439
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 437

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 (VariantGroup, nil) (defaults to: nil)

    the Amazon parent-listing row 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



658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 658

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_processorEdi::AmazonVc::DeleteListingMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



385
386
387
388
389
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 385

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_flowvoid

This method returns an undefined value.



417
418
419
420
421
422
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 417

def execute_inventory_flow
  return unless active

  inventory_message_processor.process
  inventory_message_sender.process
end

#execute_order_flowvoid

This method returns an undefined value.



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 394

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_ordersBoolean

Returns true to ignore back orders for Amazon VC.

Returns:

  • (Boolean)

    true to ignore back orders for Amazon VC



432
433
434
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 432

def ignore_back_orders
  true
end

#inventory_message_enabled?Boolean

Returns true when inventory messages are configured for this partner.

Returns:

  • (Boolean)

    true when inventory messages are configured for this partner



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

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

#inventory_message_processorEdi::AmazonVc::InventoryMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  InventoryMessageProcessor.new(self, options)
end

#inventory_message_senderEdi::AmazonVc::InventoryMessageSender, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:



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

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 true when invoice messages are configured for this partner.

Returns:

  • (Boolean)

    true when invoice messages are configured for this partner



168
169
170
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 168

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

#invoice_message_processorEdi::AmazonVc::InvoiceMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  InvoiceMessageProcessor.new(self, options)
end

#invoice_message_senderEdi::AmazonVc::InvoiceMessageSender, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:



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

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_processorEdi::AmazonVc::ListingItemInformationProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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_retrieverEdi::AmazonVc::ListingItemInformationRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



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

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 true when listing messages are configured for this partner.

Returns:

  • (Boolean)

    true when listing messages are configured for this partner



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

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

#listing_message_feed_enabled?Boolean

Returns true when listing message feeds are enabled for this partner.

Returns:

  • (Boolean)

    true when listing message feeds are enabled for this partner



296
297
298
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 296

def listing_message_feed_enabled?
  listing_message_feed_enabled
end

#listing_message_feed_processorEdi::BaseEdiService, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



312
313
314
315
316
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 312

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_senderEdi::BaseEdiService, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:



303
304
305
306
307
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 303

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_processorEdi::AmazonVc::ListingMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



376
377
378
379
380
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 376

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

  ListingMessageProcessor.new(self, options)
end

#listing_message_senderEdi::AmazonVc::ListingMessageSender, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:



367
368
369
370
371
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 367

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

  ListingMessageSender.new(self, options)
end

#merchant_idString

Returns the vendor code used as the merchant ID.

Returns:

  • (String)

    the vendor code used as the merchant ID



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

def merchant_id
  vendor_code
end

#old_catalog_item_information_enabled?Boolean

Returns true when legacy catalog item information is configured.

Returns:

  • (Boolean)

    true when legacy catalog item information is configured



442
443
444
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 442

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

#old_catalog_item_information_processorEdi::AmazonVc::CatalogItemInformationProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



472
473
474
475
476
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 472

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_retrieverEdi::AmazonVc::CatalogItemInformationRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



449
450
451
452
453
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 449

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_retrieverEdi::AmazonVc::ListingItemValidationErrorsRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



463
464
465
466
467
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 463

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 true when legacy listing validation errors can be retrieved.

Returns:

  • (Boolean)

    true when legacy listing validation errors can be retrieved



456
457
458
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 456

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

#old_pull_catalog_information(catalog_item) ⇒ Array<Hash>

Returns locale => result hashes.

Parameters:

  • catalog_item (CatalogItem)

    the catalog item to enrich

Returns:

  • (Array<Hash>)

    locale => result hashes

Raises:

  • (RuntimeError)

    if the catalog item has no ASIN



483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 483

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 true when order messages are configured for this partner.

Returns:

  • (Boolean)

    true when order messages are configured for this partner



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

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

#order_message_processorEdi::AmazonVc::OrderMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  OrderMessageProcessor.new(self, options)
end

#order_message_retrieverEdi::AmazonVc::OrderMessageRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



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

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 true when packing slips are configured for this partner.

Returns:

  • (Boolean)

    true when packing slips are configured for this partner



191
192
193
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 191

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

#packing_slip_processorEdi::AmazonVc::PackingSlipProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  PackingSlipProcessor.new(self, options)
end

#packing_slip_retrieverEdi::AmazonVc::PackingSlipRetriever, Edi::NullProcessor

Returns the retriever, or a null processor when disabled.

Returns:



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

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) ⇒ Array<Hash>

Returns result hashes for each catalog item processed.

Parameters:

  • limit (Integer, nil) (defaults to: nil)

    maximum number of records to process

  • skus (Array<String>, nil) (defaults to: nil)

    specific SKUs to process

  • force (Boolean) (defaults to: false)

    pull even when information is already present

Returns:

  • (Array<Hash>)

    result hashes for each catalog item processed



699
700
701
702
703
704
705
706
707
708
709
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 699

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) ⇒ Array<Hash>

Returns locale => result hashes.

Parameters:

  • amazon_variation (VariantGroup)

    the Amazon parent-listing row to look up

Returns:

  • (Array<Hash>)

    locale => result hashes



593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 593

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) ⇒ Array<Hash>

Returns locale => result hashes.

Parameters:

  • catalog_item (CatalogItem)

    the catalog item to enrich

Returns:

  • (Array<Hash>)

    locale => result hashes

Raises:

  • (RuntimeError)

    if the catalog item has no ASIN



531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 531

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) ⇒ Array<Hash>

Returns locale => result hashes.

Parameters:

  • catalog_item (CatalogItem)

    the catalog item to look up

Returns:

  • (Array<Hash>)

    locale => result hashes



563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 563

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:

  • amazon_variation (VariantGroup)

    the Amazon parent-listing row to push

Returns:

  • (Array)

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



679
680
681
682
683
684
685
686
687
688
689
690
691
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 679

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



629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 629

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 true when return notification messages are configured for this partner.

Returns:

  • (Boolean)

    true when return notification messages are configured for this partner



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

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

#return_notification_message_processorEdi::AmazonVc::ReturnNotificationMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:

  • (Edi::AmazonVc::ReturnNotificationMessageProcessor, Edi::NullProcessor)

    the processor, or a null processor when disabled



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

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_senderEdi::AmazonVc::ReturnNotificationMessageSender, Edi::NullProcessor

Returns the sender, or a null processor when disabled.

Returns:

  • (Edi::AmazonVc::ReturnNotificationMessageSender, Edi::NullProcessor)

    the sender, or a null processor when disabled



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

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_mapperEdi::AmazonVc::ShipCodeMapper

Returns the ship code mapper.

Returns:



427
428
429
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 427

def ship_code_mapper
  ShipCodeMapper.new(self)
end

#transaction_message_enabled?Boolean

Returns true when transaction messages are configured for this partner.

Returns:

  • (Boolean)

    true when transaction messages are configured for this partner



252
253
254
# File 'app/services/edi/amazon_vc/orchestrator.rb', line 252

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

#transaction_message_processorEdi::AmazonVc::TransactionMessageProcessor, Edi::NullProcessor

Returns the processor, or a null processor when disabled.

Returns:



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

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

  TransactionMessageProcessor.new(self, options)
end