Class: CatalogItemPresenter

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

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



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'app/presenters/catalog_item_presenter.rb', line 229

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)
  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' }) if r.parent_catalog_item.present?
  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?
    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' }) if r.listing_message_enabled? || r.walmart_catalog_item?
    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



254
255
256
# File 'app/presenters/catalog_item_presenter.rb', line 254

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)


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

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



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

def advertised_price_percent_off_msrp_human
  percent_off_msrp_human(retail_price)
end

#amazon_business_price_with_currencyObject



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

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



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

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



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

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



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

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)


95
96
97
98
99
100
101
# File 'app/presenters/catalog_item_presenter.rb', line 95

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

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

#amz_min_seller_price_override_with_currencyObject



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

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


12
13
14
# File 'app/presenters/catalog_item_presenter.rb', line 12

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


26
27
28
# File 'app/presenters/catalog_item_presenter.rb', line 26

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


22
23
24
# File 'app/presenters/catalog_item_presenter.rb', line 22

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


6
7
8
9
10
# File 'app/presenters/catalog_item_presenter.rb', line 6

def breadcrumb_item
  return unless catalog_item.store_item && 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


16
17
18
19
20
# File 'app/presenters/catalog_item_presenter.rb', line 16

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


30
31
32
# File 'app/presenters/catalog_item_presenter.rb', line 30

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


42
43
44
45
46
47
48
49
50
51
# File 'app/presenters/catalog_item_presenter.rb', line 42

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



258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'app/presenters/catalog_item_presenter.rb', line 258

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


34
35
36
# File 'app/presenters/catalog_item_presenter.rb', line 34

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


38
39
40
# File 'app/presenters/catalog_item_presenter.rb', line 38

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

#identifiersObject



53
54
55
56
57
58
59
60
61
# File 'app/presenters/catalog_item_presenter.rb', line 53

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



277
278
279
280
281
282
283
284
285
286
# File 'app/presenters/catalog_item_presenter.rb', line 277

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



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

def map_price_percent_off_msrp_human
  percent_off_msrp_human(map_price)
end

#map_price_with_currencyObject



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

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



178
179
180
# File 'app/presenters/catalog_item_presenter.rb', line 178

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



219
220
221
222
223
# File 'app/presenters/catalog_item_presenter.rb', line 219

def max_discount_human
  return unless max_discount

  h.number_to_percentage(max_discount, strip_insignificant_zeros: true)
end

#msrp_with_currencyObject



147
148
149
150
151
152
153
# File 'app/presenters/catalog_item_presenter.rb', line 147

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



115
116
117
# File 'app/presenters/catalog_item_presenter.rb', line 115

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

#new_sale_price_with_currencyObject



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

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



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

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



111
112
113
# File 'app/presenters/catalog_item_presenter.rb', line 111

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

#parent_catalog_item_discountObject



199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'app/presenters/catalog_item_presenter.rb', line 199

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



213
214
215
216
217
# File 'app/presenters/catalog_item_presenter.rb', line 213

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



71
72
73
# File 'app/presenters/catalog_item_presenter.rb', line 71

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 && parent_catalog_item.amount
end

#percent_off_msrp_human(value) ⇒ Object



182
183
184
185
186
187
188
# File 'app/presenters/catalog_item_presenter.rb', line 182

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

  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



163
164
165
166
167
168
169
170
171
172
# File 'app/presenters/catalog_item_presenter.rb', line 163

def price_with_percent_off_from_msrp(price_with_currency, percent_off_human)
  return price_with_currency unless percent_off_human.present?

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

#price_with_vat_and_currencyObject



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

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:



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

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:



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

delegate :qty_on_hand, to: :store_item

#retail_price_with_currencyObject



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

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



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

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



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

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



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

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



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

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



225
226
227
# File 'app/presenters/catalog_item_presenter.rb', line 225

def status_label
  h.catalog_item_state_badge(r)
end

#store_item_cost_with_currencyObject



75
76
77
# File 'app/presenters/catalog_item_presenter.rb', line 75

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



63
64
65
# File 'app/presenters/catalog_item_presenter.rb', line 63

def store_name
  store_item.store.name
end