Class: Restaurant
- Inherits:
-
ApplicationRecord
show all
- Extended by:
- Enumerize
- Includes:
- Counter::CounterCache, HungryHub::DynamicTime, ModelExt::Restaurants::Callbacks, ModelExt::Restaurants::ClassMethods, ModelExt::Restaurants::CreditCard, ModelExt::Restaurants::FriendlyIdSetup, ModelExt::Restaurants::Geocoding, ModelExt::Restaurants::ImenuPro, ModelExt::Restaurants::InstanceMethods, ModelExt::Restaurants::PrimaryTags, ModelExt::Restaurants::Relations, ModelExt::Restaurants::Scopes, ModelExt::Restaurants::Translations, SoftDelete
- Defined in:
- app/models/restaurant.rb
Overview
This class has many reservations, and has reservations_count attribute but we don't use Rails `counter_cache` feature to increment/decrement reservations_count data the data is generated every night instead attributes:
custom_text:
is a field to add short text that will be displayed on home page
CompactRestaurant will merge all Restaurant's custom_text data into this field
call_driver_time_limit_duration:
system will use global level if this is 0. This is a how long system will wait from the first driver call
Constant Summary
collapse
- AVAILABILITY_PREORDER =
'preorder'
- AVAILABILITY_IN_STOCK =
'in stock'
- AVAILABILITY_OUT_OF_STOCK =
'out of stock'
Instance Attribute Summary collapse
#cc_hold_amount, #cc_immediate_charge_amount
Instance Method Summary
collapse
-
#any_voucher_offers? ⇒ Boolean
-
#avg_review ⇒ Float
get average from review stat.
-
#come_pay_label(get_comemore_payless) ⇒ Object
-
#create_inv_checkers ⇒ Object
if is_dine_in only, then returns one instance only if is_take_away only, then returns one instance only if both of attributes are true, then returns two instances.
-
#date_offer_expired?(date) ⇒ Boolean
-
#default_currency ⇒ Object
-
#get_best_promotion(package) ⇒ Object
Determine the best promotion for a package based on the promotion_badge_percentage and comemore_payless_percentage.
-
#get_comemore_payless_percentage(package) ⇒ Object
-
#get_hashed_mobile_images(options = { v2_api: false, }) ⇒ Object
-
#get_hashed_mobile_images_three ⇒ Object
-
#get_parking_id ⇒ Object
-
#get_promotion_badge_percentage(package) ⇒ Object
-
#get_promotion_type(percentage_discount, promotion_badge_percentage, comemore_payless_percentage) ⇒ Object
Determine the promotion type based on the presence of promotion_badge_percentage or comemore_payless_percentage.
-
#get_text_tags_by_group(group) ⇒ Object
-
#has_delivery_inventories? ⇒ Boolean
-
#has_no_offers? ⇒ Boolean
-
#has_self_delivery? ⇒ Boolean
-
#inv_checker_service_class ⇒ Inventory::InvCheckerHungryHubService, ...
Return one of Inventory::InvCheckerBase subclasses.
-
#is_blocked?(options = {}) ⇒ Boolean
options = { day: :future or :today, date: custom date}.
-
#it_quantities ⇒ Object
-
#location_format ⇒ Object
-
#name(lang = MyLocaleManager.normalize_locale, for_api: false) ⇒ Object
-
#old_link=(link) ⇒ Object
-
#opening_hours ⇒ Object
-
#package_solds ⇒ Object
-
#parking ⇒ Object
-
#parking=(val) ⇒ Object
-
#party_size_range ⇒ Object
-
#promotion_badge(with_percentage: false) ⇒ Object
get highest promotion discount percentage for a restaurant.
-
#promotion_text(promotion_type, percentage_discount, get_comemore_payless) ⇒ Object
Determine the promotion text based on the presence of promotion_badge_percentage or comemore_payless_percentage.
-
#request_choice_options ⇒ Object
-
#res_duration=(time) ⇒ Object
-
#selected_inventory_model ⇒ Object
-
#self_delivery_channel ⇒ Object
-
#set_default_minimum_seat_allotment ⇒ Object
-
#short_name_sms ⇒ Object
-
#sum_party_size ⇒ Integer
sum of reservations party size.
-
#to_param ⇒ Object
-
#use_third_party_inventory? ⇒ Boolean
-
#validate_commission_for_packages(commision) ⇒ Object
#time_zone
#primary_tag_by_category
#imenu_pro_link, #imenu_pro_link=
#adult_cc_hold_amount=, #adult_cc_immediate_charge_amount=, #assert_charge_immediately?, #assert_on_hold_charge?, #kids_cc_hold_amount=, #kids_cc_immediate_charge_amount=, #party_require_credit_card?, #require_credit_card?
#award_badge_tags, #award_type_tags, #bts_route_tags, #cuisine_tags, #dining_style_tags, #facility_tags, #fetch_restaurant_tags, #hashtag_tags, #location_tags, #mrt_route_tags, #popular_zone_tags, #shopping_mall_tags
#city_country_name, #city_name, #city_name_changed?, #name_en_with_city, #slug_candidates, #slug_includes_city_name?
#bump_inventory_checker_cache_versions, #create_or_update_restaurant_tags, #refresh_inv_checker, #refresh_view_cache_key
#active_add_ons_with_auto_extend, #active_and_not_expired?, #active_packages_with_auto_extend, #active_staff_emails, #availability_status, #bookable_and_not_expired?, #default_max_dine_in_booking_cutoff_time, #default_min_booking_time, #default_min_booking_time_admin_level_for_delivery, #default_min_booking_time_admin_level_for_dine_in, #default_provider_for, #determine_max_availability_date, #determine_min_booking_time, #eligible_for_rewards?, #inv_cache_key, #inventory_bistrochat?, #inventory_my_menu?, #inventory_seven_rooms?, #inventory_tablecheck?, #inventory_weeloy?, #override_delivery_min_booking?, #override_dine_in_min_booking?, #provider_for, #selected_alipay_payment_provider, #selected_cc_payment_provider, #selected_payment_provider, #selected_promptpay_payment_provider, #selected_wechat_pay_payment_provider, #today_in_tz, #view_cache_key, #view_cache_key_redis_key
Methods included from SoftDelete
#soft_deleted?, #soft_destroy
sync_carrierwave_url
Instance Attribute Details
#earliest_time ⇒ Object
355
356
357
358
359
360
|
# File 'app/models/restaurant.rb', line 355
def earliest_time
inv = inventories.by_date.first
return inv.start_time.strftime('%H:%M') if inv.present?
'No inventories today'
end
|
#image_count=(value) ⇒ Object
Sets the attribute image_count
242
243
244
|
# File 'app/models/restaurant.rb', line 242
def image_count=(value)
@image_count = value
end
|
#images=(value) ⇒ Object
Sets the attribute images
242
243
244
|
# File 'app/models/restaurant.rb', line 242
def images=(value)
@images = value
end
|
#lat ⇒ Float
|
# File 'app/models/restaurant.rb', line 201
|
#latest_time ⇒ Object
362
363
364
365
366
367
368
369
370
|
# File 'app/models/restaurant.rb', line 362
def latest_time
inv = inventories.by_date.last
if inv.present?
time = inv.end_time - res_duration.minutes
return time.strftime('%H:%M')
end
'No inventories today'
end
|
#lng ⇒ Float
209
|
# File 'app/models/restaurant.rb', line 209
audited
|
Sets the attribute menu_images
242
243
244
|
# File 'app/models/restaurant.rb', line 242
def (value)
@menu_images = value
end
|
Instance Method Details
#any_voucher_offers? ⇒ Boolean
566
567
568
569
|
# File 'app/models/restaurant.rb', line 566
def any_voucher_offers?
date = Time.now_in_tz(time_zone).to_date
voucher_offer_date.present? && voucher_offer_date >= date
end
|
#avg_review ⇒ Float
get average from review stat
730
731
732
733
734
|
# File 'app/models/restaurant.rb', line 730
def avg_review
key = branch_id? ? :branch_id : :restaurant_id
review_stat = Restaurants::ReviewStat.find_by(key => branch_id || id)
review_stat&.average
end
|
#come_pay_label(get_comemore_payless) ⇒ Object
716
717
718
719
720
721
722
723
724
725
|
# File 'app/models/restaurant.rb', line 716
def come_pay_label(get_comemore_payless)
package_type = get_comemore_payless[:package_type].to_s
klass = package_type.safe_constantize
promo_type = klass ? klass::TYPE_SHORT : ''
I18n.t("views.package.promo.come_pay_less_dynamic.#{promo_type}",
group_size: get_comemore_payless[:group_size],
group_size_to_pay: get_comemore_payless[:group_size_to_pay], locale: :en)
end
|
#create_inv_checkers ⇒ Object
if is_dine_in only, then returns one instance only if is_take_away only, then returns one instance only if both of attributes are true, then returns two instances
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
|
# File 'app/models/restaurant.rb', line 288
def create_inv_checkers
instances = []
if is_dine_in
instances << create_checker_instance(for_dine_in: true, for_delivery: false)
end
if is_take_away
instances << create_checker_instance(for_dine_in: false, for_delivery: true)
end
if instances.empty?
instances << create_checker_instance(for_dine_in: true, for_delivery: false)
end
instances
end
|
#date_offer_expired?(date) ⇒ Boolean
444
445
446
447
448
449
450
451
452
453
454
455
456
457
|
# File 'app/models/restaurant.rb', line 444
def date_offer_expired?(date)
return true if date.blank?
d = date.is_a?(::Date) || date.is_a?(::Time) ? date : Time.now_in_tz(time_zone).to_date
return true if expiry_date.blank? && voucher_offer_date.blank?
return false if any_voucher_offers?
return false if expiry_date >= d
true
rescue StandardError
HH_LOGGER.error('restaurant has invalid expiry date', id: id)
true
end
|
#default_currency ⇒ Object
532
533
534
|
# File 'app/models/restaurant.rb', line 532
def default_currency
@default_currency ||= country.currency_code_upcase
end
|
Determine the best promotion for a package based on the promotion_badge_percentage and comemore_payless_percentage
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
|
# File 'app/models/restaurant.rb', line 628
def get_best_promotion(package)
promotion_badge_percentage = get_promotion_badge_percentage(package)&.to_i
get_comemore_payless = get_comemore_payless_percentage(package)
comemore_payless_percentage = get_comemore_payless&.dig(:discount_percentage)&.to_i || 0
percentage_discount = [promotion_badge_percentage, comemore_payless_percentage].compact.max.to_i
promotion_type = get_promotion_type(percentage_discount, promotion_badge_percentage, comemore_payless_percentage)
return if percentage_discount.zero? || promotion_type.nil?
{
percentage_discount: percentage_discount,
promotion_type: promotion_type,
promotion_text: promotion_text(promotion_type, percentage_discount, get_comemore_payless),
}
end
|
#get_comemore_payless_percentage(package) ⇒ Object
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
|
# File 'app/models/restaurant.rb', line 670
def get_comemore_payless_percentage(package)
current_time = Time.now_in_tz(time_zone)
today = current_time.to_date
pricing_groups = package&.pricing_groups
active_pricing_groups = pricing_groups&.where('end_date >= ?', today)
empty_date_pricing_groups = pricing_groups&.where('end_date IS NULL')
comemore_payless = if active_pricing_groups.present?
active_pricing_groups
elsif package.dynamic_price_comemore_payless? && empty_date_pricing_groups.present?
empty_date_pricing_groups
end
discount_percentage = comemore_payless&.select("group_size, group_size_to_pay,
((group_size - group_size_to_pay) * 100 / CAST(group_size AS FLOAT)) AS discount_percentage")&.
order(Arel.sql('discount_percentage DESC'))&.limit(1)&.first
return { group_size: nil, group_size_to_pay: nil, discount_percentage: 0 } if discount_percentage.blank?
{
group_size: discount_percentage.group_size,
group_size_to_pay: discount_percentage.group_size_to_pay,
discount_percentage: discount_percentage.discount_percentage,
package_type: package.package_attr.package_type,
}
end
|
#get_hashed_mobile_images(options = {
v2_api: false,
}) ⇒ Object
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
# File 'app/models/restaurant.rb', line 329
def get_hashed_mobile_images(options = {
v2_api: false,
})
Rails.cache.fetch("#{cache_key}|hashed_mobile_images|#{options}", expires_in: CACHEFLOW.generate_expiry) do
im_h = {}
files = Dir.glob("#{Rails.root}/public/#{id}-*-mobile.jpg")
files.sort! do |x, y|
file_a = x.match("#{id}-(\\d*)-mobile.jpg")[1].to_i
file_b = y.match("#{id}-(\\d*)-mobile.jpg")[1].to_i
file_a <=> file_b
end
files.each_with_index do |p, ind|
im_h[ind.to_s] = p[(p.rindex(%r{/}) + 1)..]
end
im_h['mobile_images'] = files.count unless options.delete(:v2_api)
im_h
end
end
|
#get_hashed_mobile_images_three ⇒ Object
351
352
353
|
# File 'app/models/restaurant.rb', line 351
def get_hashed_mobile_images_three
Dir.glob("#{Rails.root}/public/#{id}-*-mobile.jpg").count
end
|
#get_parking_id ⇒ Object
435
436
437
438
439
440
|
# File 'app/models/restaurant.rb', line 435
def get_parking_id
tag = restaurant_tags.where("title_#{MyLocaleManager.normalize_locale} LIKE ?", 'Parking:%').first
return tag.id if tag.present?
RestaurantTag.where('title_en LIKE ?', 'Parking:N%').first.try(:id)
end
|
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
|
# File 'app/models/restaurant.rb', line 649
def get_promotion_badge_percentage(package)
package_attr = package.package_attr
dynamic_pricing_type = package_attr&.dynamic_pricing_type
dynamic_pricings = package.pricings.where(dynamic_pricing_type: dynamic_pricing_type)
case dynamic_pricing_type.to_sym
when :normal
package_attr&.promotion_badge_percentage
else
current_time = Time.now_in_tz(time_zone)
query_dynamic_pricings = dynamic_pricings.where.not(promotion_badge_percentage: nil)
active_or_empty_date = query_dynamic_pricings.where('end_date >= ?', current_time.to_date).
or(query_dynamic_pricings.where(end_date: nil))
active_or_empty_date.order(promotion_badge_percentage: :desc).limit(1).
pluck(:promotion_badge_percentage).first
end
end
|
Determine the promotion type based on the presence of promotion_badge_percentage or comemore_payless_percentage
699
700
701
702
703
704
705
|
# File 'app/models/restaurant.rb', line 699
def get_promotion_type(percentage_discount, promotion_badge_percentage, comemore_payless_percentage)
if percentage_discount == promotion_badge_percentage
'percentage_discount'
elsif percentage_discount == comemore_payless_percentage
'comemore_payless'
end
end
|
#get_text_tags_by_group(group) ⇒ Object
323
324
325
326
327
|
# File 'app/models/restaurant.rb', line 323
def get_text_tags_by_group(group)
restaurant_tags.where("title_#{MyLocaleManager.normalize_locale} LIKE ?", "#{group}:%").map do |t|
t.title.gsub(/.*:/, '')
end
end
|
#has_delivery_inventories? ⇒ Boolean
554
555
556
557
558
559
560
561
562
563
564
|
# File 'app/models/restaurant.rb', line 554
def has_delivery_inventories?
return true if mon_take_away.presence ||
tue_take_away.presence ||
wed_take_away.presence ||
thu_take_away.presence ||
fri_take_away.presence ||
sat_take_away.presence ||
sun_take_away.presence
false
end
|
#has_no_offers? ⇒ Boolean
459
460
461
|
# File 'app/models/restaurant.rb', line 459
def has_no_offers?
!any_offers && !any_voucher_offers?
end
|
#has_self_delivery? ⇒ Boolean
536
537
538
539
540
541
542
|
# File 'app/models/restaurant.rb', line 536
def has_self_delivery?
@has_self_delivery ||= begin
self_delivery = delivery_channels.where(is_self_delivery: true)
self_delivery.count.positive? ? true : false
end
@has_self_delivery == true
end
|
Return one of Inventory::InvCheckerBase subclasses
#is_blocked?(options = {}) ⇒ Boolean
options = { day: :future or :today, date: custom date}
464
465
466
467
468
469
470
471
472
473
474
475
476
477
|
# File 'app/models/restaurant.rb', line 464
def is_blocked?(options = {})
at = options.delete(:at)
date = options.delete(:date) || Date.current_date
inv = case at.to_s
when 'future'
inventories.where('date >= ?', date)
when 'today'
inventories.where('date = ?', date)
else
inventories.where('date >= ?', date)
end
inv.where(quantity_available: 0).count.positive?
end
|
#it_quantities ⇒ Object
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
|
# File 'app/models/restaurant.rb', line 385
def it_quantities
@quantity = []
4.times do |i|
@quantity[i] = []
end
inventory_template_groups.each do |itg|
itg.inventory_templates.each do |inv|
m1 = inv.start_time.strftime('%M').to_i
m1.zero? ? 0 : m1 /= 15
m2 = inv.end_time.strftime('%M').to_i
m2.zero? ? 0 : m2 /= 15
h1 = inv.start_time.strftime('%H').to_i
h2 = inv.end_time.strftime('%H').to_i
if (h1 == h2) && (m2 - m1).positive?
(m2 - m1).times do |t|
@quantity[m1 + t][h1] = inv.quantity_available
end
elsif h1 != h2
(h2 - h1 + 1).times do |th|
if th == h2 - h1
(m2 - m1).times do |tm|
@quantity[m1 + tm][h1 + th] = inv.quantity_available
end
else
4.times do |tm|
@quantity[tm - m1][h1 + th] = inv.quantity_available
end
end
end
end
end
end
@quantity
end
|
428
429
430
431
432
433
|
# File 'app/models/restaurant.rb', line 428
def location_format
tag = restaurant_tags.where("title_#{MyLocaleManager.normalize_locale} LIKE ?", 'Location:%').first
return tag.title.slice(9..tag.title.length) if tag.present?
'None'
end
|
#name(lang = MyLocaleManager.normalize_locale, for_api: false) ⇒ Object
#old_link=(link) ⇒ Object
495
496
497
498
499
500
501
502
503
|
# File 'app/models/restaurant.rb', line 495
def old_link=(link)
link = link.to_s.split('ayce/hh/').last
if link.blank?
errors.add(:base, 'Invalid wordpress restaurant link')
return
end
write_attribute :old_link, link
end
|
#opening_hours ⇒ Object
372
373
374
375
376
377
378
379
380
381
382
383
|
# File 'app/models/restaurant.rb', line 372
def opening_hours
return nil if id.nil?
oh = self[:opening_hours]
return oh if oh.present?
return nil if misc.nil?
is_any = misc.split(/opening hours:?/i)
is_any.length > 1 ? "Opening Hours: #{is_any.last}" : nil
rescue StandardError
nil
end
|
#package_solds ⇒ Object
313
314
315
316
|
# File 'app/models/restaurant.rb', line 313
def package_solds
rps = RestaurantPackageSold.new(id)
rps.data
end
|
#parking ⇒ Object
507
508
509
510
511
512
513
514
|
# File 'app/models/restaurant.rb', line 507
def parking
parking_tag = Rails.cache.fetch("#{cache_key}|has_parking?", expires_in: CACHEFLOW.generate_expiry) do
parking_tag = ::RestaurantTag.find_by(title_en: 'Facility:Have Parking')
restaurant_tags.include?(parking_tag)
end
parking_tag == true
end
|
#parking=(val) ⇒ Object
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
|
# File 'app/models/restaurant.rb', line 516
def parking=(val)
parking_tag = ::RestaurantTag.find_by(title_en: 'Facility:Have Parking')
if val.to_i.zero?
if parking_tag.present?
restaurant_tags.delete(parking_tag)
touch if persisted?
save
end
elsif parking_tag.present? && !restaurant_tag_ids.include?(parking_tag.id)
restaurant_tags << parking_tag
touch if persisted?
save
end
end
|
#party_size_range ⇒ Object
491
492
493
|
# File 'app/models/restaurant.rb', line 491
def party_size_range
(min_party_size..largest_table).to_a
end
|
get highest promotion discount percentage for a restaurant
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
|
# File 'app/models/restaurant.rb', line 605
def promotion_badge(with_percentage: false)
packages = restaurant_packages.exclude_preview.includes(:package).map(&:package)
promotion = packages.reject { |package| package.respond_to?(:is_add_on) && package.is_add_on }.
map { |package| get_best_promotion(package) }.
reject(&:nil?).
max_by { |x| x[:percentage_discount] }
unless promotion
result = { promotion_type: nil, promotion_text: nil }
result[:percentage_discount] = 0 if with_percentage
return result
end
result = {
promotion_type: promotion[:promotion_type],
promotion_text: promotion[:promotion_text],
}
result[:percentage_discount] = promotion[:percentage_discount] if with_percentage
result
end
|
#promotion_text(promotion_type, percentage_discount, get_comemore_payless) ⇒ Object
Determine the promotion text based on the presence of promotion_badge_percentage or comemore_payless_percentage
708
709
710
711
712
713
714
|
# File 'app/models/restaurant.rb', line 708
def promotion_text(promotion_type, percentage_discount, get_comemore_payless)
if promotion_type == 'percentage_discount'
"#{percentage_discount}% OFF"
else
come_pay_label(get_comemore_payless)
end
end
|
#request_choice_options ⇒ Object
479
480
481
482
483
484
485
486
487
488
489
|
# File 'app/models/restaurant.rb', line 479
def request_choice_options
return [] if request_choice.blank?
options = []
request_choice.split(/(,|\|)/).map(&:strip).select do |o|
o != ',' && o != '|'
end.each do |o|
options.push(o)
end
options
end
|
#res_duration=(time) ⇒ Object
318
319
320
321
|
# File 'app/models/restaurant.rb', line 318
def res_duration=(time)
time = time / 60 if time.is_a?(ActiveSupport::Duration)
self[:res_duration] = time
end
|
#selected_inventory_model ⇒ Object
#self_delivery_channel ⇒ Object
544
545
546
547
548
|
# File 'app/models/restaurant.rb', line 544
def self_delivery_channel
return nil unless has_self_delivery?
delivery_channels.find_by!(is_self_delivery: true)
end
|
#set_default_minimum_seat_allotment ⇒ Object
277
278
279
|
# File 'app/models/restaurant.rb', line 277
def set_default_minimum_seat_allotment
self.minimum_seat_allotment = 0
end
|
#short_name_sms ⇒ Object
550
551
552
|
# File 'app/models/restaurant.rb', line 550
def short_name_sms
short_name.presence || name_en.presence || name_th
end
|
#sum_party_size ⇒ Integer
sum of reservations party size
237
238
239
|
# File 'app/models/restaurant.rb', line 237
define_counter_cache :sum_party_size do |_|
_.reservations.reached_goal_scope.sum(:party_size)
end
|
#to_param ⇒ Object
281
282
283
|
# File 'app/models/restaurant.rb', line 281
def to_param
id
end
|
#use_third_party_inventory? ⇒ Boolean
595
596
597
598
|
# File 'app/models/restaurant.rb', line 595
def use_third_party_inventory?
inv_third_party = InventoryWrapper.new(restaurant_id: id).inv_model
!['Inventory', 'InventoryTakeAway'].include?(inv_third_party.to_s)
end
|
#validate_commission_for_packages(commision) ⇒ Object
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
|
# File 'app/models/restaurant.rb', line 571
def validate_commission_for_packages(commision)
unique_commissions = restaurant_packages.map { |rp| rp.package.commision }.uniq
tolerance = 0.0001
if unique_commissions.count == 1
if commision.blank?
true
elsif commision.present? && (unique_commissions.last - commision.to_f).abs > tolerance
errors.add(:commision,
'error. Account level commission and package level commission must be the same or else Account level should be blank')
end
elsif unique_commissions.count > 1 && commision.blank?
true
elsif unique_commissions.count > 1 && commision.present?
errors.add(:commision,
'error. Account level commission and package level commission must be the same or else Account level should be blank')
end
end
|