diff --git a/local/modules/PurgeFakeCustomer/Command/FakeCustomerPurge.php b/local/modules/PurgeFakeCustomer/Command/FakeCustomerPurge.php
new file mode 100644
index 000000000..853c930b8
--- /dev/null
+++ b/local/modules/PurgeFakeCustomer/Command/FakeCustomerPurge.php
@@ -0,0 +1,34 @@
+
+ * Date: 12/01/2021
+ */
+namespace PurgeFakeCustomer\Command;
+
+use PurgeFakeCustomer\Event\FakeCustomerEvent;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Thelia\Command\ContainerAwareCommand;
+use Thelia\Model\ConfigQuery;
+
+class FakeCustomerPurge extends ContainerAwareCommand
+{
+ protected function execute(InputInterface $input, OutputInterface $output)
+ {
+ $output->writeln(
+ sprintf("Deleting fake customers")
+ );
+
+ $critere = ConfigQuery::read('purgefakecustomer_critere', '');
+ $event = new FakeCustomerEvent($critere, $input->getOption('verbose'));
+
+ $this->getDispatcher()->dispatch(FakeCustomerEvent::PURGE, $event);
+
+ foreach ($event->getStatus() as $status => $level) {
+ $output->writeln("<$level>$status$level>");
+ }
+
+ $output->writeln(sprintf("%d fake customers deleteddàçp", $event->getDeletedCount()));
+ }
+}
diff --git a/local/modules/PurgeFakeCustomer/Config/secret-key.txt b/local/modules/PurgeFakeCustomer/Config/secret-key.txt
new file mode 100644
index 000000000..886d90fdb
--- /dev/null
+++ b/local/modules/PurgeFakeCustomer/Config/secret-key.txt
@@ -0,0 +1 @@
+sterivein-2021
\ No newline at end of file
diff --git a/local/modules/PurgeFakeCustomer/Controller/PurgeController.php b/local/modules/PurgeFakeCustomer/Controller/PurgeController.php
new file mode 100644
index 000000000..0b04e4e4a
--- /dev/null
+++ b/local/modules/PurgeFakeCustomer/Controller/PurgeController.php
@@ -0,0 +1,41 @@
+
+ * Date: 12/01/2021
+ */
+class PurgeController extends BaseFrontController
+{
+ public function purge($secretKey)
+ {
+ $responseText = '';
+ $storedSecretKey = trim(@file_get_contents(__DIR__ .'/../Config/secret-key.txt'));
+
+ if ($storedSecretKey != $secretKey) {
+ $responseText .= sprintf("ERROR: key verification failed.
");
+ } else {
+
+ $critere = ConfigQuery::read('purgefakecustomer_critere', '');
+ $responseText .= sprintf("INFO: Deleting fake customers
");
+ $verbose = $this->getRequest()->query->get('verbose', false);
+
+ $event = new FakeCustomerEvent($critere, !empty($verbose));
+ $this->getDispatcher()->dispatch(FakeCustomerEvent::PURGE, $event);
+
+ foreach ($event->getStatus() as $status => $level) {
+ $responseText .= strtoupper($level) . ": $status
";
+ }
+
+ $responseText .= sprintf("INFO: %d fake customers deleted
", $event->getDeletedCount());
+ }
+
+ return new Response($responseText);
+ }
+}
diff --git a/local/modules/PurgeFakeCustomer/Event/FakeCustomerEvent.php b/local/modules/PurgeFakeCustomer/Event/FakeCustomerEvent.php
new file mode 100644
index 000000000..b7273b737
--- /dev/null
+++ b/local/modules/PurgeFakeCustomer/Event/FakeCustomerEvent.php
@@ -0,0 +1,83 @@
+critere = $critere;
+ $this->verbose = $verbose;
+ }
+
+ /**
+ * @return string
+ */
+ public function getCritere()
+ {
+ return $this->critere;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getStatus()
+ {
+ return $this->status;
+ }
+
+ /**
+ * @param string $status
+ * @return $this
+ */
+ public function appendStatus($status, $level = 'info')
+ {
+ $this->status[$status] = $level;
+ return $this;
+ }
+
+ /**
+ * @return boolean
+ */
+ public function isVerbose()
+ {
+ return $this->verbose;
+ }
+
+ /**
+ * @return int
+ */
+ public function getDeletedCount()
+ {
+ return $this->deletedCount;
+ }
+
+ /**
+ * @param int $deletedCount
+ * @return $this
+ */
+ public function setDeletedCount($deletedCount)
+ {
+ $this->deletedCount = $deletedCount;
+ return $this;
+ }
+}
diff --git a/local/modules/PurgeFakeCustomer/EventListener/EventManager.php b/local/modules/PurgeFakeCustomer/EventListener/EventManager.php
new file mode 100644
index 000000000..3b7aaaf43
--- /dev/null
+++ b/local/modules/PurgeFakeCustomer/EventListener/EventManager.php
@@ -0,0 +1,62 @@
+
+ * Date: 12/01/2021
+ */
+namespace PurgeFakeCustomer\EventListener;
+
+use Propel\Runtime\Exception\PropelException;
+use Propel\Runtime\Propel;
+use PurgeFakeCustomer\Event\FakeCustomerEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Thelia\Model\CustomerQuery;
+use Thelia\Model\Map\FeatureTableMap;
+use Thelia\Model\Map\TemplateTableMap;
+use Thelia\Model\Template as ChildTemplate;
+
+class EventManager implements EventSubscriberInterface
+{
+ public function purge(FakeCustomerEvent $event)
+ {
+ $critereComplet = '';
+ $critere = $event->getCritere();
+
+ if ($critere !== '') $critereComplet = $critere . ' AND ';
+ $critereComplet = $critereComplet . '`customer_id` NOT IN (SELECT DISTINCT(`customer_id`) FROM `order`)';
+
+ $verbose = $event->isVerbose();
+ $deleted = 0;
+
+ $sql = 'SELECT `customer_id` FROM `address` WHERE ' . $critereComplet;
+ $con = Propel::getServiceContainer()->getReadConnection(FeatureTableMap::DATABASE_NAME);
+ try {
+ $stmt = $con->prepare($sql);
+ $stmt->execute();
+ } catch (Exception $e) {
+ Propel::log($e->getMessage(), Propel::LOG_ERR);
+ throw new PropelException(sprintf('Unable to execute SELECT statement [%s]', $sql), 0, $e);
+ }
+ $obj = null;
+ if ($rows = $stmt->fetchAll(\PDO::FETCH_NUM)) {
+ $obj = new ChildTemplate();
+ $obj->hydrate($row);
+ TemplateTableMap::addInstanceToPool($obj, (string) $key);
+ }
+ $stmt->closeCursor();
+
+ return $obj;
+
+ $event->setDeletedCount($deleted);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function getSubscribedEvents()
+ {
+ return [
+ FakeCustomerEvent::PURGE => ["purge", 128]
+ ];
+ }
+}