Class: CatalogItemPresenter

Inherits:
BasePresenter show all
Includes:
Presenters::StandardOperationsForRecord
Defined in:
app/presenters/catalog_item_presenter.rb

Overview

Presenter: catalog item presenter.

Instance Attribute Summary

Attributes inherited from BasePresenter

#current_account, #options, #url_helper

Delegated Instance Attributes collapse

Methods inherited from BasePresenter

#can?, #capture, #concat, #content_tag, #fa_icon, #link_to, #number_to_currency, #simple_format

Instance Method Summary collapse

Methods inherited from BasePresenter

#h, #initialize, #present, presents, #r, #safe_present, #u

Constructor Details

This class inherits a constructor from BasePresenter

Instance Method Details

#actionsObject



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'app/presenters/catalog_item_presenter.rb', line 244

def actions
  links = []
  return links unless can?(:update, r)

  links << link_to('Edit', h.edit_catalog_item_path(r))
  links += h.available_events_links(r)
  if r.parent_catalog_item.present?
    links << link_to('Reset Price', h.reset_price_to_parent_discount_catalog_item_path(r), data: { turbo_method: :post, turbo_confirm: 'This will reset the price to the parent catalog item and apply the catalog item discount' })
  end
  links << :separator
  if can?(:create, EdiCommunicationLog)
    links << link_to('Push Inventory', h.push_inventory_message_catalog_item_path(r), data: { turbo_method: :post, turbo_confirm: 'This will push the inventory to EDI/API partners linked to this catalog item' }) if r.inventory_message_enabled?
    links << link_to('Push Pricing', h.push_price_message_catalog_item_path(r), data: { turbo_method: :post, turbo_confirm: 'This will push the pricing to EDI/API partners linked to this catalog item' }) if r.price_message_enabled?
    links << link_to('Push Listing Data', h.amazon_listing_data_catalog_item_path(r)) if r.listing_message_enabled?
    if r.listing_message_enabled? || r.walmart_catalog_item?
      links << link_to('Delete Listing', h.delete_amazon_listing_data_catalog_item_path(r), data: { turbo_method: :delete, turbo_confirm: 'This will delete/retire the listing on the marketplace' })
    end
    links << :separator
  end
  if h.can?(:destroy, r)
    links << if r.ok_to_destroy?
               link_to('Delete', h.catalog_item_path(r), data: { turbo_method: :delete })
             else
               { content: 'Cannot be deleted' }
             end
  end
  links
end

#actions_combo_buttonObject



273
274
275
# File 'app/presenters/catalog_item_presenter.rb', line 273

def actions_combo_button
  h.render_combo_drop_down actions, main_link_class: 'btn-primary', main_link_style: 'padding-left: 2em; padding-right: 2em'
end

#advertised_price_map_violation?Boolean

MAP violation for the advertised/retail price displayed in CRM.
We treat this as a violation whenever retail_price < map_price (when both present),
regardless of retailer_type, because marketplaces are the primary use case.

Returns:

  • (Boolean)


208
209
210
211
212
# File 'app/presenters/catalog_item_presenter.rb', line 208

def advertised_price_map_violation?
  return false unless retail_price.present? && map_price.present?

  retail_price < map_price
end

#advertised_price_percent_off_msrp_humanObject



170
171
172
# File 'app/presenters/catalog_item_presenter.rb', line 170

def advertised_price_percent_off_msrp_human
  percent_off_msrp_human(retail_price)
end

#amazon_business_price_with_currencyObject



94
95
96
# File 'app/presenters/catalog_item_presenter.rb', line 94

def amazon_business_price_with_currency
  h.number_to_currency(amazon_business_price_with_tax, unit: amount_currency_symbol) if amazon_business_price_with_tax
end

#amazon_maximum_seller_allowed_price_with_currencyObject



102
103
104
# File 'app/presenters/catalog_item_presenter.rb', line 102

def amazon_maximum_seller_allowed_price_with_currency
  h.number_to_currency(amazon_maximum_seller_allowed_price_with_tax, unit: amount_currency_symbol) if amazon_maximum_seller_allowed_price_with_tax
end

#amazon_minimum_seller_allowed_price_with_currencyObject



98
99
100
# File 'app/presenters/catalog_item_presenter.rb', line 98

def amazon_minimum_seller_allowed_price_with_currency
  h.number_to_currency(amazon_minimum_seller_allowed_price_with_tax, unit: amount_currency_symbol) if amazon_minimum_seller_allowed_price_with_tax
end

