AMS_Backend/app/Controllers/Backend/CustomerDashboardController.php
2025-11-06 13:41:06 +08:00

274 lines
10 KiB
PHP

<?php
namespace App\Controllers\Backend;
use CodeIgniter\RESTful\ResourceController;
use App\Models\Orders;
use App\Models\TopupModel;
use App\Models\CustomerWallet;
use App\Models\CustomerVoucherList;
use App\Models\CustomerPoint;
use App\Models\LogCustomerCheckin; // Add LogCustomerCheckin model
class CustomerDashboardController extends ResourceController
{
private $orders;
private $topups;
private $wallets;
private $vouchers;
private $points;
private $checkins; // Add checkins model
public function __construct()
{
$this->orders = new Orders();
$this->topups = new TopupModel();
$this->wallets = new CustomerWallet();
$this->vouchers = new CustomerVoucherList();
$this->points = new CustomerPoint();
$this->checkins = new LogCustomerCheckin(); // Initialize checkins model
}
public function show($customerId = null)
{
if (!$customerId) {
return $this->fail('Customer ID is required', 400);
}
$orderSummary = $this->orders
->select('customer_id, COUNT(id) as total_orders, SUM(grand_total) as total_grand')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$topupSummary = $this->topups
->select('customer_id, COUNT(id) as total_topups, SUM(amount) as total_topup_amount')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$pointsSummary = $this->points
->select('customer_id,
COUNT(id) as total_point_transactions,
SUM(`in`) as total_point_in,
SUM(`out`) as total_point_out,
MAX(balance) as current_points')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$walletSummary = $this->wallets
->select('customer_id, SUM(`in`) as total_in, SUM(`out`) as total_out, MAX(balance) as current_balance')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$voucherSummary = $this->vouchers
->select('customer_id,
COUNT(id) as total_vouchers,
SUM(CASE WHEN voucher_status = "active" THEN 1 ELSE 0 END) as active_vouchers,
SUM(CASE WHEN voucher_status = "used" THEN 1 ELSE 0 END) as used_vouchers,
SUM(CASE WHEN voucher_status = "expired" THEN 1 ELSE 0 END) as expired_vouchers')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$activeVouchers = $this->vouchers
->where('customer_id', $customerId)
->where('voucher_status', 'active')
->where('voucher_expiry_date >=', date('Y-m-d H:i:s'))
->orderBy('voucher_expiry_date', 'ASC')
->findAll();
// Get check-in data
$checkinData = $this->checkins
->select('customer_id,
COUNT(id) as total_checkins,
MAX(streak_count) as highest_streak,
MAX(checkin_date) as last_checkin_date')
->where('customer_id', $customerId)
->groupBy('customer_id')
->first();
$recentCheckins = $this->checkins
->where('customer_id', $customerId)
->orderBy('checkin_date', 'DESC')
->limit(7) // Get last 7 check-ins
->findAll();
$orderLifecycle = $this->orders
->select('MIN(created_at) as first_order_date, MAX(created_at) as last_order_date')
->where('customer_id', $customerId)
->where('status !=', 'cancelled')
->first();
$topupLifecycle = $this->topups
->select('MIN(created_at) as first_topup_date, MAX(created_at) as last_topup_date')
->where('customer_id', $customerId)
->where('status', 'success')
->first();
$pointsLifecycle = $this->points
->select('MIN(created_at) as first_point_date, MAX(created_at) as last_point_date')
->where('customer_id', $customerId)
->first();
// Get check-in lifecycle
$checkinLifecycle = $this->checkins
->select('MIN(checkin_date) as first_checkin_date, MAX(checkin_date) as last_checkin_date')
->where('customer_id', $customerId)
->first();
$customerStatus = $this->calculateCustomerStatus($orderLifecycle, $topupLifecycle, $pointsLifecycle, $checkinLifecycle);
$lifecycleData = [
'first_activity' => $this->getEarliestDate([
$orderLifecycle['first_order_date'] ?? null,
$topupLifecycle['first_topup_date'] ?? null,
$pointsLifecycle['first_point_date'] ?? null,
$checkinLifecycle['first_checkin_date'] ?? null
]),
'last_activity' => $this->getLatestDate([
$orderLifecycle['last_order_date'] ?? null,
$topupLifecycle['last_topup_date'] ?? null,
$pointsLifecycle['last_point_date'] ?? null,
$checkinLifecycle['last_checkin_date'] ?? null
]),
'first_order' => $orderLifecycle['first_order_date'] ?? null,
'last_order' => $orderLifecycle['last_order_date'] ?? null,
'first_topup' => $topupLifecycle['first_topup_date'] ?? null,
'last_topup' => $topupLifecycle['last_topup_date'] ?? null,
'first_point' => $pointsLifecycle['first_point_date'] ?? null,
'last_point' => $pointsLifecycle['last_point_date'] ?? null,
'first_checkin' => $checkinLifecycle['first_checkin_date'] ?? null,
'last_checkin' => $checkinLifecycle['last_checkin_date'] ?? null,
'customer_status' => $customerStatus,
'days_since_last_activity' => $this->calculateDaysSinceLastActivity(
$orderLifecycle['last_order_date'] ?? null,
$topupLifecycle['last_topup_date'] ?? null,
$pointsLifecycle['last_point_date'] ?? null,
$checkinLifecycle['last_checkin_date'] ?? null
)
];
return $this->respond([
'status' => 200,
'message' => 'Customer dashboard data retrieved successfully',
'data' => [
'orders' => $orderSummary ?? [
'customer_id' => $customerId,
'total_orders' => 0,
'total_grand' => 0
],
'topups' => $topupSummary ?? [
'customer_id' => $customerId,
'total_topups' => 0,
'total_topup_amount' => 0
],
'points' => $pointsSummary ?? [
'customer_id' => $customerId,
'total_point_transactions' => 0,
'total_point_in' => 0,
'total_point_out' => 0,
'current_points' => 0
],
'wallet' => $walletSummary ?? [
'customer_id' => $customerId,
'total_in' => 0,
'total_out' => 0,
'current_balance' => 0
],
'vouchers' => [
'summary' => $voucherSummary ?? [
'customer_id' => $customerId,
'total_vouchers' => 0,
'active_vouchers' => 0,
'used_vouchers' => 0,
'expired_vouchers' => 0
],
'active_vouchers_list' => $activeVouchers
],
'checkins' => [ // Added checkins section
'summary' => $checkinData ?? [
'customer_id' => $customerId,
'total_checkins' => 0,
'highest_streak' => 0,
'last_checkin_date' => null
],
'recent_checkins' => $recentCheckins
],
'lifecycle' => $lifecycleData
]
]);
}
private function calculateCustomerStatus($orderLifecycle, $topupLifecycle, $pointsLifecycle, $checkinLifecycle)
{
$lastOrderDate = $orderLifecycle['last_order_date'] ?? null;
$lastTopupDate = $topupLifecycle['last_topup_date'] ?? null;
$lastPointDate = $pointsLifecycle['last_point_date'] ?? null;
$lastCheckinDate = $checkinLifecycle['last_checkin_date'] ?? null;
$lastActivity = $this->getLatestDate([$lastOrderDate, $lastTopupDate, $lastPointDate, $lastCheckinDate]);
if (!$lastActivity) {
return 'new';
}
$daysInactive = $this->calculateDaysSince($lastActivity);
if ($daysInactive <= 30) {
return 'active';
} elseif ($daysInactive <= 90) {
return 'dormant';
} else {
return 'churned';
}
}
private function calculateDaysSinceLastActivity($lastOrderDate, $lastTopupDate, $lastPointDate, $lastCheckinDate)
{
$lastActivity = $this->getLatestDate([$lastOrderDate, $lastTopupDate, $lastPointDate, $lastCheckinDate]);
if (!$lastActivity) {
return null;
}
return $this->calculateDaysSince($lastActivity);
}
private function calculateDaysSince($dateString)
{
if (!$dateString) {
return null;
}
$date = new \DateTime($dateString);
$now = new \DateTime();
$interval = $now->diff($date);
return $interval->days;
}
private function getEarliestDate(array $dates)
{
$validDates = array_filter($dates);
if (empty($validDates)) {
return null;
}
sort($validDates);
return $validDates[0];
}
private function getLatestDate(array $dates)
{
$validDates = array_filter($dates);
if (empty($validDates)) {
return null;
}
rsort($validDates);
return $validDates[0];
}
}