src/Flexy/ShopBundle/Service/FlexyShopStatisticProvider.php line 830
<?php
namespace App\Flexy\ShopBundle\Service;
use App\Entity\Settings;
use App\Flexy\ShopBundle\Entity\Order\CashBoxOrder;
use App\Flexy\ShopBundle\Entity\Order\Order;
use App\Flexy\ShopBundle\Entity\Order\OrderItem;
use App\Flexy\ShopBundle\Entity\Product\CategoryProduct;
use App\Flexy\ShopBundle\Entity\Product\Product;
use App\Flexy\ShopBundle\Entity\Promotion\Coupon;
use App\Flexy\ShopBundle\Entity\Store\Store;
use App\Service\FlexySettingsProvider;
use DateTime;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\UX\Chartjs\Builder\ChartBuilderInterface;
use Symfony\UX\Chartjs\Model\Chart;
class FlexyShopStatisticProvider{
public function __construct(
private readonly EntityManagerInterface $em,
private readonly RequestStack $requestStack,
private readonly FlexySettingsProvider $flexySettingsProvider,
private readonly ChartBuilderInterface $chartBuilderInterface
)
{
}
public $chartColors = ['rgba(138,97,255,1)', 'rgb(209, 67, 188)', '#d68d2e','#499bce','#f4d33e','#52ae1d'];
public function quickStats($store=null,$year=null,$month=null){
// ByStore,ByDateInterval,
$lastWeek = new DateTime('last week this month');
$lastMonth = new DateTime('first day of this month');
if($lastWeek < $lastMonth){
$lastMonth = clone $lastWeek;
$lastMonth->modify('first day of this month');
}
if($year and $month){
$lastWeek = new DateTime($year."-".$month);
$lastMonth = new DateTime($year."-".$month);
$lastWeek->modify("last week this month");
$lastMonth->modify("first day of this month");
}
$queryCustomers = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
WHERE (c.store = :store OR :store IS NULL)
AND (YEAR(c.createdAt) = :year OR :year IS NULL)
AND c.gender IS NOT NULL
AND c.dateOfBirth IS NOT NULL
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
');
$queryCustomers
->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth);
$statsCustomers = $queryCustomers->getSingleResult();
//
//
$queryCustomersMale = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
WHERE (YEAR(c.createdAt) = :year OR :year IS NULL)
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
AND c.dateOfBirth <= :min_date_of_birth
AND c.gender = :gender'
);
/* (c.store = :store OR :store IS NULL)
AND*/
$queryCustomersMale
//->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth)
->setParameter('min_date_of_birth', new \DateTime('2008-01-01'))
->setParameter('gender', 'male'); // Valeur du genre à "male"
$statsCustomersMale = $queryCustomersMale->getSingleResult();
//
//
$queryCustomersFemale = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
WHERE (YEAR(c.createdAt) = :year OR :year IS NULL)
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
AND c.dateOfBirth <= :min_date_of_birth
AND c.gender = :gender'
);
/* (c.store = :store OR :store IS NULL)
AND*/
$queryCustomersFemale
//->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth)
->setParameter('min_date_of_birth', new \DateTime('2008-01-01'))
->setParameter('gender', 'female'); // Valeur du genre à "male"
$statsCustomersFemale = $queryCustomersFemale->getSingleResult();
//
/*$queryCustomersNoProductSubscription = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
LEFT JOIN App\Flexy\ShopBundle\Entity\Product\ProductSubscription ps WITH ps.customer = c
WHERE (c.store = :store OR :store IS NULL)
AND (YEAR(c.createdAt) = :year OR :year IS NULL)
AND c.gender IS NOT NULL
AND c.dateOfBirth IS NOT NULL
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
AND ps.customer IS NULL' // Filtre pour les clients sans souscription
);*/
$queryCustomersWithTwoOrders = $this->em->createQuery(
'SELECT COUNT(c.id) AS all
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
WHERE
(YEAR(c.createdAt) = :year OR :year IS NULL)
AND (MONTH( c.createdAt) = :month OR :month IS NULL)
AND (
SELECT COUNT(o.id)
FROM App\Flexy\ShopBundle\Entity\Order\Order o
WHERE o.customer = c
AND NOT EXISTS (
SELECT o.id
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.product p
WHERE oi.parentOrder = o AND p.name IN (:excludedNames)
)
) > 1'
);
$queryCustomersWithTwoOrders
->setParameter('excludedNames', ['Réedition Carte', 'Entre journalier'])
->setParameter('year', $year)
->setParameter('month', $month);
$statsCustomersWithTwoOrders = $queryCustomersWithTwoOrders->getSingleResult();
//
$queryCustomersNoProductSubscription = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
LEFT JOIN App\Flexy\ShopBundle\Entity\Order\Order o WITH o.customer = c
LEFT JOIN App\Flexy\ShopBundle\Entity\Order\OrderItem item WITH item.parentOrder = o
WHERE (c.store = :store OR :store IS NULL)
AND (YEAR(c.createdAt) = :year OR :year IS NULL)
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
AND item.parentOrder IS NULL' // Filtre pour les clients sans souscription
);
$queryCustomersNoProductSubscription
->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth);
$statsCustomersNoProductSubscription = $queryCustomersNoProductSubscription->getSingleResult();
//
$queryCustomerskids = $this->em->createQuery(
'SELECT COUNT(c) as all,
SUM(CASE WHEN c.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN c.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Customer\Customer c
WHERE (YEAR(c.createdAt) = :year OR :year IS NULL)
AND (MONTH(c.createdAt) = :month OR :month IS NULL)
AND c.dateOfBirth >= :min_date_of_birth
AND c.gender IN (:genders) ' // Condition pour inclure les genres male et female
);
/* (c.store = :store OR :store IS NULL)
AND*/
$queryCustomerskids
//->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth)
->setParameter('min_date_of_birth', new \DateTime('2008-01-01')) // Date minimale : 1er janvier 2008
->setParameter('genders', ['male', 'female']); // Filtrer par genres "male" ou "female"
$statsCustomerskids = $queryCustomerskids->getSingleResult();
//
$querySubscriptions = $this->em->createQuery(
'SELECT COUNT(ps) as all,
SUM(CASE WHEN ps.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN ps.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Product\ProductSubscription ps
WHERE (YEAR(ps.createdAt) = :year OR :year IS NULL)
AND (MONTH(ps.createdAt) = :month OR :month IS NULL)
');
$querySubscriptions
->setParameter('year', $year)
->setParameter('month', $month)
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth);
$statsSubscription = $querySubscriptions->getSingleResult();
$quickStats = [
"revenue"=>[
"all"=>(float)$this->getRevenue($store,$year,$month)["all"],
"new"=>'',/*(float)$this->getRevenue($store,$year,$month)["last_week"]*/
"old"=>'',
"unit"=>$this->flexySettingsProvider->get()->getCurrency(),
"icon"=>'<i class="fa-solid fa-comment-dollar"></i>',
"color"=>"purple"
],
"customers"=>[
"all"=>$statsCustomers['all'],
"new"=>$statsCustomers['last_week'],
"old"=> $statsCustomers['last_month'],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-people-group"></i>',
"color"=>"pink-dark"
],
"Adhérents hommes"=>[
"all"=>$statsCustomersMale['all'],
"new"=>$statsCustomersMale['last_week'],
"old"=> $statsCustomersMale['last_month'],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-person"></i>',
"color"=>"pink-dark"
],
"Adhérentes femmes"=>[
"all"=>$statsCustomersFemale['all'],
"new"=>$statsCustomersFemale['last_week'],
"old"=> $statsCustomersFemale['last_month'],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-person-dress"></i>',
"color"=>"pink-dark"
],
"Adhérents Enfants"=>[
"all"=>$statsCustomerskids['all'],
"new"=>$statsCustomerskids['last_week'],
"old"=> $statsCustomerskids['last_month'],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-child"></i>',
"color"=>"pink-dark"
],
"Visiteurs non inscrits"=>[
"all"=>$statsCustomersNoProductSubscription['all'],
"new"=>$statsCustomersNoProductSubscription['last_week'],
"old"=> $statsCustomersNoProductSubscription['last_month'],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-people-group"></i>',
"color"=>"pink-dark"
],
/*"waitingOrders"=>[
"all"=>$this->statsOrdersByStatus("waiting",$store,$year,$month)["all"],
"new"=>$this->statsOrdersByStatus("waiting",$store,$year,$month)["last_week"],
"old"=>$this->statsOrdersByStatus("waiting",$store,$year,$month)["last_month"],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-file-excel"></i>',
"color"=>"orange-dark"
],*/
"contrats renouvelables "=>[
"all"=>$statsCustomersWithTwoOrders['all'],
"new"=>'',
"old"=> '',
"unit"=>null,
"icon"=>'<i class="fa-solid fa-file-circle-plus"></i>',
"color"=>"pink-dark"
],
"Contrats annulés"=>[
"all"=>$this->statsOrdersByStatus("canceled",$store,$year,$month)["all"],
"new"=>$this->statsOrdersByStatus("canceled",$store,$year,$month)["last_week"],
"old"=>$this->statsOrdersByStatus("canceled",$store,$year,$month)["last_month"],
"unit"=>null,
"icon"=>'<i class="fa-regular fa-file-lines"></i>',
"color"=>"blue-dark"
],
/*"completedOrders"=>[
"all"=>$this->statsOrdersByStatus("payed",$store,$year,$month)["all"],
"new"=>$this->statsOrdersByStatus("payed",$store,$year,$month)["last_week"],
"old"=>$this->statsOrdersByStatus("payed",$store,$year,$month)["last_month"],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-clipboard-check"></i>',
"color"=>"green-dark"
],*/
"subscriptions"=>[
"all"=>$statsSubscription["all"],
"new"=>$statsSubscription["last_week"],
"old"=>$statsSubscription["last_month"],
"unit"=>null,
"icon"=>'<i class="fa-solid fa-link"></i>',
"color"=>"purple-dark"
],
];
return $quickStats;
}
public function getRevenue($store=null,$year=null,$month=null)
{
$lastWeek = new DateTime('last week this month');
$lastMonth = new DateTime('first day of this month');
if($lastWeek < $lastMonth){
$lastMonth = clone $lastWeek;
$lastMonth->modify('first day of this month');
}
if($year and $month){
$lastWeek = new DateTime($year."-".$month);
$lastMonth = new DateTime($year."-".$month);
$lastWeek->modify("last week this month");
$lastMonth->modify("first day of this month");
}
//SELECT SUM(oi.quantity * oi.price) as all,
/*$query = $this->em->createQuery(
'SELECT
SUM(payments.amount) as all,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :lastWeek AND :now THEN payments.amount ELSE 0 END) as last_week,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :lastMonth AND :now THEN payments.amount ELSE 0 END) as last_month,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :today and :tomorrow THEN payments.amount ELSE 0 END) as today,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :yesterday and :today THEN payments.amount ELSE 0 END) as yesterday
FROM App\Flexy\ShopBundle\Entity\Order\Order o
JOIN o.payments payments
JOIN o.cashBoxOrder cashBoxOrder
WHERE (o.store = :store OR :store IS NULL)
AND cashBoxOrder IS NOT NULL
AND (YEAR(cashBoxOrder.startAt) = :year OR :year IS NULL)
AND (MONTH(cashBoxOrder.startAt) = :month OR :month IS NULL)
'
)->setParameters([
'today' => new \DateTime('today'),
'yesterday' => new \DateTime('yesterday'),
'tomorrow' => new \DateTime('tomorrow'),
'lastWeek' => $lastWeek,
'lastMonth' => $lastMonth,
'now' => new \DateTime(),
'store'=>$store,
'year'=>$year,
'month'=>$month
]);
$revenue = $query->getSingleResult();*/
//SELECT SUM(oi.quantity * oi.price) as all,
$query = $this->em->createQuery(
'SELECT
SUM(payments.amount) as all,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :lastWeek AND :now THEN payments.amount ELSE 0 END) as last_week,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :lastMonth AND :now THEN payments.amount ELSE 0 END) as last_month,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :today AND :tomorrow THEN payments.amount ELSE 0 END) as today,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :yesterday AND :yesterdayEnd THEN payments.amount ELSE 0 END) as yesterday,
SUM(CASE WHEN cashBoxOrder.startAt BETWEEN :firstDayOfMonth AND :now THEN payments.amount ELSE 0 END) as current_month
FROM App\Flexy\ShopBundle\Entity\Order\Order o
JOIN o.payments payments
JOIN o.cashBoxOrder cashBoxOrder
WHERE (o.store = :store OR :store IS NULL)
AND cashBoxOrder IS NOT NULL
AND (YEAR(cashBoxOrder.startAt) = :year OR :year IS NULL)
AND (MONTH(cashBoxOrder.startAt) = :month OR :month IS NULL)'
)->setParameters([
'today' => new \DateTime('today'),
'tomorrow' => new \DateTime('tomorrow'),
'yesterday' => new \DateTime('yesterday'),
'yesterdayEnd' => (new \DateTime('today'))->modify('-1 second'),
'firstDayOfMonth' => (new \DateTime('first day of this month'))->setTime(0, 0), // Le début du mois courant à 00:00:00
'lastWeek' => $lastWeek,
'lastMonth' => $lastMonth,
'now' => new \DateTime(),
'store' => $store,
'year' => $year,
'month' => $month
]);
$revenue = $query->getSingleResult();
return $revenue;
}
public function getAverageRevenuePerDay($period="day",$details = false)
{
$query = $this->em->createQuery(
'SELECT DATE(o.createdAt) as period,
AVG(i.price * i.quantity) as averageRevenue
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem i
JOIN i.parentOrder o
GROUP BY period
');
if($period == "week"){
$query = $this->em->createQuery(
'SELECT YEARWEEK(o.createdAt) as period,
AVG(i.price * i.quantity) as averageRevenue
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem i
JOIN i.parentOrder o
GROUP BY period
');
}elseif($period == "month"){
$query = $this->em->createQuery(
"SELECT DATE_FORMAT(o.createdAt, '%Y-%m') as period,
AVG(i.price * i.quantity) as averageRevenue
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem i
JOIN i.parentOrder o
GROUP BY period
");
}
$results = $query->getResult();
if($details==true){
return $results;
}
$totalRevenue = 0;
foreach($results as $singleResult){
$totalRevenue = $totalRevenue + $singleResult["averageRevenue"];
}
$revenue = 0;
if(count($results) > 0){
$revenue = $totalRevenue / count($results);
}
return $revenue;
}
public function getRevenueByYear($store=null,$year=null)
{
$entityManager = $this->em;
$subquery = $entityManager->createQuery(
'SELECT o.id
FROM App\Flexy\ShopBundle\Entity\Order\Order o
WHERE o.status != :status
AND (YEAR(o.createdAt) = :year OR :year IS NULL )'
)->setParameters([
'status' => 'canceled',
'year' => $year,
]);
$query = $entityManager->createQuery(
'SELECT MONTH(orderEntity.createdAt) as month, YEAR(orderEntity.createdAt) as year,
SUM(oi.quantity * oi.price) as revenue
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.parentOrder orderEntity
WHERE orderEntity.id IN (' . $subquery->getDQL() . ')
AND orderEntity.status != :status
AND (YEAR(orderEntity.createdAt) = :year OR :year IS NULL )
AND (orderEntity.store = :store OR :store IS NULL)
GROUP BY month, year'
)->setParameters([
'status' => 'canceled',
'year' => $year,
'store' => $store,
]);
$revenue = $query->getResult();
// Format month and year as strings
foreach ($revenue as $key => $value) {
// Vérifiez que les clés 'month' et 'year' existent avant de les utiliser
if (isset($value['month']) && isset($value['year'])) {
$month = DateTime::createFromFormat('!m', $value['month'])->format('F');
$year = $value['year'];
$revenue[$key]['monthYear'] = $month . " " . $year;
unset($revenue[$key]['month']);
unset($revenue[$key]['year']);
} else {
// Gérer les cas où les clés 'month' ou 'year' sont manquantes
throw new \Exception("Les clés 'month' ou 'year' sont manquantes dans les résultats de la requête.");
}
}
return $revenue;
}
public function getRevenueByMonth($store=null,$year=null,$month=null)
{
$entityManager = $this->em;
$subquery = $entityManager->createQuery(
'SELECT o.id
FROM App\Flexy\ShopBundle\Entity\Order\Order o
WHERE o.status != :status
AND YEAR(o.createdAt) = :year
AND MONTH(o.createdAt) = :month'
)->setParameters([
'status' => 'canceled',
'year' => $year ?? date('Y'),
'month' => $month ?? date('m'),
]);
$query = $entityManager->createQuery(
'SELECT orderEntity.createdAt as date, SUM(oi.quantity * oi.price) as revenue
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.parentOrder orderEntity
WHERE orderEntity.id IN (' . $subquery->getDQL() . ')
AND orderEntity.status != :status
AND YEAR(orderEntity.createdAt) = :year
AND MONTH(orderEntity.createdAt) = :month
AND (orderEntity.store = :store OR :store IS NULL)
GROUP BY date'
)->setParameters([
'status' => 'canceled',
'year' => $year ?? date('Y'),
'month' => $month ?? date('m'),
'store' => $store,
]);
$revenue = $query->getResult();
// Format date as string
foreach ($revenue as $key => $value) {
$date = $value['date'];
$revenue[$key]['date'] = $date->format('Y-m-d');
}
return $revenue;
}
public function statsOrderStatus($store=null,$year=null,$month=null){
$query = "SELECT
COUNT(DISTINCT o.id) as all,
SUM(CASE WHEN EXISTS(SELECT stypeCollect FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeCollect WHERE CONCAT(',', stypeCollect.events, ',') LIKE '%collected%' AND ts.stepType = stypeCollect) THEN 1 ELSE 0 END) as collecting,
SUM(CASE WHEN EXISTS(SELECT stypeProcessing FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeProcessing WHERE CONCAT(',', stypeProcessing.events, ',') LIKE '%processed%' AND ts.stepType = stypeProcessing) THEN 1 ELSE 0 END) as processing,
SUM(CASE WHEN EXISTS(SELECT stypeShipping FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeShipping WHERE CONCAT(',', stypeShipping.events, ',') LIKE '%shipped%' AND ts.stepType = stypeShipping) THEN 1 ELSE 0 END) as shipping,
SUM(CASE WHEN o.status = 'paid' THEN 1 ELSE 0 END) as paid,
ROUND( ( SUM(CASE WHEN EXISTS(SELECT stypeCollectPercent FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeCollectPercent WHERE CONCAT(',', stypeCollectPercent.events, ',') LIKE '%collected%' AND ts.stepType = stypeCollectPercent) THEN 1 ELSE 0 END) / COUNT(DISTINCT o.id)) * 100) as percentage_collecting,
ROUND( ( SUM(CASE WHEN EXISTS(SELECT stypeProcessingPercent FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeProcessingPercent WHERE CONCAT(',', stypeProcessingPercent.events, ',') LIKE '%processed%' AND ts.stepType = stypeProcessingPercent) THEN 1 ELSE 0 END) / COUNT(DISTINCT o.id)) * 100) as percentage_processing,
ROUND( ( SUM(CASE WHEN EXISTS(SELECT stypeShippingPercent FROM App\Flexy\ShopBundle\Entity\Shipping\StepType stypeShippingPercent WHERE CONCAT(',', stypeShippingPercent.events, ',') LIKE '%shipped%' AND ts.stepType = stypeShippingPercent) THEN 1 ELSE 0 END) / COUNT(DISTINCT o.id)) * 100) as percentage_shipping,
ROUND( ( SUM(CASE WHEN o.status = 'paid' THEN 1 ELSE 0 END) / COUNT(DISTINCT o.id)) * 100) as percentage_paid
FROM App\Flexy\ShopBundle\Entity\Shipping\Shipment s
JOIN s.relatedOrder o
LEFT JOIN s.trackingSteps ts
WHERE s.id IS NOT NULL
AND o.status != :status
AND (o.store = :store OR :store IS NULL)
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
";
$queryBuilder = $this->em->createQuery($query)->setParameters([
"status"=>"canceled",
"store"=>$store,
"year"=>$year,
"month"=>$month
]);
$statsOrdersStatus = $queryBuilder->getResult();
return $statsOrdersStatus;
}
public function statsOrdersByStatus($status="canceled",$store=null,$year=null,$month=null){
$queryOrders = $this->em->createQuery(
'SELECT COUNT(o) as all,
SUM(CASE WHEN o.createdAt >= :last_week THEN 1 ELSE 0 END) as last_week,
SUM(CASE WHEN o.createdAt >= :last_month THEN 1 ELSE 0 END) as last_month
FROM App\Flexy\ShopBundle\Entity\Order\Order o
WHERE o.status = :status
AND (o.store = :store OR :store IS NULL)
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
');
$lastWeek = new DateTime('last week this month');
$lastMonth = new DateTime('first day of this month');
if($lastWeek < $lastMonth){
$lastMonth = clone $lastWeek;
$lastMonth->modify('first day of this month');
}
if($year and $month){
$lastWeek = new DateTime($year."-".$month);
$lastMonth = new DateTime($year."-".$month);
$lastWeek->modify("last week this month");
$lastMonth->modify("first day of this month");
}
$queryOrders
->setParameter('last_week', $lastWeek)
->setParameter('last_month', $lastMonth)
->setParameter('status', $status)
->setParameter('store', $store)
->setParameter('year', $year)
->setParameter('month', $month)
;
$statsOrders = $queryOrders->getSingleResult();
return $statsOrders;
}
public function productRevenue(Product $product): float
{
$qb = $this->em->createQueryBuilder();
$qb->select('SUM(oi.price * oi.quantity) as revenue')
->from(OrderItem::class, 'oi')
->join('oi.product', 'p')
->where('p.id = :productId')
->setParameter('productId', $product->getId());
$result = $qb->getQuery()->getSingleResult();
return $result['revenue'];
}
public function categoryRevenue(CategoryProduct $category): float
{
$qb = $this->em->createQueryBuilder();
$qb->select('SUM(oi.price * oi.quantity) as revenue')
->from(OrderItem::class, 'oi')
->join('oi.product', 'p')
->join('p.categoriesProduct', 'c')
->where('c.id = :categoryId')
->setParameter('categoryId', $category->getId());
$result = $qb->getQuery()->getSingleResult();
return $result['revenue'];
}
/*public function revenueByProducts($store=null,$year=null,$month=null){
$dql = 'SELECT
p,
(
SELECT SUM(oi.quantity * oi.price)
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.parentOrder o
WHERE o.status != :status AND oi.product = p
AND (o.store = :store OR :store IS NULL)
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
) as revenue
FROM
App\Flexy\ShopBundle\Entity\Product\Product p
LEFT JOIN
App\Flexy\ShopBundle\Entity\Order\OrderItem oItem WITH oItem.product = p
GROUP BY
p.id, p.name
HAVING
revenue > 0
ORDER BY
revenue DESC
';
$query = $this->em->createQuery($dql)->setParameters(
[
"status"=>"canceled",
"year"=>$year,
"month"=>$month,
"store"=>$store
]
)->setMaxResults(12);
$productsRevenue = $query->getResult();
return $productsRevenue;
}*/
public function revenueByProducts($store=null,$year=null,$month=null){
$dql = '
SELECT
p.id AS productId,
p.name AS productName,
SUM(oi.quantity * oi.price) AS revenue,
COUNT(oi.id) AS totalSold
FROM
App\Flexy\ShopBundle\Entity\Order\OrderItem oi
LEFT JOIN
App\Flexy\ShopBundle\Entity\Product\Product p WITH p.id = oi.product
LEFT JOIN
oi.parentOrder o
WHERE
(YEAR(oi.createdAt) = :year OR :year IS NULL)
AND (o.store = :store OR :store IS NULL)
AND (MONTH(oi.createdAt) = :month OR :month IS NULL)
AND p.name IS NOT NULL
GROUP BY
p.id, p.name
HAVING
revenue > 0
ORDER BY
revenue DESC
';
$query = $this->em->createQuery($dql)->setParameters([
"store"=>$store,
'year' => $year,
'month' => $month,
])->setMaxResults(12);
$productsRevenue = $query->getResult();
return $productsRevenue;
}
public function visitAll($store=null,$year=null,$month=null){
$dql = "SELECT
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL THEN 1 ELSE 0 END) as automatique,
SUM(CASE WHEN v.manual = 1 THEN 1 ELSE 0 END) as manuel,
DATE_FORMAT(v.createdAt, '%M') as Mois,
YEAR(CURRENT_DATE()) as annee
FROM
App\Flexy\ShopBundle\Entity\Customer\Visit v
WHERE
YEAR(v.createdAt) = YEAR(CURRENT_DATE())
GROUP BY
Mois
";
$query = $this->em->createQuery($dql)->setMaxResults(12);
$visit = $query->getResult();
return $visit;
}
public function getVisitYesterday($store=null,$year=null,$month=null)
{
$today = new \DateTime('today');
$yesterday =new \DateTime('yesterday');
$yesterdayFormatted = $yesterday->format('Y-m-d H:i');
$todayFormatted = $today->format('Y-m-d H:i');
$dql = "SELECT
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL THEN 1 ELSE 0 END) as automatique,
SUM(CASE WHEN v.manual = 1 THEN 1 ELSE 0 END) as manuel,
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL AND c.gender = 'female' THEN 1 ELSE 0 END) as female_automatique,
SUM(CASE WHEN v.manual = 1 AND c.gender = 'female' THEN 1 ELSE 0 END) as female_manuel,
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL AND c.gender = 'male' THEN 1 ELSE 0 END) as male_automatique,
SUM(CASE WHEN v.manual = 1 AND c.gender = 'male' THEN 1 ELSE 0 END) as male_manuel
FROM
App\Flexy\ShopBundle\Entity\Customer\Visit v
LEFT JOIN
App\Flexy\ShopBundle\Entity\Customer\Customer c WITH v.customer = c
WHERE v.createdAt >= :yesterday
AND v.createdAt < :today
";
$query = $this->em->createQuery($dql)->setParameters(
[
"yesterday"=>$yesterdayFormatted,
"today"=>$todayFormatted,
]
)->setMaxResults(12);
$visit = $query->getResult();
//dd($visit);
return $visit;
}
public function getVisitToday($store=null,$year=null,$month=null)
{
$today = new \DateTime('today');
$tomorrow =new \DateTime('tomorrow');
$tomorrowFormatted = $tomorrow->format('Y-m-d H:i');
$todayFormatted = $today->format('Y-m-d H:i');
$dql = "SELECT
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL THEN 1 ELSE 0 END) as automatique,
SUM(CASE WHEN v.manual = 1 THEN 1 ELSE 0 END) as manuel,
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL AND c.gender = 'female' THEN 1 ELSE 0 END) as female_automatique,
SUM(CASE WHEN v.manual = 1 AND c.gender = 'female' THEN 1 ELSE 0 END) as female_manuel,
SUM(CASE WHEN v.manual = 0 OR v.manual IS NULL AND c.gender = 'male' THEN 1 ELSE 0 END) as male_automatique,
SUM(CASE WHEN v.manual = 1 AND c.gender = 'male' THEN 1 ELSE 0 END) as male_manuel
FROM
App\Flexy\ShopBundle\Entity\Customer\Visit v
LEFT JOIN
App\Flexy\ShopBundle\Entity\Customer\Customer c WITH v.customer = c
WHERE v.createdAt >= :today
AND v.createdAt < :tomorrow
";
$query = $this->em->createQuery($dql)->setParameters(
[
"tomorrow"=>$tomorrowFormatted,
"today"=>$todayFormatted,
]
)->setMaxResults(12);
$visit = $query->getResult();
//dd($visit);
return $visit;
}
public function revenueByCategories($store=null,$year=null,$month=null){
$dql = 'SELECT
c.name as category,
(
SELECT SUM(oi.quantity * oi.price)
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.parentOrder o
WHERE c.parentCategory IS NOT NULL AND o.status != :status AND oi.product MEMBER OF c.products
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
AND (o.store = :store OR :store IS NULL)
) as revenue
FROM
App\Flexy\ShopBundle\Entity\Product\CategoryProduct c
GROUP BY
c.id, c.name
HAVING
revenue > 0
ORDER BY
revenue DESC';
$query = $this->em->createQuery($dql)->setParameters(
[
"status"=>"canceled",
"year"=>$year,
"month"=>$month,
"store"=>$store
]
)->setMaxResults(12);
$categoriesRevenue = $query->getResult();
return $categoriesRevenue;
}
public function revenueByAgents($store=null,$year=null,$month=null){
$dql = 'SELECT
a.firstName as agentFirstName,
a.lastName as agentLastName,
(
SELECT SUM(payments.amount)
FROM App\Flexy\ShopBundle\Entity\Payment\Payment payments
JOIN payments.relatedOrder o
WHERE o.agent = a
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
AND (o.store = :store OR :store IS NULL)
) as revenue
FROM
App\Flexy\ShopBundle\Entity\Resource\Agent a
GROUP BY
a.id, a.firstName
HAVING
revenue > 0
ORDER BY
revenue DESC';
$query = $this->em->createQuery($dql)->setParameters(
[
"year"=>$year,
"month"=>$month,
"store"=>$store
]
)->setMaxResults(12);
$agentsRevenue = $query->getResult();
return $agentsRevenue;
}
public function revenueByParentCategories($store=null,$year=null,$month=null){
$dql = 'SELECT
pc.name as category,
(
SELECT SUM(oi.quantity * oi.price)
FROM App\Flexy\ShopBundle\Entity\Order\OrderItem oi
JOIN oi.parentOrder o
JOIN oi.product p
JOIN p.categoriesProduct categ
WHERE categ.parentCategory = pc AND o.status != :status
AND (YEAR(o.createdAt) = :year OR :year IS NULL)
AND (MONTH(o.createdAt) = :month OR :month IS NULL)
AND (o.store = :store OR :store IS NULL)
) as revenue
FROM
App\Flexy\ShopBundle\Entity\Product\CategoryProduct c
JOIN
c.parentCategory pc
WHERE
c.parentCategory IS NOT NULL
GROUP BY
pc.id, pc.name
HAVING
revenue > 0
ORDER BY
revenue DESC';
$query = $this->em->createQuery($dql)->setParameters(
[
"status"=>"canceled",
"year"=>$year,
"month"=>$month,
"store"=>$store
]
);
$categoriesRevenue = $query->getResult();
return $categoriesRevenue;
}
public function revenueByCashBoxOrder(CashBoxOrder $cashBoxOrder){
$queryBuilder = $this->em->createQueryBuilder();
$queryBuilder->select('SUM(oi.price * oi.quantity) AS revenue');
$queryBuilder->from('App\Flexy\ShopBundle\Entity\Order\Order', 'o');
$queryBuilder->join('o.orderItems', 'oi');
$queryBuilder->join('App\Flexy\ShopBundle\Entity\Order\CashBoxOrder', 'cashBox');
$queryBuilder->where('cashBox = :cashBox');
$queryBuilder->groupBy('cashBox');
$queryBuilder->addGroupBy('cashBox.startAt');
$queryBuilder->setParameter("cashBox",$cashBoxOrder);
$results = $queryBuilder->getQuery()->getResult();
return $results;
}
public function revenueByCityRegion(){
$queryBuilder = $this->em->createQueryBuilder();
$queryBuilder->select('cr.name AS cityRegionName, SUM(oi.price * oi.quantity) AS revenue')
->from('App\Flexy\ShopBundle\Entity\Order\Order', 'o')
->join('o.orderItems', 'oi')
->leftJoin('o.cityRegionCollect', 'crc')
->leftJoin('o.cityRegionShipping', 'crs')
->join('App\Flexy\ShopBundle\Entity\Shipping\CityRegion', 'cr', 'WITH', 'cr = crc OR cr = crs')
->groupBy('cr')
->addGroupBy('cr.name');
$results = $queryBuilder->getQuery()->getResult();
return $results;
}
// CHARTS FUNCTIONS :
public function chartRevenue($store=null,$year=null,$month=null){
//$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_LINE);
$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_BAR);
$labels = [];
$data = [];
if($year and $month){
foreach($this->getRevenueByMonth($store,$year,$month) as $singleMonth){
$labels[] = $singleMonth["date"];
$data[] = $singleMonth["revenue"];
}
}
else{
foreach($this->getRevenueByYear($store,$year) as $singleMonth){
$labels[] = $singleMonth["monthYear"];
$data[] = $singleMonth["revenue"];
}
}
$chart->setData([
'labels' => $labels,
'datasets' => [
[
'label' => 'Chiffre d\'affaire ',
'backgroundColor' => $this->chartColors,
//'borderColor' => 'rgb(255, 99, 132)',
"borderRadius"=>10,
'data' => $data,
"tension"=> 0.5,
"fill" => true,
],
],
]);
$chart->setOptions([
"plugins"=>[
"legend"=>[
"labels"=>[
"font"=>[
"size"=>12,
"family"=> "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"
]
]
]
],
'scales' => [
'y' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
'suggestedMin' => 0,
//'suggestedMax' => 3000,
"display"=>true ,
"grid"=>[
"lineWidth"=>0.2,
"borderColor"=>"rgba(0,0,0,0)"
],
],
'x' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
"display"=>true,
"grid"=>[
"lineWidth"=>0,
"borderColor"=>"rgba(0,0,0,0)"
],
],
],
]);
return $chart;
}
public function chartVisteBymonths($store=null,$year=null,$month=null){
$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_LINE);
$labels = [];
$data = [];
foreach($this->visitAll($store,$year,$month) as $singleData){
$labels[] = $singleData["Mois"];
$data[] = $singleData["automatique"];
$data1[] = $singleData["manuel"];
}
$chart->setData([
'labels' => $labels,
'datasets' => [
[
'label' => '🏃🏻♂️ Pointage Manuel',
'backgroundColor' => 'rgb(255, 99, 132, .4)',
'borderColor' => 'rgb(255, 99, 132)',
'data' => $data1,
'tension' => 0.4,
],
[
'label' => '🏃🏻♂️ Pointage 💳 Carte',
'backgroundColor' => 'rgba(45, 220, 126, .4)',
'borderColor' => 'rgba(45, 220, 126)',
'data' => $data,
'tension' => 0.4,
],
],
]);
$chart->setOptions([
'maintainAspectRatio' => false,
]);
return $chart;
}
public function chartRevenueByParentCategories($store=null,$year=null,$month=null){
$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_DOUGHNUT);
$labels = [];
$data = [];
foreach($this->revenueByParentCategories($store,$year,$month) as $singleData){
$labels[] = $singleData["category"];
$data[] = $singleData["revenue"];
}
$chart->setData([
'labels' => $labels,
'datasets' => [
[
'label' => 'Chiffre d\'affaire ',
'backgroundColor' => $this->chartColors,
'data' => $data,
],
],
]);
$chart->setOptions([
"plugins"=>[
"legend"=>[
"labels"=>[
"font"=>[
"size"=>12,
"family"=> "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"
]
]
]
],
'scales' => [
'y' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
'suggestedMin' => 0,
"display"=>false ,
"grid"=>[
"lineWidth"=>0.2,
"borderColor"=>"rgba(0,0,0,0)"
],
],
'x' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
"display"=>true,
"grid"=>[
"lineWidth"=>0,
"borderColor"=>"rgba(0,0,0,0)"
],
],
],
]);
return $chart;
}
public function chartRevenueByProduct(){
$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_BAR);
$chart->setData([
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July','January', 'February', 'March', 'April', 'May', 'June', 'July'],
'datasets' => [
[
'label' => 'Chiffre d\'affaire ',
'backgroundColor' => $this->chartColors,
//'borderColor' => 'rgb(255, 99, 132)',
"borderRadius"=>10,
'data' => [12, 10, 5, 2, 20, 30, 45,12, 10, 5, 2, 20, 30, 45],
"tension"=> 0.4,
//"fill" => true,
],
],
]);
$chart->setOptions([
"plugins"=>[
"legend"=>[
"labels"=>[
"font"=>[
"size"=>12,
"family"=> "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"
]
]
]
],
'scales' => [
'y' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
'suggestedMin' => 0,
'suggestedMax' => 100,
"display"=>true ,
"grid"=>[
"lineWidth"=>0.2,
"borderColor"=>"rgba(0,0,0,0)"
],
],
'x' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
"display"=>true,
"grid"=>[
"lineWidth"=>0,
"borderColor"=>"rgba(0,0,0,0)"
],
],
],
]);
return $chart;
}
public function chartRevenueByCategory(){
$chart = $this->chartBuilderInterface->createChart(Chart::TYPE_BAR);
$chart->setData([
'labels' => ['January', 'February', 'March', 'April', 'May', 'June', 'July','January', 'February', 'March', 'April', 'May', 'June', 'July'],
'datasets' => [
[
'label' => 'Chiffre d\'affaire ',
'backgroundColor' => $this->chartColors,
//'borderColor' => 'rgb(255, 99, 132)',
"borderRadius"=>10,
'data' => [12, 10, 5, 2, 20, 30, 45,12, 10, 5, 2, 20, 30, 45],
"tension"=> 0.4,
//"fill" => true,
],
],
]);
$chart->setOptions([
"plugins"=>[
"legend"=>[
"labels"=>[
"font"=>[
"size"=>12,
"family"=> "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif"
]
]
]
],
'scales' => [
'y' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
'suggestedMin' => 0,
'suggestedMax' => 100,
"display"=>true ,
"grid"=>[
"lineWidth"=>0.2,
"borderColor"=>"rgba(0,0,0,0)"
],
],
'x' => [
'ticks' => [
'font' => [
'size' => 11,
'family' => "'Montserrat', 'Helvetica', 'Arial', sans-serif",
'style' => 'normal',
'weight' => 'normal',
],
'color' => 'rgba(0,0,0,0.3)',
],
"display"=>true,
"grid"=>[
"lineWidth"=>0,
"borderColor"=>"rgba(0,0,0,0)"
],
],
],
]);
return $chart;
}
public function periodsOrdersOptions($store=null){
$qb = $this->em->createQueryBuilder();
$qb->select('YEAR(o.createdAt) AS year, MONTH(o.createdAt) AS month')
->from('App\Flexy\ShopBundle\Entity\Order\Order', 'o')
->where(
'(o.store = :store OR :store IS NULL)'
)
->orderBy('year', 'DESC')
->addOrderBy('month', 'ASC')
->setParameters([
"store"=>$store,
])
;
$results = $qb->getQuery()->getResult();
$years = [];
foreach ($results as $result) {
$year = $result['year'];
$month = $result['month'];
$monthName = date("F", mktime(0, 0, 0, $month, 1));
if (!isset($years[$year])) {
$years[$year] = [];
}
if (!in_array(['number' => $month, 'name' => $monthName], $years[$year])) {
$years[$year][] = ['number' => $month, 'name' => $monthName];
}
}
$finalArray = [];
foreach ($years as $year => $months) {
$finalArray[] = [
'year' => $year,
'months' => $months
];
}
// sort the final array by the latest year and month
usort($finalArray, function($a, $b) {
$aYear = $a['year'];
$aMonth = end($a['months'])['number'];
$bYear = $b['year'];
$bMonth = end($b['months'])['number'];
if ($aYear == $bYear) {
return ($aMonth < $bMonth) ? 1 : -1;
}
return ($aYear < $bYear) ? 1 : -1;
});
return $finalArray;
// $finalArray now contains an array of years where orders exist, each year
// with the months where orders exist, including the numeric value and name of the month,
// sorted by the latest year and month.
}
}