Class: VariantGroup::AmazonDefaults

Inherits:
Object
  • Object
show all
Defined in:
app/models/variant_group/amazon_defaults.rb

Overview

Derivation rules for Amazon parent listings (absorbed from AmazonVariation's
class methods): parent-SKU/name conventions per heating-product family,
variation-theme defaults, and version-SKU cloning. Pure functions — the
VariantGroup amazon rows carry the state.

Constant Summary collapse

VARIATION_THEME_ATTRIBUTE_MAP =

Maps Amazon variation theme components (e.g. SIZE_NAME, COLOR) to the
corresponding JSON listing generator attribute names used by
Edi::Amazon::JsonListingGenerator::Attributes classes.

Examples:

theme "SIZE_NAME/COLOR_NAME" resolves to [:size, :color]

{
  'SIZE'          => :size,
  'SIZE_NAME'     => :size,
  'COLOR'         => :color,
  'COLOR_NAME'    => :color,
  'STYLE'         => :style,
  'STYLE_NAME'    => :style,
  'VOLTAGE'       => :voltage,
  'CONFIGURATION' => :configuration,
  'MATERIAL'      => :material,
  'MATERIAL_TYPE' => :material,
  'PATTERN'       => :pattern,
  'PATTERN_NAME'  => :pattern
}.freeze

Class Method Summary collapse

Class Method Details

.find_or_create_amazon_override_for_item(item, amazon_marketplace:) ⇒ VariantGroup

Find or create the Amazon parent listing row for the item, scoped to the
marketplace, under the item's default family (created on demand).

Parameters:

Returns:

Raises:

  • (ArgumentError)


138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'app/models/variant_group/amazon_defaults.rb', line 138

def find_or_create_amazon_override_for_item(item, amazon_marketplace:)
  parent_sku = parent_identifiers_for_item(item)[:parent_sku]
  catalog = amazon_marketplace.seller_central_catalog
  raise ArgumentError, "no Seller Central catalog for marketplace #{amazon_marketplace.id}" unless catalog

  row = build_amazon_override_row(item, parent_sku, catalog)
  # The override's membership mirrors what's actually listed under the
  # Amazon parent — never the default family's. Absorb every item
  # currently listed under this parent (a first onboard under an
  # inheriting override makes membership explicit) plus this item. The
  # row lock serializes position allocation across concurrent onboards.
  row.with_lock do
    absorb_listed_members(row)
    row.variant_group_members.find_or_create_by!(item:) do |member|
      member.position = (row.variant_group_members.maximum(:position) || 0) + 1
    end
  end
  row
end

.next_version_sku(sku) ⇒ String

Next -vN version of an Amazon parent SKU for relist cloning:
"SKU123" with existing "SKU123-v2", "SKU123-v4" -> "SKU123-v5".

Parameters:

  • sku (String)

Returns:

  • (String)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/models/variant_group/amazon_defaults.rb', line 33

def next_version_sku(sku)
  base_sku = sku.sub(/-v\d+$/, '')
  existing = VariantGroup.amazon_channel
                         .where('external_sku = ? OR external_sku LIKE ?', base_sku, "#{base_sku}-v%")
                         .pluck(:external_sku)

  max_version = existing.filter_map do |existing_sku|
    if existing_sku == base_sku
      1 # the original counts as version 1
    elsif existing_sku =~ /^#{Regexp.escape(base_sku)}-v(\d+)$/
      Regexp.last_match(1).to_i
    end
  end.max || 1

  "#{base_sku}-v#{max_version + 1}"
end

.parent_identifiers_for_item(item) ⇒ Hash{Symbol=>String,nil}

Conventional Amazon parent SKU + model name for an item, by
heating-product SKU family.

Parameters:

Returns:

  • (Hash{Symbol=>String,nil})

    :parent_sku, :model_name



54
55
56
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
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'app/models/variant_group/amazon_defaults.rb', line 54

