système de réduction pour l'app en fonction des clients, correcion de la base, maintenant les reductions sont appliquer automatiquement sur le client en fonction du montant dépenser, ajout d'un système de verif pour changer en fonction des modif, les reductions sont automatiquement changer ou crée en fonction des dépenses du client donc j'ai enlever le edit et new pcq on en a plus besoin encore 2 3 truc a régler mais le plus gros est fait, FAUT UPDATE LA BASE AVEC LES MIGRATIONS EN COURS SINON CA MARCHERA PAS

This commit is contained in:
joshua 2025-04-06 17:11:21 +02:00
parent e7206e3c8c
commit 01f23682b3
11 changed files with 253 additions and 185 deletions

View File

@ -39,7 +39,7 @@
"symfony/string": "7.1.*", "symfony/string": "7.1.*",
"symfony/translation": "7.1.*", "symfony/translation": "7.1.*",
"symfony/twig-bundle": "7.1.*", "symfony/twig-bundle": "7.1.*",
"symfony/ux-icons": "^2.21", "symfony/ux-icons": "^2.24",
"symfony/ux-turbo": "^2.20", "symfony/ux-turbo": "^2.20",
"symfony/validator": "7.1.*", "symfony/validator": "7.1.*",
"symfony/web-link": "7.1.*", "symfony/web-link": "7.1.*",

