Commit ed2b0107 by Damien Moulard

Merge branch 'develop' into 4123-explanation-for-deactivating-user

parents 093932d6 735b3a14
...@@ -158,3 +158,12 @@ Permettre la simulation du https en local : ...@@ -158,3 +158,12 @@ Permettre la simulation du https en local :
Lancer le serveur local Lancer le serveur local
**$ symfony server:start** **$ symfony server:start**
Compiler les assets (css & js) après modification pour tests
**$ yarn install** si besoin (première modif des assets)
**$ yarn run encore dev**
Compiler les assets avant de commit :
**$ yarn run encore prod**
...@@ -52,3 +52,52 @@ legend.required:after { ...@@ -52,3 +52,52 @@ legend.required:after {
.invalid-feedback { .invalid-feedback {
display: inline-block !important; display: inline-block !important;
} }
#code-digits-container {
display: flex;
flex-wrap: wrap;
justify-content: center;
width: 300px;
margin: 10px auto 30px auto;
}
.payment-code-button, .payment-code-correction-button {
display: inline-block;
background-color: white;
height: 80px;
width: 80px;
font-size: 1.5rem;
border: 3px solid #106a8c;
color: #117298;
font-weight: bold;
text-align: center;
text-decoration: none;
margin: 4px 2px;
border-radius: 50%;
}
.payment-code-button:active, .payment-code-correction-button:active {
background-color:#106a8c;
color: white;
}
.payment-code-button-placeholder {
height: 80px;
width: 80px;
}
#code-visual {
height: 60px;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
}
#payment-validation-subheader {
display: flex;
justify-content: center;
font-style: italic;
margin-top: -10px;
margin-bottom: 20px;
}
\ No newline at end of file
...@@ -154,7 +154,7 @@ function showConfirmTransactionModal(div, form, montant, don, destinataire = nul ...@@ -154,7 +154,7 @@ function showConfirmTransactionModal(div, form, montant, don, destinataire = nul
}); });
} }
jQuery(document).ready(function() { $(function() {
// Get the ul that holds the collection of groupes // Get the ul that holds the collection of groupes
$collectionHolder = $('.groupeprestas'); $collectionHolder = $('.groupeprestas');
...@@ -466,12 +466,47 @@ jQuery(document).ready(function() { ...@@ -466,12 +466,47 @@ jQuery(document).ready(function() {
} }
}); });
$(".paiementDate").toggle($('#formSolidoumeItem_isRecurrent').is(':checked')) $(".paiementDate").toggle($('#formSolidoumeItem_isRecurrent').is(':checked'));
$('#formSolidoumeItem_amount').slider() $('#formSolidoumeItem_amount').slider();
$('#formSolidoumeItem_isRecurrent').click(function() { $('#formSolidoumeItem_isRecurrent').click(function() {
$(".paiementDate").toggle(this.checked); $(".paiementDate").toggle(this.checked);
}); });
if ($("form[name='formEncaissement']").length > 0) {
// Reset value on page loading (in case of second try)
$("#formEncaissement_payment_code").val('');
// Set payment summary on validation page
let paymentValidationSubheaderText = `${$("#formEncaissement_adherent option:selected").text()} - Montant : ${$("#formEncaissement_montant").val()}`;
$("#payment-validation-subheader").text(paymentValidationSubheaderText);
}
/**
* On cashing payment, validation code screen, add digit to input when corresponding button clicked.
*/
$(".payment-code-button").on("click", function() {
// Get existing input
let code = $("#formEncaissement_payment_code").val();
// Add button value
code += this.dataset.value;
$("#formEncaissement_payment_code").val(code);
// Visual payment code representation
$("#code-visual").text("*".repeat(code.length));
});
$(".payment-code-correction-button").on("click", function() {
// Get existing input
let code = $("#formEncaissement_payment_code").val();
// Remove last char of code
code = code.slice(0, -1);
$("#formEncaissement_payment_code").val(code);
$("#code-visual").text("*".repeat(code.length));
});
// $('.js-datepicker').datepicker({ // $('.js-datepicker').datepicker({
// closeText: 'Fermer', // closeText: 'Fermer',
// prevText: '<Préc', // prevText: '<Préc',
......
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -3,10 +3,10 @@ ...@@ -3,10 +3,10 @@
"app": { "app": {
"js": [ "js": [
"/build/runtime.6ad5c9da.js", "/build/runtime.6ad5c9da.js",
"/build/app.f88c3afa.js" "/build/app.07dbfd30.js"
], ],
"css": [ "css": [
"/build/app.f135e702.css" "/build/app.0815270c.css"
] ]
}, },
"admin": { "admin": {
......
{ {
"build/app.css": "/build/app.f135e702.css", "build/app.css": "/build/app.0815270c.css",
"build/app.js": "/build/app.f88c3afa.js", "build/app.js": "/build/app.07dbfd30.js",
"build/admin.css": "/build/admin.5dc0eea7.css", "build/admin.css": "/build/admin.5dc0eea7.css",
"build/admin.js": "/build/admin.8a6adf4b.js", "build/admin.js": "/build/admin.8a6adf4b.js",
"build/runtime.js": "/build/runtime.6ad5c9da.js", "build/runtime.js": "/build/runtime.6ad5c9da.js",
......
...@@ -39,6 +39,7 @@ use Symfony\Component\Security\Core\Security as Secur; ...@@ -39,6 +39,7 @@ use Symfony\Component\Security\Core\Security as Secur;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler;
use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken;
use Symfony\Component\Security\Core\Security;
class IndexController extends AbstractController class IndexController extends AbstractController
{ {
...@@ -51,9 +52,20 @@ class IndexController extends AbstractController ...@@ -51,9 +52,20 @@ class IndexController extends AbstractController
private $session; private $session;
private $tokenStorage; private $tokenStorage;
private $router; private $router;
private $security;
public function __construct(EventDispatcherInterface $eventDispatcher, EntityManagerInterface $em, UserManagerInterface $userManager, CsrfTokenManagerInterface $tokenManager = null, GuardAuthenticatorHandler $guard, SessionInterface $session, LoginAuthenticator $authenticator, TokenStorageInterface $tokenStorage, RouterInterface $router)
{ public function __construct(
EventDispatcherInterface $eventDispatcher,
EntityManagerInterface $em,
UserManagerInterface $userManager,
CsrfTokenManagerInterface $tokenManager = null,
GuardAuthenticatorHandler $guard,
SessionInterface $session,
LoginAuthenticator $authenticator,
TokenStorageInterface $tokenStorage,
RouterInterface $router,
Security $security
) {
$this->eventDispatcher = $eventDispatcher; $this->eventDispatcher = $eventDispatcher;
$this->em = $em; $this->em = $em;
$this->userManager = $userManager; $this->userManager = $userManager;
...@@ -63,7 +75,8 @@ class IndexController extends AbstractController ...@@ -63,7 +75,8 @@ class IndexController extends AbstractController
$this->session = $session; $this->session = $session;
$this->tokenStorage = $tokenStorage; $this->tokenStorage = $tokenStorage;
$this->router = $router; $this->router = $router;
} $this->security = $security;
}
/** /**
* @Route("/", name="index") * @Route("/", name="index")
...@@ -91,6 +104,18 @@ class IndexController extends AbstractController ...@@ -91,6 +104,18 @@ class IndexController extends AbstractController
$template = 'index_wordpress.html.twig'; $template = 'index_wordpress.html.twig';
} }
if (
isset($_GET["upswd"])
&& $_GET["upswd"] == "success"
&& $this->security->isGranted('ROLE_ADHERENT')
&& $this->getParameter('tav_env') == true
) {
$this->addFlash(
'warning',
'Suite à la modification de votre mot de passe, pensez à mettre à jour votre code de paiment pour pouvoir effectuer des achats.'
);
}
return $this->render('@kohinos/' . $template, [ return $this->render('@kohinos/' . $template, [
'news' => [], 'news' => [],
'last_username' => $lastUsername, 'last_username' => $lastUsername,
......
...@@ -19,7 +19,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; ...@@ -19,7 +19,6 @@ use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class UserAdherentController extends FluxController class UserAdherentController extends FluxController
{ {
...@@ -163,7 +162,7 @@ class UserAdherentController extends FluxController ...@@ -163,7 +162,7 @@ class UserAdherentController extends FluxController
* @Route("/adherent/set-payment-code", name="adherentSetPaymentCode") * @Route("/adherent/set-payment-code", name="adherentSetPaymentCode")
* @IsGranted("ROLE_ADHERENT") * @IsGranted("ROLE_ADHERENT")
*/ */
public function setPaymentCodeAction(Request $request, UserPasswordEncoderInterface $encoder) public function setPaymentCodeAction(Request $request)
{ {
$adherent = $this->getUser()->getAdherent(); $adherent = $this->getUser()->getAdherent();
$form = $this->createForm(SetPaymentCodeFormType::class, $adherent); $form = $this->createForm(SetPaymentCodeFormType::class, $adherent);
...@@ -174,7 +173,8 @@ class UserAdherentController extends FluxController ...@@ -174,7 +173,8 @@ class UserAdherentController extends FluxController
$plainCode = $data->getPaymentCode(); $plainCode = $data->getPaymentCode();
if (is_numeric($plainCode) && strlen($plainCode) >= 4 && strlen($plainCode) <= 8) { if (is_numeric($plainCode) && strlen($plainCode) >= 4 && strlen($plainCode) <= 8) {
$encoded = $encoder->encodePassword($this->getUser(), $plainCode); $encoded = crypt($plainCode, $this->getUser()->getSalt());
$adherent->setPaymentCode($encoded); $adherent->setPaymentCode($encoded);
$this->em->flush(); $this->em->flush();
......
...@@ -9,11 +9,14 @@ use App\Entity\GlobalParameter; ...@@ -9,11 +9,14 @@ use App\Entity\GlobalParameter;
use App\Entity\Payment; use App\Entity\Payment;
use App\Entity\Prestataire; use App\Entity\Prestataire;
use App\Entity\User; use App\Entity\User;
use App\Entity\TransactionAdherentPrestataire;
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;
use App\Form\Type\DonPrestataireFormType; use App\Form\Type\DonPrestataireFormType;
use App\Form\Type\UserInfosFormType; use App\Form\Type\UserInfosFormType;
use App\Form\Type\EncaissementFormType;
use App\Form\Type\EncaissementValidationFormType;
use App\Utils\CotisationUtils; use App\Utils\CotisationUtils;
use App\Utils\OperationUtils; use App\Utils\OperationUtils;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
...@@ -22,9 +25,11 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; ...@@ -22,9 +25,11 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Core\Security;
use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorInterface;
use Twig\Environment;
class UserController extends AbstractController class UserController extends AbstractController
{ {
...@@ -33,14 +38,28 @@ class UserController extends AbstractController ...@@ -33,14 +38,28 @@ class UserController extends AbstractController
private $security; private $security;
private $operationUtils; private $operationUtils;
private $cotisationUtils; private $cotisationUtils;
private $session;
private $mailer;
private $templating;
public function __construct(EntityManagerInterface $em, TranslatorInterface $translator, Security $security, OperationUtils $operationUtils, CotisationUtils $cotisationUtils) public function __construct(
{ EntityManagerInterface $em,
TranslatorInterface $translator,
Security $security,
OperationUtils $operationUtils,
CotisationUtils $cotisationUtils,
SessionInterface $session,
\Swift_Mailer $mailer,
Environment $templating
) {
$this->em = $em; $this->em = $em;
$this->translator = $translator; $this->translator = $translator;
$this->security = $security; $this->security = $security;
$this->operationUtils = $operationUtils; $this->operationUtils = $operationUtils;
$this->cotisationUtils = $cotisationUtils; $this->cotisationUtils = $cotisationUtils;
$this->session = $session;
$this->mailer = $mailer;
$this->templating = $templating;
} }
/** /**
...@@ -222,4 +241,119 @@ class UserController extends AbstractController ...@@ -222,4 +241,119 @@ class UserController extends AbstractController
return $this->redirectToRoute('index'); return $this->redirectToRoute('index');
} }
/**
* @Route("/encaissement", name="encaissement")
* @IsGranted({"ROLE_CAISSIER", "ROLE_PRESTATAIRE"})
*/
public function encaissementAction(Request $request)
{
$form = $this->createForm(EncaissementFormType::class, null, []);
$form->handleRequest($request);
$validation = false;
if ($form->isSubmitted()) {
$data = $form->getData();
if ($form->isValid()) {
$input_code = $data["payment_code"];
$validation = true; // As soon as the form is submitted & valid, we enter the validation process
if (empty($input_code)) {
// First step validated (set user & amount) -> go to validation
goto end;
}
$adherent = $data["adherent"];
$adherent_code = $adherent->getPaymentCode();
// if adherent doesn't have a validation code
if (is_null($adherent_code)) {
$this->addFlash(
'error',
$this->translator->trans('L\'habitant·e n\'a pas encore défini un code de validation de paiement sur son espace personnel, il·elle ne peut pas payer en Monnaie Solidaire pour l\'instant.')
);
goto end;
}
// Check validation code
// NOTE as we use password salt, must change payment code if password changes
$encoded_input = crypt($input_code, $adherent->getUser()->getSalt());
if (!hash_equals($adherent_code, $encoded_input)) {
$this->addFlash(
'error',
$this->translator->trans('Code incorrect')
);
goto end;
}
// Check adherent has enough funds
$balance = $adherent->getEmlcAccount()->getBalance();
$transaction_amount = floatval($data["montant"]);
if ($balance < $transaction_amount) {
// Send mail for insufficient funds
$subject = $this->translator->trans('[MONNAIE ALIMENTAIRE COMMUNE] – Solde insuffisant');
$mail = (new \Swift_Message($subject))
->setFrom($this->em->getRepository(GlobalParameter::class)->val(GlobalParameter::MLC_NOTIF_EMAIL))
->setTo($adherent->getUser()->getEmail())
->setBody(
$this->templating->render(
'@kohinos/email/tav/insufficient_funds.html.twig',
[
'subject' => $subject
]
),
'text/html'
);
$this->mailer->send($mail);
$this->addFlash(
'error',
$this->translator->trans('Solde de l\'habitant·e insuffisant')
);
return $this->redirectToRoute('index');
}
// Save transaction
$flux = new TransactionAdherentPrestataire();
$flux->setExpediteur($adherent);
$presta = $this->session->get('_prestagere');
$presta = $this->em->getRepository(Prestataire::class)->findOneById($presta->getId());
$flux->setDestinataire($presta);
$flux->setOperateur($this->security->getUser());
$flux->setMontant($transaction_amount);
$flux->setMoyen(MoyenEnum::MOYEN_EMLC);
$now = (new \Datetime('now'))->format('d/m/Y H:i:s');
$flux->setReference('Achat en Monnaie Solidaire du ' . $now);
$this->em->persist($flux);
$this->operationUtils->executeOperations($flux);
$this->em->flush();
$this->addFlash(
'success',
$this->translator->trans('Transaction réussie !')
);
return $this->redirectToRoute('index');
} else {
$this->addFlash(
'error',
$this->translator->trans('Problème avec l\'encaissement !') . ' ' . $form->getErrors()
);
}
}
end:
return $this->render('@kohinos/tav/encaissement_page.html.twig', [
'form' => $form->createView(),
'validation' => $validation
]);
}
} }
...@@ -56,7 +56,7 @@ class UserListener implements EventSubscriberInterface ...@@ -56,7 +56,7 @@ class UserListener implements EventSubscriberInterface
public function onChangePasswordSuccess(FormEvent $event) public function onChangePasswordSuccess(FormEvent $event)
{ {
$url = $this->router->generate('index'); $url = $this->router->generate('index') . '?upswd=success';
$event->setResponse(new RedirectResponse($url)); $event->setResponse(new RedirectResponse($url));
} }
......
<?php
namespace App\Form\Type;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use App\Entity\Adherent;
class EncaissementFormType extends AbstractType
{
protected $em;
protected $security;
public function __construct(
EntityManagerInterface $em,
Security $security
) {
$this->em = $em;
$this->security = $security;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('adherent', EntityType::class, [
'class' => Adherent::class,
'choices' => $this->em->getRepository(Adherent::class)->findOrderByName(),
'attr' => [
'class' => 'form-control select2',
],
'placeholder' => 'Choisissez un.e adhérent.e',
'required' => true,
'label' => 'Adherent :',
'choice_label' => 'name'
])
->add('montant', NumberType::class, [
'label' => 'Montant : ',
'required' => true,
'attr' => ['autocomplete' => 'off']
])
->add('payment_code', HiddenType::class, [
'label' => 'Code de validation de l\'habitant·e : ',
'required' => false,
'attr' => ['autocomplete' => 'off']
])
->add('save', SubmitType::class, ['label' => 'Valider'])
;
}
public function getBlockPrefix()
{
return 'formEncaissement';
}
}
...@@ -17,6 +17,7 @@ class SetPaymentCodeFormType extends AbstractType ...@@ -17,6 +17,7 @@ class SetPaymentCodeFormType extends AbstractType
->add('payment_code', PasswordType::class, [ ->add('payment_code', PasswordType::class, [
'label' => 'Saisir mon nouveau code (4 à 8 chiffres)', 'label' => 'Saisir mon nouveau code (4 à 8 chiffres)',
'required' => true, 'required' => true,
'attr' => ['autocomplete' => 'off']
]) ])
->add('save', SubmitType::class, ['label' => 'Valider']) ->add('save', SubmitType::class, ['label' => 'Valider'])
; ;
......
{% if tav_env == 1 %}
{% set esoldelabel = 'Solde e-mlc'|trans %}
{% include '@kohinos/block/solde.html.twig' with {'compte': getCurrentPrestataire().emlcAccount.balance, 'soldelabel': esoldelabel, 'currency' : 'e'~(KOH_MLC_SYMBOL|default(''))} %}
{% include '@kohinos/tav/block/encaisser_paiement.html.twig' %}
{% endif %}
{% include '@kohinos/block/transactions.html.twig' with {'title': 'Transactions'} %}
\ No newline at end of file
{% set esoldelabel = 'Solde e-mlc'|trans %} {% set esoldelabel = 'Solde e-mlc'|trans %}
{% include '@kohinos/block/solde.html.twig' with {'compte': getCurrentPrestataire().emlcAccount.balance, 'soldelabel': esoldelabel, 'currency' : 'e'~(KOH_MLC_SYMBOL|default(''))} %} {% include '@kohinos/block/solde.html.twig' with {'compte': getCurrentPrestataire().emlcAccount.balance, 'soldelabel': esoldelabel, 'currency' : 'e'~(KOH_MLC_SYMBOL|default(''))} %}
{% if tav_env == 1 %}
{% include '@kohinos/tav/block/encaisser_paiement.html.twig' %}
{% endif %}
{% if getCurrentPrestataire().mlc == false %} {% if getCurrentPrestataire().mlc == false %}
{% include '@kohinos/presta/block/infos.html.twig' %} {% include '@kohinos/presta/block/infos.html.twig' %}
{% endif %} {% endif %}
......
...@@ -49,7 +49,7 @@ ...@@ -49,7 +49,7 @@
{% elseif app.user and is_granted('ROLE_CAISSIER') and getCurrentPrestataire() != null %} {% elseif app.user and is_granted('ROLE_CAISSIER') and getCurrentPrestataire() != null %}
{% include '@kohinos/block/transactions.html.twig' with {'title': 'Transactions'} %} {% include '@kohinos/block/admin_caissier.html.twig' %}
{% elseif app.user and is_granted('ROLE_ADHERENT') and app.user.adherent %} {% elseif app.user and is_granted('ROLE_ADHERENT') and app.user.adherent %}
......
{% extends '@kohinos/email/email_layout.html.twig' %}
{% set title %}{% spaceless %}
{{ subject }}
{% endspaceless %}
{% endset %}
{% block content %}
<p>
{{ 'Cher-e Participant-e à la Caisse Alimentaire Commune,'|trans }}
</p>
<p>
{{ 'Nous avons enregistré une tentative de paiement en Monnaie Alimentaire Commune.'|trans }}
</p>
<p>
{{ 'L’opération n’a pas pu être validé car votre solde était insuffisant au moment de son exécution.'|trans }}
</p>
<p>
{{ 'Pour vérifier votre solde, rendez-vous dans la rubrique "Mon solde" sur le site internet de la Caisse Alimentaire Commune.'|trans }}
<br/>
{{ 'Pour toute question, nous vous invitons à vous rendre sur l’espace "Questions-Réponses".'|trans }}
</p>
<p>
{{ 'Nous restons bien entendu à votre écoute pour toute demande complémentaire.'|trans }}
</p>
<p>
{{ 'Cordialement,'|trans }}
<br/>
{{ 'La Caisse Alimentaire Commune.'|trans }}
</p>
{% endblock %}
\ No newline at end of file
{% extends '@kohinos/block/block_collapse.html.twig' %}
{% block blocktitle %}
<i class="fa fa-shopping-basket mr-4"></i> {{'Encaisser un paiement en Monnaie Solidaire'|trans }}
{% endblock blocktitle %}
{% block blockcontent %}
<a class='btn btn-xs btn-primary mt-2' href='{{ path('encaissement') }}'>
{{ 'Encaisser'|trans }}
</a>
{% endblock blockcontent %}
{% extends '@kohinos/common/layout.html.twig' %}
{% block content %}
<div class='container' style='max-width: 800px;'>
{% include '@kohinos/block/breadcrumb.html.twig' with {'label': 'Encaissement'} %}
{% if validation == true %}
<h2 class='text-center w-100 mt-4 mb-4'>{{ "Code de validation de l'habitant·e"|trans }}</h2>
<div id="payment-validation-subheader"></div>
{% else %}
<h2 class='text-center w-100 mt-4 mb-4'>{{ "Encaissement"|trans }}</h2>
{% endif %}
<div class='text-center mb-5'>
{{ form_start(form, {'attr': {'autocomplete': 'off'}}) }}
{% if validation == true %}
<div id="code-visual"></div>
<div id="code-digits-container">
<button type="button" class="payment-code-button" data-value="1">1</button>
<button type="button" class="payment-code-button" data-value="2">2</button>
<button type="button" class="payment-code-button" data-value="3">3</button>
<button type="button" class="payment-code-button" data-value="4">4</button>
<button type="button" class="payment-code-button" data-value="5">5</button>
<button type="button" class="payment-code-button" data-value="6">6</button>
<button type="button" class="payment-code-button" data-value="7">7</button>
<button type="button" class="payment-code-button" data-value="8">8</button>
<button type="button" class="payment-code-button" data-value="9">9</button>
<button type="button" class="payment-code-correction-button">
<i class="fa fa-backspace"></i>
</button>
<button type="button" class="payment-code-button" data-value="0">0</button>
<div class="payment-code-button-placeholder"></div>
</div>
<div style="display:none;">
{{ form_row(form.adherent) }}
{{ form_row(form.montant) }}
</div>
{% else %}
{{ form_row(form.adherent) }}
{{ form_row(form.montant) }}
{% endif %}
{{ form_end(form) }}
</div>
</div>
{% endblock %}
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