Class: PartnerService::Benchmark::CalculateService

Inherits:
ApplicationService show all
Includes:
ElasticAPM::SpanHelpers
Defined in:
app/services/partner_service/benchmark/calculate_service.rb

Overview

Service to calculate benchmark data for partner portal Uses pre-aggregated MongoDB collections for improved performance

Data Sources:

  • Monthly view: restaurant_benchmark_monthly, restaurant_benchmark_tags_monthly

  • Weekly view: restaurant_benchmark_weekly, restaurant_benchmark_tags_weekly

The pre-aggregated collections contain calculated metrics (gmv, total_covers, avg_spend_per_person) eliminating the need for runtime aggregation.

Examples:

Monthly benchmark

service = PartnerService::Benchmark::CalculateService.new(
  restaurant: restaurant,
  data_view_type: 'monthly',
  start_month: '2025-01',
  end_month: '2025-06',
  data_type: 'all'
)
result = service.call

Weekly benchmark

service = PartnerService::Benchmark::CalculateService.new(
  restaurant: restaurant,
  data_view_type: 'weekly',
  start_date: '2025-01-01',
  end_date: '2025-02-15',
  data_type: 'competitor'
)
result = service.call

Constant Summary collapse

MIN_PERIODS =

Minimum periods required for meaningful benchmark comparison

2
MAX_PERIODS =

Maximum periods to prevent performance issues and maintain readability Based on: Partner dashboard UX research and MongoDB query performance testing

12

Instance Attribute Summary collapse

Attributes inherited from ApplicationService

#object

Instance Method Summary collapse

Methods inherited from ApplicationService

#execute, #execute!

Constructor Details

#initialize(restaurant:, data_view_type:, data_type:, restaurants: nil, start_date: nil, end_date: nil, start_month: nil, end_month: nil) ⇒ CalculateService

Initialize the service

Parameters:

  • restaurant (Restaurant)

    The current/reference restaurant (used for tags and competitors)

  • restaurants (ActiveRecord::Relation, Array<Restaurant>) (defaults to: nil)

    Collection of restaurants for vertigo data

  • data_view_type (String)

    'monthly' or 'weekly'

  • data_type (String)

    'all', 'tags', or 'competitor'

  • start_date (String, Date) (defaults to: nil)

    Start date for weekly view

  • end_date (String, Date) (defaults to: nil)

    End date for weekly view

  • start_month (String, Date) (defaults to: nil)

    Start month for monthly view (YYYY-MM format)

  • end_month (String, Date) (defaults to: nil)

    End month for monthly view (YYYY-MM format)

Raises:

  • (ArgumentError)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 58

def initialize(restaurant:, data_view_type:, data_type:, restaurants: nil, start_date: nil, end_date: nil, start_month: nil, end_month: nil)
  raise ArgumentError, 'Restaurant cannot be nil' if restaurant.nil?

  @restaurant = restaurant
  @restaurants = restaurants || [restaurant]
  @data_view_type = data_view_type
  @data_type = data_type
  @start_date = start_date&.to_date if start_date.present?
  @end_date = end_date&.to_date if end_date.present?
  @start_month = parse_month(start_month) if start_month.present?
  @end_month = parse_month(end_month) if end_month.present?
  @errors = []
  @mongo_client = MongoDbService::Connection.new
  @competitor_ids_ordered = nil
end

Instance Attribute Details

#data_typeObject (readonly)

Returns the value of attribute data_type.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def data_type
  @data_type
end

#data_view_typeObject (readonly)

Returns the value of attribute data_view_type.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def data_view_type
  @data_view_type
end

#end_dateObject (readonly)

Returns the value of attribute end_date.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def end_date
  @end_date
end

#end_monthObject (readonly)

Returns the value of attribute end_month.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def end_month
  @end_month
end

#errorsObject (readonly)

Returns the value of attribute errors.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def errors
  @errors
end

#restaurantObject (readonly)

Returns the value of attribute restaurant.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def restaurant
  @restaurant
end

#restaurantsObject (readonly)

Returns the value of attribute restaurants.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def restaurants
  @restaurants
end

#start_dateObject (readonly)

Returns the value of attribute start_date.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def start_date
  @start_date
end

#start_monthObject (readonly)

Returns the value of attribute start_month.



45
46
47
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 45

def start_month
  @start_month
end

Instance Method Details

#callHash?

Execute the service

Returns:

  • (Hash, nil)

    Benchmark data or nil if validation fails



77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 77

def call
  return nil unless valid?

  case data_view_type
  when 'monthly'
    calculate_monthly_benchmark
  when 'weekly'
    calculate_weekly_benchmark
  else
    @errors << 'Invalid data_view_type'
    nil
  end
end

#error_messagesString

Get error messages

Returns:

  • (String)


103
104
105
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 103

def error_messages
  errors.join(', ')
end

#valid?Boolean

Check if service is valid

Returns:

  • (Boolean)


95
96
97
98
# File 'app/services/partner_service/benchmark/calculate_service.rb', line 95

def valid?
  validate_parameters
  errors.empty?
end