@@ -0,0 +1,9 @@ | |||
<?php | |||
return [ | |||
'components' => [ | |||
'view' => [ | |||
'class' => 'common\components\ViewBackend', | |||
], | |||
], | |||
]; |
@@ -83,6 +83,7 @@ class DashboardController extends BackendController | |||
'pointsSaleCount' => $this->getPointSaleContainer()->getRepository()->countPointSales(), | |||
'distributionsArray' => $this->getDistributionContainer()->getRepository()->findDistributionsDashboard(), | |||
'ordersArray' => $this->getOrderContainer()->getRepository()->findOrdersDashboard(), | |||
'subscriptionsLatestAddedArray' => $this->getSubscriptionContainer()->getRepository()->findSubscriptionsLatestAdded() | |||
]); | |||
} | |||
} |
@@ -418,6 +418,8 @@ class DocumentController extends BackendController | |||
$userManager = $this->getUserManager(); | |||
$documentManager = $this->getDocumentManager(); | |||
$orderManager = $this->getOrderManager(); | |||
$producerManager = $this->getProducerManager(); | |||
$producerCurrent = $this->getProducerCurrent(); | |||
\Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | |||
@@ -460,8 +462,13 @@ class DocumentController extends BackendController | |||
$json['delivery_note_create_array'] = $this->initDeliveryNoteArray('create', $deliveryNotesCreateArray); | |||
$json['delivery_note_update_array'] = $this->initDeliveryNoteArray('update', $deliveryNotesUpdateArray); | |||
$json['orders_create_array'] = $this->initOrdersArray($orderManager->findOrdersByUserNotInvoiced($user)); | |||
$json['orders_update_array'] = $document ? $this->initOrdersArray($orderManager->findOrdersByUserAndInvoice($user, $document)) : []; | |||
$json['orders_create_array'] = []; | |||
$json['orders_update_array'] = []; | |||
if(!$producerManager->getConfig('option_invoice_only_based_on_delivery_notes')) { | |||
$json['orders_create_array'] = $this->initOrdersArray($orderManager->findOrdersByUserNotInvoiced($user)); | |||
$json['orders_update_array'] = $document ? $this->initOrdersArray($orderManager->findOrdersByUserAndInvoice($user, $document)) : []; | |||
} | |||
} | |||
if ($classDocument == 'DeliveryNote') { |
@@ -38,19 +38,18 @@ | |||
namespace backend\controllers; | |||
use common\helpers\Ajax; | |||
use common\helpers\Alwaysdata; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use Yii; | |||
use yii\helpers\Html; | |||
use yii\web\NotFoundHttpException; | |||
use yii\filters\VerbFilter; | |||
use yii\filters\AccessControl; | |||
use yii\data\ActiveDataProvider; | |||
/** | |||
* UserController implements the CRUD actions for User model. | |||
*/ | |||
class ProducerAdminController extends BackendController | |||
{ | |||
public function behaviors() | |||
@@ -160,14 +159,12 @@ class ProducerAdminController extends BackendController | |||
$producer = $this->findProducer($id); | |||
if($producer->contact_email) { | |||
Alwaysdata::createProducerSiteShortUrlRedirection($producer); | |||
Alwaysdata::createProducerEmailRedirection($producer); | |||
Yii::$app->alwaysdataClient->initRedirections($producer); | |||
return Ajax::responseSuccess('Redirections initialisées chez Alwaysdata'); | |||
} | |||
else { | |||
$this->addFlash('error', "L'adresse email de contact du producteur n'est pas définie."); | |||
return Ajax::responseError("L'adresse email de contact du producteur n'est pas définie"); | |||
} | |||
return $this->redirect(['index']); | |||
} | |||
public function actionDolibarr(int $id) | |||
@@ -176,13 +173,11 @@ class ProducerAdminController extends BackendController | |||
$producer = $this->findProducer($id); | |||
if($producer->dolibarr_socid) { | |||
$producerManager->generateDolibarrProducerInvoice($producer); | |||
$this->setFlash('success', "Facture générée sur Dolibarr pour le producteur <strong>".$producer->name."</strong>"); | |||
return Ajax::responseSuccess("Facture générée sur Dolibarr pour le producteur \"".Html::encode($producer->name)."\""); | |||
} | |||
else { | |||
$this->setFlash('error', "Dolibarr : l'id user du producteur doit être défini"); | |||
return Ajax::responseError("Dolibarr : l'id user du producteur doit être défini"); | |||
} | |||
return $this->redirect(['index']); | |||
} | |||
public function actionUserTransfer($fromProducerId, $toProducerId, $withOrders = 1) |
@@ -171,4 +171,22 @@ class ProducerController extends BackendController | |||
return $this->redirect(\Yii::$app->request->referrer); | |||
} | |||
public function actionPagesize() | |||
{ | |||
$producerCurrent = $this->getProducerCurrent(); | |||
$request = Yii::$app->request; | |||
if($request->isPost) { | |||
$entity = $request->post('entity'); | |||
$pageSize = $request->post('pagesize'); | |||
$this->getProducerContainer()->getProducerPageSizer() | |||
->updatePagesize($producerCurrent, $entity, $pageSize); | |||
} | |||
$referer = strtok(Yii::$app->request->referrer, "?"); | |||
return $this->redirect($referer); | |||
} | |||
} |
@@ -66,61 +66,25 @@ class StatsController extends BackendController | |||
} | |||
/** | |||
* Affiche les statistiques de l'année avec le CA réalisé par mois. | |||
* Affiche le CA réalisé par mois sur une année donnée | |||
*/ | |||
public function actionIndex() | |||
public function actionIndex(int $year = null) | |||
{ | |||
/* | |||
* Volume de commande de l'année passée (par mois) | |||
*/ | |||
$dateStart = date('Y-m-d', time() - 60 * 60 * 24 * 365); | |||
$dateEnd = date('Y-m-d', time() + 60 * 60 * 24 * 31); | |||
$data = []; | |||
// labels | |||
$dataLabels = []; | |||
$start = new DateTime($dateStart); | |||
$interval = new DateInterval('P1M'); | |||
$end = new DateTime($dateEnd); | |||
$period = new DatePeriod($start, $interval, $end); | |||
foreach ($period as $date) { | |||
$month = date('m/Y', $date->getTimestamp()); | |||
$dataLabels[] = $month; | |||
$res = Yii::$app->db->createCommand("SELECT SUM(product_order.price * product_order.quantity) AS total | |||
FROM `order`, product_order, distribution | |||
WHERE distribution.id_producer = :id_producer | |||
AND `order`.id_distribution = distribution.id | |||
AND `order`.id = product_order.id_order | |||
AND distribution.date >= :date_start | |||
AND distribution.date <= :date_end | |||
") | |||
->bindValue(':id_producer', GlobalParam::getCurrentProducerId()) | |||
->bindValue(':date_start', date('Y-m-', $date->getTimestamp()) . '01') | |||
->bindValue(':date_end', date('Y-m-', $date->getTimestamp()) . '31') | |||
->queryOne(); | |||
if ($res['total']) { | |||
$data[$month] = $res['total']; | |||
} else { | |||
$data[$month] = 0; | |||
} | |||
$producerManager = $this->getProducerManager(); | |||
$producerCurrent = $this->getProducerCurrent(); | |||
if(!$year) { | |||
$year = date('Y'); | |||
} | |||
// création d'un tableau sans index car chart.js n'accepte pas les index | |||
$dataNoIndex = []; | |||
foreach ($data as $key => $val) { | |||
$dataNoIndex[] = round($val, 2); | |||
} | |||
$yearsWithTurnoverArray = $producerManager->getYearsWithTurnover($producerCurrent); | |||
$dataChartTurnover = $producerManager->getDatasChartTurnoverStatistics($producerCurrent, $year); | |||
return $this->render('index', [ | |||
'dataLabels' => $dataLabels, | |||
'data' => $dataNoIndex, | |||
'yearCurrent' => $year, | |||
'dataLabels' => $dataChartTurnover['labels'], | |||
'data' => $dataChartTurnover['data'], | |||
'yearsWithTurnoverArray' => $yearsWithTurnoverArray | |||
]); | |||
} | |||
@@ -36,11 +36,18 @@ pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
use common\helpers\GlobalParam; | |||
use common\logic\Order\Order\Model\Order; | |||
use common\logic\Order\Order\Wrapper\OrderManager; | |||
use common\logic\Producer\Producer\Wrapper\ProducerManager; | |||
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager; | |||
use common\logic\User\User\Wrapper\UserManager; | |||
use yii\helpers\Html ; | |||
$userManager = UserManager::getInstance(); | |||
$orderManager = OrderManager::getInstance(); | |||
$subscriptionManager = SubscriptionManager::getInstance(); | |||
$producerManager = ProducerManager::getInstance(); | |||
$this->setTitle('Tableau de bord'); | |||
@@ -125,6 +132,52 @@ $this->setTitle('Tableau de bord'); | |||
<div class="clr"></div> | |||
<?php if(is_array($subscriptionsLatestAddedArray) && count($subscriptionsLatestAddedArray)): ?> | |||
<div id="last-subscriptions"> | |||
<div class="panel panel-default"> | |||
<div class="panel-heading"> | |||
<h3 class="panel-title"> | |||
Derniers abonnements créés | |||
</h3> | |||
</div> | |||
<div class="panel-body"> | |||
<table class="table table-condensed table-bordered"> | |||
<thead> | |||
<tr> | |||
<th>Date</th> | |||
<th>Client</th> | |||
<th>Point de vente</th> | |||
<th>Produits</th> | |||
<th>Jours</th> | |||
<th>Période</th> | |||
<th></th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
<?php foreach($subscriptionsLatestAddedArray as $subscription): ?> | |||
<tr> | |||
<td><?= date('d/m/Y à H:i', strtotime($subscription->created_at)); ?></td> | |||
<td><?= $userManager->getUsername($subscription->user); ?></td> | |||
<td><?= Html::encode($subscription->pointSale->name); ?></td> | |||
<td><?= $subscriptionManager->getProductsListAsHtml($subscription); ?></td> | |||
<td><?= $subscriptionManager->getDaysAsHtml($subscription); ?></td> | |||
<td><?= $subscriptionManager->getPeriodAsHtml($subscription); ?></td> | |||
<td> | |||
<a href="<?= $this->getUrlManager()->createUrl(['subscription/update', 'id' => $subscription->id]) ?>" class="btn btn-default"> | |||
<span class="glyphicon glyphicon-pencil"></span> | |||
</a> | |||
</td> | |||
</tr> | |||
<?php endforeach; ?> | |||
</tbody> | |||
</table> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="clr"></div> | |||
<?php endif; ?> | |||
<!-- dernières commandes --> | |||
<?php if(is_array($ordersArray) && count($ordersArray)): ?> | |||
<div id="last-orders" class=""> |
@@ -475,7 +475,7 @@ $this->setPageTitle('Distributions') ; | |||
</div> | |||
<div class="wrapper-button-dropdown"> | |||
<button type="button" class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |||
<button type="button" :class="'btn btn-xs dropdown-toggle ' + (countDocuments(order) ? 'btn-success' : 'btn-default')" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> | |||
<span class="glyphicon glyphicon-file"></span> <template v-if="countDocuments(order)">{{ countDocuments(order) }}</template> <span class="caret"></span> | |||
</button> | |||
<ul class="dropdown-menu"> |
@@ -49,220 +49,167 @@ $this->addBreadcrumb($this->getTitle()) ; | |||
$this->addButton(['label' => 'Nouveau producteur <span class="glyphicon glyphicon-plus"></span>', 'url' => 'producer-admin/create', 'class' => 'btn btn-primary']) ; | |||
?> | |||
<div class="producer-admin-index"> | |||
<div class="alert alert-info"> | |||
Facturé le mois dernier : <strong><?= $sumPrices ?> €</strong><br /> | |||
</div> | |||
<?= GridView::widget([ | |||
'dataProvider' => $dataProviderProducer, | |||
'columns' => [ | |||
[ | |||
'attribute' => 'active', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
$html = '' ; | |||
if($model->active) { | |||
$html .= '<span class="label label-success">En ligne</span>' ; | |||
} | |||
else { | |||
$html .= '<span class="label label-danger">Hors-ligne</span>' ; | |||
} | |||
<div class="alert alert-info"> | |||
Facturé le mois dernier : <strong><?= $sumPrices ?> €</strong><br /> | |||
</div> | |||
<?= GridView::widget([ | |||
'dataProvider' => $dataProviderProducer, | |||
'columns' => [ | |||
[ | |||
'attribute' => 'active', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
$html = '' ; | |||
if($model->active) { | |||
$html .= '<span class="label label-success">En ligne</span>' ; | |||
} | |||
else { | |||
$html .= '<span class="label label-danger">Hors-ligne</span>' ; | |||
} | |||
if(strlen($model->code)) | |||
{ | |||
$html .= ' <span class="glyphicon glyphicon-lock" data-toggle="tooltip" data-placement="bottom" data-original-title="'.Html::encode($model->code).'"></span>' ; | |||
} | |||
return $html ; | |||
} | |||
], | |||
'name', | |||
/*[ | |||
'attribute' => 'date_creation', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
return date('d/m/Y', strtotime($model->date_creation)) ; | |||
} | |||
],*/ | |||
/*[ | |||
'attribute' => 'Lieu', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
return Html::encode($model->city.' ('.$model->postcode.')') ; | |||
} | |||
],*/ | |||
/*[ | |||
'attribute' => 'Utilisateurs', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
if(!$model->userProducer || !count($model->userProducer)) | |||
{ | |||
return 'Aucun utilisateur' ; | |||
} | |||
else { | |||
$users = count($model->userProducer).' client' ; | |||
if(count($model->userProducer) > 1) { | |||
$users .= 's' ; | |||
if(strlen($model->code)) | |||
{ | |||
$html .= ' <span class="glyphicon glyphicon-lock" data-toggle="tooltip" data-placement="bottom" data-original-title="'.Html::encode($model->code).'"></span>' ; | |||
} | |||
return $users ; | |||
} | |||
} | |||
],*/ | |||
[ | |||
'attribute' => 'Contact', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
if(!isset($model->user) || (isset($model->user) && count($model->user) == 0)) | |||
{ | |||
return 'Aucun contact' ; | |||
return $html ; | |||
} | |||
else { | |||
foreach($model->user as $u) | |||
], | |||
'name', | |||
[ | |||
'attribute' => 'Contact', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
if(!isset($model->user) || (isset($model->user) && count($model->user) == 0)) | |||
{ | |||
if($u->status == User::STATUS_PRODUCER) | |||
return 'Aucun contact' ; | |||
} | |||
else { | |||
foreach($model->user as $u) | |||
{ | |||
return Html::encode($u->lastname.' '.$u->name) | |||
.'<br />'.Html::encode($u->email) | |||
.'<br />'.Html::encode($u->phone) ; | |||
if($u->status == User::STATUS_PRODUCER) | |||
{ | |||
return Html::encode($u->lastname.' '.$u->name) | |||
.'<br />'.Html::encode($u->email) | |||
.'<br />'.Html::encode($u->phone) ; | |||
} | |||
} | |||
} | |||
} | |||
} | |||
], | |||
/*[ | |||
'attribute' => 'Prix libre', | |||
'label' => 'Prix libre', | |||
'format' => 'raw', | |||
'value' => function($model) { | |||
if(is_null($model->free_price)) { | |||
return '' ; | |||
} | |||
else { | |||
$str = ''; | |||
if($model->isBillingTypeFreePrice()) { | |||
$str .= '<strong>'; | |||
} | |||
$str .= $model->getFreePrice(); | |||
if($model->isBillingTypeFreePrice()) { | |||
$str .= '</strong>'; | |||
} | |||
return $str; | |||
} | |||
} | |||
],*/ | |||
[ | |||
'label' => 'Facturation', | |||
'format' => 'raw', | |||
'value' => function($producer) use ($producerManager) { | |||
$str = ''; | |||
$str .= '<ul style="margin: 0px;padding-left: 15px;">'; | |||
], | |||
[ | |||
'label' => 'Facturation', | |||
'format' => 'raw', | |||
'value' => function($producer) use ($producerManager) { | |||
$isBillingFrequencyMonthly = $producerManager->isBillingFrequencyMonthly($producer); | |||
$summaryMonthly = $producerManager->getSummaryAmountsToBeBilled($producer, 'Mois dernier', 1); | |||
$isBillingFrequencyQuaterly = $producerManager->isBillingFrequencyQuarterly($producer); | |||
$summaryQuaterly = $producerManager->getSummaryAmountsToBeBilled($producer, '3 derniers mois', 3); | |||
$isBillingFrequencyBiannual = $producerManager->isBillingFrequencyBiannual($producer); | |||
$summaryBiannual = $producerManager->getSummaryAmountsToBeBilled($producer, '6 derniers mois', 6); | |||
$str = ''; | |||
$str .= '<ul style="margin: 0px;padding-left: 15px;">'; | |||
$isBillingFrequencyMonthly = $producerManager->isBillingFrequencyMonthly($producer); | |||
$summaryMonthly = $producerManager->getSummaryAmountsToBeBilled($producer, 'Mois dernier', 1); | |||
$isBillingFrequencyQuaterly = $producerManager->isBillingFrequencyQuarterly($producer); | |||
$summaryQuaterly = $producerManager->getSummaryAmountsToBeBilled($producer, '3 derniers mois', 3); | |||
$isBillingFrequencyBiannual = $producerManager->isBillingFrequencyBiannual($producer); | |||
$summaryBiannual = $producerManager->getSummaryAmountsToBeBilled($producer, '6 derniers mois', 6); | |||
if(($isBillingFrequencyMonthly && $summaryMonthly) | |||
|| ($isBillingFrequencyQuaterly && $summaryQuaterly) | |||
|| ($isBillingFrequencyBiannual && $summaryBiannual)) { | |||
$str .= '<li>'; | |||
if ($isBillingFrequencyMonthly && $summaryMonthly) { | |||
$str .= $summaryMonthly; | |||
} elseif ($isBillingFrequencyQuaterly && $summaryQuaterly) { | |||
$str .= $summaryQuaterly; | |||
} elseif ($isBillingFrequencyBiannual && $summaryBiannual) { | |||
$str .= $summaryBiannual; | |||
} | |||
if(($isBillingFrequencyMonthly && $summaryMonthly) | |||
|| ($isBillingFrequencyQuaterly && $summaryQuaterly) | |||
|| ($isBillingFrequencyBiannual && $summaryBiannual)) { | |||
if ($producer->option_billing_reduction && strlen($str)) { | |||
$str .= '<br /><u>Avec réduction</u> : '; | |||
if ($producer->option_billing_reduction_percentage) { | |||
$str .= ' ' . $producer->option_billing_reduction_percentage . ' %'; | |||
} | |||
} | |||
$str .= '</li>'; | |||
$str .= '<li>'; | |||
if ($isBillingFrequencyMonthly && $summaryMonthly) { | |||
$str .= $summaryMonthly; | |||
} elseif ($isBillingFrequencyQuaterly && $summaryQuaterly) { | |||
$str .= $summaryQuaterly; | |||
} elseif ($isBillingFrequencyBiannual && $summaryBiannual) { | |||
$str .= $summaryBiannual; | |||
$str .= '<li>Facturation '.strtolower(Producer::$billingFrequencyArray[$producer->option_billing_frequency]).'</li>'; | |||
} | |||
if ($producer->option_billing_reduction && strlen($str)) { | |||
$str .= '<br /><u>Avec réduction</u> : '; | |||
if ($producer->option_billing_reduction_percentage) { | |||
$str .= ' ' . $producer->option_billing_reduction_percentage . ' %'; | |||
} | |||
if($producer->option_billing_permanent_transfer) { | |||
$str .= '<li>Virement permanent : <strong>'.Price::format($producer->option_billing_permanent_transfer_amount).'</strong></li>'; | |||
} | |||
$str .= '</li>'; | |||
$str .= '<li>Facturation '.strtolower(Producer::$billingFrequencyArray[$producer->option_billing_frequency]).'</li>'; | |||
} | |||
$str .= '</ul>'; | |||
if($producer->option_billing_permanent_transfer) { | |||
$str .= '<li>Virement permanent : <strong>'.Price::format($producer->option_billing_permanent_transfer_amount).'</strong></li>'; | |||
return $str; | |||
} | |||
], | |||
[ | |||
'attribute' => 'admin_comment', | |||
'label' => 'Commentaire', | |||
'format' => 'raw', | |||
'value' => function($producer) { | |||
if($producer->admin_comment) { | |||
return $producer->admin_comment; | |||
} | |||
$str .= '</ul>'; | |||
return $str; | |||
} | |||
], | |||
[ | |||
'attribute' => 'admin_comment', | |||
'label' => 'Commentaire', | |||
'format' => 'raw', | |||
'value' => function($producer) { | |||
if($producer->admin_comment) { | |||
return $producer->admin_comment; | |||
return ''; | |||
} | |||
return ''; | |||
} | |||
], | |||
[ | |||
'class' => 'yii\grid\ActionColumn', | |||
'template' => '{update} {dolibarr} {billing} {alwaysdata}', | |||
'headerOptions' => ['class' => 'column-actions'], | |||
'contentOptions' => ['class' => 'column-actions'], | |||
'buttons' => [ | |||
'update' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-pencil"></span>', | |||
$url, | |||
[ | |||
'title' => 'Modifier', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
'dolibarr' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-paste"></span>', | |||
$url, | |||
[ | |||
'title' => 'Générer la facture sur Dolibarr', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
'billing' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-euro"></span>', | |||
$url, | |||
[ | |||
'title' => 'Facturation', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
'alwaysdata' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-road"></span>', | |||
$url, | |||
[ | |||
'title' => 'Redirections Alwaysdata (email et url courte)', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
], | |||
[ | |||
'class' => 'yii\grid\ActionColumn', | |||
'template' => '{update} {billing} {dolibarr} {alwaysdata}', | |||
'headerOptions' => ['class' => 'column-actions'], | |||
'contentOptions' => ['class' => 'column-actions'], | |||
'buttons' => [ | |||
'update' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-pencil"></span>', | |||
$url, | |||
[ | |||
'title' => 'Modifier', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
'dolibarr' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-paste"></span>', | |||
$url, | |||
[ | |||
'title' => 'Générer la facture sur Dolibarr', | |||
'class' => 'btn btn-default btn-dolibarr' | |||
] | |||
); | |||
}, | |||
'billing' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-euro"></span>', | |||
$url, | |||
[ | |||
'title' => 'Facturation', | |||
'class' => 'btn btn-default' | |||
] | |||
); | |||
}, | |||
'alwaysdata' => function ($url, $model) { | |||
return Html::a( | |||
'<span class="glyphicon glyphicon-road"></span>', | |||
$url, | |||
[ | |||
'title' => 'Redirections Alwaysdata (email et url courte)', | |||
'class' => 'btn btn-default btn-alwaysdata' | |||
] | |||
); | |||
}, | |||
], | |||
], | |||
], | |||
], | |||
]); ?> | |||
]); ?> | |||
</div> |
@@ -458,6 +458,10 @@ $this->addBreadcrumb($this->getTitle()); | |||
<?= $form->field($model, 'document_invoice_first_reference'); ?> | |||
<?= $form->field($model, 'document_delivery_note_prefix'); ?> | |||
<?= $form->field($model, 'document_delivery_note_first_reference'); ?> | |||
<?= $form->field($model, 'option_invoice_only_based_on_delivery_notes')->dropDownList([ | |||
0 => 'Non', | |||
1 => 'Oui' | |||
]); ?> | |||
<?= $form->field($model, 'document_display_orders_invoice')->dropDownList([ | |||
0 => 'Non', | |||
1 => 'Oui' |
@@ -37,12 +37,23 @@ termes. | |||
*/ | |||
use dosamigos\chartjs\ChartJs; | |||
use yii\helpers\Html; | |||
$this->setTitle('Statistiques <small>Chiffre d\'affaire</small>') ; | |||
$this->setTitle('Statistiques - Chiffre d\'affaire') ; | |||
$this->addBreadcrumb('Statistiques (chiffre d\'affaire)') ; | |||
?> | |||
<?php | |||
foreach($yearsWithTurnoverArray as $year) { | |||
$classBtn = 'btn-default'; | |||
if($yearCurrent == $year) { | |||
$classBtn = 'btn-primary'; | |||
} | |||
echo Html::a($year, ['stats/index', 'year' => $year], ['class' => 'btn '.$classBtn]).' '; | |||
} | |||
?> | |||
<?= ChartJs::widget([ | |||
'type' => 'line', | |||
'options' => [ |
@@ -39,7 +39,7 @@ termes. | |||
use \backend\controllers\StatsController ; | |||
use yii\helpers\Html; | |||
$this->setTitle('Statistiques <small>Produits '.$year.'</small>', 'Statistiques produits '.$year) ; | |||
$this->setTitle('Statistiques - Produits '.$year, 'Statistiques produits '.$year) ; | |||
$this->addBreadcrumb('Statistiques produits '.$year) ; | |||
$this->addButton(['label' => '< '.($year - 1), 'url' => ['stats/products','year' => $year - 1], 'class' => 'btn btn-default']) ; | |||
$this->addButton(['label' => ($year + 1).' >', 'url' => ['stats/products','year' => $year + 1], 'class' => 'btn btn-default']) ; |
@@ -36,6 +36,7 @@ pris connaissance de la licence CeCILL, et que vous en avez accepté les | |||
termes. | |||
*/ | |||
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager; | |||
use yii\helpers\Html; | |||
use yii\grid\GridView; | |||
use common\helpers\GlobalParam ; | |||
@@ -45,6 +46,8 @@ use common\logic\Product\Product\Wrapper\ProductManager; | |||
use yii\helpers\ArrayHelper; | |||
use common\logic\Product\Product\Model\Product; | |||
$subscriptionManager = SubscriptionManager::getInstance(); | |||
$this->setTitle('Abonnements') ; | |||
$this->addBreadcrumb($this->getTitle()) ; | |||
$this->addButton(['label' => 'Nouvel abonnement <span class="glyphicon glyphicon-plus"></span>', 'url' => 'subscription/create', 'class' => 'btn btn-primary']) ; | |||
@@ -122,24 +125,8 @@ $subscriptionsArray = Subscription::searchAll() ; | |||
'headerOptions' => ['class' => 'column-hide-on-mobile'], | |||
'filterOptions' => ['class' => 'column-hide-on-mobile'], | |||
'contentOptions' => ['class' => 'column-hide-on-mobile'], | |||
'value' => function($model) { | |||
$html = '<small>' ; | |||
if($model->date_end) { | |||
$html .= 'Du ' ; | |||
} | |||
else { | |||
$html .= 'À partir du ' ; | |||
} | |||
$html .= '</small>' ; | |||
$html .= date('d/m/Y',strtotime($model->date_begin)) ; | |||
if($model->date_end) { | |||
$html .= '<br />au '.date('d/m/Y',strtotime($model->date_end)) ; | |||
if(date('Y-m-d') > $model->date_end) { | |||
$html .= ' <span class="label label-danger">Terminé</span>' ; | |||
} | |||
} | |||
return $html ; | |||
'value' => function($model) use ($subscriptionManager) { | |||
return $subscriptionManager->getPeriodAsHtml($model); | |||
} | |||
], | |||
[ | |||
@@ -158,36 +145,8 @@ $subscriptionsArray = Subscription::searchAll() ; | |||
'headerOptions' => ['class' => 'column-hide-on-mobile'], | |||
'filterOptions' => ['class' => 'column-hide-on-mobile'], | |||
'contentOptions' => ['class' => 'text-small column-hide-on-mobile'], | |||
'value' => function($model) { | |||
$html = '' ; | |||
if($model->monday) { | |||
$html .= 'lundi, ' ; | |||
} | |||
if($model->tuesday) { | |||
$html .= 'mardi, ' ; | |||
} | |||
if($model->wednesday) { | |||
$html .= 'mercredi, ' ; | |||
} | |||
if($model->thursday) { | |||
$html .= 'jeudi, ' ; | |||
} | |||
if($model->friday) { | |||
$html .= 'vendredi, ' ; | |||
} | |||
if($model->saturday) { | |||
$html .= 'samedi, ' ; | |||
} | |||
if($model->sunday) { | |||
$html .= 'dimanche, ' ; | |||
} | |||
if(strlen($html)) { | |||
return substr ($html, 0, strlen($html) - 2) ; | |||
} | |||
else { | |||
return '<span class="glyphicon glyphicon-warning-sign"></span> Aucun jour' ; | |||
} | |||
'value' => function($model) use ($subscriptionManager) { | |||
return $subscriptionManager->getDaysAsHtml($model); | |||
} | |||
], | |||
[ |
@@ -36,6 +36,8 @@ | |||
* termes. | |||
*/ | |||
use common\components\PageSizer; | |||
use common\logic\Producer\Producer\Wrapper\ProducerManager; | |||
use yii\helpers\Html; | |||
use yii\grid\GridView; | |||
use common\logic\User\User\Wrapper\UserManager; | |||
@@ -43,6 +45,8 @@ use common\logic\Order\Order\Model\Order; | |||
use common\logic\User\UserProducer\Model\UserProducer; | |||
use common\logic\User\User\Model\User; | |||
$producerManager = ProducerManager::getInstance(); | |||
$this->setTitle('Utilisateurs'); | |||
$this->addBreadcrumb($this->getTitle()); | |||
$this->addButton(['label' => 'Nouvel utilisateur <span class="glyphicon glyphicon-plus"></span>', 'url' => 'user/create', 'class' => 'btn btn-primary']); | |||
@@ -64,6 +68,8 @@ $this->render('_menu', [ | |||
<?= GridView::widget([ | |||
'dataProvider' => $dataProvider, | |||
'filterModel' => $searchModel, | |||
'summary' => $this->getProducerContainer()->getProducerPageSizer() | |||
->getPageSizeSummary($producer, 'user', 'Utilisateurs'), | |||
'columns' => [ | |||
[ | |||
'attribute' => 'username', |
@@ -1827,37 +1827,42 @@ body.skin-black .content-wrapper .submenu { | |||
body.skin-black .main-footer a { | |||
color: #F39C12; | |||
} | |||
/* line 311, ../sass/_adminlte.scss */ | |||
body.skin-black .gridview-pagesize { | |||
float: right; | |||
margin-bottom: 8px; | |||
} | |||
/* line 312, ../sass/_adminlte.scss */ | |||
/* line 317, ../sass/_adminlte.scss */ | |||
body.login-page { | |||
background: none; | |||
background-color: white; | |||
} | |||
/* line 316, ../sass/_adminlte.scss */ | |||
/* line 321, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo { | |||
text-align: center; | |||
font-family: 'highvoltageregular'; | |||
} | |||
/* line 320, ../sass/_adminlte.scss */ | |||
/* line 325, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-logo img { | |||
width: 50px; | |||
} | |||
/* line 325, ../sass/_adminlte.scss */ | |||
/* line 330, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary { | |||
background-color: #F39C12; | |||
border-color: #F39C12; | |||
padding: 5px 10px; | |||
} | |||
/* line 330, ../sass/_adminlte.scss */ | |||
/* line 335, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body .btn-primary:active { | |||
background-color: #f4a62a; | |||
border-color: #F39C12; | |||
} | |||
/* line 336, ../sass/_adminlte.scss */ | |||
/* line 341, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a { | |||
color: #F39C12; | |||
} | |||
/* line 338, ../sass/_adminlte.scss */ | |||
/* line 343, ../sass/_adminlte.scss */ | |||
body.login-page .login-box .login-box-body a:hover { | |||
color: #f4a62a; | |||
} |
@@ -51,6 +51,8 @@ $(document).ready(function () { | |||
opendistrib_menu_treeview(); | |||
opendistrib_select2(); | |||
opendistrib_dropdown_producers(); | |||
opendistrib_gridview_pagesize(); | |||
opendistrib_producers_admin(); | |||
}); | |||
var UrlManager = { | |||
@@ -63,6 +65,25 @@ var UrlManager = { | |||
} | |||
}; | |||
function opendistrib_producers_admin() { | |||
$('.producer-admin-index .btn-alwaysdata, .producer-admin-index .btn-dolibarr').click(function() { | |||
var $button = $(this); | |||
$button.attr('disabled', 'disabled'); | |||
axios.get($button.attr('href'), {}) | |||
.then(function (response) { | |||
appAlerts.alertResponse(response); | |||
$button.removeAttr('disabled'); | |||
}); | |||
return false; | |||
}); | |||
} | |||
function opendistrib_gridview_pagesize() { | |||
$('.gridview-pagesize select').change(function() { | |||
$(this).parent().parent().submit(); | |||
}); | |||
} | |||
function opendistrib_dropdown_producers() { | |||
$('.producer-menu .dropdown-toggle').click(function() { |
@@ -212,11 +212,23 @@ var app = new Vue({ | |||
} | |||
if (distributions.length) { | |||
var fillMode = 'solid'; | |||
var dayToday = app.formatDate(new Date()); | |||
for (var i = 0; i < distributions.length; i++) { | |||
if(distributions[i].date < dayToday) { | |||
fillMode = 'outline'; | |||
} | |||
else { | |||
fillMode = 'solid'; | |||
} | |||
app.calendar.attrs.push({ | |||
key: distributions[i].date, | |||
highlight: true, | |||
dates: distributions[i].date | |||
dates: distributions[i].date, | |||
highlight: { | |||
color: 'green', | |||
fillMode: fillMode | |||
} | |||
}); | |||
if (distributions[i].date == dateFormatCompare) { |
@@ -307,6 +307,11 @@ body.skin-black { | |||
color: $color1 ; | |||
} | |||
} | |||
.gridview-pagesize { | |||
float: right; | |||
margin-bottom: 8px; | |||
} | |||
} | |||
body.login-page { |
@@ -1,16 +1,23 @@ | |||
<?php | |||
namespace common\helpers; | |||
namespace common\components; | |||
use common\helpers\Password; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use GuzzleHttp\Client; | |||
use yii\base\ErrorException; | |||
class Alwaysdata | |||
class AlwaysdataClient | |||
{ | |||
public static function createProducerEmailRedirection(Producer $producer) | |||
public function initRedirections(Producer $producer) | |||
{ | |||
return self::post('mailbox',[ | |||
$this->createProducerSiteShortUrlRedirection($producer); | |||
$this->createProducerEmailRedirection($producer); | |||
} | |||
public function createProducerEmailRedirection(Producer $producer) | |||
{ | |||
return $this->post('mailbox',[ | |||
'domain' => \Yii::$app->parameterBag->get('alwaysdataDomainOpendistribId'), | |||
'name' => $producer->slug, | |||
'password' => Password::generate(13), | |||
@@ -19,9 +26,9 @@ class Alwaysdata | |||
]); | |||
} | |||
public static function createProducerSiteShortUrlRedirection(Producer $producer) | |||
public function createProducerSiteShortUrlRedirection(Producer $producer) | |||
{ | |||
return self::post('site', [ | |||
return $this->post('site', [ | |||
'addresses' => [$producer->slug.'.opendistrib.net'], | |||
'type' => 'redirect', | |||
'url' => 'https://producteurs.opendistrib.net/'.$producer->slug, | |||
@@ -30,18 +37,18 @@ class Alwaysdata | |||
]); | |||
} | |||
private static function post(string $resource, array $data) | |||
private function post(string $resource, array $data) | |||
{ | |||
$client = self::getClient($resource); | |||
$client = $this->getClient($resource); | |||
return $client->request('POST', '', [ | |||
'body' => json_encode($data) | |||
]); | |||
} | |||
private static function getClient(string $resource) | |||
private function getClient(string $resource) | |||
{ | |||
self::checkConfiguration(); | |||
$this->checkConfiguration(); | |||
return new Client([ | |||
'base_uri' => \Yii::$app->parameterBag->get('alwaysdataApiUrl').$resource.'/', | |||
@@ -49,7 +56,7 @@ class Alwaysdata | |||
]); | |||
} | |||
private static function checkConfiguration() | |||
private function checkConfiguration() | |||
{ | |||
if(!\Yii::$app->parameterBag->has('alwaysdataApiUrl') | |||
|| !\Yii::$app->parameterBag->has('alwaysdataAccount') |
@@ -35,8 +35,8 @@ class BusinessLogic | |||
$this->getDeliveryNoteContainer(), | |||
$this->getDocumentContainer(), | |||
$this->getPointSaleContainer(), | |||
$this->getSubscriptionContainer(), | |||
$this->getProductContainer(), | |||
$this->getSubscriptionContainer(), | |||
$this->getDistributionContainer(), | |||
$this->getProducerContainer(), | |||
$this->getOrderContainer(), |
@@ -0,0 +1,39 @@ | |||
<?php | |||
namespace common\components; | |||
use yii\helpers\Html; | |||
class PageSizer | |||
{ | |||
const DEFAULT_PAGE_SIZE = 25; | |||
public static array $pageSizeOptions = [25, 50, 75, 100]; | |||
public function getForm(string $entity, string $labelEntity, int $pageSize, array $action = ['producer/pagesize']) | |||
{ | |||
return '<form class="form-inline gridview-pagesize" method="post" action="'.\Yii::$app->urlManager->createUrl($action).'"><div class="form-group"><label class="control-label">'.$labelEntity.' par page : </label> '. | |||
Html::hiddenInput('entity', $entity). | |||
Html::dropDownList( | |||
'pagesize', | |||
$pageSize, | |||
$this->getPageSizeOptions(), | |||
array('class'=>'form-control')).'</div></form></div>'; | |||
} | |||
public function getPageSizeOptions(): array | |||
{ | |||
$pageSizeOptionsArray = []; | |||
foreach(self::$pageSizeOptions as $pageSize) { | |||
$pageSizeOptionsArray[$pageSize] = $pageSize; | |||
} | |||
return $pageSizeOptionsArray; | |||
} | |||
public function isPageSizeExist(int $pageSize): bool | |||
{ | |||
return in_array($pageSize, self::$pageSizeOptions); | |||
} | |||
} |
@@ -66,6 +66,12 @@ return [ | |||
'parameterBag' => [ | |||
'class' => 'common\components\ParameterBag' | |||
], | |||
'pageSizer' => [ | |||
'class' => 'common\components\PageSizer' | |||
], | |||
'alwaysdataClient' => [ | |||
'class' => 'common\components\AlwaysdataClient' | |||
], | |||
'assetManager' => [ | |||
'linkAssets' => YII_ENV == "dev" ? 'true' : false, | |||
], |
@@ -37,7 +37,7 @@ | |||
*/ | |||
return [ | |||
'version' => '23.10.A', | |||
'version' => '23.10.B', | |||
'siteName' => 'Opendistrib', | |||
'adminEmail' => 'contact@opendistrib.net', | |||
'supportEmail' => 'contact@opendistrib.net', |
@@ -42,6 +42,7 @@ use common\logic\Product\Product\Model\Product; | |||
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription; | |||
use common\logic\Subscription\Subscription\Model\Subscription; | |||
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager; | |||
use common\logic\User\User\Wrapper\UserManager; | |||
use Yii; | |||
use yii\base\Model; | |||
@@ -116,13 +117,15 @@ class SubscriptionForm extends Model | |||
*/ | |||
public function save() | |||
{ | |||
$userManager = UserManager::getInstance(); | |||
$subscriptionManager = SubscriptionManager::getInstance(); | |||
if ($this->id) { | |||
$subscription = Subscription::searchOne(['id' => $this->id]) ; | |||
$subscription->populateUpdatedBy($userManager->getCurrent()); | |||
} | |||
else { | |||
$subscription = $subscriptionManager->instanciateSubscription() ; | |||
$subscription = $subscriptionManager->instanciateSubscription($userManager->getCurrent()) ; | |||
} | |||
if ($subscription) { |
@@ -17,12 +17,13 @@ use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\Product\Product\Repository\ProductRepository; | |||
use common\logic\Product\Product\Service\ProductSolver; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use common\logic\User\UserProducer\Model\UserProducer; | |||
use kartik\mpdf\Pdf; | |||
class DistributionReportPdfGenerator extends AbstractGenerator | |||
{ | |||
const LIMIT_PRODUCTS = 100; | |||
const LIMIT_PRODUCTS = 120; | |||
protected OrderRepository $orderRepository; | |||
protected OrderBuilder $orderBuilder; | |||
@@ -32,6 +33,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
protected OrderSolver $orderSolver; | |||
protected ProductSolver $productSolver; | |||
protected DocumentSolver $documentSolver; | |||
protected UserRepository $userRepository; | |||
public function loadDependencies(): void | |||
{ | |||
@@ -43,6 +45,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
$this->orderSolver = $this->loadService(OrderSolver::class); | |||
$this->productSolver = $this->loadService(ProductSolver::class); | |||
$this->documentSolver = $this->loadService(DocumentSolver::class); | |||
$this->userRepository = $this->loadService(UserRepository::class); | |||
} | |||
public function generateDistributionReportPdf(Distribution $distribution, bool $save = false) | |||
@@ -172,8 +175,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$strProducts .= '(' .$quantity .$theUnit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
$strProducts .= $this->displayOrderProduct($quantity, $unit, $product); | |||
} | |||
} | |||
@@ -227,8 +229,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
foreach ($productsArray as $product) { | |||
foreach ($order->productOrder as $productOrder) { | |||
if($product->id == $productOrder->id_product) { | |||
$unit = ( $this->productSolver->strUnit($productOrder->unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($productOrder->unit, 'wording_short', true) ; | |||
$strProducts .= '('.$productOrder->quantity .$unit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
$strProducts .= $this->displayOrderProduct($productOrder->quantity, $productOrder->unit, $product); | |||
} | |||
} | |||
} | |||
@@ -275,13 +276,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
$credit = '' ; | |||
if(isset($order->user) && $order->user->id) { | |||
$userProducer = UserProducer::searchOne([ | |||
'id_user' => $order->user->id | |||
]); | |||
if($userProducer) { | |||
$credit = number_format($userProducer->credit,2).' €' ; | |||
} | |||
$credit = number_format($this->userRepository->getCredit($order->user, true),2).' €' ; | |||
} | |||
return '<td>'.$credit.'</td>' ; | |||
@@ -338,8 +333,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $pointSale->orders, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$this->productSolver->getNameExport($product) . '<br />'; | |||
$html .= $this->displayOrderProduct($quantity, $unit, $product); | |||
} | |||
} | |||
@@ -363,8 +357,7 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
foreach( Product::$unitsArray as $unit => $dataUnit) { | |||
$quantity = $this->orderSolver->getProductQuantity($product, $ordersArray, false, $unit); | |||
if ($quantity) { | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
$html .= '(' .$quantity .$theUnit.') '.$product->name . '<br />'; | |||
$html .= $this->displayOrderProduct($quantity, $unit, $product); | |||
} | |||
} | |||
if($isBig && $cpt == self::LIMIT_PRODUCTS) { | |||
@@ -380,4 +373,10 @@ class DistributionReportPdfGenerator extends AbstractGenerator | |||
return $html; | |||
} | |||
public function displayOrderProduct(string $quantity, string $unit, Product $product) | |||
{ | |||
$theUnit = ( $this->productSolver->strUnit($unit, 'wording_short', true) == 'p.') ? '' : ' '. $this->productSolver->strUnit($unit, 'wording_short', true) ; | |||
return '<strong>'.$quantity. $theUnit.'</strong> '.$this->productSolver->getNameExport($product). '<br />'; | |||
} | |||
} |
@@ -240,29 +240,8 @@ class OrderRepository extends AbstractRepository | |||
public function getAmountSummary(Order $order): string | |||
{ | |||
$html = ''; | |||
$creditActive = $this->producerSolver->getConfig('credit'); | |||
$html .= $this->orderSolver->getOrderAmountWithTax($order, Order::AMOUNT_TOTAL, true); | |||
if ($creditActive) { | |||
$html .= '<br />'; | |||
if ($order->paid_amount) { | |||
if ($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_PAID) { | |||
$html .= '<span class="label label-success">Payée</span>'; | |||
} elseif ($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_UNPAID) { | |||
$html .= '<span class="label label-danger">Non payée</span><br /> | |||
Reste <strong>' . $this->orderSolver->getOrderAmount( | |||
$order, | |||
Order::AMOUNT_REMAINING, | |||
true | |||
) . '</strong> à payer'; | |||
} elseif ($this->orderSolver->getPaymentStatus($order) == Order::PAYMENT_SURPLUS) { | |||
$html .= '<span class="label label-success">Payée</span>'; | |||
} | |||
} else { | |||
$html .= '<span class="label label-default">Non réglé</span>'; | |||
} | |||
} | |||
$html .= '<br />'.$this->getPaymentLabelShort($order); | |||
return $html; | |||
} | |||
@@ -78,6 +78,7 @@ class PointSaleSolver extends AbstractService implements SolverInterface | |||
if (strlen($pointSale->$field)) { | |||
$str = nl2br(Html::encode($pointSale->$field)); | |||
$str = preg_replace('/\[select_previous_day\](.*?)\[\/select_previous_day\]/', '<a href="javascript:void(0);" class="select-previous-day">$1</a>', $str); | |||
$str = preg_replace('@([^>"])(https?://[a-z0-9\./+,%#_-]+)@i', '$1<a href="$2" target="_blank">$2</a>', $str); | |||
} | |||
return $str; | |||
} |
@@ -268,7 +268,8 @@ class Producer extends ActiveRecordCommon | |||
'option_export_evoliz', | |||
'option_display_message_new_opendistrib_version', | |||
'option_billing_permanent_transfer', | |||
'option_export_display_column_delivery_note' | |||
'option_export_display_column_delivery_note', | |||
'option_invoice_only_based_on_delivery_notes' | |||
], | |||
'boolean' | |||
], | |||
@@ -435,6 +436,7 @@ class Producer extends ActiveRecordCommon | |||
'dolibarr_product_id' => 'Dolibarr : id produit', | |||
'option_export_display_column_delivery_note' => "Récapitulatif PDF : afficher une colonne bon de livraison", | |||
'option_weeks_distributions_activated_in_advance' => "Semaines de distributions à activer à l'avance", | |||
'option_invoice_only_based_on_delivery_notes' => 'Facturer uniquement sur la base des bons de livraison' | |||
]; | |||
} | |||
@@ -3,7 +3,6 @@ | |||
namespace common\logic\Producer\Producer\Repository; | |||
use common\helpers\Departments; | |||
use common\helpers\GlobalParam; | |||
use common\helpers\Price; | |||
use common\logic\AbstractRepository; | |||
use common\logic\Document\Document\Model\DocumentInterface; | |||
@@ -119,6 +118,31 @@ class ProducerRepository extends AbstractRepository | |||
return $this->getTurnover($producer, $period, $format); | |||
} | |||
public function getYearsWithTurnover(Producer $producer): array | |||
{ | |||
$year = date('Y'); | |||
$yearsArray = []; | |||
for($i = 0; $i <= 10; $i++) { | |||
if($this->hasTurnoverOverTheYear($producer, $year - $i)) { | |||
array_unshift($yearsArray, $year - $i); | |||
} | |||
} | |||
return $yearsArray; | |||
} | |||
public function hasTurnoverOverTheYear(Producer $producer, int $year): bool | |||
{ | |||
for($month = 1; $month <= 12; $month++) { | |||
if($this->getTurnover($producer, $year.'-'.$month)) { | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
/** | |||
* Retourne le CA du producteur pour un mois donné | |||
*/ | |||
@@ -132,11 +156,10 @@ class ProducerRepository extends AbstractRepository | |||
$command = $connection->createCommand( | |||
' | |||
SELECT SUM(product_order.price * product_order.quantity) AS turnover | |||
FROM `order`, product_order, distribution, product | |||
FROM `order`, product_order, distribution | |||
WHERE `order`.id = product_order.id_order | |||
AND distribution.id_producer = :id_producer | |||
AND `order`.id_distribution = distribution.id | |||
AND product_order.id_product = product.id | |||
AND distribution.date > :date_begin | |||
AND distribution.date < :date_end', | |||
[ | |||
@@ -160,7 +183,7 @@ class ProducerRepository extends AbstractRepository | |||
{ | |||
$totalTurnover = 0; | |||
for($i = 1; $i <= $numberMonths; $i++) { | |||
for ($i = 1; $i <= $numberMonths; $i++) { | |||
$timeMonth = strtotime('-' . $i . ' month'); | |||
$month = date('Y-m', $timeMonth); | |||
$totalTurnover += $this->getTurnover($producer, $month); | |||
@@ -175,6 +198,40 @@ class ProducerRepository extends AbstractRepository | |||
return $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, $format); | |||
} | |||
public function getDatasChartTurnoverStatistics(Producer $producer, int $year) | |||
{ | |||
$interval = new \DateInterval('P1M'); | |||
$start = new \DateTime($year.'-01-01'); | |||
if($year == date('Y')) { | |||
$end = new \DateTime('last day of this month'); | |||
} | |||
else { | |||
$end = new \DateTime($year.'-12-31'); | |||
} | |||
$period = new \DatePeriod($start, $interval, $end); | |||
$data = []; | |||
$dataLabels = []; | |||
foreach ($period as $date) { | |||
$month = $date->format('m/Y'); | |||
$dataLabels[] = $month; | |||
$turnover = $this->getTurnover($producer, $date->format('Y-m')); | |||
$data[$month] = $turnover; | |||
} | |||
// création d'un tableau sans index car chart.js n'accepte pas les index | |||
$dataNoIndex = []; | |||
foreach ($data as $key => $val) { | |||
$dataNoIndex[] = round($val, 2); | |||
} | |||
return [ | |||
'labels' => $dataLabels, | |||
'data' => $dataNoIndex | |||
]; | |||
} | |||
public function getSummaryAmountsToBeBilled(Producer $producer, string $label, int $numberOfMonths = 1, $context = 'list'): string | |||
{ | |||
$text = ''; | |||
@@ -192,14 +249,14 @@ class ProducerRepository extends AbstractRepository | |||
$turnover = $this->getTurnover($producer, $month); | |||
if ($turnover) { | |||
if($numberOfMonths > 1) { | |||
$text .= ucfirst(strftime('%B ', $timeMonth)).' '.date('Y', $timeMonth).' : '; | |||
if ($numberOfMonths > 1) { | |||
$text .= ucfirst(strftime('%B ', $timeMonth)) . ' ' . date('Y', $timeMonth) . ' : '; | |||
} | |||
$isBold = $this->producerSolver->isBillingTypeClassic($producer) && !$producer->option_billing_permanent_transfer; | |||
if ($isBold) $text .= '<strong>'; | |||
$text .= $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, true); | |||
if ($isBold) $text .= '</strong>'; | |||
$text .= ' (' . Price::format($turnover, 0). ' CA)'; | |||
$text .= ' (' . Price::format($turnover, 0) . ' CA)'; | |||
$text .= '<br />'; | |||
$sumInvoicePrice += $this->producerPriceRangeRepository->getAmountToBeBilledByTurnover($turnover, false); | |||
@@ -207,12 +264,12 @@ class ProducerRepository extends AbstractRepository | |||
} | |||
if (strlen($text)) { | |||
$text = '<i>'.$label.'</i>' . ' : <br />' . $text; | |||
$text = '<i>' . $label . '</i>' . ' : <br />' . $text; | |||
} | |||
} | |||
if($numberOfMonths > 1 && $sumInvoicePrice > 0) { | |||
$text .= '<br />Total : <strong>'.Price::format($sumInvoicePrice, 0).'</strong>'; | |||
if ($numberOfMonths > 1 && $sumInvoicePrice > 0) { | |||
$text .= '<br />Total : <strong>' . Price::format($sumInvoicePrice, 0) . '</strong>'; | |||
} | |||
return $text; | |||
@@ -273,9 +330,9 @@ class ProducerRepository extends AbstractRepository | |||
$count = 0; | |||
$producersArray = $this->findProducersActive(); | |||
foreach($producersArray as $producer) { | |||
if($this->getTurnoverByNumberMonths($producer, 3)) { | |||
$count ++; | |||
foreach ($producersArray as $producer) { | |||
if ($this->getTurnoverByNumberMonths($producer, 3)) { | |||
$count++; | |||
} | |||
} | |||
@@ -311,9 +368,9 @@ class ProducerRepository extends AbstractRepository | |||
$producersWithTimeSavedArray = $this->findProducersWithTimeSaved(); | |||
$countProducersWithOptionTimeSaved = count($producersWithTimeSavedArray); | |||
if($countProducersWithOptionTimeSaved) { | |||
if ($countProducersWithOptionTimeSaved) { | |||
$sumTimeSaved = 0; | |||
foreach($producersWithTimeSavedArray as $producerWithTimeSaved) { | |||
foreach ($producersWithTimeSavedArray as $producerWithTimeSaved) { | |||
$sumTimeSaved += $producerWithTimeSaved->option_time_saved; | |||
} | |||
@@ -0,0 +1,47 @@ | |||
<?php | |||
namespace common\logic\Producer\Producer\Service; | |||
use common\components\PageSizer; | |||
use common\logic\AbstractUtils; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
class ProducerPageSizer extends AbstractUtils | |||
{ | |||
protected ProducerSolver $producerSolver; | |||
protected ProducerBuilder $producerBuilder; | |||
protected PageSizer $pageSizer; | |||
public function loadDependencies(): void | |||
{ | |||
$this->pageSizer = \Yii::$app->pageSizer; | |||
$this->producerSolver = $this->loadService(ProducerSolver::class); | |||
$this->producerBuilder = $this->loadService(ProducerBuilder::class); | |||
} | |||
public function getPageSizeConfigName(string $entity) | |||
{ | |||
return 'option_pagesize_'.$entity; | |||
} | |||
public function getPageSize(Producer $producer, string $entity) | |||
{ | |||
$pageSizeConfig = $this->getPageSizeConfigName($entity); | |||
return $this->producerSolver->getConfig($pageSizeConfig, $producer) ?: PageSizer::DEFAULT_PAGE_SIZE ; | |||
} | |||
public function getPageSizeSummary(Producer $producer, string $entity, string $labelEntity): string | |||
{ | |||
return $this->pageSizer->getForm($entity, $labelEntity, $this->getPageSize($producer, $entity)); | |||
} | |||
public function updatePagesize(Producer $producer, string $entity, int $pageSize) | |||
{ | |||
$field = $this->getPageSizeConfigName($entity); | |||
if(isset($producer->$field) && $this->pageSizer->isPageSizeExist($pageSize)) { | |||
$producer->$field = $pageSize; | |||
$this->producerBuilder->update($producer); | |||
} | |||
} | |||
} |
@@ -2,6 +2,7 @@ | |||
namespace common\logic\Producer\Producer\Service; | |||
use common\components\PageSizer; | |||
use common\helpers\GlobalParam; | |||
use common\logic\AbstractService; | |||
use common\logic\Producer\Producer\Model\Producer; |
@@ -7,6 +7,7 @@ use common\logic\Producer\Producer\Repository\ProducerRepository; | |||
use common\logic\Producer\Producer\Service\DolibarrProducerUtils; | |||
use common\logic\Producer\Producer\Service\ProducerBuilder; | |||
use common\logic\Producer\Producer\Service\ProducerDefinition; | |||
use common\logic\Producer\Producer\Service\ProducerPageSizer; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
use common\logic\Producer\Producer\Service\ProducerUtils; | |||
@@ -20,6 +21,7 @@ class ProducerContainer extends AbstractContainer | |||
ProducerRepository::class, | |||
ProducerBuilder::class, | |||
ProducerUtils::class, | |||
ProducerPageSizer::class, | |||
DolibarrProducerUtils::class, | |||
]; | |||
} | |||
@@ -48,4 +50,9 @@ class ProducerContainer extends AbstractContainer | |||
{ | |||
return ProducerUtils::getInstance(); | |||
} | |||
public function getProducerPageSizer(): ProducerPageSizer | |||
{ | |||
return ProducerPageSizer::getInstance(); | |||
} | |||
} |
@@ -7,6 +7,7 @@ use common\logic\Producer\Producer\Repository\ProducerRepository; | |||
use common\logic\Producer\Producer\Service\DolibarrProducerUtils; | |||
use common\logic\Producer\Producer\Service\ProducerBuilder; | |||
use common\logic\Producer\Producer\Service\ProducerDefinition; | |||
use common\logic\Producer\Producer\Service\ProducerPageSizer; | |||
use common\logic\Producer\Producer\Service\ProducerSolver; | |||
use common\logic\Producer\Producer\Service\ProducerUtils; | |||
@@ -16,6 +17,7 @@ use common\logic\Producer\Producer\Service\ProducerUtils; | |||
* @mixin ProducerRepository | |||
* @mixin ProducerBuilder | |||
* @mixin ProducerUtils | |||
* @mixin ProducerPageSizer | |||
* @mixin DolibarrProducerUtils | |||
*/ | |||
class ProducerManager extends AbstractManager |
@@ -44,9 +44,6 @@ use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription; | |||
use common\logic\User\User\Model\User; | |||
/** | |||
* This is the model class for table "subscription". | |||
*/ | |||
class Subscription extends ActiveRecordCommon | |||
{ | |||
const AUTO_PAYMENT_DEDUCTED = 1; | |||
@@ -69,7 +66,9 @@ class Subscription extends ActiveRecordCommon | |||
return [ | |||
[['id_producer', 'id_point_sale'], 'required'], | |||
[['id_user', 'id_producer', 'id_point_sale', 'monday', 'tuesday', | |||
'wednesday', 'thursday', 'friday', 'saturday', 'sunday', 'week_frequency', 'auto_payment'], 'integer'], | |||
'wednesday', 'thursday', 'friday', 'saturday', 'sunday', | |||
'week_frequency', 'auto_payment', 'id_created_by', 'id_updated_by'], 'integer'], | |||
[['created_at', 'updated_at'], 'datetime', 'format' => 'php:Y-m-d H:i:s'], | |||
[['username', 'comment', 'date_begin', 'date_end'], 'safe'], | |||
]; | |||
} | |||
@@ -95,7 +94,11 @@ class Subscription extends ActiveRecordCommon | |||
'sunday' => 'Dimanche', | |||
'week_frequency' => 'Périodicité', | |||
'auto_payment' => 'Débit automatique', | |||
'comment' => 'Commentaire' | |||
'comment' => 'Commentaire', | |||
'created_at' => 'Création', | |||
'updated_at' => 'Modification', | |||
'created_by' => 'Créé par', | |||
'updated_by' => 'Modifié par', | |||
]; | |||
} | |||
@@ -138,4 +141,26 @@ class Subscription extends ActiveRecordCommon | |||
return $this->hasMany(ProductSubscription::class, ['id_subscription' => 'id']) | |||
->with('product'); | |||
} | |||
public function getCreatedBy() | |||
{ | |||
return $this->hasOne(User::class, ['id' => 'id_created_by']); | |||
} | |||
public function populateCreatedBy(User $createdBy): void | |||
{ | |||
$this->populateFieldObject('id_created_by', 'createdBy', $createdBy); | |||
$this->created_at = date('Y-m-d H:i:s'); | |||
} | |||
public function getUpdatedBy() | |||
{ | |||
return $this->hasOne(User::class, ['id' => 'id_updated_by']); | |||
} | |||
public function populateUpdatedBy(User $updatedBy): void | |||
{ | |||
$this->populateFieldObject('id_updated_by', 'updatedBy', $updatedBy); | |||
$this->updated_at = date('Y-m-d H:i:s'); | |||
} | |||
} |
@@ -67,4 +67,12 @@ class SubscriptionRepository extends AbstractRepository | |||
->filterByUser($user) | |||
->count(); | |||
} | |||
public function findSubscriptionsLatestAdded() | |||
{ | |||
return $this->createDefaultQuery() | |||
->filterByCreatedDuringPastWeek() | |||
->filterByCreatedByUser() | |||
->find(); | |||
} | |||
} |
@@ -20,4 +20,18 @@ class SubscriptionRepositoryQuery extends AbstractRepositoryQuery | |||
$this->andWhere(['subscription.id_user' => $user->id]); | |||
return $this; | |||
} | |||
public function filterByCreatedDuringPastWeek(): self | |||
{ | |||
$datePastWeek = new \DateTime('-7 days'); | |||
$this->andWhere('subscription.created_at >= :created_at') | |||
->addParams(['created_at' => $datePastWeek->format('Y-m-d H:i:s')]); | |||
return $this; | |||
} | |||
public function filterByCreatedByUser(): self | |||
{ | |||
$this->andWhere('subscription.id_user = subscription.id_created_by'); | |||
return $this; | |||
} | |||
} |
@@ -6,6 +6,7 @@ use common\logic\AbstractBuilder; | |||
use common\logic\Distribution\Distribution\Repository\DistributionRepository; | |||
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription; | |||
use common\logic\Subscription\Subscription\Model\Subscription; | |||
use common\logic\User\User\Model\User; | |||
class SubscriptionBuilder extends AbstractBuilder | |||
{ | |||
@@ -16,18 +17,19 @@ class SubscriptionBuilder extends AbstractBuilder | |||
$this->distributionRepository = $this->loadService(DistributionRepository::class); | |||
} | |||
public function instanciateSubscription(): Subscription | |||
public function instanciateSubscription(User $createdBy): Subscription | |||
{ | |||
$subscription = new Subscription(); | |||
$subscription->auto_payment = Subscription::AUTO_PAYMENT_DEDUCTED; | |||
$subscription->populateCreatedBy($createdBy); | |||
return $subscription; | |||
} | |||
public function createSubscription(): Subscription | |||
public function createSubscription(User $createdBy): Subscription | |||
{ | |||
$subscription = $this->instanciateSubscription(); | |||
$this->saveCreate($subscription); | |||
$subscription = $this->instanciateSubscription($createdBy); | |||
$this->create($subscription); | |||
return $subscription; | |||
} |
@@ -3,17 +3,22 @@ | |||
namespace common\logic\Subscription\Subscription\Service; | |||
use common\logic\AbstractService; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\Product\Product\Service\ProductSolver; | |||
use common\logic\SolverInterface; | |||
use common\logic\Subscription\Subscription\Model\Subscription; | |||
use common\logic\User\User\Service\UserSolver; | |||
use yii\helpers\Html; | |||
class SubscriptionSolver extends AbstractService implements SolverInterface | |||
{ | |||
protected UserSolver $userSolver; | |||
protected ProductSolver $productSolver; | |||
public function loadDependencies(): void | |||
{ | |||
$this->userSolver = $this->loadService(UserSolver::class); | |||
$this->productSolver = $this->loadService(ProductSolver::class); | |||
} | |||
/** | |||
@@ -69,4 +74,79 @@ class SubscriptionSolver extends AbstractService implements SolverInterface | |||
return false; | |||
} | |||
public function getProductsListAsHtml(Subscription $subscription): string | |||
{ | |||
$html = '' ; | |||
foreach($subscription->productSubscription as $productSubscription) | |||
{ | |||
if(isset($productSubscription->product) && $productSubscription->product) { | |||
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']) . ' '. $this->productSolver->strUnit($productSubscription->product->unit, 'wording_short').')<br />' ; | |||
} | |||
else { | |||
$html .= 'Produit non défini<br />' ; | |||
} | |||
} | |||
if(!count($subscription->productSubscription)) | |||
{ | |||
$html .= '<span class="glyphicon glyphicon-warning-sign"></span> Aucun produit' ; | |||
} | |||
return $html ; | |||
} | |||
public function getPeriodAsHtml(Subscription $subscription): string | |||
{ | |||
$html = '<small>' ; | |||
if($subscription->date_end) { | |||
$html .= 'Du ' ; | |||
} | |||
else { | |||
$html .= 'À partir du ' ; | |||
} | |||
$html .= '</small>' ; | |||
$html .= date('d/m/Y',strtotime($subscription->date_begin)) ; | |||
if($subscription->date_end) { | |||
$html .= '<br />au '.date('d/m/Y',strtotime($subscription->date_end)) ; | |||
if(date('Y-m-d') > $subscription->date_end) { | |||
$html .= ' <span class="label label-danger">Terminé</span>' ; | |||
} | |||
} | |||
return $html ; | |||
} | |||
public function getDaysAsHtml(Subscription $subscription): string | |||
{ | |||
$html = '' ; | |||
if($subscription->monday) { | |||
$html .= 'lundi, ' ; | |||
} | |||
if($subscription->tuesday) { | |||
$html .= 'mardi, ' ; | |||
} | |||
if($subscription->wednesday) { | |||
$html .= 'mercredi, ' ; | |||
} | |||
if($subscription->thursday) { | |||
$html .= 'jeudi, ' ; | |||
} | |||
if($subscription->friday) { | |||
$html .= 'vendredi, ' ; | |||
} | |||
if($subscription->saturday) { | |||
$html .= 'samedi, ' ; | |||
} | |||
if($subscription->sunday) { | |||
$html .= 'dimanche, ' ; | |||
} | |||
if(strlen($html)) { | |||
return substr ($html, 0, strlen($html) - 2) ; | |||
} | |||
else { | |||
return '<span class="glyphicon glyphicon-warning-sign"></span> Aucun jour' ; | |||
} | |||
} | |||
} |
@@ -40,6 +40,7 @@ namespace common\logic\User\User\Model; | |||
use common\helpers\GlobalParam; | |||
use common\logic\PointSale\PointSale\Model\PointSale; | |||
use common\logic\Producer\Producer\Wrapper\ProducerManager; | |||
use common\logic\User\User\Repository\UserRepository; | |||
use yii\data\ActiveDataProvider; | |||
@@ -62,6 +63,9 @@ class UserSearch extends User | |||
public function search($params = []) | |||
{ | |||
$producerManager = ProducerManager::getInstance(); | |||
$producer = GlobalParam::getCurrentProducer(); | |||
$query = User::find() | |||
->select( | |||
'`user`.id, ' | |||
@@ -88,7 +92,7 @@ class UserSearch extends User | |||
. '`user`.type, ' | |||
. '(SELECT COUNT(*) FROM `order` WHERE `user`.id = `order`.id_user) AS count_orders'); | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.id_producer = :id_producer AND user_producer.active = 1', [':id_producer' => GlobalParam::getCurrentProducerId()]); | |||
$query->innerJoin('user_producer', 'user.id = user_producer.id_user AND user_producer.id_producer = :id_producer AND user_producer.active = 1', [':id_producer' => $producer->id]); | |||
$dataProvider = new ActiveDataProvider([ | |||
'query' => $query, | |||
@@ -97,7 +101,7 @@ class UserSearch extends User | |||
'defaultOrder' => ['created_at' => SORT_DESC] | |||
], | |||
'pagination' => [ | |||
'pageSize' => 20, | |||
'pageSize' => $producerManager->getConfig('option_pagesize_user', $producer), | |||
], | |||
]); | |||
@@ -0,0 +1,31 @@ | |||
<?php | |||
require_once dirname(__FILE__).'/_macros.php'; | |||
version( | |||
'09/10/2023', | |||
[ | |||
[ | |||
"[Administration] Tableau de bord : affichage des derniers abonnements ajoutés", | |||
"[Administration] Distributions > calendrier : dates passées affichées avec un simple liseret vert", | |||
"[Administration] Distributions > commandes : bouton des documents en vert quand au moins un document a été généré", | |||
"[Administration] Distributions > récapitulatif commandes PDF : amélioration lisibilité quantités", | |||
"[Administration] Utilisateurs > liste : sélection du nombre d'utilisateurs affichés par page", | |||
"[Administration] Factures > ajouter : possibilité de facturer uniquement sur base des bons de livraison (Paramètres > Facturation > 'Facturer uniquement sur la base des bons de livraison')", | |||
"[Administration] Statistiques > chiffre d'affaire : affichage année par année", | |||
"[Administration & espace producteur] Points de vente : possibilité de mettre un lien dans le descriptif (transformé en lien cliquable)", | |||
"[Espace producteur] Mes commandes : libellé du paiement des commandes identique à celui affiché dans l'administration" | |||
], | |||
[ | |||
"[Administration] Distributions > récapitulatif commandes PDF : correctif crédit faux affiché à 0,00 €", | |||
] | |||
], | |||
[ | |||
[ | |||
"[Administration] Producteurs : création facture Dolibarr et initialisation Alwaysdata via ajax" | |||
], | |||
[] | |||
], | |||
); | |||
?> |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231004_083707_add_column_producer_option_invoice_only_based_on_delivery_notes | |||
*/ | |||
class m231004_083707_add_column_producer_option_invoice_only_based_on_delivery_notes extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_invoice_only_based_on_delivery_notes', Schema::TYPE_BOOLEAN); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_invoice_only_based_on_delivery_notes'); | |||
} | |||
} |
@@ -0,0 +1,26 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231005_072832_add_column_producer_option_pagesize_user | |||
*/ | |||
class m231005_072832_add_column_producer_option_pagesize_user extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('producer', 'option_pagesize_user', Schema::TYPE_INTEGER); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('producer', 'option_pagesize_user'); | |||
} | |||
} |
@@ -0,0 +1,32 @@ | |||
<?php | |||
use yii\db\Migration; | |||
use yii\db\Schema; | |||
/** | |||
* Class m231006_084312_add_columns_subscription_created_updated | |||
*/ | |||
class m231006_084312_add_columns_subscription_created_updated extends Migration | |||
{ | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeUp() | |||
{ | |||
$this->addColumn('subscription', 'id_created_by', Schema::TYPE_INTEGER); | |||
$this->addColumn('subscription', 'created_at', Schema::TYPE_DATETIME); | |||
$this->addColumn('subscription', 'id_updated_by', Schema::TYPE_INTEGER); | |||
$this->addColumn('subscription', 'updated_at', Schema::TYPE_DATETIME); | |||
} | |||
/** | |||
* {@inheritdoc} | |||
*/ | |||
public function safeDown() | |||
{ | |||
$this->dropColumn('subscription', 'id_created_by'); | |||
$this->dropColumn('subscription', 'created_at'); | |||
$this->dropColumn('subscription', 'id_updated_by'); | |||
$this->dropColumn('subscription', 'updated_at'); | |||
} | |||
} |
@@ -49,7 +49,7 @@ $this->params['breadcrumbs'][] = $this->title; | |||
$userManager = UserManager::getInstance(); | |||
$urlRedirect = null; | |||
if($userManager->isProducer($user)) { | |||
$urlRedirect = $this->getUrlManagerBackend()->createAbsoluteUrl(['site/index']); | |||
$urlRedirect = $this->getUrlManagerBackend()->createAbsoluteUrl(['dashboard/index']); | |||
$redirectLabel = "Redirection vers votre tableau de bord ..."; | |||
} | |||
elseif($producerRedirect) { |
@@ -327,7 +327,7 @@ class CreditController extends ProducerBaseController | |||
http_response_code(200); | |||
} | |||
else { | |||
http_response_code(400); | |||
http_response_code(200); | |||
} | |||
die(); |
@@ -767,7 +767,6 @@ class OrderController extends ProducerBaseController | |||
private function ajaxInfosPointsSale($producer, $distribution = false) | |||
{ | |||
$pointSaleManager = $this->getPointSaleManager(); | |||
$userManager = $this->getUserManager(); | |||
$producerManager = $this->getProducerManager(); | |||
$orderManager = $this->getOrderManager(); | |||
@@ -40,6 +40,7 @@ use common\logic\PointSale\PointSale\Model\PointSale; | |||
use common\logic\Producer\Producer\Wrapper\ProducerManager; | |||
use common\logic\Product\Product\Model\Product; | |||
use common\logic\Product\Product\Wrapper\ProductManager; | |||
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager; | |||
use yii\helpers\Html; | |||
use yii\grid\GridView; | |||
use common\helpers\GlobalParam; | |||
@@ -47,6 +48,7 @@ use yii\helpers\ArrayHelper; | |||
$producerManager = ProducerManager::getInstance(); | |||
$productManager = ProductManager::getInstance(); | |||
$subscriptionManager = SubscriptionManager::getInstance(); | |||
$this->setTitle('Abonnements') ; | |||
$this->addButton(['label' => '<span class="glyphicon glyphicon-plus"></span> Ajouter', 'url' => 'subscription/form', 'class' => 'btn btn-primary']) ; | |||
@@ -56,25 +58,8 @@ $columns = [ | |||
'attribute' => 'product_name', | |||
'label' => 'Produits', | |||
'format' => 'raw', | |||
'value' => function($model) use ($productManager) { | |||
$html = '' ; | |||
foreach($model->productSubscription as $productSubscription) | |||
{ | |||
if(isset($productSubscription->product) && $productSubscription->product) { | |||
$html .= Html::encode($productSubscription->product->name).' ('.($productSubscription->quantity * Product::$unitsArray[$productSubscription->product->unit]['coefficient']) . ' '. $productManager->strUnit($productSubscription->product->unit, 'wording_short').')<br />' ; | |||
} | |||
else { | |||
$html .= 'Produit non défini<br />' ; | |||
} | |||
} | |||
// aucun produit | |||
if(!count($model->productSubscription)) | |||
{ | |||
$html .= '<span class="glyphicon glyphicon-warning-sign"></span> Aucun produit' ; | |||
} | |||
return $html ; | |||
'value' => function($subscription) use ($subscriptionManager) { | |||
return $subscriptionManager->getProductsListAsHtml($subscription); | |||
} | |||
], | |||
[ |
@@ -1474,19 +1474,23 @@ termes. | |||
.order-order #main #app-order-order table#points-sale td.name .comment { | |||
color: gray; | |||
} | |||
/* line 227, ../sass/order/_order.scss */ | |||
/* line 225, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.name .comment a { | |||
color: #F39C12; | |||
} | |||
/* line 231, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.actions { | |||
width: 150px; | |||
} | |||
/* line 229, ../sass/order/_order.scss */ | |||
/* line 233, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale td.actions button { | |||
width: 100%; | |||
} | |||
/* line 235, ../sass/order/_order.scss */ | |||
/* line 239, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#points-sale tr.selected td { | |||
background-color: white; | |||
} | |||
/* line 243, ../sass/order/_order.scss */ | |||
/* line 247, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name { | |||
font-family: "highvoltageregular"; | |||
font-size: 22px; | |||
@@ -1494,12 +1498,12 @@ termes. | |||
text-transform: uppercase; | |||
padding-top: 13px; | |||
} | |||
/* line 250, ../sass/order/_order.scss */ | |||
/* line 254, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name .glyphicon-triangle-bottom, | |||
.order-order #main #app-order-order table#products td.category-name .glyphicon-triangle-right { | |||
font-size: 15px; | |||
} | |||
/* line 255, ../sass/order/_order.scss */ | |||
/* line 259, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name span.label { | |||
font-family: "Arial"; | |||
font-weight: normal; | |||
@@ -1507,17 +1511,17 @@ termes. | |||
text-transform: none; | |||
margin-left: 15px; | |||
} | |||
/* line 264, ../sass/order/_order.scss */ | |||
/* line 268, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.category-name:hover { | |||
cursor: pointer; | |||
background-color: #F39C12; | |||
color: white; | |||
} | |||
/* line 272, ../sass/order/_order.scss */ | |||
/* line 276, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products td.photo img { | |||
width: 100px; | |||
} | |||
/* line 282, ../sass/order/_order.scss */ | |||
/* line 286, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices { | |||
margin-top: 10px; | |||
font-size: 10px; | |||
@@ -1525,34 +1529,34 @@ termes. | |||
padding-bottom: 2px; | |||
margin-bottom: 0px; | |||
} | |||
/* line 290, ../sass/order/_order.scss */ | |||
/* line 294, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices ul li { | |||
margin-bottom: 5px; | |||
} | |||
/* line 292, ../sass/order/_order.scss */ | |||
/* line 296, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .decreasing-prices ul li strong { | |||
font-weight: bold; | |||
} | |||
/* line 300, ../sass/order/_order.scss */ | |||
/* line 304, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit, .order-order #main #app-order-order table#products .price-total { | |||
width: 135px; | |||
text-align: center; | |||
} | |||
/* line 304, ../sass/order/_order.scss */ | |||
/* line 308, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .price-unit .unit, .order-order #main #app-order-order table#products .price-total .unit { | |||
color: gray; | |||
font-size: 13px; | |||
} | |||
/* line 309, ../sass/order/_order.scss */ | |||
/* line 313, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity { | |||
width: 175px; | |||
} | |||
/* line 311, ../sass/order/_order.scss */ | |||
/* line 315, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity input.quantity { | |||
text-align: center; | |||
border-right: 0px none; | |||
} | |||
/* line 315, ../sass/order/_order.scss */ | |||
/* line 319, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products .td-quantity .input-group-addon { | |||
padding: 5px; | |||
padding-left: 0px; | |||
@@ -1560,69 +1564,69 @@ termes. | |||
border-left: 0px none; | |||
border-right: 0px none; | |||
} | |||
/* line 326, ../sass/order/_order.scss */ | |||
/* line 330, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary h3 { | |||
margin-top: 0px; | |||
font-family: "capsuularegular"; | |||
text-transform: none; | |||
margin-bottom: 5px; | |||
} | |||
/* line 333, ../sass/order/_order.scss */ | |||
/* line 337, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul { | |||
margin-bottom: 15px; | |||
padding-left: 20px; | |||
font-size: 23px; | |||
} | |||
/* line 340, ../sass/order/_order.scss */ | |||
/* line 344, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .quantity { | |||
font-size: 18px; | |||
} | |||
/* line 344, ../sass/order/_order.scss */ | |||
/* line 348, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .name { | |||
font-family: "capsuularegular"; | |||
font-size: 24px; | |||
} | |||
/* line 348, ../sass/order/_order.scss */ | |||
/* line 352, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .summary ul li .other { | |||
font-family: "capsuularegular"; | |||
font-size: 18px; | |||
} | |||
/* line 356, ../sass/order/_order.scss */ | |||
/* line 360, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order table#products tr.total .price-total { | |||
font-size: 23px; | |||
} | |||
/* line 364, ../sass/order/_order.scss */ | |||
/* line 368, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .delivery { | |||
margin-bottom: 20px; | |||
} | |||
/* line 367, ../sass/order/_order.scss */ | |||
/* line 371, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .delivery .delivery-home { | |||
margin-bottom: 20px; | |||
} | |||
/* line 376, ../sass/order/_order.scss */ | |||
/* line 380, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .comment { | |||
margin-bottom: 20px; | |||
} | |||
/* line 381, ../sass/order/_order.scss */ | |||
/* line 385, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #content-step-payment .credit .info { | |||
margin-left: 20px; | |||
color: gray; | |||
} | |||
/* line 388, ../sass/order/_order.scss */ | |||
/* line 392, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #specific-delays { | |||
margin-top: 15px; | |||
} | |||
/* line 396, ../sass/order/_order.scss */ | |||
/* line 400, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #infos { | |||
margin-top: 30px; | |||
} | |||
/* line 398, ../sass/order/_order.scss */ | |||
/* line 402, ../sass/order/_order.scss */ | |||
.order-order #main #app-order-order #infos .panel-body { | |||
padding-top: 0px; | |||
white-space: pre-line; | |||
} | |||
/* line 408, ../sass/order/_order.scss */ | |||
/* line 412, ../sass/order/_order.scss */ | |||
#main #content .panel h3 { | |||
font-family: "highvoltageregular"; | |||
margin: 0px; |
@@ -250,10 +250,10 @@ var app = new Vue({ | |||
if(response.data.categories) { | |||
app.categories = response.data.categories ; | |||
if(app.countProductsByCategory(response.data.categories[0])) { | |||
app.setCategoryCurrent(response.data.categories[0]) ; | |||
app.setCategoryCurrent(response.data.categories[0], true) ; | |||
} | |||
else { | |||
app.setCategoryCurrent(response.data.categories[1]) ; | |||
app.setCategoryCurrent(response.data.categories[1], true) ; | |||
} | |||
} | |||
@@ -611,8 +611,8 @@ var app = new Vue({ | |||
return count ; | |||
}, | |||
setCategoryCurrent: function(category) { | |||
if(this.categoryCurrent && this.categoryCurrent.id == category.id) { | |||
setCategoryCurrent: function(category, first) { | |||
if(this.categoryCurrent && this.categoryCurrent.id == category.id && !first) { | |||
this.categoryCurrent = null ; | |||
} | |||
else { |
@@ -221,6 +221,10 @@ | |||
.comment { | |||
color: gray; | |||
a { | |||
color: $color1; | |||
} | |||
} | |||
} | |||
@@ -4,3 +4,10 @@ | |||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. | |||
class_name: UnitTester | |||
modules: | |||
enabled: | |||
- Asserts | |||
- Yii2 | |||
config: | |||
Yii2: | |||
configFile: '../config/common/unit.php' |
@@ -0,0 +1,25 @@ | |||
<?php | |||
namespace tests\codeception\common\unit; | |||
//use \Tests\Support\UnitTester; | |||
use common\logic\Producer\Producer\Model\Producer; | |||
use common\logic\Producer\Producer\Wrapper\ProducerContainer; | |||
use tests\codeception\common\UnitTester; | |||
class ExampleTest extends \Codeception\Test\Unit | |||
{ | |||
protected UnitTester $tester; | |||
protected function _before() | |||
{ | |||
} | |||
public function testMe() | |||
{ | |||
$producerContainer = ProducerContainer::getInstance(); | |||
$producer = $producerContainer->getBuilder()->instanciateProducer(); | |||
$this->assertTrue($producer instanceof Producer, 'Producer instancié'); | |||
} | |||
} |
@@ -2,4 +2,11 @@ | |||
/** | |||
* Application configuration for all backend test types | |||
*/ | |||
return []; | |||
return [ | |||
'components' => [ | |||
'view' => [ | |||
'class' => 'common\components\ViewBackend', | |||
], | |||
], | |||
]; |
@@ -3,4 +3,10 @@ | |||
* Application configuration for all frontend test types | |||
*/ | |||
return []; | |||
return [ | |||
'components' => [ | |||
'view' => [ | |||
'class' => 'common\components\ViewFrontend', | |||
], | |||
], | |||
]; |
@@ -3,4 +3,10 @@ | |||
* Application configuration for all frontend test types | |||
*/ | |||
return []; | |||
return [ | |||
'components' => [ | |||
'view' => [ | |||
'class' => 'producer\components\ProducerView', | |||
], | |||
], | |||
]; |
@@ -9,7 +9,7 @@ $I = new FunctionalTester($scenario); | |||
$contactPage = ContactPage::openBy($I); | |||
$I->wantTo("m'assurer que le formulaire de contact fonctionne"); | |||
$I->see('Me contacter', 'h1'); | |||
$I->see('Contact', 'h1'); | |||
$I->amGoingTo("envoyer un message"); | |||
$contactPage->submit([ | |||
@@ -19,4 +19,4 @@ $contactPage->submit([ | |||
'body' => 'Message', | |||
'isTest' => 'isTest' | |||
]); | |||
$I->see('Votre message a bien été envoyé', '.alert-success'); | |||
$I->see('Merci pour votre message', '.alert-success'); |
@@ -6,6 +6,4 @@ use tests\codeception\frontend\FunctionalTester; | |||
$I = new FunctionalTester($scenario); | |||
$I->wantTo("m'assurer que la page d'accueil s'affiche"); | |||
$I->amOnPage('site/index'); | |||
$I->see('distribution alimentaire', 'h1'); | |||
$I->see('Fonctionnalités', '.the-title'); | |||
$I->see('Tarifs', '.the-title'); | |||
$I->see('un outil pour organiser des ventes en circuit court', 'h1'); |
@@ -1,9 +0,0 @@ | |||
<?php | |||
use tests\codeception\frontend\FunctionalTester; | |||
/* @var $scenario Codeception\Scenario */ | |||
$I = new FunctionalTester($scenario); | |||
$I->wantTo("m'assurer que la page des tarifs s'affiche"); | |||
$I->amOnPage('site/prices'); | |||
$I->see('Tarifs', 'h1'); |
@@ -0,0 +1,9 @@ | |||
<?php | |||
use tests\codeception\frontend\FunctionalTester; | |||
/* @var $scenario Codeception\Scenario */ | |||
$I = new FunctionalTester($scenario); | |||
$I->wantTo("m'assurer que la page 'fonctionnalités, services & tarifs' fonctionne"); | |||
$I->amOnPage('site/service'); | |||
$I->see('Fonctionnalités, services & tarifs', 'h1'); |
@@ -23,11 +23,11 @@ $signupPage->submit([ | |||
'id_producer' => '32', | |||
'is_test' => 'isTest' | |||
]); | |||
$I->see('Inscription confirmée', 'h1'); | |||
$I->see('Votre inscription a bien été prise en compte', '.alert-success'); | |||
$I->amOnPage('logout'); | |||
$I->see('distribution alimentaire', 'h1'); | |||
$I->see('un outil pour organiser des ventes en circuit court', 'h1'); | |||
$I->amOnPage($signupPage->route); | |||
@@ -47,4 +47,4 @@ $signupPage->submit([ | |||
'cgv' => '1', | |||
'is_test' => 'isTest' | |||
]); | |||
$I->see('Inscription confirmée', 'h1'); | |||
$I->see('Votre inscription a bien été prise en compte', '.alert-success'); |