@@ -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 | |||
]); | |||
} | |||
} |
@@ -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."); | |||
} | |||
} | |||
} |
@@ -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()], | |||
], | |||
] | |||
) ?> |
@@ -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> |
@@ -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); | |||
} | |||
?> |
@@ -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> |
@@ -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 { |
@@ -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" ; |
@@ -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; | |||
} | |||
} | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||
} |
@@ -28,6 +28,9 @@ class BusinessLogic | |||
$this->getProductOrderContainer(), | |||
$this->getProductPriceContainer(), | |||
$this->getProductSubscriptionContainer(), | |||
$this->getTicketUserContainer(), | |||
$this->getTicketMessageContainer(), | |||
$this->getTicketContainer(), | |||
$this->getQuotationContainer(), | |||
$this->getInvoiceContainer(), | |||
$this->getDeliveryNoteContainer(), |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -124,4 +124,5 @@ return [ | |||
} | |||
], | |||
'language' => 'fr-FR', | |||
'timeZone' => 'Europe/Paris', | |||
]; |
@@ -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; | |||
} | |||
} |
@@ -0,0 +1,8 @@ | |||
<?php | |||
namespace common\logic; | |||
abstract class AbstractSolver extends AbstractService implements SolverInterface | |||
{ | |||
} |
@@ -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 |
@@ -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; |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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 => '' | |||
]; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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(); | |||
} | |||
} |
@@ -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; | |||
} | |||
} |
@@ -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'); | |||
} | |||
} |