#amount_with_currencyObject



122
123
124
# File 'app/presenters/catalog_item_presenter.rb', line 122

def amount_with_currency
  h.number_to_currency amount, unit: amount_currency_symbol if amount
end

#amz_min_seller_price_override_exceeds_max_discount?Boolean

Returns:

  • (Boolean)


110
111
112
113
114
115
116
# File 'app/presenters/catalog_item_presenter.rb', line 110

def amz_min_seller_price_override_exceeds_max_discount?
  return false unless amz_min_seller_price_override.present? && amount.present? && amount.positive?
  return false if max_discount_allowed_percentage.blank?

  discount_percentage = ((amount - amz_min_seller_price_override) / amount) * 100
  discount_percentage > max_discount_allowed_percentage
end

#amz_min_seller_price_override_with_currencyObject



106
107
108
# File 'app/presenters/catalog_item_presenter.rb', line 106

def amz_min_seller_price_override_with_currency
  h.number_to_currency(amz_min_seller_price_override, unit: amount_currency_symbol) if amz_min_seller_price_override
end


14
15
16
# File 'app/presenters/catalog_item_presenter.rb', line 14

def breadcrumb_all_catalogs
  h.(:li, h.link_to('Catalogs', h.catalogs_path), class: 'breadcrumb-item')
end


28
29
30
# File 'app/presenters/catalog_item_presenter.rb', line 28

def breadcrumb_catalog_item
  h.(:li, h.link_to("#{sku} (CI)", h.catalog_item_path(id)), class: 'breadcrumb-item') unless new_record?
end


24
25
26
# File 'app/presenters/catalog_item_presenter.rb', line 24

def breadcrumb_current_catalog
  h.(:li, h.link_to(catalog.name, h.catalog_path(catalog_id)), class: 'breadcrumb-item')
end


8
9
10
11
12
# File 'app/presenters/catalog_item_presenter.rb', line 8

def breadcrumb_item
  return unless catalog_item.store_item&.item

  h.(:li, h.link_to(catalog_item.item.sku, h.item_path(catalog_item.item.id)), class: 'breadcrumb-item')
end


18
19
20
21
22
# File 'app/presenters/catalog_item_presenter.rb', line 18

def breadcrumb_parent_catalog
  return unless (parent_catalog = catalog.parent_catalog)

  h.(:li, h.link_to(parent_catalog.name, h.catalog_path(parent_catalog)), class: 'breadcrumb-item')
end


32
33
34
# File 'app/presenters/catalog_item_presenter.rb', line 32

def breadcrumb_parent_catalog_item
  h.(:li, h.link_to("#{sku} (CI)", h.catalog_item_path(parent_catalog_item.id)), class: 'breadcrumb-item') if parent_catalog_item
end


57
58
59
60
61
62
63
64
65
66
# File 'app/presenters/catalog_item_presenter.rb', line 57

def breadcrumbs
  h.capture do
    h.concat breadcrumb_item
    h.concat breadcrumb_all_catalogs
    h.concat breadcrumb_parent_catalog
    h.concat breadcrumb_parent_catalog_item
    h.concat breadcrumb_current_catalog
    h.concat breadcrumb_catalog_item
  end
end

#catalog_item_tab_optionsObject



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'app/presenters/catalog_item_presenter.rb', line 277

def catalog_item_tab_options
  tab_hsh = {
    main: { remote_href: h.tab_main_catalog_item_path(self) },
    price_history: { remote_href: h.tab_price_history_catalog_item_path(self) },
    descriptions: { remote_href: h.tab_descriptions_catalog_item_path(self) },
    specs: { remote_href: h.tab_specs_catalog_item_path(self) },
    images: { remote_href: h.tab_images_catalog_item_path(self) },
    dependents: { remote_href: h.tab_dependents_catalog_item_path(self) },
    siblings: { remote_href: h.show_siblings_catalog_item_path(self) },
    edi: { remote_href: h.show_edi_catalog_item_path(self) }
  }
  tab_hsh[:amazon] = { remote_href: h.show_amazon_catalog_item_path(self) } if amazon_catalog_item?
  tab_hsh[:wayfair] = { remote_href: h.show_wayfair_catalog_item_path(self) } if wayfair_catalog_item?
  tab_hsh[:retailer_probes] = { remote_href: h.tab_retailer_probes_catalog_item_path(self) } if catalog.external_price_check_enabled?
  tab_hsh[:sibling_retailers] = { remote_href: h.tab_sibling_retailers_catalog_item_path(self), label: 'Sibling Retailers' }
  tab_hsh
