```
✨ feat(EsyWeb/Intranet): Ajoute et modifie les routes et gère les prix automatiques.
```
This commit is contained in:
32
migrations/Version20251017085407.php
Normal file
32
migrations/Version20251017085407.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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 Version20251017085407 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 customer_price (id SERIAL NOT NULL, type VARCHAR(255) NOT NULL, ammount DOUBLE PRECISION NOT NULL, description TEXT DEFAULT NULL, PRIMARY KEY(id))');
|
||||
}
|
||||
|
||||
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('DROP TABLE customer_price');
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ use Vich\UploaderBundle\Templating\Helper\UploaderHelper;
|
||||
|
||||
class EsyWebController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/artemis/esyweb', name: 'artemis_esyweb', methods: ['GET', 'POST'])]
|
||||
#[Route(path: '/artemis/esyweb/website', name: 'artemis_esyweb', methods: ['GET', 'POST'])]
|
||||
public function websites(LoggerService $loggerService,Request $request,EntityManagerInterface $entityManager,WebsiteRepository $websiteRepository)
|
||||
{
|
||||
$loggerService->log("VIEW","Affiche la page de site internet",$this->getUser());
|
||||
@@ -37,7 +37,7 @@ class EsyWebController extends AbstractController
|
||||
'websites' => $websiteRepository->findAll(),
|
||||
]);
|
||||
}
|
||||
#[Route(path: '/artemis/esyweb/{id}', name: 'artemis_esyweb_view', methods: ['GET', 'POST'])]
|
||||
#[Route(path: '/artemis/esyweb/website/{id}', name: 'artemis_esyweb_view', methods: ['GET', 'POST'])]
|
||||
public function websiteView(?Website $website,LoggerService $loggerService,Request $request,EntityManagerInterface $entityManager,WebsiteRepository $websiteRepository)
|
||||
{
|
||||
if(is_null($website)) {
|
||||
@@ -50,7 +50,7 @@ class EsyWebController extends AbstractController
|
||||
'website' => $website
|
||||
]);
|
||||
}
|
||||
#[Route(path: '/artemis/esyweb/add', name: 'artemis_esyweb_add', methods: ['GET', 'POST'])]
|
||||
#[Route(path: '/artemis/esyweb/website/add', name: 'artemis_esyweb_add', methods: ['GET', 'POST'])]
|
||||
public function websiteAdd(LoggerService $loggerService,Request $request,EntityManagerInterface $entityManager,EventDispatcherInterface $eventDispatcher)
|
||||
{
|
||||
$loggerService->log("VIEW","Affiche la page de création de site internet",$this->getUser());
|
||||
|
||||
103
src/Controller/Artemis/Intranet/PriceController.php
Normal file
103
src/Controller/Artemis/Intranet/PriceController.php
Normal file
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Artemis\Intranet;
|
||||
|
||||
use App\Service\Echeance\EventEcheanceCreated;
|
||||
use App\Service\Pdf\EmailListPdf;
|
||||
use App\Service\Pdf\PaymentPdf;
|
||||
use App\Entity\{Account,
|
||||
Customer,
|
||||
CustomerAdvertPayment,
|
||||
CustomerAdvertPaymentLine,
|
||||
CustomerContact,
|
||||
CustomerDevis,
|
||||
CustomerDevisLine,
|
||||
CustomerDns,
|
||||
CustomerDnsEmail,
|
||||
CustomerOrder,
|
||||
CustomerOrderLine,
|
||||
CustomerPrice,
|
||||
CustomerSplit,
|
||||
CustomerSplitLine,
|
||||
OrderNumberCurrent};
|
||||
use App\Form\Artemis\Intranet\{CustomerDnsEmailType, CustomerEditType, CustomerNddType, CustomerType, PriceType};
|
||||
use App\Repository\{CustomerDnsRepository,
|
||||
CustomerOrderRepository,
|
||||
CustomerPriceRepository,
|
||||
CustomerRepository,
|
||||
OrderNumberCurrentRepository,
|
||||
OrderNumberDispoRepository};
|
||||
use App\Security\PasswordGenerator;
|
||||
use App\Service\Customer\Billing\{
|
||||
CreateAvisEventSend,
|
||||
CreateDevisCustomerEvent,
|
||||
CreateDevisCustomerEventSend,
|
||||
CreateFactureEventSend
|
||||
};
|
||||
use App\Service\Customer\{CreateAvisEvent,
|
||||
CreateCustomerNddEmailEvent,
|
||||
CreateFactureEvent,
|
||||
CustomerSendPasswordEmail,
|
||||
DeleteCustomerEvent,
|
||||
EventSpaceCustomerCreated,
|
||||
PdfList\SendPdfEmailListEvent,
|
||||
RestoreCustomerEvent};
|
||||
use App\Service\Logger\LoggerService;
|
||||
use App\Service\Ovh\Client;
|
||||
use App\Service\Vault\VaultClient;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Exbil\MailCowAPI;
|
||||
use Knp\Component\Pager\PaginatorInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormFactoryInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\KernelInterface;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Uid\Uuid;
|
||||
|
||||
class PriceController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/artemis/customer/price', name: 'artemis_intranet_price', methods: ['GET', 'POST'])]
|
||||
public function customerPrice(
|
||||
LoggerService $loggerService,
|
||||
CustomerPriceRepository $customerPriceRepository,
|
||||
EntityManagerInterface $entityManager,
|
||||
Request $request,
|
||||
FormFactoryInterface $formFactory,
|
||||
)
|
||||
{
|
||||
$loggerService->log("VIEW","Affichage price automatique",$this->getUser());
|
||||
|
||||
$pricesList = [
|
||||
'price_ndd',
|
||||
'price_hosting',
|
||||
'price_email'
|
||||
];
|
||||
foreach ($pricesList as $price) {
|
||||
$ptc = $customerPriceRepository->findOneBy(['type' => $price]);
|
||||
if(!$ptc instanceof CustomerPrice) {
|
||||
$ptc = new CustomerPrice();
|
||||
$ptc->setType($price);
|
||||
$ptc->setAmmount(0);
|
||||
$ptc->setDescription("");
|
||||
$entityManager->persist($ptc);
|
||||
$entityManager->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$forms = [];
|
||||
foreach ($customerPriceRepository->findAll() as $price) {
|
||||
$fc = $formFactory->createNamed('price_'.$price->getId(),PriceType::class,$price);
|
||||
$fc->handleRequest($request);
|
||||
$forms[$price->getType()] = $fc->createView();
|
||||
}
|
||||
|
||||
|
||||
return $this->render('artemis/intranet/price.twig', [
|
||||
'ptcs' => $forms
|
||||
]);
|
||||
}
|
||||
}
|
||||
65
src/Entity/CustomerPrice.php
Normal file
65
src/Entity/CustomerPrice.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\CustomerPriceRepository;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
#[ORM\Entity(repositoryClass: CustomerPriceRepository::class)]
|
||||
class CustomerPrice
|
||||
{
|
||||
#[ORM\Id]
|
||||
#[ORM\GeneratedValue]
|
||||
#[ORM\Column]
|
||||
private ?int $id = null;
|
||||
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $type = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?float $ammount = null;
|
||||
|
||||
#[ORM\Column(type: 'text', nullable: true)]
|
||||
private ?string $description = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function setType(string $type): static
|
||||
{
|
||||
$this->type = $type;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getAmmount(): ?float
|
||||
{
|
||||
return $this->ammount;
|
||||
}
|
||||
|
||||
public function setAmmount(float $ammount): static
|
||||
{
|
||||
$this->ammount = $ammount;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription(?string $description): static
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
32
src/Form/Artemis/Intranet/PriceType.php
Normal file
32
src/Form/Artemis/Intranet/PriceType.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form\Artemis\Intranet;
|
||||
|
||||
use App\Entity\CustomerPrice;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class PriceType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('ammount',TextType::class,[
|
||||
'label' => 'Prix',
|
||||
'required' => true,
|
||||
])
|
||||
->add('description',TextareaType::class,[
|
||||
'label' => 'Description',
|
||||
'required' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefault('data_class',CustomerPrice::class);
|
||||
}
|
||||
}
|
||||
43
src/Repository/CustomerPriceRepository.php
Normal file
43
src/Repository/CustomerPriceRepository.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\CustomerPrice;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @extends ServiceEntityRepository<CustomerPrice>
|
||||
*/
|
||||
class CustomerPriceRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, CustomerPrice::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return CustomerPrice[] Returns an array of CustomerPrice objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('c')
|
||||
// ->andWhere('c.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('c.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?CustomerPrice
|
||||
// {
|
||||
// return $this->createQueryBuilder('c')
|
||||
// ->andWhere('c.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
@@ -127,7 +127,11 @@
|
||||
<span class="ml-3">Client(s)</span>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="{{ path('artemis_intranet_price') }}" class="flex items-center p-2 text-base font-normal text-gray-900 dark:text-white {% if app.request.get('_route') == 'artemis_intranet_price' %}bg-gray-200 dark:bg-gray-700{% endif %} rounded-lg">
|
||||
<span class="ml-3">Prix automatique</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="px-4 py-2">
|
||||
|
||||
54
templates/artemis/intranet/price.twig
Normal file
54
templates/artemis/intranet/price.twig
Normal file
@@ -0,0 +1,54 @@
|
||||
{% extends 'artemis/base.twig' %}
|
||||
|
||||
{% block content %}
|
||||
{# Conteneur principal en mode sombre #}
|
||||
<div class="bg-gray-900 min-h-screen text-gray-100 p-4 sm:p-6 lg:p-8">
|
||||
<div class="container mx-auto">
|
||||
{# Titre en couleur claire #}
|
||||
<h1 class="text-3xl font-bold mb-6 text-white">Prix automatique</h1>
|
||||
|
||||
{# Le conteneur principal pour les formulaires #}
|
||||
<div class="space-y-6">
|
||||
{% for key,form in ptcs %}
|
||||
{# Conteneur pour chaque formulaire : une carte plus claire sur fond sombre #}
|
||||
<div class="bg-gray-800 p-6 rounded-lg shadow-xl border border-gray-700 transition duration-300 hover:shadow-2xl">
|
||||
<h2 class="text-2xl font-bold mb-6 text-white">{{ key|trans }}</h2>
|
||||
|
||||
{{ form_start(form, {'attr': {'class': 'space-y-4'}}) }}
|
||||
|
||||
{# Style pour le champ 'ammount' #}
|
||||
<div class="mb-4">
|
||||
{# Label en blanc #}
|
||||
<label for="{{ form.ammount.vars.id }}" class="block text-sm font-medium text-gray-200">Montant</label>
|
||||
{# Champ de formulaire adapté au mode sombre (fond sombre, texte blanc) #}
|
||||
{{ form_widget(form.ammount, {'attr': {'class': 'mt-1 block w-full px-3 py-2 border border-gray-700 bg-gray-900 text-white rounded-md shadow-sm placeholder-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}}) }}
|
||||
{{ form_errors(form.ammount) }}
|
||||
</div>
|
||||
|
||||
{# Style pour le champ 'description' #}
|
||||
<div class="mb-4">
|
||||
{# Label en blanc #}
|
||||
<label for="{{ form.description.vars.id }}" class="block text-sm font-medium text-gray-200">Description</label>
|
||||
{# Champ de formulaire adapté au mode sombre (fond sombre, texte blanc) #}
|
||||
{{ form_widget(form.description, {'attr': {'class': 'mt-1 block w-full px-3 py-2 border border-gray-700 bg-gray-900 text-white rounded-md shadow-sm placeholder-gray-500 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm'}}) }}
|
||||
{{ form_errors(form.description) }}
|
||||
</div>
|
||||
|
||||
{# Style pour le bouton d'envoi (inchangé car les couleurs Indigo fonctionnent bien en mode sombre) #}
|
||||
<div class="text-right">
|
||||
<button type="submit" class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 focus:ring-offset-gray-800">
|
||||
Enregistrer
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}
|
||||
Prix automatique
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user