Class: CancelReservationService
- Inherits:
-
BaseOperationService
- Object
- BaseOperationService
- CancelReservationService
- Includes:
- ActionView::Helpers::DateHelper, DefaultErrorContainer
- Defined in:
- app/services/cancel_reservation_service.rb
Overview
Cancel reservation
Instance Attribute Summary collapse
-
#actor ⇒ Object
Returns the value of attribute actor.
-
#cancel_reason ⇒ Object
Returns the value of attribute cancel_reason.
-
#options ⇒ Object
writeonly
Sets the attribute options.
-
#reservation_id ⇒ Object
Returns the value of attribute reservation_id.
Attributes inherited from BaseOperationService
Instance Method Summary collapse
- #execute ⇒ Object
-
#initialize(reservation_id, actor, options = {}) ⇒ CancelReservationService
constructor
A new instance of CancelReservationService.
- #valid? ⇒ Boolean
Methods included from DefaultErrorContainer
#error, #error_message_simple, #merge_errors
Methods inherited from BaseOperationService
Constructor Details
#initialize(reservation_id, actor, options = {}) ⇒ CancelReservationService
Returns a new instance of CancelReservationService.
20 21 22 23 24 |
# File 'app/services/cancel_reservation_service.rb', line 20 def initialize(reservation_id, actor, = {}) @reservation_id = reservation_id @actor = actor @options = end |
Instance Attribute Details
#actor ⇒ Object
Returns the value of attribute actor.
11 12 13 |
# File 'app/services/cancel_reservation_service.rb', line 11 def actor @actor end |
#cancel_reason ⇒ Object
Returns the value of attribute cancel_reason.
11 12 13 |
# File 'app/services/cancel_reservation_service.rb', line 11 def cancel_reason @cancel_reason end |
#options=(value) ⇒ Object (writeonly)
Sets the attribute options
12 13 14 |
# File 'app/services/cancel_reservation_service.rb', line 12 def (value) @options = value end |
#reservation_id ⇒ Object
Returns the value of attribute reservation_id.
11 12 13 |
# File 'app/services/cancel_reservation_service.rb', line 11 def reservation_id @reservation_id end |
Instance Method Details
#execute ⇒ Object
26 27 28 29 30 31 32 33 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 59 60 61 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 133 |
# File 'app/services/cancel_reservation_service.rb', line 26 def execute return false unless valid? result = false ActiveRecord::Base.transaction do reservation.lock! reservation.mark_voucher_as_inactive! reservation.cancel_reason = cancel_reason reservation.cancelled_by = actor reservation.audit_comment = "cancelled by #{actor}" reservation.mark_as_canceled! unless reservation.save! merge_errors(reservation.errors) raise ActiveRecord::Rollback end # Cancel seven rooms reservation if restaurant using seven rooms inventory cancel_sr_reservation_result = cancel_seven_rooms_reservation unless cancel_sr_reservation_result.success? errors.add(:base, SevenRooms::ErrorMessages.(actor, cancel_sr_reservation_result.)) raise ActiveRecord::Rollback end # Cancel TableCheck reservation if restaurant using TableCheck inventory cancel_tc_reservation_result = cancel_tablecheck_reservation unless cancel_tc_reservation_result.success? errors.add(:base, Tablecheck::ErrorMessages.(actor, cancel_tc_reservation_result.)) raise ActiveRecord::Rollback end cancel_weeloy_reservation_result = cancel_weeloy_reservation unless cancel_weeloy_reservation_result.success? errors.add(:base, Weeloy::ErrorMessages.(actor, cancel_weeloy_reservation_result.)) raise ActiveRecord::Rollback end # Cancel BistroChat reservation if restaurant using BistroChat inventory cancel_bistrochat_reservation_result = cancel_bistrochat_reservation unless cancel_bistrochat_reservation_result.success? errors.add(:base, Bistrochat::ErrorMessages.(actor, cancel_bistrochat_reservation_result.)) raise ActiveRecord::Rollback end # Cancel MyMenu reservation if restaurant using MyMenu inventory = unless .success? errors.add(:base, MyMenu::ErrorMessages.(actor, .)) raise ActiveRecord::Rollback end delete_calendar cancel_referral_reward cancel_booking_reward # Skip payment verification for admins, vendor-allowed cancellations, or force cancellations # force_cancel bypasses payment checks for emergency/administrative scenarios unless by_admin? || vendor_cancellation_allowed? || force_cancel? check_payment end # Process refund guarantee claim if requested if claim_refund? refund_claim_service = RefundGuaranteeClaimService.new(reservation_id, actor) unless refund_claim_service.execute merge_errors(refund_claim_service.errors) raise ActiveRecord::Rollback end end if by_admin? || by_owner? reservation.trigger_immediate_sync else reservation.trigger_priority_sync end result = true end return false unless result invalidate_shopee_pay if reservation.shopee_pay_provider? if reservation.by_marketplace? vendor_name = reservation.vendor_reservation.oauth_application.name case vendor_name # No need to send CANCEL status to OpenRice Webhook if the actor is user # Because OpenRice will get the real time status from API response when ApiVendorV1::Constants::OPEN_RICE_VENDOR_NAME if !by_user? Vendors::OpenRice::WebhookWorker.perform_async(reservation.id.to_s, reservation.vendor_reservation.id.to_s, ApiVendorV1::Constants::CANCEL) end when ApiVendorV1::Constants::TAG_THAI_VENDOR_NAME Vendors::TagThai::WebhookWorker.perform_async(reservation.id, ApiVendorV1::Constants::CANCEL) when ApiVendorV1::Constants::GOOGLE_RESERVE_VENDOR_NAME google_status = by_user? ? ApiVendorV1::Constants::RWG_CANCELED : ApiVendorV1::Constants::RWG_DECLINED_BY_MERCHANT Vendors::GoogleReserve::WebhookWorker.perform_async(reservation.id, google_status) else APMErrorHandler.report("Invalid vendor name: #{vendor_name}") end end NotificationWorkers::Reservation.perform_in(30.seconds, reservation.id, 'cancel') Netcore::EventWorker.perform_in(Netcore::EventWorker::DELAY, :reservation_event, reservation_id) true end |
#valid? ⇒ Boolean
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'app/services/cancel_reservation_service.rb', line 135 def valid? return false unless reservation_id&.to_i&.positive? && actor.present? unless reservation.active? errors.add(:base, 'Reservation already cancelled') return false end if actor.to_sym == :owner && reservation.restaurant.any_offers? && cancel_reason.blank? errors.add(:base, 'Reason is required') return false end if require_reason? errors.add(:base, 'Reason is required') return false end time_zone = reservation.restaurant.time_zone last_cancel_at = Time.now_in_tz(time_zone) - 24.hours res_time = reservation.reservation_time.in_time_zone(time_zone) if actor.to_sym == :owner && res_time < last_cancel_at errors.add(:base, 'Sorry you can not update if reservation has been passed more than 24 hours') return false end restaurant = reservation.restaurant if actor.to_sym == :user if reservation.is_past? errors.add(:base, 'Sorry your reservation has passed. You can no longer cancel your reservation. You have been marked as No Show') return false elsif restaurant.time_in_advance_to_rectify.to_i.positive? && !reservation.allowed_to_rectify? time_needed = distance_of_time_in_words restaurant.time_in_advance_to_rectify.minutes errors.add(:base, I18n.t('reservation.too_quick_to_rectify', time_needed: time_needed, phone: restaurant.phone)) return false end end # Prevent cancellation of reservations with successful charges, unless: # - Actor is admin (full authority) # - Vendor cancellation is explicitly allowed for this booking channel # - Force cancel is enabled (emergency/administrative override) # - User is claiming refund guarantee (handled separately) if !by_admin? && reservation.charges.present? && reservation.charges.success_scope.present? && !vendor_cancellation_allowed? && !force_cancel? && !claim_refund? errors.add(:base, 'Sorry, this booking can not be canceled') return false end true end |