Class: Maintenance::ItemMaintenance
- Inherits:
-
BaseService
- Object
- BaseService
- Maintenance::ItemMaintenance
- Defined in:
- app/services/maintenance/item_maintenance.rb
Instance Method Summary collapse
-
#consolidate_specs ⇒ Object
Goal is to consolidate duplicate specs that exist on multiple items into one spec.
- #discontinue_old_custom_mats ⇒ Object
- #discontinue_old_unused_items ⇒ Object
-
#discontinue_pending_discontinued_catalog_items(older_than = nil) ⇒ Object
Transitions pending_discontinue catalog items to discontinued once their wait period has elapsed.
- #process ⇒ Object
- #propagate_discontinued_items ⇒ Object
- #propagate_discontinued_store_items ⇒ Object
- #remove_empty_specs ⇒ Object
- #spec_refresh ⇒ Object
- #synchronize_asins ⇒ Object
-
#synchronize_secondary_product_lines ⇒ Object
Ensures the primary product line is also in the item_product_lines table.
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
#consolidate_specs ⇒ Object
Goal is to consolidate duplicate specs that exist on multiple items into one spec
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 |
# File 'app/services/maintenance/item_maintenance.rb', line 38 def consolidate_specs sql = <<-SQL SELECT token, grouping, sku_regexp, method, text_blurb, units, image_id, formatter, array_agg(id) AS spec_ids FROM product_specifications WHERE product_line_id IS NULL and product_category_id IS NULL GROUP BY token, grouping, sku_regexp, method, text_blurb, units, image_id, formatter HAVING COUNT(id) > 1 ORDER BY token, grouping, sku_regexp, method, text_blurb, units, image_id, formatter ---LIMIT 3 SQL # Execute the SQL and get the result result = ActiveRecord::Base.connection.select_all(sql) # Extract the spec_ids from the result grouped_spec_ids = result.map { |row| PG::TextDecoder::Array.new.decode(row['spec_ids']) } logger.info "Found #{grouped_spec_ids.flatten.count} duplicate specs" survivor_spec_ids = {} grouped_spec_ids.each do |spec_ids| spec_ids = spec_ids.map(&:to_i) ProductSpecification.transaction do # What are the item ids collected_item_ids = Item.joins(:direct_product_specifications).where(product_specifications: { do_not_merge: false, id: spec_ids }).distinct.pluck(:id) # Keep the first one and destroy the rest primary_spec_id = spec_ids.shift # Delete the redundant specs ProductSpecification.where(id: spec_ids).destroy_all # Save the collected item ids into the primary spec survivor_spec = ProductSpecification.find(primary_spec_id) new_item_ids = collected_item_ids survivor_spec_ids[primary_spec_id] = { spec_ids_merged: spec_ids, item_ids: new_item_ids } survivor_spec.item_ids = new_item_ids survivor_spec.should_auto_translate = true survivor_spec.save! end end survivor_spec_ids end |
#discontinue_old_custom_mats ⇒ Object
92 93 94 95 96 97 98 |
# File 'app/services/maintenance/item_maintenance.rb', line 92 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_items ⇒ Object
88 89 90 |
# File 'app/services/maintenance/item_maintenance.rb', line 88 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.
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
# File 'app/services/maintenance/item_maintenance.rb', line 130 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 |
#process ⇒ Object
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'app/services/maintenance/item_maintenance.rb', line 2 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 consolidate_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_items ⇒ Object
100 101 102 103 104 105 106 107 108 109 |
# File 'app/services/maintenance/item_maintenance.rb', line 100 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_item_ids = store_items.pluck(:id) res = store_items.update_all(is_discontinued: true) logger.debug("Propagated item discontinued", store_item_count: res) res end |
#propagate_discontinued_store_items ⇒ Object
111 112 113 114 115 116 117 118 119 120 121 |
# File 'app/services/maintenance/item_maintenance.rb', line 111 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_item_ids = catalog_items.pluck(:id) res = catalog_items.update_all(state: 'pending_discontinue') logger.debug("Propagated store item discontinued", catalog_item_count: res) res end |
#remove_empty_specs ⇒ Object
31 32 33 34 35 |
# File 'app/services/maintenance/item_maintenance.rb', line 31 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_refresh ⇒ Object
27 28 29 |
# File 'app/services/maintenance/item_maintenance.rb', line 27 def spec_refresh Item.async_update_all_items_product_specifications end |
#synchronize_asins ⇒ Object
78 79 80 81 82 83 84 85 86 |
# File 'app/services/maintenance/item_maintenance.rb', line 78 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_lines ⇒ Object
Ensures the primary product line is also in the item_product_lines table
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'app/services/maintenance/item_maintenance.rb', line 160 def synchronize_secondary_product_lines sql = <<-SQL 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.connection.execute(sql) end |