Class: Edi::Amazon::ListingMessageFeedProcessor
- Inherits:
-
BaseEdiService
- Object
- BaseService
- BaseEdiService
- Edi::Amazon::ListingMessageFeedProcessor
- Defined in:
- app/services/edi/amazon/listing_message_feed_processor.rb
Overview
Service object: listing message feed processor.
Constant Summary collapse
- DEFAULT_ATTRIBUTE_PAYLOAD =
Default attribute payload for the daily listing PATCH sync.
PRODUCT attributes only. Offer/fulfillment attributes (fulfillment_availability,
purchasable_offer, list_price) are deliberately excluded here — those are submitted
through the dedicated inventory_advice / price_advice messages. Sending them on a
product PATCH only triggers Amazon's INVALID_ATTRIBUTE (90000900) warnings and
double-submits offer data. { item_package_quantity: :replace, item_package_weight: :replace, item_package_dimensions: :replace, supplier_declared_dg_hz_regulation: :replace }.freeze
- BATTERIES_REQUIRED_ATTRIBUTE_PAYLOAD =
Batteries required attribute payload.
{ batteries_required: :replace }.freeze
Constants included from Edi::AddressAbbreviator
Edi::AddressAbbreviator::MAX_LENGTH
Instance Attribute Summary
Attributes inherited from BaseEdiService
Attributes inherited from BaseService
Instance Method Summary collapse
- #append_catalog_item(messages, ci, idx, sku, fba = false) ⇒ Object
- #append_catalog_items(catalog_items) ⇒ Object
- #build_json(catalog_items: nil, states: nil) ⇒ Object
- #get_amazon_json_patches(catalog_item, product_type: nil, fba: false) ⇒ Object
- #get_default_attribute_payload(catalog_item, product_type: nil) ⇒ Object
- #load_catalog_items(states: nil) ⇒ Object
- #process(catalog_items: nil, states: nil) ⇒ Object
Methods inherited from BaseEdiService
#duplicate_po_already_notified?, #initialize, #mark_duplicate_po_as_notified, #report_order_creation_issues, #safe_process_edi_communication_log
Methods included from Edi::AddressAbbreviator
#abbreviate_street, #collect_street_originals, #record_address_abbreviation_notes
Methods inherited from BaseService
#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger
Constructor Details
This class inherits a constructor from Edi::BaseEdiService
Instance Method Details
#append_catalog_item(messages, ci, idx, sku, fba = false) ⇒ Object
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 103 def append_catalog_item(, ci, idx, sku, fba = false) begin discontinued = ci.discontinued? || ci.pending_discontinue? || ci.in_hide_from_feed_state? return if fba && discontinued # Don't know what else to do? pt = ci.amazon_listing_reported_product_type || ci.amazon_reported_product_type || ci.amazon_desired_product_type || 'SPACE_HEATER' patches = get_amazon_json_patches(ci, product_type: pt, fba:) return unless pt.present? && patches.any? = { messageId: idx, sku: sku, operationType: 'PATCH', # Here we are only implementing the PATCH operations productType: pt.upcase, patches: patches } << rescue StandardError => e logger.error "Error processing catalog item #{ci.id} for partner #{orchestrator.partner}: #{e.}" ErrorReporting.error(e, catalog_item_id: ci.id, partner_id: orchestrator.partner) end end |
#append_catalog_items(catalog_items) ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 89 def append_catalog_items(catalog_items) # see: https://github.com/amzn/selling-partner-api-models/blob/main/schemas/feeds/listings-feed-message-schema-v2.json idx = 0 = [] catalog_items.find_each do |ci| ErrorReporting.scoped(catalog_item_id: ci.id) do logger.info "Processing catalog item #{ci.id} for partner #{orchestrator.partner}" append_catalog_item(, ci, idx += 1, ci.reported_vendor_sku, false) append_catalog_item(, ci, idx += 1, ci.amazon_fba_sku, true) if ci.has_amazon_fba? end end end |
#build_json(catalog_items: nil, states: nil) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 74 def build_json(catalog_items: nil, states: nil) # see: https://github.com/amzn/selling-partner-api-models/blob/main/schemas/feeds/listings-feed-schema-v2.json catalog_items ||= load_catalog_items(states:) logger.info "#{catalog_items.size} items in json listing feed payload" feed_hash = { header: { sellerId: orchestrator.merchant_id, version: '2.0', issueLocale: 'en_US' }, messages: append_catalog_items(catalog_items) } feed_hash.to_json end |
#get_amazon_json_patches(catalog_item, product_type: nil, fba: false) ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 127 def get_amazon_json_patches(catalog_item, product_type: nil, fba: false) # see: https://developer-docs.amazon.com/sp-api/docs/listings-items-api-v2021-08-01-reference#listingsitempatchrequest # see: https://developer-docs.amazon.com/sp-api/docs/listings-items-api-v2021-08-01-reference#patchoperation # see: https://developer-docs.amazon.com/sp-api/docs/listing-workflow-migration-tutorial#submitting-inventory-data # "patches": [ # { # "op": "replace", # "path": "/attributes/fulfillment_availability", # "value": [ # { # "fulfillment_channel_code": "DEFAULT", # "quantity": 10 # } # ] # } # ] # Here we send a daily PRODUCT-ONLY feed: # - shipping dimensions (item_package_quantity, item_package_weight, item_package_dimensions) # - dangerous-goods regulation (supplier_declared_dg_hz_regulation) # Inventory (fulfillment_availability) and price (purchasable_offer / list_price) are NOT # sent here — they go through the dedicated inventory_advice and price_advice messages. amazon_product_listing_generator = Edi::Amazon::JsonListingGenerator::Factory.generator_for_catalog_item(catalog_item, product_type:, attribute_actions: get_default_attribute_payload(catalog_item, product_type:), fba:, business_price_available: orchestrator.try(:business_price_available)) amazon_product_listing_generator.get_patches end |
#get_default_attribute_payload(catalog_item, product_type: nil) ⇒ Object
54 55 56 57 58 59 60 61 62 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 54 def get_default_attribute_payload(catalog_item, product_type: nil) product_type ||= catalog_item.amazon_product_type_in_effect amazon_schema = AmazonSchema.amazon_channel_seller.where(product_type: product_type).where(amazon_marketplace_id: catalog_item.catalog.amazon_marketplace.id).first attribute_payload = DEFAULT_ATTRIBUTE_PAYLOAD # rubocop:disable Performance/InefficientHashSearch -- AmazonSchema delegates :keys (Array) to its properties hash but defines no #key?, so #keys.include? is required here attribute_payload = attribute_payload.merge(BATTERIES_REQUIRED_ATTRIBUTE_PAYLOAD) if amazon_schema.keys.include?(:batteries_required) # Almost all product types will require this but not all, like RELAY, so test if it's in there # rubocop:enable Performance/InefficientHashSearch attribute_payload end |
#load_catalog_items(states: nil) ⇒ Object
64 65 66 67 68 69 70 71 72 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 64 def load_catalog_items(states: nil) states ||= %w[active require_vendor_update pending_vendor_update pending_discontinue] catalog_items = orchestrator.customer.catalog .catalog_items .for_edi_feeds_by_states(states) .amazons_with_asins .with_item.eager_load(:store_item, :item) catalog_items.order(StoreItem[:qty_available]) end |
#process(catalog_items: nil, states: nil) ⇒ Object
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 |
# File 'app/services/edi/amazon/listing_message_feed_processor.rb', line 24 def process(catalog_items: nil, states: nil) # see: https://developer-docs.amazon.com/sp-api/docs/listings-feed-type-values#listings-feed # see: https://developer-docs.amazon.com/sp-api/docs/building-listings-management-workflows-guide#should-i-submit-in-bulk-using-the-json_listings_feed-or-individually-with-the-listings-items-api # see: https://developer-docs.amazon.com/sp-api/docs/listings-items-api-v2021-08-01-reference#patchlistingsitem logger.info "Creating listing message feed for partner #{orchestrator.partner}" catalog_items ||= load_catalog_items(states:) return :empty_set if catalog_items.blank? # Here we want to handle whether to send a feed for many catalog items or a single patch for a single catalog item to avoid all the 429 throttling when sending multiple feeds if catalog_items.size == 1 ci = catalog_items.first ci.amazon_send_patch_listing_information(attribute_actions: get_default_attribute_payload(ci)) else ecl = nil EdiCommunicationLog.transaction do data_json = build_json(catalog_items:, states:) ecl = EdiCommunicationLog.create_outbound_file_from_data( data: data_json, data_type: 'json', file_extension: 'cii', partner: orchestrator.partner, category: 'listing_feed_data', resources: catalog_items, file_info: {} ) end ecl end end |