Sfoglia il codice sorgente

Merge branch 'feature/support' into develop

feature/souke
Guillaume Bourgeois 1 anno fa
parent
commit
33a00a843f
44 ha cambiato i file con 2417 aggiunte e 472 eliminazioni
  1. +87
    -0
      backend/controllers/SupportAdminController.php
  2. +151
    -0
      backend/controllers/SupportController.php
  3. +69
    -36
      backend/views/layouts/left.php
  4. +60
    -0
      backend/views/support/create.php
  5. +235
    -0
      backend/views/support/index.php
  6. +89
    -0
      backend/views/support/view.php
  7. +411
    -417
      backend/web/css/screen.css
  8. +22
    -3
      backend/web/sass/_adminlte.scss
  9. +10
    -0
      backend/web/sass/screen.scss
  10. +29
    -0
      backend/web/sass/support/_index.scss
  11. +19
    -0
      backend/web/sass/support/_view.scss
  12. +3
    -0
      common/components/BusinessLogic.php
  13. +36
    -0
      common/components/BusinessLogicTrait.php
  14. +7
    -0
      common/components/View.php
  15. +1
    -0
      common/config/main.php
  16. +25
    -7
      common/logic/AbstractRepository.php
  17. +8
    -0
      common/logic/AbstractSolver.php
  18. +0
    -1
      common/logic/Subscription/ProductSubscription/Repository/ProductSubscriptionRepository.php
  19. +0
    -1
      common/logic/Subscription/ProductSubscription/Repository/ProductSubscriptionRepositoryQuery.php
  20. +7
    -7
      common/logic/Subscription/ProductSubscription/Wrapper/ProductSubscriptionManager.php
  21. +125
    -0
      common/logic/Ticket/Ticket/Model/Ticket.php
  22. +93
    -0
      common/logic/Ticket/Ticket/Model/TicketSearch.php
  23. +52
    -0
      common/logic/Ticket/Ticket/Repository/TicketRepository.php
  24. +16
    -0
      common/logic/Ticket/Ticket/Repository/TicketRepositoryQuery.php
  25. +78
    -0
      common/logic/Ticket/Ticket/Service/TicketBuilder.php
  26. +14
    -0
      common/logic/Ticket/Ticket/Service/TicketDefinition.php
  27. +113
    -0
      common/logic/Ticket/Ticket/Service/TicketSolver.php
  28. +42
    -0
      common/logic/Ticket/Ticket/Wrapper/TicketContainer.php
  29. +23
    -0
      common/logic/Ticket/Ticket/Wrapper/TicketManager.php
  30. +105
    -0
      common/logic/Ticket/TicketMessage/Model/TicketMessage.php
  31. +28
    -0
      common/logic/Ticket/TicketMessage/Repository/TicketMessageRepository.php
  32. +16
    -0
      common/logic/Ticket/TicketMessage/Repository/TicketMessageRepositoryQuery.php
  33. +30
    -0
      common/logic/Ticket/TicketMessage/Service/TicketMessageBuilder.php
  34. +14
    -0
      common/logic/Ticket/TicketMessage/Service/TicketMessageDefinition.php
  35. +35
    -0
      common/logic/Ticket/TicketMessage/Wrapper/TicketMessageContainer.php
  36. +21
    -0
      common/logic/Ticket/TicketMessage/Wrapper/TicketMessageManager.php
  37. +103
    -0
      common/logic/Ticket/TicketUser/Model/TicketUser.php
  38. +39
    -0
      common/logic/Ticket/TicketUser/Repository/TicketUserRepository.php
  39. +30
    -0
      common/logic/Ticket/TicketUser/Repository/TicketUserRepositoryQuery.php
  40. +49
    -0
      common/logic/Ticket/TicketUser/Service/TicketUserBuilder.php
  41. +14
    -0
      common/logic/Ticket/TicketUser/Service/TicketUserDefinition.php
  42. +35
    -0
      common/logic/Ticket/TicketUser/Wrapper/TicketUserContainer.php
  43. +21
    -0
      common/logic/Ticket/TicketUser/Wrapper/TicketUserManager.php
  44. +52
    -0
      console/migrations/m230717_120138_module_ticket.php

+ 87
- 0
backend/controllers/SupportAdminController.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace backend\controllers;

use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\Ticket\Model\TicketSearch;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;

/**
* UserController implements the CRUD actions for User model.
*/
class SupportAdminController extends SupportController
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [],
],
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return $this->getUserManager()->isCurrentAdmin();
}
]
],
],
];
}

public function actionIndex()
{
$searchTicket = new TicketSearch();
$dataProviderTicketOpen = $searchTicket->search('admin', ['TicketSearch' => ['status' => Ticket::STATUS_OPEN]]);
$dataProviderTicketClosed = $searchTicket->search('admin', ['TicketSearch' => ['status' => Ticket::STATUS_CLOSED]]);

return $this->render('@backend/views/support/index', [
'context' => 'admin',
'searchTicket' => $searchTicket,
'dataProviderTicketOpen' => $dataProviderTicketOpen,
'dataProviderTicketClosed' => $dataProviderTicketClosed
]);
}

}

+ 151
- 0
backend/controllers/SupportController.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace backend\controllers;

use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\Ticket\Model\TicketSearch;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
use yii\helpers\Html;
use yii\web\NotFoundHttpException;

class SupportController extends BackendController
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::class,
'actions' => [
],
],
'access' => [
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
'roles' => ['@'],
'matchCallback' => function ($rule, $action) {
return $this->getUserManager()->hasAccessBackend();
}
]
],
],
];
}

public function actionIndex()
{
$searchTicket = new TicketSearch();
$dataProviderTicketOpen = $searchTicket->search('producer', ['TicketSearch' => ['status' => Ticket::STATUS_OPEN]]);
$dataProviderTicketClosed = $searchTicket->search('producer', ['TicketSearch' => ['status' => Ticket::STATUS_CLOSED]]);

return $this->render('index', [
'context' => 'producer',
'searchTicket' => $searchTicket,
'dataProviderTicketOpen' => $dataProviderTicketOpen,
'dataProviderTicketClosed' => $dataProviderTicketClosed
]);
}

public function actionCreate()
{
$userCurrent = $this->getUserCurrent();
$ticketManager = $this->getTicketManager();
$ticketMessageManager = $this->getTicketMessageManager();
$ticket = $ticketManager->instanciateTicket($this->getProducerCurrent(), $userCurrent);

if ($ticket->load(\Yii::$app->request->post()) && $ticketManager->saveCreate($ticket)) {
$ticketMessageManager->createTicketMessage($ticket, $userCurrent, $ticket->message);
$this->setFlash('success', 'Le ticket a bien été créé.');
return $this->redirect(['view', 'id' => $ticket->id]);
} else {
return $this->render('@backend/views/support/create', [
'ticket' => $ticket,
]);
}
}

public function actionView(int $id)
{
$ticketManager = $this->getTicketManager();
$ticketMessageManager = $this->getTicketMessageManager();
$ticket = $this->findTicket($id);
$ticketManager->viewTicket($ticket, $this->getUserCurrent());
$ticketMessage = $ticketMessageManager->instanciateTicketMessage($ticket, $this->getUserCurrent());
if ($ticketMessage->load(\Yii::$app->request->post()) && $ticketManager->createTicketMessage($ticketMessage)) {
return $this->redirect(['view', 'id' => $ticket->id, '#' => 'bottom']);
}

return $this->render('@backend/views/support/view', [
'ticket' => $ticket,
'ticketMessageResponse' => $ticketMessage
]);
}

public function actionClose(int $id)
{
$ticketManager = $this->getTicketManager();
$ticket = $this->findTicket($id);
$ticketManager->closeTicket($ticket);
$this->addFlash('success', "Le ticket <strong>".Html::encode($ticket->subject)."</strong> a bien été fermé.");
return $this->redirect(['index']);
}

public function actionOpen(int $id)
{
$ticketManager = $this->getTicketManager();
$ticket = $this->findTicket($id);
$ticketManager->openTicket($ticket);
$this->addFlash('success', "Le ticket a bien été ouvert.");
return $this->redirect(['index']);
}

public function findTicket(int $id)
{
$ticketManager = $this->getTicketManager();
$ticket = $ticketManager->findOneTicketById($id);

if ($ticket && $ticketManager->hasTicketAccess($ticket, $this->getUserCurrent())) {
return $ticket;
} else {
throw new NotFoundHttpException("Le ticket est introuvable.");
}
}
}

