Class: Catalog::AssignCatalogItem

Inherits:
BaseService show all
Defined in:
app/services/catalog/assign_catalog_item.rb

Overview

Operation to assign a catalog item from one parent catalog

Defined Under Namespace

Classes: Result

Constant Summary collapse

BASE_PRICE_FACTOR =

This is a default price based on cogs when not supplied

3.0

Instance Method Summary collapse

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 BaseService

Instance Method Details

#process(target_catalog, item, catalog_item_params = {}) ⇒ Object

target catalog: the target catalog to use
item, the item to create in the destination catalog
catalog_item_params, defaults to apply



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
# File 'app/services/catalog/assign_catalog_item.rb', line 14

def process(target_catalog, item, catalog_item_params = {})
  # Discount to apply is first the parametrized amount or the target catalog setting for parent catalog discount
  discount_to_apply = catalog_item_params.delete(:discount_to_apply).presence || target_catalog.parent_catalog_discount || 0.0
  discount_to_apply_refurb = catalog_item_params.delete(:discount_to_apply_refurb).presence || target_catalog.parent_catalog_discount_refurb || 0.0

  add_kit_components_to_catalog = catalog_item_params.delete(:add_kit_components_to_catalog)

  new_catalog_item = target_catalog.catalog_items.build(catalog_item_params)
  # Default state is based on target_catalog
  new_catalog_item.state = target_catalog.default_catalog_item_state if target_catalog.default_catalog_item_state
  # Do we have a source catalog to pull other defaults from?
  new_catalog_item.store_item = target_catalog.store.store_items.available.find_by(item_id: item.id)
  errors = []
  # See if we have a parent catalog item we can inherit some defaults from it
  if (parent_catalog = target_catalog.parent_catalog)
    if (parent_catalog_item = parent_catalog.catalog_items.with_item.find_by(Item[:id].eq(item.id))) && parent_catalog_item.valid?
      new_catalog_item.max_discount ||= parent_catalog_item.max_discount
      new_catalog_item.amount ||= parent_catalog_item.amount # starting point
      new_catalog_item.store_item ||= parent_catalog_item.store_item
    end
    # This only works if we have an existing parent catalog to pull defaults from, otherwise store item and what not also have to be created
    if add_kit_components_to_catalog && new_catalog_item&.store_item&.item
      # Find the kit components (items) which are not already in the target catalog
      new_catalog_item.store_item.item.kit_components.select { |kc| kc.catalog_items.joins(:store_item).where(catalog_id: target_catalog.id, store_items: { location: new_catalog_item.store_item.location }).empty? }.each do |kc|
        # Find the kit component in the parent catalog
        if (parent_kc_ci = parent_catalog.catalog_items.with_item.find_by(Item[:id].eq(kc.id))) && parent_kc_ci.valid?
          parent_kc_ci_attributes = parent_kc_ci.deep_dup.attributes.with_indifferent_access.merge(state: 'active_hidden')
          r = Catalog::CreateCatalogItem.new.process(target_catalog, parent_kc_ci_attributes) # better to hide from feed since they are automatically added per Elodie
          errors.concat(r&.catalog_item&.errors&.full_messages || [])
        else
          errors << "Kit component #{kc.sku} not found in parent catalog #{parent_catalog.name} [#{parent_catalog.id}]"
        end
      end
    end
  end

  # Sensible default for max discount
  new_catalog_item.max_discount ||= 100
  # If all else fails, zero it out
  new_catalog_item.amount ||= 0
  # If our new catalog item amount is zero, we will first start in invalid_catalog_item state
  new_catalog_item.state = 'invalid_catalog_item' if new_catalog_item.amount.zero?
  # If we have a catalog amount and discount let's go and apply the discount
  if new_catalog_item.amount
    if item.condition_new? && discount_to_apply.positive? && discount_to_apply <= 1.0
      new_catalog_item.amount = new_catalog_item.amount * (1.0 - discount_to_apply)
    elsif item.condition_refurbished? && discount_to_apply_refurb.positive? && discount_to_apply_refurb <= 1.0
      new_catalog_item.amount = new_catalog_item.amount * (1.0 - discount_to_apply_refurb)
    end
  end
  # Since we don't know let's start with cogs * 3
  new_catalog_item.amount = (new_catalog_item.store_item.unit_cogs * BASE_PRICE_FACTOR).round(2) if new_catalog_item.amount.nil? && new_catalog_item.store_item&.unit_cogs&.positive?

  begin
    if new_catalog_item.save
      Result.new catalog_item: new_catalog_item,
                 catalog_item_created: true,
                 messages: ["Catalog Item #{new_catalog_item.id} created for item #{item.sku}"]
    else
      errors.concat(new_catalog_item.errors.full_messages)
      Result.new catalog_item: new_catalog_item,
                 catalog_item_created: false,
                 messages: ["Unable to create catalog item for #{item.sku}"] + errors
    end
  rescue StandardError => e
    errors << e.message
    Result.new catalog_item: new_catalog_item,
               catalog_item_created: false,
               messages: ["Unable to create catalog item for #{item.sku}"] + errors
  end
end