Class: Catalog::AmazonPricingAutomationService
- Inherits:
-
BaseService
- Object
- BaseService
- Catalog::AmazonPricingAutomationService
- 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 =
Exceptions that trigger retries in db.
[ActiveRecord::ConnectionNotEstablished, PG::ConnectionBad].freeze
- DB_RETRY_TRIES =
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 =
Competitive price threshold percent.
Catalog::AmazonPriceLoweringService::COMPETITIVE_PRICE_THRESHOLD_PERCENT
- AMAZON_SELLER_IDS =
Amazon seller ids.
Catalog::AmazonPriceLoweringService::AMAZON_SELLER_IDS
- EXTERNAL_BLOCK_REASONS =
Raise-attempt outcomes where an external retailer price is the binding
constraint - these create/refresh a reprice_blocked_by_external flag. %i[ blocked_by_refreshed_sibling_price blocked_by_cached_sibling_price at_or_above_sibling_retailer at_or_above_external_threshold ].freeze
- RAISE_GATE_REASONS =
Raise-attempt gates that exit before external prices are evaluated.
They carry no information about whether an earlier external block has
cleared, so any active reprice_blocked_by_external flag is left alone. %i[ repricing_disabled not_buy_box_winner buy_box_winner_not_stable ].freeze
Instance Attribute Summary
Attributes inherited from BaseService
Instance Method Summary collapse
-
#initialize ⇒ AmazonPricingAutomationService
constructor
A new instance of AmazonPricingAutomationService.
-
#process(options = {}) ⇒ Result
The automation result.
-
#refresh_listing_issues(catalog_item) ⇒ void
Re-derive the
has_issuesflag for a single catalog item from its (freshly-pulled) Amazon listing data — resolving a flag Amazon no longer reports and (re)creating one it still does.
Methods inherited from BaseService
#log_debug, #log_error, #log_info, #log_warning, #logger, #tagged_logger
Constructor Details
#initialize ⇒ AmazonPricingAutomationService
Returns a new instance of AmazonPricingAutomationService.
49 50 51 52 53 54 |
# File 'app/services/catalog/amazon_pricing_automation_service.rb', line 49 def initialize super @lowering_service = Catalog::AmazonPriceLoweringService.new @raising_service = Catalog::AmazonPriceRaisingService.new @buy_box_service = Catalog::AmazonBuyBoxService.new(lowering_service: @lowering_service, raising_service: @raising_service) end |
Instance Method Details
#process(options = {}) ⇒ Result
Returns the automation result.
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'app/services/catalog/amazon_pricing_automation_service.rb', line 62 def process( = {}) = .symbolize_keys if .is_a?(Hash) catalog_ids = [:catalog_ids] || [CatalogConstants::AMAZON_SC_US_CATALOG_ID, CatalogConstants::AMAZON_SC_CA_CATALOG_ID] limit = [:limit]&.to_i skip_fresh_data_check = .fetch(:skip_fresh_data_check, false) send_email_report = .fetch(:send_email_report, true) = [] processed_count = 0 price_increased_count = 0 price_lowered_count = 0 price_reverted_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 << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Price increased to #{catalog_item.reload.amount}" when :price_lowered price_lowered_count += 1 << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Price lowered to #{catalog_item.reload.amount}" when :price_reverted price_reverted_count += 1 << "Catalog Item #{catalog_item.id} (#{catalog_item.sku}): Raise reverted to #{catalog_item.reload.amount} after Buy Box loss" when :flagged flagged_count += 1 << "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] << "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? || price_reverted_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, price_reverted_count: price_reverted_count, flagged_count: flagged_count, blocked_by_external: blocked_by_external, messages: ) end Result.new( processed_count: processed_count, price_increased_count: price_increased_count, price_lowered_count: price_lowered_count, price_reverted_count: price_reverted_count, flagged_count: flagged_count, blocked_by_external: blocked_by_external, messages: ) end |
#refresh_listing_issues(catalog_item) ⇒ void
This method returns an undefined value.
Re-derive the has_issues flag for a single catalog item from its
(freshly-pulled) Amazon listing data — resolving a flag Amazon no longer
reports and (re)creating one it still does. Public entry point for the
Listing Issues "Recheck" refresh; reconciles issues only, never reprices.
140 141 142 |
# File 'app/services/catalog/amazon_pricing_automation_service.rb', line 140 def refresh_listing_issues(catalog_item) sync_listing_issues(catalog_item) end |