Class: Maintenance::ItemMaintenance

Inherits:
BaseService show all
Defined in:
app/services/maintenance/item_maintenance.rb

Overview

Service object: item maintenance.

Instance Attribute Summary

Attributes inherited from BaseService

#options

Instance Method Summary collapse

Methods inherited from BaseService

#initialize, #log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger

Constructor Details

This class inherits a constructor from BaseService

Instance Method Details

#discontinue_old_custom_matsObject



53
54
55
56
57
58
59
# File 'app/services/maintenance/item_maintenance.rb', line 53

def discontinue_old_custom_mats
  logger.info 'Discontinuing old custom mats'
  old_mats = Item.active.joins(:product_category).where(
    "product_categories.url LIKE '%-custom-%' and items.created_at < ? and not exists(select 1 from store_items si where si.item_id = items.id and si.qty_on_hand > 0)", 1.year.ago
  )
  old_mats.find_each(&:discontinue_self_and_dependents)
end

#discontinue_old_unused_itemsObject



49
50
51
# File 'app/services/maintenance/item_maintenance.rb', line 49

def discontinue_old_unused_items
  Maintenance::Item::DiscontinueUnusedItems.new.process
end

#discontinue_pending_discontinued_catalog_items(older_than = nil) ⇒ Object

Transitions pending_discontinue catalog items to discontinued once their
wait period has elapsed. Orchestrators can define a custom lifetime via
pending_discontinue_lifetime_duration (e.g. Menard: 1 week). Items in
catalogs without a custom lifetime use the default of 1 day.

Parameters:

  • older_than (Time, nil) (defaults to: nil)

    manual override that bypasses orchestrator
    lookup and applies to ALL items (for console/testing use)



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'app/services/maintenance/item_maintenance.rb', line 91

def discontinue_pending_discontinued_catalog_items(older_than = nil)
  all_pending = CatalogItem.where(state: 'pending_discontinue')
  total = 0

  if older_than
    total += transition_batch(all_pending, older_than)
  else
    custom_lifetimes = Edi::BaseOrchestrator.catalog_id_to_pending_discontinue_lifetime
    default_cutoff = Edi::BaseOrchestrator::DEFAULT_PENDING_DISCONTINUE_LIFETIME.ago

    if custom_lifetimes.any?
      custom_catalog_ids = custom_lifetimes.keys

      custom_lifetimes.each do |catalog_id, lifetime|
        batch = all_pending.where(catalog_id: catalog_id)
        total += transition_batch(batch, lifetime.ago)
      end

      remainder = all_pending.where.not(catalog_id: custom_catalog_ids)
      total += transition_batch(remainder, default_cutoff)
    else
      total += transition_batch(all_pending, default_cutoff)
    end
  end

  logger.debug("Discontinued catalog items pending_discontinue", catalog_item_count: total)
  total
end

#processObject



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'app/services/maintenance/item_maintenance.rb', line 5

def process
  jobs = %i[discontinue_old_custom_mats
            discontinue_old_unused_items
            propagate_discontinued_items
            propagate_discontinued_store_items
            discontinue_pending_discontinued_catalog_items
            synchronize_asins
            remove_empty_specs
            spec_refresh
            synchronize_secondary_product_lines]
  results = {}
  jobs.each do |job_name|
    job_identity = "Maintenance::ItemMaintenance - #{job_name}"
    PaperTrail.request(whodunnit: job_identity) do
      logger.tagged(job_identity) do
        logger.info 'Starting Job'
        results[job_name] = send(job_name)
        logger.info 'Job finished'
      end
    end
  end
  results
end

#propagate_discontinued_itemsObject



61
62
63
64
65
66
67
68
69
70
# File 'app/services/maintenance/item_maintenance.rb', line 61

def propagate_discontinued_items
  # update store_items set is_discontinued = true
  # where exists(select 1 from items where items.id = store_items.item_id and items.is_discontinued);
  store_items = StoreItem.where(is_discontinued: false)
                         .where('exists(select 1 from items where items.id = store_items.item_id and items.is_discontinued)')
  store_items.ids
  res = store_items.update_all(is_discontinued: true)
  logger.debug("Propagated item discontinued", store_item_count: res)
  res
end

#propagate_discontinued_store_itemsObject



72
73
74
75
76
77
78
79
80
81
82
# File 'app/services/maintenance/item_maintenance.rb', line 72

def propagate_discontinued_store_items
  # Exclude discontinued: store-item propagation must not resurrect a catalog row that
  # already completed the discontinue lifecycle (typo was "discontued", so discontinued
  # rows were incorrectly forced back to pending_discontinue nightly).
  catalog_items = CatalogItem.where.not(state: %w[pending_discontinue discontinued])
                             .where('exists(select 1 from store_items si where si.id = catalog_items.store_item_id and si.is_discontinued = true )')
  catalog_items.ids
  res = catalog_items.update_all(state: 'pending_discontinue')
  logger.debug("Propagated store item discontinued", catalog_item_count: res)
  res
end

#remove_empty_specsObject



33
34
35
36
37
# File 'app/services/maintenance/item_maintenance.rb', line 33

def remove_empty_specs
  empty_specs = ProductSpecification.where(text_blurb: [nil, '']).where(method: 'text').where(template: false)
  logger.debug("Removing empty specs", count: empty_specs.count)
  empty_specs.delete_all
end

#spec_refreshObject



29
30
31
# File 'app/services/maintenance/item_maintenance.rb', line 29

def spec_refresh
  Item.async_update_all_items_product_specifications
end

#synchronize_asinsObject



39
40
41
42
43
44
45
46
47
# File 'app/services/maintenance/item_maintenance.rb', line 39

def synchronize_asins
  logger.info 'Synchronizing Asins from Item to Catalog Items'
  CatalogItem.transaction do
    CatalogItem.amazons_with_asins.eager_load(:item).where('catalog_items.third_party_part_number IS NULL OR items.amazon_asin <> catalog_items.third_party_part_number').find_each do |ci|
      logger.info "Synchronizing catalog item #{ci.id}, old tppn: #{ci.third_party_part_number}, new: #{ci.item.amazon_asin}"
      ci.update_column(:third_party_part_number, ci.item.amazon_asin)
    end
  end
end

#synchronize_secondary_product_linesObject

Ensures the primary product line is also in the item_product_lines table



121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/services/maintenance/item_maintenance.rb', line 121

def synchronize_secondary_product_lines
  sql = <<-SQL.squish
    INSERT INTO item_product_lines (item_id, product_line_id, position)
      select i.id, i.primary_product_line_id, (select count(*) from item_product_lines ipl where ipl.item_id = i.id) + 1
      from items i
      where
      i.primary_product_line_id IS NOT NULL
      AND NOT EXISTS(select 1 from item_product_lines ipl where ipl.item_id = i.id and ipl.product_line_id = i.primary_product_line_id)
  SQL

  ActiveRecord::Base.lease_connection.execute(sql)
end