Add background job to track historical WooCommerce revenues
[MAILPOET-1857]
This commit is contained in:
@ -54,5 +54,6 @@ class Daemon {
|
|||||||
yield $this->workers_factory->createInactiveSubscribersWorker($this->timer);
|
yield $this->workers_factory->createInactiveSubscribersWorker($this->timer);
|
||||||
yield $this->workers_factory->createWooCommerceSyncWorker($this->timer);
|
yield $this->workers_factory->createWooCommerceSyncWorker($this->timer);
|
||||||
yield $this->workers_factory->createAuthorizedSendingEmailsCheckWorker($this->timer);
|
yield $this->workers_factory->createAuthorizedSendingEmailsCheckWorker($this->timer);
|
||||||
|
yield $this->workers_factory->createWooCommerceOrdersWorker($this->timer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
70
lib/Cron/Workers/WooCommerceOrders.php
Normal file
70
lib/Cron/Workers/WooCommerceOrders.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Cron\Workers;
|
||||||
|
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use MailPoet\Models\ScheduledTask;
|
||||||
|
use MailPoet\Models\StatisticsClicks;
|
||||||
|
use MailPoet\Statistics\Track\WooCommercePurchases;
|
||||||
|
use MailPoet\WooCommerce\Helper as WCHelper;
|
||||||
|
use MailPoet\WP\Functions as WPFunctions;
|
||||||
|
|
||||||
|
if (!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class WooCommerceOrders extends SimpleWorker {
|
||||||
|
const TASK_TYPE = 'woocommerce_orders';
|
||||||
|
const BATCH_SIZE = 20;
|
||||||
|
|
||||||
|
/** @var WCHelper */
|
||||||
|
private $woocommerce_helper;
|
||||||
|
|
||||||
|
/** @var WooCommercePurchases */
|
||||||
|
private $woocommerce_purchases;
|
||||||
|
|
||||||
|
function __construct(WCHelper $woocommerce_helper, WooCommercePurchases $woocommerce_purchases, $timer = false) {
|
||||||
|
$this->woocommerce_helper = $woocommerce_helper;
|
||||||
|
$this->woocommerce_purchases = $woocommerce_purchases;
|
||||||
|
parent::__construct($timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkProcessingRequirements() {
|
||||||
|
return $this->woocommerce_helper->isWooCommerceActive() && empty(self::getCompletedTasks()); // run only once
|
||||||
|
}
|
||||||
|
|
||||||
|
function processTaskStrategy(ScheduledTask $task) {
|
||||||
|
$oldest_click = StatisticsClicks::orderByAsc('created_at')->limit(1)->findOne();
|
||||||
|
if (!$oldest_click) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// continue from 'last_id' processed by previous run
|
||||||
|
$meta = $task->getMeta();
|
||||||
|
$last_id = isset($meta['last_id']) ? $meta['last_id'] : 0;
|
||||||
|
add_filter('posts_where', function ($where = '') use ($last_id) {
|
||||||
|
return $where . ' AND wp_posts.ID > ' . $last_id;
|
||||||
|
}, 10, 2);
|
||||||
|
|
||||||
|
$order_ids = $this->woocommerce_helper->wcGetOrders([
|
||||||
|
'status' => 'completed',
|
||||||
|
'date_completed' => '>=' . $oldest_click->created_at,
|
||||||
|
'orderby' => 'ID',
|
||||||
|
'order' => 'ASC',
|
||||||
|
'limit' => self::BATCH_SIZE,
|
||||||
|
'return' => 'ids',
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (empty($order_ids)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($order_ids as $order_id) {
|
||||||
|
$this->woocommerce_purchases->trackPurchase($order_id, false);
|
||||||
|
}
|
||||||
|
$task->meta = ['last_id' => end($order_ids)];
|
||||||
|
$task->save();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function getNextRunDate() {
|
||||||
|
return Carbon::createFromTimestamp(WPFunctions::get()->currentTime('timestamp')); // schedule immediately
|
||||||
|
}
|
||||||
|
}
|
@ -17,6 +17,7 @@ use MailPoet\Features\FeaturesController;
|
|||||||
use MailPoet\Segments\SubscribersFinder;
|
use MailPoet\Segments\SubscribersFinder;
|
||||||
use MailPoet\Segments\WooCommerce as WooCommerceSegment;
|
use MailPoet\Segments\WooCommerce as WooCommerceSegment;
|
||||||
use MailPoet\Services\AuthorizedEmailsController;
|
use MailPoet\Services\AuthorizedEmailsController;
|
||||||
|
use MailPoet\Statistics\Track\WooCommercePurchases;
|
||||||
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
use MailPoet\WooCommerce\Helper as WooCommerceHelper;
|
||||||
use MailPoet\Mailer\Mailer;
|
use MailPoet\Mailer\Mailer;
|
||||||
use MailPoet\Settings\SettingsController;
|
use MailPoet\Settings\SettingsController;
|
||||||
@ -48,6 +49,9 @@ class WorkersFactory {
|
|||||||
/** @var WooCommerceHelper */
|
/** @var WooCommerceHelper */
|
||||||
private $woocommerce_helper;
|
private $woocommerce_helper;
|
||||||
|
|
||||||
|
/** @var WooCommercePurchases */
|
||||||
|
private $woocommerce_purchases;
|
||||||
|
|
||||||
/** @var AuthorizedEmailsController */
|
/** @var AuthorizedEmailsController */
|
||||||
private $authorized_emails_controller;
|
private $authorized_emails_controller;
|
||||||
|
|
||||||
@ -69,6 +73,7 @@ class WorkersFactory {
|
|||||||
WooCommerceSegment $woocommerce_segment,
|
WooCommerceSegment $woocommerce_segment,
|
||||||
InactiveSubscribersController $inactive_subscribers_controller,
|
InactiveSubscribersController $inactive_subscribers_controller,
|
||||||
WooCommerceHelper $woocommerce_helper,
|
WooCommerceHelper $woocommerce_helper,
|
||||||
|
WooCommercePurchases $woocommerce_purchases,
|
||||||
AuthorizedEmailsController $authorized_emails_controller,
|
AuthorizedEmailsController $authorized_emails_controller,
|
||||||
SubscribersFinder $subscribers_finder
|
SubscribersFinder $subscribers_finder
|
||||||
) {
|
) {
|
||||||
@ -81,6 +86,7 @@ class WorkersFactory {
|
|||||||
$this->woocommerce_segment = $woocommerce_segment;
|
$this->woocommerce_segment = $woocommerce_segment;
|
||||||
$this->inactive_subscribers_controller = $inactive_subscribers_controller;
|
$this->inactive_subscribers_controller = $inactive_subscribers_controller;
|
||||||
$this->woocommerce_helper = $woocommerce_helper;
|
$this->woocommerce_helper = $woocommerce_helper;
|
||||||
|
$this->woocommerce_purchases = $woocommerce_purchases;
|
||||||
$this->authorized_emails_controller = $authorized_emails_controller;
|
$this->authorized_emails_controller = $authorized_emails_controller;
|
||||||
$this->subscribers_finder = $subscribers_finder;
|
$this->subscribers_finder = $subscribers_finder;
|
||||||
}
|
}
|
||||||
@ -139,4 +145,8 @@ class WorkersFactory {
|
|||||||
return new AuthorizedSendingEmailsCheck($this->authorized_emails_controller, $timer);
|
return new AuthorizedSendingEmailsCheck($this->authorized_emails_controller, $timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return WooCommerceOrders */
|
||||||
|
function createWooCommerceOrdersWorker($timer) {
|
||||||
|
return new WooCommerceOrders($this->woocommerce_helper, $this->woocommerce_purchases, $timer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,23 +19,26 @@ class WooCommercePurchases {
|
|||||||
$this->woocommerce_helper = $woocommerce_helper;
|
$this->woocommerce_helper = $woocommerce_helper;
|
||||||
}
|
}
|
||||||
|
|
||||||
function trackPurchase($id) {
|
function trackPurchase($id, $use_cookies = true) {
|
||||||
$order = $this->woocommerce_helper->wcGetOrder($id);
|
$order = $this->woocommerce_helper->wcGetOrder($id);
|
||||||
if (!$order instanceof WC_Order) {
|
if (!$order instanceof WC_Order) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$order_email_clicks = $this->getClicks($order->get_billing_email(), $order->get_date_created());
|
|
||||||
$cookie_email_clicks = $this->getClicks($this->getSubscriberEmailFromCookie(), $order->get_date_created());
|
|
||||||
|
|
||||||
// track purchases from all clicks matched by order email
|
// track purchases from all clicks matched by order email
|
||||||
$processed_newsletter_ids_map = [];
|
$processed_newsletter_ids_map = [];
|
||||||
|
$order_email_clicks = $this->getClicks($order->get_billing_email(), $order->get_date_created());
|
||||||
foreach ($order_email_clicks as $click) {
|
foreach ($order_email_clicks as $click) {
|
||||||
StatisticsWooCommercePurchases::createOrUpdateByClickAndOrder($click, $order);
|
StatisticsWooCommercePurchases::createOrUpdateByClickAndOrder($click, $order);
|
||||||
$processed_newsletter_ids_map[$click->newsletter_id] = true;
|
$processed_newsletter_ids_map[$click->newsletter_id] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$use_cookies) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// track purchases from clicks matched by cookie email (only for newsletters not tracked by order)
|
// track purchases from clicks matched by cookie email (only for newsletters not tracked by order)
|
||||||
|
$cookie_email_clicks = $this->getClicks($this->getSubscriberEmailFromCookie(), $order->get_date_created());
|
||||||
foreach ($cookie_email_clicks as $click) {
|
foreach ($cookie_email_clicks as $click) {
|
||||||
if (isset($processed_newsletter_ids_map[$click->newsletter_id])) {
|
if (isset($processed_newsletter_ids_map[$click->newsletter_id])) {
|
||||||
continue; // do not track click for newsletters that were already tracked by order email
|
continue; // do not track click for newsletters that were already tracked by order email
|
||||||
|
@ -27,6 +27,10 @@ class Helper {
|
|||||||
return wc_get_order($order);
|
return wc_get_order($order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wcGetOrders(array $args) {
|
||||||
|
return wc_get_orders($args);
|
||||||
|
}
|
||||||
|
|
||||||
function wcPrice($price, array $args = []) {
|
function wcPrice($price, array $args = []) {
|
||||||
return wc_price($price, $args);
|
return wc_price($price, $args);
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,14 @@ function wc_get_order($order = false) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $args
|
||||||
|
* @return WC_Order[]|int[]|\stdClass
|
||||||
|
*/
|
||||||
|
function wc_get_orders($args) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
function wc_price(float $price, array $args = []): string {
|
function wc_price(float $price, array $args = []): string {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -265,6 +265,7 @@ class DaemonHttpRunnerTest extends \MailPoetTest {
|
|||||||
'createExportFilesCleanupWorker' => $worker,
|
'createExportFilesCleanupWorker' => $worker,
|
||||||
'createInactiveSubscribersWorker' => $worker,
|
'createInactiveSubscribersWorker' => $worker,
|
||||||
'createAuthorizedSendingEmailsCheckWorker' => $worker,
|
'createAuthorizedSendingEmailsCheckWorker' => $worker,
|
||||||
|
'createWooCommerceOrdersWorker' => $worker,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,7 @@ class DaemonTest extends \MailPoetTest {
|
|||||||
'createExportFilesCleanupWorker' => $this->createSimpleWorkerMock(),
|
'createExportFilesCleanupWorker' => $this->createSimpleWorkerMock(),
|
||||||
'createInactiveSubscribersWorker' => $this->createSimpleWorkerMock(),
|
'createInactiveSubscribersWorker' => $this->createSimpleWorkerMock(),
|
||||||
'createAuthorizedSendingEmailsCheckWorker' => $this->createSimpleWorkerMock(),
|
'createAuthorizedSendingEmailsCheckWorker' => $this->createSimpleWorkerMock(),
|
||||||
|
'createWooCommerceOrdersWorker' => $this->createSimpleWorkerMock(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user