Class: Edi::Wayfair::ListingGenerator::ListingGenerator

Inherits:
Object
  • Object
show all
Defined in:
app/services/edi/wayfair/listing_generator/listing_generator.rb

Overview

Generates Wayfair product update payloads using taxonomy-based attributes
Similar to Amazon's JsonListingGenerator but for Wayfair's updateMarketSpecificCatalogItems mutation

Usage:
generator = ListingGenerator.new(catalog_item)
payload = generator.generate

=> { supplierPartNumber: "SKU123", attributes: [...] }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(catalog_item, wayfair_schema: nil) ⇒ ListingGenerator

Returns a new instance of ListingGenerator.



15
16
17
18
19
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 15

def initialize(catalog_item, wayfair_schema: nil)
  @catalog_item = catalog_item
  @wayfair_schema = wayfair_schema || fetch_schema
  @errors = []
end

Instance Attribute Details

#catalog_itemObject (readonly)

Returns the value of attribute catalog_item.



13
14
15
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 13

def catalog_item
  @catalog_item
end

#errorsObject (readonly)

Returns the value of attribute errors.



13
14
15
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 13

def errors
  @errors
end

#wayfair_schemaObject (readonly)

Returns the value of attribute wayfair_schema.



13
14
15
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 13

def wayfair_schema
  @wayfair_schema
end

Instance Method Details

#attribute_coverageHash

Check which attributes can be mapped

Returns:

  • (Hash)

    { mappable: [...], missing: [...], unmapped_required: [...] }



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

def attribute_coverage
  return { mappable: [], missing: [], unmapped_required: [] } unless wayfair_schema

  available = Attributes::AttributeFactory.attributes_available
  schema_ids = wayfair_schema.attribute_ids
  required_ids = wayfair_schema.required_attributes.map { |a| a['taxonomyAttributeId'] }

  mappable = []
  missing = []
  unmapped_required = []

  available.each do |attr_name|
    mapper = Attributes::AttributeFactory.build(attr_name, catalog_item: catalog_item, wayfair_schema: wayfair_schema)
    if mapper.build.present?
      mappable << attr_name
    else
      missing << attr_name
    end
  rescue StandardError => e
    Rails.logger.debug "ListingGenerator: Error checking #{attr_name}: #{e.message}"
    missing << attr_name
  end

  # Find required attributes we don't have mappers for
  Attributes::AttributeFactory.attributes_by_taxonomy_id.each do |id, _klass|
    if required_ids.include?(id) && !mappable.any? { |m| Attributes::AttributeFactory.build(m, catalog_item: catalog_item, wayfair_schema: wayfair_schema).taxonomy_attribute_id == id rescue false }
      attr_def = wayfair_schema.find_attribute(id)
      unmapped_required << { id: id, title: attr_def&.dig('title') }
    end
  end

  { mappable: mappable, missing: missing, unmapped_required: unmapped_required }
end

#generate(attributes: nil) ⇒ Hash

Generate the full update payload

Parameters:

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

    Optional list of attribute names to include (nil = all available)

Returns:

  • (Hash)

    The update payload for updateMarketSpecificCatalogItems



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 24

def generate(attributes: nil)
  @errors = []

  unless wayfair_schema
    @errors << 'No Wayfair schema available for this catalog item'
    return nil
  end

  attribute_payloads = build_attribute_payloads(attributes)

  if attribute_payloads.empty?
    @errors << 'No attributes could be mapped'
    return nil
  end

  {
    supplierPartNumber: supplier_part_number,
    attributes: attribute_payloads
  }
end

#generate_required_onlyObject

Generate payload for only required attributes



46
47
48
49
50
51
52
53
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 46

def generate_required_only
  required_ids = wayfair_schema&.required_attributes&.map { |a| a['taxonomyAttributeId'] } || []
  required_names = required_ids.filter_map do |id|
    Attributes::AttributeFactory.attributes_by_taxonomy_id[id]&.attribute_name
  end

  generate(attributes: required_names)
end

#previewObject

Preview what would be sent (for debugging)



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'app/services/edi/wayfair/listing_generator/listing_generator.rb', line 92

def preview
  payload = generate
  return { error: errors.first } unless payload

  {
    supplier_part_number: payload[:supplierPartNumber],
    attribute_count: payload[:attributes].size,
    attributes: payload[:attributes].map do |attr|
      {
        id: attr[:taxonomyAttributeId],
        title: wayfair_schema.find_attribute(attr[:taxonomyAttributeId])&.dig('title'),
        value: attr[:value] || attr[:values]
      }
    end
  }
end