Skip to content

Commit

Permalink
[PO-187]("Add setting for age of orders to be picked in CancelPending…
Browse files Browse the repository at this point in the history
…Order cron.") (#507)

* PO-187("Add setting for age of orders to be picked in CancelPendingOrder cron.")

* addressed review comments

* added debug log

* addressed review comments

* addressed review comments

* Update FormFieldTrack.php

* removed redundant debug logs

* label name minor fix
  • Loading branch information
rohitcbr authored Nov 21, 2024
1 parent 93e38ed commit a61b7c3
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 41 deletions.
107 changes: 72 additions & 35 deletions Cron/CancelPendingOrders.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class CancelPendingOrders {
*/
protected const STATE_NEW = 'new';

protected const PENDING_ORDER_CRON = 'pending_order_cron';

protected const RESET_CART_CRON = 'reset_cart_cron';

/**
* @var \Magento\Framework\Api\SortOrderBuilder
*/
Expand Down Expand Up @@ -60,6 +64,10 @@ class CancelPendingOrders {
*/
protected $debug;

protected $pendingOrderAge;

protected const PENDING_ORDER_MAXIMUM_AGE_DEFAULT = 43200;

/**
* CancelOrder constructor.
* @param \Magento\Sales\Api\OrderRepositoryInterface $orderRepository
Expand Down Expand Up @@ -87,6 +95,7 @@ public function __construct(
$this->logger = $logger;
$this->isCancelPendingOrderCronEnabled = $this->config->isCancelPendingOrderCronEnabled();
$this->pendingOrderTimeout = ($this->config->getPendingOrderTimeout() > 0) ? $this->config->getPendingOrderTimeout() : 30;
$this->pendingOrderAge = (($this->config->getPendingOrderAge() > 0) && ($this->config->getPendingOrderAge() < self::PENDING_ORDER_MAXIMUM_AGE_DEFAULT)) ? $this->config->getPendingOrderAge() : self::PENDING_ORDER_MAXIMUM_AGE_DEFAULT;
$this->isCancelResetCartCronEnabled = $this->config->isCancelResetCartOrderCronEnabled();
$this->resetCartOrderTimeout = ($this->config->getResetCartOrderTimeout() > 0) ? $this->config->getResetCartOrderTimeout() : 30;
$this->debug = $debug;
Expand All @@ -99,26 +108,14 @@ public function execute()
&& $this->pendingOrderTimeout > 0)
{
$this->logger->info("Cronjob: Cancel Pending Order Cron started.");
$dateTimeCheck = date('Y-m-d H:i:s', strtotime('-' . $this->pendingOrderTimeout . ' minutes'));
$sortOrder = $this->sortOrderBuilder->setField('entity_id')->setDirection('DESC')->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(
'updated_at',
$dateTimeCheck,
'lt'
)->addFilter(
'status',
static::STATUS_PENDING,
'eq'
)->setSortOrders(
[$sortOrder]
)->create();

$searchCriteria = $this->getSearchCriteria(self::PENDING_ORDER_CRON, $this->pendingOrderTimeout, $this->pendingOrderAge, null, self::STATUS_PENDING);

$orders = $this->orderRepository->getList($searchCriteria);
foreach ($orders->getItems() as $order)
{
if ($order->getPayment()->getMethod() === 'razorpay') {
$this->debug->log("Cronjob: Magento Order Id = " . $order->getIncrementId() . " picked for cancelation.");
$this->debug->log("Cronjob: Magento Order Id = " . $order->getIncrementId() . " picked for cancellation.");

$this->cancelOrder($order);
}
Expand All @@ -135,31 +132,15 @@ public function execute()
&& $this->resetCartOrderTimeout > 0)
{
$this->logger->info("Cronjob: Cancel Reset Cart Order Cron started.");
$dateTimeCheck = date('Y-m-d H:i:s', strtotime('-' . $this->resetCartOrderTimeout . ' minutes'));
$sortOrder = $this->sortOrderBuilder->setField('entity_id')->setDirection('DESC')->create();
$searchCriteria = $this->searchCriteriaBuilder
->addFilter(
'updated_at',
$dateTimeCheck,
'lt'
)->addFilter(
'state',
static::STATE_NEW,
'eq'
)->addFilter(
'status',
static::STATUS_CANCELED,
'eq'
)->setSortOrders(
[$sortOrder]
)->create();

$searchCriteria = $this->getSearchCriteria(self::RESET_CART_CRON, $this->resetCartOrderTimeout, null, self::STATE_NEW, self::STATUS_CANCELED);

$orders = $this->orderRepository->getList($searchCriteria);

foreach ($orders->getItems() as $order)
{
if ($order->getPayment()->getMethod() === 'razorpay') {
$this->debug->log("Cronjob: Magento Order Id = " . $order->getIncrementId() . " picked for cancelation in reset cart cron.");
$this->debug->log("Cronjob: Magento Order Id = " . $order->getIncrementId() . " picked for cancellation in reset cart cron.");

$this->cancelOrder($order);
}
Expand All @@ -177,7 +158,7 @@ private function cancelOrder($order)
if ($order)
{
if ($order->canCancel() and
$this->isOrderAlreadyPaid($order->getEntityId()) === false)
$this->isOrderAlreadyPaid($order->getEntityId()) === false)
{
$this->logger->info("Cronjob: Cancelling Order ID: " . $order->getIncrementId());

Expand All @@ -203,4 +184,60 @@ private function isOrderAlreadyPaid($entity_id)

return ($orderLinkData->getRzpWebhookNotifiedAt() !== null);
}

private function getSearchCriteria($cronName, $orderTimeout, $orderAge, $orderState, $orderStatus)
{
$searchCriteria = null;
if ($cronName === self::PENDING_ORDER_CRON)
{
$dateTimeCheck = date('Y-m-d H:i:s', strtotime('-' . $orderTimeout . ' minutes'));
$sortOrder = $this->sortOrderBuilder->setField('entity_id')->setDirection('DESC')->create();

if (($orderAge !== null) && ($orderAge > $orderTimeout))
{
$pendingOrderAgeCheck = date('Y-m-d H:i:s', strtotime('-' . $orderAge . ' minutes'));

$searchCriteria = $this->searchCriteriaBuilder
->addFilter(
'updated_at',
$dateTimeCheck,
'lt'
)->addFilter(
'updated_at',
$pendingOrderAgeCheck,
'gt'
)->addFilter(
'status',
$orderStatus,
'eq'
)->setSortOrders(
[$sortOrder]
)->create();
}
}
else if ($cronName === self::RESET_CART_CRON
&& $orderState !== null)
{
$dateTimeCheck = date('Y-m-d H:i:s', strtotime('-' . $orderTimeout . ' minutes'));
$sortOrder = $this->sortOrderBuilder->setField('entity_id')->setDirection('DESC')->create();

$searchCriteria = $this->searchCriteriaBuilder
->addFilter(
'updated_at',
$dateTimeCheck,
'lt'
)->addFilter(
'state',
$orderState,
'eq'
)->addFilter(
'status',
$orderStatus,
'eq'
)->setSortOrders(
[$sortOrder]
)->create();
}
return $searchCriteria;
}
}
6 changes: 6 additions & 0 deletions Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Config
const WEBHOOK_SECRET = 'webhook_secret';
const ENABLE_PENDING_ORDERS_CRON = 'enable_pending_orders_cron';
const PENDING_ORDER_TIMEOUT = 'pending_orders_timeout';
const PENDING_ORDER_AGE = 'pending_orders_age';
const ENABLE_RESET_CART_CRON = 'enable_reset_cart_cron';
const RESET_CART_ORDERS_TIMEOUT = 'reset_cart_orders_timeout';
const DISABLE_UPGRADE_NOTICE = 'disable_upgrade_notice';
Expand Down Expand Up @@ -88,6 +89,11 @@ public function getPendingOrderTimeout()
return (int) $this->getConfigData(self::PENDING_ORDER_TIMEOUT);
}

public function getPendingOrderAge()
{
return (int) $this->getConfigData(self::PENDING_ORDER_AGE);
}

public function isCancelResetCartOrderCronEnabled()
{
return (bool) (int) $this->getConfigData(self::ENABLE_RESET_CART_CRON, $this->storeId);
Expand Down
70 changes: 66 additions & 4 deletions Model/FormFieldTrack.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,9 +134,54 @@ protected function _getElementHtml(AbstractElement $element)
url: '". $baseUrl ."razorpay/payment/FormDataAnalytics',
type: 'POST',
dataType: 'json',
data: {
event: 'Form Field Validation Error',
properties: validationData
data: {
event: 'Form Field Validation Error',
properties: validationData
}
})
}
})
}
else if (elementId == 'payment_us_razorpay_pending_orders_age')
{
element.blur(function(){
let elementVal = String(element.val())
let pendingOrderTimeoutElement = $('#' + 'payment_us_razorpay_pending_orders_timeout')
let pendingOrderTimeoutValue = String(pendingOrderTimeoutElement.val())
// Validations
let checkRequiredEntryBool = checkRequiredEntry(elementVal)
let checkIfValidDigitsBool = checkIfValidDigits(elementVal)
let checkIfNonNegativeBool = checkIfNonNegative(elementVal)
let checkIfInNumberRangeBool = checkIfInNumberRange(elementVal, 60, 43200)
let checkIfPendingOrderAgeGreaterThanTimeoutBool = checkIfPendingOrderAgeGreaterThanTimeout(elementVal, pendingOrderTimeoutValue)
if (
!checkRequiredEntryBool ||
!checkIfValidDigitsBool ||
!checkIfNonNegativeBool ||
!checkIfInNumberRangeBool ||
!checkIfPendingOrderAgeGreaterThanTimeoutBool
){
let validationData = {
'store_name' : storeName,
'field_name' : fieldName,
'field_type' : fieldType,
'required-entry' : checkRequiredEntryBool,
'validate-digits' : checkIfValidDigitsBool,
'validate-not-negative-number' : checkIfNonNegativeBool,
'digits-range-60-43200' : checkIfInNumberRangeBool,
'check-if-pending-order-age-greater-than-timeout' : checkIfPendingOrderAgeGreaterThanTimeoutBool
}
// Send event
$.ajax({
url: '". $baseUrl ."razorpay/payment/FormDataAnalytics',
type: 'POST',
dataType: 'json',
data: {
event: 'Form Field Validation Error',
properties: validationData
}
})
}
Expand All @@ -156,6 +201,7 @@ protected function _getElementHtml(AbstractElement $element)
'payment_us_razorpay_order_status' : $('#payment_us_razorpay_order_status').val(),
'payment_us_razorpay_auto_invoice' : $('#payment_us_razorpay_auto_invoice').val(),
'payment_us_razorpay_pending_orders_timeout' : $('#payment_us_razorpay_pending_orders_timeout').val(),
'payment_us_razorpay_pending_orders_age' : $('#payment_us_razorpay_pending_orders_age').val(),
}
let resultMapObject = new Map()
Expand All @@ -167,7 +213,8 @@ protected function _getElementHtml(AbstractElement $element)
row == 'payment_us_razorpay_key_secret' ||
row == 'payment_us_razorpay_order_status' ||
row == 'payment_us_razorpay_auto_invoice' ||
row == 'payment_us_razorpay_pending_orders_timeout'
row == 'payment_us_razorpay_pending_orders_timeout' ||
row == 'payment_us_razorpay_pending_orders_age'
)
{
// Check for empty fields
Expand Down Expand Up @@ -209,6 +256,13 @@ protected function _getElementHtml(AbstractElement $element)
})
}
});
require(['jquery', 'mage/validation'], function($) {
$.validator.addMethod('validate-age-timeout', function(value, element) {
var age = parseFloat($('#' + 'payment_us_razorpay_pending_orders_age').val());
var timeout = parseFloat($('#' + 'payment_us_razorpay_pending_orders_timeout').val());
return isNaN(age) || age > timeout;
}, $.mage.__('Pending Orders Age must be greater than Pending Orders Timeout.'));
});
//]]>
</script>
";
Expand Down Expand Up @@ -242,6 +296,14 @@ function checkIfInNumberRange(field, x, y)
return (fieldNum >= x && fieldNum <=y)? true : false;
}
function checkIfPendingOrderAgeGreaterThanTimeout(pendingOrderAge, pendingOrderTimeout)
{
let pendingOrderAgeInt = parseInt(pendingOrderAge);
let pendingOrderTimeoutInt = parseInt(pendingOrderTimeout);
return (pendingOrderAgeInt > pendingOrderTimeoutInt)? true : false;
}
";
}
}
15 changes: 13 additions & 2 deletions etc/adminhtml/system.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,25 @@
<validate>required-entry validate-digits validate-not-negative-number validate-digits-range digits-range-20-43200</validate>
</field>

<field id="enable_reset_cart_cron" translate="label" type="select" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<field id="pending_orders_age" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Pending Orders Maximum Age</label>
<comment>Optional. Set maximum age of pending orders in minutes. Age can be updated between range of 60 to 43200 minutes. This will enable cron for moving pending orders which are under the given age to Cancel status. Please make sure to put maximum age value greater than Pending Orders Timeout value.</comment>
<config_path>payment/razorpay/pending_orders_age</config_path>
<depends>
<field id="enable_pending_orders_cron">1</field>
</depends>
<frontend_model>Razorpay\Magento\Model\FormFieldTrack</frontend_model>
<validate>validate-digits validate-not-negative-number validate-digits-range digits-range-60-43200 validate-age-timeout</validate>
</field>

<field id="enable_reset_cart_cron" translate="label" type="select" sortOrder="7" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Reset cart cron enabled</label>
<source_model>Magento\Config\Model\Config\Source\Yesno</source_model>
<frontend_model>Razorpay\Magento\Model\EnableResetCartOrdersCron</frontend_model>
<config_path>payment/razorpay/enable_reset_cart_cron</config_path>
</field>

<field id="reset_cart_orders_timeout" translate="label" type="text" sortOrder="6" showInDefault="1" showInWebsite="0" showInStore="0">
<field id="reset_cart_orders_timeout" translate="label" type="text" sortOrder="8" showInDefault="1" showInWebsite="0" showInStore="0">
<label>Reset cart timeout</label>
<comment>Set timeout in minutes (default : 30 minutes). Timeout can be updated between the range of 20 minutes and 43200 minutes (30 days). This will enable cron for resetting the cart from new to canceled status for a given timeout.</comment>
<config_path>payment/razorpay/reset_cart_orders_timeout</config_path>
Expand Down
1 change: 1 addition & 0 deletions etc/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<webhook_triggered_at>0</webhook_triggered_at>
<enable_pending_orders_cron>1</enable_pending_orders_cron>
<pending_orders_timeout>30</pending_orders_timeout>
<pending_orders_age>43200</pending_orders_age>
<enable_reset_cart_cron>0</enable_reset_cart_cron>
<reset_cart_orders_timeout>30</reset_cart_orders_timeout>
<enable_custom_paid_order_status>0</enable_custom_paid_order_status>
Expand Down
8 changes: 8 additions & 0 deletions view/adminhtml/requirejs-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
var config = {
paths: {
"validation": "Razorpay_Magento/js/validation"
},
shim: {
"validation": ["jquery"]
}
};

0 comments on commit a61b7c3

Please sign in to comment.