582 lines
20 KiB
PHP
582 lines
20 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Backend;
|
|
|
|
use CodeIgniter\HTTP\ResponseInterface;
|
|
use CodeIgniter\RESTful\ResourceController;
|
|
use App\Models\OrderItemOptions;
|
|
use App\Models\OrderItems;
|
|
use App\Models\OrderPayments;
|
|
use App\Models\Orders;
|
|
use App\Models\OrderTaxes;
|
|
use CodeIgniter\Database\Config;
|
|
use CodeIgniter\HTTP\Message;
|
|
use App\Models\OrderDeliveries;
|
|
use App\Libraries\Wato;
|
|
use App\Models\User;
|
|
use App\Models\MenuItemVariations;
|
|
|
|
class OrderController extends ResourceController
|
|
{
|
|
private $orders;
|
|
private $order_items;
|
|
private $order_item_options;
|
|
private $order_payments;
|
|
private $order_taxes;
|
|
private $order_deliveries;
|
|
private $db;
|
|
private $wato;
|
|
private $user;
|
|
private $menu_item_variations;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->orders = new Orders();
|
|
$this->order_items = new OrderItems();
|
|
$this->order_item_options = new OrderItemOptions();
|
|
$this->order_taxes = new OrderTaxes();
|
|
$this->order_payments = new OrderPayments();
|
|
$this->order_deliveries = new OrderDeliveries();
|
|
$this->db = Config::connect();
|
|
$this->wato = new Wato();
|
|
$this->user = new User();
|
|
$this->menu_item_variations = new MenuItemVariations();
|
|
}
|
|
|
|
public function orderList()
|
|
{
|
|
$user_id = $this->request->getVar('user_id');
|
|
$start_date = $this->request->getVar('start_date');
|
|
$end_date = $this->request->getVar('end_date');
|
|
$status = $this->request->getVar('status');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
$order_type = $this->request->getVar('order_type');
|
|
|
|
// Get the user information to check role and outlet
|
|
$user = $this->user->find($user_id);
|
|
|
|
if (!$user) {
|
|
return $this->respond([
|
|
'status' => 404,
|
|
'message' => 'User not found',
|
|
'data' => []
|
|
]);
|
|
}
|
|
|
|
$orderQuery = $this->orders
|
|
->orderBy('created_at', 'DESC');
|
|
|
|
// If user is not admin, filter by their outlet_id
|
|
if ($user['role'] !== 'admin') {
|
|
$orderQuery->where('outlet_id', $user['outlet_id']);
|
|
} else {
|
|
// If admin and specific outlet_id is provided, use it
|
|
if (!empty($outlet_id)) {
|
|
$orderQuery->where('outlet_id', $outlet_id);
|
|
}
|
|
// Otherwise admin sees all orders (no outlet filter)
|
|
}
|
|
|
|
if (!empty($start_date)) {
|
|
$orderQuery->where('created_at >=', $start_date . ' 00:00:00');
|
|
}
|
|
|
|
if (!empty($end_date)) {
|
|
$orderQuery->where('created_at <=', $end_date . ' 23:59:59');
|
|
}
|
|
|
|
if (!empty($status)) {
|
|
$orderQuery->where('status', $status);
|
|
}
|
|
|
|
|
|
if (!empty($outlet_id)) {
|
|
$orderQuery->where('outlet_id', $outlet_id);
|
|
}
|
|
|
|
if (!empty($order_type)) {
|
|
$orderQuery->where('order_type', $order_type);
|
|
}
|
|
|
|
$orders = $orderQuery->findAll();
|
|
|
|
if (empty($orders)) {
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'No orders found!',
|
|
'data' => []
|
|
]);
|
|
}
|
|
|
|
foreach ($orders as &$order) {
|
|
$order_id = $order['id'];
|
|
|
|
// Fetch items + options
|
|
$order['items'] = $this->order_items->where('order_id', $order_id)->findAll();
|
|
foreach ($order['items'] as &$item) {
|
|
$item['options'] = $this->order_item_options
|
|
->where('order_item_id', $item['id'])
|
|
->findAll();
|
|
}
|
|
|
|
// Fetch taxes
|
|
$order['taxes'] = $this->order_taxes
|
|
->where('order_id', $order_id)
|
|
->findAll();
|
|
|
|
// Fetch payments
|
|
$order['payments'] = $this->order_payments
|
|
->where('order_id', $order_id)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll();
|
|
|
|
// Fetch deliveries
|
|
$order['deliveries'] = $this->order_deliveries
|
|
->where('order_id', $order_id)
|
|
->findAll();
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Orders retrieved successfully',
|
|
'data' => $orders
|
|
]);
|
|
}
|
|
|
|
public function showOrder($order_id = null)
|
|
{
|
|
// Get order with customer + outlet info
|
|
$order = $this->orders
|
|
->select('
|
|
orders.*,
|
|
customers.id as customer_id,
|
|
customers.name as customer_name,
|
|
customers.email as customer_email,
|
|
customers.phone as customer_phone,
|
|
customers.profile_picture as customer_profile_pic,
|
|
outlets.id as outlet_id,
|
|
outlets.title as outlet_title,
|
|
outlets.email as outlet_email,
|
|
outlets.phone as outlet_phone,
|
|
outlets.address as outlet_address,
|
|
')
|
|
->join('customers', 'customers.id = orders.customer_id', 'left')
|
|
->join('outlets', 'outlets.id = orders.outlet_id', 'left') // join outlets
|
|
->where('orders.id', $order_id)
|
|
->first();
|
|
|
|
if (!$order) {
|
|
return $this->fail('Order not found', 400);
|
|
}
|
|
|
|
// Items + options + menu images
|
|
$order['items'] = $this->order_items
|
|
->select('order_items.*, menu_images.image_url as menu_item_image')
|
|
->join('menu_images', 'menu_images.menu_item_id = order_items.menu_item_id', 'left')
|
|
->where('order_items.order_id', $order_id)
|
|
->groupBy('order_items.id')
|
|
->findAll();
|
|
|
|
foreach ($order['items'] as &$item) {
|
|
$item['options'] = $this->order_item_options->where('order_item_id', $item['id'])->findAll();
|
|
$item['menu_item_image'] = getMenuImage($item['menu_item_id']);
|
|
|
|
$item['variation_name'] = $this->menu_item_variations
|
|
->where('menu_item_id', $item['menu_item_id'])
|
|
->where('id', $item['variation_id'])
|
|
->first()['title'] ?? '';
|
|
}
|
|
|
|
// Taxes
|
|
$order['taxes'] = $this->order_taxes->where('order_id', $order_id)->findAll();
|
|
|
|
// Payments
|
|
$order['payments'] = $this->order_payments
|
|
->where('order_id', $order_id)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll();
|
|
|
|
// Deliveries
|
|
$order['deliveries'] = $this->order_deliveries->where('order_id', $order_id)->findAll();
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Order retrieved successfully',
|
|
'data' => $order
|
|
]);
|
|
}
|
|
|
|
|
|
public function updateOrderSchedule($order_id = null)
|
|
{
|
|
// Validate order_id
|
|
if (empty($order_id)) {
|
|
return $this->fail('Order ID is required', 400);
|
|
}
|
|
|
|
// Get the order
|
|
$order = $this->orders->find($order_id);
|
|
if (!$order) {
|
|
return $this->fail('Order not found', 404);
|
|
}
|
|
|
|
// Check if order status is 'complete'
|
|
if (isset($order['status']) && $order['status'] === 'complete') {
|
|
return $this->fail('Cannot modify schedule for completed orders', 400);
|
|
}
|
|
|
|
// Get request data
|
|
$selected_date = $this->request->getVar('selected_date');
|
|
$selected_time = $this->request->getVar('selected_time');
|
|
|
|
// Validate input
|
|
if (empty($selected_date) || empty($selected_time)) {
|
|
return $this->fail('Both selected_date and selected_time are required', 400);
|
|
}
|
|
|
|
// Prepare data to update
|
|
$data = [
|
|
'selected_date' => $selected_date,
|
|
'selected_time' => $selected_time,
|
|
'updated_at' => date('Y-m-d H:i:s') // Update timestamp
|
|
];
|
|
|
|
try {
|
|
// Update the order
|
|
$updated = $this->orders->update($order_id, $data);
|
|
|
|
if (!$updated) {
|
|
return $this->fail('Failed to update order schedule', 500);
|
|
}
|
|
|
|
// Get the updated order
|
|
$updatedOrder = $this->orders->find($order_id);
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Order schedule updated successfully',
|
|
'data' => $updatedOrder
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->fail('An error occurred while updating order schedule: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function updateOrderStatus($order_id = null)
|
|
{
|
|
// Validate order_id
|
|
if (empty($order_id)) {
|
|
return $this->fail('Order ID is required', 400);
|
|
}
|
|
|
|
// Get the order
|
|
$order = $this->orders->select('orders.*, customer_addresses.phone as recipient_phone')
|
|
->join('customer_addresses', 'customer_addresses.id = orders.customer_address_id AND customer_addresses.deleted_at IS NULL', 'left')->find($order_id);
|
|
if (!$order) {
|
|
return $this->fail('Order not found', 404);
|
|
}
|
|
|
|
// Get request data
|
|
$status = $this->request->getVar('status');
|
|
|
|
// Validate input
|
|
if (empty($status)) {
|
|
return $this->fail('Status is required', 400);
|
|
}
|
|
|
|
// Define allowed status values
|
|
$allowedStatuses = ['pending', 'picked_up', 'on_the_way', 'completed', 'ready_to_pickup'];
|
|
if (!in_array($status, $allowedStatuses)) {
|
|
return $this->fail('Invalid status value. Allowed values: ' . implode(', ', $allowedStatuses), 400);
|
|
}
|
|
|
|
// Prepare data to update
|
|
$data = [
|
|
'status' => $status,
|
|
'updated_at' => date('Y-m-d H:i:s') // Update timestamp
|
|
];
|
|
|
|
try {
|
|
// Update the order
|
|
$updated = $this->orders->update($order_id, $data);
|
|
if ($order['status'] != $status) { //send notification to customer if status is changed
|
|
$message = '';
|
|
switch ($status) {
|
|
case 'ready_to_pickup':
|
|
$message = "🍴 Your food is ready for pickup!\nPlease show your order number at the counter: \n**{{" . $order['order_so'] . "}}**";
|
|
break;
|
|
case 'on_the_way':
|
|
$message = "🚚 Your order [**" . $order['order_so'] . "**] is on the way!\nThe driver is delivering your food now.\nPlease get ready to receive it.";
|
|
break;
|
|
case 'completed':
|
|
$message = "🎉 Your order [**" . $order['order_so'] . "**] has been completed.\nWe hope you enjoy your meal!\nThank you for ordering with us.";
|
|
break;
|
|
}
|
|
|
|
if ($message) {
|
|
$this->wato->pushNotification($order['recipient_phone'], $message);
|
|
}
|
|
}
|
|
|
|
if (!$updated) {
|
|
return $this->fail('Failed to update order status', 500);
|
|
}
|
|
|
|
// Get the updated order
|
|
$updatedOrder = $this->orders->find($order_id);
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Order status updated successfully',
|
|
'data' => $updatedOrder
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->fail('An error occurred while updating order status: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function createOrderDelivery()
|
|
{
|
|
// Get request data
|
|
$order_id = $this->request->getVar('order_id');
|
|
$fee_amount = $this->request->getVar('actual_fee_amount');
|
|
$tracking_link = $this->request->getVar('tracking_link');
|
|
|
|
// Optional fields that will be set to empty string if not provided
|
|
$provider_name = $this->request->getVar('provider_name') ?? '';
|
|
$provider_order_id = $this->request->getVar('provider_order_id') ?? '';
|
|
$actual_fee_amount = $this->request->getVar('fee_amount') ?? '';
|
|
$transaction_id = $this->request->getVar('transaction_id') ?? '';
|
|
|
|
// Validate required fields
|
|
if (empty($order_id) || empty($actual_fee_amount) || empty($tracking_link)) {
|
|
return $this->fail('order_id, actual_fee_amount, and tracking_link are required', 400);
|
|
}
|
|
|
|
// Check if the order exists
|
|
$order = $this->orders->find($order_id);
|
|
if (!$order) {
|
|
return $this->fail('Order not found', 404);
|
|
}
|
|
|
|
// Prepare data for insertion with empty strings for optional fields
|
|
$data = [
|
|
'order_id' => $order_id,
|
|
'provider_name' => $provider_name,
|
|
'status' => 'pending', // Default status
|
|
'provider_order_id' => $provider_order_id,
|
|
'fee_amount' => $fee_amount,
|
|
'actual_fee_amount' => $actual_fee_amount,
|
|
'transaction_id' => $transaction_id,
|
|
'tracking_link' => $tracking_link,
|
|
'created_at' => date('Y-m-d H:i:s'),
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
try {
|
|
// Insert the data
|
|
$inserted = $this->order_deliveries->insert($data);
|
|
|
|
if (!$inserted) {
|
|
return $this->fail('Failed to create order delivery record', 500);
|
|
}
|
|
|
|
// Get the inserted ID
|
|
$insertId = $this->db->insertID();
|
|
|
|
// Return success response with the created record
|
|
return $this->respond([
|
|
'status' => 201,
|
|
'message' => 'Order delivery record created successfully',
|
|
'data' => array_merge(['id' => $insertId], $data)
|
|
], 201);
|
|
} catch (\Exception $e) {
|
|
return $this->fail('An error occurred while creating order delivery: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function updateOrderDelivery($id = null)
|
|
{
|
|
if (empty($id)) {
|
|
return $this->fail('Delivery record ID is required', 400);
|
|
}
|
|
|
|
// Get request data - all fields optional except id
|
|
$data = [
|
|
'actual_fee_amount' => $this->request->getVar('actual_fee_amount') ?? '',
|
|
'tracking_link' => $this->request->getVar('tracking_link'),
|
|
'updated_at' => date('Y-m-d H:i:s')
|
|
];
|
|
|
|
// Remove fields that weren't provided in the request (except status which has a default)
|
|
$data = array_filter($data, function ($value, $key) {
|
|
return $value !== null || $key === 'status';
|
|
}, ARRAY_FILTER_USE_BOTH);
|
|
|
|
if (empty($data)) {
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'No fields to update',
|
|
'data' => null
|
|
]);
|
|
}
|
|
|
|
try {
|
|
$updated = $this->order_deliveries->update($id, $data);
|
|
|
|
if (!$updated) {
|
|
return $this->fail('Failed to update order delivery record', 500);
|
|
}
|
|
|
|
// Get the updated record
|
|
$updatedData = $this->order_deliveries->find($id);
|
|
|
|
// Convert NULL values to empty strings in the response
|
|
$responseData = [
|
|
'id' => $id,
|
|
'order_id' => $updatedData['order_id'],
|
|
'provider_name' => $updatedData['provider_name'] ?? '',
|
|
'status' => $updatedData['status'] ?? '',
|
|
'provider_order_id' => $updatedData['provider_order_id'] ?? '',
|
|
'fee_amount' => $updatedData['fee_amount'] ?? '',
|
|
'actual_fee_amount' => $updatedData['actual_fee_amount'],
|
|
'transaction_id' => $updatedData['transaction_id'] ?? '',
|
|
'tracking_link' => $updatedData['tracking_link'],
|
|
'created_at' => $updatedData['created_at'],
|
|
'updated_at' => $updatedData['updated_at']
|
|
];
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Order delivery updated successfully',
|
|
'data' => $responseData
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->fail('An error occurred while updating order delivery: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function getOrderDelivery($order_id = null)
|
|
{
|
|
// Validate order_id
|
|
if (empty($order_id)) {
|
|
return $this->fail('Order ID is required', 400);
|
|
}
|
|
|
|
try {
|
|
// Get delivery record by order_id
|
|
$delivery = $this->order_deliveries->where('order_id', $order_id)->get()->getRowArray();
|
|
|
|
if (!$delivery) {
|
|
return $this->respond([
|
|
'status' => 404,
|
|
'message' => 'No delivery record found for this order',
|
|
'data' => null
|
|
], 404);
|
|
}
|
|
|
|
// Format the response data with empty strings instead of NULL
|
|
$responseData = [
|
|
'id' => $delivery['id'],
|
|
'order_id' => $delivery['order_id'],
|
|
'provider_name' => $delivery['provider_name'] ?? '',
|
|
'status' => $delivery['status'] ?? '',
|
|
'provider_order_id' => $delivery['provider_order_id'] ?? '',
|
|
'fee_amount' => $delivery['fee_amount'] ?? '',
|
|
'actual_fee_amount' => $delivery['actual_fee_amount'],
|
|
'transaction_id' => $delivery['transaction_id'] ?? '',
|
|
'tracking_link' => $delivery['tracking_link'],
|
|
'created_at' => $delivery['created_at'],
|
|
'updated_at' => $delivery['updated_at']
|
|
];
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Order delivery retrieved successfully',
|
|
'data' => $responseData
|
|
]);
|
|
} catch (\Exception $e) {
|
|
return $this->fail('An error occurred while fetching order delivery: ' . $e->getMessage(), 500);
|
|
}
|
|
}
|
|
|
|
public function customerOrderList()
|
|
{
|
|
$start_date = $this->request->getVar('start_date');
|
|
$end_date = $this->request->getVar('end_date');
|
|
$status = $this->request->getVar('status');
|
|
$outlet_id = $this->request->getVar('outlet_id');
|
|
$order_type = $this->request->getVar('order_type');
|
|
|
|
$orderQuery = $this->orders
|
|
->orderBy('created_at', 'DESC');
|
|
|
|
|
|
if (!empty($start_date)) {
|
|
$orderQuery->where('created_at >=', $start_date . ' 00:00:00');
|
|
}
|
|
|
|
if (!empty($end_date)) {
|
|
$orderQuery->where('created_at <=', $end_date . ' 23:59:59');
|
|
}
|
|
|
|
if (!empty($status)) {
|
|
$orderQuery->where('status', $status);
|
|
}
|
|
|
|
|
|
if (!empty($outlet_id)) {
|
|
$orderQuery->where('outlet_id', $outlet_id);
|
|
}
|
|
|
|
if (!empty($order_type)) {
|
|
$orderQuery->where('order_type', $order_type);
|
|
}
|
|
|
|
$orders = $orderQuery->findAll();
|
|
|
|
if (empty($orders)) {
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'No orders found!',
|
|
'data' => []
|
|
]);
|
|
}
|
|
|
|
foreach ($orders as &$order) {
|
|
$order_id = $order['id'];
|
|
|
|
// Fetch items + options
|
|
$order['items'] = $this->order_items->where('order_id', $order_id)->findAll();
|
|
foreach ($order['items'] as &$item) {
|
|
$item['options'] = $this->order_item_options
|
|
->where('order_item_id', $item['id'])
|
|
->findAll();
|
|
}
|
|
|
|
// Fetch taxes
|
|
$order['taxes'] = $this->order_taxes
|
|
->where('order_id', $order_id)
|
|
->findAll();
|
|
|
|
// Fetch payments
|
|
$order['payments'] = $this->order_payments
|
|
->where('order_id', $order_id)
|
|
->orderBy('created_at', 'DESC')
|
|
->findAll();
|
|
|
|
// Fetch deliveries
|
|
$order['deliveries'] = $this->order_deliveries
|
|
->where('order_id', $order_id)
|
|
->findAll();
|
|
}
|
|
|
|
return $this->respond([
|
|
'status' => 200,
|
|
'message' => 'Orders retrieved successfully',
|
|
'data' => $orders
|
|
]);
|
|
}
|
|
|
|
}
|