Class: Edi::Google::PromotionDataProcessor

Inherits:
BaseEdiService show all
Defined in:
app/services/edi/google/promotion_data_processor.rb

Overview

Builds the public Google Merchant promotions (US + CA) from tier-3
sale-page coupons and stages them as outbound EdiCommunicationLogs for
PromotionSender — the "special offer" badge layer that
complements the product feed's struck-through salePrice.

Source of truth is Coupon.promo_for_sale_page (active, in-effect,
sale_page_position > 0, locale-aware) intersected with tier-3 promotional
coupons that are explicitly opted in (syndicate_to_google). The opt-in
gate is deliberate: the sale-page set also contains offers Google prohibits
(e.g. occupation-gated "military" coupons), which no coupon attribute
reliably distinguishes — so syndication is a per-coupon marketing choice in
the coupon admin, not an automatic sweep. Each coupon maps through
Feed::Google::MerchantApi::PromotionBuilder; coupons that can't be a Google
promotion (price-forcing / below policy thresholds) map to nil and are dropped.

Constant Summary collapse

CURRENCY_BY_COUNTRY =

ISO currency per promotions target country (matches the two main catalogs).

{ 'US' => 'USD', 'CA' => 'CAD' }.freeze
MAX_ITEM_INCLUSION =

Google caps itemIdInclusion; a product-restricted coupon with more
applicable offers than this is SKIPPED (and logged) rather than truncated
(advertises the offer on an arbitrary subset) or widened to ALL_PRODUCTS
(advertises on ineligible products). Re-scope the coupon if it's hit.

500

Constants included from RequestIdentifiable

RequestIdentifiable::REQUEST_ID_HEADERS

Constants included from AddressAbbreviator

AddressAbbreviator::MAX_LENGTH

Instance Attribute Summary

Attributes inherited from BaseEdiService

#orchestrator

Attributes inherited from BaseService

#options

Instance Method Summary collapse

Methods inherited from BaseEdiService

#amazon_feed_product_type, #duplicate_po_already_notified?, #initialize, #mark_duplicate_po_as_notified, #onboard_ordered_catalog_items, #report_order_creation_issues, #safe_process_edi_communication_log

Methods included from RequestIdentifiable

#partner_request_id

Methods included from AddressAbbreviator

#abbreviate_street, #collect_street_originals, #record_address_abbreviation_notes

Methods inherited from BaseService

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

Constructor Details

This class inherits a constructor from Edi::BaseEdiService

Instance Method Details

#processEdiCommunicationLog

Stages ONE promotion_data ECL for this partner's country (US / CA),
mirroring Edi::Google::ProductDataProcessor — one partner = one country = one
promotions data source.

Returns:



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
# File 'app/services/edi/google/promotion_data_processor.rb', line 34

def process
  logger.info "Generating Google Merchant API promotions for #{orchestrator.partner}"
  catalog = Catalog.find(orchestrator.catalog_id)
  country = orchestrator.feed_label

  promotions = I18n.with_locale(catalog.locale_for_catalog) do
    # Belt-and-suspenders mirroring the syndicate_to_google validation on
    # Coupon (which update_all/insert_all/save(validate:false) can bypass):
    # only public, customer-entered codes (not auto-apply / promo_tracking,
    # whose discount is already in salePrice) are valid Google promotions.
    Coupon.promo_for_sale_page.tier3.syndicated_to_google
          .non_auto_applied.where(promo_tracking: false)
          .for_public.where.not(code: [nil, ''])
          .filter_map { |coupon| build(coupon, catalog, country) }
  end

  EdiCommunicationLog.create_outbound_file_from_data(
    data: promotions.to_json,
    file_extension: 'json',
    partner: orchestrator.partner,
    category: 'promotion_data',
    data_type: 'json',
    file_info: { promotion_count: promotions.size, target_country: country }
  )
end