Преглед на файлове

Merge branch 'develop'

master
Guillaume Bourgeois преди 1 година
родител
ревизия
5307ee8589
променени са 61 файла, в които са добавени 4198 реда и са изтрити 473 реда
  1. +9
    -0
      backend/config/test-local.php
  2. +1
    -0
      backend/controllers/DashboardController.php
  3. +9
    -2
      backend/controllers/DocumentController.php
  4. +7
    -12
      backend/controllers/ProducerAdminController.php
  5. +18
    -0
      backend/controllers/ProducerController.php
  6. +12
    -48
      backend/controllers/StatsController.php
  7. +53
    -0
      backend/views/dashboard/index.php
  8. +1
    -1
      backend/views/distribution/index.php
  9. +142
    -195
      backend/views/producer-admin/index.php
  10. +4
    -0
      backend/views/producer/update.php
  11. +12
    -1
      backend/views/stats/index.php
  12. +1
    -1
      backend/views/stats/products.php
  13. +7
    -48
      backend/views/subscription/index.php
  14. +6
    -0
      backend/views/user/index.php
  15. +12
    -7
      backend/web/css/screen.css
  16. +21
    -0
      backend/web/js/backend.js
  17. +14
    -2
      backend/web/js/vuejs/distribution-index.js
  18. +5
    -0
      backend/web/sass/_adminlte.scss
  19. +18
    -11
      common/components/AlwaysdataClient.php
  20. +1
    -1
      common/components/BusinessLogic.php
  21. +39
    -0
      common/components/PageSizer.php
  22. +6
    -0
      common/config/main.php
  23. +1
    -1
      common/config/params.php
  24. +4
    -1
      common/forms/SubscriptionForm.php
  25. +15
    -16
      common/logic/Distribution/Distribution/Service/DistributionReportPdfGenerator.php
  26. +1
    -22
      common/logic/Order/Order/Repository/OrderRepository.php
  27. +1
    -0
      common/logic/PointSale/PointSale/Service/PointSaleSolver.php
  28. +3
    -1
      common/logic/Producer/Producer/Model/Producer.php
  29. +72
    -15
      common/logic/Producer/Producer/Repository/ProducerRepository.php
  30. +47
    -0
      common/logic/Producer/Producer/Service/ProducerPageSizer.php
  31. +1
    -0
      common/logic/Producer/Producer/Service/ProducerSolver.php
  32. +7
    -0
      common/logic/Producer/Producer/Wrapper/ProducerContainer.php
  33. +2
    -0
      common/logic/Producer/Producer/Wrapper/ProducerManager.php
  34. +30
    -5
      common/logic/Subscription/Subscription/Model/Subscription.php
  35. +8
    -0
      common/logic/Subscription/Subscription/Repository/SubscriptionRepository.php
  36. +14
    -0
      common/logic/Subscription/Subscription/Repository/SubscriptionRepositoryQuery.php
  37. +6
    -4
      common/logic/Subscription/Subscription/Service/SubscriptionBuilder.php
  38. +80
    -0
      common/logic/Subscription/Subscription/Service/SubscriptionSolver.php
  39. +6
    -2
      common/logic/User/User/Model/UserSearch.php
  40. +31
    -0
      common/versions/23.10.B.php
  41. +26
    -0
      console/migrations/m231004_083707_add_column_producer_option_invoice_only_based_on_delivery_notes.php
  42. +26
    -0
      console/migrations/m231005_072832_add_column_producer_option_pagesize_user.php
  43. +32
    -0
      console/migrations/m231006_084312_add_columns_subscription_created_updated.php
  44. +1
    -1
      frontend/views/site/signup_confirm.php
  45. +1
    -1
      producer/controllers/CreditController.php
  46. +0
    -1
      producer/controllers/OrderController.php
  47. +4
    -19
      producer/views/subscription/index.php
  48. +34
    -30
      producer/web/css/screen.css
  49. +4
    -4
      producer/web/js/vuejs/order-order.js
  50. +4
    -0
      producer/web/sass/order/_order.scss
  51. +3270
    -1
      tests/codeception/common/_support/_generated/UnitTesterActions.php
  52. +7
    -0
      tests/codeception/common/unit.suite.yml
  53. +25
    -0
      tests/codeception/common/unit/ExampleTest.php
  54. +8
    -1
      tests/codeception/config/backend/config.php
  55. +7
    -1
      tests/codeception/config/frontend/config.php
  56. +7
    -1
      tests/codeception/config/producer/config.php
  57. +2
    -2
      tests/codeception/frontend/functional/ContactCept.php
  58. +1
    -3
      tests/codeception/frontend/functional/HomeCept.php
  59. +0
    -9
      tests/codeception/frontend/functional/PricesCept.php
  60. +9
    -0
      tests/codeception/frontend/functional/ServiceCept.php
  61. +3
    -3
      tests/codeception/frontend/functional/SignupCept.php

