279 lines
10 KiB
PHP
279 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\Controllers\Backend;
|
|
|
|
use CodeIgniter\RESTful\ResourceController;
|
|
use App\Models\Orders;
|
|
use App\Models\TopupModel;
|
|
use App\Models\Customer;
|
|
use App\Models\Outlet;
|
|
|
|
|
|
class DashboardController extends ResourceController
|
|
{
|
|
private $orders;
|
|
private $topup;
|
|
private $customer;
|
|
private $outlets;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->orders = new Orders();
|
|
$this->topup = new TopupModel();
|
|
$this->customer = new Customer();
|
|
$this->outlets = new Outlet();
|
|
}
|
|
|
|
|
|
public function dashboard()
|
|
{
|
|
$today = date('Y-m-d');
|
|
$month = date('m');
|
|
$year = date('Y');
|
|
|
|
// 1. Net Sales Today (sum of grand_total where paid)
|
|
$netSalesToday = $this->orders
|
|
->selectSum('grand_total')
|
|
->where('DATE(created_at)', $today)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->grand_total ?? 0;
|
|
|
|
// 2. Today Transaction (count orders today)
|
|
$todayTransaction = $this->orders
|
|
->where('DATE(created_at)', $today)
|
|
->where('payment_status', 'paid')
|
|
->countAllResults();
|
|
|
|
// 3. Net Sales Month to Date
|
|
$netSalesMonthToDate = $this->orders
|
|
->selectSum('grand_total')
|
|
->where('MONTH(created_at)', $month)
|
|
->where('YEAR(created_at)', $year)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->grand_total ?? 0;
|
|
|
|
// 4. Net Sales Year to Date
|
|
$netSalesYearToDate = $this->orders
|
|
->selectSum('grand_total')
|
|
->where('YEAR(created_at)', $year)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->grand_total ?? 0;
|
|
|
|
// 5. Topup
|
|
$topup1 = $this->topup
|
|
->selectSum('amount')
|
|
->where('DATE(created_at)', $today)
|
|
->where('status', 'Success')
|
|
->get()->getRow()->amount ?? 0;
|
|
|
|
$topup2 = $this->topup
|
|
->selectSum('other_amount')
|
|
->where('DATE(created_at)', $today)
|
|
->where('status', 'Success')
|
|
->get()->getRow()->other_amount ?? 0;
|
|
|
|
// 6. Total Customer Wallet Balance
|
|
$wallet_balance = $this->customer
|
|
->selectSum('customer_wallet')
|
|
->get()->getRow()->customer_wallet ?? 0;
|
|
|
|
// 7. Today Voucher Redeemed / Discount
|
|
$today_voucher_amount = $this->orders
|
|
->selectSum('voucher_discount_amount')
|
|
->where('DATE(created_at)', $today)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->voucher_discount_amount ?? 0;
|
|
|
|
$today_promo_amount = $this->orders
|
|
->selectSum('promo_discount_amount')
|
|
->where('DATE(created_at)', $today)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->promo_discount_amount ?? 0;
|
|
|
|
$today_discount_amount = $this->orders
|
|
->selectSum('promo_discount_amount')
|
|
->where('DATE(created_at)', $today)
|
|
->where('payment_status', 'paid')
|
|
->get()->getRow()->promo_discount_amount ?? 0;
|
|
|
|
|
|
$data = [
|
|
'today_net_sales' => $netSalesToday,
|
|
'today_total_transaction' => $todayTransaction,
|
|
'net_sales_month_to_date' => $netSalesMonthToDate,
|
|
'net_sales_year_to_date' => $netSalesYearToDate,
|
|
'today_topup' => $topup1 + $topup2,
|
|
'total_wallet_balance' => $wallet_balance,
|
|
'today_total_discount_amount' => $today_voucher_amount + $today_promo_amount + $today_discount_amount,
|
|
];
|
|
|
|
return $this->respond(['status' => 200, 'data' => $data]);
|
|
}
|
|
|
|
public function dashboardSummary ()
|
|
{
|
|
$data = [
|
|
'today' => $this->orders->getTodayOrdersRevenueByHour(),
|
|
'yesterday' => $this->orders->getYesterdayOrdersRevenueByHour(),
|
|
'last7days' => $this->orders->getLast7DaysOrdersRevenue(),
|
|
'last30days' => $this->orders->getLast30DaysOrdersRevenue(),
|
|
];
|
|
|
|
return $this->respond(['status' => 200, 'data' => $data]);
|
|
}
|
|
|
|
|
|
public function liveMonitor()
|
|
{
|
|
//Current Offline outlets
|
|
$outlets = $this->outlets->getOperatingHoursWithDaysList();
|
|
$onlineCount = 0;
|
|
$offlineCount = 0;
|
|
|
|
foreach ($outlets as $outlet) {
|
|
if ($this->isOutletOnline($outlet)) {
|
|
$onlineCount++;
|
|
} else {
|
|
$offlineCount++;
|
|
}
|
|
}
|
|
|
|
|
|
// Cancelled Orders (all time, or do you also want by date range?)
|
|
$cancelledOrders = $this->orders
|
|
->where('payment_status', 'cancelled')
|
|
->countAllResults();
|
|
|
|
// Dates
|
|
$endDateCurrent = date('Y-m-d'); // today
|
|
$startDateCurrent = date('Y-m-d', strtotime('-7 days')); // 7 days ago
|
|
|
|
$endDatePrevious = date('Y-m-d', strtotime('-8 days')); // day before current range
|
|
$startDatePrevious = date('Y-m-d', strtotime('-15 days')); // 15 days ago
|
|
|
|
// Function to fetch stats for a range
|
|
$getStats = function($startDate, $endDate) {
|
|
// Gross Sales
|
|
$grossSales = $this->orders
|
|
->selectSum('grand_total', 'gross_sales')
|
|
->where('payment_status', 'paid')
|
|
->where('created_at >=', $startDate)
|
|
->where('created_at <=', $endDate)
|
|
->where('promo_discount_amount <=', 0) // No promo discount
|
|
->where('voucher_discount_amount <=', 0) // No voucher discount
|
|
->where('discount_amount <=', 0) // No regular discount
|
|
->get()->getRow()->gross_sales ?? 0;
|
|
|
|
// Total Customer
|
|
$totalCustomer = $this->orders
|
|
->select('COUNT(DISTINCT customer_id) as total_customer')
|
|
->where('payment_status', 'paid')
|
|
->where('created_at >=', $startDate)
|
|
->where('created_at <=', $endDate)
|
|
->get()->getRow()->total_customer ?? 0;
|
|
|
|
// Net Sales from Offers
|
|
$netSalesOffers = $this->orders
|
|
->selectSum('grand_total', 'net_sales_offers')
|
|
->where('payment_status', 'paid')
|
|
->where('created_at >=', $startDate)
|
|
->where('created_at <=', $endDate)
|
|
->groupStart()
|
|
->where('promo_discount_amount >', 0)
|
|
->orWhere('voucher_discount_amount >', 0)
|
|
->orWhere('discount_amount >', 0)
|
|
->groupEnd()
|
|
->get()->getRow()->net_sales_offers ?? 0;
|
|
|
|
// Average Transaction
|
|
$avgTransaction = $this->orders
|
|
->selectAvg('grand_total', 'avg_transaction')
|
|
->where('payment_status', 'paid')
|
|
->where('created_at >=', $startDate)
|
|
->where('created_at <=', $endDate)
|
|
->get()->getRow()->avg_transaction ?? 0;
|
|
|
|
return [
|
|
'gross_sales' => $grossSales,
|
|
'total_customer' => $totalCustomer,
|
|
'net_sales_from_offers' => $netSalesOffers,
|
|
'avg_transaction' => $avgTransaction,
|
|
];
|
|
};
|
|
|
|
// Current 7 days
|
|
$current = $getStats($startDateCurrent, $endDateCurrent);
|
|
|
|
// Previous 7 days
|
|
$previous = $getStats($startDatePrevious, $endDatePrevious);
|
|
|
|
// Function to calculate percentage difference
|
|
$calcPercentage = function($currentValue, $previousValue) {
|
|
if ($previousValue == 0) {
|
|
return $currentValue > 0 ? 100 : 0;
|
|
}
|
|
return (($currentValue - $previousValue) / $previousValue) * 100;
|
|
};
|
|
|
|
$data = [
|
|
'offline_outlets' => $offlineCount,
|
|
'cancelled_orders' => $cancelledOrders,
|
|
'gross_sales' => [
|
|
'current' => $current['gross_sales'],
|
|
'previous' => $previous['gross_sales'],
|
|
'percentage' => $calcPercentage($current['gross_sales'], $previous['gross_sales']),
|
|
],
|
|
'total_customer' => [
|
|
'current' => $current['total_customer'],
|
|
'previous' => $previous['total_customer'],
|
|
'percentage' => $calcPercentage($current['total_customer'], $previous['total_customer']),
|
|
],
|
|
'net_sales_from_offers' => [
|
|
'current' => $current['net_sales_from_offers'],
|
|
'previous' => $previous['net_sales_from_offers'],
|
|
'percentage' => $calcPercentage($current['net_sales_from_offers'], $previous['net_sales_from_offers']),
|
|
],
|
|
'avg_transaction' => [
|
|
'current' => $current['avg_transaction'],
|
|
'previous' => $previous['avg_transaction'],
|
|
'percentage' => $calcPercentage($current['avg_transaction'], $previous['avg_transaction']),
|
|
],
|
|
];
|
|
|
|
return $this->respond(['status' => 200, 'data' => $data]);
|
|
}
|
|
|
|
private function isOutletOnline($outlet)
|
|
{
|
|
// Get current day and time
|
|
$currentDay = date('l'); // e.g., "Monday"
|
|
$currentTime = date('H:i:s'); // Current time in 24-hour format
|
|
|
|
// Check if outlet operates on current day
|
|
if (!isset($outlet['operating_schedule'][$currentDay]) ||
|
|
!$outlet['operating_schedule'][$currentDay]['is_operated']) {
|
|
return false;
|
|
}
|
|
|
|
$operatingHours = $outlet['operating_schedule'][$currentDay]['operating_hours'];
|
|
|
|
// Check if current time falls within any operating hour slot
|
|
foreach ($operatingHours as $timeSlot) {
|
|
$startTime = $timeSlot['start_time'];
|
|
$endTime = $timeSlot['end_time'];
|
|
|
|
// Handle cases where end time is 23:59:00 (which means until midnight)
|
|
if ($endTime === '23:59:00') {
|
|
$endTime = '23:59:59';
|
|
}
|
|
|
|
if ($currentTime >= $startTime && $currentTime <= $endTime) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
}
|