end

Renders a delete button for the catalog item.

Parameters:

Options Hash (options):

  • class (String)

    CSS classes

  • data (Hash)

    data attributes

Returns:

  • (String, nil)

    HTML link, or nil when not permitted



43
44
45
# File 'app/presenters/catalog_item_presenter.rb', line 43

def destroy_catalog_item_link(options = {})
  destroy_record_button(catalog_item, options)
end

Renders an edit button for the catalog item.

Parameters:

Options Hash (options):

  • class (String)

    CSS classes

Returns:

  • (String, nil)

    HTML link, or nil when not permitted



53
54
55
# File 'app/presenters/catalog_item_presenter.rb', line 53

def edit_catalog_item_link(options = {})
  edit_record_button(catalog_item, options)
end

#identifiersObject



68
69
70
71
72
73
74
75
76
# File 'app/presenters/catalog_item_presenter.rb', line 68

def identifiers
  ids = {}
  ids['Supplier SKUs'] = item.supplier_skus.join(', ') if item.supplier_skus.present?
  ids['ASIN'] = amazon_asin if amazon_asin.present?
  ids['TPPN'] = third_party_part_number if third_party_part_number.present?
  ids['TPSKU'] = third_party_sku if third_party_sku.present? && third_party_sku != item.sku
  ids['UPC'] = item.upc if item.upc.present?
  ids
end

#image_profile_marketplaceObject

Determines which image profile marketplace to show for this catalog item



296
297
298
299
300
301
302
303
304
305
# File 'app/presenters/catalog_item_presenter.rb', line 296

def image_profile_marketplace
  catalog_id = catalog.id
  if CatalogConstants::AMAZON_CATALOG_IDS.include?(catalog_id)
    'AMZ'
  elsif CatalogConstants::WALMART_CATALOGS.include?(catalog_id)
    'WAL'
  else
    'WYS'
  end
end

#map_price_percent_off_msrp_humanObject



174
175
176
# File 'app/presenters/catalog_item_presenter.rb', line 174

def map_price_percent_off_msrp_human
  percent_off_msrp_human(map_price)
end

#map_price_with_currencyObject



158
159
160
# File 'app/presenters/catalog_item_presenter.rb', line 158

def map_price_with_currency
  h.number_to_currency map_price, unit: retail_price_currency_symbol if map_price
end

#map_price_with_percent_offObject



193
194
195
# File 'app/presenters/catalog_item_presenter.rb', line 193

def map_price_with_percent_off
  price_with_percent_off_from_msrp(map_price_with_currency, map_price_percent_off_msrp_human)
end

#max_discount_humanObject



234
235
236
237
238
# File 'app/presenters/catalog_item_presenter.rb', line 234

def max_discount_human
  return unless max_discount

  h.number_to_percentage(max_discount, strip_insignificant_zeros: true)
end

#msrp_with_currencyObject



162
163
164
165
166
167
168
# File 'app/presenters/catalog_item_presenter.rb', line 162

def msrp_with_currency
  return unless msrp

  # Use parent_catalog's currency if available, otherwise fall back to current catalog's currency
  currency_symbol = parent_catalog_currency_symbol || retail_price_currency_symbol
  h.number_to_currency msrp, unit: currency_symbol
end

#new_price_with_currencyObject



130
131
132
# File 'app/presenters/catalog_item_presenter.rb', line 130

def new_price_with_currency
  h.number_to_currency new_price, unit: amount_currency_symbol if new_price
end

#new_sale_price_with_currencyObject



142
143
144
# File 'app/presenters/catalog_item_presenter.rb', line 142

def new_sale_price_with_currency
  h.number_to_currency new_sale_price, unit: amount_currency_symbol if new_sale_price
end

#new_sale_price_with_vat_and_currencyObject



150
151
152
# File 'app/presenters/catalog_item_presenter.rb', line 150

def new_sale_price_with_vat_and_currency
  h.number_to_currency new_sale_price_with_vat, unit: amount_currency_symbol if new_sale_price_with_vat
end

#old_amount_with_currencyObject



126
127
128
# File 'app/presenters/catalog_item_presenter.rb', line 126

def old_amount_with_currency
  h.number_to_currency old_amount, unit: amount_currency_symbol if old_amount
end

#parent_catalog_item_discountObject



214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'app/presenters/catalog_item_presenter.rb', line 214