+ 69
- 36
backend/views/layouts/left.php Vedi File

@@ -39,9 +39,11 @@
use common\helpers\GlobalParam;
use common\helpers\Opendistrib;
use yii\helpers\Html;
use common\logic\Ticket\Ticket\Wrapper\TicketManager;

$producerManager = $this->getProducerManager();
$userManager = $this->getUserManager();
$ticketManager = $this->getTicketManager();
$producer = GlobalParam::getCurrentProducer();

?>
@@ -50,50 +52,73 @@ $producer = GlobalParam::getCurrentProducer();

<section class="sidebar">
<?php
$newVersionOpendistribTemplate = '';
if($producer && !$producerManager->isUpToDateWithOpendistribVersion($producer)) {
$newVersionOpendistribTemplate = '<span class="pull-right-container"><small class="label pull-right bg-yellow">'.GlobalParam::getOpendistribVersion().'</small></span>';
}
$producer = GlobalParam::getCurrentProducer();
$newVersionOpendistribLabel = '';
if ($producer && !$producerManager->isUpToDateWithOpendistribVersion($producer)) {
$newVersionOpendistribLabel = '<span class="pull-right-container"><small class="label pull-right bg-green">'.GlobalParam::getOpendistribVersion().'</small></span>';
}

$countTicketsProducerUnreadLabel = '';
$countTicketsProducerUnread = $ticketManager->countTicketsUnreadByUser($this->getUserCurrent());
if($countTicketsProducerUnread && !$userManager->isCurrentAdmin()) {
$countTicketsProducerUnreadLabel = '<span class="pull-right-container"><small class="label pull-right bg-green">'.$countTicketsProducerUnread.'</small></span>';
}

$countTicketsAdminUnreadLabel = '';
$countTicketsAdminUnread = $ticketManager->countTicketsAdminUnreadByUser($this->getUserCurrent());
if($countTicketsAdminUnread && $userManager->isCurrentAdmin()) {
$countTicketsAdminUnreadLabel = '<span class="pull-right-container"><small class="label pull-right bg-green">'.$countTicketsAdminUnread.'</small></span>';
}

?>

