✨ feat(paiement): Ajoute l'interface de paiement Stancer et la gestion du statut.
This commit is contained in:
@@ -14,3 +14,5 @@ header {
|
||||
.opblock-section-header{
|
||||
background: #f8adf8 !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import './app.scss'
|
||||
import * as Turbo from "@hotwired/turbo"
|
||||
import {PaymentPage} from "./class/PaymentPage.js";
|
||||
|
||||
customElements.define('payment-page',PaymentPage,{extends:'button'})
|
||||
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
@@ -36,3 +36,37 @@ input {
|
||||
height: 20px;
|
||||
color: #6b7280; /* Tailwind gray-500 */
|
||||
}
|
||||
|
||||
|
||||
.banke{
|
||||
background: red;
|
||||
padding: 0.5rem;
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
display: none;
|
||||
&.show{
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.modal-payment{
|
||||
background: rgba(0,0,0,0.5);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backdrop-filter: blur(5px);
|
||||
.iframe-container {
|
||||
background: var(--color-gray-800);
|
||||
width: 50%;
|
||||
height: 90%;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
assets/class/PaymentPage.js
Normal file
47
assets/class/PaymentPage.js
Normal file
@@ -0,0 +1,47 @@
|
||||
export class PaymentPage extends HTMLButtonElement{
|
||||
connectedCallback(){
|
||||
let element = this;
|
||||
element.addEventListener('click', function(){
|
||||
let banke = document.querySelector('.banke');
|
||||
banke.classList.remove('show');
|
||||
let displayModal = document.createElement('div');
|
||||
displayModal.classList.add('modal-payment');
|
||||
|
||||
let iframeContainer = document.createElement('div');
|
||||
iframeContainer.classList.add('iframe-container');
|
||||
|
||||
window.addEventListener('message', function (event) {
|
||||
if (event.origin !== 'https://payment.stancer.com') {
|
||||
return;
|
||||
}
|
||||
if(event.data.status != undefined) {
|
||||
if(event.data.status != "init" && event.data.status != "pending" && event.data.status != "secure-auth-start" && event.data.status != "secure-auth-end") {
|
||||
if (event.data.status == "paid") {
|
||||
displayModal.remove();
|
||||
location.href = "/paiement/complete?id=" + element.getAttribute('id');
|
||||
} else if (event.data.status == "finished") {
|
||||
displayModal.remove();
|
||||
location.href = event.data.url;
|
||||
} else {
|
||||
fetch("/api-interne/intranet/customer/payment/cancel?id="+element.getAttribute('id'))
|
||||
displayModal.remove();
|
||||
banke.classList.add('show');
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(event.data);
|
||||
});
|
||||
fetch("/api-interne/intranet/customer/payment?id="+element.getAttribute('id'))
|
||||
.then(r=>r.json())
|
||||
.then(r=>{
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.src = r.url;
|
||||
iframeContainer.appendChild(iframe);
|
||||
|
||||
window.frame = iframeContainer;
|
||||
})
|
||||
displayModal.appendChild(iframeContainer);
|
||||
document.body.appendChild(displayModal);
|
||||
})
|
||||
}
|
||||
}
|
||||
36
migrations/Version20250730123638.php
Normal file
36
migrations/Version20250730123638.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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 Version20250730123638 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('ALTER TABLE customer_advert_payment ADD card TEXT DEFAULT NULL');
|
||||
$this->addSql('ALTER TABLE customer_advert_payment ADD pay_at TIMESTAMP(0) WITHOUT TIME ZONE DEFAULT NULL');
|
||||
$this->addSql('COMMENT ON COLUMN customer_advert_payment.card IS \'(DC2Type:array)\'');
|
||||
$this->addSql('COMMENT ON COLUMN customer_advert_payment.pay_at IS \'(DC2Type:datetime_immutable)\'');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->addSql('CREATE SCHEMA public');
|
||||
$this->addSql('ALTER TABLE customer_advert_payment DROP card');
|
||||
$this->addSql('ALTER TABLE customer_advert_payment DROP pay_at');
|
||||
}
|
||||
}
|
||||
@@ -3,15 +3,88 @@
|
||||
namespace App\Controller\ApiInterne\Intranet;
|
||||
|
||||
|
||||
use App\Entity\CustomerAdvertPayment;
|
||||
use App\Repository\CustomerAdvertPaymentRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use LuFiipe\InseeSierene\Sirene;
|
||||
use Stancer\Config;
|
||||
use Stancer\Customer;
|
||||
use Stancer\Payment;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
|
||||
class CustomerController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/api-interne/intranet/customer/payment/cancel',name: 'api-interne-intranet-customer-payment-cancel')]
|
||||
public function customerPaymentCancel(EntityManagerInterface $entityManager,Request $request,CustomerAdvertPaymentRepository $customerAdvertPayment): Response
|
||||
{
|
||||
if(!$request->query->has('id'))
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
$advert = $customerAdvertPayment->find($request->query->get('id'));
|
||||
if(!$advert instanceof CustomerAdvertPayment)
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
if($advert->getState() == "pay")
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
$advert->setPaymentId(null);
|
||||
|
||||
$entityManager->persist($advert);
|
||||
$entityManager->flush();
|
||||
|
||||
return $this->json([]);
|
||||
}
|
||||
#[Route(path: '/api-interne/intranet/customer/payment/',name: 'api-interne-intranet-customer-payment')]
|
||||
public function customerPayment(EntityManagerInterface $entityManager,Request $request,CustomerAdvertPaymentRepository $customerAdvertPayment): Response
|
||||
{
|
||||
if(!$request->query->has('id'))
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
$advert = $customerAdvertPayment->find($request->query->get('id'));
|
||||
if(!$advert instanceof CustomerAdvertPayment)
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
if($advert->getState() == "pay")
|
||||
return $this->json([],Response::HTTP_FORBIDDEN);
|
||||
|
||||
$payEdit = str_replace('"',"",$advert->getPaymentId());
|
||||
|
||||
$client = Config::init([$_ENV['STANCER_PUBLIC_KEY'], $_ENV['STANCER_PRIVATE_KEY']]);
|
||||
$client->setMode($_ENV['STANCER_ENV']);
|
||||
if($advert->getPaymentId() != null) {
|
||||
$payment = new Payment($payEdit);
|
||||
return $this->json([
|
||||
'url' => $payment->getPaymentPageUrl(),
|
||||
]);
|
||||
} else {
|
||||
|
||||
$total = 0;
|
||||
foreach ($advert->getCustomerAdvertPaymentLines() as $item) {
|
||||
$total = $total + (floatval($item->getPriceHt()) * 1.20);
|
||||
}
|
||||
$paymentReturnPath = $this->generateUrl("app_payment_complete", ['id'=>$advert->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$paymentReturnPath = str_replace("http://", "https://", $paymentReturnPath);
|
||||
$customerStancer = new Customer($advert->getCustomer()->getStancerId());
|
||||
$payment = new Payment();
|
||||
$payment->setAmount($total * 100);
|
||||
$payment->setCurrency("EUR");
|
||||
$payment->setDescription("Paiement de l'avis de paiement - " . $advert->getNumAvis());
|
||||
$payment->setCustomer($customerStancer);
|
||||
$payment->setReturnUrl($paymentReturnPath);
|
||||
$payment->setOrderId($advert->getNumAvis());
|
||||
$payment->setMethodsAllowed(["card"]);
|
||||
$payment->setCapture(true);
|
||||
$paimentId = $payment->send();
|
||||
$advert->setPaymentId($paimentId);
|
||||
$entityManager->persist($advert);
|
||||
$entityManager->flush();
|
||||
}
|
||||
return $this->json([
|
||||
'url' => $payment->getPaymentPageUrl(),
|
||||
]);
|
||||
|
||||
}
|
||||
#[Route(path: '/api-interne/intranet/customer/auto/{siret}',name: 'api-interne-intranet-customer-auto')]
|
||||
public function customerAuto(?string $siret): Response
|
||||
{
|
||||
|
||||
@@ -3,8 +3,12 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\CustomerAdvertPayment;
|
||||
use App\Entity\CustomerAdvertPaymentLine;
|
||||
use App\Repository\CustomerAdvertPaymentRepository;
|
||||
use App\Service\Mailer\Mailer;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Stancer\Config;
|
||||
use Stancer\Customer;
|
||||
use Stancer\Payment;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -13,14 +17,57 @@ use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\Mime\Part\DataPart;
|
||||
use Symfony\Component\Mime\Part\File;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
|
||||
|
||||
class PaymentController extends AbstractController
|
||||
{
|
||||
|
||||
#[Route(path: '/paiement/complete',name: 'app_payment_complete')]
|
||||
public function paymentComplete(EntityManagerInterface $entityManager,Mailer $mailer,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
|
||||
{
|
||||
if(!$request->query->has('id'))
|
||||
return $this->render('admin/payement_invalid.twig',[
|
||||
'message' => 'Avis de paiement n\'a été trouver'
|
||||
]);
|
||||
$advert = $customerAdvertPaymentRepository->find($request->query->get('id'));
|
||||
if(!$advert instanceof CustomerAdvertPayment)
|
||||
return $this->render('admin/payement_invalid.twig',[
|
||||
'message' => 'Avis de paiement n\'a été trouver'
|
||||
]);
|
||||
|
||||
|
||||
if($advert->getState() == "pay") {
|
||||
$client = Config::init([$_ENV['STANCER_PUBLIC_KEY'], $_ENV['STANCER_PRIVATE_KEY']]);
|
||||
$client->setMode($_ENV['STANCER_ENV']);
|
||||
$payEdit = str_replace('"', "", $advert->getPaymentId());
|
||||
$payment = new Payment($payEdit);
|
||||
if ($payment->isSuccess()) {
|
||||
$cardInfo = [
|
||||
'brand' => $payment->card->brand,
|
||||
'brandName' => $payment->card->brandName,
|
||||
'exp_year' => $payment->card->exp_year,
|
||||
'exp_month' => $payment->card->exp_month,
|
||||
'last4' => $payment->card->last4,
|
||||
'country' => $payment->card->country,
|
||||
];
|
||||
$advert->setState("pay");
|
||||
$advert->setCard($cardInfo);
|
||||
$advert->setPayAt(new \DateTimeImmutable());
|
||||
$entityManager->persist($advert);
|
||||
$entityManager->flush();
|
||||
dd('email customer');
|
||||
dd('email siteconseil');
|
||||
}
|
||||
}
|
||||
return $this->render('admin/payement_complete.twig',[
|
||||
'advert' => $advert,
|
||||
]);
|
||||
}
|
||||
#[Route(path: '/paiement',name: 'app_payment')]
|
||||
public function signComplete(Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
|
||||
public function payment(EntityManagerInterface $entityManager,Request $request,CustomerAdvertPaymentRepository $customerAdvertPaymentRepository): Response
|
||||
{
|
||||
if(!$request->query->has('id'))
|
||||
return $this->render('admin/payement_invalid.twig',[
|
||||
@@ -53,10 +100,34 @@ class PaymentController extends AbstractController
|
||||
'number' =>$advert->getNumAvis(),
|
||||
'amount' => $amount,
|
||||
'amountHt' => $amountHt,
|
||||
'payment' =>$payment->getPaymentPageUrl(),
|
||||
];
|
||||
/* if($request->query->has('act') && $request->query->get('act') == 'createPaiment'){
|
||||
|
||||
$total = 0;
|
||||
foreach ($advert->getCustomerAdvertPaymentLines() as $item) {
|
||||
$total = $total + (floatval($item->getPriceHt()) * 1.20);
|
||||
}
|
||||
$paymentReturnPath = $this->generateUrl("app_payment_complete", ['id'=>$advert->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$paymentReturnPath = str_replace("http://", "https://", $paymentReturnPath);
|
||||
$customerStancer = new Customer($advert->getCustomer()->getStancerId());
|
||||
$payment = new Payment();
|
||||
$payment->setAmount($total * 100);
|
||||
$payment->setCurrency("EUR");
|
||||
$payment->setDescription("Paiement de l'avis de paiement - " . $advert->getNumAvis());
|
||||
$payment->setCustomer($customerStancer);
|
||||
$payment->setReturnUrl($paymentReturnPath);
|
||||
$payment->setOrderId($advert->getNumAvis());
|
||||
$payment->setMethodsAllowed(["card"]);
|
||||
$payment->setCapture(true);
|
||||
$paimentId = $payment->send();
|
||||
$advert->setPaymentId($paimentId);
|
||||
$entityManager->persist($advert);
|
||||
$entityManager->flush();
|
||||
return $this->redirect($payment->getPaymentPageUrl());
|
||||
}*/
|
||||
return $this->render('admin/payement_interface.twig',[
|
||||
'paymentNotice' => $paymentNotice
|
||||
'paymentNotice' => $paymentNotice,
|
||||
'advert' => $advert
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Entity;
|
||||
use App\Repository\CustomerAdvertPaymentRepository;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Vich\UploaderBundle\Mapping\Annotation as Vich;
|
||||
@@ -60,6 +61,12 @@ class CustomerAdvertPayment
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $updateAt;
|
||||
|
||||
#[ORM\Column(type: Types::ARRAY,nullable: true)]
|
||||
private array $card = [];
|
||||
|
||||
#[ORM\Column(nullable: true)]
|
||||
private ?\DateTimeImmutable $payAt = null;
|
||||
public function __construct()
|
||||
{
|
||||
$this->customerAdvertPaymentLines = new ArrayCollection();
|
||||
@@ -308,4 +315,28 @@ class CustomerAdvertPayment
|
||||
{
|
||||
$this->fileOriginalName = $fileOriginalName;
|
||||
}
|
||||
|
||||
public function getCard(): array
|
||||
{
|
||||
return $this->card;
|
||||
}
|
||||
|
||||
public function setCard(array $card): static
|
||||
{
|
||||
$this->card = $card;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPayAt(): ?\DateTimeImmutable
|
||||
{
|
||||
return $this->payAt;
|
||||
}
|
||||
|
||||
public function setPayAt(\DateTimeImmutable $payAt): static
|
||||
{
|
||||
$this->payAt = $payAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ class BillingEventSusbriber
|
||||
$this->entityManager->flush();
|
||||
|
||||
if($createAvis->getPaymentId() == null) {
|
||||
$paymentReturnPath = $this->urlGenerator->generate("app_login", [], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$paymentReturnPath = $this->urlGenerator->generate("app_payment_complete", ['id'=>$createAvis->getId()], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$paymentReturnPath = str_replace("http://", "https://", $paymentReturnPath);
|
||||
|
||||
$total = 0;
|
||||
@@ -78,8 +78,8 @@ class BillingEventSusbriber
|
||||
foreach ($createAvis->getCustomerAdvertPaymentLines() as $item) {
|
||||
$total = $total + (floatval($item->getPriceHt()) * 1.20);
|
||||
}
|
||||
$customerStancer = new Customer($customerId);
|
||||
//creeat payement link
|
||||
//$customerStancer = new Customer($customerId);
|
||||
/*//creeat payement link
|
||||
$payment = new Payment();
|
||||
$payment->setAmount($total * 100);
|
||||
$payment->setCurrency("EUR");
|
||||
@@ -92,7 +92,7 @@ class BillingEventSusbriber
|
||||
$paimentId = $data = $payment->send();
|
||||
$createAvis->setPaymentId($paimentId);
|
||||
$this->entityManager->persist($createAvis);
|
||||
$this->entityManager->flush();
|
||||
$this->entityManager->flush();*/
|
||||
}
|
||||
|
||||
$pdf = New PaymentPdf($this->kernel,$createAvis,$this->urlGenerator->generate('app_payment',[
|
||||
|
||||
27
templates/admin/payement_complete.twig
Normal file
27
templates/admin/payement_complete.twig
Normal file
@@ -0,0 +1,27 @@
|
||||
{% extends 'admin/base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="min-h-screen flex items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-md w-full space-y-8 p-10 rounded-xl shadow-lg bg-gray-700">
|
||||
<div class="text-center">
|
||||
<!-- Icône de succès (SVG ou Emoji) -->
|
||||
<svg class="mx-auto h-24 w-24 text-green-500" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
||||
</svg>
|
||||
<h2 class="mt-6 text-3xl font-extrabold text-white">
|
||||
Paiement effectué avec succès !
|
||||
</h2>
|
||||
<p class="mt-2 text-sm text-white">
|
||||
Merci pour votre paiement. Votre transaction a été traitée avec succès.
|
||||
</p>
|
||||
<p class="mt-2 text-sm text-white-600">
|
||||
Une fois le paiement vérifiée de notre coté, une facture vous sera envoyée
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
Paiement réussi !
|
||||
{% endblock %}
|
||||
@@ -4,6 +4,8 @@
|
||||
<div class="container mx-auto p-6 bg-gray-800 shadow-md rounded-lg">
|
||||
<h2 class="text-2xl font-bold mb-6 text-white">Détails de votre avis de paiement</h2>
|
||||
|
||||
<span class=" bg-red-900 banke text-white">Votre paiement à été refusée par votre banque</span>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-6">
|
||||
<div class="bg-gray-500 p-4 rounded-md">
|
||||
<p class="text-sm font-medium text-white-600">Client</p>
|
||||
@@ -24,12 +26,12 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col sm:flex-row space-y-4 sm:space-y-0 sm:space-x-4">
|
||||
<a href="" class="w-full sm:w-auto bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md text-center transition duration-300 ease-in-out">
|
||||
<a target="_blank" href="{{ vich_uploader_asset(advert,'file') }}" class="w-full sm:w-auto bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-md text-center transition duration-300 ease-in-out">
|
||||
Voir l'avis de paiement
|
||||
</a>
|
||||
<a href="{{ paymentNotice.payment }}" class="w-full sm:w-auto bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-md text-center transition duration-300 ease-in-out">
|
||||
<button is="payment-page" id="{{ advert.id }}" class="w-full sm:w-auto bg-green-600 hover:bg-green-700 text-white font-bold py-2 px-4 rounded-md text-center transition duration-300 ease-in-out">
|
||||
Payer
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<td class="px-6 py-4">{{ orderAdvert.numAvis }}</td>
|
||||
<td class="px-6 py-4">{{ orderAdvert.createAt|date('d/m/Y H:i') }}</td>
|
||||
<td class="px-6 py-4">{{ (orderAdvert|totalOrder)|format_currency('EUR') }}</td>
|
||||
<td class="px-6 py-4 {% if orderAdvert.state == "accepted"%} text-green-400 {% elseif orderAdvert.state == "cancel"%} text-red-400{% else %}text-orange-400{% endif %}">{{ orderAdvert.state|trans }} </td>
|
||||
<td class="px-6 py-4 {% if orderAdvert.state == "pay"%} text-green-400 {% else %}text-orange-400{% endif %}">{{ orderAdvert.state|trans }} </td>
|
||||
<td class="px-6 py-4 text-center">
|
||||
{% if orderAdvert.state == "created" %}
|
||||
<a href="{{ path('artemis_intranet_customer_view',{id:customer.id,currentOrder:'a',current:'order',idAvis:orderAdvert.id,act:'send'}) }}" class="block bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded">Envoyée l'avis de paiement</a>
|
||||
|
||||
@@ -14,3 +14,4 @@ send: Envoyée - Attends de signature
|
||||
send_avis: Envoyée - Attends de paiement
|
||||
accepted: Accéptée
|
||||
cancel: Annulée
|
||||
pay: Payée
|
||||
|
||||
Reference in New Issue
Block a user