Class: Api::Vendor::V1::VendorReservationsController

Inherits:
BaseController
  • Object
show all
Includes:
Concerns::Authentication, Concerns::CreateReservation, Concerns::IntegrationTestHelpers, Concerns::ReservationUtils
Defined in:
app/controllers/api/vendor/v1/vendor_reservations_controller.rb

Constant Summary

Constants inherited from BaseController

BaseController::CACHE_NAMESPACE

Instance Attribute Summary

Attributes inherited from BaseController

#vendor

Instance Method Summary collapse

Methods included from LogrageCustomLogger

#append_info_to_payload

Methods included from ResponseCacheConcern

#my_response_cache

Instance Method Details

#cancelObject



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
190
191
192
193
194
195
196
# File 'app/controllers/api/vendor/v1/vendor_reservations_controller.rb', line 162

def cancel
  reason = params.require(:reason)
  vendor_reservation_id = params.require(:vendor_reservation_id)

  reservation = Reservation.
    joins(:vendor_reservation).
    find_by(vendor_reservations: { id: vendor_reservation_id, vendor_id: vendor.id })

  return cancel_response(false, 'reservation not found') unless reservation

  RequestStore.store[:reservation_id] ||= reservation.id
  RequestStore.store[:restaurant_id] ||= reservation.restaurant_id
  BUSINESS_LOGGER.set_business_context({ reservation_id: reservation.id,
                                         vendor_name: vendor.name })
  VendorLogger.log_event(:request, params[:route], payload: params)

  service_options = { require_reason: true }
  service_options[:force_cancel] = integration_test_force_cancel_option if integration_test_mode?

  service = CancelReservationService.new(
    reservation.id,
    :user,
    service_options,
  )
  service.cancel_reason = reason

  if service.execute
    cancel_response(true, 'reservation successfully cancelled')
  else
    cancel_response(false, service.error_message_simple)
  end
rescue StandardError => e
  APMErrorHandler.report e
  cancel_response(false, e.message)
end

#createObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
# File 'app/controllers/api/vendor/v1/vendor_reservations_controller.rb', line 8

def create
  tmp_reservation_id = params.require(:tmp_reservation_id)
  reference_id = params.dig(:reservation, :reference_id)
  reseller_reference_id = params.dig(:reservation, :reseller, :reference_id)
  BUSINESS_LOGGER.set_business_context({ reservation_id: tmp_reservation_id,
                                         vendor_reference_id: reference_id || reseller_reference_id })
  VendorLogger.log_event(:request, params[:route], payload: params)

  # idempotency check
  if reference_id.present? || reseller_reference_id.present?
    vendor_reservation = VendorReservation.find_by(
      vendor_id: vendor.id,
      reference_id: reference_id,
      reseller_reference_id: reseller_reference_id,
    )

    if vendor_reservation.present?
      BUSINESS_LOGGER.info("#{self.class}: Vendor Reservation already exist, returning it")
      return render_create_reservation_success_response(vendor_reservation.reservation)
    end
  end

  is_package_qty_adjustable = ::Channel.adjust_package_qty_for_vendor?(vendor.name)

  # check and create new vendor payment
  required_payment_attributes = [:transaction_id, :currency, :status, :paid_at]
  amount_cents = params.dig(:vendor_payment, :amount_cents)&.to_d
  if amount_cents.present?
    BUSINESS_LOGGER.info(
      "#{self.class}: Vendor sent amount_cents in vendor payment attributes",
      { vendor: vendor.name },
    )
  end

  amount_subunits = params.dig(:vendor_payment, :amount_subunits)&.to_i
  if amount_subunits.present?
    BUSINESS_LOGGER.info("#{self.class}: Vendor sent amount_subunits in vendor payment attributes")
  end

  has_valid_amount = amount_cents.present? || amount_subunits.present?

  if required_payment_attributes.all? { |attr| params.dig(:vendor_payment, attr).present? } && has_valid_amount
    payment_currency = params[:vendor_payment][:currency] || Country::THAI_CURRENCY_CODE

    vendor_payment_attributes = {
      reservation_id: tmp_reservation_id,
      vendor_id: vendor.id,
      transaction_id: params[:vendor_payment][:transaction_id],
      # old vendors are sending wrong amount_cents (in unit), so we need to convert it to cents (subunits)
      # we have introduced new amount_subunits for future vendors with correct amount sent by vendors in cents
      amount_cents: amount_subunits || Money.from_amount(amount_cents, payment_currency).cents,
      currency: params[:vendor_payment][:currency],
      status: params[:vendor_payment][:status],
      paid_at: params[:vendor_payment][:paid_at],
    }
  end

  # create the vendor reservation
  create_vendor_reservation(vendor_payment_attributes, is_package_qty_adjustable)
