FIXES
-error handling from KBZ response error handling from network error
This commit is contained in:
@@ -1,9 +1,10 @@
|
|||||||
class Foodcourt::QrpayController < BaseFoodcourtController
|
class Foodcourt::QrpayController < BaseFoodcourtController
|
||||||
|
class PaymentProcessingError < StandardError; end
|
||||||
|
|
||||||
require 'rqrcode'
|
require 'rqrcode'
|
||||||
skip_before_action :authenticate, only: [:create]
|
skip_before_action :authenticate, only: [:create]
|
||||||
skip_before_action :verify_authenticity_token, only: [:create]
|
skip_before_action :verify_authenticity_token, only: [:create]
|
||||||
|
|
||||||
|
|
||||||
def init
|
def init
|
||||||
@cash_exist = PaymentMethodSetting.cash_exist
|
@cash_exist = PaymentMethodSetting.cash_exist
|
||||||
@credit_exist = PaymentMethodSetting.credit_exist
|
@credit_exist = PaymentMethodSetting.credit_exist
|
||||||
@@ -31,6 +32,7 @@ class Foodcourt::QrpayController < BaseFoodcourtController
|
|||||||
@membership_rebate_balance=0
|
@membership_rebate_balance=0
|
||||||
|
|
||||||
if Sale.exists?(sale_id)
|
if Sale.exists?(sale_id)
|
||||||
|
begin
|
||||||
@cash = 0.0
|
@cash = 0.0
|
||||||
@kbz_pay_amount = 0.0
|
@kbz_pay_amount = 0.0
|
||||||
@other = 0.0
|
@other = 0.0
|
||||||
@@ -187,6 +189,9 @@ class Foodcourt::QrpayController < BaseFoodcourtController
|
|||||||
|
|
||||||
@paymethod = PaymentMethodSetting.find_by(payment_method: "MMQR")
|
@paymethod = PaymentMethodSetting.find_by(payment_method: "MMQR")
|
||||||
|
|
||||||
|
if @paymethod.nil?
|
||||||
|
raise "MMQR payment method not configured"
|
||||||
|
end
|
||||||
|
|
||||||
@merchant = KbzMerchant.new(@paymethod)
|
@merchant = KbzMerchant.new(@paymethod)
|
||||||
|
|
||||||
@@ -207,9 +212,19 @@ class Foodcourt::QrpayController < BaseFoodcourtController
|
|||||||
|
|
||||||
when 'error'
|
when 'error'
|
||||||
@error = @response[:message]
|
@error = @response[:message]
|
||||||
|
raise PaymentProcessingError, @response[:message]
|
||||||
when 'failed'
|
when 'failed'
|
||||||
@error = @response[:message]
|
@error = @response[:message]
|
||||||
|
raise PaymentProcessingError, @response[:message]
|
||||||
end
|
end
|
||||||
|
rescue PaymentProcessingError, StandardError => e
|
||||||
|
Rails.logger.error("Payment processing error: #{e.message}")
|
||||||
|
cancel_order_and_sale(sale_id, e.message)
|
||||||
|
flash[:error] = "Payment failed: #{e.message}"
|
||||||
|
redirect_to foodcourt_food_court_path
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -333,4 +348,85 @@ class Foodcourt::QrpayController < BaseFoodcourtController
|
|||||||
format.json { render :json => { status: true, order_id: order.order_id } }
|
format.json { render :json => { status: true, order_id: order.order_id } }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def cancel_order_and_sale(sale_id, error_message = nil)
|
||||||
|
result = { success: false, error: nil }
|
||||||
|
|
||||||
|
sale = Sale.find_by(sale_id: sale_id)
|
||||||
|
unless sale
|
||||||
|
result[:error] = "Sale not found"
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
order = sale.orders.first
|
||||||
|
unless order
|
||||||
|
result[:error] = "Order not found"
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
booking = order.booking
|
||||||
|
unless booking
|
||||||
|
result[:error] = "Booking not found"
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
begin
|
||||||
|
Sale.transaction do
|
||||||
|
order.order_items.update_all(order_item_status: 'cancelled') if order.order_items.present?
|
||||||
|
|
||||||
|
order.update!(status: 'cancelled')
|
||||||
|
|
||||||
|
booking.update!(booking_status: 'cancelled')
|
||||||
|
|
||||||
|
if sale.shift_sale_id
|
||||||
|
shift = ShiftSale.find(sale.shift_sale_id)
|
||||||
|
if sale.sale_status == "completed"
|
||||||
|
shift.calculate(sale_id, "void")
|
||||||
|
else
|
||||||
|
shift.update!(total_void: shift.total_void + sale.grand_total)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if sale.discount_type == "member_discount"
|
||||||
|
sale.update!(total_discount: 0)
|
||||||
|
sale.compute_by_sale_items(0, nil, 'foodcourt')
|
||||||
|
end
|
||||||
|
|
||||||
|
sale.update!(
|
||||||
|
rounding_adjustment: 0.0,
|
||||||
|
payment_status: 'void',
|
||||||
|
sale_status: 'void'
|
||||||
|
)
|
||||||
|
|
||||||
|
if table = booking.dining_facility
|
||||||
|
table.update!(status: 'available') unless table.current_bookings.exists?
|
||||||
|
end
|
||||||
|
|
||||||
|
action_by = current_user.role == "cashier" && params[:access_code].present? ?
|
||||||
|
Employee.find_by(emp_id: params[:access_code])&.name :
|
||||||
|
current_user.name
|
||||||
|
|
||||||
|
remark = error_message ? "Payment failed: #{error_message}" : "Manually cancelled"
|
||||||
|
SaleAudit.record_audit_for_edit(
|
||||||
|
sale.sale_id,
|
||||||
|
current_user.name,
|
||||||
|
action_by,
|
||||||
|
remark,
|
||||||
|
"SALEVOID"
|
||||||
|
)
|
||||||
|
|
||||||
|
SaleOrder.where(sale_id: sale.sale_id).find_each do |sodr|
|
||||||
|
AssignedOrderItem.where(order_id: sodr.order_id).update_all(delivery_status: 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
result[:success] = true
|
||||||
|
end
|
||||||
|
rescue StandardError => e
|
||||||
|
result[:error] = "Cancellation failed: #{e.message}"
|
||||||
|
Rails.logger.error "Cancellation error: #{e.message}\n#{e.backtrace.join("\n")}"
|
||||||
|
end
|
||||||
|
result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
<!-- This is now Column 1 -->
|
<!-- This is now Column 1 -->
|
||||||
<div class="col-6"> <!-- Using col-md-6 for responsiveness, col-6 is also fine -->
|
<div class="col-6"> <!-- Using col-md-6 for responsiveness, col-6 is also fine -->
|
||||||
<div class="text-center">
|
<div class="text-center">
|
||||||
<img src="/image/mmqr.webp" alt="MMQR Payment" style="max-width: 120px; margin-bottom: 10px;">
|
<img src="/image/mmqr.webp" alt="MMQR Payment" style="max-width: 90px; margin-bottom: 10px;">
|
||||||
<h5>Scan to Pay</h5>
|
<h5>Scan to Pay</h5>
|
||||||
<p class="text-muted">Use your mobile wallet app</p>
|
<p class="text-muted">Use your mobile wallet app</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -298,15 +298,16 @@
|
|||||||
|
|
||||||
@media(min-width: 600px){
|
@media(min-width: 600px){
|
||||||
#second_display_order_items{
|
#second_display_order_items{
|
||||||
margin-top: -3rem;
|
margin-top: 1rem;
|
||||||
}
|
}
|
||||||
#mmqr_payment{
|
#mmqr_payment{
|
||||||
margin-top: -3rem;
|
margin-top: 1rem;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#payment_success{
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 576px) {
|
@media (max-width: 576px) {
|
||||||
.card-header h4 { font-size: 1.1rem; }
|
.card-header h4 { font-size: 1.1rem; }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<% breadcrumb_add t("payment_methods"), settings_payment_method_settings_path, settings_payment_method_settings_path, t("views.btn.#{action_name}") %>
|
<% breadcrumb_add t("payment_methods"), settings_payment_method_settings_path, settings_payment_method_settings_path, t("views.btn.#{action_name}") %>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
|
<div class="col-xs-12 col-sm-12 col-md-8 col-lg-8">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="body">
|
<div class="body">
|
||||||
@@ -89,10 +89,10 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const jsonFields = document.getElementById('json-fields');
|
const jsonFields = document.getElementById('json-fields');
|
||||||
const jsonOutput = document.getElementById('additional-parameters-json');
|
const jsonOutput = document.getElementById('additional-parameters-json');
|
||||||
|
|
||||||
@@ -163,10 +163,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- <script type="text/javascript">
|
<!-- <script type="text/javascript">
|
||||||
$(function() {
|
$(function() {
|
||||||
$(document).on('click', '#payment_method_setting_gateway_communication_type', function(event){
|
$(document).on('click', '#payment_method_setting_gateway_communication_type', function(event){
|
||||||
if ($(this).val() == "Api") {
|
if ($(this).val() == "Api") {
|
||||||
@@ -179,6 +179,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|||||||
Reference in New Issue
Block a user