24
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "7fff997f78db4185bb53c4543a245c74", "content-hash": "d1751dd70a356412dfadda645c7118ec",
"packages": [ "packages": [
{ {
"name": "amphp/amp", "name": "amphp/amp",
@ -8164,16 +8164,16 @@
}, },
{ {
"name": "symfony/ux-icons", "name": "symfony/ux-icons",
"version": "v2.21.0", "version": "v2.24.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/ux-icons.git", "url": "https://github.com/symfony/ux-icons.git",
"reference": "c3b3fd29b3f90e977b267251ef15ea06f3cec553" "reference": "39f689b41081f7788ee9c4a188817599d546bfb2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/ux-icons/zipball/c3b3fd29b3f90e977b267251ef15ea06f3cec553", "url": "https://api.github.com/repos/symfony/ux-icons/zipball/39f689b41081f7788ee9c4a188817599d546bfb2",
"reference": "c3b3fd29b3f90e977b267251ef15ea06f3cec553", "reference": "39f689b41081f7788ee9c4a188817599d546bfb2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -8197,8 +8197,8 @@
"type": "symfony-bundle", "type": "symfony-bundle",
"extra": { "extra": {
"thanks": { "thanks": {
"name": "symfony/ux", "url": "https://github.com/symfony/ux",
"url": "https://github.com/symfony/ux" "name": "symfony/ux"
} }
}, },
"autoload": { "autoload": {
@ -8233,7 +8233,7 @@
"twig" "twig"
], ],
"support": { "support": {
"source": "https://github.com/symfony/ux-icons/tree/v2.21.0" "source": "https://github.com/symfony/ux-icons/tree/v2.24.0"
}, },
"funding": [ "funding": [
{ {
@ -8249,7 +8249,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-10-21T19:01:22+00:00" "time": "2025-04-04T17:32:18+00:00"
}, },
{ {
"name": "symfony/ux-turbo", "name": "symfony/ux-turbo",
@ -11242,7 +11242,7 @@
], ],
"aliases": [], "aliases": [],
"minimum-stability": "stable", "minimum-stability": "stable",
"stability-flags": [], "stability-flags": {},
"prefer-stable": true, "prefer-stable": true,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
@ -11250,6 +11250,6 @@
"ext-ctype": "*", "ext-ctype": "*",
"ext-iconv": "*" "ext-iconv": "*"
}, },
"platform-dev": [], "platform-dev": {},
"plugin-api-version": "2.3.0" "plugin-api-version": "2.6.0"
} }

View File

@ -1,19 +1,22 @@
<?php <?php
// src/Controller/ClientsController.php
namespace App\Controller; namespace App\Controller;
use App\Entity\Clients; use App\Entity\Clients;
use App\Entity\Reductions;
use App\Form\ClientsType; use App\Form\ClientsType;
use App\Repository\ClientsRepository; use App\Repository\ClientsRepository;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Annotation\Route;
#[Route('/clients')] #[Route('/clients')]
final class ClientsController extends AbstractController final class ClientsController extends AbstractController
{ {
#[Route(name: 'app_clients_index', methods: ['GET'])] #[Route(name: 'app_clients_index', methods: ['GET'])]
public function index(ClientsRepository $clientsRepository): Response public function index(ClientsRepository $clientsRepository): Response
{ {
@ -30,6 +33,12 @@ final class ClientsController extends AbstractController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$montantTotal = $client->getTotalDepense();
if($montantTotal > 1000){
$this->appliquerReductionEtCreerSiNecessaire($client, $entityManager);
}
$entityManager->persist($client); $entityManager->persist($client);
$entityManager->flush(); $entityManager->flush();
@ -42,7 +51,6 @@ final class ClientsController extends AbstractController
]); ]);
} }
#[Route('/{id}/edit', name: 'app_clients_edit', methods: ['GET', 'POST'])] #[Route('/{id}/edit', name: 'app_clients_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, Clients $client, EntityManagerInterface $entityManager): Response public function edit(Request $request, Clients $client, EntityManagerInterface $entityManager): Response
{ {
@ -50,6 +58,13 @@ final class ClientsController extends AbstractController
$form->handleRequest($request); $form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) { if ($form->isSubmitted() && $form->isValid()) {
$montantTotal = $client->getTotalDepense();
if($montantTotal > 1000){
$this->appliquerReductionEtCreerSiNecessaire($client, $entityManager);
}
$entityManager->flush(); $entityManager->flush();
return $this->redirectToRoute('app_clients_index', [], Response::HTTP_SEE_OTHER); return $this->redirectToRoute('app_clients_index', [], Response::HTTP_SEE_OTHER);
@ -62,13 +77,62 @@ final class ClientsController extends AbstractController
} }
#[Route('/{id}', name: 'app_clients_delete', methods: ['POST'])] #[Route('/{id}', name: 'app_clients_delete', methods: ['POST'])]
public function delete(Request $request, Clients $client, EntityManagerInterface $entityManager, int $id, ): Response public function delete(Request $request, Clients $client, EntityManagerInterface $entityManager): Response
{ {
if ($this->isCsrfTokenValid('delete'.$client->getId(), $request->getPayload()->getString('_token'))) { if ($this->isCsrfTokenValid('delete'.$client->getId(), $request->request->get('_token'))) {
$entityManager->remove($client); $entityManager->remove($client);
$entityManager->flush(); $entityManager->flush();
} }
return $this->redirectToRoute('app_clients_index', [], Response::HTTP_SEE_OTHER); return $this->redirectToRoute('app_clients_index', [], Response::HTTP_SEE_OTHER);
} }
// Méthode pour appliquer ou créer une réduction pour un client
// src/Controller/ClientsController.php
private function appliquerReductionEtCreerSiNecessaire(Clients $client, EntityManagerInterface $entityManager)
{
$montantTotal = $client->getTotalDepense();
$entityManager->persist($client);
$reductions = $entityManager->getRepository(Reductions::class)
->createQueryBuilder('r')
->where('r.montant_min <= :montantTotal')
->andWhere('r.actif = :actif')
->andWhere('r.DateDebut <= :currentDate')
->andWhere('r.DateFin >= :currentDate')
->setParameter('montantTotal', $montantTotal)
->setParameter('actif', true)
->setParameter('currentDate', new \DateTime())
->getQuery()
->getResult();
$newReduction = new Reductions();
if ($montantTotal >= 2000) {
$montantMin = 2000;
$pourcentage = 10;
} elseif ($montantTotal >= 1000) {
$montantMin = 1000;
$pourcentage = 5;
}
$newReduction->setPourcentage($pourcentage)
->setMontantMin($montantMin)
->setDateDebut(new \DateTime())
->setDateFin((new \DateTime())->modify('+1 year'))
->setActif(true)
->setClient($client);
$entityManager->persist($newReduction);
$entityManager->flush();
if (!$client->getReductions()->contains($newReduction)) {
$client->addReduction($newReduction);
}
$entityManager->flush();
}
} }

View File

