diff --git a/Api/Data/EraseCustomerInterface.php b/Api/Data/EraseCustomerInterface.php
index f1cfe70..28366ea 100644
--- a/Api/Data/EraseCustomerInterface.php
+++ b/Api/Data/EraseCustomerInterface.php
@@ -23,6 +23,7 @@ interface EraseCustomerInterface extends ExtensibleDataInterface
public const SCHEDULED_AT = 'scheduled_at';
public const STATE = 'state';
public const STATUS = 'status';
+ public const MESSAGE = 'message';
public const ERASED_AT = 'erased_at';
/**#@-*/
@@ -118,6 +119,21 @@ public function getStatus(): string;
*/
public function setStatus(string $status): EraseCustomerInterface;
+ /**
+ * Retrieve the error message
+ *
+ * @return string|null
+ */
+ public function getMessage(): ?string;
+
+ /**
+ * Set the error message
+ *
+ * @param string|null $message
+ * @return \Opengento\Gdpr\Api\Data\EraseCustomerInterface
+ */
+ public function setMessage(?string $message): EraseCustomerInterface;
+
/**
* Retrieve the erased at if it exists
*
diff --git a/Controller/Adminhtml/Privacy/MassErase.php b/Controller/Adminhtml/Privacy/MassErase.php
new file mode 100644
index 0000000..d698ba7
--- /dev/null
+++ b/Controller/Adminhtml/Privacy/MassErase.php
@@ -0,0 +1,78 @@
+eraseCustomerManagement = $eraseCustomerManagement;
+ parent::__construct($context, $filter, $collectionFactory);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ protected function massAction(AbstractCollection $collection)
+ {
+ $customerErased = 0;
+
+ foreach ($collection->getAllIds() as $customerId) {
+ try {
+ $this->eraseCustomerManagement->process($this->eraseCustomerManagement->create((int) $customerId));
+ $customerErased++;
+ } catch (LocalizedException $e) {
+ $this->messageManager->addErrorMessage(
+ new Phrase('Customer with id "%1": %2', [$customerId, $e->getMessage()])
+ );
+ } catch (\Exception $e) {
+ $this->messageManager->addExceptionMessage($e, new Phrase('An error occurred on the server.'));
+ }
+ }
+
+ if ($customerErased) {
+ $this->messageManager->addSuccessMessage(
+ new Phrase('A total of %1 record(s) were erased.', [$customerErased])
+ );
+ }
+
+ /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
+ $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
+ $resultRedirect->setPath('customer/index/index');
+
+ return $resultRedirect;
+ }
+}
diff --git a/Model/EraseCustomer.php b/Model/EraseCustomer.php
index abca122..c265676 100755
--- a/Model/EraseCustomer.php
+++ b/Model/EraseCustomer.php
@@ -106,6 +106,22 @@ public function setStatus(string $status): EraseCustomerInterface
return $this->setData(self::STATUS, $status);
}
+ /**
+ * @inheritdoc
+ */
+ public function getMessage(): ?string
+ {
+ return $this->_getData(self::MESSAGE) === null ? null : (string) $this->_getData(self::MESSAGE);
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function setMessage(?string $message): EraseCustomerInterface
+ {
+ return $this->setData(self::MESSAGE, $message);
+ }
+
/**
* @inheritdoc
*/
diff --git a/Model/EraseCustomerChecker.php b/Model/EraseCustomerChecker.php
index 8273f22..9f88f69 100644
--- a/Model/EraseCustomerChecker.php
+++ b/Model/EraseCustomerChecker.php
@@ -91,6 +91,6 @@ public function canProcess(int $customerId): bool
&& $entity->getStatus() === EraseCustomerInterface::STATUS_READY)
|| ($entity->getState() === EraseCustomerInterface::STATE_PROCESSING
&& $entity->getStatus() === EraseCustomerInterface::STATUS_FAILED))
- && $this->customerChecker->hasPendingOrders($entity->getCustomerId());
+ && !$this->customerChecker->hasPendingOrders($entity->getCustomerId());
}
}
diff --git a/Model/EraseCustomerManagement.php b/Model/EraseCustomerManagement.php
index 0d33ff7..5e368ad 100644
--- a/Model/EraseCustomerManagement.php
+++ b/Model/EraseCustomerManagement.php
@@ -114,6 +114,7 @@ public function cancel(int $customerId): bool
/**
* @inheritdoc
+ * @throws \Exception
*/
public function process(EraseCustomerInterface $entity): EraseCustomerInterface
{
@@ -128,14 +129,47 @@ public function process(EraseCustomerInterface $entity): EraseCustomerInterface
$entity = $this->eraseCustomerRepository->save($entity);
try {
- $this->eraseManagement->erase($entity->getCustomerId());
- $entity->setState(EraseCustomerInterface::STATE_COMPLETE);
- $entity->setStatus(EraseCustomerInterface::STATUS_SUCCEED);
- $entity->setErasedAt($this->localeDate->gmtDate());
+ if ($this->eraseManagement->erase($entity->getCustomerId())) {
+ return $this->success($entity);
+ }
+
+ return $this->fail($entity);
} catch (\Exception $e) {
- $entity->setState(EraseCustomerInterface::STATE_PROCESSING);
- $entity->setStatus(EraseCustomerInterface::STATUS_FAILED);
+ $this->fail($entity, $e->getMessage());
+ throw $e;
}
+ }
+
+ /**
+ * Erasure has succeeded
+ *
+ * @param \Opengento\Gdpr\Api\Data\EraseCustomerInterface $entity
+ * @return \Opengento\Gdpr\Api\Data\EraseCustomerInterface
+ * @throws \Magento\Framework\Exception\CouldNotSaveException
+ */
+ private function success(EraseCustomerInterface $entity): EraseCustomerInterface
+ {
+ $entity->setState(EraseCustomerInterface::STATE_COMPLETE);
+ $entity->setStatus(EraseCustomerInterface::STATUS_SUCCEED);
+ $entity->setErasedAt($this->localeDate->gmtDate());
+ $entity->setMessage(null);
+
+ return $this->eraseCustomerRepository->save($entity);
+ }
+
+ /**
+ * Erasure has failed
+ *
+ * @param \Opengento\Gdpr\Api\Data\EraseCustomerInterface $entity
+ * @param string|null $message
+ * @return \Opengento\Gdpr\Api\Data\EraseCustomerInterface
+ * @throws \Magento\Framework\Exception\CouldNotSaveException
+ */
+ private function fail(EraseCustomerInterface $entity, ?string $message = null): EraseCustomerInterface
+ {
+ $entity->setState(EraseCustomerInterface::STATE_PROCESSING);
+ $entity->setStatus(EraseCustomerInterface::STATUS_FAILED);
+ $entity->setMessage($message);
return $this->eraseCustomerRepository->save($entity);
}
diff --git a/Model/Newsletter/Subscriber.php b/Model/Newsletter/Subscriber.php
index f3850cc..d0186a6 100644
--- a/Model/Newsletter/Subscriber.php
+++ b/Model/Newsletter/Subscriber.php
@@ -7,10 +7,13 @@
namespace Opengento\Gdpr\Model\Newsletter;
+use \Magento\Newsletter\Model\Subscriber as SubscriberModel;
use Magento\Newsletter\Model\SubscriberFactory;
/**
* `\Opengento\Gdpr\Model\Newsletter\Subscriber` class is the final state of `\Magento\Newsletter\Model\Subscriber`.
+ *
+ * @method SubscriberModel loadByCustomerId(int $customerId)
*/
final class Subscriber
{
@@ -30,6 +33,16 @@ public function __construct(
$this->subscriber = $subscriberFactory->create(['data' => $data]);
}
+ /**
+ * Retrieve the real subscriber subject
+ *
+ * @return \Magento\Newsletter\Model\Subscriber
+ */
+ public function getRealSubscriber(): SubscriberModel
+ {
+ return $this->subscriber;
+ }
+
/**
* @inheritdoc
*/
diff --git a/Service/Anonymize/Processor/SubscriberDataProcessor.php b/Service/Anonymize/Processor/SubscriberDataProcessor.php
index 96f5d86..21afcbf 100644
--- a/Service/Anonymize/Processor/SubscriberDataProcessor.php
+++ b/Service/Anonymize/Processor/SubscriberDataProcessor.php
@@ -53,10 +53,11 @@ public function __construct(
*/
public function execute(int $customerId): bool
{
- /** @var \Magento\Newsletter\Model\Subscriber $subscriber */
+ /** @var \Opengento\Gdpr\Model\Newsletter\Subscriber $subscriber */
$subscriber = $this->subscriberFactory->create();
$subscriber->loadByCustomerId($customerId);
- $this->subscriberResourceModel->save($this->anonymizer->anonymize($subscriber));
+ $this->anonymizer->anonymize($subscriber);
+ $this->subscriberResourceModel->save($subscriber->getRealSubscriber());
return true;
}
diff --git a/Service/Delete/Processor/SubscriberDataProcessor.php b/Service/Delete/Processor/SubscriberDataProcessor.php
index 579460f..21077ab 100644
--- a/Service/Delete/Processor/SubscriberDataProcessor.php
+++ b/Service/Delete/Processor/SubscriberDataProcessor.php
@@ -8,7 +8,7 @@
namespace Opengento\Gdpr\Service\Delete\Processor;
use Magento\Newsletter\Model\ResourceModel\Subscriber as ResourceSubscriber;
-use Opengento\Gdpr\Model\Newsletter\SubscriberFactory;
+use Magento\Newsletter\Model\SubscriberFactory;
use Opengento\Gdpr\Service\Delete\ProcessorInterface;
/**
@@ -17,7 +17,7 @@
final class SubscriberDataProcessor implements ProcessorInterface
{
/**
- * @var \Opengento\Gdpr\Model\Newsletter\SubscriberFactory
+ * @var \Magento\Newsletter\Model\SubscriberFactory
*/
private $subscriberFactory;
@@ -27,7 +27,7 @@ final class SubscriberDataProcessor implements ProcessorInterface
private $subscriberResourceModel;
/**
- * @param \Opengento\Gdpr\Model\Newsletter\SubscriberFactory $subscriberFactory
+ * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
* @param \Magento\Newsletter\Model\ResourceModel\Subscriber $subscriberResourceModel
*/
public function __construct(
diff --git a/Setup/InstallSchema.php b/Setup/InstallSchema.php
index a20e356..2cc7283 100755
--- a/Setup/InstallSchema.php
+++ b/Setup/InstallSchema.php
@@ -79,6 +79,13 @@ private function createEraseCustomerTable(SchemaSetupInterface $setup): bool
['nullable' => false],
'Status'
)
+ ->addColumn(
+ EraseCustomerInterface::MESSAGE,
+ Table::TYPE_TEXT,
+ 255,
+ ['nullable' => true],
+ 'Message'
+ )
->addColumn(
EraseCustomerInterface::ERASED_AT,
Table::TYPE_TIMESTAMP,
@@ -105,7 +112,7 @@ private function createEraseCustomerTable(SchemaSetupInterface $setup): bool
EraseCustomerInterface::CUSTOMER_ID,
$setup->getTable('customer_entity'),
'entity_id',
- Table::ACTION_NO_ACTION
+ Table::ACTION_CASCADE
)
->setComment('Customer Erase Scheduler');
diff --git a/TODO.md b/TODO.md
index 55d161f..0449612 100644
--- a/TODO.md
+++ b/TODO.md
@@ -23,8 +23,7 @@ Area:
- Multiple export in command line result in filename expanded at each iteration
## Anonymizer
-
-- Check customer only closed/completed orders
+
- Payment Data
- Invitation Data
diff --git a/etc/adminhtml/routes.xml b/etc/adminhtml/routes.xml
new file mode 100644
index 0000000..296cf02
--- /dev/null
+++ b/etc/adminhtml/routes.xml
@@ -0,0 +1,14 @@
+
+
+