Add dynamic filter for WC total spent

[MAILPOET-3227]
This commit is contained in:
Jan Lysý
2021-04-21 11:18:09 +02:00
committed by Veljko V
parent d471e19f92
commit f63865b94c
6 changed files with 82 additions and 0 deletions

View File

@ -139,6 +139,8 @@ class DynamicSegments extends APIEndpoint {
return WPFunctions::get()->__('Please fill all required values.', 'mailpoet');
case InvalidFilterException::MISSING_NUMBER_OF_ORDERS_FIELDS:
return WPFunctions::get()->__('Please select a type for the comparison, a number of orders and a number of days.', 'mailpoet');
case InvalidFilterException::MISSING_TOTAL_SPENT_FIELDS:
return WPFunctions::get()->__('Please select a type for the comparison, an amount and a number of days.', 'mailpoet');
default:
return WPFunctions::get()->__('An error occurred while saving data.', 'mailpoet');
}

View File

@ -275,6 +275,7 @@ class ContainerConfigurator implements IContainerConfigurator {
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceTotalSpent::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\Filters\WooCommerceSubscription::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\SegmentSaveController::class)->setPublic(true);
$container->autowire(\MailPoet\Segments\DynamicSegments\FilterDataMapper::class)->setPublic(true);

View File

@ -16,5 +16,6 @@ class InvalidFilterException extends InvalidStateException {
const INVALID_EMAIL_ACTION = 8;
const MISSING_VALUE = 9;
const MISSING_NUMBER_OF_ORDERS_FIELDS = 10;
const MISSING_TOTAL_SPENT_FIELDS = 11;
};

View File

@ -10,6 +10,7 @@ use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceSubscription;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceTotalSpent;
class FilterDataMapper {
public function map(array $data = []): DynamicSegmentFilterData {
@ -98,6 +99,13 @@ class FilterDataMapper {
$filterData['number_of_orders_type'] = $data['number_of_orders_type'];
$filterData['number_of_orders_count'] = $data['number_of_orders_count'];
$filterData['number_of_orders_days'] = $data['number_of_orders_days'];
} elseif ($data['action'] === WooCommerceTotalSpent::ACTION_TOTAL_SPENT) {
if (!isset($data['total_spent_type']) || !isset($data['total_spent_amount']) || !isset($data['total_spent_days'])) {
throw new InvalidFilterException('Missing required fields', InvalidFilterException::MISSING_TOTAL_SPENT_FIELDS);
}
$filterData['total_spent_type'] = $data['total_spent_type'];
$filterData['total_spent_amount'] = $data['total_spent_amount'];
$filterData['total_spent_days'] = $data['total_spent_days'];
} else {
throw new InvalidFilterException("Unknown action " . $data['action'], InvalidFilterException::MISSING_ACTION);
}

View File

@ -14,6 +14,7 @@ use MailPoet\Segments\DynamicSegments\Filters\WooCommerceCategory;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceNumberOfOrders;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceProduct;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceSubscription;
use MailPoet\Segments\DynamicSegments\Filters\WooCommerceTotalSpent;
use MailPoet\Segments\SegmentDependencyValidator;
use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder;
use MailPoetVendor\Doctrine\ORM\EntityManager;
@ -34,6 +35,9 @@ class FilterHandler {
/** @var WooCommerceNumberOfOrders */
private $wooCommerceNumberOfOrders;
/** @var WooCommerceTotalSpent */
private $wooCommerceTotalSpent;
/** @var WooCommerceSubscription */
private $wooCommerceSubscription;
@ -54,6 +58,7 @@ class FilterHandler {
WooCommerceCategory $wooCommerceCategory,
EmailOpensAbsoluteCountAction $emailOpensAbsoluteCount,
WooCommerceNumberOfOrders $wooCommerceNumberOfOrders,
WooCommerceTotalSpent $wooCommerceTotalSpent,
WooCommerceSubscription $wooCommerceSubscription,
SegmentDependencyValidator $segmentDependencyValidator
) {
@ -66,6 +71,7 @@ class FilterHandler {
$this->entityManager = $entityManager;
$this->segmentDependencyValidator = $segmentDependencyValidator;
$this->emailOpensAbsoluteCount = $emailOpensAbsoluteCount;
$this->wooCommerceTotalSpent = $wooCommerceTotalSpent;
}
public function apply(QueryBuilder $queryBuilder, SegmentEntity $segment): QueryBuilder {
@ -143,6 +149,8 @@ class FilterHandler {
return $this->wooCommerceProduct->apply($queryBuilder, $filter);
} elseif ($action === WooCommerceNumberOfOrders::ACTION_NUMBER_OF_ORDERS) {
return $this->wooCommerceNumberOfOrders->apply($queryBuilder, $filter);
} elseif ($action === WooCommerceTotalSpent::ACTION_TOTAL_SPENT) {
return $this->wooCommerceTotalSpent->apply($queryBuilder, $filter);
}
return $this->wooCommerceCategory->apply($queryBuilder, $filter);
default:

View File

@ -0,0 +1,62 @@
<?php
namespace MailPoet\Segments\DynamicSegments\Filters;
use MailPoet\Entities\DynamicSegmentFilterEntity;
use MailPoet\Entities\SubscriberEntity;
use MailPoetVendor\Carbon\Carbon;
use MailPoetVendor\Doctrine\DBAL\Query\QueryBuilder;
use MailPoetVendor\Doctrine\ORM\EntityManager;
class WooCommerceTotalSpent implements Filter {
const ACTION_TOTAL_SPENT = 'totalSpent';
/** @var EntityManager */
private $entityManager;
public function __construct(EntityManager $entityManager) {
$this->entityManager = $entityManager;
}
public function apply(QueryBuilder $queryBuilder, DynamicSegmentFilterEntity $filter): QueryBuilder {
global $wpdb;
$subscribersTable = $this->entityManager->getClassMetadata(SubscriberEntity::class)->getTableName();
$filterData = $filter->getFilterData();
$type = $filterData->getParam('total_spent_type');
$amount = $filterData->getParam('total_spent_amount');
$days = $filterData->getParam('total_spent_days');
$date = Carbon::now()->subDays($days);
$queryBuilder->innerJoin(
$subscribersTable,
$wpdb->postmeta,
'postmeta',
"postmeta.meta_key = '_customer_user' AND $subscribersTable.wp_user_id=postmeta.meta_value"
)->leftJoin(
'postmeta',
$wpdb->posts,
'posts',
'posts.ID = postmeta.post_id AND posts.post_date >= :date' . $filter->getId() . ' AND postmeta.post_id NOT IN ( SELECT id FROM ' . $wpdb->posts . ' as p WHERE p.post_status IN ("wc-cancelled", "wc-failed"))'
)->leftJoin(
'posts',
$wpdb->postmeta,
'order_total',
"posts.ID = order_total.post_id AND order_total.meta_key = '_order_total'"
)->setParameter(
'date' . $filter->getId(), $date->toDateTimeString()
)->groupBy(
'inner_subscriber_id'
);
if ($type === '>') {
$queryBuilder->having('SUM(order_total.meta_value) > :amount' . $filter->getId());
} elseif ($type === '<') {
$queryBuilder->having('SUM(order_total.meta_value) < :amount' . $filter->getId());
}
$queryBuilder->setParameter('amount' . $filter->getId(), $amount);
return $queryBuilder;
}
}