def parent_identifiers_for_item(item)
  item_sku = item.sku
  if item_sku.match?(/^TCT.*-KIT-.*-MEM-/) # TCT120-KIT-OP-MEM-030
    _, _, control_type, = item_sku.split('-')
    parent_sku = "TCT-#{control_type}-MEM-KIT"
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TCT.*-KIT-O\w+-/) # non-membrane kit TCT240-KIT-OP-115
    _, _, control_type, = item_sku.split('-')
    parent_sku = "TCT-#{control_type}-KIT"
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TCT.*-KIT-(UWG5|UTN5)-MEM/)
    parent_sku = 'TCT-UWG5-MEM-KIT'
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TCT.*-KIT-(UWG5|UTN5)/)
    parent_sku = 'TCT-UWG5-KIT'
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TRT.*-KIT-O\w+-1.5x/) # TRT120-KIT-OP-1.5x18
    _, _, control_type, = item_sku.split('-')
    parent_sku = "TRT-#{control_type}-FLEX-KIT"
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TRT.*-KIT-O\w+-3/) # e.g. TRT120-KIT-ON-3.0x08
    _, _, control_type, = item_sku.split('-')
    parent_sku = "TRT-#{control_type}-EASYMAT-KIT"
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TRT.*-KIT-(UWG5|UTN5)/) # e.g. TRT120-KIT-UWG5-3.0x08
    _, _, control_type, = item_sku.split('-')
    parent_sku = "TRT-#{control_type}-FLEX-KIT"
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^WHMA-\d{3}-\d{4}$/) # WHMA-120-0205
    parent_sku = 'WHMA'
    model_name = "#{parent_sku} Snow Melting Mat"
  elsif item_sku.match?(/^WHCA-\d{3}-\d{4}$/) # WHCA-120-0043
    parent_sku = 'WHCA'
    model_name = "#{parent_sku} Snow Melting Cable"
  elsif item_sku.match?(/^TCT/) && item.is_heating_element?
    parent_sku = 'TCT-CABLE'
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TRT\d{3}-1.5x/) && item.is_heating_element?
    parent_sku = 'TRT-FLEXROLL'
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^TRT.*-[23]/) && item.is_heating_element?
    parent_sku = 'TRT-EASYMAT'
    model_name = "#{parent_sku} Floor Heating Kit"
  elsif item_sku.match?(/^ERT\d{3}-3/) # ERT120-3.0x10
    parent_sku = 'ERT-EASYMAT'
    model_name = "#{parent_sku} Environ Easy Mat"
  end
  { parent_sku:, model_name: }
end

.preview_theme_value_for_item(item, attribute) ⇒ String?

Preview value of a variation theme attribute for an item — mirrors
BaseAttribute#fetch_value without needing a catalog_item.

Parameters:

  • item (Item)
  • attribute (Symbol, String)

    theme attribute name (e.g. :voltage, :size)

Returns:

  • (String, nil)

    the item's spec output for the attribute



129
130
131
# File 'app/models/variant_group/amazon_defaults.rb', line 129

def preview_theme_value_for_item(item, attribute)
  item.spec_output(:"amazon_#{attribute}").presence || item.spec_output(attribute).presence
end

.variation_name_for_item(item) ⇒ String

Returns parent display name derived from the item's Amazon title.

Parameters:

Returns:

  • (String)

    parent display name derived from the item's Amazon title



116
117
118
119
120
121
122
# File 'app/models/variant_group/amazon_defaults.rb', line 116

def variation_name_for_item(item)
  title = item.title_for_amazon.to_s
  return item.sku if title.blank?

  title.gsub(/[\d.]+ sq ft/, '').gsub(/[\d.]+ sqft/, '').gsub(/\(\d{3}V\)/, '')
       .squeeze(' ')
end

.variation_theme_name_for_item(item) ⇒ String?

Returns conventional variation theme for the item's family.

Parameters:

Returns:

  • (String, nil)

    conventional variation theme for the item's family



106
107
108
109
110
111
112
# File 'app/models/variant_group/amazon_defaults.rb', line 106

def variation_theme_name_for_item(item)
  if item.sku.start_with?('TCT', 'TRT', 'ERT')
    'VOLTAGE/SIZE' # native two-axis theme in the SPACE_HEATER schema (US + CA)
  elsif item.sku.start_with?('WHMA', 'WHCA')
    'VOLTAGE/SIZE_NAME'
  end
end