<?php
namespace App\Controller;
use DateTime;
use App\Entity\Depense;
use App\Entity\Produit;
use App\Entity\Recette;
use App\Entity\Boutique;
use App\Entity\Livraison;
use App\Entity\EntreeStock;
use App\Entity\SortieStock;
use App\Repository\VenteRepository;
use App\Repository\FactureRepository;
use App\Repository\ProduitRepository;
use Doctrine\ORM\EntityManagerInterface;
use App\Repository\EntreeStockRepository;
use Symfony\Component\VarDumper\Cloner\Data;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
class DashboardController extends AbstractController
{
private $entityManager;
private $venteRepository;
public function __construct(EntityManagerInterface $entityManager, VenteRepository $venteRepository)
{
$this->entityManager = $entityManager;
$this->venteRepository = $venteRepository;
}
#[Route('/dashboard', name: 'app_dashboard')]
public function index(Request $request, ProduitRepository $menuRepository, FactureRepository $factureRepository): Response
{
// Récupérer l'utilisateur connecté et son rôle
$user = $this->getUser();
$isSuperAdmin = $this->isGranted('ROLE_SUPER_ADMIN');
$isAdmin = $this->isGranted('ROLE_ADMIN');
// Récupérer la période sélectionnée (journalier, hebdomadaire, mensuel, trimestriel, semestriel, annuel)
$period = $request->query->get('period', 'daily');
// Initialiser les variables de date selon la période
$startDate = new \DateTime('today');
$endDate = clone $startDate;
$endDate->modify('+1 day');
$periodLabel = 'Journalier';
// Définir les dates selon la période sélectionnée
switch ($period) {
case 'weekly':
$startDate = new \DateTime('monday this week');
$endDate = clone $startDate;
$endDate->modify('+1 week');
$periodLabel = 'Hebdomadaire';
break;
case 'monthly':
$startDate = new \DateTime('first day of this month');
$endDate = clone $startDate;
$endDate->modify('+1 month');
$periodLabel = 'Mensuel';
break;
case 'quarterly':
$startDate = new \DateTime('first day of this month');
$quarter = ceil($startDate->format('n') / 3);
$startDate->setDate($startDate->format('Y'), ($quarter - 1) * 3 + 1, 1);
$endDate = clone $startDate;
$endDate->modify('+3 months');
$periodLabel = 'Trimestriel';
break;
case 'biannual':
$startDate = new \DateTime('first day of january this year');
if ((int)$startDate->format('n') > 6) {
$startDate->setDate($startDate->format('Y'), 7, 1);
}
$endDate = clone $startDate;
$endDate->modify('+6 months');
$periodLabel = 'Semestriel';
break;
case 'annual':
$startDate = new \DateTime('first day of january this year');
$endDate = clone $startDate;
$endDate->modify('+1 year');
$periodLabel = 'Annuel';
break;
}
// Récupérer toutes les boutiques pour admin/superadmin ou seulement la boutique associée pour magasinier
$boutiqueRepository = $this->entityManager->getRepository(Boutique::class);
if ($isSuperAdmin || $isAdmin) {
// Admin ou SuperAdmin voit toutes les boutiques
$boutiques = $boutiqueRepository->findAll();
} else {
// Magasinier ne voit que sa boutique assignée
$boutiques = [];
if ($user && $user->getBoutique()) {
$boutiques = [$user->getBoutique()];
}
}
// Récupérer les recettes par boutique pour la période sélectionnée
$recetteRepository = $this->entityManager->getRepository(Recette::class);
$recettesByBoutique = [];
$totalRecette = 0;
foreach ($boutiques as $boutique) {
$recettes = $recetteRepository->createQueryBuilder('r')
->where('r.dateRecette >= :start')
->andWhere('r.dateRecette < :end')
->andWhere('r.boutique = :boutique')
->setParameter('start', $startDate->format('Y-m-d H:i:s'))
->setParameter('end', $endDate->format('Y-m-d H:i:s'))
->setParameter('boutique', $boutique)
->getQuery()
->getResult();
$montantTotal = 0;
foreach ($recettes as $recette) {
$montantTotal += $recette->getMontant();
}
$recettesByBoutique[$boutique->getId()] = [
'boutique' => $boutique,
'montant' => $montantTotal
];
$totalRecette += $montantTotal;
}
// Récupérer les autres données existantes
$numberOfMenus = $menuRepository->createQueryBuilder('m')
->select('COUNT(m.id)')
->getQuery()
->getSingleScalarResult();
$topMenus = $this->entityManager->getRepository(Produit::class)->findTopMenus(5);
$bottomProducts = $this->entityManager->getRepository(Produit::class)->findBottomProducts(5);
$today = new DateTime('today');
$recette = $this->entityManager->getRepository(Recette::class)->findOneBy(['dateRecette' => $today]);
$depenses = $this->entityManager->getRepository(Depense::class)->createQueryBuilder('d')
->where('d.dateDepense >= :start')
->andWhere('d.dateDepense < :end')
->setParameter('start', $startDate->format('Y-m-d H:i:s'))
->setParameter('end', $endDate->format('Y-m-d H:i:s'))
->getQuery()
->getResult();
$livraisonsEnAttente = $this->entityManager->getRepository(Livraison::class)->findBy(['statut' => 'en attente']);
$livraisonsEnCours = $this->entityManager->getRepository(Livraison::class)->findBy(['statut' => 'en cours']);
$dailyRevenue = $factureRepository->getRevenueByPeriod($today, new \DateTime('tomorrow'));
$monthlyRevenue = $factureRepository->getRevenueByPeriod(new \DateTime('first day of this month'), new \DateTime('last day of this month'));
$trimesterRevenue = $factureRepository->getRevenueByPeriod(new \DateTime(date('Y-m-d', strtotime('-2 months', strtotime('first day of this month')))), new \DateTime('last day of this month'));
return $this->render('dashboard/index.html.twig', [
'numberOfMenus' => $numberOfMenus,
'topMenus' => $topMenus,
'btP' => $bottomProducts,
'montantRecette' => $recette ? $recette->getMontant() : 0,
'depenses' => $depenses,
'livraisonsEnAttente' => $livraisonsEnAttente,
'livraisonsEnCours' => $livraisonsEnCours,
'dailyRevenue' => $dailyRevenue,
'monthlyRevenue' => $monthlyRevenue,
'trimesterRevenue' => $trimesterRevenue,
'recettesByBoutique' => $recettesByBoutique,
'totalRecette' => $totalRecette,
'period' => $period,
'periodLabel' => $periodLabel,
'isSuperAdmin' => $isSuperAdmin,
'isAdmin' => $isAdmin,
'userBoutique' => $user ? $user->getBoutique() : null,
]);
}
#[Route('/dashboard/boutique/{id}/recettes', name: 'app_dashboard_boutique_recettes')]
public function boutiqueRecettes(Request $request, Boutique $boutique): Response
{
// Vérifier les permissions
$user = $this->getUser();
if (!$this->isGranted('ROLE_ADMIN') && !$this->isGranted('ROLE_SUPER_ADMIN')) {
if (!$user->getBoutique() || $user->getBoutique()->getId() !== $boutique->getId()) {
throw $this->createAccessDeniedException('Vous n\'avez pas accès à cette boutique');
}
}
// Récupérer la période et les dates
$period = $request->query->get('period', 'daily');
$startDate = new \DateTime('today');
$endDate = clone $startDate;
$endDate->modify('+1 day');
// Définir les dates selon la période sélectionnée (même logique que dans index)
switch ($period) {
case 'weekly':
$startDate = new \DateTime('monday this week');
$endDate = clone $startDate;
$endDate->modify('+1 week');
break;
case 'monthly':
$startDate = new \DateTime('first day of this month');
$endDate = clone $startDate;
$endDate->modify('+1 month');
break;
case 'quarterly':
$startDate = new \DateTime('first day of this month');
$quarter = ceil($startDate->format('n') / 3);
$startDate->setDate($startDate->format('Y'), ($quarter - 1) * 3 + 1, 1);
$endDate = clone $startDate;
$endDate->modify('+3 months');
break;
case 'biannual':
$startDate = new \DateTime('first day of january this year');
if ((int)$startDate->format('n') > 6) {
$startDate->setDate($startDate->format('Y'), 7, 1);
}
$endDate = clone $startDate;
$endDate->modify('+6 months');
break;
case 'annual':
$startDate = new \DateTime('first day of january this year');
$endDate = clone $startDate;
$endDate->modify('+1 year');
break;
}
// Récupérer les recettes pour cette boutique dans la période
$recetteRepository = $this->entityManager->getRepository(Recette::class);
$recettes = $recetteRepository->createQueryBuilder('r')
->where('r.dateRecette >= :start')
->andWhere('r.dateRecette < :end')
->andWhere('r.boutique = :boutique')
->setParameter('start', $startDate->format('Y-m-d H:i:s'))
->setParameter('end', $endDate->format('Y-m-d H:i:s'))
->setParameter('boutique', $boutique)
->orderBy('r.dateRecette', 'DESC')
->getQuery()
->getResult();
return $this->render('dashboard/boutique_recettes.html.twig', [
'boutique' => $boutique,
'recettes' => $recettes,
'period' => $period,
'startDate' => $startDate,
'endDate' => $endDate
]);
}
// Les autres méthodes existantes (dashboardData, dashboardData2, dashboardReportsData)
#[Route('/dashboard/data', name: 'app_dashboard_data')]
public function dashboardData(Request $request): Response
{
$filter = $request->query->get('filter', 'today');
if (!in_array($filter, ['today', 'month', 'year'])) {
return $this->json(['error' => 'Invalid filter'], Response::HTTP_BAD_REQUEST);
}
switch ($filter) {
case 'today':
$salesCount = $this->venteRepository->getSalesCountByPeriod('today');
break;
case 'month':
$salesCount = $this->venteRepository->getSalesCountByPeriod('month');
break;
case 'year':
$salesCount = $this->venteRepository->getSalesCountByPeriod('year');
break;
default:
$salesCount = 0;
break;
}
// Construire les données au format JSON
$data = [
'nombreVentes' => $salesCount
// Ajoutez ici d'autres données si nécessaire
];
// Renvoyer les données au format JSON
return $this->json($data);
}
#[Route('/dashboard/data2', name: 'app_dashboard_data2')]
public function dashboardData2(Request $request): Response
{
$filter = $request->query->get('filter', 'today');
if (!in_array($filter, ['today', 'month', 'year'])) {
return $this->json(['error' => 'Invalid filter'], Response::HTTP_BAD_REQUEST);
}
$totalRevenue = 0;
switch ($filter) {
case 'today':
$totalRevenue = $this->venteRepository->getTotalRevenueByPeriod('today');
break;
case 'month':
$totalRevenue = $this->venteRepository->getTotalRevenueByPeriod('month');
break;
case 'year':
$totalRevenue = $this->venteRepository->getTotalRevenueByPeriod('year');
break;
}
$data = [
'totalRevenue' => $totalRevenue
];
return $this->json($data);
}
#[Route('/dashboard/reports/data', name: 'app_dashboard_reports_data')]
public function dashboardReportsData(Request $request): Response
{
$filter = $request->query->get('filter', 'today');
if (!in_array($filter, ['today', 'month', 'year'])) {
return $this->json(['error' => 'Invalid filter'], Response::HTTP_BAD_REQUEST);
}
// Initialiser les variables pour les données de ventes et de revenus
$salesData = [];
$revenueData = [];
$categories = [];
switch ($filter) {
case 'today':
// Générer les catégories pour aujourd'hui (par exemple, chaque heure)
for ($i = 0; $i < 24; $i++) {
$categories[] = (new \DateTime())->setTime($i, 0)->format('Y-m-d\TH:i:s.v\Z');
$salesData[] = $this->venteRepository->getSalesCountByPeriod('today');
$revenueData[] = $this->venteRepository->getTotalRevenueByPeriod('today');
}
break;
case 'month':
// Générer les catégories pour ce mois (par exemple, chaque jour)
$daysInMonth = (int) date('t');
$currentDate = new \DateTime('first day of this month');
for ($i = 0; $i < $daysInMonth; $i++) {
$categories[] = $currentDate->format('Y-m-d\TH:i:s.v\Z');
$salesData[] = $this->venteRepository->getSalesCountByPeriod('month');
$revenueData[] = $this->venteRepository->getTotalRevenueByPeriod('month');
$currentDate->modify('+1 day');
}
break;
case 'year':
// Générer les catégories pour cette année (par exemple, chaque mois)
for ($i = 1; $i <= 12; $i++) {
$categories[] = (new \DateTime())->setDate(date('Y'), $i, 1)->format('Y-m-d\TH:i:s.v\Z');
$salesData[] = $this->venteRepository->getSalesCountByPeriod('year');
$revenueData[] = $this->venteRepository->getTotalRevenueByPeriod('year');
}
break;
default:
// Gérer d'autres cas si nécessaire
break;
}
// Construire les données au format JSON
$data = [
'Ventes' => $salesData,
'Revenues' => $revenueData,
'categories' => $categories,
];
return $this->json($data);
}
}