fix: 📈 update dashboard statistics #52
This commit is contained in:
parent
184da0204b
commit
f454d35960
15 changed files with 419 additions and 254 deletions
|
|
@ -19,8 +19,8 @@ final class InvoicingUnit extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'colis' => 'COLIS',
|
||||
];
|
||||
}
|
||||
|
|
@ -33,8 +33,8 @@ final class InvoicingUnit extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'colis' => __('Colis'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ final class OrderUnit extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'colis' => 'COLIS',
|
||||
];
|
||||
}
|
||||
|
|
@ -33,8 +33,8 @@ final class OrderUnit extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'colis' => __('Colis'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class PriceShowingMode extends BaseEnumRoutable
|
|||
{
|
||||
return [
|
||||
'authenticated' => 'authenticated',
|
||||
'guest' => 'guest',
|
||||
'guest' => 'guest',
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ class PriceShowingMode extends BaseEnumRoutable
|
|||
{
|
||||
return [
|
||||
'authenticated' => __('Client Connecté'),
|
||||
'guest' => __('Public'),
|
||||
'guest' => __('Public'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,12 +27,12 @@ class ProductBrand extends BaseEnumRoutable
|
|||
public static function labels()
|
||||
{
|
||||
return [
|
||||
'none' => 'Sans marque',
|
||||
'loue' => 'Loué',
|
||||
'legaulois' => 'Le Gaulois',
|
||||
'legauloispro' => 'Le Gaulois Professionnel',
|
||||
'marie' => 'Marie',
|
||||
'tregalette' => 'Trégalette',
|
||||
'none' => 'Sans marque',
|
||||
'loue' => 'Loué',
|
||||
'legaulois' => 'Le Gaulois',
|
||||
'legauloispro' => 'Le Gaulois Professionnel',
|
||||
'marie' => 'Marie',
|
||||
'tregalette' => 'Trégalette',
|
||||
'esprirestauration' => 'Espri Restauration',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,21 +34,21 @@ class SalarieSite extends BaseEnumRoutable
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'slhp' => 'SLHP',
|
||||
'ldcser' => 'LDCSER',
|
||||
'ldcvol' => 'LDCVOL',
|
||||
'ldcter' => 'LDCTER',
|
||||
'ldctra' => 'LDCTRA',
|
||||
'ldccav' => 'LDCCAV',
|
||||
'ldchol' => 'LDCHOL',
|
||||
'slhp' => 'SLHP',
|
||||
'ldcser' => 'LDCSER',
|
||||
'ldcvol' => 'LDCVOL',
|
||||
'ldcter' => 'LDCTER',
|
||||
'ldctra' => 'LDCTRA',
|
||||
'ldccav' => 'LDCCAV',
|
||||
'ldchol' => 'LDCHOL',
|
||||
'cepacpe' => 'CEPACP',
|
||||
'dde' => 'DDE',
|
||||
'dpe' => 'DPE',
|
||||
'sl' => 'SL',
|
||||
'gdfroi' => 'GDFROI',
|
||||
'ldcplb' => 'LDCPLB',
|
||||
'slela' => 'SLELA',
|
||||
'tpwiss' => 'TPWISS'
|
||||
'dde' => 'DDE',
|
||||
'dpe' => 'DPE',
|
||||
'sl' => 'SL',
|
||||
'gdfroi' => 'GDFROI',
|
||||
'ldcplb' => 'LDCPLB',
|
||||
'slela' => 'SLELA',
|
||||
'tpwiss' => 'TPWISS'
|
||||
];
|
||||
}
|
||||
|
||||
|
|
@ -60,21 +60,21 @@ class SalarieSite extends BaseEnumRoutable
|
|||
public static function labels()
|
||||
{
|
||||
return [
|
||||
'slhp' => 'Holdings',
|
||||
'ldcser' => 'LDC Services',
|
||||
'ldcvol' => 'LDC Sablé',
|
||||
'ldcter' => 'LDC Intenational',
|
||||
'ldctra' => 'LDC Traiteur',
|
||||
'ldccav' => 'Cavol',
|
||||
'ldchol' => 'LDC Holding',
|
||||
'slhp' => 'Holdings',
|
||||
'ldcser' => 'LDC Services',
|
||||
'ldcvol' => 'LDC Sablé',
|
||||
'ldcter' => 'LDC Intenational',
|
||||
'ldctra' => 'LDC Traiteur',
|
||||
'ldccav' => 'Cavol',
|
||||
'ldchol' => 'LDC Holding',
|
||||
'cepacpe' => 'CPE-CEPA',
|
||||
'dde' => 'Unité Dinde',
|
||||
'dpe' => 'DPE',
|
||||
'sl' => 'Saint-Laurent',
|
||||
'gdfroi' => 'Grand Froid',
|
||||
'ldcplb' => 'LDC PLB',
|
||||
'slela' => 'SLELA',
|
||||
'tpwiss' => 'TPWISS'
|
||||
'dde' => 'Unité Dinde',
|
||||
'dpe' => 'DPE',
|
||||
'sl' => 'Saint-Laurent',
|
||||
'gdfroi' => 'Grand Froid',
|
||||
'ldcplb' => 'LDC PLB',
|
||||
'slela' => 'SLELA',
|
||||
'tpwiss' => 'TPWISS'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ final class SellUnit extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'pce' => 'PCE',
|
||||
'kgm' => 'KGM',
|
||||
'colis' => 'COLIS',
|
||||
];
|
||||
}
|
||||
|
|
@ -33,8 +33,8 @@ final class SellUnit extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'pce' => __('Pièce'),
|
||||
'kgm' => __('Kg'),
|
||||
'colis' => __('Colis'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ final class SettingRegisterMode extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'public' => 'public',
|
||||
'public' => 'public',
|
||||
'salaries' => 'salaries',
|
||||
];
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ final class SettingRegisterMode extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'public' => __('Public'),
|
||||
'public' => __('Public'),
|
||||
'salaries' => __('Salaries'),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
41
app/Enums/StatsCustomerType.php
Normal file
41
app/Enums/StatsCustomerType.php
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self nbSalarie()
|
||||
* @method static self nbSalarieWithAccount()
|
||||
* @method static self membershipRate()
|
||||
*
|
||||
*/
|
||||
class StatsCustomerType extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'nbSalarie' => 1,
|
||||
'nbSalarieWithAccount' => 2,
|
||||
'membershipRate' => 3,
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Enum labels
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'nbSalarie' => trans('Nombre de salariés'),
|
||||
'nbSalarieWithAccount' => trans('Nombre de salariés ayant créé un compte'),
|
||||
'membershipRate' => trans('Taux d\'adhésion à la :appName', ['appName' => config('app.name')]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -5,21 +5,22 @@ namespace App\Enums;
|
|||
use Kwaadpepper\Enum\BaseEnum;
|
||||
|
||||
/**
|
||||
* @method static self nbActiveClients()
|
||||
* @method static self nbValidateCmd()
|
||||
* @method static self nbWaitingCmd()
|
||||
* @method static self nbCanceledCmd()
|
||||
* @method static self canceledRate()
|
||||
* @method static self orderFrequency()
|
||||
* @method static self nbActiveClients()
|
||||
* @method static self nbCmdWith7DayDelay()
|
||||
* @method static self nbCmdWith14DayDelay()
|
||||
* @method static self nbCmdWithMoreThan14DayDelay()
|
||||
* @method static self caHt()
|
||||
* @method static self canceledRate()
|
||||
* @method static self orderFrequency()
|
||||
* @method static self purchaseFrequency()
|
||||
* @method static self averageBasketHt()
|
||||
* @method static self averageProductCountPerOrder()
|
||||
* @method static self caHt()
|
||||
* @method static self caTtc()
|
||||
*
|
||||
*/
|
||||
class StatsType extends BaseEnum
|
||||
class StatsShopType extends BaseEnum
|
||||
{
|
||||
/**
|
||||
* Enum values
|
||||
|
|
@ -29,18 +30,19 @@ class StatsType extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'nbValidateCmd' => 1,
|
||||
'nbWaitingCmd' => 2,
|
||||
'nbCanceledCmd' => 3,
|
||||
'canceledRate' => 4,
|
||||
'orderFrequency' => 5,
|
||||
'nbActiveClients' => 6,
|
||||
'nbCmdWith7DayDelay' => 7,
|
||||
'nbCmdWith14DayDelay' => 8,
|
||||
'nbCmdWithMoreThan14DayDelay' => 9,
|
||||
'caHt' => 10,
|
||||
'averageBasketHt' => 11,
|
||||
'averageProductCountPerOrder' => 12
|
||||
'nbActiveClients' => 1,
|
||||
'nbValidateCmd' => 2,
|
||||
'nbWaitingCmd' => 3,
|
||||
'nbCanceledCmd' => 4,
|
||||
'nbCmdWith7DayDelay' => 5,
|
||||
'nbCmdWith14DayDelay' => 6,
|
||||
'canceledRate' => 7,
|
||||
'orderFrequency' => 8,
|
||||
'purchaseFrequency' => 9,
|
||||
'averageBasketHt' => 10,
|
||||
'averageProductCountPerOrder' => 11,
|
||||
'caHt' => 12,
|
||||
'caTtc' => 13,
|
||||
];
|
||||
}
|
||||
/**
|
||||
|
|
@ -51,18 +53,19 @@ class StatsType extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'nbValidateCmd' => trans('Nombre de commandes validées'),
|
||||
'nbWaitingCmd' => trans('Nombre de commandes en attente'),
|
||||
'nbCanceledCmd' => trans('Nombre de commandes annulées'),
|
||||
'canceledRate' => trans('Taux d\'abandon (en pourcentage)'),
|
||||
'orderFrequency' => trans('Fréquence d\'achat (en jours)'),
|
||||
'nbActiveClients' => trans('Nombre de clients actifs'),
|
||||
'nbValidateCmd' => trans('Commandes validées'),
|
||||
'nbWaitingCmd' => trans('Commandes en attente'),
|
||||
'nbCanceledCmd' => trans('Commandes annulées'),
|
||||
'nbCmdWith7DayDelay' => trans('Nombre de commandes à J+7'),
|
||||
'nbCmdWith14DayDelay' => trans('Nombre de commandes à J+14'),
|
||||
'nbCmdWithMoreThan14DayDelay' => trans('Nombre de commandes à J+15 et plus'),
|
||||
'caHt' => trans('Montant total HT'),
|
||||
'canceledRate' => trans('Taux d\'abandon'),
|
||||
'orderFrequency' => trans('Fréquence de commande'),
|
||||
'purchaseFrequency' => trans('Fréquence d\'achat'),
|
||||
'averageBasketHt' => trans('Prix du panier moyen'),
|
||||
'averageProductCountPerOrder' => trans('Nombre d\'article moyen par commande')
|
||||
'averageProductCountPerOrder' => trans('Nombre d\'article moyen par commande'),
|
||||
'caHt' => trans('Montant total HT'),
|
||||
'caTtc' => trans('Montant total TTC'),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -19,8 +19,8 @@ final class WeightUnit extends BaseEnum
|
|||
protected static function values(): array
|
||||
{
|
||||
return [
|
||||
'g' => 'G',
|
||||
'kg' => 'KG',
|
||||
'g' => 'G',
|
||||
'kg' => 'KG',
|
||||
'ton' => 'T',
|
||||
];
|
||||
}
|
||||
|
|
@ -33,8 +33,8 @@ final class WeightUnit extends BaseEnum
|
|||
protected static function labels(): array
|
||||
{
|
||||
return [
|
||||
'g' => __('Gramme'),
|
||||
'kg' => __('Kg'),
|
||||
'g' => __('Gramme'),
|
||||
'kg' => __('Kg'),
|
||||
'ton' => __('Tonne'),
|
||||
];
|
||||
}
|
||||
|
|
@ -48,9 +48,9 @@ final class WeightUnit extends BaseEnum
|
|||
public static function convert(): array
|
||||
{
|
||||
return [
|
||||
'G' => 0.001,
|
||||
'G' => 0.001,
|
||||
'KG' => 1,
|
||||
'T' => 1000,
|
||||
'T' => 1000,
|
||||
];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Http\Controllers\Bo;
|
||||
|
||||
use App\Enums\StatsCustomerType;
|
||||
use App\Enums\StatsShopType;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Carbon\Carbon;
|
||||
use App\Http\Requests\Bo\DashboardRequest;
|
||||
|
|
@ -17,16 +19,22 @@ class DashboardController extends Controller
|
|||
*/
|
||||
public function index(DashboardRequest $request)
|
||||
{
|
||||
$stats = [];
|
||||
$adhesion = StatsHelper::getMembershipPercentage();
|
||||
$previousDates = [];
|
||||
$statsShop = [];
|
||||
$statsCustomer = [];
|
||||
$prevDates = [];
|
||||
|
||||
if ($request->has('start') && $request->has('end')) {
|
||||
$start = new Carbon($request->start);
|
||||
$end = new Carbon($request->end);
|
||||
$previousDates = StatsHelper::getPreviousPeriod($start, $end);
|
||||
$stats = StatsHelper::getStats($start, $end);
|
||||
$start = new Carbon($request->start);
|
||||
$end = new Carbon($request->end);
|
||||
|
||||
$prevDates = StatsHelper::getPreviousPeriod($start, $end);
|
||||
$statsShop = StatsHelper::getStats(StatsShopType::toArray(), $start, $end);
|
||||
$statsCustomer = StatsHelper::getStats(StatsCustomerType::toArray(), $start, $end);
|
||||
}
|
||||
return view('bo.dashboard', compact('stats', 'adhesion', 'previousDates'));
|
||||
return view('bo.dashboard', compact(
|
||||
'prevDates',
|
||||
'statsShop',
|
||||
'statsCustomer',
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,25 +9,25 @@ use App\Models\Salarie;
|
|||
use Carbon\Carbon;
|
||||
use Carbon\CarbonPeriod;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use App\Enums\StatsType;
|
||||
|
||||
final class StatsHelper
|
||||
{
|
||||
/**
|
||||
* getStats
|
||||
*
|
||||
* @param array $statsType
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return array
|
||||
*/
|
||||
public static function getStats(Carbon $start, Carbon $end)
|
||||
public static function getStats(array $statsType, Carbon $start, Carbon $end)
|
||||
{
|
||||
$stats = [];
|
||||
foreach (StatsType::toArray() as $type) {
|
||||
foreach ($statsType as $type) {
|
||||
$stats[$type->value] = [
|
||||
'previous' => self::getPrevious(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
|
||||
'current' => self::{sprintf('get%s', ucfirst($type->getDefinition()))}($start, $end),
|
||||
'diff' => self::getDiff(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
|
||||
'current' => self::{sprintf('get%s', ucfirst($type->getDefinition()))}($start, $end),
|
||||
'diff' => self::getDiff(sprintf('get%s', ucfirst($type->getDefinition())), $start, $end),
|
||||
];
|
||||
}
|
||||
return $stats;
|
||||
|
|
@ -60,16 +60,72 @@ final class StatsHelper
|
|||
return self::{$method}($start, $end) - self::getPrevious($method, $start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all validated orders.
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return mixed
|
||||
*/
|
||||
private function getNbSalarie(Carbon $start, Carbon $end)
|
||||
{
|
||||
return self::getNumberCustomers($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all validated orders.
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return mixed
|
||||
*/
|
||||
private function getNbSalarieWithAccount(Carbon $start, Carbon $end)
|
||||
{
|
||||
return self::getNumberSalaries($start, $end);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the percentage of registered people / people with a generated code
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return integer
|
||||
*/
|
||||
public static function getNumberCustomers(Carbon $start, Carbon $end): int
|
||||
{
|
||||
return Customers::query()
|
||||
->whereDate('created_at', '>=', $start)
|
||||
->whereDate('created_at', '<=', $end)
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the percentage of registered people / people with a generated code
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return integer
|
||||
*/
|
||||
public static function getNumberSalaries(Carbon $start, Carbon $end): int
|
||||
{
|
||||
return Customers::query()
|
||||
->has('salarie')
|
||||
->whereDate('created_at', '>=', $start)
|
||||
->whereDate('created_at', '<=', $end)
|
||||
->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the percentage of registered people / people with a generated code
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return integer|float
|
||||
*/
|
||||
public static function getMembershipPercentage()
|
||||
public static function getMembershipRate(Carbon $start, Carbon $end): int
|
||||
{
|
||||
$employee = Salarie::count();
|
||||
$registered = Customers::has('salarie')->count();
|
||||
return round($registered / $employee * 100, 2);
|
||||
$registered = self::getNumberSalaries($start, $end);
|
||||
return round($registered / Salarie::count() * 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -164,6 +220,23 @@ final class StatsHelper
|
|||
return round($nbValidateCmd / $period, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the order frequency.
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return mixed
|
||||
*/
|
||||
private function getPurchaseFrequency(Carbon $start, Carbon $end)
|
||||
{
|
||||
$activeClients = self::getNbActiveClients($start, $end);
|
||||
if (!$activeClients) {
|
||||
return 0;
|
||||
}
|
||||
$nbValidateCmd = self::getNbValidateCmd($start, $end);
|
||||
return round($nbValidateCmd / $activeClients, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of active clients (ordered in the period).
|
||||
*
|
||||
|
|
@ -214,23 +287,6 @@ final class StatsHelper
|
|||
})->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number command where the collect day is > 14 days after the order.
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return mixed
|
||||
*/
|
||||
private function getNbCmdWithMoreThan14DayDelay(Carbon $start, Carbon $end)
|
||||
{
|
||||
return Order::with('timeslot')->whereHas('status', function (Builder $query) {
|
||||
$query->whereIn('id', [3, 4, 5, 6]);
|
||||
})->whereBetween('date', [$start, $end])->get()->filter(function (Order $order) {
|
||||
return Carbon::create($order->timeslot->day)
|
||||
->greaterThan(Carbon::create($order->date)->modify('+14 day'));
|
||||
})->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CA HT.
|
||||
*
|
||||
|
|
@ -254,6 +310,30 @@ final class StatsHelper
|
|||
return $totalCaHt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the CA TTC.
|
||||
*
|
||||
* @param \Carbon\Carbon $start
|
||||
* @param \Carbon\Carbon $end
|
||||
* @return mixed
|
||||
*/
|
||||
private function getCaTtc(Carbon $start, Carbon $end)
|
||||
{
|
||||
$orderedProducts = OrderLine::whereHas('order', function (Builder $query) use ($start, $end) {
|
||||
$query->whereHas('status', function (Builder $query) {
|
||||
$query->whereIn('id', [3, 4, 5, 6]);
|
||||
})->whereBetween('date', [$start->toDateString(), $end->toDateString()]);
|
||||
})->get();
|
||||
|
||||
$totalCaTtc = 0;
|
||||
$orderedProducts->map(function ($item) use (&$totalCaTtc) {
|
||||
$totalCaTtc += $item->total_ttc;
|
||||
});
|
||||
|
||||
return $totalCaTtc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the average basket HT.
|
||||
*
|
||||
|
|
@ -312,7 +392,7 @@ final class StatsHelper
|
|||
$diffDays = $start->copy()->diffInDays($end);
|
||||
return (object)[
|
||||
'start' => $start->copy()->subDays($diffDays + 1),
|
||||
'end' => $start->copy()->subDay()
|
||||
'end' => $start->copy()->subDay()
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,17 +98,17 @@ class Customers extends Authenticatable
|
|||
parent::toArray(),
|
||||
(array)$this->apiData
|
||||
))->intersectByKeys([
|
||||
'email' => '',
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'address' => '',
|
||||
'address2' => '',
|
||||
'postcode' => '',
|
||||
'email' => '',
|
||||
'firstname' => '',
|
||||
'lastname' => '',
|
||||
'address' => '',
|
||||
'address2' => '',
|
||||
'postcode' => '',
|
||||
'birth_date' => '',
|
||||
'city' => '',
|
||||
'country' => '',
|
||||
'opt_in' => '',
|
||||
'phone' => ''
|
||||
'city' => '',
|
||||
'country' => '',
|
||||
'opt_in' => '',
|
||||
'phone' => ''
|
||||
])->toArray();
|
||||
} else {
|
||||
return parent::toArray();
|
||||
|
|
|
|||
|
|
@ -5,40 +5,24 @@
|
|||
<h1 class="h2">Dashboard</h1>
|
||||
</div>
|
||||
<div class="container">
|
||||
<table class="table table-responsive table-bordered">
|
||||
<thead>
|
||||
<tr class="text-center table-secondary">
|
||||
<th scope="col">{{ __('Nombre de salariés') }}</th>
|
||||
<th scope="col">{{ __('Nombre de salariés inscrits') }}</th>
|
||||
<th scope="col">{{ __('Taux d\'adhésion') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="text-center table-light text-bold fw-semibold">
|
||||
<td>{{ number_format(App\Models\Salarie::count(), 0, ",", " ") }}</td>
|
||||
<td>{{ number_format(App\Models\Customers::has('salarie')->count(), 0, ",", " ") }}</td>
|
||||
<td>{{ number_format($adhesion, 2, ",", " ") }} %</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br />
|
||||
{{-- DATES --}}
|
||||
<form action="{{ route('bo.dashboard') }}">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label for="start">{{ __('Date de début') }}:</label>
|
||||
<input class="form-control" type="date" id="start" name="start" value="{{ request()->start }}" required/>
|
||||
@if (!empty($stats))
|
||||
<label for="previousStart">{{ __('Date de début de la période précédente') }}:</label>
|
||||
<input class="form-control" type="date" id="previousStart" name="previousStart" value="{{ $previousDates->start->toDateString() }}" aria-label="disabled input" disabled>
|
||||
@if (!empty($statsShop))
|
||||
<label for="previousStart">{{ __('Date de début de la période précédente') }}:</label>
|
||||
<input class="form-control" type="date" id="previousStart" name="previousStart" value="{{ $prevDates->start->toDateString() }}" aria-label="disabled input" disabled>
|
||||
@endif
|
||||
<br>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label for="end">{{ __('Date de fin') }}:</label>
|
||||
<input class="form-control" type="date" id="end" name="end" value="{{ request()->end }}" required/>
|
||||
@if (!empty($stats))
|
||||
<label for="previousEnd">{{ __('Date de fin de la période précédente') }}:</label>
|
||||
<input class="form-control" type="date" id="previousEnd" name="previousEnd" value="{{ $previousDates->end->toDateString() }}" aria-label="disabled input" disabled>
|
||||
@if (!empty($statsShop))
|
||||
<label for="previousEnd">{{ __('Date de fin de la période précédente') }}:</label>
|
||||
<input class="form-control" type="date" id="previousEnd" name="previousEnd" value="{{ $prevDates->end->toDateString() }}" aria-label="disabled input" disabled>
|
||||
@endif
|
||||
</div>
|
||||
<div class="col d-inline-flex align-items-center">
|
||||
|
|
@ -46,99 +30,154 @@
|
|||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<table class="table table-responsive table-bordered table-hover">
|
||||
<thead>
|
||||
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
|
||||
<th scope="col"></th>
|
||||
<th scope="col">{{ __('Période précédente') }}</th>
|
||||
<th scope="col">{{ __('Période actuelle') }}</th>
|
||||
<th scope="col">{{ __('Différence') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@if(!empty($stats))
|
||||
<tbody>
|
||||
@foreach ($stats as $k => $stat)
|
||||
<tr class="text-center">
|
||||
@if (
|
||||
$k === App\Enums\StatsType::nbWaitingCmd()->value ||
|
||||
$k === App\Enums\StatsType::nbCanceledCmd()->value ||
|
||||
$k === App\Enums\StatsType::canceledRate()->value ||
|
||||
$k === App\Enums\StatsType::orderFrequency()->value
|
||||
)
|
||||
<th @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsType::make($k)->label }}</th>
|
||||
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::canceledRate()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} %
|
||||
@break
|
||||
@case(App\Enums\StatsType::orderFrequency()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} {{ __('jours') }}
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['previous']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::canceledRate()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} %
|
||||
@break
|
||||
@case(App\Enums\StatsType::orderFrequency()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} {{ __('jours') }}
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['current']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] < 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::canceledRate()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} %</b>
|
||||
@break
|
||||
@case(App\Enums\StatsType::orderFrequency()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} {{ __('jours') }}</b>
|
||||
@break
|
||||
@default
|
||||
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
|
||||
@endswitch
|
||||
</td>
|
||||
@else
|
||||
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsType::make($k)->label }}</th>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::caHt()->value)
|
||||
@case(App\Enums\StatsType::averageBasketHt()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} €
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['previous']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::caHt()->value)
|
||||
@case(App\Enums\StatsType::averageBasketHt()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} €
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['current']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsType::caHt()->value)
|
||||
@case(App\Enums\StatsType::averageBasketHt()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} €</b>
|
||||
@break
|
||||
@default
|
||||
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
|
||||
@endswitch
|
||||
</td>
|
||||
@endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
@endif
|
||||
</table>
|
||||
{{-- CUSTOMERS DATA --}}
|
||||
@if(!empty($statsCustomer))
|
||||
<table class="table table-responsive table-bordered table-hover">
|
||||
<thead>
|
||||
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
|
||||
<th scope="col">{{-- keep empty --}}</th>
|
||||
<th scope="col">{{ __('Période précédente') }}</th>
|
||||
<th scope="col">{{ __('Période actuelle') }}</th>
|
||||
<th scope="col">{{ __('Différence') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($statsCustomer as $k => $stat)
|
||||
<tr class="text-center">
|
||||
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
{{ App\Enums\StatsCustomerType::make($k)->label }}
|
||||
</th>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsCustomerType::membershipRate()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} %
|
||||
@break
|
||||
@default
|
||||
{{ $stat['previous'] }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsCustomerType::membershipRate()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} %
|
||||
@break
|
||||
@default
|
||||
{{ $stat['current'] }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
|
||||
<b>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsCustomerType::membershipRate()->value)
|
||||
{{ number_format($stat['diff'], 2, ",", " ") }} %
|
||||
@break
|
||||
@default
|
||||
{{ $stat['diff'] }}
|
||||
@endswitch
|
||||
</b>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@endif
|
||||
@if(!empty($statsShop))
|
||||
<table class="table table-responsive table-bordered table-hover">
|
||||
<thead>
|
||||
<tr class="text-center bg-secondary bg-gradient bg-opacity-25">
|
||||
<th scope="col">{{-- keep empty --}}</th>
|
||||
<th scope="col">{{ __('Période précédente') }}</th>
|
||||
<th scope="col">{{ __('Période actuelle') }}</th>
|
||||
<th scope="col">{{ __('Différence') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($statsShop as $k => $stat)
|
||||
<tr class="text-center">
|
||||
@if (
|
||||
$k === App\Enums\StatsShopType::nbWaitingCmd()->value ||
|
||||
$k === App\Enums\StatsShopType::nbCanceledCmd()->value ||
|
||||
$k === App\Enums\StatsShopType::canceledRate()->value
|
||||
)
|
||||
<th @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsShopType::make($k)->label }}</th>
|
||||
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::canceledRate()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} %
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['previous']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] < 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::canceledRate()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} %
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['current']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] < 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::canceledRate()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} %</b>
|
||||
@break
|
||||
@default
|
||||
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
|
||||
@endswitch
|
||||
</td>
|
||||
@else
|
||||
<th @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>{{ App\Enums\StatsShopType::make($k)->label }}</th>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::caHt()->value)
|
||||
@case(App\Enums\StatsShopType::caTtc()->value)
|
||||
@case(App\Enums\StatsShopType::averageBasketHt()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} €
|
||||
@break
|
||||
@case(App\Enums\StatsShopType::orderFrequency()->value)
|
||||
{{ number_format($stat['previous'], 2, ",", " ") }} {{ __('jours') }}
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['previous']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="table-success" @else class="table-danger"@endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::caHt()->value)
|
||||
@case(App\Enums\StatsShopType::caTtc()->value)
|
||||
@case(App\Enums\StatsShopType::averageBasketHt()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} €
|
||||
@break
|
||||
@case(App\Enums\StatsShopType::orderFrequency()->value)
|
||||
{{ number_format($stat['current'], 2, ",", " ") }} {{ __('jours') }}
|
||||
@break
|
||||
@default
|
||||
{{ str_replace(".", ",", $stat['current']) }}
|
||||
@endswitch
|
||||
</td>
|
||||
<td @if ($stat['diff'] > 0) class="text-success table-success" @else class="text-danger table-danger" @endif>
|
||||
@switch($k)
|
||||
@case(App\Enums\StatsShopType::caHt()->value)
|
||||
@case(App\Enums\StatsShopType::caTtc()->value)
|
||||
@case(App\Enums\StatsShopType::averageBasketHt()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} €</b>
|
||||
@break
|
||||
@case(App\Enums\StatsShopType::orderFrequency()->value)
|
||||
<b>{{ number_format($stat['diff'], 2, ",", " ") }} {{ __('jours') }}</b>
|
||||
@break
|
||||
@default
|
||||
<b>{{ str_replace(".", ",", $stat['diff']) }}</b>
|
||||
@endswitch
|
||||
</td>
|
||||
@endif
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
@else
|
||||
<p>{{ __('Veuillez renseigner une période afin de visualiser les statistiques') }}</p>
|
||||
@endif
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -5,11 +5,8 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<!-- CSRF Token -->
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ __('Tableau de bord') }}</title>
|
||||
|
||||
<script src="https://cdn.ckeditor.com/ckeditor5/23.0.0/classic/ckeditor.js"></script>
|
||||
|
||||
<link rel="stylesheet" href="/b-o/css/app.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -25,14 +22,16 @@
|
|||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
|
||||
<div class="position-sticky pt-3">
|
||||
<ul class="nav flex-column mb-2">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{route('home')}}" target="_front">{{ __('Voir le site') }}</a>
|
||||
<a class="nav-link" href="{{ route('home') }}" target="_front">{{ __('Voir le site') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ route('bo.dashboard') }}">{{ __('Dashboard') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="accordion" id="accordionMenu">
|
||||
|
|
@ -76,7 +75,6 @@
|
|||
<i class="fas fa-warehouse"></i> {{ __('Catalogue') }}
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="collapseProduits" class="accordion-collapse collapse {{ ( request()->routeIs('bo.products*') || request()->routeIs('bo.ranges*') || request()->routeIs('bo.tags*') ) ? 'show' : '' }}" aria-labelledby="headingProduits" data-bs-parent="#accordionMenu">
|
||||
<div class="accordion-body">
|
||||
<ul class="nav flex-column mb-2">
|
||||
|
|
@ -95,7 +93,6 @@
|
|||
<i class="fas fa-cart-arrow-down"></i> {{ __('Merchandising') }}
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="collapseMerchandising" class="accordion-collapse collapse {{ ( request()->routeIs('bo.promotions*') || request()->routeIs('bo.products.starred') ) ? 'show' : '' }}" aria-labelledby="headingMerchandising" data-bs-parent="#accordionMenu">
|
||||
<div class="accordion-body">
|
||||
<ul class="nav flex-column mb-2">
|
||||
|
|
@ -114,7 +111,6 @@
|
|||
<i class="fas fa-cash-register"></i> {{ __('Commandes') }}
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="collapseOrders" class="accordion-collapse collapse {{ ( request()->routeIs('bo.orders*') ) ? 'show' : '' }}" aria-labelledby="headingOrders" data-bs-parent="#accordionMenu">
|
||||
<div class="accordion-body">
|
||||
<ul class="nav flex-column mb-2">
|
||||
|
|
@ -149,7 +145,6 @@
|
|||
<i class="fas fa-cog"></i> Règlages
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="collapseSettings" class="accordion-collapse collapse {{ ( request()->routeIs('bo.settings*') ) ? 'show' : '' }}" aria-labelledby="headingSettings" data-bs-parent="#accordionMenu">
|
||||
<div class="accordion-body">
|
||||
<ul class="nav flex-column mb-2">
|
||||
|
|
@ -167,7 +162,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
|
||||
@yield('content')
|
||||
</main>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue