274 lines
10 KiB
PHP
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];
|
|
}
|
|
} |