<?= dmstr\widgets\Menu::widget(
[
'options' => ['class' => 'sidebar-menu tree', 'data-widget' => 'tree'],
'items' => [
['label' => 'Tableau de bord', 'icon' => 'dashboard', 'url' => ['/site/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Distributions', 'icon' => 'calendar', 'url' => ['/distribution/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => "Besoin d'aide ?", 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentProducer()],
[
'label' => 'Support',
'icon' => 'comments',
'url' => ['support/index'],
'visible' => $userManager->isCurrentProducer(),
'template' => '<a href="{url}">{icon} {label}' . $countTicketsProducerUnreadLabel . '</a>'
],
['label' => $producer->name, 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Tableau de bord', 'icon' => 'dashboard', 'url' => ['/site/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Distributions', 'icon' => 'calendar', 'url' => ['/distribution/index'], 'visible' => $userManager->isCurrentProducer()],
[
'label' => 'Produits',
'icon' => 'clone',
'url' => ['/product/index'],
'visible' => $userManager->isCurrentProducer(),
'visible' => $userManager->isCurrentProducer(),
'active' => Yii::$app->controller->id == 'product',
'items' => [
['label' => 'Liste', 'icon' => 'th-list', 'url' => ['/product/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Catégories', 'icon' => 'book', 'url' => ['/product-category/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Import prix', 'icon' => 'upload', 'url' => ['/product/price-import'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Liste', 'icon' => 'th-list', 'url' => ['/product/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Catégories', 'icon' => 'book', 'url' => ['/product-category/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Import prix', 'icon' => 'upload', 'url' => ['/product/price-import'], 'visible' => $userManager->isCurrentProducer()],
]
],
['label' => 'Points de vente', 'icon' => 'map-marker', 'url' => ['/point-sale/index'], 'visible' => $userManager->isCurrentProducer(), 'active' => Yii::$app->controller->id == 'point-sale'],
['label' => 'Points de vente', 'icon' => 'map-marker', 'url' => ['/point-sale/index'], 'visible' => $userManager->isCurrentProducer(), 'active' => Yii::$app->controller->id == 'point-sale'],
[
'label' => 'Utilisateurs',
'icon' => 'users',
'url' => ['/user/index'],
'items' => [
['label' => 'Liste', 'icon' => 'th-list', 'url' => ['/user/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Groupes', 'icon' => 'users', 'url' => ['/user-group/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Liste', 'icon' => 'th-list', 'url' => ['/user/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Groupes', 'icon' => 'users', 'url' => ['/user-group/index'], 'visible' => $userManager->isCurrentProducer()],
],
],
['label' => 'Abonnements', 'icon' => 'repeat', 'url' => ['/subscription/index'], 'visible' => $userManager->isCurrentProducer(), 'active' => Yii::$app->controller->id == 'subscription'],
['label' => 'Communiquer', 'icon' => 'bullhorn', 'url' => ['/communicate/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Abonnements', 'icon' => 'repeat', 'url' => ['/subscription/index'], 'visible' => $userManager->isCurrentProducer(), 'active' => Yii::$app->controller->id == 'subscription'],
['label' => 'Communiquer', 'icon' => 'bullhorn', 'url' => ['/communicate/index'], 'visible' => $userManager->isCurrentProducer()],
[
'label' => 'Documents',
'icon' => 'clone',
'url' => ['/delivery-note/index'],
'items' => [
['label' => 'Bons de livraison', 'icon' => 'sticky-note-o', 'url' => ['/delivery-note/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Factures', 'icon' => 'sticky-note-o', 'url' => ['/invoice/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Devis', 'icon' => 'sticky-note-o', 'url' => ['/quotation/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Bons de livraison', 'icon' => 'sticky-note-o', 'url' => ['/delivery-note/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Factures', 'icon' => 'sticky-note-o', 'url' => ['/invoice/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Devis', 'icon' => 'sticky-note-o', 'url' => ['/quotation/index'], 'visible' => $userManager->isCurrentProducer()],
],
],
[
@@ -101,25 +126,33 @@ $producer = GlobalParam::getCurrentProducer();
'icon' => 'line-chart',
'url' => ['/stats/index'],
'items' => [
['label' => 'Chiffre d\'affaire', 'icon' => 'line-chart', 'url' => ['/stats/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Rapports', 'icon' => 'pencil-square-o', 'url' => ['/report/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Produits', 'icon' => 'table', 'url' => ['/stats/products'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Chiffre d\'affaire', 'icon' => 'line-chart', 'url' => ['/stats/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Rapports', 'icon' => 'pencil-square-o', 'url' => ['/report/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Produits', 'icon' => 'table', 'url' => ['/stats/products'], 'visible' => $userManager->isCurrentProducer()],
],
],
['label' => 'Paramètres', 'icon' => 'cog', 'url' => ['/producer/update'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Accès', 'icon' => 'lock', 'url' => ['/access/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Paramètres', 'icon' => 'cog', 'url' => ['/producer/update'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Accès', 'icon' => 'lock', 'url' => ['/access/index'], 'visible' => $userManager->isCurrentProducer()],
['label' => "Opendistrib", 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentProducer()],
[
'label' => 'Développement',
'icon' => 'code',
'url' => ['/development/index'],
'visible' => $userManager->isCurrentProducer(),
'active' => Yii::$app->controller->id == 'development',
'template'=>'<a href="{url}">{icon} {label}'.$newVersionOpendistribTemplate.'</a>'
'label' => 'Développement',
'icon' => 'code',
'url' => ['/development/index'],
'visible' => $userManager->isCurrentProducer(),
'active' => Yii::$app->controller->id == 'development',
'template' => '<a href="{url}">{icon} {label}' . $newVersionOpendistribLabel . '</a>'
],
['label' => 'Tarifs', 'icon' => 'euro', 'url' => ['/producer/billing'], 'visible' => $userManager->isCurrentProducer()],
['label' => 'Tarifs', 'icon' => 'euro', 'url' => ['/producer/billing'], 'visible' => $userManager->isCurrentProducer()],

['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Producteurs', 'icon' => 'th-list', 'url' => ['/producer-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Administration', 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentAdmin()],
[
'label' => 'Tickets',
'icon' => 'comments',
'url' => ['support-admin/index'],
'visible' => $userManager->isCurrentAdmin(),
'template' => '<a href="{url}">{icon} {label}' . $countTicketsAdminUnreadLabel . '</a>'
],
['label' => 'Producteurs', 'icon' => 'th-list', 'url' => ['/producer-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
[
'label' => 'Statistiques',
'icon' => 'line-chart',
@@ -132,14 +165,14 @@ $producer = GlobalParam::getCurrentProducer();
],
],

['label' => 'Tranches de prix', 'icon' => 'eur', 'url' => ['/producer-price-range-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Taxes', 'icon' => 'eur', 'url' => ['/tax-rate-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Communiquer', 'icon' => 'bullhorn', 'url' => ['/communicate-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Tranches de prix', 'icon' => 'eur', 'url' => ['/producer-price-range-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Taxes', 'icon' => 'eur', 'url' => ['/tax-rate-admin/index'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Communiquer', 'icon' => 'bullhorn', 'url' => ['/communicate-admin/index'], 'visible' => $userManager->isCurrentAdmin()],

//['label' => 'Outils', 'options' => ['class' => 'header'], 'visible' => $userManager->isCurrentAdmin()],
//['label' => 'Gii', 'icon' => 'file-code-o', 'url' => ['/gii'], 'visible' => $userManager->isCurrentAdmin()],
//['label' => 'Debug', 'icon' => 'dashboard', 'url' => ['/debug'], 'visible' => $userManager->isCurrentAdmin()],
['label' => 'Login', 'url' => ['site/login'], 'visible' => ! $userManager->isCurrentConnected()],
['label' => 'Login', 'url' => ['site/login'], 'visible' => !$userManager->isCurrentConnected()],
],
]
) ?>

+ 60
- 0
backend/views/support/create.php Vedi File

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

/**
Copyright distrib (2018)

contact@opendistrib.net

Ce logiciel est un programme informatique servant à aider les producteurs
à distribuer leur production en circuits courts.

Ce logiciel est régi par la licence CeCILL soumise au droit français et
respectant les principes de diffusion des logiciels libres. Vous pouvez
utiliser, modifier et/ou redistribuer ce programme sous les conditions
de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
sur le site "http://www.cecill.info".

En contrepartie de l'accessibilité au code source et des droits de copie,
de modification et de redistribution accordés par cette licence, il n'est
offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
seule une responsabilité restreinte pèse sur l'auteur du programme, le
titulaire des droits patrimoniaux et les concédants successifs.

A cet égard l'attention de l'utilisateur est attirée sur les risques
associés au chargement, à l'utilisation, à la modification et/ou au
développement et à la reproduction du logiciel par l'utilisateur étant
donné sa spécificité de logiciel libre, qui peut le rendre complexe à
manipuler et qui le réserve donc à des développeurs et des professionnels
avertis possédant des connaissances informatiques approfondies. Les
utilisateurs sont donc invités à charger et tester l'adéquation du
logiciel à leurs besoins dans des conditions permettant d'assurer la
sécurité de leurs systèmes et ou de leurs données et, plus généralement,
à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.

Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
pris connaissance de la licence CeCILL, et que vous en avez accepté les
termes.
*/

use yii\helpers\Html;
use yii\widgets\ActiveForm;

$this->setTitle('Créer un ticket') ;
$this->addBreadcrumb(['label' => 'Support', 'url' => ['index']]) ;
$this->addBreadcrumb('Créer un ticket') ;

?>

<div class="ticket-create">
<div class="box">
<?php $form = ActiveForm::begin(); ?>
<div class="box-body">
<?= $form->field($ticket, 'subject'); ?>
<?= $form->field($ticket, 'message')->textarea(['rows' => 6]); ?>
</div>
<div class="box-footer">
<?= Html::submitButton('Créer', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>

+ 235
- 0
backend/views/support/index.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\Ticket\Wrapper\TicketManager;
use yii\helpers\Html;
use yii\grid\GridView;

$ticketManager = TicketManager::getInstance();
$userCurrent = $this->getUserCurrent();
$this->setTitle('Support');
$this->addBreadcrumb($this->getTitle());

?>

<div class="support-index">
<?php if($context == 'producer'): ?>
<div>
<div class="col-md-4">
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-phone"></i></span>
<div class="info-box-content">
<span class="info-box-text">Me contacter directement</span>
<span class="info-box-text">
<br/>
<strong><?= Yii::$app->params['adminPhoneNumber'] ?></strong>
</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-calendar"></i></span>
<div class="info-box-content">
<span class="info-box-text"><br/>
<?= Html::a('Prendre rendez-vous', Yii::$app->params['appointmentUrl'], ['class' => 'btn btn-sm btn-default', 'target' => '_blank']); ?>
</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="info-box">
<span class="info-box-icon bg-yellow"><i class="fa fa-comments"></i></span>
<div class="info-box-content">
<span class="info-box-text"><br/><?= Html::a('Ouvrir un ticket', ['support/create'], ['class' => 'btn btn-sm btn-default']); ?></span>
</div>
</div>
</div>
</div>
<div class="clr"></div>
<?php endif; ?>

<div class="nav-tabs-custom ticket-list">
<ul class="nav nav-tabs pull-right">
<li><a href="#tab_2-2" data-toggle="tab">Fermés <span
class="label label-default"><?= $dataProviderTicketClosed->totalCount ?></span></a></li>
<li class="active"><a href="#tab_1-1" data-toggle="tab">Ouverts <span
class="label label-default"><?= $dataProviderTicketOpen->totalCount ?></span></a></li>
<li class="pull-left header"><i class="fa fa-comments"></i> Tickets</li>
</ul>
<div class="tab-content">
<div class="tab-pane active" id="tab_1-1">
<?= ticketList($context, $searchTicket, $dataProviderTicketOpen, $userCurrent); ?>
</div>
<div class="tab-pane" id="tab_2-2">
<?= ticketList($context, $searchTicket, $dataProviderTicketClosed, $userCurrent); ?>
</div>
</div>
</div>
</div>

<?php

function ticketList($context, $searchTicket, $dataProviderTicket, $userCurrent)
{
$ticketManager = TicketManager::getInstance();

$columnCreatedAt = [
'attribute' => 'created_at',
'headerOptions' => ['class' => 'td-created-at column-hide-on-mobile'],
'value' => function ($ticket) {
return date('d/m/Y', strtotime($ticket->created_at));
}
];
$columnSubject = [
'attribute' => 'subject',
'headerOptions' => ['class' => 'td-subject'],
'format' => 'raw',
'value' => function ($ticket) use ($ticketManager, $userCurrent) {

if($ticketManager->isTicketUnread($ticket, $userCurrent)) {
$firstTicketMessageUnread = $ticketManager->getFirstTicketMessageUnread($ticket, $userCurrent);
$link = '<strong>'.Html::a($ticket->subject, ['view', 'id' => $ticket->id, '#' => $firstTicketMessageUnread->id]).'</strong>';
}
else {
$link = Html::a($ticket->subject, ['view', 'id' => $ticket->id]);
}

return $link;
}
];
$columnLastMessage = [
'label' => 'Dernier message',
'headerOptions' => ['class' => 'td-last-message column-hide-on-mobile'],
'value' => function ($ticket) {
$ticketMessages = $ticket->ticketMessages;
if ($ticketMessages && is_array($ticketMessages)) {
$lastTicketMessage = end($ticketMessages);
$origin = date_create(date('Y-m-d', strtotime($lastTicketMessage->created_at)));
$target = date_create();
$interval = date_diff($origin, $target);
$days = (int)$interval->format('%R%a');

if ($days == 0) {
return "Aujourd'hui";
} elseif ($days == 1) {
return "Hier";
} else {
return $days . ' jours';
}
}

return '';
}
];
$columnMessages = [
'label' => 'Messages',
'headerOptions' => ['class' => 'td-messages column-hide-on-mobile'],
'value' => function ($ticket) {
return count($ticket->ticketMessages);
}
];
$columnButtonActions = [
'class' => 'yii\grid\ActionColumn',
'template' => '{view} {close-open}',
'headerOptions' => ['class' => 'column-actions'],
'contentOptions' => ['class' => 'column-actions'],
'buttons' => [
'view' => function ($url, $ticket) {
$url = ['view', 'id' => $ticket->id];
return Html::a('<span class="glyphicon glyphicon-eye-open"></span>', $url, [
'title' => 'Voir le ticket', 'class' => 'btn btn-default'
]);
},
'close-open' => function ($url, $ticket) use ($ticketManager) {
if ($ticketManager->isTicketOpen($ticket)) {
$title = 'Fermer';
$url = ['close', 'id' => $ticket->id];
$glyphicon = 'glyphicon-folder-close';
} else {
$title = 'Ré-ouvrir';
$url = ['open', 'id' => $ticket->id];
$glyphicon = 'glyphicon-folder-open';
}
return Html::a('<span class="glyphicon ' . $glyphicon . '"></span>', $url, [
'title' => $title, 'class' => 'btn btn-default'
]);
}
],
];
$columnProducer = [
'attribute' => 'id_producer',
'headerOptions' => ['class' => 'td-producer'],
'value' => function ($ticket) {
return $ticket->producer->name;
}
];

if($context == 'producer') {
$columns = [
$columnCreatedAt,
$columnSubject,
$columnLastMessage,
$columnMessages,
$columnButtonActions
];
}
elseif($context == 'admin') {
$columns = [
$columnCreatedAt,
$columnProducer,
$columnSubject,
$columnLastMessage,
$columnMessages,
$columnButtonActions
];
}


$optionsGridView = [
'summary' => '',
'filterModel' => $searchTicket,
'dataProvider' => $dataProviderTicket,
'columns' => $columns,
];

return GridView::widget($optionsGridView);
}

?>

+ 89
- 0
backend/views/support/view.php Vedi File

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

use common\logic\Ticket\Ticket\Wrapper\TicketManager;
use common\logic\User\User\Wrapper\UserManager;
use yii\helpers\Html;
use yii\widgets\ActiveForm;

$ticketManager = TicketManager::getInstance();
$userManager = UserManager::getInstance();
$this->setTitle('Voir un ticket');
$this->addBreadcrumb(['label' => 'Support', 'url' => ['index']]);
$this->addBreadcrumb('Voir un ticket');

?>
<div class="ticket-view">
<div class="box box-solid">
<div class="box-body">
<table class="table">
<tbody>
<tr>
<td><strong>Sujet</strong></td>
<td><?= Html::encode($ticket->subject); ?></td>
</tr>
<tr>
<td><strong>Ouverture</strong></td>
<td><?= $ticketManager->getTicketDateCreatedAtFormat($ticket); ?></td>
</tr>
<tr>
<td><strong>Statut</strong></td>
<td><?= $ticketManager->getTicketStatusLabelAsHtml($ticket); ?></td>
</tr>
</tbody>
</table>
</div>
</div>

<ul class="timeline">
<?php foreach($ticket->ticketMessages as $key => $ticketMessage): ?>
<li>
<?php if ($key === array_key_last($ticket->ticketMessages)): ?>
<a name="bottom"></a>
<?php endif; ?>
<a name="<?= $ticketMessage->id ?>"></a>
<i class="fa fa-user <?= $userManager->isAdmin($ticketMessage->user) ? 'bg-orange' : 'bg-aqua'; ?>"></i>
<div class="timeline-item">
<span class="time"><i class="fa fa-clock-o"></i> <?= date('d/m/Y à H:i', strtotime($ticketMessage->created_at)) ?></span>
<h3 class="timeline-header"><?= Html::encode($userManager->getUsername($ticketMessage->user)); ?></h3>
<div class="timeline-body">
<?= nl2br($ticketMessage->message); ?>
</div>
</div>
</li>
<?php endforeach; ?>
</ul>

<div class="box box-success">
<div class="box-header">
<h3 class="box-title"><i class="fa fa-comments"></i> Répondre</h3>
</div>
<div class="box-body">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($ticketMessageResponse, 'message')->textarea(['rows' => 6]); ?>
<div class="form-group">
<?= Html::submitButton('Répondre', ['class' => 'btn btn-success btn-sm']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>

<div class="box <?= $ticketManager->isTicketOpen($ticket) ? 'box-danger' : 'box-success'; ?>">
<div class="box-header">
<h3 class="box-title">
<?php if($ticketManager->isTicketOpen($ticket)): ?>
<i class="fa fa-folder"></i> Cliquez ici si vous souhaitez fermer le ticket
<?php else: ?>
<i class="fa fa-folder-open"></i> Cliquez ici si vous souhaitez rouvrir le ticket
<?php endif; ?>
</h3>
</div>
<div class="box-body">
<?php if($ticketManager->isTicketOpen($ticket)): ?>
<?= Html::a('Fermer le ticket', ['close', 'id' => $ticket->id], ['class' => 'btn btn-danger btn-sm']) ?>
<?php else: ?>
<?= Html::a('Rouvrir le ticket', ['open', 'id' => $ticket->id], ['class' => 'btn btn-success btn-sm']) ?>
<?php endif; ?>
</div>
</div>

</div>

+ 411
- 417
backend/web/css/screen.css
File diff soppresso perché troppo grande
Vedi File


+ 22
- 3
backend/web/sass/_adminlte.scss Vedi File

@@ -69,7 +69,19 @@ body.skin-black {
.sidebar-toggle {
color: #333 ;
}

.link-support {
float: left;
padding: 15px 15px;
border-right: solid 1px #e0e0e0;
color: #333;

&:hover {
text-decoration: none;
color: $color1;
}
}

.navbar-custom-menu .navbar-nav > li > a,
.navbar-right > li > a {
border-left: solid 1px #e0e0e0 ;
@@ -137,6 +149,12 @@ body.skin-black {
}
}

.sidebar {
.sidebar-menu > li.header {
color: #899397;
}
}

.sidebar-menu > li.active > a {
border-color: $color1 ;
}
@@ -155,7 +173,7 @@ body.skin-black {
}
}
}
.content-wrapper {
background-color: #f5f5f5 ;
@@ -177,8 +195,9 @@ body.skin-black {
font-size: 20px;
}
}

a {
color: $color1 ;
color: darken($color1, 5) ;
}
.btn {

+ 10
- 0
backend/web/sass/screen.scss Vedi File

@@ -59,6 +59,14 @@ a {
}
}

.float-right {
float: right;
}

.float-left {
float: left;
}

#block-demo {
padding: 10px 0px ;
background-color: $color2 ;
@@ -1522,4 +1530,6 @@ a.btn, button.btn {
@import "document/_form.scss" ;
@import "document/_index.scss" ;
@import "development/_index.scss" ;
@import "support/_index.scss";
@import "support/_view.scss";
@import "_responsive.scss" ;

+ 29
- 0
backend/web/sass/support/_index.scss Vedi File

@@ -0,0 +1,29 @@

.support-index {
.ticket-list {

.nav-tabs {
.label {
position: relative;
top: -2px;
left: 2px;
padding: 0.3em 0.6em 0.2em 0.6em;
}
}

.table {
.filters {
display: none;
}

.td-created-at,
.td-last-message,
.td-messages {
width: 100px;
}
.td-producer {
width: 200px;
}
}
}
}

+ 19
- 0
backend/web/sass/support/_view.scss Vedi File

@@ -0,0 +1,19 @@

.ticket-view {

.table {
tr:first-child td {
border-top: 0px none;
}
}

.timeline {
&::before {
background: transparent none;
}

li, .timeline-item {
margin-right: 0px;
}
}
}

+ 3
- 0
common/components/BusinessLogic.php Vedi File

@@ -28,6 +28,9 @@ class BusinessLogic
$this->getProductOrderContainer(),
$this->getProductPriceContainer(),
$this->getProductSubscriptionContainer(),
$this->getTicketUserContainer(),
$this->getTicketMessageContainer(),
$this->getTicketContainer(),
$this->getQuotationContainer(),
$this->getInvoiceContainer(),
$this->getDeliveryNoteContainer(),

+ 36
- 0
common/components/BusinessLogicTrait.php Vedi File

@@ -44,6 +44,12 @@ use common\logic\Subscription\ProductSubscription\Wrapper\ProductSubscriptionCon
use common\logic\Subscription\ProductSubscription\Wrapper\ProductSubscriptionManager;
use common\logic\Subscription\Subscription\Wrapper\SubscriptionContainer;
use common\logic\Subscription\Subscription\Wrapper\SubscriptionManager;
use common\logic\Ticket\Ticket\Wrapper\TicketContainer;
use common\logic\Ticket\Ticket\Wrapper\TicketManager;
use common\logic\Ticket\TicketMessage\Wrapper\TicketMessageContainer;
use common\logic\Ticket\TicketMessage\Wrapper\TicketMessageManager;
use common\logic\Ticket\TicketUser\Wrapper\TicketUserContainer;
use common\logic\Ticket\TicketUser\Wrapper\TicketUserManager;
use common\logic\User\CreditHistory\Wrapper\CreditHistoryContainer;
use common\logic\User\CreditHistory\Wrapper\CreditHistoryManager;
use common\logic\User\User\Wrapper\UserContainer;
@@ -187,6 +193,21 @@ trait BusinessLogicTrait
return UserUserGroupManager::getInstance();
}

public function getTicketManager(): TicketManager
{
return TicketManager::getInstance();
}

public function getTicketMessageManager(): TicketMessageManager
{
return TicketMessageManager::getInstance();
}

public function getTicketUserManager(): TicketUserManager
{
return TicketUserManager::getInstance();
}

public function getUserContainer(): UserContainer
{
return UserContainer::getInstance();
@@ -316,4 +337,19 @@ trait BusinessLogicTrait
{
return ProductDistributionContainer::getInstance();
}

public function getTicketContainer(): TicketContainer
{
return TicketContainer::getInstance();
}

public function getTicketMessageContainer(): TicketMessageContainer
{
return TicketMessageContainer::getInstance();
}

public function getTicketUserContainer(): TicketUserContainer
{
return TicketUserContainer::getInstance();
}
}

+ 7
- 0
common/components/View.php Vedi File

@@ -38,6 +38,8 @@ termes.

namespace common\components ;

use common\logic\User\User\Model\User;

class View extends \yii\web\View
{
use BusinessLogicTrait;
@@ -125,4 +127,9 @@ class View extends \yii\web\View
{
return \Yii::$app->urlManagerBackend;
}

public function getUserCurrent(): ?User
{
return \Yii::$app->user->identity;
}
}

+ 1
- 0
common/config/main.php Vedi File

@@ -124,4 +124,5 @@ return [
}
],
'language' => 'fr-FR',
'timeZone' => 'Europe/Paris',
];

+ 25
- 7
common/logic/AbstractRepository.php Vedi File

@@ -18,6 +18,9 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI
{
$this->query->createQuery();

$this->defaultWith();
$this->defaultJoinWith();

return $this->query;
}

@@ -25,28 +28,43 @@ abstract class AbstractRepository extends AbstractService implements RepositoryI
{
$this->createQuery();

$defaultOptions = $this->getDefaultOptionsSearch();
$this->defaultWith();
$this->defaultJoinWith();
$this->defaultFilterProducerContext();
$this->defaultOrderBy();

return $this->query;
}

// with
public function defaultWith(): void
{
$defaultOptions = $this->getDefaultOptionsSearch();
if (is_array($defaultOptions['with']) && count($defaultOptions['with'])) {
$this->query->with($defaultOptions['with']);
}
}

// join with
public function defaultJoinWith(): void
{
$defaultOptions = $this->getDefaultOptionsSearch();
if (is_array($defaultOptions['join_with']) && count($defaultOptions['join_with'])) {
$this->query->joinWith($defaultOptions['join_with']);
}
}

// id producer contexte
public function defaultFilterProducerContext(): void
{
$defaultOptions = $this->getDefaultOptionsSearch();
if(isset($defaultOptions['attribute_id_producer']) && $defaultOptions['attribute_id_producer']) {
$this->query->andWhere([$defaultOptions['attribute_id_producer'] => $this->getProducerContextId()]);
}
}

// order by
public function defaultOrderBy(): void
{
$defaultOptions = $this->getDefaultOptionsSearch();
if(isset($defaultOptions['orderby']) && $defaultOptions['orderby']) {
$this->query->orderBy($defaultOptions['orderby']);
}

return $this->query;
}
}

+ 8
- 0
common/logic/AbstractSolver.php Vedi File

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

namespace common\logic;

abstract class AbstractSolver extends AbstractService implements SolverInterface
{

}

+ 0
- 1
common/logic/Subscription/ProductSubscription/Repository/ProductSubscriptionRepository.php Vedi File

@@ -3,7 +3,6 @@
namespace common\logic\Subscription\ProductSubscription\Repository;

use common\logic\AbstractRepository;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use common\logic\Subscription\Subscription\Model\Subscription;

class ProductSubscriptionRepository extends AbstractRepository

+ 0
- 1
common/logic/Subscription/ProductSubscription/Repository/ProductSubscriptionRepositoryQuery.php Vedi File

@@ -3,7 +3,6 @@
namespace common\logic\Subscription\ProductSubscription\Repository;

use common\logic\AbstractRepositoryQuery;
use common\logic\Subscription\ProductSubscription\Model\ProductSubscription;
use common\logic\Subscription\ProductSubscription\Service\ProductSubscriptionDefinition;
use common\logic\Subscription\Subscription\Model\Subscription;
use yii\db\ActiveQuery;

+ 7
- 7
common/logic/Subscription/ProductSubscription/Wrapper/ProductSubscriptionManager.php Vedi File

@@ -3,19 +3,19 @@
namespace common\logic\Subscription\ProductSubscription\Wrapper;

use common\logic\AbstractManager;
use common\logic\Subscription\ProductSubscription\Repository\ProductSubscriptionRepository;
use common\logic\Subscription\ProductSubscription\Service\ProductSubscriptionBuilder;
use common\logic\Subscription\ProductSubscription\Service\ProductSubscriptionDefinition;
use common\logic\Subscription\ProductSubscription\Repository\TicketRepository;
use common\logic\Subscription\ProductSubscription\Service\TicketBuilder;
use common\logic\Subscription\ProductSubscription\Service\TicketDefinition;

/**
* @mixin ProductSubscriptionDefinition
* @mixin ProductSubscriptionRepository
* @mixin ProductSubscriptionBuilder
* @mixin TicketDefinition
* @mixin TicketRepository
* @mixin TicketBuilder
*/
class ProductSubscriptionManager extends AbstractManager
{
public function getContainerFqcn(): string
{
return ProductSubscriptionContainer::class;
return TicketContainer::class;
}
}

+ 125
- 0
common/logic/Ticket/Ticket/Model/Ticket.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace common\logic\Ticket\Ticket\Model;

use common\components\ActiveRecordCommon;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\Ticket\TicketMessage\Model\TicketMessage;
use common\logic\Ticket\TicketUser\Model\TicketUser;
use common\logic\User\User\Model\User;

class Ticket extends ActiveRecordCommon
{
const STATUS_OPEN = 'open';
const STATUS_CLOSED = 'closed';

public $message;

/**
* @inheritdoc
*/
public static function tableName()
{
return 'ticket';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['id_producer', 'id_user', 'subject', 'status'], 'required'],
[['id_producer', 'id_user'], 'integer'],
[['subject', 'status'], 'string'],
[['created_at', 'message'], 'safe'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'id_producer' => 'Producteur',
'id_user' => 'Utilisateur',
'subject' => 'Sujet',
'status' => 'Statut',
'created_at' => 'Ouverture',
'updated_at' => 'Modification',
];
}

/*
* Relations
*/

public function getProducer()
{
return $this->hasOne(Producer::class, ['id' => 'id_producer']);
}

public function getUser()
{
return $this->hasOne(User::class, ['id' => 'id_user']);
}

public function getTicketMessages()
{
return $this->hasMany(TicketMessage::class, ['id_ticket' => 'id'])
->orderBy(['created_at' => SORT_ASC]);
}

public function getTicketUsers()
{
return $this->hasMany(TicketUser::class, ['id_ticket' => 'id']);
}

public function populateProducer(Producer $producer): void
{
$this->populateFieldObject('id_producer', 'producer', $producer);
}

public function populateUser(User $user): void
{
$this->populateFieldObject('id_user', 'user', $user);
}
}

+ 93
- 0
common/logic/Ticket/Ticket/Model/TicketSearch.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace common\logic\Ticket\Ticket\Model;

use common\helpers\GlobalParam;
use common\logic\Ticket\Ticket\Repository\TicketRepository;
use yii\data\ActiveDataProvider;

class TicketSearch extends Ticket
{
public function rules()
{
return [
[['subject', 'status'], 'string'],
[['subject', 'status'], 'string', 'max' => 255],
[['id_producer', 'id_user'], 'integer'],
];
}

public function search($context, $params)
{
$ticketRepository = TicketRepository::getInstance();
$optionsSearch = $ticketRepository->getDefaultOptionsSearch();

$query = Ticket::find()
->with($optionsSearch['with'])
->innerJoinWith($optionsSearch['join_with'], true);

if($context == 'producer') {
$query->where(['ticket.id_producer' => GlobalParam::getCurrentProducerId()]);
}

$dataProvider = new ActiveDataProvider([
'query' => $query,
'sort' => [
'attributes' => ['updated_at'],
'defaultOrder' => [
'updated_at' => SORT_DESC,
]
],
'pagination' => [
'pageSize' => 20,
],
]);

$this->load($params);

if (!$this->validate()) {
return $dataProvider;
}

$query->andFilterWhere(['like', 'ticket.subject', $this->subject]);
$query->andFilterWhere(['like', 'ticket.status', $this->status]);

return $dataProvider;
}
}

+ 52
- 0
common/logic/Ticket/Ticket/Repository/TicketRepository.php Vedi File

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

namespace common\logic\Ticket\Ticket\Repository;

use common\logic\AbstractRepository;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\Ticket\Service\TicketSolver;
use common\logic\User\User\Model\User;

class TicketRepository extends AbstractRepository
{
protected TicketRepositoryQuery $query;
protected TicketSolver $ticketSolver;

public function loadDependencies(): void
{
$this->loadQuery(TicketRepositoryQuery::class);
$this->ticketSolver = $this->loadService(TicketSolver::class);
}

/**
* Retourne les options de base nécessaires à la fonction de recherche.
*/
public function getDefaultOptionsSearch(): array
{
return [
self::WITH => ['user', 'producer', 'ticketMessages', 'ticketUsers'],
self::JOIN_WITH => [],
self::ORDER_BY => '',
self::ATTRIBUTE_ID_PRODUCER => 'ticket.id_producer'
];
}

public function findOneTicketById(int $id): ?Ticket
{
return $this->createQuery()
->filterById($id)
->findOne();
}

public function countTicketsUnreadByUser(User $user): int
{
$ticketsArray = $this->createDefaultQuery()->find();
return $this->ticketSolver->countTicketsUnreadByUserFromArray($ticketsArray, $user);
}

public function countTicketsAdminUnreadByUser(User $user): int
{
$ticketsArray = $this->createQuery()->find();
return $this->ticketSolver->countTicketsUnreadByUserFromArray($ticketsArray, $user);
}
}

+ 16
- 0
common/logic/Ticket/Ticket/Repository/TicketRepositoryQuery.php Vedi File

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

namespace common\logic\Ticket\Ticket\Repository;

use common\logic\AbstractRepositoryQuery;
use common\logic\Ticket\Ticket\Service\TicketDefinition;

class TicketRepositoryQuery extends AbstractRepositoryQuery
{
protected TicketDefinition $definition;

public function loadDependencies(): void
{
$this->loadDefinition(TicketDefinition::class);
}
}

+ 78
- 0
common/logic/Ticket/Ticket/Service/TicketBuilder.php Vedi File

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

namespace common\logic\Ticket\Ticket\Service;

use common\logic\AbstractBuilder;
use common\logic\Producer\Producer\Model\Producer;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketMessage\Model\TicketMessage;
use common\logic\Ticket\TicketMessage\Service\TicketMessageBuilder;
use common\logic\Ticket\TicketUser\Service\TicketUserBuilder;
use common\logic\User\User\Model\User;

class TicketBuilder extends AbstractBuilder
{
protected TicketMessageBuilder $ticketMessageBuilder;
protected TicketUserBuilder $ticketUserBuilder;

public function loadDependencies(): void
{
$this->ticketMessageBuilder = $this->loadService(TicketMessageBuilder::class);
$this->ticketUserBuilder = $this->loadService(TicketUserBuilder::class);
}

public function instanciateTicket(Producer $producer, User $user): Ticket
{
$ticket = new Ticket();

$ticket->status = Ticket::STATUS_OPEN;
$ticket->populateProducer($producer);
$ticket->populateUser($user);

return $ticket;
}

public function createTicket(Producer $producer, User $user): Ticket
{
$ticket = $this->instanciateTicket($producer, $user);
$this->saveCreate($ticket);

return $ticket;
}

public function updateTicketStatus(Ticket $ticket, string $status)
{
$ticket->status = $status;
$this->saveUpdate($ticket);

$this->updateTicketUpdatedAt($ticket);
}

public function closeTicket(Ticket $ticket)
{
$this->updateTicketStatus($ticket, Ticket::STATUS_CLOSED);
}

public function openTicket(Ticket $ticket)
{
$this->updateTicketStatus($ticket, Ticket::STATUS_OPEN);
}

public function updateTicketUpdatedAt(Ticket $ticket)
{
$ticket->updated_at = date('Y-m-d H:i:s');
$this->saveUpdate($ticket);
}

public function createTicketMessage(TicketMessage $ticketMessage)
{
$this->updateTicketUpdatedAt($ticketMessage->ticket);
return $this->saveCreate($ticketMessage);
}

public function viewTicket(Ticket $ticket, User $user)
{
$ticketUser = $this->ticketUserBuilder->createTicketUserIfNotExist($ticket, $user);
$this->ticketUserBuilder->updateTicketUserReadAt($ticketUser);
}
}

+ 14
- 0
common/logic/Ticket/Ticket/Service/TicketDefinition.php Vedi File

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

namespace common\logic\Ticket\Ticket\Service;

use common\logic\AbstractDefinition;
use common\logic\Ticket\Ticket\Model\Ticket;

class TicketDefinition extends AbstractDefinition
{
public function getEntityFqcn(): string
{
return Ticket::class;
}
}

+ 113
- 0
common/logic/Ticket/Ticket/Service/TicketSolver.php Vedi File

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

namespace common\logic\Ticket\Ticket\Service;

use common\logic\AbstractSolver;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketMessage\Model\TicketMessage;
use common\logic\Ticket\TicketUser\Model\TicketUser;
use common\logic\User\User\Model\User;
use common\logic\User\User\Service\UserSolver;

class TicketSolver extends AbstractSolver
{
protected UserSolver $userSolver;

public function loadDependencies(): void
{
$this->userSolver = $this->loadService(UserSolver::class);
}

public function hasTicketAccess(Ticket $ticket, User $user): string
{
return $user->id_producer == $ticket->id_producer
|| $this->userSolver->isAdmin($user);
}

public function isTicketOpen(Ticket $ticket)
{
return $ticket->status == Ticket::STATUS_OPEN;
}

public function isTicketClosed(Ticket $ticket)
{
return $ticket->status == Ticket::STATUS_CLOSED;
}

public function getTicketDateCreatedAtFormat(Ticket $ticket)
{
return date('d/m/Y', strtotime($ticket->created_at));
}

public function getTicketStatusLabelAsHtml(Ticket $ticket)
{
$classLabel = 'label-success';
$statusLabel = 'Ouvert';
if ($this->isTicketClosed($ticket)) {
$classLabel = 'label-danger';
$statusLabel = 'Fermé';
}

return '<span class="label ' . $classLabel . '">' . $statusLabel . '</span>';
}

public function getTicketUser(Ticket $ticket, User $user)
{
foreach($ticket->ticketUsers as $ticketUser) {
if($ticketUser->id_user == $user->id) {
return $ticketUser;
}
}

return null;
}

public function isTicketMessageUnread(TicketMessage $ticketMessage, TicketUser $ticketUser)
{
if($ticketMessage->created_at > $ticketUser->read_at) {
return true;
}

return false;
}

public function isTicketUnread(Ticket $ticket, User $user): int
{
$ticketUser = $this->getTicketUser($ticket, $user);
if($ticketUser) {
foreach($ticket->ticketMessages as $ticketMessage) {
if($this->isTicketMessageUnread($ticketMessage, $ticketUser)) {
return true;
}
}
}

return false;
}

public function getFirstTicketMessageUnread(Ticket $ticket, User $user): ?TicketMessage
{
$ticketUser = $this->getTicketUser($ticket, $user);
if($ticketUser) {
foreach($ticket->ticketMessages as $ticketMessage) {
if($this->isTicketMessageUnread($ticketMessage, $ticketUser)) {
return $ticketMessage;
}
}
}

return null;
}

public function countTicketsUnreadByUserFromArray(array $ticketsArray, User $user): int
{
$count = 0;
foreach($ticketsArray as $ticket) {
if($this->isTicketUnread($ticket, $user)) {
$count++;
}
}

return $count;
}
}

+ 42
- 0
common/logic/Ticket/Ticket/Wrapper/TicketContainer.php Vedi File

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

namespace common\logic\Ticket\Ticket\Wrapper;

use common\logic\AbstractContainer;
use common\logic\Ticket\Ticket\Repository\TicketRepository;
use common\logic\Ticket\Ticket\Service\TicketBuilder;
use common\logic\Ticket\Ticket\Service\TicketDefinition;
use common\logic\Ticket\Ticket\Service\TicketSolver;

class TicketContainer extends AbstractContainer
{
public function getServices(): array
{
return [
TicketDefinition::class,
TicketRepository::class,
TicketBuilder::class,
TicketSolver::class,
];
}

public function getDefinition(): TicketDefinition
{
return TicketDefinition::getInstance();
}

public function getRepository(): TicketRepository
{
return TicketRepository::getInstance();
}

public function getBuilder(): TicketBuilder
{
return TicketBuilder::getInstance();
}

public function getSolver(): TicketSolver
{
return TicketSolver::getInstance();
}
}

+ 23
- 0
common/logic/Ticket/Ticket/Wrapper/TicketManager.php Vedi File

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

namespace common\logic\Ticket\Ticket\Wrapper;

use common\logic\AbstractManager;
use common\logic\Ticket\Ticket\Repository\TicketRepository;
use common\logic\Ticket\Ticket\Service\TicketBuilder;
use common\logic\Ticket\Ticket\Service\TicketDefinition;
use common\logic\Ticket\Ticket\Service\TicketSolver;

/**
* @mixin TicketDefinition
* @mixin TicketRepository
* @mixin TicketBuilder
* @mixin TicketSolver
*/
class TicketManager extends AbstractManager
{
public function getContainerFqcn(): string
{
return TicketContainer::class;
}
}

+ 105
- 0
common/logic/Ticket/TicketMessage/Model/TicketMessage.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace common\logic\Ticket\TicketMessage\Model;

use common\components\ActiveRecordCommon;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\User\User\Model\User;

class TicketMessage extends ActiveRecordCommon
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'ticket_message';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['id_ticket', 'id_user', 'message'], 'required'],
[['id_ticket', 'id_user'], 'integer'],
[['message'], 'string'],
[['created_at'], 'safe'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'id_ticket' => 'Ticket',
'id_user' => 'Utilisateur',
'message' => 'Message',
'created_at' => 'Date de création',
];
}

/*
* Relations
*/

public function getUser()
{
return $this->hasOne(User::class, ['id' => 'id_user']);
}

public function getTicket()
{
return $this->hasOne(Ticket::class, ['id' => 'id_ticket']);
}

public function populateUser(User $user): void
{
$this->populateFieldObject('id_user', 'user', $user);
}

public function populateTicket(Ticket $ticket): void
{
$this->populateFieldObject('id_ticket', 'ticket', $ticket);
}
}

+ 28
- 0
common/logic/Ticket/TicketMessage/Repository/TicketMessageRepository.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Repository;

use common\logic\AbstractRepository;

class TicketMessageRepository extends AbstractRepository
{
protected TicketMessageRepositoryQuery $query;

public function loadDependencies(): void
{
$this->loadQuery(TicketMessageRepositoryQuery::class);
}

/**
* Retourne les options de base nécessaires à la fonction de recherche.
*/
public function getDefaultOptionsSearch(): array
{
return [
self::WITH => ['user', 'producer', 'ticketMessages'],
self::JOIN_WITH => [],
self::ORDER_BY => '',
self::ATTRIBUTE_ID_PRODUCER => ''
];
}
}

+ 16
- 0
common/logic/Ticket/TicketMessage/Repository/TicketMessageRepositoryQuery.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Repository;

use common\logic\AbstractRepositoryQuery;
use common\logic\Ticket\TicketMessage\Service\TicketMessageDefinition;

class TicketMessageRepositoryQuery extends AbstractRepositoryQuery
{
protected TicketMessageDefinition $definition;

public function loadDependencies(): void
{
$this->loadDefinition(TicketMessageDefinition::class);
}
}

+ 30
- 0
common/logic/Ticket/TicketMessage/Service/TicketMessageBuilder.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Service;

use common\logic\AbstractBuilder;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketMessage\Model\TicketMessage;
use common\logic\User\User\Model\User;

class TicketMessageBuilder extends AbstractBuilder
{
public function instanciateTicketMessage(Ticket $ticket, User $user, string $message = ''): TicketMessage
{
$ticketMessage = new TicketMessage();

$ticketMessage->populateTicket($ticket);
$ticketMessage->populateUser($user);
$ticketMessage->message = $message;

return $ticketMessage;
}

public function createTicketMessage(Ticket $ticket, User $user, string $message): TicketMessage
{
$ticketMessage = $this->instanciateTicketMessage($ticket, $user, $message);
$this->saveCreate($ticketMessage);

return $ticketMessage;
}
}

+ 14
- 0
common/logic/Ticket/TicketMessage/Service/TicketMessageDefinition.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Service;

use common\logic\AbstractDefinition;
use common\logic\Ticket\TicketMessage\Model\TicketMessage;

class TicketMessageDefinition extends AbstractDefinition
{
public function getEntityFqcn(): string
{
return TicketMessage::class;
}
}

+ 35
- 0
common/logic/Ticket/TicketMessage/Wrapper/TicketMessageContainer.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Wrapper;

use common\logic\AbstractContainer;
use common\logic\Ticket\TicketMessage\Repository\TicketMessageRepository;
use common\logic\Ticket\TicketMessage\Service\TicketMessageBuilder;
use common\logic\Ticket\TicketMessage\Service\TicketMessageDefinition;

class TicketMessageContainer extends AbstractContainer
{
public function getServices(): array
{
return [
TicketMessageDefinition::class,
TicketMessageRepository::class,
TicketMessageBuilder::class
];
}

public function getDefinition(): TicketMessageDefinition
{
return TicketMessageDefinition::getInstance();
}

public function getRepository(): TicketMessageRepository
{
return TicketMessageRepository::getInstance();
}

public function getFactory(): TicketMessageBuilder
{
return TicketMessageBuilder::getInstance();
}
}

+ 21
- 0
common/logic/Ticket/TicketMessage/Wrapper/TicketMessageManager.php Vedi File

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

namespace common\logic\Ticket\TicketMessage\Wrapper;

use common\logic\AbstractManager;
use common\logic\Ticket\TicketMessage\Repository\TicketMessageRepository;
use common\logic\Ticket\TicketMessage\Service\TicketMessageBuilder;
use common\logic\Ticket\TicketMessage\Service\TicketMessageDefinition;

/**
* @mixin TicketMessageDefinition
* @mixin TicketMessageRepository
* @mixin TicketMessageBuilder
*/
class TicketMessageManager extends AbstractManager
{
public function getContainerFqcn(): string
{
return TicketMessageContainer::class;
}
}

+ 103
- 0
common/logic/Ticket/TicketUser/Model/TicketUser.php Vedi File

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

/**
* Copyright distrib (2018)
*
* contact@opendistrib.net
*
* Ce logiciel est un programme informatique servant à aider les producteurs
* à distribuer leur production en circuits courts.
*
* Ce logiciel est régi par la licence CeCILL soumise au droit français et
* respectant les principes de diffusion des logiciels libres. Vous pouvez
* utiliser, modifier et/ou redistribuer ce programme sous les conditions
* de la licence CeCILL telle que diffusée par le CEA, le CNRS et l'INRIA
* sur le site "http://www.cecill.info".
*
* En contrepartie de l'accessibilité au code source et des droits de copie,
* de modification et de redistribution accordés par cette licence, il n'est
* offert aux utilisateurs qu'une garantie limitée. Pour les mêmes raisons,
* seule une responsabilité restreinte pèse sur l'auteur du programme, le
* titulaire des droits patrimoniaux et les concédants successifs.
*
* A cet égard l'attention de l'utilisateur est attirée sur les risques
* associés au chargement, à l'utilisation, à la modification et/ou au
* développement et à la reproduction du logiciel par l'utilisateur étant
* donné sa spécificité de logiciel libre, qui peut le rendre complexe à
* manipuler et qui le réserve donc à des développeurs et des professionnels
* avertis possédant des connaissances informatiques approfondies. Les
* utilisateurs sont donc invités à charger et tester l'adéquation du
* logiciel à leurs besoins dans des conditions permettant d'assurer la
* sécurité de leurs systèmes et ou de leurs données et, plus généralement,
* à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.
*
* Le fait que vous puissiez accéder à cet en-tête signifie que vous avez
* pris connaissance de la licence CeCILL, et que vous en avez accepté les
* termes.
*/

namespace common\logic\Ticket\TicketUser\Model;

use common\components\ActiveRecordCommon;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\User\User\Model\User;

class TicketUser extends ActiveRecordCommon
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'ticket_user';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['id_ticket', 'id_user'], 'required'],
[['id_ticket', 'id_user'], 'integer'],
[['read_at'], 'safe'],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'id_ticket' => 'Ticket',
'id_user' => 'Utilisateur',
'read_at' => 'Date de lecture',
];
}

/*
* Relations
*/

public function getUser()
{
return $this->hasOne(User::class, ['id' => 'id_user']);
}

public function getTicket()
{
return $this->hasOne(Ticket::class, ['id' => 'id_ticket']);
}

public function populateUser(User $user): void
{
$this->populateFieldObject('id_user', 'user', $user);
}

public function populateTicket(Ticket $ticket): void
{
$this->populateFieldObject('id_ticket', 'ticket', $ticket);
}
}

+ 39
- 0
common/logic/Ticket/TicketUser/Repository/TicketUserRepository.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Repository;

use common\logic\AbstractRepository;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketUser\Model\TicketUser;
use common\logic\User\User\Model\User;

class TicketUserRepository extends AbstractRepository
{
protected TicketUserRepositoryQuery $query;

public function loadDependencies(): void
{
$this->loadQuery(TicketUserRepositoryQuery::class);
}

/**
* Retourne les options de base nécessaires à la fonction de recherche.
*/
public function getDefaultOptionsSearch(): array
{
return [
self::WITH => ['ticket', 'user'],
self::JOIN_WITH => [],
self::ORDER_BY => '',
self::ATTRIBUTE_ID_PRODUCER => ''
];
}

public function findOneTicketUser(Ticket $ticket, User $user): ?TicketUser
{
return $this->createDefaultQuery()
->filterByTicket($ticket)
->filterByUser($user)
->findOne();
}
}

+ 30
- 0
common/logic/Ticket/TicketUser/Repository/TicketUserRepositoryQuery.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Repository;

use common\logic\AbstractRepositoryQuery;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketUser\Service\TicketUserDefinition;
use common\logic\User\User\Model\User;

class TicketUserRepositoryQuery extends AbstractRepositoryQuery
{
protected TicketUserDefinition $definition;

public function loadDependencies(): void
{
$this->loadDefinition(TicketUserDefinition::class);
}

public function filterByTicket(Ticket $ticket): self
{
$this->andWhere(['ticket_user.id_ticket' => $ticket->id]);
return $this;
}

public function filterByUser(User $user): self
{
$this->andWhere(['ticket_user.id_user' => $user->id]);
return $this;
}
}

+ 49
- 0
common/logic/Ticket/TicketUser/Service/TicketUserBuilder.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Service;

use common\logic\AbstractBuilder;
use common\logic\Ticket\Ticket\Model\Ticket;
use common\logic\Ticket\TicketUser\Model\TicketUser;
use common\logic\Ticket\TicketUser\Repository\TicketUserRepository;
use common\logic\User\User\Model\User;

class TicketUserBuilder extends AbstractBuilder
{
protected TicketUserRepository $ticketUserRepository;

public function loadDependencies(): void
{
$this->ticketUserRepository = $this->loadService(TicketUserRepository::class);
}

public function instanciateTicketUser(Ticket $ticket, User $user): TicketUser
{
$ticketUser = new TicketUser();

$ticketUser->populateTicket($ticket);
$ticketUser->populateUser($user);

return $ticketUser;
}

public function createTicketUser(Ticket $ticket, User $user): TicketUser
{
$ticketUser = $this->instanciateTicketUser($ticket, $user);
$this->saveCreate($ticketUser);

return $ticketUser;
}

public function createTicketUserIfNotExist(Ticket $ticket, User $user): TicketUser
{
return $this->ticketUserRepository->findOneTicketUser($ticket, $user)
?? $this->createTicketUser($ticket, $user);
}

public function updateTicketUserReadAt(TicketUser $ticketUser)
{
$ticketUser->read_at = date('Y-m-d H:i:s');
$this->saveUpdate($ticketUser);
}
}

+ 14
- 0
common/logic/Ticket/TicketUser/Service/TicketUserDefinition.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Service;

use common\logic\AbstractDefinition;
use common\logic\Ticket\TicketUser\Model\TicketUser;

class TicketUserDefinition extends AbstractDefinition
{
public function getEntityFqcn(): string
{
return TicketUser::class;
}
}

+ 35
- 0
common/logic/Ticket/TicketUser/Wrapper/TicketUserContainer.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Wrapper;

use common\logic\AbstractContainer;
use common\logic\Ticket\TicketUser\Repository\TicketUserRepository;
use common\logic\Ticket\TicketUser\Service\TicketUserBuilder;
use common\logic\Ticket\TicketUser\Service\TicketUserDefinition;

class TicketUserContainer extends AbstractContainer
{
public function getServices(): array
{
return [
TicketUserDefinition::class,
TicketUserRepository::class,
TicketUserBuilder::class
];
}

public function getDefinition(): TicketUserDefinition
{
return TicketUserDefinition::getInstance();
}

public function getRepository(): TicketUserRepository
{
return TicketUserRepository::getInstance();
}

public function getBuilder(): TicketUserBuilder
{
return TicketUserBuilder::getInstance();
}
}

+ 21
- 0
common/logic/Ticket/TicketUser/Wrapper/TicketUserManager.php Vedi File

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

namespace common\logic\Ticket\TicketUser\Wrapper;

use common\logic\AbstractManager;
use common\logic\Ticket\TicketMessage\Repository\TicketMessageRepository;
use common\logic\Ticket\TicketMessage\Service\TicketMessageBuilder;
use common\logic\Ticket\TicketMessage\Service\TicketMessageDefinition;

/**
* @mixin TicketMessageDefinition
* @mixin TicketMessageRepository
* @mixin TicketMessageBuilder
*/
class TicketUserManager extends AbstractManager
{
public function getContainerFqcn(): string
{
return TicketUserContainer::class;
}
}

+ 52
- 0
console/migrations/m230717_120138_module_ticket.php Vedi File

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

use yii\db\Migration;
use yii\db\Schema;

/**
* Class m230717_120138_module_ticket
*/
class m230717_120138_module_ticket extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
$this->createTable('ticket', [
'id' => 'pk',
'id_producer' => Schema::TYPE_INTEGER.' NOT NULL',
'id_user' => Schema::TYPE_INTEGER.' NOT NULL',
'subject' => Schema::TYPE_STRING.' NOT NULL',
'status' => Schema::TYPE_STRING.' NOT NULL',
'created_at' => Schema::TYPE_DATETIME.' NOT NULL DEFAULT CURRENT_TIMESTAMP',
'updated_at' => Schema::TYPE_DATETIME.' NOT NULL DEFAULT CURRENT_TIMESTAMP'
]);

$this->createTable('ticket_message', [
'id' => 'pk',
'id_ticket' => Schema::TYPE_INTEGER.' NOT NULL',
'id_user' => Schema::TYPE_INTEGER.' NOT NULL',
'message' => Schema::TYPE_TEXT.' NOT NULL',
'created_at' => Schema::TYPE_DATETIME.' NOT NULL DEFAULT CURRENT_TIMESTAMP',
'updated_at' => Schema::TYPE_DATETIME.' NOT NULL DEFAULT CURRENT_TIMESTAMP',
]);

$this->createTable('ticket_user', [
'id' => 'pk',
'id_user' => Schema::TYPE_INTEGER.' NOT NULL',
'id_ticket' => Schema::TYPE_INTEGER.' NOT NULL',
'read_at' => Schema::TYPE_DATETIME.' NOT NULL DEFAULT CURRENT_TIMESTAMP',
]);
}

/**
* {@inheritdoc}
*/
public function safeDown()
{
$this->dropTable('ticket');
$this->dropTable('ticket_message');
$this->dropTable('ticket_user');
}
}

Loading…
Annulla
Salva