Class: VendorsService::GoogleReserve::MerchantFeedsService

Inherits:
BaseOperationService show all
Includes:
ElasticAPM::SpanHelpers, Concerns::FeedUploader
Defined in:
app/services/vendors_service/google_reserve/merchant_feeds_service.rb

Overview

VendorsService::GoogleReserve::MerchantFeedsService generates restaurant merchant information feeds for Google Reserve (RWG)

This service creates a JSON feed containing restaurant merchant information and uploads it to Google's SFTP server. The merchant feed includes comprehensive restaurant data required for both Business-link and E2E Google Reserve integration.

Process Overview

  1. Fetch active restaurants with Google Reserve integration enabled

  2. Build merchant data for each restaurant including contact info and location

  3. Generate and upload feed file using centralized FeedUploader workflow

  4. Upload the file to Google's SFTP server via secure connection

Merchant Feed Structure

The generated JSON follows Google's merchant feed specification: {

"metadata": {
  "processing_instruction": "PROCESS_AS_COMPLETE",
  "shard_number": 0,
  "total_shards": 1,
  "generation_timestamp": <timestamp>
},
"merchant": [
  {
    "category": "restaurant",
    "merchant_id": "restaurant-<id>",
    "name": "<restaurant_name>",
    "url": "<restaurant_url>",
    "telephone": "<phone_in_e164_format>",
    "geo": { "latitude": ..., "longitude": ..., "address": {...} },
    "action_link": [{ "url": ..., "action_link_type": ..., "language": ..., "platform": ... }],
    "agreement_status": "signed",
    "terms": { "url": "<terms_url>" }
  }
]

}

Restaurant Eligibility

Only restaurants that meet ALL criteria are included:

  • Active and not expired

  • Have latitude/longitude coordinates

  • Have active Google Reserve integration (agreement_status: active)

  • Have valid Google Reserve package types

  • Not in testing exclusion list

Error Handling

  • Individual restaurant processing errors are logged but don't stop the entire job

  • Geocoding failures are handled with retries and fallbacks

  • SFTP upload failures are reported with context information

  • Phone number formatting errors are handled gracefully

Dependencies

  • AdminSetting for feature flag and testing exclusions

  • FeedUploader concern for centralized file generation and upload

  • SftpService for Google SFTP uploads

  • Geocoder for address resolution

  • Phonelib for phone number formatting

Instance Attribute Summary

Attributes inherited from BaseOperationService

#outcome

Instance Method Summary collapse

Methods inherited from BaseOperationService

#success?

Constructor Details

#initializeMerchantFeedsService

Returns a new instance of MerchantFeedsService.



66
67
68
69
70
71
72
# File 'app/services/vendors_service/google_reserve/merchant_feeds_service.rb', line 66

def initialize
  super()
  BUSINESS_LOGGER.set_business_context({
                                         vendor_name: ApiVendorV1::Constants::GOOGLE_RESERVE_VENDOR_NAME,
                                         feed_type: 'merchant_feeds',
                                       })
end

Instance Method Details

#generate_and_upload_feedBoolean

Main entry point for the merchant feed generation process

Returns:

  • (Boolean)

    Success status

Raises:

  • (StandardError)

    Any unhandled errors are reported to APM



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'app/services/vendors_service/google_reserve/merchant_feeds_service.rb', line 78

def generate_and_upload_feed
  return false unless AdminSetting.enable_reserve_with_google_feature.to_s == true.to_s

  BUSINESS_LOGGER.info("#{self.class}: Starting Google Reserve merchant feeds generation")

  restaurants = fetch_restaurants
  BUSINESS_LOGGER.info("#{self.class}: Found restaurants for Google Reserve merchant feed",
                       { count: restaurants.count })

  data = []
  restaurants.find_each do |restaurant|
    data << build_data(restaurant.decorate)
  end

  json_data = build_to_json(data)
  generate_and_upload_feed_file(json_data, :merchant_feed)

  BUSINESS_LOGGER.info("#{self.class}: Successfully generated Google Reserve merchant feed")
  true
rescue StandardError => e
  APMErrorHandler.report('Failed to generate Google Reserve merchant feed', exception: e)
  raise e
end