+ 9
- 0
backend/config/test-local.php Целия файл

@@ -0,0 +1,9 @@
<?php

return [
'components' => [
'view' => [
'class' => 'common\components\ViewBackend',
],
],
];

+ 1
- 0
backend/controllers/DashboardController.php Целия файл

@@ -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()
]);
}
}

+ 9
- 2
backend/controllers/DocumentController.php Целия файл

@@ -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') {

+ 7
- 12
backend/controllers/ProducerAdminController.php Целия файл

@@ -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)

+ 18
- 0
backend/controllers/ProducerController.php Целия файл

@@ -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);
}

}

+ 12
- 48
backend/controllers/StatsController.php Целия файл

@@ -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
]);
}


+ 53
- 0
backend/views/dashboard/index.php Целия файл

@@ -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="">

+ 1
- 1
backend/views/distribution/index.php Целия файл

@@ -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">

+ 142
- 195
backend/views/producer-admin/index.php Целия файл

@@ -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 . '&nbsp;%';
}
}
$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 . '&nbsp;%';
}
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>

+ 4
- 0
backend/views/producer/update.php Целия файл

@@ -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'

+ 12
- 1
backend/views/stats/index.php Целия файл

@@ -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' => [

+ 1
- 1
backend/views/stats/products.php Целия файл

@@ -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' => '&lt; '.($year - 1), 'url' => ['stats/products','year' => $year - 1], 'class' => 'btn btn-default']) ;
$this->addButton(['label' => ($year + 1).' &gt;', 'url' => ['stats/products','year' => $year + 1], 'class' => 'btn btn-default']) ;

+ 7
- 48
backend/views/subscription/index.php Целия файл

@@ -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&nbsp;' ;
}
else {
$html .= 'À partir du ' ;
}
$html .= '</small>' ;
$html .= date('d/m/Y',strtotime($model->date_begin)) ;
if($model->date_end) {
$html .= '<br />au&nbsp;'.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);
}
],
[

+ 6
- 0
backend/views/user/index.php Целия файл

@@ -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',

+ 12
- 7
backend/web/css/screen.css Целия файл

@@ -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;
}

+ 21
- 0
backend/web/js/backend.js Целия файл

@@ -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() {

+ 14
- 2
backend/web/js/vuejs/distribution-index.js Целия файл

@@ -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) {

+ 5
- 0
backend/web/sass/_adminlte.scss Целия файл

@@ -307,6 +307,11 @@ body.skin-black {
color: $color1 ;
}
}

.gridview-pagesize {
float: right;
margin-bottom: 8px;
}
}

body.login-page {

common/helpers/Alwaysdata.php → common/components/AlwaysdataClient.php Целия файл

@@ -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')

+ 1
- 1
common/components/BusinessLogic.php Целия файл

@@ -35,8 +35,8 @@ class BusinessLogic
$this->getDeliveryNoteContainer(),
$this->getDocumentContainer(),
$this->getPointSaleContainer(),
$this->getSubscriptionContainer(),
$this->getProductContainer(),
$this->getSubscriptionContainer(),
$this->getDistributionContainer(),
$this->getProducerContainer(),
$this->getOrderContainer(),

+ 39
- 0
common/components/PageSizer.php Целия файл

@@ -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);
}

}

+ 6
- 0
common/config/main.php Целия файл

@@ -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,
],

+ 1
- 1
common/config/params.php Целия файл

@@ -37,7 +37,7 @@
*/

return [
'version' => '23.10.A',
'version' => '23.10.B',
'siteName' => 'Opendistrib',
'adminEmail' => 'contact@opendistrib.net',
'supportEmail' => 'contact@opendistrib.net',

+ 4
- 1
common/forms/SubscriptionForm.php Целия файл

@@ -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) {

+ 15
- 16
common/logic/Distribution/Distribution/Service/DistributionReportPdfGenerator.php Целия файл

@@ -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.') ? '' : '&nbsp;'. $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.') ? '' : '&nbsp;'. $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.') ? '' : '&nbsp;'. $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.') ? '' : '&nbsp;'. $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.') ? '' : '&nbsp;'. $this->productSolver->strUnit($unit, 'wording_short', true) ;
return '<strong>'.$quantity. $theUnit.'</strong> '.$this->productSolver->getNameExport($product). '<br />';
}
}

+ 1
- 22
common/logic/Order/Order/Repository/OrderRepository.php Целия файл

@@ -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;
}


+ 1
- 0
common/logic/PointSale/PointSale/Service/PointSaleSolver.php Целия файл

@@ -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;
}

+ 3
- 1
common/logic/Producer/Producer/Model/Producer.php Целия файл

@@ -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'
];
}


+ 72
- 15
common/logic/Producer/Producer/Repository/ProducerRepository.php Целия файл

@@ -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;
}


+ 47
- 0
common/logic/Producer/Producer/Service/ProducerPageSizer.php Целия файл

@@ -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);
}
}
}