def parent_catalog_item_discount
  return unless parent_catalog_item
  return unless effective_price

  parent_amount = parent_catalog_item.amount
  if parent_amount == effective_price
    0
  elsif parent_amount&.positive?
    ((1 - (effective_price / parent_amount)) * 100).round(2)
  else
    100
  end
end

#parent_catalog_item_discount_humanObject



228
229
230
231
232
# File 'app/presenters/catalog_item_presenter.rb', line 228

def parent_catalog_item_discount_human
  return unless (pcid = parent_catalog_item_discount)

  h.number_to_percentage(pcid, strip_insignificant_zeros: true)
end

#parent_catalog_price_with_currencyObject



86
87
88
# File 'app/presenters/catalog_item_presenter.rb', line 86

def parent_catalog_price_with_currency
  h.number_to_currency parent_catalog_item_amount, unit: parent_catalog_item.amount_currency_symbol if parent_catalog_item&.amount
end

#percent_off_msrp_human(value) ⇒ Object



197
198
199
200
201
202
203
# File 'app/presenters/catalog_item_presenter.rb', line 197

def percent_off_msrp_human(value)
  return unless msrp.present? && msrp.to_d.positive?
  return if value.blank?

  pct = (1 - (value.to_d / msrp.to_d)) * 100
  h.number_to_percentage(pct, precision: 0, strip_insignificant_zeros: true)
end

#price_with_percent_off_from_msrp(price_with_currency, percent_off_human) ⇒ Object



178
179
180
181
182
183
184
185
186
187
# File 'app/presenters/catalog_item_presenter.rb', line 178

def price_with_percent_off_from_msrp(price_with_currency, percent_off_human)
  return price_with_currency if percent_off_human.blank?

  h.safe_join(
    [
      price_with_currency,
      h.tag.small("(#{percent_off_human} off)", class: 'text-body-secondary ms-1')
    ]
  )
end

#price_with_vat_and_currencyObject



134
135
136
# File 'app/presenters/catalog_item_presenter.rb', line 134

def price_with_vat_and_currency
  h.number_to_currency price_with_vat, unit: amount_currency_symbol if price_with_vat
end

#qty_availableObject

Alias for Store_item#qty_available

Returns:

  • (Object)

    Store_item#qty_available

See Also:



84
# File 'app/presenters/catalog_item_presenter.rb', line 84

delegate :qty_available, to: :store_item

#qty_on_handObject

Alias for Store_item#qty_on_hand

Returns:

  • (Object)

    Store_item#qty_on_hand

See Also:



82
# File 'app/presenters/catalog_item_presenter.rb', line 82

delegate :qty_on_hand, to: :store_item

#retail_price_with_currencyObject



154
155
156
# File 'app/presenters/catalog_item_presenter.rb', line 154

def retail_price_with_currency
  h.number_to_currency retail_price, unit: retail_price_currency_symbol if retail_price
end

#retail_price_with_percent_offObject



189
190
191
# File 'app/presenters/catalog_item_presenter.rb', line 189

def retail_price_with_percent_off
  price_with_percent_off_from_msrp(retail_price_with_currency, advertised_price_percent_off_msrp_human)
end

#retailer_requested_cost_with_currencyObject



118
119
120
# File 'app/presenters/catalog_item_presenter.rb', line 118

def retailer_requested_cost_with_currency
  h.number_to_currency(retailer_requested_cost, unit: amount_currency_symbol) if retailer_requested_cost
end

#sale_price_with_currencyObject



138
139
140
# File 'app/presenters/catalog_item_presenter.rb', line 138

def sale_price_with_currency
  h.number_to_currency sale_price, unit: amount_currency_symbol if sale_price
end

#sale_price_with_vat_and_currencyObject



146
147
148
# File 'app/presenters/catalog_item_presenter.rb', line 146

def sale_price_with_vat_and_currency
  h.number_to_currency sale_price_with_vat, unit: amount_currency_symbol if sale_price_with_vat
end

#status_labelObject



240
241
242
# File 'app/presenters/catalog_item_presenter.rb', line 240

def status_label
  h.catalog_item_state_badge(r)
end

#store_item_cost_with_currencyObject



90
91
92
# File 'app/presenters/catalog_item_presenter.rb', line 90

def store_item_cost_with_currency
  h.number_to_currency store_item.unit_cogs.round(4), unit: parent_catalog_item.amount_currency_symbol if store_item&.unit_cogs
end

#store_nameObject



78
79
80
# File 'app/presenters/catalog_item_presenter.rb', line 78

def store_name
  store_item.store.name
end