Files
newznab-tmux/app/Http/Controllers/Admin/AdminPromotionController.php
2026-03-04 14:38:25 +01:00

230 lines
7.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\BasePageController;
use App\Http\Requests\Admin\AdminPromotionRequest;
use App\Models\RolePromotion;
use App\Models\RolePromotionStat;
use App\Support\DateRangeFilter;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\View\View;
class AdminPromotionController extends BasePageController
{
/**
* Display a listing of promotions.
*/
public function index(): View
{
$promotions = RolePromotion::orderBy('is_active', 'desc')
->orderBy('created_at', 'desc')
->get();
return view('admin.promotions.index', [
'promotions' => $promotions,
]);
}
/**
* Show the form for creating a new promotion.
*/
public function create(): View
{
$customRoles = RolePromotion::getCustomRoles();
return view('admin.promotions.create', [
'customRoles' => $customRoles,
]);
}
/**
* Store a newly created promotion in storage.
*/
public function store(AdminPromotionRequest $request): RedirectResponse
{
RolePromotion::create([
'name' => $request->input('name'),
'description' => $request->input('description'),
'applicable_roles' => $request->input('applicable_roles', []),
'additional_days' => $request->input('additional_days'),
'start_date' => $request->input('start_date'),
'end_date' => $request->input('end_date'),
'is_active' => $request->has('is_active'),
]);
return redirect()->route('admin.promotions.index')
->with('success', 'Promotion created successfully.');
}
/**
* Show the form for editing the specified promotion.
*/
public function edit(int $id): View
{
$promotion = RolePromotion::findOrFail($id);
$customRoles = RolePromotion::getCustomRoles();
return view('admin.promotions.edit', [
'promotion' => $promotion,
'customRoles' => $customRoles,
]);
}
/**
* Update the specified promotion in storage.
*/
public function update(AdminPromotionRequest $request, int $id): RedirectResponse
{
$promotion = RolePromotion::findOrFail($id);
$promotion->update([
'name' => $request->input('name'),
'description' => $request->input('description'),
'applicable_roles' => $request->input('applicable_roles', []),
'additional_days' => $request->input('additional_days'),
'start_date' => $request->input('start_date'),
'end_date' => $request->input('end_date'),
'is_active' => $request->has('is_active'),
]);
return redirect()->route('admin.promotions.index')
->with('success', 'Promotion updated successfully.');
}
/**
* Remove the specified promotion from storage.
*/
public function destroy(int $id): RedirectResponse
{
$promotion = RolePromotion::findOrFail($id);
$promotion->delete();
return redirect()->route('admin.promotions.index')
->with('success', 'Promotion deleted successfully.');
}
/**
* Toggle the active status of the specified promotion.
*/
public function toggle(int $id): RedirectResponse
{
$promotion = RolePromotion::findOrFail($id);
$promotion->update(['is_active' => ! $promotion->is_active]);
$status = $promotion->is_active ? 'activated' : 'deactivated';
return redirect()->route('admin.promotions.index')
->with('success', "Promotion {$status} successfully.");
}
/**
* Display overall promotion statistics.
*/
public function statistics(Request $request): View
{
[$startDate, $endDate] = DateRangeFilter::fromRequest($request);
// Get all promotions with their statistics
$promotions = RolePromotion::withCount(['statistics' => function ($query) use ($startDate, $endDate) {
if ($startDate) {
$query->whereBetween('applied_at', [$startDate, $endDate]);
}
}])
->with(['statistics' => function ($query) use ($startDate, $endDate) {
if ($startDate) {
$query->whereBetween('applied_at', [$startDate, $endDate]);
}
$query->with(['user', 'role']);
}])
->get();
// Calculate overall statistics
$overallStats = [
'total_promotions' => $promotions->count(),
'active_promotions' => $promotions->where('is_active', true)->count(),
'total_applications' => $promotions->sum('statistics_count'),
'unique_users' => RolePromotionStat::query()
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->distinct('user_id')
->count('user_id'),
'total_days_added' => RolePromotionStat::query()
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->sum('days_added'),
];
// Get top promotions by usage
$topPromotions = $promotions->sortByDesc('statistics_count')->take(5);
// Get recent activity
$recentActivity = RolePromotionStat::with(['user', 'promotion', 'role'])
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->latest('applied_at')
->limit(10)
->get();
// Get statistics by role
$statsByRole = RolePromotionStat::query()
->selectRaw('role_id, COUNT(*) as total_upgrades, SUM(days_added) as total_days, COUNT(DISTINCT user_id) as unique_users')
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->groupBy('role_id')
->with('role')
->get();
return view('admin.promotions.statistics', [
'promotions' => $promotions,
'overallStats' => $overallStats,
'topPromotions' => $topPromotions,
'recentActivity' => $recentActivity,
'statsByRole' => $statsByRole,
'startDate' => $startDate,
'endDate' => $endDate,
'selectedPeriod' => $request->input('period', '30days'),
]);
}
/**
* Display statistics for a specific promotion.
*/
public function showStatistics(int $id, Request $request): View
{
$promotion = RolePromotion::findOrFail($id);
[$startDate, $endDate] = DateRangeFilter::fromRequest($request);
// Get promotion statistics
$stats = $promotion->getStatisticsForPeriod($startDate ?? Carbon::createFromTimestamp(0), $endDate);
$statsByRole = $promotion->getStatisticsByRole();
// Get applications with users
$applications = RolePromotionStat::forPromotion($id)
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->with(['user', 'role'])
->latest('applied_at')
->paginate(20);
// Get daily statistics for chart
$dailyStats = RolePromotionStat::forPromotion($id)
->when($startDate, fn ($q) => $q->whereBetween('applied_at', [$startDate, $endDate]))
->selectRaw('DATE(applied_at) as date, COUNT(*) as count, SUM(days_added) as days')
->groupBy('date')
->orderBy('date')
->get();
return view('admin.promotions.show-statistics', [
'promotion' => $promotion,
'stats' => $stats,
'statsByRole' => $statsByRole,
'applications' => $applications,
'dailyStats' => $dailyStats,
'startDate' => $startDate,
'endDate' => $endDate,
'selectedPeriod' => $request->input('period', '30days'),
]);
}
}