rescue ActionController::ParameterMissing => e
  response = { success: false, message: e.message, data: nil }
  VendorLogger.log_event(:response, params[:route], payload: response)
  render json: response
end

#showObject



198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'app/controllers/api/vendor/v1/vendor_reservations_controller.rb', line 198

def show
  vendor_reservation_id = params.require(:id)

  reservation = Reservation.
    includes(:vendor_reservation).
    where(vendor_reservations: { id: vendor_reservation_id, vendor_id: vendor.id }).first!

  options = {
    params: {
      vendor_name: vendor.name,
      integration_test_mode: integration_test_mode?,
    },
  }
  serializer = Api::Vendor::V1::ReservationSerializer.new(reservation, options)

  response_hash = {
    success: true,
    message: nil,
  }
  render json: serializer.as_json.merge(response_hash)
rescue ActionController::ParameterMissing => e
  render json: { success: false, message: e.message, data: nil }
rescue ActiveRecord::RecordNotFound
  render json: { success: false, message: 'reservation not found', data: nil }
rescue StandardError => e
  APMErrorHandler.report e
  render json: { success: false, message: e.message, data: nil }
end

#updateObject



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
134
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
# File 'app/controllers/api/vendor/v1/vendor_reservations_controller.rb', line 73

def update
  vendor_reservation_id = params.require(:id)

  ActiveRecord::Base.transaction do
    begin
      is_package_qty_adjustable = ::Channel.adjust_package_qty_for_vendor?(vendor.name)

      reservation = Reservation.
        includes(:vendor_reservation).
        where(vendor_reservations: { id: vendor_reservation_id, vendor_id: vendor.id }, active: true).first!
    rescue ActiveRecord::RecordNotFound
      return render json: { success: false, message: 'reservation not found', data: nil }
    end

    update_params = update_reservation_params
    package_params = safe_package_params

    if is_package_qty_adjustable
      adult = update_params[:adult]
      kids = update_params[:kids]
      package_params.each do |package|
        rest_pack = HhPackage::RestaurantPackage.find(package[:id])
        package[:quantity] = calculate_package_qty(rest_pack, adult, kids)
      end
    end

    if ::Channel.adjust_pax_to_max_per_pack_qty?(vendor.name)
      rest_pack_id = package_params[0]['id'].to_i
      restaurant_package = HhPackage::RestaurantPackage.find_by(id: rest_pack_id)

      ttl_pkg_qty = if restaurant_package&.package&.dynamic_price_pricing_model&.to_sym == :per_pack
                      package_params[0]['quantity'].to_i
                    else
                      1 # for per_person packages, we set package qty as 1 in reservation params
                    end

      adjusted_adult_kids_qty = calculate_pax_qty(rest_pack_id,
                                                  update_params[:adult],
                                                  update_params[:kids])

      update_params[:adult], update_params[:kids] = adjusted_adult_kids_qty.map { |count| count * ttl_pkg_qty }
    end

    RequestStore.store[:reservation_id] ||= reservation.id
    RequestStore.store[:restaurant_id] ||= reservation.restaurant_id

    operation = Api::Vendor::V1::Concerns::UpdateReservation.new(
      reservation.id,
      update_params,
      package: package_params,
      vendor_reservation_params: create_vendor_reservation_params,
    )

    if operation.execute
      updated_reservation = operation.reservation

      updated_vendor_reservation = operation.update_vendor_reservation!(vendor_reservation_id,
                                                                        updated_reservation.id)

      operation.update_vendor_payment!(reservation.id, updated_reservation.id, vendor.id)

      # Trigger reservation summary sync using the concern method
      operation.sync_updated_reservations!(updated_reservation)

      options = {
        params: {
          vendor_name: vendor.name,
          integration_test_mode: integration_test_mode?,
        },
      }
      serializer = Api::Vendor::V1::ReservationSerializer.new(updated_vendor_reservation, options)
      response_hash = {
        success: true,
        message: 'reservation successfully updated',
      }
      render json: serializer.as_json.merge(response_hash)
    else
      return render json: { success: false, message: operation.error_message, data: nil }
    end
  end
rescue ActionController::ParameterMissing => e
  render json: { success: false, message: e.message, data: nil }
rescue ActiveRecord::RecordInvalid => e
  render json: { success: false, message: e.message, data: nil }
rescue StandardError => e
  APMErrorHandler.report e
  render json: { success: false, message: e.message, data: nil }
end