Class: Edi::Wayfair::CatalogItemUpdateSender

Inherits:
BaseEdiService show all
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 =
'https://api.wayfair.io/sandbox/v1/product-catalog-api/graphql'
UPDATE_CATALOG_ITEMS_MUTATION =

GraphQL mutation for updating catalog items

<<~GRAPHQL.squish
  mutation UpdateMarketSpecificCatalogItems($input: UpdateMarketSpecificCatalogItemsInput!) {
    updateCatalogEntitiesMutations {
      updateMarketSpecificCatalogItems(input: $input) {
        requestHandle
      }
    }
  }
GRAPHQL
STATUS_QUERY =

GraphQL query to check update status

<<~GRAPHQL.squish
  query StatusOfUpdateRequest($requestHandle: String!) {
    statusOfUpdateRequest(requestHandle: $requestHandle) {
      requestHandle
      requestStatus
      requestStatusMessage
      submissionTime
      completionTime
      numberOfItemsTotal
      numberOfItemsSucceeded
      numberOfItemsFailed
      numberOfItemsPending
      failedItems {
        sku
        errors {
          errorCode
          errorMessage
        }
      }
    }
  }
GRAPHQL

Constants included from AddressAbbreviator

AddressAbbreviator::MAX_LENGTH

Instance Attribute Summary

Attributes inherited from BaseEdiService

#orchestrator

Instance Method Summary collapse

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, #options, #tagged_logger

Constructor Details

This class inherits a constructor from Edi::BaseEdiService

Instance Method Details

#check_status(request_handle) ⇒ StatusResult

Check the status of a previous update request

Parameters:

  • request_handle (String)

    The request handle from a previous update

Returns:



114
115
116
117
118
119
120
121
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
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 114

def check_status(request_handle)
  transport = build_catalog_transport
  query_payload = build_graphql_payload(STATUS_QUERY, { requestHandle: request_handle })

  result = transport.send_request('POST', catalog_api_url, query_payload, transport.build_request_headers)
  http_response = result[:http_res]

  unless http_response&.status&.success?
    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)

  StatusResult.new(
    success: true,
    status: status_data[:requestStatus],
    message: status_data[:requestStatusMessage],
    details: status_data
  )
end

#process(catalog_item:, attributes: nil, dry_run: false) ⇒ UpdateResult

Send a catalog item update to Wayfair

Parameters:

  • catalog_item (CatalogItem)

    The catalog item to update

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

    Optional list of attribute names to send

  • dry_run (Boolean) (defaults to: false)

    If true, only generates payload without sending

Returns:



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
# File 'app/services/edi/wayfair/catalog_item_update_sender.rb', line 66

def process(catalog_item:, attributes: nil, dry_run: false)
  wayfair_schema = orchestrator.wayfair_schema_for(catalog_item.wayfair_taxonomy_category_id_in_effect)

  unless wayfair_schema
    return UpdateResult.new(
      success: false,
      request_handle: 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_handle: 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_handle: 'dry_run',
      errors: [],
      ecl: nil,
      payload: item_payload
    )
  end

  # Build the full mutation input
  mutation_input = build_mutation_input(item_payload)

  # Send to Wayfair
  send_update(catalog_item, mutation_input, item_payload)
end