@ -40,10 +40,17 @@ class Clients
#[ORM\ManyToMany(targetEntity: Commandes::class, mappedBy: 'Client')] #[ORM\ManyToMany(targetEntity: Commandes::class, mappedBy: 'Client')]
private Collection $commandes; private Collection $commandes;
#[ORM\Column]
private ?float $totalDepense = null;
#[ORM\OneToMany(targetEntity: Reductions::class, mappedBy: 'client', cascade: ['persist', 'remove'])]
private Collection $reductions;
public function __construct() public function __construct()
{ {
$this->tables = new ArrayCollection(); $this->tables = new ArrayCollection();
$this->commandes = new ArrayCollection(); $this->commandes = new ArrayCollection();
$this->reductions = new ArrayCollection();
} }
public function getId(): ?int public function getId(): ?int
@ -149,4 +156,60 @@ class Clients
return $this; return $this;
} }
public function getTotalDepense(): ?float
{
return $this->totalDepense;
}
public function setTotalDepense(float $totalDepense): static
{
$this->totalDepense = $totalDepense;
return $this;
}
// Dans l'entité Clients
public function appliquerReduction(): void
{
$montantTotal = $this->getTotalDepense();
// Vérifie s'il y a des réductions valides disponibles
$reductions = $this->getReductions(); // Récupérer toutes les réductions du client
foreach ($reductions as $reduction) {
// Vérifie si la réduction est valide (date de validité et montant minimum)
if ($reduction->getDateDebut() <= new \DateTime() && $reduction->getDateFin() >= new \DateTime()) {
if ($montantTotal >= $reduction->getMontantMin()) {
// Applique la réduction en pourcentage au total des dépenses
$reductionMontant = ($montantTotal * $reduction->getPourcentage()) / 100;
$nouveauTotal = $montantTotal - $reductionMontant; // Nouveau montant après réduction
$this->setTotalDepense($nouveauTotal); // Mise à jour du total des dépenses du client
// Met à jour l'objet client avec la réduction
break; // Si une réduction a été appliquée, on arrête
}
}
}
}
public function getReductions(): Collection
{
return $this->reductions;
}
public function addReduction(Reductions $reduction): static
{
if (!$this->reductions->contains($reduction)) {
$this->reductions->add($reduction);
}
return $this;
}
public function removeReduction(Reductions $reduction): static
{
$this->reductions->removeElement($reduction);
return $this;
}
} }

View File

@ -39,9 +39,6 @@ class Plats
#[ORM\ManyToMany(targetEntity: Commandes::class, inversedBy: 'plats')] #[ORM\ManyToMany(targetEntity: Commandes::class, inversedBy: 'plats')]
private Collection $Commande; private Collection $Commande;
#[ORM\ManyToOne(inversedBy: 'plats')]
private ?Reductions $Reduction = null;
public function __construct() public function __construct()
{ {
$this->Commande = new ArrayCollection(); $this->Commande = new ArrayCollection();
@ -147,16 +144,4 @@ class Plats
return $this; return $this;
} }
public function getReduction(): ?Reductions
{
return $this->Reduction;
}
public function setReduction(?Reductions $Reduction): static
{
$this->Reduction = $Reduction;
return $this;
}
} }

View File

@ -16,88 +16,30 @@ class Reductions
#[ORM\Column] #[ORM\Column]
private ?int $id = null; private ?int $id = null;
#[ORM\Column(length: 255)] #[ORM\Column]
private ?string $Description = null; private ?int $pourcentage = null;
#[ORM\Column] #[ORM\Column]
private ?float $Prix = null; private ?int $montant_min = null;
#[ORM\Column] #[ORM\Column]
private ?int $Pourcentage = null; private ?bool $actif = null;
#[ORM\Column(length: 255)]
private ?string $MontantFixe = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)] #[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $DateDebut = null; private ?\DateTimeInterface $DateDebut = null;
#[ORM\Column(type: Types::DATETIME_MUTABLE)] #[ORM\Column(type: Types::DATETIME_MUTABLE)]
private ?\DateTimeInterface $DateFin = null; private ?\DateTimeInterface $DateFin = null;
/**
* @var Collection<int, Plats>
*/
#[ORM\OneToMany(targetEntity: Plats::class, mappedBy: 'Reduction')]
private Collection $plats;
public function __construct() #[ORM\ManyToOne(targetEntity: Clients::class, inversedBy: 'reductions')]
{ #[ORM\JoinColumn(nullable: false)]
$this->plats = new ArrayCollection(); private ?Clients $client = null;
}
public function getId(): ?int public function getId(): ?int
{ {
return $this->id; return $this->id;
} }
public function getDescription(): ?string
{
return $this->Description;
}
public function setDescription(string $Description): static
{
$this->Description = $Description;
return $this;
}
public function getPrix(): ?float
{
return $this->Prix;
}
public function setPrix(float $Prix): static
{
$this->Prix = $Prix;
return $this;
}
public function getPourcentage(): ?int
{
return $this->Pourcentage;
}
public function setPourcentage(int $Pourcentage): static
{
$this->Pourcentage = $Pourcentage;
return $this;
}
public function getMontantFixe(): ?string
{
return $this->MontantFixe;
}
public function setMontantFixe(string $MontantFixe): static
{
$this->MontantFixe = $MontantFixe;
return $this;
}
public function getDateDebut(): ?\DateTimeInterface public function getDateDebut(): ?\DateTimeInterface
{ {
return $this->DateDebut; return $this->DateDebut;
@ -122,33 +64,50 @@ class Reductions
return $this; return $this;
} }
/** public function getPourcentage(): ?int
* @return Collection<int, Plats>
*/
public function getPlats(): Collection
{ {
return $this->plats; return $this->pourcentage;
} }
public function addPlat(Plats $plat): static public function setPourcentage(int $pourcentage): static
{ {
if (!$this->plats->contains($plat)) { $this->pourcentage = $pourcentage;
$this->plats->add($plat);
$plat->setReduction($this);
}
return $this; return $this;
} }
public function removePlat(Plats $plat): static public function getMontantMin(): ?int
{ {
if ($this->plats->removeElement($plat)) { return $this->montant_min;
// set the owning side to null (unless already changed)
if ($plat->getReduction() === $this) {
$plat->setReduction(null);
}
} }
public function setMontantMin(int $montant_min): static
{
$this->montant_min = $montant_min;
return $this;
}
public function isActif(): ?bool
{
return $this->actif;
}
public function setActif(bool $actif): static
{
$this->actif = $actif;
return $this;
}
public function getClient(): ?Clients
{
return $this->client;
}
public function setClient(?Clients $client): static
{
$this->client = $client;
return $this; return $this;
} }
} }

