AMS_Backend/app/Helpers/order_helper.php
2025-11-06 13:41:06 +08:00

339 lines
13 KiB
PHP

<?php
use App\Models\Orders;
use App\Models\Outlet;
use App\Models\Customer;
use App\Models\MenuItems;
use App\Models\OrderItems;
use App\Models\OrderTaxes;
use App\Libraries\Lalamove;
use App\Models\CustomerPoint;
use App\Models\CustomerVoucherList;
use App\Models\OrderPayments;
use App\Models\CustomerWallet;
use App\Models\OrderDeliveries;
use App\Models\OrderItemOptions;
use App\Libraries\Wato;
if (!function_exists('getOrderType')) {
function getOrderType($id)
{
$orders = new Orders();
$order = $orders
->select('order_type')
->where('id', $id)
->where('deleted_at', null)
->first();
if (!$order) {
return '';
}
return $order['order_type'] ?? '';
}
}
if (!function_exists('getFullOrderDetail')) {
function getFullOrderDetail($id)
{
$orders = new Orders();
$order_items = new OrderItems();
$order_item_options = new OrderItemOptions();
$order_payments = new OrderPayments();
$order_taxes = new OrderTaxes();
$order_detail = array();
$order = $orders->find($id);
if (!$order) {
return array();
}
$order_detail = $order;
$order_detail['items'] = $order_items->where('order_id', $order['id'])->findAll();
foreach ($order_detail['items'] as &$item) {
$item['options'] = $order_item_options
->where('order_item_id', $item['id'])
->findAll();
}
$order_detail['taxes'] = $order_taxes
->where('order_id', $order['id'])
->findAll();
$order_detail['payments'] = $order_payments
->where('order_id', $order['id'])
->orderBy('created_at', 'DESC')
->findAll();
// $order_detail['item'] =
return $order_detail;
}
}
if (!function_exists('completeOrder')) {
function completeOrder($order_id)
{
$orders = new Orders();
$customers = new Customer();
$order_payments = new OrderPayments();
$customer_wallet = new CustomerWallet();
$customer_point_history = new CustomerPoint();
//get order and customer data
$order = $orders->select('orders.*, customers.*, order_payments.*')
->join('customers', 'customers.id = orders.customer_id AND customers.deleted_at IS NULL')
->join('order_payments', 'order_payments.order_id = orders.id AND order_payments.deleted_at IS NULL')
->where('orders.id', $order_id)
->where('orders.deleted_at', null)
->first();
if (!$order) {
return false;
}
//get payment method
$order_so = $order['order_so'];
$payment_method = $order['payment_method'];
$customer_id = $order['customer_id'];
$grand_total = $order['grand_total'];
$outlet_id = $order['outlet_id'];
$order_type = $order['order_type'];
//get outlet data
$outlets = new Outlet();
$outlet = $outlets->where('id', $outlet_id)->where('deleted_at', null)->first();
//update payment status
$orders->update($order_id, ['payment_status' => 'paid']);
switch ($payment_method) {
case 'wallet':
$wallet_balance = $order['customer_wallet'] - $grand_total;
$customers->update($customer_id, ['customer_wallet' => $wallet_balance]);
$order_payments->update($order_id, ['status' => 'completed', 'paid_at' => date('Y-m-d H:i:s')]);
$customer_wallet_transaction = [
'customer_id' => $customer_id,
'related_id' => $order_id,
'related_type' => 'order',
'action' => 'out',
'current' => $order['customer_wallet'],
'in' => 0,
'out' => $grand_total,
'balance' => $wallet_balance,
'remark' => $grand_total . ' deducted from wallet for order ' . $order_so,
];
$customer_wallet->insert($customer_wallet_transaction);
break;
default:
//update order payments
$order_payments->update($order_id, ['status' => 'completed', 'paid_at' => date('Y-m-d H:i:s')]);
break;
}
//update point
$customer_point = $order['customer_point'] + floor($grand_total);
$customers->update($customer_id, ['customer_point' => $customer_point]);
$customer_point_transaction = [
'customer_id' => $customer_id,
'related_id' => $order_id,
'related_type' => 'order',
'action' => 'in',
'current' => $order['customer_point'],
'in' => floor($grand_total),
'out' => 0,
'balance' => $customer_point,
'remark' => floor($grand_total) . ' points earned from order ' . $order_so,
];
$customer_point_history->insert($customer_point_transaction);
//get customer point history cumulative
$customer_point_history_cumulative = $customer_point_history->where('customer_id', $customer_id)->where('deleted_at', null)->selectSum('in')->get()->getRow()->in ?? 0;
//get membership tier setting and check for automatic upgrade
$setting_membership_tier = new \App\Models\SettingMembershipTier();
$membership_tier_setting = $setting_membership_tier->where('deleted_at', null)->orderBy('min_points', 'ASC')->findAll();
// Get current customer membership tier
$current_customer = $customers->where('id', $customer_id)->first();
$current_membership_tier = $current_customer['customer_tier_id'] ?? 0;
$get_current_tier = $setting_membership_tier->where('id', $current_membership_tier)->first();
$current_tier_min_points = $get_current_tier['min_points'] ?? 0;
// echo($customer_point_history_cumulative);exit;
// Check if customer qualifies for higher membership tier
$new_membership_tier = $current_membership_tier;
foreach ($membership_tier_setting as $tier) {
if ($customer_point_history_cumulative >= $tier['min_points'] && $tier['min_points'] > $current_tier_min_points) {
// Customer qualifies for this tier
// if($tier['id'] > $current_membership_tier){
$new_membership_tier = $tier['id'];
log_message('info', 'Customer ' . $customer_id . ' upgraded from tier ' . $current_membership_tier . ' to tier ' . $new_membership_tier . ' (Points: ' . $customer_point_history_cumulative . ')');
// }
}
}
// Update customer membership tier if upgraded
if ($new_membership_tier != $current_membership_tier) {
$customers->update($customer_id, [
'customer_tier_id' => $new_membership_tier
]);
log_message('info', 'Customer ' . $customer_id . ' membership tier updated to: ' . $new_membership_tier);
}
if ($order_type == 'delivery') { //need to check date & time as well
// Check which delivery service was used based on quotation ID
if ($order['lalamove_quot_id'] != null) {
// Lalamove was used for quotation
$lalamove = new Lalamove();
$lalamove_response = $lalamove->submitOrder($order_id);
if (isset($lalamove_response['data']['orderId'])) {
$order_delivery = new OrderDeliveries();
$order_delivery->insert([
'order_id' => $order_id,
'provider_name' => 'Lalamove',
'status' => 'success',
'provider_order_id' => $lalamove_response['data']['orderId'],
'fee_amount' => $lalamove_response['data']['priceBreakdown']['total'],
'actual_fee_amount' => $lalamove_response['data']['priceBreakdown']['total'],
'transaction_id' => $lalamove_response['data']['quotationId'],
'tracking_link' => $lalamove_response['data']['shareLink'],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
} else {
return false;
}
} else if ($order['grab_quot_id'] != null) {
// Grab was used for quotation
$grab = new \App\Libraries\Grab();
$grab_response = $grab->submitOrder($order_id);
if (isset($grab_response['deliveryID'])) {
$order_delivery = new OrderDeliveries();
$order_delivery->insert([
'order_id' => $order_id,
'provider_name' => 'Grab',
'status' => 'success',
'provider_order_id' => $grab_response['deliveryID'],
'fee_amount' => $order['delivery_fee'] ?? 0,
'actual_fee_amount' => $order['delivery_fee'] ?? 0,
'transaction_id' => $order['grab_quot_id'] ?? null,
'tracking_link' => $grab_response['trackingURL'] ?? null,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
//update order status
$orders->update($order_id, ['grab_quot_id' => $grab_response['deliveryID']]);
} else {
return false;
}
} else if ($order['delivery_fee'] > 0) {
//manual delivery fee
$order_delivery = new OrderDeliveries();
$order_delivery->insert([
'order_id' => $order_id,
'provider_name' => 'Manual',
'status' => 'success',
'fee_amount' => $order['delivery_fee'] ?? 0,
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);
}
}
// Get all items for this order
$order_items = new OrderItems();
$menu_item = new MenuItems();
$customer_voucher_lists = new CustomerVoucherList();
$membershipTier = null;
$hasMembershipItem = false;
$orderItems = $order_items->where('order_id', $order_id)->findAll();
// Loop through items in order — assume $orderItems is already in "latest first" order
foreach ($orderItems as $item) {
$menuItem = $menu_item->where('id', $item['menu_item_id'])->first();
if ($menuItem && !empty($menuItem['membership_tier'])) {
$membershipTier = (int) $menuItem['membership_tier'];
$hasMembershipItem = true;
break; // stop at first membership found — since list is latest first
}
}
if ($hasMembershipItem) {
// Update customer tier
$customers->update($customer_id, [
'customer_tier_id' => $membershipTier,
'customer_type' => 'VIP Customer'
]);
// Give 3 vouchers
for ($i = 0; $i < 3; $i++) {
$voucherCode = strtoupper(uniqid('VCH'));
$data = [
'customer_id' => $customer_id,
'promo_setting_id' => '29',
'voucher_order_id' => $order_id,
'voucher_topup_id' => 0,
'voucher_code' => $voucherCode,
'voucher_expiry_date' => '2025-12-31',
'voucher_status' => 'active',
];
$customer_voucher_lists->insert($data);
}
}
//send notification to customer
$wato = new Wato();
$message = "🍽️ Your order has been placed successfully!\nOur outlet is now preparing your food.\nThank you for your patience.";
$wato->pushNotification($order['phone'], $message);
return true;
//update order status
// $orders->update($order_id, ['delivery_status' => 'pending']);
}
}
if (!function_exists('calculateRoundingAmount')) {
function calculateRoundingAmount($original_amount)
{
// Convert to float and format to 2 decimal places
$original_amount = number_format_no_round((float)$original_amount);
// echo($amount);exit;
// Get the last digit (cents)
$lastDigit = (int)substr($original_amount, -1);
// Apply rounding rules
if ($lastDigit <= 2) {
// Round down to nearest 0
$amount = substr_replace($original_amount, '0', -1);
} elseif ($lastDigit <= 7) {
// Round to nearest 5
$amount = substr_replace($original_amount, '5', -1);
} else {
// Round up to next 10 cents
$amount = number_format((float)$original_amount+0.1, 2, '.', '');
$amount = substr_replace($amount, '0', -1);
}
if ($lastDigit >= 6 && $lastDigit <= 9) {
return number_format(((float)$amount - (float)$original_amount), 2);
} else {
return number_format(((float)$original_amount - (float)$amount), 2);
}
}
}