getCurrentUser(); if (!$user || !$user->hasPermission($permission)) { $this->addFlash('error', 'Você não tem permissão para acessar esta área.'); $this->redirect('admin/dashboard')->send(); exit; } } /** * Display a listing of the affiliates. * * @param Request $request * @return Response */ public function index(Request $request): Response { $this->checkPermission('affiliatesadmin.view'); $affiliates = Affiliate::all(); return $this->renderAdminView('@affiliatesadmin/index.twig', ['affiliates' => $affiliates]); } /** * Show the form for creating a new affiliate. * * @param Request $request * @return Response */ public function create(Request $request): Response { $this->checkPermission('affiliatesadmin.manage'); return $this->renderAdminView('@affiliatesadmin/form.twig'); } /** * Store a newly created affiliate in storage. * * @param Request $request * @return Response */ public function store(Request $request): Response { $this->checkPermission('affiliatesadmin.manage'); $data = $request->request->all(); if (empty($data['affiliates_name']) || empty($data['affiliates_email'])) { $this->addFlash('error', __('affiliatesadmin.validation_name_email_required')); return $this->redirect('/admin/affiliatesadmin/create'); } if (!filter_var($data['affiliates_email'], FILTER_VALIDATE_EMAIL)) { $this->addFlash('error', __('affiliatesadmin.validation_invalid_email')); return $this->redirect('/admin/affiliatesadmin/create'); } if (Affiliate::where('affiliates_email', $data['affiliates_email'])->exists()) { $this->addFlash('error', __('affiliatesadmin.validation_email_exists')); return $this->redirect('/admin/affiliatesadmin/create'); } // Check if user already exists in the system $existingUser = User::where('users_email', $data['affiliates_email'])->first(); if (!$existingUser && empty($data['password'])) { $this->addFlash('error', 'A senha é obrigatória para criar um novo usuário no sistema.'); return $this->redirect('/admin/affiliatesadmin/create'); } // Create the Affiliate record Affiliate::create($data); if ($existingUser) { // Only change role if user is a standard 'user' // Prevent downgrading admins or super_admins if (in_array($existingUser->users_role, ['user', ''])) { $existingUser->users_role = 'member'; $existingUser->save(); $this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' O usuário existente foi promovido para "member".'); } else { $this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' O usuário existente manteve seu nível de acesso privilegiado: ' . $existingUser->users_role); } } else { // Create a new System User $user = new User(); $user->users_name = $data['affiliates_name']; $user->users_email = $data['affiliates_email']; $user->users_password = password_hash($data['password'], PASSWORD_DEFAULT); $user->users_role = 'member'; $user->users_status = 'active'; $user->save(); $this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' Um novo usuário com nível "member" foi criado.'); } return $this->redirect('/admin/affiliatesadmin'); } /** * Display the specified affiliate. * * @param Request $request * @param int $id * @return Response */ public function show(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.view'); $affiliate = Affiliate::findOrFail($id); return $this->renderAdminView('@affiliatesadmin/show.twig', ['affiliate' => $affiliate]); } /** * Show the form for editing the specified affiliate. * * @param Request $request * @param int $id * @return Response */ public function edit(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.manage'); $affiliate = Affiliate::findOrFail($id); return $this->renderAdminView('@affiliatesadmin/form.twig', ['affiliate' => $affiliate]); } /** * Update the specified affiliate in storage. * * @param Request $request * @param int $id * @return Response */ public function update(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.manage'); $affiliate = Affiliate::findOrFail($id); $data = $request->request->all(); if (empty($data['affiliates_name']) || empty($data['affiliates_email'])) { $this->addFlash('error', __('affiliatesadmin.validation_name_email_required')); return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit'); } if (!filter_var($data['affiliates_email'], FILTER_VALIDATE_EMAIL)) { $this->addFlash('error', __('affiliatesadmin.validation_invalid_email')); return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit'); } if (Affiliate::where('affiliates_email', $data['affiliates_email'])->where('affiliates_id', '!=', $id)->exists()) { $this->addFlash('error', __('affiliatesadmin.validation_email_exists')); return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit'); } $affiliate->update($data); $this->addFlash('success', __('affiliatesadmin.affiliate_updated_successfully')); return $this->redirect('/admin/affiliatesadmin'); } /** * Remove the specified affiliate from storage. * * @param Request $request * @param int $id * @return Response */ public function destroy(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.manage'); Affiliate::destroy($id); $this->addFlash('success', __('affiliatesadmin.affiliate_deleted_successfully')); return $this->redirect('/admin/affiliatesadmin'); } /** * Display a listing of commissions. * * @param Request $request * @return Response */ public function commissions(Request $request): Response { $this->checkPermission('affiliatesadmin.view_commissions'); $commissions = AffiliateCommission::all(); return $this->renderAdminView('@affiliatesadmin/commissions.twig', ['commissions' => $commissions]); } /** * Approve a commission. * * @param Request $request * @param int $id * @return Response */ public function approveCommission(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.manage_commissions'); $commission = AffiliateCommission::findOrFail($id); $commission->affiliate_commissions_status = 'approved'; $commission->save(); $this->addFlash('success', __('affiliatesadmin.commission_approved_successfully')); return $this->redirect('/admin/affiliatesadmin/commissions'); } /** * Reject a commission. * * @param Request $request * @param int $id * @return Response */ public function rejectCommission(Request $request, int $id): Response { $this->checkPermission('affiliatesadmin.manage_commissions'); $commission = AffiliateCommission::findOrFail($id); $commission->affiliate_commissions_status = 'rejected'; $commission->save(); $this->addFlash('success', __('affiliatesadmin.commission_rejected_successfully')); return $this->redirect('/admin/affiliatesadmin/commissions'); } /** * Display a listing of banners. * * @param Request $request * @return Response */ public function banners(Request $request): Response { $this->checkPermission('affiliatesadmin.view_banners'); $banners = AffiliateBanner::all(); return $this->renderAdminView('@affiliatesadmin/banners.twig', ['banners' => $banners]); } /** * Show the form for creating a new banner. * * @param Request $request * @return Response */ public function createBanner(Request $request): Response { $this->checkPermission('affiliatesadmin.manage_banners'); return $this->renderAdminView('@affiliatesadmin/banner-form.twig'); } /** * Store a newly created banner in storage. * * @param Request $request * @return Response */ public function storeBanner(Request $request): Response { $this->checkPermission('affiliatesadmin.manage_banners'); $data = $request->request->all(); if (empty($data['affiliate_banners_name']) || empty($data['affiliate_banners_target_url'])) { $this->addFlash('error', __('affiliatesadmin.validation_banner_fields_required')); return $this->redirect('/admin/affiliatesadmin/banners/create'); } if ($request->files->has('banner_file')) { $file = $request->files->get('banner_file'); if ($file && $file->isValid()) { $data['affiliate_banners_image_url'] = $this->handleBannerUpload($file); } } if (empty($data['affiliate_banners_image_url'])) { $this->addFlash('error', 'O arquivo de imagem do banner é obrigatório.'); return $this->redirect('/admin/affiliatesadmin/banners/create'); } AffiliateBanner::create($data); $this->addFlash('success', __('affiliatesadmin.banner_created_successfully')); return $this->redirect('/admin/affiliatesadmin/banners'); } /** * Show the form for editing the specified banner. * * @param Request $request * @param int $id * @return Response */ public function editBanner(Request $request, int $id): Response { $banner = AffiliateBanner::findOrFail($id); return $this->renderAdminView('@affiliatesadmin/banner-form.twig', ['banner' => $banner]); } /** * Update the specified banner in storage. * * @param Request $request * @param int $id * @return Response */ public function updateBanner(Request $request, int $id): Response { $banner = AffiliateBanner::findOrFail($id); $data = $request->request->all(); if (empty($data['affiliate_banners_name']) || empty($data['affiliate_banners_target_url'])) { $this->addFlash('error', __('affiliatesadmin.validation_banner_fields_required')); return $this->redirect('/admin/affiliatesadmin/banners/' . $id . '/edit'); } if ($request->files->has('banner_file')) { $file = $request->files->get('banner_file'); if ($file && $file->isValid()) { // Delete old file if exists if ($banner->affiliate_banners_image_url) { $oldPath = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin/' . $banner->affiliate_banners_image_url; if (file_exists($oldPath) && is_file($oldPath)) { unlink($oldPath); } } $data['affiliate_banners_image_url'] = $this->handleBannerUpload($file); } } $banner->update($data); $this->addFlash('success', __('affiliatesadmin.banner_updated_successfully')); return $this->redirect('/admin/affiliatesadmin/banners'); } /** * Handle banner image upload. * * @param \Symfony\Component\HttpFoundation\File\UploadedFile $file * @return string|null */ private function handleBannerUpload($file): ?string { $uploadDir = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin'; if (!is_dir($uploadDir)) { if (!mkdir($uploadDir, 0777, true)) { return null; } } $filename = uniqid('banner_') . '.' . $file->guessExtension(); $file->move($uploadDir, $filename); // Store ONLY the filename in the database // The view will prepend /storage/uploads/affiliatesadmin/ return $filename; } /** * Remove the specified banner from storage. * * @param Request $request * @param int $id * @return Response */ public function destroyBanner(Request $request, int $id): Response { $banner = AffiliateBanner::findOrFail($id); if ($banner->affiliate_banners_image_url) { $path = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin/' . $banner->affiliate_banners_image_url; if (file_exists($path) && is_file($path)) { unlink($path); } } AffiliateBanner::destroy($id); $this->addFlash('success', __('affiliatesadmin.banner_deleted_successfully')); return $this->redirect('/admin/affiliatesadmin/banners'); } /** * Display affiliate statistics. * * @param Request $request * @return Response */ public function statistics(Request $request): Response { $this->checkPermission('affiliatesadmin.view_statistics'); $stats = [ 'total_affiliates' => Affiliate::count(), 'total_commissions_approved' => AffiliateCommission::where('affiliate_commissions_status', 'approved')->sum('affiliate_commissions_amount'), 'total_clicks' => AffiliateClick::count(), 'conversion_rate' => 0, ]; if ($stats['total_clicks'] > 0) { $approvedCount = AffiliateCommission::where('affiliate_commissions_status', 'approved')->count(); $stats['conversion_rate'] = round(($approvedCount / $stats['total_clicks']) * 100, 2); } return $this->renderAdminView('@affiliatesadmin/statistics.twig', [ 'stats' => $stats ]); } }