From f611c33dc1eb66b0df8a3b199152eb9e7abd93dc Mon Sep 17 00:00:00 2001 From: Vadym Honcharuk Date: Fri, 20 Sep 2024 13:37:54 +0300 Subject: [PATCH] [Analytics][Tracker] Feature #3340, add company_id and customer_group_id in tracking data --- .../Report/CustomerGroupSelector.php | 60 +++++++ .../Model/Report/Context.php | 10 ++ .../CustomerGroupIdFilterQueryProvider.php | 74 +++++++++ .../CustomerGroupIdFilterQueryProvider.php | 81 ++++++++++ src/module-elasticsuite-analytics/etc/di.xml | 18 ++- ...le_elasticsuite_analytics_search_usage.xml | 4 + .../report/customer_group_selector.phtml | 38 +++++ .../adminhtml/web/css/source/_module.less | 13 ++ .../web/js/report/customer-group-selector.js | 43 +++++ .../Block/Variables/Page/Customer.php | 151 ++++++++++++++++++ .../etc/elasticsuite_indices.xml | 6 + .../view/frontend/layout/default.xml | 3 + 12 files changed, 495 insertions(+), 6 deletions(-) create mode 100644 src/module-elasticsuite-analytics/Block/Adminhtml/Report/CustomerGroupSelector.php create mode 100644 src/module-elasticsuite-analytics/Model/Report/Event/CustomerGroupIdFilterQueryProvider.php create mode 100644 src/module-elasticsuite-analytics/Model/Report/Session/CustomerGroupIdFilterQueryProvider.php create mode 100644 src/module-elasticsuite-analytics/view/adminhtml/templates/report/customer_group_selector.phtml create mode 100644 src/module-elasticsuite-analytics/view/adminhtml/web/js/report/customer-group-selector.js create mode 100644 src/module-elasticsuite-tracker/Block/Variables/Page/Customer.php diff --git a/src/module-elasticsuite-analytics/Block/Adminhtml/Report/CustomerGroupSelector.php b/src/module-elasticsuite-analytics/Block/Adminhtml/Report/CustomerGroupSelector.php new file mode 100644 index 000000000..99170e56d --- /dev/null +++ b/src/module-elasticsuite-analytics/Block/Adminhtml/Report/CustomerGroupSelector.php @@ -0,0 +1,60 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ +namespace Smile\ElasticsuiteAnalytics\Block\Adminhtml\Report; + +use Magento\Framework\View\Element\Template; +use Magento\Customer\Model\ResourceModel\Group\CollectionFactory; + +/** + * Block used to display customer group selector in reports. + * + * @SuppressWarnings(PHPMD.CamelCasePropertyName) + * + * @category Smile + * @package Smile\ElasticsuiteAnalytics + * @author Vadym Honcharuk + */ +class CustomerGroupSelector extends Template +{ + /** + * @var CollectionFactory + */ + protected $customerGroupCollectionFactory; + + /** + * CustomerGroupSelector constructor. + * + * @param Template\Context $context The context of the template. + * @param CollectionFactory $customerGroupCollectionFactory Factory for creating customer group collection. + * @param array $data Additional block data. + */ + public function __construct( + Template\Context $context, + CollectionFactory $customerGroupCollectionFactory, + array $data = [] + ) { + $this->customerGroupCollectionFactory = $customerGroupCollectionFactory; + parent::__construct($context, $data); + } + + /** + * Get customer groups in an option array format. + * + * @return array + */ + public function getCustomerGroups() + { + return $this->customerGroupCollectionFactory->create()->toOptionArray(); + } +} diff --git a/src/module-elasticsuite-analytics/Model/Report/Context.php b/src/module-elasticsuite-analytics/Model/Report/Context.php index b326d5585..ede55322b 100644 --- a/src/module-elasticsuite-analytics/Model/Report/Context.php +++ b/src/module-elasticsuite-analytics/Model/Report/Context.php @@ -66,6 +66,16 @@ public function getStoreId() return $this->request->getParam('store'); } + /** + * Get customer group ID. + * + * @return mixed + */ + public function getCustomerGroupId() + { + return $this->request->getParam('customer_group'); + } + /** * Get date range. * diff --git a/src/module-elasticsuite-analytics/Model/Report/Event/CustomerGroupIdFilterQueryProvider.php b/src/module-elasticsuite-analytics/Model/Report/Event/CustomerGroupIdFilterQueryProvider.php new file mode 100644 index 000000000..a1ce55ce5 --- /dev/null +++ b/src/module-elasticsuite-analytics/Model/Report/Event/CustomerGroupIdFilterQueryProvider.php @@ -0,0 +1,74 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ +namespace Smile\ElasticsuiteAnalytics\Model\Report\Event; + +use Smile\ElasticsuiteAnalytics\Model\Report\QueryProviderInterface; +use Smile\ElasticsuiteCore\Search\Request\QueryInterface; +use Smile\ElasticsuiteCore\Search\Request\Query\QueryFactory; +use Smile\ElasticsuiteAnalytics\Model\Report\Context; + +/** + * Customer group id filter query provider. + * + * @category Smile + * @package Smile\ElasticsuiteAnalytics + */ +class CustomerGroupIdFilterQueryProvider implements QueryProviderInterface +{ + /** + * @var QueryFactory + */ + private $queryFactory; + + /** + * @var Context + */ + private $context; + + /** + * DateFilterQueryProvider constructor. + * + * @param QueryFactory $queryFactory Query factory. + * @param Context $context Report context. + */ + public function __construct(QueryFactory $queryFactory, Context $context) + { + $this->queryFactory = $queryFactory; + $this->context = $context; + } + + /** + * {@inheritDoc} + */ + public function getQuery() + { + // Get customer group ID from the context. + $customerGroupId = $this->context->getCustomerGroupId(); + + // Check if customer group ID is set and not 'all'. + if ($customerGroupId !== 'all' && $customerGroupId !== null) { + // Return a TERM query for the customer group ID. + return $this->queryFactory->create( + QueryInterface::TYPE_TERM, + [ + 'field' => 'customer.group_id', + 'value' => (int) $customerGroupId, + ] + ); + } + + // If 'all' is selected or no customer group ID is set, return null (no filtering). + return null; + } +} diff --git a/src/module-elasticsuite-analytics/Model/Report/Session/CustomerGroupIdFilterQueryProvider.php b/src/module-elasticsuite-analytics/Model/Report/Session/CustomerGroupIdFilterQueryProvider.php new file mode 100644 index 000000000..2a5f5b48a --- /dev/null +++ b/src/module-elasticsuite-analytics/Model/Report/Session/CustomerGroupIdFilterQueryProvider.php @@ -0,0 +1,81 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ +namespace Smile\ElasticsuiteAnalytics\Model\Report\Session; + +use Smile\ElasticsuiteAnalytics\Model\Report\QueryProviderInterface; +use Smile\ElasticsuiteCore\Search\Request\QueryInterface; +use Smile\ElasticsuiteCore\Search\Request\Query\QueryFactory; +use Smile\ElasticsuiteAnalytics\Model\Report\Context; + +/** + * Customer group id filter query provider. + * + * @category Smile + * @package Smile\ElasticsuiteAnalytics + */ +class CustomerGroupIdFilterQueryProvider implements QueryProviderInterface +{ + /** + * @var QueryFactory + */ + private $queryFactory; + + /** + * @var Context + */ + private $context; + + /** + * CustomerGroupIdFilterQueryProvider constructor. + * + * @param QueryFactory $queryFactory Query factory. + * @param Context $context Report context. + */ + public function __construct(QueryFactory $queryFactory, Context $context) + { + $this->queryFactory = $queryFactory; + $this->context = $context; + } + + /** + * {@inheritDoc} + */ + public function getQuery() + { + // Get customer group ID from the context. + $customerGroupId = $this->context->getCustomerGroupId(); + + // Check if customer group ID is set and not 'all'. + if ($customerGroupId !== 'all' && $customerGroupId !== null) { + // Return a TERM query for the customer group ID. + return $this->queryFactory->create( + QueryInterface::TYPE_BOOL, + [ + 'must' => [ + $this->queryFactory->create( + QueryInterface::TYPE_TERM, + [ + 'field' => 'customer_group_id', + 'value' => (int) $customerGroupId, + ] + ), + ], + ] + ); + } + + // If 'all' is selected or no customer group ID is set, return null (no filtering). + return null; + } +} diff --git a/src/module-elasticsuite-analytics/etc/di.xml b/src/module-elasticsuite-analytics/etc/di.xml index ef4acea8b..904617e20 100755 --- a/src/module-elasticsuite-analytics/etc/di.xml +++ b/src/module-elasticsuite-analytics/etc/di.xml @@ -23,6 +23,7 @@ Smile\ElasticsuiteAnalytics\Model\Report\Event\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Event\CustomerGroupIdFilterQueryProvider @@ -41,6 +42,7 @@ Smile\ElasticsuiteAnalytics\Model\Report\Session\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Session\CustomerGroupIdFilterQueryProvider tracking_log_session @@ -51,7 +53,7 @@ Smile\ElasticsuiteAnalytics\Model\Search\Usage\Kpi\ConversionRates\SearchRequestBuilder - + @@ -60,10 +62,11 @@ Smile\ElasticsuiteAnalytics\Model\Report\Event\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Event\CustomerGroupIdFilterQueryProvider - + Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms\PopularTerms\SearchRequestBuilder @@ -72,7 +75,7 @@ - + @@ -82,10 +85,11 @@ Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms\SpellcheckedTerms\QueryProvider Smile\ElasticsuiteAnalytics\Model\Report\Event\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Event\CustomerGroupIdFilterQueryProvider - + Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms\SpellcheckedTerms\SearchRequestBuilder @@ -94,7 +98,7 @@ - + @@ -104,10 +108,11 @@ Smile\ElasticsuiteAnalytics\Model\Report\Session\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Session\CustomerGroupIdFilterQueryProvider - + Smile\ElasticsuiteAnalytics\Model\Search\Usage\Terms\NoResultTerms\SearchRequestBuilder @@ -122,6 +127,7 @@ Smile\ElasticsuiteAnalytics\Model\Report\Session\DateFilterQueryProvider + Smile\ElasticsuiteAnalytics\Model\Report\Session\CustomerGroupIdFilterQueryProvider diff --git a/src/module-elasticsuite-analytics/view/adminhtml/layout/smile_elasticsuite_analytics_search_usage.xml b/src/module-elasticsuite-analytics/view/adminhtml/layout/smile_elasticsuite_analytics_search_usage.xml index 087d04dba..a65aeb180 100644 --- a/src/module-elasticsuite-analytics/view/adminhtml/layout/smile_elasticsuite_analytics_search_usage.xml +++ b/src/module-elasticsuite-analytics/view/adminhtml/layout/smile_elasticsuite_analytics_search_usage.xml @@ -17,6 +17,7 @@ diff --git a/src/module-elasticsuite-analytics/view/adminhtml/web/css/source/_module.less b/src/module-elasticsuite-analytics/view/adminhtml/web/css/source/_module.less index fc3f9eafb..48bb9ec20 100644 --- a/src/module-elasticsuite-analytics/view/adminhtml/web/css/source/_module.less +++ b/src/module-elasticsuite-analytics/view/adminhtml/web/css/source/_module.less @@ -69,4 +69,17 @@ } } } + + .customer-group-selector { + color: #41362f; + float: left; + font-size: 1.3rem; + margin-top: .59rem; + margin-left: 4rem; + } + + .customer-group-selector label { + margin-right: 1rem; + font-weight: 700; + } } diff --git a/src/module-elasticsuite-analytics/view/adminhtml/web/js/report/customer-group-selector.js b/src/module-elasticsuite-analytics/view/adminhtml/web/js/report/customer-group-selector.js new file mode 100644 index 000000000..54089bc0e --- /dev/null +++ b/src/module-elasticsuite-analytics/view/adminhtml/web/js/report/customer-group-selector.js @@ -0,0 +1,43 @@ +/** + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade Smile ElasticSuite to newer + * versions in the future. + * + * @category Smile + * @package Smile\ElasticsuiteAnalytics + * @author Vadym Honcharuk + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +define('Smile_ElasticsuiteAnalytics/js/report/customer-group-selector', [ + 'jquery', + 'mage/url' +], function($, urlBuilder) { + 'use strict'; + + return function() { + // !On document ready, set the selected value in the customer group dropdown. + $(document).ready(function() { + var urlParams = new URLSearchParams(window.location.search); + var selectedGroup = urlParams.get('customer_group'); + + if (selectedGroup) { + $('#customer_group').val(selectedGroup); + } + }); + + // Handle the customer group dropdown value change. + $('#customer_group').on('change', function() { + var selectedGroup = $(this).val(); + var newUrl = new URL(window.location.href); + + newUrl.searchParams.set('customer_group', selectedGroup); + + // Redirect to the new URL with the customer group filter. + window.location.href = newUrl.href; + }); + }; +}); + diff --git a/src/module-elasticsuite-tracker/Block/Variables/Page/Customer.php b/src/module-elasticsuite-tracker/Block/Variables/Page/Customer.php new file mode 100644 index 000000000..f9c591f84 --- /dev/null +++ b/src/module-elasticsuite-tracker/Block/Variables/Page/Customer.php @@ -0,0 +1,151 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ +namespace Smile\ElasticsuiteTracker\Block\Variables\Page; + +use Magento\Customer\Model\Group as CustomerGroup; +use Magento\Customer\Model\Session; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Exception\NoSuchEntityException; +use Magento\Framework\Json\Helper\Data; +use Magento\Framework\Module\Manager as ModuleManager; +use Magento\Framework\Registry; +use Magento\Framework\View\Element\Template; +use Smile\ElasticsuiteTracker\Helper\Data as TrackerHelper; + +/** + * Customer variables block for page tracking. + * + * @category Smile + * @package Smile\ElasticsuiteTracker + * @author Vadym Honcharuk + */ +class Customer extends \Smile\ElasticsuiteTracker\Block\Variables\Page\AbstractBlock +{ + /** + * @var Session + */ + private $customerSession; + + /** + * @var ModuleManager + */ + private $moduleManager; + + /** + * @var \Magento\Company\Api\CompanyRepositoryInterface|null + */ + private $companyRepository = null; + + /** + * Customer constructor. + * + * @param Template\Context $context Template Context. + * @param Data $jsonHelper Magento JSON Helper. + * @param TrackerHelper $trackerHelper Smile Tracker Helper. + * @param Registry $registry Magento Core Registry. + * @param Session $customerSession Customer Session. + * @param ModuleManager $moduleManager Magento Module Manager. + * @param array $data Additional data. + * @throws LocalizedException + */ + public function __construct( + Template\Context $context, + Data $jsonHelper, + TrackerHelper $trackerHelper, + Registry $registry, + Session $customerSession, + ModuleManager $moduleManager, + array $data = [] + ) { + $this->customerSession = $customerSession; + $this->moduleManager = $moduleManager; + + // Check if Magento_Company module is enabled before attempting to load the repository. + if ($this->moduleManager->isEnabled('Magento_Company')) { + if (interface_exists('\Magento\Company\Api\CompanyRepositoryInterface')) { + $this->companyRepository = $context->getObjectManager()->get(\Magento\Company\Api\CompanyRepositoryInterface::class); + } else { + throw new LocalizedException(__('CompanyRepositoryInterface is not available.')); + } + } + + parent::__construct($context, $jsonHelper, $trackerHelper, $registry, $data); + } + + /** + * Returns an array of customer-related variables (customer_group_id and company_id). + * + * @return array + */ + public function getVariables() + { + return array_merge( + $this->getCustomerGroupId(), + $this->getCustomerCompanyId() + ); + } + + /** + * Retrieve customer group ID. + * If the customer is logged in, fetch their group ID. + * Otherwise, assign the 'NOT LOGGED IN' group ID. + * + * @return array + */ + private function getCustomerGroupId() + { + $variables = []; + + if ($this->customerSession->isLoggedIn()) { + $customer = $this->customerSession->getCustomer(); + $variables['customer.group_id'] = $customer->getGroupId(); + } else { + // Guest user (NOT LOGGED IN). + $variables['customer.group_id'] = CustomerGroup::NOT_LOGGED_IN_ID; + } + + return $variables; + } + + /** + * Retrieve customer company ID. + * If the customer is logged in and Magento_Company module is enabled, fetch the company ID. + * Otherwise, return null for guests or when the module is not available. + * + * @return array + */ + private function getCustomerCompanyId() + { + $variables = []; + + // Check if the customer is logged in and Magento_Company is enabled. + if ($this->customerSession->isLoggedIn() && $this->companyRepository) { + $customer = $this->customerSession->getCustomer(); + + try { + // Retrieve company information by customer ID. + $company = $this->companyRepository->getByCustomerId($customer->getId()); + $variables['customer.company_id'] = $company->getId(); + } catch (NoSuchEntityException $e) { + // No company found for this customer. + $variables['customer.company_id'] = null; + } + } else { + // No company for guests or when the module is not available. + $variables['customer.company_id'] = null; + } + + return $variables; + } +} diff --git a/src/module-elasticsuite-tracker/etc/elasticsuite_indices.xml b/src/module-elasticsuite-tracker/etc/elasticsuite_indices.xml index 5cf078b30..8fd7dd34a 100644 --- a/src/module-elasticsuite-tracker/etc/elasticsuite_indices.xml +++ b/src/module-elasticsuite-tracker/etc/elasticsuite_indices.xml @@ -29,6 +29,10 @@ + + + + @@ -120,6 +124,8 @@ + + diff --git a/src/module-elasticsuite-tracker/view/frontend/layout/default.xml b/src/module-elasticsuite-tracker/view/frontend/layout/default.xml index ea0b0275d..85dcf343c 100644 --- a/src/module-elasticsuite-tracker/view/frontend/layout/default.xml +++ b/src/module-elasticsuite-tracker/view/frontend/layout/default.xml @@ -41,6 +41,9 @@ +