View File

@ -4,6 +4,7 @@ namespace App\Form;
use App\Entity\Clients; use App\Entity\Clients;
use App\Entity\Commandes; use App\Entity\Commandes;
use App\Entity\Reductions;
use App\Entity\Tables; use App\Entity\Tables;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
@ -25,7 +26,7 @@ class ClientsType extends AbstractType
'multiple' => true, 'multiple' => true,
'expanded' => true, 'expanded' => true,
]) ])
->add('totalDepense')
; ;
} }

View File

@ -27,10 +27,6 @@ class PlatsType extends AbstractType
'multiple' => true, 'multiple' => true,
'expanded' => true, 'expanded' => true,
]) ])
->add('Reduction', EntityType::class, [
'class' => Reductions::class,
'choice_label' => 'description',
])
; ;
} }

View File

@ -2,7 +2,10 @@
namespace App\Form; namespace App\Form;
use App\Entity\Clients;
use App\Entity\Reductions; use App\Entity\Reductions;
use http\Client;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\OptionsResolver;
@ -12,16 +15,19 @@ class ReductionsType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options): void public function buildForm(FormBuilderInterface $builder, array $options): void
{ {
$builder $builder
->add('Description') ->add('Taux')
->add('Prix')
->add('Pourcentage')
->add('MontantFixe')
->add('DateDebut', null, [ ->add('DateDebut', null, [
'widget' => 'single_text', 'widget' => 'single_text',
]) ])
->add('DateFin', null, [ ->add('DateFin', null, [
'widget' => 'single_text', 'widget' => 'single_text',
]) ])
->add('client', EntityType::class, [
'class' => Clients::class,
'choice_label' => 'nom',
'multiple' => false,
'expanded' => true,
])
; ;
} }

View File

