Class: Catalog::AmazonPricingAutomationService

Inherits:
BaseService
  • Object
show all
Defined in:
app/services/catalog/amazon_pricing_automation_service.rb

Overview

Nightly pricing automation service for Amazon US and Canada catalogs.
Orchestrates both price lowering (to win Buy Box) and price raising (when winning stably).

This service delegates to specialized services:

  • AmazonPriceLoweringService: Handles all price competition logic
  • AmazonPriceRaisingService: Handles gradual price increases for stable winners

Runs nightly after fresh Amazon data is pulled (scheduled for 6:15am CT).

Defined Under Namespace

Classes: Result

Constant Summary collapse

DB_RETRY_EXCEPTIONS =
[ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad].freeze
DB_RETRY_TRIES =
3
BUY_BOX_WINNER_STABLE_DAYS =

Delegate constants to specialized services for external reference

Catalog::AmazonPriceRaisingService::BUY_BOX_WINNER_STABLE_DAYS
COMPETITIVE_PRICE_THRESHOLD_PERCENT =
Catalog::AmazonPriceLoweringService::COMPETITIVE_PRICE_THRESHOLD_PERCENT
AMAZON_SELLER_IDS =
Catalog::AmazonPriceLoweringService::AMAZON_SELLER_IDS

Instance Method Summary collapse

Methods inherited from BaseService

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

Constructor Details

#initializeAmazonPricingAutomationService

Returns a new instance of AmazonPricingAutomationService.



26
27
28
29
30
# File 'app/services/catalog/amazon_pricing_automation_service.rb', line 26

def initialize
  super
  @lowering_service = Catalog::AmazonPriceLoweringService.new
  @raising_service = Catalog::AmazonPriceRaisingService.new
end

Instance Method Details

#process(options = {}) ⇒ Object



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
85
86
87
88
89
90
91
92
93
94
95
96
# File 'app/services/catalog/amazon_pricing_automation_service.rb', line 32

def process(options = {})
  options = options.symbolize_keys if options.is_a?(Hash)
  catalog_ids = options[:catalog_ids] || [CatalogConstants::AMAZON_SC_US_CATALOG_ID, CatalogConstants::AMAZON_SC_CA_CATALOG_ID]
  limit = options[:limit]&.to_i
  skip_fresh_data_check = options.fetch(:skip_fresh_data_check, false)
  send_email_report = options.fetch(:send_email_report, true)

  messages = []
  processed_count = 0
  price_increased_count = 0
  price_lowered_count = 0
  flagged_count = 0
  blocked_by_external = []

  catalog_items = build_catalog_items_query(catalog_ids, limit, skip_fresh_data_check)
  logger.info "Found #{catalog_items.count} catalog items to process"

  catalog_items.find_each do |catalog_item|
    yield(catalog_item: catalog_item) if block_given?

    result = with_connection_retry(catalog_item) { process_catalog_item(catalog_item) }
    processed_count += 1

    case result[:action]
    when :price_increased
      price_increased_count += 1
      messages << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Price increased to #{catalog_item.reload.amount}"
    when :price_lowered
      price_lowered_count += 1
      messages << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Price lowered to #{catalog_item.reload.amount}"
    when :flagged
      flagged_count += 1
      messages << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Flagged - #{result[:reason]}"
    when :blocked_by_external
      # Track items blocked by external retailer prices
      blocked_by_external << result[:blocked_item_data]
      messages << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Blocked by external price $#{result[:external_price]}"
    when :no_action
      logger.debug "Catalog Item #{catalog_item.id}: No action - #{result[:reason]}"
    end

    logger.info "Processed catalog item #{catalog_item.id}: #{result[:action]}"
  end

  # Send email report if there were significant actions
  if send_email_report && (price_increased_count.positive? || price_lowered_count.positive? || blocked_by_external.any?)
    send_repricing_report(
      processed_count: processed_count,
      price_increased_count: price_increased_count,
      price_lowered_count: price_lowered_count,
      flagged_count: flagged_count,
      blocked_by_external: blocked_by_external,
      messages: messages
    )
  end

  Result.new(
    processed_count: processed_count,
    price_increased_count: price_increased_count,
    price_lowered_count: price_lowered_count,
    flagged_count: flagged_count,
    blocked_by_external: blocked_by_external,
    messages: messages
  )
end