Class: Edi::Wayfair::CatalogItemUpdateSender
- Inherits:
-
BaseEdiService
- Object
- BaseService
- BaseEdiService
- Edi::Wayfair::CatalogItemUpdateSender
- Includes:
- CatalogApiTransport
- Defined in:
- app/services/edi/wayfair/catalog_item_update_sender.rb
Overview
Sends catalog item updates to Wayfair using the Product Catalog Update API
Uses the updateMarketSpecificCatalogItems mutation
API Documentation: https://developer.wayfair.io/posts/catalog-product-update
Usage:
orchestrator = Edi::Wayfair::Orchestrator.build(:wayfair_us)
sender = CatalogItemUpdateSender.new(orchestrator)
result = sender.process(catalog_item: catalog_item)
Defined Under Namespace
Classes: StatusResult, UpdateResult
Constant Summary collapse
- CATALOG_UPDATE_API_URL =
Product Catalog Update API endpoints
'https://api.wayfair.io/v1/product-catalog-api/graphql'- SANDBOX_CATALOG_UPDATE_API_URL =
URL for sandbox catalog update api.
'https://api.wayfair.io/sandbox/v1/product-catalog-api/graphql'- UPDATE_CATALOG_ITEMS_MUTATION =
GraphQL mutation for updating catalog items.
Live-schema notes (verified 2026-06-12 via sandbox introspection): the
response field isrequestId(not requestHandle). <<~GRAPHQL.squish mutation UpdateMarketSpecificCatalogItems($input: UpdateMarketSpecificCatalogItemsInput!) { updateCatalogEntitiesMutations { updateMarketSpecificCatalogItems(input: $input) { requestId } } } GRAPHQL
- STATUS_QUERY =
GraphQL query to check update status.
statusOfUpdateRequesttakes a
StatusOfUpdateRequestInput ({ requestId, supplierId }) and reports the
async validation outcome (status COMPLETED / BLOCKED / PROCESSING …)
with per-entity problems. <<~GRAPHQL.squish query StatusOfUpdateRequest($input: StatusOfUpdateRequestInput!) { statusOfUpdateRequest(input: $input) { requestId validationOnly status problems { code title detail catalogEntityIdentifier catalogEntityPropertyId inputValue } } } GRAPHQL
Constants included from CatalogApiTransport
Edi::Wayfair::CatalogApiTransport::CATALOG_API_BASE, Edi::Wayfair::CatalogApiTransport::CATALOG_AUTH_URL
Constants included from RequestIdentifiable
RequestIdentifiable::REQUEST_ID_HEADERS
Constants included from AddressAbbreviator
AddressAbbreviator::MAX_LENGTH
Instance Attribute Summary
Attributes inherited from BaseEdiService
Attributes inherited from BaseService
Instance Method Summary collapse
-
#check_status(request_id) ⇒ StatusResult
Check the status of a previous update request.
-
#process(catalog_item:, attributes: nil, dry_run: false, validate_only: false) ⇒ UpdateResult
Send a catalog item update to Wayfair.
Methods inherited from BaseEdiService
#amazon_feed_product_type, #duplicate_po_already_notified?, #initialize, #mark_duplicate_po_as_notified, #onboard_ordered_catalog_items, #report_order_creation_issues, #safe_process_edi_communication_log
Methods included from RequestIdentifiable
Methods included from 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
#check_status(request_id) ⇒ StatusResult
Check the status of a previous update request
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 137 def check_status(request_id) transport = build_catalog_transport variables = { input: { requestId: request_id, supplierId: orchestrator.try(:warehouse_code).to_s } } query_payload = build_graphql_payload(STATUS_QUERY, variables) result = transport.send_request('POST', catalog_api_url, query_payload, transport.build_request_headers) http_response = result[:http_res] unless http_response&.status&.between?(200, 299) return StatusResult.new( success: false, status: 'ERROR', message: "HTTP error: #{http_response&.status}", details: nil ) end json_data = JSON.parse(http_response.body.to_s).with_indifferent_access if json_data[:errors].present? return StatusResult.new( success: false, status: 'ERROR', message: json_data[:errors].first&.dig('message'), details: json_data[:errors] ) end status_data = json_data.dig(:data, :statusOfUpdateRequest) problems = Array(status_data&.dig(:problems)) StatusResult.new( success: true, status: status_data&.dig(:status), message: problems.first&.then { |p| [p[:code], p[:detail].presence || p[:title]].compact.join(': ') }, details: status_data ) end |
#process(catalog_item:, attributes: nil, dry_run: false, validate_only: false) ⇒ UpdateResult
Send a catalog item update to Wayfair
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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 85 def process(catalog_item:, attributes: nil, dry_run: false, validate_only: false) # Effective = desired override when set, else the current synced category. # Wayfair uses taxonomyCategoryId as context for the attribute ids; it does # not reclass an existing item. Class changes still require support. taxonomy_category_id = catalog_item.wayfair_effective_taxonomy_category_id wayfair_schema = orchestrator.wayfair_schema_for(taxonomy_category_id) unless wayfair_schema return UpdateResult.new( success: false, request_id: nil, errors: ['No taxonomy schema available. Please sync catalog item first.'], ecl: nil, payload: nil ) end # Generate the update payload generator = ListingGenerator::ListingGenerator.new(catalog_item, wayfair_schema: wayfair_schema) item_payload = generator.generate(attributes: attributes) unless item_payload return UpdateResult.new( success: false, request_id: nil, errors: generator.errors, ecl: nil, payload: nil ) end if dry_run logger.info "Wayfair Catalog Update [DRY RUN]: Would send #{item_payload[:attributes].size} attributes for #{item_payload[:supplierPartNumber]}" return UpdateResult.new( success: true, request_id: 'dry_run', errors: [], ecl: nil, payload: item_payload ) end # Build the full mutation input mutation_input = build_mutation_input(item_payload, taxonomy_category_id: taxonomy_category_id, validate_only: validate_only) # Send to Wayfair send_update(catalog_item, mutation_input, item_payload) end |