Commit 30825449 authored by Antony Le Courtes's avatar Antony Le Courtes
Browse files

Merge remote-tracking branch 'origin/master'

parents 96e1cbf0 f439dc72
......@@ -223,4 +223,9 @@ Cordialement,
"DESCRIPTION" => "Adresse email d'expéditeur des mails via les indicateur, si vide alors l'email de l'utilisateur sera utilisé",
],
/* Contrat */
"avenant" => [
"VALEUR" => "active",
"DESCRIPTION" => "Permettre la création d'avenants au contrat",
],
];
\ No newline at end of file
......@@ -117,6 +117,7 @@ return [
'visualisation' => 'Visualisation',
'edition' => 'Édition',
'validation' => 'Validation',
'refus-piece' => 'Refus - Pièce justificative',
'devalidation' => 'Dévalidation',
'archivage' => 'Archivage',
'gestion-edition' => 'Gestion des pièces justificatives (édition)',
......
......@@ -52,7 +52,7 @@ return [
],
],
],
'valider' => [
'valider' => [
// valider la PJ
'type' => 'Segment',
'options' => [
......@@ -66,7 +66,7 @@ return [
],
],
],
'devalider' => [
'devalider' => [
// dévalider la PJ
'type' => 'Segment',
'options' => [
......@@ -80,7 +80,21 @@ return [
],
],
],
'archiver' => [
'refuser' => [
// refuser la PJ
'type' => 'Segment',
'options' => [
'route' => '/refuser/:pieceJointe',
'constraints' => [
'pieceJointe' => '[0-9]*',
'fichier' => '[0-9]*',
],
'defaults' => [
'action' => 'refuser',
],
],
],
'archiver' => [
// archiver la PJ
'type' => 'Segment',
'options' => [
......@@ -93,7 +107,7 @@ return [
],
],
],
'fichier' => [
'fichier' => [
'type' => 'Literal',
'options' => [
'route' => '/fichier',
......@@ -310,6 +324,11 @@ return [
'action' => ['supprimer'],
'privileges' => [Privileges::DOSSIER_SUPPRESSION],
],
[
'controller' => 'Application\Controller\Dossier',
'action' => ['supprimer'],
'privileges' => [Privileges::DOSSIER_SUPPRESSION],
],
[
'controller' => 'Application\Controller\IntervenantDossier',
......@@ -359,7 +378,7 @@ return [
],
[
'controller' => 'Application\Controller\PieceJointe',
'action' => ['infos', 'lister', 'validation'],
'action' => ['infos', 'lister', 'validation', 'refuser'],
'privileges' => Privileges::PIECE_JUSTIFICATIVE_VISUALISATION,
],
[
......
......@@ -6,6 +6,7 @@ use Application\Assertion\ContratAssertion;
use Application\Entity\Db\Fichier;
use Application\Entity\Db\Intervenant;
use Application\Entity\Db\ModeleContrat;
use Application\Entity\Db\Parametre;
use Application\Entity\Db\Service;
use Application\Entity\Db\Structure;
use Application\Entity\Db\Validation;
......@@ -26,6 +27,7 @@ use Application\Service\Traits\TypeVolumeHoraireServiceAwareTrait;
use Application\Service\Traits\ContextServiceAwareTrait;
use Application\Service\Traits\WorkflowServiceAwareTrait;
use Intervenant\Service\NoteServiceAwareTrait;
use Phan\Debug;
use UnicaenApp\Controller\Plugin\Upload\UploaderPlugin;
use UnicaenApp\Util;
use UnicaenApp\View\Model\MessengerViewModel;
......@@ -134,8 +136,10 @@ class ContratController extends AbstractController
}
$services['non-contractualises'][$sid][] = $service;
}
$avenantResult = $this->getServiceParametres()->get('avenant');
$avenant = ($avenantResult == Parametre::AVENANT);
return compact('title', 'intervenant', 'contrats', 'services', 'emailIntervenant');
return compact('title', 'intervenant', 'contrats', 'services', 'emailIntervenant', 'avenant');
}
......
......@@ -14,6 +14,7 @@ use Application\Form\PieceJointe\Traits\ModifierTypePieceJointeStatutFormAwareTr
use Application\Service\Traits\IntervenantServiceAwareTrait;
use Application\Service\Traits\PieceJointeServiceAwareTrait;
use Intervenant\Entity\Db\Statut;
use Intervenant\Form\MailerIntervenantFormAwareTrait;
use Intervenant\Entity\Db\TypeIntervenant;
use Intervenant\Service\StatutServiceAwareTrait;
use Application\Service\Traits\TypePieceJointeServiceAwareTrait;
......@@ -24,6 +25,8 @@ use UnicaenApp\View\Model\MessengerViewModel;
use Laminas\View\Model\ViewModel;
use Laminas\View\Model\JsonModel;
use Application\Service\Traits\ContextServiceAwareTrait;
use Intervenant\Service\MailServiceAwareTrait;
use Intervenant\Service\NoteServiceAwareTrait;
/**
......@@ -41,7 +44,9 @@ class PieceJointeController extends AbstractController
use TypePieceJointeServiceAwareTrait;
use TypePieceJointeStatutServiceAwareTrait;
use WorkflowServiceAwareTrait;
use MailServiceAwareTrait;
use NoteServiceAwareTrait;
use MailerIntervenantFormAwareTrait;
/**
* Initialisation des filtres Doctrine pour les historique.
......@@ -523,4 +528,47 @@ class PieceJointeController extends AbstractController
}
}
public function refuserAction()
{
/** @var PieceJointe $pj */
$intervenant = $this->getServiceContext()->getSelectedIdentityRole()->getIntervenant();
if ($intervenant && $pj->getIntervenant() != $intervenant) {
// un intervenant tente de supprimer la PJ d'un autre intervenant
throw new \Exception('Vous ne pouvez pas supprimer la pièce jointe d\'un autre intervenant');
}
$pj = $this->getEvent()->getParam('pieceJointe');
$title = 'Rédiger un email à l\'intervenant pour le refus de pièce';
$form = $this->getFormMailerIntervenant()->setIntervenant($pj->getIntervenant())->initForm();
if ($this->getRequest()->isPost() && $this->getRequest()->getPost()->count() > 0) {
try {
$data = $this->getRequest()->getPost();
$from = $data['from'];
$to = $data['to'];
$subject = $data['subject'];
$content = $data['content'];
$this->getServiceMail()->envoyerMail($from, $to, $subject, $content);
//Création d'une trace de l'envoi dans les notes de l'intervenant
$this->getServiceNote()->createNoteFromEmail($pj->getIntervenant(), $subject, $content);
$this->flashMessenger()->addSuccessMessage('Email envoyé à l\'intervenant');
foreach ($pj->getFichier() as $fichier) {
$this->getServicePieceJointe()->supprimerFichier($fichier, $pj);
}
$this->updateTableauxBord($pj->getIntervenant());
} catch (\Exception $e) {
$this->flashMessenger()->addErrorMessage($this->translate($e));
}
}
return compact('pj', 'title', 'form');
}
}
......@@ -16,6 +16,8 @@ class Parametre implements HistoriqueAwareInterface
const CONTRAT_FRANCHI_VALIDATION = 'validation';
const CONTRAT_FRANCHI_DATE_RETOUR = 'date-retour';
const AVENANT = 'avenant';
use HistoriqueAwareTrait;
/**
......
......@@ -565,6 +565,23 @@ class ParametresForm extends AbstractForm
'class' => 'btn btn-primary',
],
]);
$this->add([
'type' => 'Select',
'name' => 'avenant',
'options' => [
'label' => 'Possibilité de créer des avenants',
'value_options' => [
PARAMETRE::AVENANT => 'Les avenants sont disponibles',
'desactive' => 'Fonctionnalité désactivée',
],
],
'attributes' => [
'class' => 'selectpicker',
'data-size' => 20,
],
]);
}
......
<?php
use \Application\Service\Traits\ParametresServiceAwareTrait;
use Application\Provider\Privilege\Privileges;
/**
......@@ -17,7 +18,6 @@ foreach ($contrats as $contrat) {
}
$this->intervenant($intervenant)->renderTitle("Contrat/avenant");
echo $this->messenger()->addCurrentMessagesFromFlashMessenger();
if ($services['non-contractualises']) {
......@@ -46,7 +46,8 @@ $this->messenger() ?>
<?php if ($contrats || $services['non-contractualises']): ?>
<?php if ($services['non-contractualises']): ?>
<table class="table table-bordered table-hover">
<?php if (!$hasContrat || $avenant): ?>
<table class="table table-bordered table-hover">
<tr>
<th class="structure">Composante</th>
<th>Enseignement(s) non contractualisé(s)</th>
......@@ -64,11 +65,16 @@ $this->messenger() ?>
<td><?= $structure ?></td>
<td>
<?php if ($canCreer): ?>
<a class="btn btn-primary"
href="<?= $this->url('contrat/creer', ['intervenant' => $intervenant->getId(), 'structure' => $structure->getId()]); ?>">
<i class="fas fa-file"></i> Créer un
projet <?= $hasContrat ? 'd\'avenant' : 'de contrat' ?>
</a>
<a class="btn btn-primary"
href="<?= $this->url('contrat/creer', ['intervenant' => $intervenant->getId(), 'structure' => $structure->getId()]); ?>">
<i class="fas fa-file"></i> Créer un
projet <?= $hasContrat ? 'd\'avenant' : 'de contrat' ?>
</a>
<?php else:
echo $this->feuilleDeRoute($intervenant)->renderWhyNonAtteignable(\Application\Entity\Db\WfEtape::CODE_CONTRAT, $structure);
endif; ?>
......@@ -88,7 +94,9 @@ $this->messenger() ?>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</table>
<?php endif; ?>
<div class="well">
<h2>Contrats et avenants</h2>
......
......@@ -135,6 +135,8 @@
<li><strong>:annee :</strong> année universitaire du contrat (ex : 2019/2020)</li>
</ul>
</p>
<?= $this->formControlGroup($form->get('avenant')); ?>
</div>
</div>
</div>
......@@ -299,6 +301,7 @@
</div>
</div>
</div>
<?php
if ($canEdit) echo $this->formsubmit($form->get('submit'));
......
<?php
echo $this->messenger()->addCurrentMessagesFromFlashMessenger();
/**
* @var $form \Intervenant\Form\MailerIntervenantForm
*/
echo $this->form()->openTag($form);
echo $this->formControlGroup($form->get('from'));
echo $this->formControlGroup($form->get('to'));
echo $this->formControlGroup($form->get('subject'));
echo $this->formControlGroup($form->get('content'));
echo $this->formRow($form->get('submit'));
echo $this->formElement($form->get('security'));
echo $this->form()->closeTag();
?>
<script type="text/javascript">
$(function () {
var selector = "textarea#<?= $form->get('content')->getAttribute('id') ?>";
var form = $("form#<?= $form->getAttribute('id') ?>");
var message = "Êtes-vous sûr(e) de vouloir envoyer ce message à l'intervenant ?";
installEditor(selector, form);
// avant de POSTer
form.submit(function (e) {
if (!confirm(message)) {
e.preventDefault();
e.stopPropagation();
}
});
});
/**
* Installation d'un éditeur WYSIWYG (vers HTML) : http://www.tinymce.com
* NB: l'inclusion du script de TinyMCE est faite dans la vue "mère" (application/indicateur/result.phtml).
* @param {string} selector
* @param {object} form
*/
function installEditor(selector, form)
{
WidgetInitializer.includeJs(Url('vendor/tinymce-4.4.1/js/tinymce/tinymce.min.js'));
tinymce.editors = [];
tinymce.init({
selector: selector,
language: 'fr_FR',
width: '100%',
height: 250,
plugins: "link",
statusbar: false,
menubar: false,
toolbar: "bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link | undo redo"
});
// Prevent bootstrap dialog from blocking focusin
$(document).on('focusin', function (e) {
if ($(e.target).closest(".mce-window").length) {
e.stopImmediatePropagation();
}
});
// Indispensable pour que le contenu du textarea soit mis à jour avant de POSTer
form.submit(function () {
tinymce.triggerSave();
});
}
</script>
\ No newline at end of file
......@@ -26,6 +26,18 @@ $params = [
</a>
<?php endif ?>
<?php if ($pj->getFichier()->count() > 0 && !$pj->getValidation() && $this->isAllowed(Privileges::getResourceId(Privileges::PIECE_JUSTIFICATIVE_REFUS_PIECE))): ?>
<!-- data-loading-text="Patientez..."-->
<a class="refuser-pj btn btn-danger ajax-modal"
href="<?= $this->url('piece-jointe/intervenant/refuser', $params, [], true) ?>"
title="Refuser la pièce justificative '<?= $pj->getType() ?>'"
data-event="pj-refus-event"
data-tpj="<?= $pj->getType()->getId() ?>">
<i class="fas fa-trash-can"></i> Refuser
</a>
<?php endif ?>
<!-- actions de dévalidation de la pièce jointe entière -->
<?php if ($pj->getValidation() && $this->isAllowed(Privileges::getResourceId(Privileges::PIECE_JUSTIFICATIVE_DEVALIDATION))): ?>
<a class="devalider-pj btn btn-danger"
......
......@@ -176,6 +176,7 @@ return [
Service\NoteService::class => Service\NoteServiceFactory::class,
Service\TypeNoteService::class => Service\TypeNoteServiceFactory::class,
Assertion\NoteAssertion::class => \UnicaenAuth\Assertion\AssertionFactory::class,
Service\MailService::class => Service\MailServiceFactory::class,
Assertion\StatutAssertion::class => Assertion\StatutAssertionFactory::class,
],
......
......@@ -9,12 +9,10 @@ use Intervenant\Assertion\NoteAssertion;
use Intervenant\Entity\Db\Note;
use Intervenant\Form\MailerIntervenantFormAwareTrait;
use Intervenant\Form\NoteSaisieFormAwareTrait;
use Intervenant\Service\MailServiceAwareTrait;
use Intervenant\Service\NoteServiceAwareTrait;
use Laminas\Mail\Message as MailMessage;
use Laminas\Mime\Message;
use Laminas\Mime\Mime;
use Laminas\Mime\Part;
use UnicaenApp\View\Model\MessengerViewModel;
class NoteController extends AbstractController
......@@ -22,6 +20,7 @@ class NoteController extends AbstractController
use NoteServiceAwareTrait;
use NoteSaisieFormAwareTrait;
use MailerIntervenantFormAwareTrait;
use MailServiceAwareTrait;
public function indexAction()
{
......@@ -36,7 +35,7 @@ class NoteController extends AbstractController
throw new \Exception('Intervenant introuvable');
}
$notes = $this->getServiceNote()->getByIntervenant($intervenant, 'note');
$notes = $this->getServiceNote()->getByIntervenant($intervenant, 'note');
$emails = $this->getServiceNote()->getByIntervenant($intervenant, 'email');
$historique = $this->getServiceNote()->getHistoriqueIntervenant($intervenant);
......@@ -46,21 +45,22 @@ class NoteController extends AbstractController
}
public function saisirAction()
{
$intervenant = $this->getEvent()->getParam('intervenant');
$note = $this->getEvent()->getParam('note');
$form = $this->getFormNoteSaisie();
$note = $this->getEvent()->getParam('note');
$form = $this->getFormNoteSaisie();
if (empty($note)) {
$canEdit = $this->isAllowed(Privileges::getResourceId(Privileges::INTERVENANT_NOTE_AJOUT));
$title = 'Création d\'une nouvelle note intervenant';
$note = $this->getServiceNote()->newEntity();
$title = 'Création d\'une nouvelle note intervenant';
$note = $this->getServiceNote()->newEntity();
$note->setIntervenant($intervenant);
} else {
$canEdit = $this->isAllowed($note, NoteAssertion::PRIV_EDITER_NOTE);
$title = 'Édition d\'une note intervenant';
$title = 'Édition d\'une note intervenant';
}
......@@ -76,29 +76,30 @@ class NoteController extends AbstractController
});
} else {
$form->bind($note);
}
return compact('form', 'intervenant', 'title');
}
public function voirAction()
{
$intervenant = $this->getEvent()->getParam('intervenant');
$note = $this->getEvent()->getParam('note');
$title = 'Visualisation d\'une note intervenant';
$note = $this->getEvent()->getParam('note');
$title = 'Visualisation d\'une note intervenant';
return compact('intervenant', 'note', 'title');
}
public function supprimerAction()
{
$intervenant = $this->getEvent()->getParam('intervenant');
$note = $this->getEvent()->getParam('note');
$note = $this->getEvent()->getParam('note');
$canDelete = $this->isAllowed($note, NoteAssertion::PRIV_SUPPRIMER_NOTE);
......@@ -117,47 +118,30 @@ class NoteController extends AbstractController
return new MessengerViewModel(compact('note'));
}
public function envoyerEmailAction()
{
$intervenant = $this->getEvent()->getParam('intervenant');
$title = 'Rédiger un email à l\'intervenant';
$title = 'Rédiger un email à l\'intervenant';
$form = $this->getFormMailerIntervenant()->setIntervenant($intervenant)->initForm();
if ($this->getRequest()->isPost()) {
try {
$data = $this->getRequest()->getPost();
$from = $data['from'];
$to = $data['to'];
$data = $this->getRequest()->getPost();
$from = $data['from'];
$to = $data['to'];
$subject = $data['subject'];
$content = $data['content'];
$body = new Message();
$text = new Part($content);
$text->type = Mime::TYPE_HTML;
$text->charset = 'utf-8';
$body->addPart($text);
$message = new MailMessage();
$message->setEncoding('UTF-8')
->setFrom($from)
->setSubject($subject)
->addTo($to)
->setBody($body);
//Envoi du mail
$this->mail()->send($message);
$this->getServiceMail()->envoyerMail($from, $to, $subject, $content);
//Création d'une trace de l'envoi dans les notes de l'intervenant
$this->getServiceNote()->createNoteFromEmail($intervenant, $subject, $content);
$this->flashMessenger()->addSuccessMessage('Email envoyé à l\'intervenant');
} catch (\Exception $e) {
$this->flashMessenger()->addErrorMessage($this->translate($e));
}
}
return compact('intervenant', 'form', 'title');
}
}
......
<?php
namespace Intervenant\Service;
use Application\Service\AbstractService;
use Laminas\Mail\Message as MailMessage;
use Laminas\Mime\Message;
use Laminas\Mime\Mime;
use Laminas\Mime\Part;
use Intervenant\Form\MailerIntervenantFormAwareTrait;
use Intervenant\Form\NoteSaisieFormAwareTrait;
use UnicaenApp\Controller\Plugin\Mail;
/**
* Description of StatutServiceFactory
*
* @author Florian Joriot <florian.joriot at unicaen.fr>
*/
class MailService extends AbstractService
{
use NoteServiceAwareTrait;
use NoteSaisieFormAwareTrait;
use MailerIntervenantFormAwareTrait;
use MailServiceAwareTrait;
/**
* @var Mail
*/
private Mail $mail;
/**
* @return Mail
*/
public function getMail(): Mail
{
return $this->mail;
}