diff --git a/Cron/CancelPendingOrders.php b/Cron/CancelPendingOrders.php
index b5b28372..213db6a1 100644
--- a/Cron/CancelPendingOrders.php
+++ b/Cron/CancelPendingOrders.php
@@ -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
*/
@@ -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
@@ -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;
@@ -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);
}
@@ -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);
}
@@ -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());
@@ -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;
+ }
}
diff --git a/Model/Config.php b/Model/Config.php
index ea55099f..2c4ee3fb 100644
--- a/Model/Config.php
+++ b/Model/Config.php
@@ -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';
@@ -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);
diff --git a/Model/FormFieldTrack.php b/Model/FormFieldTrack.php
index d51df8be..90f72677 100644
--- a/Model/FormFieldTrack.php
+++ b/Model/FormFieldTrack.php
@@ -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
}
})
}
@@ -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()
@@ -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
@@ -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.'));
+ });
//]]>
";
@@ -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;
+ }
";
}
}
\ No newline at end of file
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 9f2cae98..43edacda 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -41,14 +41,25 @@
required-entry validate-digits validate-not-negative-number validate-digits-range digits-range-20-43200
-
+
+
+ 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.
+ payment/razorpay/pending_orders_age
+
+ 1
+
+ Razorpay\Magento\Model\FormFieldTrack
+ validate-digits validate-not-negative-number validate-digits-range digits-range-60-43200 validate-age-timeout
+
+
+
Magento\Config\Model\Config\Source\Yesno
Razorpay\Magento\Model\EnableResetCartOrdersCron
payment/razorpay/enable_reset_cart_cron
-
+
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.
payment/razorpay/reset_cart_orders_timeout
diff --git a/etc/config.xml b/etc/config.xml
index 095d94f3..9f0bbb57 100644
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -17,6 +17,7 @@
0
1
30
+ 43200
0
30
0
diff --git a/view/adminhtml/requirejs-config.js b/view/adminhtml/requirejs-config.js
new file mode 100644
index 00000000..c61e047d
--- /dev/null
+++ b/view/adminhtml/requirejs-config.js
@@ -0,0 +1,8 @@
+var config = {
+ paths: {
+ "validation": "Razorpay_Magento/js/validation"
+ },
+ shim: {
+ "validation": ["jquery"]
+ }
+};