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 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
#duplicate_po_already_notified?, #initialize, #mark_duplicate_po_as_notified, #report_order_creation_issues, #safe_process_edi_communication_log
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
122 123 124 125 126 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 154 155 156 157 158 159 |
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 122 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
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 113 114 115 116 117 |
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 73 def process(catalog_item:, attributes: nil, dry_run: false, validate_only: false) taxonomy_category_id = catalog_item.wayfair_taxonomy_category_id_in_effect 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 |