1

I created a Plugin for sending emails when the owner of the shop changes the customer's group in backend. I still need to add the group (discount) in the email. The problem is that when I access to a customer and change it's group it sends me around 16 emails, the function that sends the email is afterSetGroupId(); so i don't understand why it sends me too many emails.

Here is my code: Plugin SendDiscount.php

public function afterSetGroupId(\Magento\Customer\Api\Data\CustomerInterface $customer, $result)
    {
        //$groupId = $customer->getGroupId();
        //$this->sendYourCustomEmail($customer);


        /* Receiver Detail the person who is going to receive the info that user logged in*/
        $receiverInfo = [
            'name' => 'Admin',
            'email' => 'myemail@hotmail.com'
        ];

        $store = $this->storeManager->getStore();

       $templateParams = ['store' => $store, 'administrator_name' => $receiverInfo['name']];

        $transport = $this->transportBuilder->setTemplateIdentifier(
            'phpcuong_transactional_email_customer_group'
        )->setTemplateOptions(
            ['area' => 'frontend', 'store' => $store->getId()]
        )->addTo(
            $receiverInfo['email'], $receiverInfo['name']
        )->setTemplateVars(
            $templateParams
        )->setFrom(
            'general'
        )->getTransport();

        try {
            // Send an email
            $transport->sendMessage();
        } catch (\Exception $e) {
            // Write a log message whenever get errors
            $this->logger->critical($e->getMessage());
        }


    }

This is my di.xml located under etc/adminhtml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/ObjectManager/etc/config.xsd">
    <type name="\Magento\Customer\Api\Data\CustomerInterface">
        <plugin name="PHPCuong_CustomerGroupEmail_Plugin" type="PHPCuong\CustomerGroupEmail\Plugin\SendDiscount" sortOrder="10" disabled="false"  />
    </type>
</config>
3

To send an email when customer group changes, I will recommend using events instead of using plugin.

Why not recommending plugin for this kind of task ? Because we use plugin when we need to modify input/output of any function and we use event observer when we have to do some external operation on the data like logging the data into log files, sending the data to third party servers, etc.

I will share event/observer code here which you can use to send email when customer group changes.

etc/adminhtml/events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="customer_save_after_data_object">
        <observer name="amitshree_customer_save_after_data_object" instance="Amitshree\CustomerGroup\Observer\GroupChanged" />
    </event>
</config>

etc/email_templates.xml

<?xml version="1.0"?>

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Email:etc/email_templates.xsd">
    <template id="amitshree_customer_group_changed" label="Amitshree - Customer Group Change" file="group_changed.html" type="html" module="Amitshree_CustomerGroup" area="frontend"/>
</config>

Amitshree/CustomerGroup/Observer/GroupChanged.php

<?php

namespace Amitshree\CustomerGroup\Observer;

use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Store\Model\ScopeInterface;
use Magento\Customer\Api\GroupRepositoryInterface;

class GroupChanged implements ObserverInterface
{


    public function __construct(
        TransportBuilder $transportBuilder,
        ScopeConfigInterface $scopeConfig,
        GroupRepositoryInterface $groupRepository
    ){
        $this->transportBuilder = $transportBuilder;
        $this->scopeConfig = $scopeConfig;
        $this->groupRepository = $groupRepository;
    }

    /**
     * @param \Magento\Framework\Event\Observer $observer
     * @return void
     */
    public function execute(EventObserver $observer)
    {

        $customer = $observer->getCustomerDataObject();
        $customerOld = $observer->getOrigCustomerDataObject();
        $newGroupId = $customer->getGroupId();
        $oldGroupId = $customerOld->getGroupId();
        if ($newGroupId !== $oldGroupId) {
            $newGroup = $this->groupRepository->getById($newGroupId);
            $newGroupName = $newGroup->getCode();
            $oldGroup = $this->groupRepository->getById($oldGroupId);
            $oldGroupName = $oldGroup->getCode();
            $firstName = $customer->getFirstName();
            $customerEmail = $customer->getEmail();
            $groupVariables = [
                'first_name' => $firstName,
                'new_group' => $newGroupName,
                'old_group' => $oldGroupName
            ];


            $email = $this->scopeConfig->getValue('trans_email/ident_general/email',ScopeInterface::SCOPE_STORE);
            $name  = $this->scopeConfig->getValue('trans_email/ident_general/name',ScopeInterface::SCOPE_STORE);

            $postObject = new \Magento\Framework\DataObject();
            $postObject->setData($groupVariables);

            $transport = $this->transportBuilder
                ->setTemplateIdentifier('amitshree_customer_group_changed')
                ->setTemplateOptions(['area' => \Magento\Framework\App\Area::AREA_ADMINHTML, 'store' => \Magento\Store\Model\Store::DEFAULT_STORE_ID])
                ->setTemplateVars(['data' => $postObject])
                ->setFrom(['name' => $name,'email' => $email])
                ->addTo([$customerEmail])
                ->getTransport();

            $transport->sendMessage();
        }

        return $this;
    }
}

