Commit 9796cd68 by Yvon Kerdoncuff

Merge remote-tracking branch 'origin/develop' into sprint-2-montpellier

parents 81f7495f 6c87fc12
...@@ -433,4 +433,8 @@ form[name="formEncaissement"] label { ...@@ -433,4 +433,8 @@ form[name="formEncaissement"] label {
.tav-cotisation-payment-form { .tav-cotisation-payment-form {
display: none; display: none;
margin-top: 1rem; margin-top: 1rem;
}
#infoForUserModal .modal-body {
word-break: break-all;
} }
\ No newline at end of file
...@@ -339,6 +339,14 @@ sonata_admin: ...@@ -339,6 +339,14 @@ sonata_admin:
icon: '<i class="fa fa-shopping-basket"></i>' icon: '<i class="fa fa-shopping-basket"></i>'
items: items:
- admin.productsFamily - admin.productsFamily
sonata.admin.informationPopup:
keep_open: false
on_top: true
label: "Popups d'information"
label_catalogue: SonataAdminBundle
icon: '<i class="fa fa-exclamation-circle"></i>'
items:
- admin.informationPopup
sonata.admin.group.globalparameter: sonata.admin.group.globalparameter:
keep_open: false keep_open: false
on_top: true on_top: true
......
...@@ -681,6 +681,16 @@ services: ...@@ -681,6 +681,16 @@ services:
label: "Familles de Produits" label: "Familles de Produits"
public: true public: true
admin.informationPopup:
class: App\Admin\InformationPopupAdmin
arguments: [~, App\Entity\InformationPopup, ~]
tags:
- name: sonata.admin
manager_type: orm
group: "Popups d'information"
label: "Popups d'information"
public: true
sonata.media.provider.csv: sonata.media.provider.csv:
class: App\Admin\ImportProvider class: App\Admin\ImportProvider
tags: tags:
......
...@@ -791,6 +791,11 @@ App\Entity\GlobalParameter: ...@@ -791,6 +791,11 @@ App\Entity\GlobalParameter:
description: "Numéro de téléphone à afficher dans le formulaire de contact si défini" description: "Numéro de téléphone à afficher dans le formulaire de contact si défini"
value: '' value: ''
mandatory: 1 mandatory: 1
gp31:
name: "RECONVERSION_FREQUENCY_HELP_TEXT"
description: "Texte d'explication à destination des prestataires pour le champ Fréquence de reconversion dans leur espace personnel"
value: 'Caisse Alimentaire Commune'
mandatory: 1
App\Entity\Siege: App\Entity\Siege:
......
...@@ -791,6 +791,11 @@ App\Entity\GlobalParameter: ...@@ -791,6 +791,11 @@ App\Entity\GlobalParameter:
description: "Numéro de téléphone à afficher dans le formulaire de contact si défini" description: "Numéro de téléphone à afficher dans le formulaire de contact si défini"
value: '' value: ''
mandatory: 1 mandatory: 1
gp31:
name: "RECONVERSION_FREQUENCY_HELP_TEXT"
description: "Texte d'explication à destination des prestataires pour le champ Fréquence de reconversion dans leur espace personnel"
value: 'Caisse Alimentaire Commune'
mandatory: 1
App\Entity\Siege: App\Entity\Siege:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
CKEDITOR.dialog.add("anchor",(function(e){function t(e,t){return e.createFakeElement(e.document.createElement("a",{attributes:t}),"cke_anchor","anchor")}return{title:e.lang.link.anchor.title,minWidth:300,minHeight:60,onOk:function(){var n=CKEDITOR.tools.trim(this.getValueOf("info","txtName")),a={id:n,name:n,"data-cke-saved-name":n};this._.selectedElement?this._.selectedElement.data("cke-realelement")?((n=t(e,a)).replace(this._.selectedElement),CKEDITOR.env.ie&&e.getSelection().selectElement(n)):this._.selectedElement.setAttributes(a):(n=(n=e.getSelection())&&n.getRanges()[0]).collapsed?(a=t(e,a),n.insertNode(a)):(CKEDITOR.env.ie&&9>CKEDITOR.env.version&&(a.class="cke_anchor"),(a=new CKEDITOR.style({element:"a",attributes:a})).type=CKEDITOR.STYLE_INLINE,a.applyToRange(n))},onHide:function(){delete this._.selectedElement},onShow:function(){var t,n=e.getSelection();t=n.getRanges()[0];var a=n.getSelectedElement();t.shrink(CKEDITOR.SHRINK_ELEMENT),t=(a=t.getEnclosedNode())&&a.type===CKEDITOR.NODE_ELEMENT&&("anchor"===a.data("cke-real-element-type")||a.is("a"))?a:void 0;var l=(a=t&&t.data("cke-realelement"))?CKEDITOR.plugins.link.tryRestoreFakeAnchor(e,t):CKEDITOR.plugins.link.getSelectedLink(e);if(l){this._.selectedElement=l;var i=l.data("cke-saved-name");this.setValueOf("info","txtName",i||""),!a&&n.selectElement(l),t&&(this._.selectedElement=t)}this.getContentElement("info","txtName").focus()},contents:[{id:"info",label:e.lang.link.anchor.title,accessKey:"I",elements:[{type:"text",id:"txtName",label:e.lang.link.anchor.name,required:!0,validate:function(){return!!this.getValue()||(alert(e.lang.link.anchor.errorName),!1)}}]}]}}));
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
"/build/app.3644f7b2.js" "/build/app.3644f7b2.js"
], ],
"css": [ "css": [
"/build/app.8a3f698b.css" "/build/app.ec67f059.css"
] ]
}, },
"admin": { "admin": {
......
{ {
"build/app.css": "/build/app.8a3f698b.css", "build/app.css": "/build/app.ec67f059.css",
"build/app.js": "/build/app.3644f7b2.js", "build/app.js": "/build/app.3644f7b2.js",
"build/admin.css": "/build/admin.4de55830.css", "build/admin.css": "/build/admin.4de55830.css",
"build/admin.js": "/build/admin.a08fea06.js", "build/admin.js": "/build/admin.a08fea06.js",
...@@ -85,6 +85,7 @@ ...@@ -85,6 +85,7 @@
"build/ckeditor/lang/fr.js": "/build/ckeditor/lang/fr.js", "build/ckeditor/lang/fr.js": "/build/ckeditor/lang/fr.js",
"build/ckeditor/skins/moono-lisa/dialog.css": "/build/ckeditor/skins/moono-lisa/dialog.css", "build/ckeditor/skins/moono-lisa/dialog.css": "/build/ckeditor/skins/moono-lisa/dialog.css",
"build/ckeditor/skins/moono/dialog.css": "/build/ckeditor/skins/moono/dialog.css", "build/ckeditor/skins/moono/dialog.css": "/build/ckeditor/skins/moono/dialog.css",
"build/ckeditor/plugins/link/dialogs/link.js": "/build/ckeditor/plugins/link/dialogs/link.js",
"build/ckeditor/lang/en.js": "/build/ckeditor/lang/en.js", "build/ckeditor/lang/en.js": "/build/ckeditor/lang/en.js",
"build/ckeditor/skins/kama/dialog_iequirks.css": "/build/ckeditor/skins/kama/dialog_iequirks.css", "build/ckeditor/skins/kama/dialog_iequirks.css": "/build/ckeditor/skins/kama/dialog_iequirks.css",
"build/ckeditor/skins/kama/dialog_ie7.css": "/build/ckeditor/skins/kama/dialog_ie7.css", "build/ckeditor/skins/kama/dialog_ie7.css": "/build/ckeditor/skins/kama/dialog_ie7.css",
...@@ -112,6 +113,7 @@ ...@@ -112,6 +113,7 @@
"build/ckeditor/skins/kama/skin.js": "/build/ckeditor/skins/kama/skin.js", "build/ckeditor/skins/kama/skin.js": "/build/ckeditor/skins/kama/skin.js",
"build/ckeditor/contents.css": "/build/ckeditor/contents.css", "build/ckeditor/contents.css": "/build/ckeditor/contents.css",
"build/ckeditor/skins/moono/images/hidpi/close.png": "/build/ckeditor/skins/moono/images/hidpi/close.png", "build/ckeditor/skins/moono/images/hidpi/close.png": "/build/ckeditor/skins/moono/images/hidpi/close.png",
"build/ckeditor/plugins/link/dialogs/anchor.js": "/build/ckeditor/plugins/link/dialogs/anchor.js",
"build/ckeditor/skins/moono/images/hidpi/lock.png": "/build/ckeditor/skins/moono/images/hidpi/lock.png", "build/ckeditor/skins/moono/images/hidpi/lock.png": "/build/ckeditor/skins/moono/images/hidpi/lock.png",
"build/ckeditor/skins/moono-lisa/images/hidpi/refresh.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/refresh.png", "build/ckeditor/skins/moono-lisa/images/hidpi/refresh.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/refresh.png",
"build/images/source-sans-pro-v14-latin-300.svg": "/build/images/source-sans-pro-v14-latin-300.4e7fe004.svg", "build/images/source-sans-pro-v14-latin-300.svg": "/build/images/source-sans-pro-v14-latin-300.4e7fe004.svg",
...@@ -125,6 +127,7 @@ ...@@ -125,6 +127,7 @@
"build/ckeditor/plugins/flash/lang/fr.js": "/build/ckeditor/plugins/flash/lang/fr.js", "build/ckeditor/plugins/flash/lang/fr.js": "/build/ckeditor/plugins/flash/lang/fr.js",
"build/ckeditor/plugins/forms/lang/en.js": "/build/ckeditor/plugins/forms/lang/en.js", "build/ckeditor/plugins/forms/lang/en.js": "/build/ckeditor/plugins/forms/lang/en.js",
"build/ckeditor/plugins/docprops/lang/en.js": "/build/ckeditor/plugins/docprops/lang/en.js", "build/ckeditor/plugins/docprops/lang/en.js": "/build/ckeditor/plugins/docprops/lang/en.js",
"build/ckeditor/plugins/link/images/hidpi/anchor.png": "/build/ckeditor/plugins/link/images/hidpi/anchor.png",
"build/ckeditor/skins/moono-lisa/images/hidpi/lock-open.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/lock-open.png", "build/ckeditor/skins/moono-lisa/images/hidpi/lock-open.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/lock-open.png",
"build/ckeditor/skins/moono-lisa/images/hidpi/lock.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/lock.png", "build/ckeditor/skins/moono-lisa/images/hidpi/lock.png": "/build/ckeditor/skins/moono-lisa/images/hidpi/lock.png",
"build/ckeditor/skins/moono/images/refresh.png": "/build/ckeditor/skins/moono/images/refresh.png", "build/ckeditor/skins/moono/images/refresh.png": "/build/ckeditor/skins/moono/images/refresh.png",
...@@ -134,6 +137,7 @@ ...@@ -134,6 +137,7 @@
"build/ckeditor/skins/moono/images/lock.png": "/build/ckeditor/skins/moono/images/lock.png", "build/ckeditor/skins/moono/images/lock.png": "/build/ckeditor/skins/moono/images/lock.png",
"build/ckeditor/skins/moono/images/lock-open.png": "/build/ckeditor/skins/moono/images/lock-open.png", "build/ckeditor/skins/moono/images/lock-open.png": "/build/ckeditor/skins/moono/images/lock-open.png",
"build/ckeditor/skins/moono-lisa/images/refresh.png": "/build/ckeditor/skins/moono-lisa/images/refresh.png", "build/ckeditor/skins/moono-lisa/images/refresh.png": "/build/ckeditor/skins/moono-lisa/images/refresh.png",
"build/ckeditor/plugins/link/images/anchor.png": "/build/ckeditor/plugins/link/images/anchor.png",
"build/ckeditor/config.js": "/build/ckeditor/config.js", "build/ckeditor/config.js": "/build/ckeditor/config.js",
"build/ckeditor/plugins/liststyle/lang/fr.js": "/build/ckeditor/plugins/liststyle/lang/fr.js", "build/ckeditor/plugins/liststyle/lang/fr.js": "/build/ckeditor/plugins/liststyle/lang/fr.js",
"build/ckeditor/skins/moono-lisa/images/close.png": "/build/ckeditor/skins/moono-lisa/images/close.png", "build/ckeditor/skins/moono-lisa/images/close.png": "/build/ckeditor/skins/moono-lisa/images/close.png",
......
...@@ -184,8 +184,10 @@ class DonAdmin extends AbstractAdmin ...@@ -184,8 +184,10 @@ class DonAdmin extends AbstractAdmin
public function getExportFields() public function getExportFields()
{ {
$ssaFriendlyTypeNames = $this->getConfigurationPool()->getContainer()->getParameter('tav_env')
&& $this->getConfigurationPool()->getContainer()->getParameter('ssa_friendly_flux_type_names');
return [ return [
'Id' => 'expediteur', 'Id' => $ssaFriendlyTypeNames ? 'expediteur.email' : 'expediteur',
'Groupe' => 'expediteur.groupe.name', 'Groupe' => 'expediteur.groupe.name',
'Type' => 'type', 'Type' => 'type',
'Montant' => 'montant', 'Montant' => 'montant',
......
...@@ -64,6 +64,7 @@ class FluxAdmin extends AbstractAdmin ...@@ -64,6 +64,7 @@ class FluxAdmin extends AbstractAdmin
$collection->clearExcept(['list', 'export']); $collection->clearExcept(['list', 'export']);
} }
//Where is this method used ?
protected function configureExportFields(): array protected function configureExportFields(): array
{ {
$ssaFriendlyTypeNames = $this->getConfigurationPool()->getContainer()->getParameter('tav_env') $ssaFriendlyTypeNames = $this->getConfigurationPool()->getContainer()->getParameter('tav_env')
...@@ -104,7 +105,7 @@ class FluxAdmin extends AbstractAdmin ...@@ -104,7 +105,7 @@ class FluxAdmin extends AbstractAdmin
->add('montant', 'decimal', ['label' => 'Montant', 'attributes' => ['fraction_digits' => 2]]) ->add('montant', 'decimal', ['label' => 'Montant', 'attributes' => ['fraction_digits' => 2]])
->add('expediteur', null, ['label' => 'Expediteur']) ->add('expediteur', null, ['label' => 'Expediteur'])
->add('destinataire', null, ['label' => 'Destinataire']) ->add('destinataire', null, ['label' => 'Destinataire'])
->add('operateur', null, ['label' => 'Operateur']) ->add($ssaFriendlyTypeNames ? 'operateur.email' : 'operateur', null, ['label' => 'Operateur'])
->addIdentifier('reference', null, ['label' => 'Reference']) ->addIdentifier('reference', null, ['label' => 'Reference'])
// @TODO : ajouter le verify uniquement si l'on souhaite (param url)=> sinon c'est beaucoup trop long... // @TODO : ajouter le verify uniquement si l'on souhaite (param url)=> sinon c'est beaucoup trop long...
// ->addIdentifier('verify', null, array('label' => 'Vérifié')) // ->addIdentifier('verify', null, array('label' => 'Vérifié'))
...@@ -249,7 +250,7 @@ class FluxAdmin extends AbstractAdmin ...@@ -249,7 +250,7 @@ class FluxAdmin extends AbstractAdmin
'Montant' => 'montant', 'Montant' => 'montant',
'Expediteur' => 'expediteur', 'Expediteur' => 'expediteur',
'Destinataire' => 'destinataire', 'Destinataire' => 'destinataire',
'Operateur' => 'operateur', 'Operateur' => $ssaFriendlyTypeNames ? 'operateur.email' : 'operateur',
'Moyen' => 'moyen', 'Moyen' => 'moyen',
'Reference' => 'reference', 'Reference' => 'reference',
]; ];
......
<?php
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
/**
* Administration des popups d'information.
* Ces popup sont à destination des utilisateurs (adhérents uniquement pour l'instant),
* et s'ouvrent automatiquement au lancement de l'application,
* tant que l'utilisateur n'a pas cliqué sur le bouton de confirmation
*
* KOHINOS : Outil de gestion de Monnaie Locale Complémentaire
*/
class InformationPopupAdmin extends AbstractAdmin
{
protected function configureFormFields(FormMapper $form): void
{
$form
->add('title', TextType::class, [
'label' => 'Titre',
'required' => true,
])
->add('content', CKEditorType::class, [
'label' => 'Contenu',
'required' => true,
])
->add('validationButtonText', TextType::class, [
'label' => 'Texte du bouton de validation',
'required' => true,
'attr' => [
'placeholder' => 'Par exemple : "J\'ai compris", "J\'ai bien effectué l\'action"...',
],
'help' => 'Le clic sur ce bouton entraînera la fermeture définitive de cette popup pour cet utilisateur, il est donc conseillé d\'y renseigner un texte explicite.'
])
->add('closingButtonText', TextType::class, [
'label' => 'Texte du bouton de fermeture',
'required' => true,
'attr' => [
'placeholder' => 'Par exemple : "Fermer pour l\'instant", "Je le ferai plus tard"...',
]
])
->add('enabled', null, [
'label' => 'Activé ?',
'help' => 'Une seule popup d\'information peut être active à la fois. Activer cette popup désactivera toutes les autres.'
]);
}
public function postPersist($informationPopup)
{
$this->disableOtherPopups($informationPopup);
}
public function preUpdate($informationPopup)
{
$this->disableOtherPopups($informationPopup);
}
/**
* Only one popup should be enabled at a time.
* If enableling a popup in the admin, disable the rest.
*/
private function disableOtherPopups($informationPopup)
{
if (true == $informationPopup->getEnabled()) {
$em = $this->getConfigurationPool()->getContainer()->get('doctrine')->getManager();
$qb = $em->createQueryBuilder();
$qb->update('App\Entity\InformationPopup', 'e')
->set('e.enabled', ':newValue')
->where('e.id != :id')
->setParameter('newValue', 0)
->setParameter('id', $informationPopup->getId());
$query = $qb->getQuery();
$query->execute();
}
}
protected function configureDatagridFilters(DatagridMapper $datagrid): void
{
$datagrid
->add('title', null, [
'label' => 'Titre'
]);
}
protected function configureListFields(ListMapper $list): void
{
$list
->addIdentifier('title', null, [
'label' => 'Titre'
])
->add('enabled', null, [
'label' => 'Activé ?',
]);
}
}
\ No newline at end of file
...@@ -146,8 +146,8 @@ class SendCcasTransactionsExportToPrestatairesCommand extends Command ...@@ -146,8 +146,8 @@ class SendCcasTransactionsExportToPrestatairesCommand extends Command
if ($previousAnonymousToken !== $row['anonymous_token']) { if ($previousAnonymousToken !== $row['anonymous_token']) {
$this->fputcsvSeparatedBySemicolon($file, [ $this->fputcsvSeparatedBySemicolon($file, [
'TOTAL ' . $previousAnonymousToken, 'TOTAL ' . $previousAnonymousToken,
$clientTotal, number_format($clientTotal, 2),
$nf->format($clientTotal), $this->currencySpellout($nf, $clientTotal),
'', '',
]); ]);
$clientTotal = 0; $clientTotal = 0;
...@@ -156,8 +156,8 @@ class SendCcasTransactionsExportToPrestatairesCommand extends Command ...@@ -156,8 +156,8 @@ class SendCcasTransactionsExportToPrestatairesCommand extends Command
//Write transaction line //Write transaction line
$this->fputcsvSeparatedBySemicolon($file, [ $this->fputcsvSeparatedBySemicolon($file, [
$row['anonymous_token'], $row['anonymous_token'],
$row['montant'], number_format(floatval($row['montant']), 2),
$this->currencySpellout($nf, $row['montant']), $this->currencySpellout($nf, floatval($row['montant'])),
$row['created_at'], $row['created_at'],
]); ]);
$clientTotal += $row['montant']; $clientTotal += $row['montant'];
......
...@@ -12,6 +12,8 @@ use App\Entity\Reconversion; ...@@ -12,6 +12,8 @@ use App\Entity\Reconversion;
use App\Entity\TransactionPrestataireAdherent; use App\Entity\TransactionPrestataireAdherent;
use App\Entity\User; use App\Entity\User;
use App\Entity\TransactionAdherentPrestataire; use App\Entity\TransactionAdherentPrestataire;
use App\Entity\InformationPopup;
use App\Entity\InformationPopupUser;
use App\Enum\MoyenEnum; use App\Enum\MoyenEnum;
use App\Form\Type\CotiserFormType; use App\Form\Type\CotiserFormType;
use App\Form\Type\DonAdherentFormType; use App\Form\Type\DonAdherentFormType;
...@@ -561,4 +563,31 @@ class UserController extends AbstractController ...@@ -561,4 +563,31 @@ class UserController extends AbstractController
return $this->render('@kohinos/tav/payment_done_page.html.twig', $templateData); return $this->render('@kohinos/tav/payment_done_page.html.twig', $templateData);
} }
/**
* Register that the connected user (currently only adherents) has clicked on the popup validation button,
* So it's not shown to him/her again.
*
* @Route("/user/setUserValidatedInformationPopup", name="set_user_validated_information_popup")
* @IsGranted({"ROLE_ADHERENT"})
*/
public function setUserValidatedInformationPopupAction(Request $request)
{
$user = $this->security->getUser();
$activePopup = $this->em->getRepository(InformationPopup::class)->findOneBy(['enabled' => true]);
$activePopupUser = $this->em->getRepository(InformationPopupUser::class)->findOneBy(['informationPopup' => $activePopup, 'user' => $user]);
if (null === $activePopupUser) {
$activePopupUser = new InformationPopupUser();
$activePopupUser->setInformationPopup($activePopup);
$activePopupUser->setUser($user);
}
$activePopupUser->setHasValidated(true);
$this->em->persist($activePopupUser);
$this->em->flush();
return $this->redirectToRoute('index');
}
} }
...@@ -54,6 +54,7 @@ class GlobalParameter ...@@ -54,6 +54,7 @@ class GlobalParameter
const VIREMENT_RECONVERSION_RAISON_GESTIONNAIRE = 'VIREMENT_RECONVERSION_RAISON_GESTIONNAIRE'; const VIREMENT_RECONVERSION_RAISON_GESTIONNAIRE = 'VIREMENT_RECONVERSION_RAISON_GESTIONNAIRE';
const VIREMENT_RECONVERSION_BIC_GESTIONNAIRE = 'VIREMENT_RECONVERSION_BIC_GESTIONNAIRE'; const VIREMENT_RECONVERSION_BIC_GESTIONNAIRE = 'VIREMENT_RECONVERSION_BIC_GESTIONNAIRE';
const VIREMENT_RECONVERSION_IBAN_GESTIONNAIRE = 'VIREMENT_RECONVERSION_IBAN_GESTIONNAIRE'; const VIREMENT_RECONVERSION_IBAN_GESTIONNAIRE = 'VIREMENT_RECONVERSION_IBAN_GESTIONNAIRE';
const RECONVERSION_FREQUENCY_HELP_TEXT = 'RECONVERSION_FREQUENCY_HELP_TEXT';
const SSA_ALLOW_COMPTOIR_TO_UPDATE_HOUSEHOLD_ALLOCATION_DATA = 'SSA_ALLOW_COMPTOIR_TO_UPDATE_HOUSEHOLD_ALLOCATION_DATA'; const SSA_ALLOW_COMPTOIR_TO_UPDATE_HOUSEHOLD_ALLOCATION_DATA = 'SSA_ALLOW_COMPTOIR_TO_UPDATE_HOUSEHOLD_ALLOCATION_DATA';
const SSA_HOUSEHOLD_ALLOCATION_MSG_FOR_COMPTOIR = 'SSA_HOUSEHOLD_ALLOCATION_MSG_FOR_COMPTOIR'; const SSA_HOUSEHOLD_ALLOCATION_MSG_FOR_COMPTOIR = 'SSA_HOUSEHOLD_ALLOCATION_MSG_FOR_COMPTOIR';
......
<?php
namespace App\Entity;
use App\Repository\InformationPopupRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Ramsey\Uuid\Doctrine\UuidGenerator;
/**
* @ORM\Entity(repositoryClass=InformationPopupRepository::class)
*/
class InformationPopup
{
/**
* @var \Ramsey\Uuid\UuidInterface
*
* @ORM\Id
* @ORM\Column(type="uuid", unique=true)
* @ORM\GeneratedValue(strategy="CUSTOM")
* @ORM\CustomIdGenerator(class=UuidGenerator::class)
*/
protected $id;
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
/**
* @ORM\Column(type="text")
*/
private $content;
/**
* @ORM\Column(type="string", length=100)
*/
private $validationButtonText;
/**
* @ORM\Column(type="string", length=100)
*/
private $closingButtonText;
/**
* Don't use EnablableEntityTrait as it is true by default.
* Only one InformationPopup should be active at a time.
*
* @ORM\Column(type="boolean", options={"default": false})
*/
private $enabled = false;
/**
* @ORM\OneToMany(targetEntity=InformationPopupUser::class, mappedBy="informationPopup", orphanRemoval=true)
*/
private $informationPopupUsers;
public function __construct()
{
$this->informationPopupUsers = new ArrayCollection();
}
public function __toString(): string
{
return $this->getTitle();
}
public function getId()
{
return $this->id;
}
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
public function getContent(): ?string
{
return $this->content;
}
public function setContent(string $content): self
{
$this->content = $content;
return $this;
}
public function getValidationButtonText(): ?string
{
return $this->validationButtonText;
}
public function setValidationButtonText(string $validationButtonText): self
{
$this->validationButtonText = $validationButtonText;
return $this;
}
public function getClosingButtonText(): ?string
{
return $this->closingButtonText;
}
public function setClosingButtonText(string $closingButtonText): self
{
$this->closingButtonText = $closingButtonText;
return $this;
}
public function getEnabled(): ?bool
{
return $this->enabled;
}
public function setEnabled(bool $enabled): self
{
$this->enabled = $enabled;
return $this;
}
/**
* @return Collection<int, InformationPopupUser>
*/
public function getInformationPopupUsers(): Collection
{
return $this->informationPopupUsers;
}
public function addInformationPopupUser(InformationPopupUser $informationPopupUser): self
{
if (!$this->informationPopupUsers->contains($informationPopupUser)) {
$this->informationPopupUsers[] = $informationPopupUser;
$informationPopupUser->setInformationPopup($this);
}
return $this;
}
public function removeInformationPopupUser(InformationPopupUser $informationPopupUser): self
{
if ($this->informationPopupUsers->removeElement($informationPopupUser)) {
// set the owning side to null (unless already changed)
if ($informationPopupUser->getInformationPopup() === $this) {
$informationPopupUser->setInformationPopup(null);
}
}
return $this;
}
}
<?php
namespace App\Entity;
use App\Repository\InformationPopupUserRepository;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass=InformationPopupUserRepository::class)
*/
class InformationPopupUser
{
/**
* @ORM\Id
* @ORM\GeneratedValue
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\ManyToOne(targetEntity=InformationPopup::class, inversedBy="informationPopupUsers")
* @ORM\JoinColumn(nullable=false)
*/
private $informationPopup;
/**
* @ORM\ManyToOne(targetEntity=User::class)
* @ORM\JoinColumn(nullable=false)
*/
private $user;
/**
* @ORM\Column(type="boolean", options={"default": false})
*/
private $hasValidated = false;
public function getId(): ?int
{
return $this->id;
}
public function getInformationPopup(): ?InformationPopup
{
return $this->informationPopup;
}
public function setInformationPopup(?InformationPopup $informationPopup): self
{
$this->informationPopup = $informationPopup;
return $this;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(?User $user): self
{
$this->user = $user;
return $this;
}
public function getHasValidated(): ?bool
{
return $this->hasValidated;
}
public function setHasValidated(bool $hasValidated): self
{
$this->hasValidated = $hasValidated;
return $this;
}
}
...@@ -352,6 +352,13 @@ class GlobalConfigurationFormType extends AbstractType ...@@ -352,6 +352,13 @@ class GlobalConfigurationFormType extends AbstractType
'required' => false, 'required' => false,
'_placeholder' => '', '_placeholder' => '',
]) ])
->add('payingentityname', GlobalParameterType::class, [
'label' => "Texte d'explication à destination des prestataires pour le champ Fréquence de reconversion dans leur espace personnel",
'_description' => "Texte d'explication à destination des prestataires pour le champ Fréquence de reconversion dans leur espace personnel",
'name_param' => GlobalParameter::RECONVERSION_FREQUENCY_HELP_TEXT,
'_placeholder' => '',
'required' => true,
])
; ;
} }
......
...@@ -95,9 +95,10 @@ class PrestataireInfosFormType extends AbstractType ...@@ -95,9 +95,10 @@ class PrestataireInfosFormType extends AbstractType
if ($this->container->getParameter('tav_env') && $this->container->getParameter('automatisation_reconversion')) { if ($this->container->getParameter('tav_env') && $this->container->getParameter('automatisation_reconversion')) {
$mlcName = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::MLC_NAME_SMALL); $mlcName = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::MLC_NAME_SMALL);
$helpMsqg = "Fréquence à laquelle je souhaite que la caisse commune de l'alimentation (via l'association Acclimat'action)"
. " me verse en euros la somme des {$mlcName} encaissées dans mon point de vente " // If a paying entity is defined, add to to help message
. "(1 {$mlcName} = 1 euro). Le versement se fait via un virement bancaire."; $helpMsg = $this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::RECONVERSION_FREQUENCY_HELP_TEXT);
$helpMsg = is_null($helpMsg) ? '' : $helpMsg;
$builder $builder
->add('reconversionFrequency', ChoiceType::class, [ ->add('reconversionFrequency', ChoiceType::class, [
...@@ -110,7 +111,7 @@ class PrestataireInfosFormType extends AbstractType ...@@ -110,7 +111,7 @@ class PrestataireInfosFormType extends AbstractType
'label' => 'Fréquence de reconversion :', 'label' => 'Fréquence de reconversion :',
'placeholder' => 'Choisir une option', 'placeholder' => 'Choisir une option',
'required' => false, 'required' => false,
'help' => $helpMsqg 'help' => $helpMsg
]); ]);
} }
......
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250109101735 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TABLE information_popup (id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', title VARCHAR(255) NOT NULL, content LONGTEXT NOT NULL, validation_button_text VARCHAR(100) NOT NULL, closing_button_text VARCHAR(100) NOT NULL, enabled TINYINT(1) DEFAULT \'0\' NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_general_ci` ENGINE = InnoDB');
$this->addSql('CREATE TABLE information_popup_user (id INT AUTO_INCREMENT NOT NULL, information_popup_id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', user_id CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', has_validated TINYINT(1) DEFAULT \'0\' NOT NULL, INDEX IDX_9AA7FF00FBB63E47 (information_popup_id), INDEX IDX_9AA7FF00A76ED395 (user_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE `utf8_general_ci` ENGINE = InnoDB');
$this->addSql('ALTER TABLE information_popup_user ADD CONSTRAINT FK_9AA7FF00FBB63E47 FOREIGN KEY (information_popup_id) REFERENCES information_popup (id)');
$this->addSql('ALTER TABLE information_popup_user ADD CONSTRAINT FK_9AA7FF00A76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('ALTER TABLE information_popup_user DROP FOREIGN KEY FK_9AA7FF00FBB63E47');
$this->addSql('DROP TABLE information_popup');
$this->addSql('DROP TABLE information_popup_user');
}
}
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250115160900 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'PAYING_ENTITY_NAME', 'Nom de l\'organisme qui effectuera les paiements en euros (versement des reconversions aux prestataires...)', null, '1')");
}
public function down(Schema $schema) : void
{
$this->addSql("DELETE FROM global_parameter WHERE name='PAYING_ENTITY_NAME'");
// this down() migration is auto-generated, please modify it to your needs
}
}
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250128122800 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'RECONVERSION_FREQUENCY_HELP_TEXT', 'Texte d\'explication à destination des prestataires pour le champ Fréquence de reconversion dans leur espace personnel', null, '1')");
$this->addSql("DELETE FROM global_parameter WHERE name='PAYING_ENTITY_NAME'");
}
public function down(Schema $schema) : void
{
$this->addSql("DELETE FROM global_parameter WHERE name='RECONVERSION_FREQUENCY_HELP_TEXT'");
$this->addSql("INSERT INTO global_parameter (id, name, description, value, mandatory) VALUES (UUID(), 'PAYING_ENTITY_NAME', 'Nom de l\'organisme qui effectuera les paiements en euros (versement des reconversions aux prestataires...)', null, '1')");
// this down() migration is auto-generated, please modify it to your needs
}
}
<?php
namespace App\Repository;
use App\Entity\InformationPopup;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<InformationPopup>
*
* @method InformationPopup|null find($id, $lockMode = null, $lockVersion = null)
* @method InformationPopup|null findOneBy(array $criteria, array $orderBy = null)
* @method InformationPopup[] findAll()
* @method InformationPopup[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class InformationPopupRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, InformationPopup::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(InformationPopup $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(InformationPopup $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
// /**
// * @return InformationPopup[] Returns an array of InformationPopup objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('i')
->andWhere('i.exampleField = :val')
->setParameter('val', $value)
->orderBy('i.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?InformationPopup
{
return $this->createQueryBuilder('i')
->andWhere('i.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
<?php
namespace App\Repository;
use App\Entity\InformationPopupUser;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\ORM\OptimisticLockException;
use Doctrine\ORM\ORMException;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<InformationPopupUser>
*
* @method InformationPopupUser|null find($id, $lockMode = null, $lockVersion = null)
* @method InformationPopupUser|null findOneBy(array $criteria, array $orderBy = null)
* @method InformationPopupUser[] findAll()
* @method InformationPopupUser[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class InformationPopupUserRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, InformationPopupUser::class);
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function add(InformationPopupUser $entity, bool $flush = true): void
{
$this->_em->persist($entity);
if ($flush) {
$this->_em->flush();
}
}
/**
* @throws ORMException
* @throws OptimisticLockException
*/
public function remove(InformationPopupUser $entity, bool $flush = true): void
{
$this->_em->remove($entity);
if ($flush) {
$this->_em->flush();
}
}
// /**
// * @return InformationPopupUser[] Returns an array of InformationPopupUser objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('i')
->andWhere('i.exampleField = :val')
->setParameter('val', $value)
->orderBy('i.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/
/*
public function findOneBySomeField($value): ?InformationPopupUser
{
return $this->createQueryBuilder('i')
->andWhere('i.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
...@@ -23,6 +23,8 @@ use App\Entity\Prestataire; ...@@ -23,6 +23,8 @@ use App\Entity\Prestataire;
use App\Entity\Rubrique; use App\Entity\Rubrique;
use App\Entity\Siege; use App\Entity\Siege;
use App\Entity\User; use App\Entity\User;
use App\Entity\InformationPopup;
use App\Entity\InformationPopupUser;
use App\Enum\CurrencyEnum; use App\Enum\CurrencyEnum;
use App\Flux\AccountableInterface; use App\Flux\AccountableInterface;
use App\Utils\CotisationUtils; use App\Utils\CotisationUtils;
...@@ -109,6 +111,8 @@ class AppExtension extends AbstractExtension ...@@ -109,6 +111,8 @@ class AppExtension extends AbstractExtension
new \Twig_SimpleFunction('parameter', function ($name) { new \Twig_SimpleFunction('parameter', function ($name) {
return $this->container->getParameter($name); return $this->container->getParameter($name);
}), }),
new \Twig_SimpleFunction('showInformationModal', [$this, 'showInformationModal']),
new \Twig_SimpleFunction('getInformationPopupData', [$this, 'getInformationPopupData']),
]; ];
} }
...@@ -576,4 +580,38 @@ class AppExtension extends AbstractExtension ...@@ -576,4 +580,38 @@ class AppExtension extends AbstractExtension
{ {
return $this->tavCotisationUtils->checkExistingRecurringPayment($userEmail); return $this->tavCotisationUtils->checkExistingRecurringPayment($userEmail);
} }
/**
* Display an informative modale destined to users at app loading, if conditions are required.
*
* Conditions :
* - user is adherent (forced for now)
* - user hasn't clicked on the modal validation button yet (InformationPopupUser instance not created or exists with hasValidated property at false)
*/
public function showInformationModal()
{
$user = $this->security->getUser();
if (null != $user && $this->security->isGranted('ROLE_ADHERENT')) {
// There should be only one enabled popup at a given time
$activePopup = $this->em->getRepository(InformationPopup::class)->findOneBy(['enabled' => true]);
if (!is_null($activePopup)) {
$activePopupUser = $this->em->getRepository(InformationPopupUser::class)->findOneBy(['informationPopup' => $activePopup, 'user' => $user]);
if (null == $activePopupUser || false == $activePopupUser->getHasValidated()) {
return true;
}
}
}
return false;
}
/**
* If the information modale is shown, get its data
*/
public function getInformationPopupData()
{
return $this->em->getRepository(InformationPopup::class)->findOneBy(['enabled' => true]);
}
} }
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
<div> <div>
{% if object is instanceof("App\\Entity\\DonAdherent") or (object is instanceof("App\\Entity\\Don") and object.type == 'don_adherent' ) %} {% if object is instanceof("App\\Entity\\DonAdherent") or (object is instanceof("App\\Entity\\Don") and object.type == 'don_adherent' ) %}
<a class="sonata-link-identifier" href="{{ path('adherent_edit', {'id': object.expediteur.id}) }}"> <a class="sonata-link-identifier" href="{{ path('adherent_edit', {'id': object.expediteur.id}) }}">
{{ 'Adhérent'|trans }} : {{ object.expediteur.name }} {{ 'Adhérent'|trans }} : {% if tav_env and ssa_friendly_flux_type_names %}{{ object.expediteur.email }}{% else %}{{ object.expediteur.name }}{% endif %}
</a> </a>
{% elseif object is instanceof("App\\Entity\\DonPrestataire") or (object is instanceof("App\\Entity\\Don") and object.type == 'don_prestataire' ) %} {% elseif object is instanceof("App\\Entity\\DonPrestataire") or (object is instanceof("App\\Entity\\Don") and object.type == 'don_prestataire' ) %}
<a class="sonata-link-identifier" href="{{ path('prestataire_edit', {'id': object.expediteur.id}) }}"> <a class="sonata-link-identifier" href="{{ path('prestataire_edit', {'id': object.expediteur.id}) }}">
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
{% include '@kohinos/common/modale_choix_groupe.html.twig' %} {% include '@kohinos/common/modale_choix_groupe.html.twig' %}
{% include '@kohinos/common/modale_confirmation_transaction.html.twig' %} {% include '@kohinos/common/modale_confirmation_transaction.html.twig' %}
{% include '@kohinos/common/modale_info_for_users.html.twig' %}
<!-- HEADER --> <!-- HEADER -->
{% block header %} {% block header %}
...@@ -100,6 +101,16 @@ ...@@ -100,6 +101,16 @@
}); });
</script> </script>
{% endif %} {% endif %}
{# AFFICHAGE DE LA MODALE INFORMATIVE #}
{% if showInformationModal() %}
<script>
$(document).ready(function() {
$('#infoForUserModal').modal('show');
});
</script>
{% endif %}
{% if app.request.query.get('showmlcadhesionmodal') %} {% if app.request.query.get('showmlcadhesionmodal') %}
<script> <script>
$(document).ready(function() { $(document).ready(function() {
......
<!-- Modal -->
{% set informationPopupData = getInformationPopupData() %}
<div class="modal fade" id="infoForUserModal" data-backdrop="static" data-keyboard="false" tabindex="-1" role="dialog" aria-labelledby="infoForUserModalTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
{% if informationPopupData %}
<div class="modal-header">
<h5 class="modal-title" id="infoForUserModalTitle">{{ informationPopupData.title }}</h5>
</div>
<div class="modal-body">
{{ informationPopupData.content|raw }}
</div>
<div class="modal-footer">
<a href='{{ path('set_user_validated_information_popup') }}' class="btn btn-primary">{{ informationPopupData.validationButtonText }}</a>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ informationPopupData.closingButtonText }}</button>
</div>
{% endif %}
</div>
</div>
</div>
\ No newline at end of file
...@@ -8,6 +8,7 @@ Encore ...@@ -8,6 +8,7 @@ Encore
{from: './node_modules/ckeditor/adapters', to: 'ckeditor/adapters/[path][name].[ext]'}, {from: './node_modules/ckeditor/adapters', to: 'ckeditor/adapters/[path][name].[ext]'},
{from: './node_modules/ckeditor/lang', to: 'ckeditor/lang/[path][name].[ext]', pattern: /fr\.js|en\.js$/}, {from: './node_modules/ckeditor/lang', to: 'ckeditor/lang/[path][name].[ext]', pattern: /fr\.js|en\.js$/},
{from: './node_modules/ckeditor/plugins', to: 'ckeditor/plugins/[path][name].[ext]', pattern: /(\/lang\/(fr\.js|en\.js)|(^lang\/.*))/}, {from: './node_modules/ckeditor/plugins', to: 'ckeditor/plugins/[path][name].[ext]', pattern: /(\/lang\/(fr\.js|en\.js)|(^lang\/.*))/},
{from: './node_modules/ckeditor/plugins/link', to: 'ckeditor/plugins/link/[path][name].[ext]'},
{from: './node_modules/ckeditor/skins', to: 'ckeditor/skins/[path][name].[ext]'} {from: './node_modules/ckeditor/skins', to: 'ckeditor/skins/[path][name].[ext]'}
]) ])
// directory where compiled assets will be stored // directory where compiled assets will be stored
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment