<?php
namespace App\EventSubscriber;
use App\Entity\Addressing\City;
use App\Entity\Customer\Customer;
use App\Entity\Customer\CustomerGroup;
use App\Entity\Customer\CustomerActivity;
use App\Entity\Product\Depot;
use Doctrine\ORM\EntityManagerInterface;
use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
final class CustomerAutoCodeSubscriber implements EventSubscriberInterface
{
/** @var EntityManagerInterface */
private $em;
public function __construct(EntityManagerInterface $em)
{
$this->em = $em;
}
public static function getSubscribedEvents(): array
{
return [
// Génération à la création uniquement
'sylius.customer.pre_create' => 'onPreCreate',
// Préservation/Restoration à la mise à jour
'sylius.customer.pre_update' => 'onPreUpdate',
];
}
/**
* Création : si aucun code fourni, on génère à partir du groupe.
*/
public function onPreCreate(ResourceControllerEvent $event): void
{
$customer = $event->getSubject();
if (!$customer instanceof Customer) {
return;
}
// Si un code est déjà renseigné (import ou saisie manuelle), on ne touche pas.
$currentCode = trim((string) $customer->getCode());
if ($currentCode !== '') {
return;
}
$group = $customer->getGroup();
$category=$group->getCategory();
if (!$group instanceof CustomerGroup) {
// Sans groupe, on ne peut pas générer : on laisse tel quel.
return;
}
// Incrément atomique du compteur du groupe
if($category == "STANDARD" or $category == "DIFFUSEUR" ){
$cats = ['STANDARD', 'DIFFUSEUR'];
$this->em->createQuery(
'UPDATE ' . CustomerGroup::class . ' g SET g.counter = g.counter + 1 WHERE g.category IN (:cats)'
)
->setParameter('cats', $cats)
->execute();
}else{
$cats = ['STANDARD', 'DIFFUSEUR'];
$this->em->createQuery(
'UPDATE ' . CustomerGroup::class . ' g SET g.counter = g.counter + 1 WHERE g.category IN (:cats) and g.id <> 91'
)
->setParameter('cats', $cats)
->execute();
$this->em->createQuery(
'UPDATE ' . CustomerGroup::class . ' g SET g.counter = g.counter + 1 WHERE g.id = :id'
)
->setParameter('id', $group->getId())
->execute();
}
// Rafraîchir pour relire le counter et le prefix à jour
$this->em->refresh($group);
$next = (int) $group->getCounter();
$prefix = (string) $group->getCounterPrefix();
// Padding : utilise getCounterPadLength() si dispo, sinon 5
$padLength = 5;
if (method_exists($group, 'getCounterPadLength')) {
$tryPad = (int) $group->getCounterPadLength();
if ($tryPad > 0) {
$padLength = $tryPad;
}
}
$ville=trim((string) $customer->getDefaultAddress()->getCity());
$city = $this->em->getRepository(City::class)
->createQueryBuilder('c')
->where('LOWER(c.name) = LOWER(:cityName)')
->setParameter('cityName', $ville)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
if($city) {
$v=$customer->getDefaultAddress();
$v->setCityId($city);
$v->setAddress1($customer->getDefaultAddress()->getStreet());
}
$activity = $this->em->getRepository(CustomerActivity::class)
->createQueryBuilder('c')
->where('c.id = :acti')
->setParameter('acti', $group)
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
if($activity) {
$customer->setActivity($activity);
}
$depot = $this->em->getRepository(Depot::class)
->createQueryBuilder('c')
->where('c.id = 1')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult();
if($depot) {
$customer->setDepot($depot);
}
// Concat préfixe + numéro paddé
$code = sprintf('%s%d', $prefix, $next);
$repo = $this->em->getRepository(Customer::class);
$attempts = 0;
while ($repo->findOneBy(['code' => $code]) && $attempts < 3) {
$this->em->createQuery(
'UPDATE ' . CustomerGroup::class . ' g SET g.counter = g.counter + 1 WHERE g.id = :id'
)
->setParameter('id', $group->getId())
->execute();
$this->em->refresh($group);
$next = (int) $group->getCounter();
$code = sprintf('%s%d', $prefix, $next);
$attempts++;
}
$customer->setCode($code);
}
/**
* Mise à jour : on ne régénère pas, on préserve.
* Si le code arrive vide (formulaire), on restaure la valeur stockée en base.
*/
public function onPreUpdate(ResourceControllerEvent $event): void
{
$customer = $event->getSubject();
if (!$customer instanceof Customer) {
return;
}
if($customer->getFirstName() == NULL){
$customer->setFirstName($customer->getCompanyName());
}
if($customer->getLastName() == NULL){
$customer->setLastName($customer->getCompanyName());
}
if ( $customer ->getAccountant() == NULL){
$customer->setAccountant($customer);
}
if ( $customer ->getShippingContact() == NULL){
$customer->setShippingContact($customer);
}
if ( $customer ->getInvoicingContact() == NULL){
$customer->setInvoicingContact($customer);
}
if ( $customer ->getFiche1() == NULL){
$customer->setFiche1($customer);
}
if ( $customer ->getFiche2() == NULL){
$customer->setFiche2($customer);
}
// Cas update uniquement (id déjà présent)
if (null === $customer->getId()) {
return;
}
$submittedCode = trim((string) $customer->getCode());
if ($submittedCode !== '') {
return;
}
// Si le champ a été envoyé vide (ou non soumis et mis à null), on restaure la valeur d'origine
$original = $this->em->getRepository(Customer::class)->find($customer->getId());
if ($original instanceof Customer) {
$originalCode = trim((string) $original->getCode());
if ($originalCode !== '') {
$customer->setCode($originalCode);
}
}
}
}