@@ -0,0 +1,85 @@ | |||
<?php | |||
/** | |||
* Copyright distrib (2018) | |||
* | |||
* contact@opendistrib.net | |||
* | |||
* Ce logiciel est un programme informatique servant à aider les producteurs | |||
* à distribuer leur production en circuits courts. | |||
* | |||
* Ce logiciel est régi par la licence CeCILL soumise au droit français et | |||
* respectant les principes de diffusion des logiciels libres. Vous pouvez | |||
* utiliser, modifier et/ou redistribuer ce programme sous les conditions | |||
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA | |||
* sur le site "http://www.cecill.info". | |||
* | |||
* En contrepartie de l'accessibilité au code source et des droits de copie, | |||
* de modification et de redistribution accordés par cette licence, il n'est | |||
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons, | |||
* seule une responsabilité restreinte pèse sur l'auteur du programme, le | |||
* titulaire des droits patrimoniaux et les concédants successifs. | |||
* | |||
* A cet égard l'attention de l'utilisateur est attirée sur les risques | |||
* associés au chargement, à l'utilisation, à la modification et/ou au | |||
* développement et à la reproduction du logiciel par l'utilisateur étant | |||
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à | |||
* manipuler et qui le réserve donc à des développeurs et des professionnels | |||
* avertis possédant des connaissances informatiques approfondies. Les | |||
* utilisateurs sont donc invités à charger et tester l'adéquation du | |||
* logiciel à leurs besoins dans des conditions permettant d'assurer la | |||
* sécurité de leurs systèmes et ou de leurs données et, plus généralement, | |||
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité. | |||
* | |||
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez | |||
* pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
* termes. | |||
*/ | |||
namespace backend\controllers; | |||
use common\helpers\Price; | |||
use yii\filters\AccessControl; | |||
use yii\filters\VerbFilter; | |||
class DashboardAdminController extends BackendController | |||
{ | |||
/** | |||
* @inheritdoc | |||
*/ | |||
public function behaviors() | |||
{ | |||
return [ | |||
'access' => [ | |||
'class' => AccessControl::class, | |||
'rules' => [ | |||
[ | |||
'allow' => true, | |||
'roles' => ['@'], | |||
'matchCallback' => function ($rule, $action) { | |||
return $this->getUserModule() | |||
->getAuthorizationChecker() | |||
->isGrantedAsAdministrator($this->getUserCurrent()); | |||
} | |||
], | |||
], | |||
], | |||
]; | |||
} | |||
public function actionIndex() | |||
{ | |||
return $this->render('index', [ | |||
'countUsersOnline' => $this->getUserModule()->getRepository()->countUsersOnline(), | |||
'countTicketsAdminOpen' => $this->getTicketModule()->getRepository()->countTicketsAdminStatusOpen(), | |||
'countTicketsAdminUnread' => $this->getTicketModule()->getRepository()->countTicketsAdminUnreadByUser($this->getUserCurrent()), | |||
'amountProducerUnpaidInvoices' => '--', | |||
]); | |||
} | |||
public function actionAjaxAmountProducerInvoicesUnpaid() | |||
{ | |||
return Price::format($this->getProducerModule()->getDolibarrUtils()->getAmountProducerInvoicesUnpaid()); | |||
} | |||
} |
@@ -0,0 +1,166 @@ | |||
<?php | |||
$this->setTitle('Tableau de bord'); | |||
?> | |||
<div class="dashboard-admin-index"> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-aqua"> | |||
<div class="inner"> | |||
<h3><?= $countUsersOnline ?></h3> | |||
<p>En ligne</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-wifi"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('online-admin/index') ?>" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-green"> | |||
<div class="inner"> | |||
<h3><?= 'Oui' ?></h3> | |||
<p>Support activé</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-phone"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('support-admin/index') ?>" class="small-box-footer"> | |||
Désactiver <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-<?= $countTicketsAdminUnread ? 'green' : 'blue' ?>"> | |||
<div class="inner"> | |||
<h3><?= $countTicketsAdminOpen ?></h3> | |||
<p>Tickets</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-comments"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('support-admin/index') ?>" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-green"> | |||
<div class="inner"> | |||
<h3><?= '1230 €' ?></h3> | |||
<p>Total factures producteurs mois en cours</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-euro"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('producer-admin/index') ?>" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-red"> | |||
<div class="inner"> | |||
<h3 id="amount-producer-invoices-unpaid"><?= $amountProducerUnpaidInvoices ?></h3> | |||
<p>Montant factures impayées</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-euro"></i> | |||
</div> | |||
<a target="_blank" href="<?= Yii::$app->parameterBag->get('dolibarrUrl') ?>compta/facture/list.php?leftmenu=customers_bills_notpaid&search_status=1" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-yellow"> | |||
<div class="inner"> | |||
<h3><?= '127 000 €' ?></h3> | |||
<p>CA producteurs 30 derniers jours</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-line-chart"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('stats-admin/turnover') ?>" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-yellow"> | |||
<div class="inner"> | |||
<h3><?= '141' ?></h3> | |||
<p>Commandes clients / jour</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-line-chart"></i> | |||
</div> | |||
<a href="<?= Yii::$app->urlManager->createUrl('stats-admin/turnover') ?>" class="small-box-footer"> | |||
Voir <i class="fa fa-arrow-circle-right"></i> | |||
</a> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-aqua"> | |||
<div class="inner"> | |||
<h3>43</h3> | |||
<p>Producteurs actifs sur les 3 derniers mois</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-th-list"></i> | |||
</div> | |||
<div class="small-box-footer"> </div> | |||
</div> | |||
</div> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-aqua"> | |||
<div class="inner"> | |||
<h3>357</h3> | |||
<p>Points de vente actifs sur les 3 derniers mois</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-map-marker"></i> | |||
</div> | |||
<div class="small-box-footer"> </div> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="row"> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-aqua"> | |||
<div class="inner"> | |||
<h3>3 865</h3> | |||
<p>Clients actifs sur les 3 derniers mois</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-users"></i> | |||
</div> | |||
<div class="small-box-footer"> </div> | |||
</div> | |||
</div> | |||
<div class="col-lg-6 col-xs-6"> | |||
<div class="small-box bg-aqua"> | |||
<div class="inner"> | |||
<h3>32</h3> | |||
<p>Inscriptions utilisateurs des 7 derniers jours</p> | |||
</div> | |||
<div class="icon"> | |||
<i class="fa fa-user-plus"></i> | |||
</div> | |||
<div class="small-box-footer"> </div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> |
@@ -120,6 +120,12 @@ $isUserCurrentGrantedAsProducer = $userModule->getAuthorizationChecker()->isGran | |||
// Administration | |||
['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => $isUserCurrentGrantedAsAdministrator], | |||
[ | |||
'label' => 'Tableau de bord', | |||
'icon' => 'dashboard', | |||
'url' => ['dashboard-admin/index'], | |||
'visible' => $isUserCurrentGrantedAsAdministrator, | |||
], | |||
[ | |||
'label' => 'En ligne', | |||
'icon' => 'wifi', |
@@ -1829,50 +1829,65 @@ body.skin-black .content-wrapper .alert .close:hover { | |||
opacity: 1; | |||
} | |||
/* line 301, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .small-box h3 { | |||
font-size: 28px; | |||
font-family: 'Source Sans Pro',sans-serif; | |||
} | |||
/* line 306, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .small-box .icon { | |||
top: -2px; | |||
} | |||
/* line 310, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .small-box .small-box-footer { | |||
color: white; | |||
padding-top: 6px; | |||
padding-bottom: 2px; | |||
} | |||
/* line 319, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout h4 .fa { | |||
margin-right: 7px; | |||
} | |||
/* line 304, ../sass/_adminlte.scss */ | |||
/* line 322, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout a { | |||
color: white; | |||
} | |||
/* line 307, ../sass/_adminlte.scss */ | |||
/* line 325, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .callout .btn { | |||
color: #333; | |||
text-decoration: none; | |||
} | |||
/* line 314, ../sass/_adminlte.scss */ | |||
/* line 332, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th { | |||
font-size: 13px; | |||
} | |||
/* line 317, ../sass/_adminlte.scss */ | |||
/* line 335, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table th.column-actions, body.skin-black .content-wrapper .table td.column-actions { | |||
width: 172px; | |||
text-align: right; | |||
} | |||
/* line 321, ../sass/_adminlte.scss */ | |||
/* line 339, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .table td.text-small, body.skin-black .content-wrapper .table th.text-small { | |||
font-size: 12px; | |||
} | |||
/* line 326, ../sass/_adminlte.scss */ | |||
/* line 344, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > .active > a, body.skin-black .content-wrapper .pagination > .active > span, body.skin-black .content-wrapper .pagination > .active > a:hover, body.skin-black .content-wrapper .pagination > .active > span:hover, body.skin-black .content-wrapper .pagination > .active > a:focus, body.skin-black .content-wrapper .pagination > .active > span:focus { | |||
background-color: #F39C12; | |||
border: solid 1px #F39C12; | |||
color: white; | |||
} | |||
/* line 332, ../sass/_adminlte.scss */ | |||
/* line 350, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a, body.skin-black .content-wrapper .pagination > li > span { | |||
color: #F39C12; | |||
} | |||
/* line 334, ../sass/_adminlte.scss */ | |||
/* line 352, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .pagination > li > a:hover, body.skin-black .content-wrapper .pagination > li > span:hover { | |||
color: #c87f0a; | |||
} | |||
/* line 339, ../sass/_adminlte.scss */ | |||
/* line 357, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .submenu { | |||
margin-bottom: 25px; | |||
} | |||
/* line 343, ../sass/_adminlte.scss */ | |||
/* line 361, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .form-actions { | |||
position: fixed; | |||
bottom: 0; | |||
@@ -1886,59 +1901,59 @@ body.skin-black .content-wrapper .form-actions { | |||
z-index: 10; | |||
border-top: solid 1px #e0e0e0; | |||
} | |||
/* line 356, ../sass/_adminlte.scss */ | |||
/* line 374, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .form-actions a, body.skin-black .content-wrapper .form-actions button { | |||
margin-left: 10px; | |||
} | |||
/* line 361, ../sass/_adminlte.scss */ | |||
/* line 379, ../sass/_adminlte.scss */ | |||
body.skin-black .content-wrapper .form-buttons { | |||
margin-top: 25px; | |||
text-align: right; | |||
} | |||
/* line 368, ../sass/_adminlte.scss */ | |||
/* line 386, ../sass/_adminlte.scss */ | |||
body.skin-black .main-footer a { | |||
color: #F39C12; | |||
} | |||
/* line 373, ../sass/_adminlte.scss */ | |||
/* line 391, ../sass/_adminlte.scss */ | |||
body.skin-black .gridview-pagesize { | |||
float: right; | |||
margin-bottom: 8px; | |||
} | |||
/* line 378, ../sass/_adminlte.scss */ | |||
/* line 396, ../sass/_adminlte.scss */ | |||
body.skin-black #yii-debug-toolbar { | |||
bottom: 64px; | |||
} | |||
/* line 383, ../sass/_adminlte.scss */ | |||
/* line 401, ../sass/_adminlte.scss */ | |||
body.login-page { | |||
background: none; | |||
background-color: white; | |||
} | |||
/* line 387, ../sass/_adminlte.scss */ | |||
/* line 405, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo { | |||
text-align: center; | |||
font-family: 'highvoltageregular'; | |||
} | |||
/* line 391, ../sass/_adminlte.scss */ | |||
/* line 409, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo img { | |||
width: 50px; | |||
} | |||
/* line 396, ../sass/_adminlte.scss */ | |||
/* line 414, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary { | |||
background-color: #F39C12; | |||
border-color: #F39C12; | |||
padding: 5px 10px; | |||
} | |||
/* line 401, ../sass/_adminlte.scss */ | |||
/* line 419, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary:active { | |||
background-color: #f4a62a; | |||
border-color: #F39C12; | |||
} | |||
/* line 407, ../sass/_adminlte.scss */ | |||
/* line 425, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a { | |||
color: #F39C12; | |||
} | |||
/* line 409, ../sass/_adminlte.scss */ | |||
/* line 427, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a:hover { | |||
color: #f4a62a; | |||
} |
@@ -57,18 +57,28 @@ $(document).ready(function () { | |||
opendistrib_features_index(); | |||
opendistrib_point_sale_form(); | |||
opendistrib_check_all_checkboxes(); | |||
opendistrib_dashboard_admin_invoices_unpaid(); | |||
}); | |||
var UrlManager = { | |||
getBaseUrl: function () { | |||
return $('meta[name=baseurl]').attr('content') + '/'; | |||
}, | |||
getBaseUrlAbsolute: function () { | |||
return $('meta[name=baseurl-absolute]').attr('content') + '/'; | |||
} | |||
}; | |||
function opendistrib_dashboard_admin_invoices_unpaid() { | |||
var selector = '#amount-producer-invoices-unpaid'; | |||
$(selector).click(function() { | |||
$(this).html('<i class="fa fa-spinner"></i>'); | |||
$.get(UrlManager.getBaseUrl() + 'dashboard-admin/ajax-amount-producer-invoices-unpaid', {}, function(result) { | |||
$(selector).html(result); | |||
}); | |||
}); | |||
} | |||
function opendistrib_check_all_checkboxes() { | |||
$('.check-all-checkboxes').change(function() { | |||
var selector = $(this).data('selector'); |
@@ -296,6 +296,24 @@ body.skin-black { | |||
} | |||
} | |||
} | |||
.small-box { | |||
h3 { | |||
font-size: 28px; | |||
font-family: 'Source Sans Pro',sans-serif; | |||
} | |||
.icon { | |||
top: -2px; | |||
} | |||
.small-box-footer { | |||
color: white; | |||
padding-top: 6px; | |||
padding-bottom: 2px; | |||
} | |||
} | |||
.callout { | |||
h4 .fa { |
@@ -0,0 +1,4 @@ | |||
.dashboard-admin-index { | |||
} |
@@ -1553,4 +1553,5 @@ a.btn, button.btn { | |||
@import "online-admin/_index.scss"; | |||
@import "feature-admin/_index.scss"; | |||
@import "setting/_form.scss"; | |||
@import "dashboard-admin/_index.scss" ; | |||
@import "_responsive.scss" ; |
@@ -30,17 +30,52 @@ class DolibarrProducerUtils extends AbstractManager | |||
return $invoicesArray; | |||
} | |||
public function countDolibarrProducerInvoicesUnpaid(Producer $producer): int | |||
public function getDolibarrProducerInvoicesUnpaid(Producer $producer): array | |||
{ | |||
$count = 0; | |||
$unpaidInvoicesArray = []; | |||
$invoicesArray = $this->getDolibarrProducerInvoices($producer); | |||
foreach($invoicesArray as $invoice) { | |||
if($invoice['remaintopay'] > 0) { | |||
$count ++; | |||
$unpaidInvoicesArray[] = $invoice; | |||
} | |||
} | |||
return $count; | |||
return $unpaidInvoicesArray; | |||
} | |||
public function countDolibarrProducerInvoicesUnpaid(Producer $producer): int | |||
{ | |||
return count($this->getDolibarrProducerInvoicesUnpaid($producer)); | |||
} | |||
public function getDolibarrInvoicesUnpaid() | |||
{ | |||
$unpaidInvoicesArray = []; | |||
$producersArray = $this->producerRepository->findProducersActive(); | |||
foreach($producersArray as $producer) { | |||
$unpaidInvoicesArray = array_merge( | |||
$unpaidInvoicesArray, | |||
$this->getDolibarrProducerInvoicesUnpaid($producer) | |||
); | |||
} | |||
//die('test : '.count($unpaidInvoicesArray)); | |||
return $unpaidInvoicesArray; | |||
} | |||
public function getAmountProducerInvoicesUnpaid() | |||
{ | |||
$amount = 0; | |||
$unpaidInvoicesArray = $this->getDolibarrInvoicesUnpaid(); | |||
foreach($unpaidInvoicesArray as $unpaidInvoice) { | |||
$amount += $unpaidInvoice['remaintopay']; | |||
} | |||
return $amount; | |||
} | |||
public function generateDolibarrProducerInvoice(Producer $producer) |
@@ -291,4 +291,9 @@ class UserRepository extends AbstractRepository | |||
{ | |||
return count($this->findUsersWithStatusUserAndOnline()); | |||
} | |||
public function countUsersOnline(): int | |||
{ | |||
return $this->countUsersStatusUserOnline() + $this->countUsersStatusProducerOnline(); | |||
} | |||
} |