view/adminhtml/email/group_changed.html

<!--@subject {{trans "Customer group changed"}} @-->

Hello {{var data.first_name|raw}}, your customer group has been changed for {{store url=""}} from {{var data.old_group|raw}} to {{var data.new_group|raw}}.
3
  • 1
    Hello, this one worked for me. Just in the if ($newGroupId !== $oldGroup) it needs to be if ($newGroupId !== $oldGroupId) . Thank you! Aug 19 '19 at 21:50
  • Updated. Thanks.
    – amitshree
    Aug 20 '19 at 6:46
  • 1
    thanks @amitshree it worked, as I needed, but I would like to add a suggestion for others, to use the html format instead of text, because no one will use the simple text in the live site. :) Sep 21 '20 at 4:50
0

There are several places in your codebase call the setGroupId method and it's causing this issue. I would suggest using a different plugin to only send the email before saving the customer. Something like this:

di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Customer\Model\ResourceModel\Customer">
        <plugin name="send_email_when_changing_group_id" type="PHPCuong\CustomerGroupEmail\Plugin\SendDiscount" />
    </type>
</config>

SendDiscount.php

    public function beforeSave(\Magento\Customer\Model\ResourceModel\Customer $subject, \Magento\Customer\Model\Customer $customer)
    {
        $oldGroupId = $customer->getOrigData('group_id');
        $newGroupId = $customer->getGroupId();

        if ($oldGroupId == $newGroupId) return [$customer];

        /* Receiver Detail the person who is going to receive the info that user logged in*/
        $receiverInfo = [
            'name' => 'Admin',
            'email' => 'myemail@hotmail.com'
        ];

        $store = $this->storeManager->getStore();

        $templateParams = ['store' => $store, 'administrator_name' => $receiverInfo['name']];

        $transport = $this->transportBuilder->setTemplateIdentifier(
            'phpcuong_transactional_email_customer_group'
        )->setTemplateOptions(
            ['area' => 'frontend', 'store' => $store->getId()]
        )->addTo(
            $receiverInfo['email'], $receiverInfo['name']
        )->setTemplateVars(
            $templateParams
        )->setFrom(
            'general'
        )->getTransport();

        try {
            // Send an email
            $transport->sendMessage();
        } catch (\Exception $e) {
            // Write a log message whenever get errors
            $this->logger->critical($e->getMessage());
        }

        return [$customer];
    }

Note: This is just a sample code and I haven't tested it yet.

0

The main reason of your problem is the setGroupId method, its purpose is to set group ID for customer model, not to save the group ID. That's why it's wrong to put your plugin after setGroupId, the method could be called 2398473 times while the group ID is not actually saved.

To resolve this, fire your code after customer save (which saved the data into db), not after set group ID (which only set data to model), then check if customer group ID is changed.

Since Magento's getOrigData() is broken at this moment (https://github.com/magento/magento2/issues/8788), you can do a workaround by using aroundSave:

app/code/Vendor/Module/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Customer\Model\Customer">
        <plugin name="PHPCuong_CustomerGroupEmail_Plugin" type="Vendor\Module\Plugin\SendDiscount" sortOrder="10" disabled="false"  />
    </type>
</config>

app/code/Vendor/Module/Plugin/SendDiscount.php

namespace Vendor\Module\Plugin;

use Magento\Customer\Api\CustomerRepositoryInterface;
use Magento\Customer\Model\Customer;

class SendDiscount
{
    public function __construct(
        CustomerRepositoryInterface $customerRepository
    ) {
        $this->customerRepository = $customerRepository;
    }

    public function aroundSave(
        Customer $subject,
        \Closure $proceed
    ) {
        $oldCustomer = $this->customerRepository->getById($subject->getId());
        $result = $proceed();

        //Check if customer group is changed
        if ($oldCustomer->getGroupId() != $subject->getGroupId()) {
            //do your logic
        }

        return $result;
    }
}
1
  • Hello, I tried it but after saving customer´s new group the page shows "This page isn’t working" , there are no error logs that can tell me what is the error about. Aug 19 '19 at 14:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.