<?php
namespace App\Controller\Admin;
use App\Entity\Activity;
use App\Repository\ActivityRepository;
use App\Repository\CommentRepository;
use App\Repository\ProduitDeclinationValueRepository;
use App\Repository\ProduitRepository;
use App\Repository\UserRepository;
use App\Repository\DocumentRepository;
use Doctrine\ORM\EntityManagerInterface;
use PDO;
use Psr\Log\LoggerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use App\Service\GlobalVariables;
use App\Entity\User;
use App\Form\UserAddType;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\DBAL\Types\Types;
class DashboardController extends AbstractController {
private $produitRepository;
public function __construct(
ProduitRepository $produitRepository,
ActivityRepository $activityRepository,
CommentRepository $commentRepository,
UserRepository $userRepository,
ProduitDeclinationValueRepository $produitDeclinationValueRepository,
DocumentRepository $documentRepository,
GlobalVariables $globalVariables
) {
$this->produitRepository = $produitRepository;
$this->activityRepository = $activityRepository;
$this->commentRepository = $commentRepository;
$this->userRepository = $userRepository;
$this->produitDeclinationValueRepository = $produitDeclinationValueRepository;
$this->produitRepository = $produitRepository;
$this->documentRepository = $documentRepository;
$this->globalVariables = $globalVariables;
}
/**
* @Route("/index", name="index")
*/
public function index(EntityManagerInterface $em): Response {
$user = $this->getUser();
$now = new \DateTime("now");
// *** nouveaux totaux
$totalVenteAvecFrais = 0.0; // somme TTC
$totalVenteSansFrais = 0.0; // somme TTC - frais livraison
$totalVente = 0.0; // legacy (on le gardera = avec frais)
if ($user && in_array("ROLE_SUPER_ADMIN", $user->getRoles())) {
$todayActivities = $this->activityRepository->findByCreatedAtField($now, 100);
$DcumentsByStatus = $this->documentRepository->findByCreatedAtField($now, []);
foreach ($DcumentsByStatus as $key => $document) {
// *** calcule les deux totaux
$ttc = (float) ($document->getTotalAmountTtc() ?? 0);
$frais = 0.0;
if (method_exists($document, 'getDelivery') && $document->getDelivery()) {
$frais = (float) ($document->getDelivery()->getTotalPrice() ?? 0);
}
$totalVenteAvecFrais += $ttc;
$totalVenteSansFrais += ($ttc - $frais);
}
// *** compat : l’ancienne variable = total avec frais
$totalVente = $totalVenteAvecFrais;
$lastDayActivities = $this->activityRepository->findByCreatedAtField(new \DateTime("-1 day"), 100);
// Par défaut : toute la semaine
$startLog = $_GET['log_start'] ?? (new \DateTime())->modify('monday this week')->format('Y-m-d');
$endLog = $_GET['log_end'] ?? (new \DateTime())->modify('sunday this week')->format('Y-m-d');
try {
$logEventsActivities = $this->activityRepository->LoginEventRange(
new \DateTime($startLog),
new \DateTime($endLog)
);
} catch (\Exception $e) {
$logEventsActivities = [];
}
$lastDaylogEventsActivities = $this->activityRepository->LoginEvent(new \DateTime("-1 day"), 100);
} else {
$todayActivities = $user->getActivities()->filter(function (Activity $act) use ($now) {
return $act->getCreatedAt() == $now;
});
$lastDayActivities = $user->getActivities()->filter(function (Activity $act) {
return $act->getCreatedAt() == new \DateTime("-1 day");
});
}
$comments = $this->commentRepository->findLatestComments(20);
$latestClients = $this->userRepository->findLatestUsers(10, 'client');
$countProduitDec = $this->produitDeclinationValueRepository->countProduitDeclinations(null, null, null, [], null, null, null, true, null, null, null, null, null, null, null, null);
$countProduit = $this->produitRepository->countProduits(null, null, null, true, null);
$countClient = $this->userRepository->countUsers(null, null, 'client');
$nbCommandeJour = $this->documentRepository->countCommandesForToday();
$nbUsersConnectes = $this->activityRepository->countTodayLogins(); // à créer
$startOfWeek = (new \DateTime())->modify('monday this week')->setTime(0, 0, 0);
$endOfWeek = (new \DateTime())->modify('sunday this week')->setTime(23, 59, 59);
$weekActivities = $this->activityRepository->findBetweenDates($startOfWeek, $endOfWeek);
$customActivities = [];
$startStr = $_GET['start'] ?? null;
$endStr = $_GET['end'] ?? null;
if ($startStr && $endStr) {
try {
$startDate = new \DateTime($startStr);
$endDate = new \DateTime($endStr);
$customActivities = $this->activityRepository->findBetweenDates($startDate, $endDate);
} catch (\Exception $e) {
// Gérer une erreur de date invalide si besoin
}
}
$activeTab = 'today'; // onglet par défaut
if ($startStr && $endStr) {
$activeTab = 'custom'; // si période personnalisée
}
$selectedUserId = $_GET['log_user'] ?? 'all';
if ($selectedUserId !== 'all') {
$selectedUserId = (int) $selectedUserId;
}
$logEventsActivities = [];
$startLog = $_GET['log_start'] ?? (new \DateTime())->modify('monday this week')->format('Y-m-d');
$endLog = $_GET['log_end'] ?? (new \DateTime())->modify('sunday this week')->format('Y-m-d');
try {
$startDate = new \DateTime($startLog);
$endDate = new \DateTime($endLog);
if ($selectedUserId === 'all') {
$logEventsActivities = $this->activityRepository->LoginEventRange($startDate, $endDate);
} else {
$logEventsActivities = $this->activityRepository->LoginEventRangeByUser($startDate, $endDate, $selectedUserId);
}
} catch (\Exception $e) {
$logEventsActivities = [];
}
return $this->render('@admin/dashboard/dashboard.html.twig', [
'todayActivities' => $todayActivities,
'weekActivities' => $weekActivities,
'customActivities' => $customActivities,
'activeTab' => $activeTab,
'lastDayActivities' => $lastDayActivities,
'logEventsActivities' => $logEventsActivities ?? null,
'log_start' => $startLog,
'log_end' => $endLog,
'lastDaylogEventsActivities' => $lastDaylogEventsActivities ?? null,
// *** sorties totaux
'totalVente' => $totalVente, // legacy (avec frais)
'totalVenteAvecFrais' => $totalVenteAvecFrais, // nouveau
'totalVenteSansFrais' => $totalVenteSansFrais, // nouveau
'comments' => $comments,
'latestClients' => $latestClients,
'countProduitDec' => $countProduitDec,
'countProduit' => $countProduit,
'countClient' => $countClient,
'nbCommandeJour' => $nbCommandeJour,
'nbUsersConnectes' => $nbUsersConnectes,
'log_user' => $selectedUserId,
'users' => $this->userRepository->findLightUsers(),
]);
}
/**
* @Route("/admin/dashboard/activities", name="dashboard_activities_timeline", methods={"GET"})
*/
public function activitiesTimeline(Request $request, EntityManagerInterface $em): Response
{
// Accès (même logique que ton écran) : SUPER_ADMIN ou droit STATISTIQUE si dispo.
$user = $this->getUser();
$can = $user && in_array('ROLE_SUPER_ADMIN', (array)$user->getRoles(), true);
if (!$can && $user && method_exists($user, 'getArrayRight')) {
$can = in_array('STATISTIQUE', (array)$user->getArrayRight(), true);
}
if (!$can) {
return new Response('Forbidden', 403);
}
$tz = new \DateTimeZone('Africa/Tunis');
$now = new \DateTimeImmutable('now', $tz);
$period = (string) $request->query->get('period', 'today');
// défaut : aujourd’hui
$start = $now->setTime(0, 0, 0);
$end = $now->setTime(23, 59, 59);
switch ($period) {
case '3days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P2D'))->setTime(0,0,0);
break;
case '7days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P6D'))->setTime(0,0,0);
break;
case '30days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P29D'))->setTime(0,0,0);
break;
case 'week':
$start = (new \DateTimeImmutable('monday this week', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_week':
$start = (new \DateTimeImmutable('monday last week', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('sunday last week', $tz))->setTime(23,59,59);
break;
case 'month':
$start = (new \DateTimeImmutable('first day of this month', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_month':
$start = (new \DateTimeImmutable('first day of last month', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('last day of last month', $tz))->setTime(23,59,59);
break;
case 'year':
$start = (new \DateTimeImmutable('first day of january', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_year':
$start = (new \DateTimeImmutable('first day of january last year', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('last day of december last year', $tz))->setTime(23,59,59);
break;
case 'custom': {
$s = $request->query->get('start');
$e = $request->query->get('end');
if ($s && $e) {
try {
$start = (new \DateTimeImmutable($s, $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable($e, $tz))->setTime(23,59,59);
if ($end < $start) { [$start, $end] = [$end, $start]; }
} catch (\Throwable $ex) { /* on garde today */ }
}
break;
}
// today => défaut
}
// Requête explicite, bornes inclusives, SANS limite cachée
$qb = $em->createQueryBuilder()
->select('a','u','p','d')
->from(Activity::class, 'a')
->leftJoin('a.currentUser', 'u')
->leftJoin('a.produit', 'p')
->leftJoin('a.document', 'd')
->andWhere('a.createdAt >= :start')
->andWhere('a.createdAt <= :end')
->setParameter('start', \DateTime::createFromImmutable($start))
->setParameter('end', \DateTime::createFromImmutable($end))
->orderBy('a.createdAt', 'DESC');
$qb->setMaxResults(null); // safety: pas de cap
$activities = $qb->getQuery()->getResult();
$html = $this->renderView('@admin/dashboard/_activities_timeline.html.twig', [
'activities' => $activities,
]);
return new Response($html, 200, ['Content-Type' => 'text/html; charset=UTF-8']);
}
/**
* @Route("/admin/dashboard/login-history", name="dashboard_login_history", methods={"GET"})
*/
public function loginHistory(Request $request): Response
{
// Accès : SUPER_ADMIN ou droit 'STATISTIQUE' dans arrayRight
$user = $this->getUser();
$can = $user && in_array('ROLE_SUPER_ADMIN', (array)$user->getRoles(), true);
if (!$can && $user && method_exists($user, 'getArrayRight')) {
$can = in_array('STATISTIQUE', (array)$user->getArrayRight(), true);
}
if (!$can) {
return new Response('Forbidden', 403);
}
$tz = new \DateTimeZone('Africa/Tunis');
$now = new \DateTimeImmutable('now', $tz);
$period = (string) $request->query->get('period', 'today');
$logUser = $request->query->get('log_user', 'all');
// Par défaut : aujourd’hui (00:00 → 23:59:59)
$start = $now->setTime(0, 0, 0);
$end = $now->setTime(23, 59, 59);
switch ($period) {
case '3days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P2D'))->setTime(0,0,0);
break;
case '7days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P6D'))->setTime(0,0,0);
break;
case '30days':
$end = $now->setTime(23,59,59);
$start = $end->sub(new \DateInterval('P29D'))->setTime(0,0,0);
break;
case 'week':
$start = (new \DateTimeImmutable('monday this week', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_week':
$start = (new \DateTimeImmutable('monday last week', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('sunday last week', $tz))->setTime(23,59,59);
break;
case 'month':
$start = (new \DateTimeImmutable('first day of this month', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_month':
$start = (new \DateTimeImmutable('first day of last month', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('last day of last month', $tz))->setTime(23,59,59);
break;
case 'year':
$start = (new \DateTimeImmutable('first day of january', $tz))->setTime(0,0,0);
$end = $now->setTime(23,59,59);
break;
case 'last_year':
$start = (new \DateTimeImmutable('first day of january last year', $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable('last day of december last year', $tz))->setTime(23,59,59);
break;
case 'custom':
$s = $request->query->get('start');
$e = $request->query->get('end');
if ($s && $e) {
try {
$start = (new \DateTimeImmutable($s, $tz))->setTime(0,0,0);
$end = (new \DateTimeImmutable($e, $tz))->setTime(23,59,59);
if ($end < $start) { [$start, $end] = [$end, $start]; }
} catch (\Throwable $ex) { /* on conserve today */ }
}
break;
// today => défaut
}
// Utilise tes méthodes existantes du repository
if ($logUser === 'all') {
$events = $this->activityRepository->LoginEventRange(
\DateTime::createFromImmutable($start),
\DateTime::createFromImmutable($end)
);
} else {
$events = $this->activityRepository->LoginEventRangeByUser(
\DateTime::createFromImmutable($start),
\DateTime::createFromImmutable($end),
(int) $logUser
);
}
$html = $this->renderView('@admin/dashboard/_login_events_list.html.twig', [
'events' => $events
]);
return new Response($html);
}
/**
* @Route("/page", name="page")
*/
public function page(): Response {
$produits = $this->produitRepository->findWithImage();
return $this->render('@admin/front/page.html.twig', [
'produits' => $produits
]);
}
public static function ddQuery($sql,EntityManagerInterface $em)
{
//$sql = " select @@sql_mode";
$stmt = $em->getConnection()->prepare($sql);
$result = $stmt->executeQuery()->fetchAllAssociative();
dd($result);
}
/**
* @Route("/count-document/{type}/{status}", name="count-document", methods={"GET","POST"}, options={"expose"=true})
*/
public function countDocument($type="commande",$status="en-attente"): Response {
return new JsonResponse(array(
'result' => 1,
'message' => "{type:'$type',status:'$status'}",
'count' => $this->globalVariables->getCountDocumentByType($type,$status)['count']));
}
/**
* @Route("/time-server", name="timeServer", methods={"GET","POST"}, options={"expose"=true})
*/
public function getTimeServer(): Response {
return new JsonResponse(array(
'result' => 1,
'message' => 'ok',
'data' => (new \DateTime('now'))->format("Y-m-d\\TH:i:s")));
}
/**
* @Route("/copy-db", name="copydatabase")
*/
public function copyDB( LoggerInterface $logger): Response{
$sourceDbName = 'sunshiladmin';
$destinationDbName = 'sunshiladmindemo';
$connectionSource = new PDO('mysql:host=sunshiladmin.mysql.db;dbname=sunshiladmin', 'sunshiladmin', 'SunshineElegance192510185');
$connectionDestination = new PDO('mysql:host=sunshiladmindemo.mysql.db;dbname=sunshiladmindemo' , 'sunshiladmindemo', 'adminDemo2022');
$tables = $connectionSource->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
$connectionDestination->exec("USE {$destinationDbName}");
foreach ($tables as $tableName) {
$createCommand = $connectionSource->query("SHOW CREATE TABLE `{$sourceDbName}`.`{$tableName}`")->fetchColumn(1);
$carefulCreateCommand = str_replace("CREATE TABLE", "CREATE TABLE IF NOT EXISTS", $createCommand);
$connectionDestination->exec($carefulCreateCommand);
$logger->info("Table `{$tableName}` created" . PHP_EOL);
$connectionDestination->exec("INSERT INTO `{$destinationDbName}`.`{$tableName}` SELECT * FROM `{$sourceDbName}`.`{$tableName}`");
$logger->info("Data for table `{$tableName}` copied" . PHP_EOL);
}
return new Response("<html><head></head><body>done</body></html>");
}
}