+ 1
- 0
common/logic/Producer/Producer/Service/ProducerSolver.php Целия файл

@@ -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
- 0
common/logic/Producer/Producer/Wrapper/ProducerContainer.php Целия файл

@@ -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();
}
}

+ 2
- 0
common/logic/Producer/Producer/Wrapper/ProducerManager.php Целия файл

@@ -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

+ 30
- 5
common/logic/Subscription/Subscription/Model/Subscription.php Целия файл

@@ -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');
}
}

+ 8
- 0
common/logic/Subscription/Subscription/Repository/SubscriptionRepository.php Целия файл

@@ -67,4 +67,12 @@ class SubscriptionRepository extends AbstractRepository
->filterByUser($user)
->count();
}

public function findSubscriptionsLatestAdded()
{
return $this->createDefaultQuery()
->filterByCreatedDuringPastWeek()
->filterByCreatedByUser()
->find();
}
}

+ 14
- 0
common/logic/Subscription/Subscription/Repository/SubscriptionRepositoryQuery.php Целия файл

@@ -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
- 4
common/logic/Subscription/Subscription/Service/SubscriptionBuilder.php Целия файл

@@ -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;
}

+ 80
- 0
common/logic/Subscription/Subscription/Service/SubscriptionSolver.php Целия файл

@@ -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']) . '&nbsp'. $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&nbsp;' ;
}
else {
$html .= 'À partir du ' ;
}
$html .= '</small>' ;
$html .= date('d/m/Y',strtotime($subscription->date_begin)) ;
if($subscription->date_end) {
$html .= '<br />au&nbsp;'.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' ;
}
}
}

+ 6
- 2
common/logic/User/User/Model/UserSearch.php Целия файл

@@ -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),
],
]);


+ 31
- 0
common/versions/23.10.B.php Целия файл

@@ -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"
],
[]
],
);

?>

+ 26
- 0
console/migrations/m231004_083707_add_column_producer_option_invoice_only_based_on_delivery_notes.php Целия файл

@@ -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');
}
}

+ 26
- 0
console/migrations/m231005_072832_add_column_producer_option_pagesize_user.php Целия файл

@@ -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');
}
}

+ 32
- 0
console/migrations/m231006_084312_add_columns_subscription_created_updated.php Целия файл

@@ -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');
}
}

+ 1
- 1
frontend/views/site/signup_confirm.php Целия файл

@@ -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) {

+ 1
- 1
producer/controllers/CreditController.php Целия файл

@@ -327,7 +327,7 @@ class CreditController extends ProducerBaseController
http_response_code(200);
}
else {
http_response_code(400);
http_response_code(200);
}

die();

+ 0
- 1
producer/controllers/OrderController.php Целия файл

@@ -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();


+ 4
- 19
producer/views/subscription/index.php Целия файл

@@ -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']) . '&nbsp'. $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);
}
],
[

+ 34
- 30
producer/web/css/screen.css Целия файл

@@ -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;

+ 4
- 4
producer/web/js/vuejs/order-order.js Целия файл

@@ -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 {

+ 4
- 0
producer/web/sass/order/_order.scss Целия файл

@@ -221,6 +221,10 @@

.comment {
color: gray;

a {
color: $color1;
}
}
}

+ 3270
- 1
tests/codeception/common/_support/_generated/UnitTesterActions.php
Файловите разлики са ограничени, защото са твърде много
Целия файл


+ 7
- 0
tests/codeception/common/unit.suite.yml Целия файл

@@ -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'

+ 25
- 0
tests/codeception/common/unit/ExampleTest.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é');
}
}

+ 8
- 1
tests/codeception/config/backend/config.php Целия файл

@@ -2,4 +2,11 @@
/**
* Application configuration for all backend test types
*/
return [];

return [
'components' => [
'view' => [
'class' => 'common\components\ViewBackend',
],
],
];

+ 7
- 1
tests/codeception/config/frontend/config.php Целия файл

@@ -3,4 +3,10 @@
* Application configuration for all frontend test types
*/

return [];
return [
'components' => [
'view' => [
'class' => 'common\components\ViewFrontend',
],
],
];

+ 7
- 1
tests/codeception/config/producer/config.php Целия файл

@@ -3,4 +3,10 @@
* Application configuration for all frontend test types
*/

return [];
return [
'components' => [
'view' => [
'class' => 'producer\components\ProducerView',
],
],
];

+ 2
- 2
tests/codeception/frontend/functional/ContactCept.php Целия файл

@@ -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');

+ 1
- 3
tests/codeception/frontend/functional/HomeCept.php Целия файл

@@ -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');

+ 0
- 9
tests/codeception/frontend/functional/PricesCept.php Целия файл

@@ -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');

+ 9
- 0
tests/codeception/frontend/functional/ServiceCept.php Целия файл

@@ -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');

+ 3
- 3
tests/codeception/frontend/functional/SignupCept.php Целия файл

@@ -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');

Loading…
Отказ
Запис