@ -2,21 +2,6 @@
{% block title %}Client index{% endblock %} {% block title %}Client index{% endblock %}
{% block head %}
<head>
<meta charset="UTF-8">
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text><text y=%221.3em%22 x=%220.2em%22 font-size=%2276%22 fill=%22%23fff%22>sf</text></svg>">
<link href="https://fonts.cdnfonts.com/css/brittany-signature" rel="stylesheet">
</head>
{% endblock %}
{% block stylesheets %}
<link rel="stylesheet" href="{{ asset('css/ControllerVues/list.css') }}"> <!-- Ajout du fichier CSS -->
<link rel="stylesheet" href="{{ asset('css/Index/index.css') }}"> <!-- Ajout du fichier CSS -->
<link rel="stylesheet" href="{{ asset('css/Compte/index.css') }}"> <!-- Ajout du fichier CSS -->
<link rel="stylesheet" href="{{ asset('css/GestionUtilisateurs/GestionUtilisateurs.css') }}"> <!-- Ajout du fichier CSS -->
{% endblock %}
{% block container_modal %} {% block container_modal %}
<div id="container_modal"> <div id="container_modal">
<h1>Clients index</h1> <h1>Clients index</h1>
@ -29,7 +14,9 @@
<th>Nom</th> <th>Nom</th>
<th>Email</th> <th>Email</th>
<th>Telephone</th> <th>Telephone</th>
<th>actions</th> <th>Depense</th>
<th>Réduction Appliquée</th> <!-- Nouvelle colonne -->
<th>Actions</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -40,8 +27,20 @@
<td>{{ client.Nom }}</td> <td>{{ client.Nom }}</td>
<td>{{ client.Email }}</td> <td>{{ client.Email }}</td>
<td>{{ client.Telephone }}</td> <td>{{ client.Telephone }}</td>
<td>{{ client.totalDepense }}</td>
<td> <td>
<form method="post" action="{{ path('app_clients_delete', {'id': client.id}) }}" onsubmit="return confirm('Es-tu sur de vouloir le supprimer ?');"> {% if client.reductions|length > 0 %}
{% for reduction in client.reductions %}
<span>Réduction de {{ reduction.pourcentage }}% - Valide jusqu'à {{ reduction.DateFin|date('d/m/Y') }}</span><br>
{% endfor %}
{% else %}
Aucune réduction
{% endif %}
</td>
<td>
<form method="post" action="{{ path('app_clients_delete', {'id': client.id}) }}" onsubmit="return confirm('Es-tu sûr de vouloir le supprimer ?');">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ client.id) }}"> <input type="hidden" name="_token" value="{{ csrf_token('delete' ~ client.id) }}">
{{ include('clients/_delete_form.html.twig') }} {{ include('clients/_delete_form.html.twig') }}
</form> </form>
@ -50,7 +49,7 @@
</tr> </tr>
{% else %} {% else %}
<tr> <tr>
<td colspan="6">no records found</td> <td colspan="8">Aucun client trouvé</td>
</tr> </tr>
{% endfor %} {% endfor %}
</tbody> </tbody>

View File

@ -27,12 +27,11 @@
<thead> <thead>
<tr> <tr>
<th>Id</th> <th>Id</th>
<th>Description</th>
<th>Prix</th>
<th>Pourcentage</th> <th>Pourcentage</th>
<th>MontantFixe</th> <th>Montant Minimum</th>
<th>DateDebut</th> <th>DateDebut</th>
<th>DateFin</th> <th>DateFin</th>
<th>Client</th>
<th>actions</th> <th>actions</th>
</tr> </tr>
</thead> </thead>
@ -40,18 +39,16 @@
{% for reduction in reductions %} {% for reduction in reductions %}
<tr> <tr>
<td>{{ reduction.id }}</td> <td>{{ reduction.id }}</td>
<td>{{ reduction.Description }}</td> <td>{{ reduction.pourcentage }}%</td>
<td>{{ reduction.Prix }}</td> <td>{{ reduction.montantMin }} €</td>
<td>{{ reduction.Pourcentage }}</td> <td>{{ reduction.DateDebut ? reduction.DateDebut|date('d/m/Y H:i:s') : 'Non spécifié' }}</td>
<td>{{ reduction.MontantFixe }}</td> <td>{{ reduction.DateFin ? reduction.DateFin|date('d/m/Y H:i:s') : 'Non spécifié' }}</td>
<td>{{ reduction.DateDebut ? reduction.DateDebut|date('Y-m-d H:i:s') : '' }}</td> <td>{{ reduction.client.nom }}</td>
<td>{{ reduction.DateFin ? reduction.DateFin|date('Y-m-d H:i:s') : '' }}</td>
<td> <td>
<form method="post" action="{{ path('app_reductions_delete', {'id': reduction.id}) }}" onsubmit="return confirm('Es-tu sur de vouloir le supprimer ?'); "> <form method="post" action="{{ path('app_reductions_delete', {'id': reduction.id}) }}" onsubmit="return confirm('Êtes-vous sûr de vouloir supprimer cette réduction ?'); ">
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ reduction.id) }}"> <input type="hidden" name="_token" value="{{ csrf_token('delete' ~ reduction.id) }}">
{{ include('reductions/_delete_form.html.twig') }} <button type="submit" class="btn btn-danger">Supprimer</button>
</form> </form>
<a href="{{ path('app_reductions_edit', {'id': reduction.id}) }}">Modifier</a>
</td> </td>
</tr> </tr>
{% else %} {% else %}
@ -61,8 +58,6 @@
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
<a href="{{ path('app_reductions_new') }}">Créer une réduction</a>
</div> </div>
{% endblock %} {% endblock %}