Files
HRM-System/app/Http/Controllers/ReferralController.php
2026-04-13 08:16:56 +08:00

365 lines
14 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\Currency;
use App\Models\PayoutRequest;
use App\Models\Referral;
use App\Models\ReferralSetting;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class ReferralController extends Controller
{
public function index()
{
$user = Auth::user();
$settings = ReferralSetting::current();
if ($user->isSuperAdmin()) {
return $this->superAdminView($settings);
} else {
return $this->companyView($user, $settings);
}
}
private function superAdminView($settings)
{
$totalReferralUsers = User::whereNotNull('used_referral_code')
->where('used_referral_code', '!=', 0)
->count();
$pendingPayouts = PayoutRequest::where('status', 'pending')->count();
$totalCommissionPaid = PayoutRequest::where('status', 'approved')->sum('amount');
if (isDemo()) {
// For demo mode, get total counts without month filtering
$monthlyReferrals = User::whereNotNull('used_referral_code')
->where('used_referral_code', '!=', 0)
->count();
$monthlyPayouts = PayoutRequest::where('status', 'approved')
->sum('amount') ?: 0;
} else {
// For normal mode, get monthly data and sum it
$monthlyReferralsData = User::whereNotNull('used_referral_code')
->selectRaw('MONTH(created_at) as month, COUNT(*) as count')
->whereYear('created_at', date('Y'))
->groupBy('month')
->pluck('count', 'month')
->toArray();
$monthlyReferrals = array_sum($monthlyReferralsData);
$monthlyPayoutsData = PayoutRequest::where('status', 'approved')
->selectRaw('MONTH(created_at) as month, SUM(amount) as total')
->whereYear('created_at', date('Y'))
->groupBy('month')
->pluck('total', 'month')
->toArray();
$monthlyPayouts = array_sum($monthlyPayoutsData);
}
$topCompanies = User::select('users.id', 'users.name', 'users.email', 'users.referral_code')
->selectRaw('COUNT(referrals.id) as referral_count, SUM(referrals.amount) as total_earned')
->leftJoin('referrals', 'users.id', '=', 'referrals.company_id')
->where('users.type', 'company')
->whereNotNull('users.referral_code')
->groupBy('users.id', 'users.name', 'users.email', 'users.referral_code')
->orderByDesc('referral_count')
->limit(10)
->get();
$payoutRequests = PayoutRequest::with('company')
->orderBy('created_at', 'desc')
->paginate(10);
// Get all referred users for superadmin with pagination
$referredUsers = User::whereNotNull('used_referral_code')
->with(['plan', 'referrals', 'planOrders' => function ($query) {
$query->where('status', 'approved')->orderBy('created_at', 'desc')->limit(1);
}])
->where('used_referral_code', '!=', 0)
->orderBy('created_at', 'desc')
->paginate(5)
->withQueryString();
// Always use super admin currency for plan pricing
$superAdmin = User::where('type', 'superadmin')->first();
$superAdminSettings = settings($superAdmin->id);
$currency = $superAdminSettings ? ($superAdminSettings['defaultCurrency'] ?? 'USD') : 'USD';
$currencySymbol = '$';
if (! empty($currency)) {
$currencyData = Currency::where('code', $currency)->first();
$currencySymbol = $currencyData ? $currencyData->symbol : '$';
}
return Inertia::render('referral/index', [
'userType' => 'superadmin',
'settings' => $settings,
'stats' => [
'totalReferralUsers' => $totalReferralUsers,
'pendingPayouts' => $pendingPayouts,
'totalCommissionPaid' => $totalCommissionPaid,
'monthlyReferrals' => $monthlyReferrals,
'monthlyPayouts' => $monthlyPayouts,
'topCompanies' => $topCompanies,
],
'payoutRequests' => $payoutRequests,
'referredUsers' => $referredUsers,
'currency' => $currency,
'currencySymbol' => $currencySymbol,
]);
}
private function companyView($user, $settings)
{
$totalReferrals = Referral::where('company_id', $user->id)->count();
$totalEarned = Referral::where('company_id', $user->id)->sum('amount');
$totalPayoutRequests = PayoutRequest::where('company_id', $user->id)->count();
$pendingAmount = PayoutRequest::where('company_id', $user->id)
->where('status', 'pending')
->sum('amount');
$availableBalance = $totalEarned - PayoutRequest::where('company_id', $user->id)
->whereIn('status', ['pending', 'approved'])
->sum('amount');
$payoutRequests = PayoutRequest::where('company_id', $user->id)
->orderBy('created_at', 'desc')
->paginate(10);
// Get referred users count (users who used this company's referral code)
$referredUsersCount = User::where('used_referral_code', $user->referral_code)->count();
// Get recent referred users
$recentReferredUsers = User::where('used_referral_code', $user->referral_code)
->with(['plan', 'planOrders' => function ($query) {
$query->where('status', 'approved')->orderBy('created_at', 'desc')->limit(1);
}])
->orderBy('created_at', 'desc')
->limit(5)
->get()
->map(function ($referredUser) {
return [
'id' => $referredUser->id,
'name' => $referredUser->name,
'email' => $referredUser->email,
'avatar' => check_file($referredUser->avatar) ? get_file($referredUser->avatar) : get_file('avatars/avatar.png'),
'plan' => $referredUser->plan,
'plan_orders' => $referredUser->planOrders,
];
});
// Get all referred users for the company with pagination
$referredUsers = User::where('used_referral_code', $user->referral_code)
->with(['plan', 'referrals', 'planOrders' => function ($query) {
$query->where('status', 'approved')->orderBy('created_at', 'desc')->limit(1);
}])
->orderBy('created_at', 'desc')
->paginate(5)
->withQueryString();
// Generate referral code if not exists
if (! $user->referral_code) {
$user->referral_code = 'REF'.str_pad($user->id, 6, '0', STR_PAD_LEFT);
$user->save();
}
$referralLink = url('/register?ref='.$user->referral_code);
// Always use super admin currency for plan pricing
$superAdmin = User::where('type', 'superadmin')->first();
$superAdminSettings = settings($superAdmin->id);
$currency = $superAdminSettings ? ($superAdminSettings['defaultCurrency'] ?? 'USD') : 'USD';
$currencySymbol = '$';
if (! empty($currency)) {
$currencyData = Currency::where('code', $currency)->first();
$currencySymbol = $currencyData ? $currencyData->symbol : '$';
}
return Inertia::render('referral/index', [
'userType' => 'company',
'settings' => $settings,
'stats' => [
'totalReferrals' => $totalReferrals,
'totalEarned' => $totalEarned,
'totalPayoutRequests' => $totalPayoutRequests,
'availableBalance' => $availableBalance,
'referredUsersCount' => $referredUsersCount,
],
'payoutRequests' => $payoutRequests,
'referralLink' => $referralLink,
'recentReferredUsers' => $recentReferredUsers,
'referredUsers' => $referredUsers,
'currency' => $currency,
'currencySymbol' => $currencySymbol,
]);
}
public function updateSettings(Request $request)
{
$request->validate([
'commission_percentage' => 'required|numeric|min:0|max:100',
'threshold_amount' => 'required|numeric|min:0',
'guidelines' => 'nullable|string',
'is_enabled' => 'boolean',
]);
$settings = ReferralSetting::current();
$settings->update($request->all());
return back()->with('success', __('Referral settings updated successfully'));
}
public function createPayoutRequest(Request $request)
{
$user = Auth::user();
$settings = ReferralSetting::current();
$request->validate([
'amount' => 'required|numeric|min:1',
]);
$totalEarned = Referral::where('company_id', $user->id)->sum('amount');
$totalRequested = PayoutRequest::where('company_id', $user->id)
->whereIn('status', ['pending', 'approved'])
->sum('amount');
$availableBalance = $totalEarned - $totalRequested;
if ($request->amount > $availableBalance) {
return back()->withErrors(['amount' => __('Insufficient balance')]);
}
if ($request->amount < $settings->threshold_amount) {
return back()->withErrors(['amount' => __('Amount must be at least $ :amount', ['amount' => $settings->threshold_amount])]);
}
PayoutRequest::create([
'company_id' => $user->id,
'amount' => $request->amount,
'status' => 'pending',
]);
return back()->with('success', __('Payout request submitted successfully'));
}
public function approvePayoutRequest(PayoutRequest $payoutRequest)
{
$payoutRequest->update(['status' => 'approved']);
return back()->with('success', __('Payout request approved'));
}
public function rejectPayoutRequest(PayoutRequest $payoutRequest, Request $request)
{
$payoutRequest->update([
'status' => 'rejected',
'notes' => $request->notes,
]);
return back()->with('success', __('Payout request rejected'));
}
public function getReferredUsers(Request $request)
{
$user = Auth::user();
// Always use super admin currency for plan pricing
$superAdmin = User::where('type', 'superadmin')->first();
$superAdminSettings = settings($superAdmin->id);
$currency = $superAdminSettings ? ($superAdminSettings['defaultCurrency'] ?? 'USD') : 'USD';
$currencySymbol = '$';
if (! empty($currency)) {
$currencyData = Currency::where('code', $currency)->first();
$currencySymbol = $currencyData ? $currencyData->symbol : '$';
}
if ($user->isSuperAdmin()) {
// Super admin can see all referred users
$referredUsers = User::whereNotNull('used_referral_code')
->with(['plan', 'referrals', 'planOrders' => function ($query) {
$query->where('status', 'approved')->orderBy('created_at', 'desc')->limit(1);
}])
->where('used_referral_code', '!=', 0)
->orderBy('created_at', 'desc')
->paginate(15)
->withQueryString();
} else {
// Company can see users who used their referral code
$referredUsers = User::where('used_referral_code', $user->referral_code)
->with(['plan', 'referrals', 'planOrders' => function ($query) {
$query->where('status', 'approved')->orderBy('created_at', 'desc')->limit(1);
}])
->orderBy('created_at', 'desc')
->paginate(15)
->withQueryString();
}
return Inertia::render('referral/referred-users', [
'referredUsers' => $referredUsers,
'userType' => $user->isSuperAdmin() ? 'superadmin' : 'company',
'currency' => $currency,
'currencySymbol' => $currencySymbol,
]);
}
/**
* Create referral record when user purchases a plan
*/
public static function createReferralRecord(User $user, $billingCycle = null)
{
$settings = ReferralSetting::current();
if (! $settings->is_enabled || ! $user->used_referral_code || ! $user->plan) {
return;
}
// Check if referral record already exists
$existingReferral = Referral::where('user_id', $user->id)
->where('plan_id', $user->plan_id)
->first();
if ($existingReferral) {
return; // Already created
}
$referrer = User::where('referral_code', $user->used_referral_code)
->where('type', 'company')
->first();
if (! $referrer) {
return;
}
// Get the actual paid amount from the most recent plan order
$planOrder = \App\Models\PlanOrder::where('user_id', $user->id)
->where('plan_id', $user->plan_id)
->where('status', 'approved')
->orderBy('created_at', 'desc')
->first();
// Use the actual paid amount if available, otherwise use plan price based on billing cycle
if ($planOrder && $planOrder->final_price > 0) {
$planPrice = $planOrder->final_price;
} elseif ($planOrder && $planOrder->billing_cycle === 'yearly' && $user->plan->yearly_price) {
$planPrice = $user->plan->yearly_price;
} else {
$planPrice = $user->plan->price ?? 0;
}
$commissionAmount = ($planPrice * $settings->commission_percentage) / 100;
if ($commissionAmount > 0) {
Referral::create([
'user_id' => $user->id,
'company_id' => $referrer->id,
'commission_percentage' => $settings->commission_percentage,
'amount' => $commissionAmount,
'plan_id' => $user->plan_id,
]);
}
}
}