├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── developer-experience-issue.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── no-response.yml ├── .travis.yml ├── Block └── Adminhtml │ └── System │ └── Config │ └── Manually.php ├── CHANGELOG ├── Console └── Delete.php ├── Controller └── Adminhtml │ ├── Delete │ └── Manually.php │ └── Order │ ├── Delete.php │ └── MassDelete.php ├── Cron └── Manually.php ├── Helper ├── Data.php └── Email.php ├── LICENSE ├── Model └── Config │ ├── Backend │ └── Order │ │ └── Frequency.php │ └── Source │ ├── Country.php │ ├── Frequency.php │ └── StoreView.php ├── Plugin ├── Model │ └── Order.php └── Order │ ├── AddDeleteAction.php │ └── AddDeleteButton.php ├── README.md ├── USER-GUIDE.md ├── UserGuide.pdf ├── composer.json ├── etc ├── acl.xml ├── adminhtml │ ├── di.xml │ ├── routes.xml │ └── system.xml ├── config.xml ├── crontab.xml ├── di.xml ├── email_templates.xml └── module.xml ├── i18n └── en_US.csv ├── registration.php └── view ├── adminhtml ├── templates │ └── manually.phtml └── ui_component │ ├── sales_archive_grid.xml │ └── sales_order_grid.xml └── frontend └── email └── delete_orders_email_template.html /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Technical issue with the extension 4 | labels: 'Issue' 5 | 6 | --- 7 | 8 | 11 | 12 | ### Preconditions (*) 13 | 16 | 1. 17 | 2. 18 | 19 | ### Steps to reproduce (*) 20 | 23 | 1. 24 | 2. 25 | 26 | ### Expected result (*) 27 | 28 | 1. [Screenshots, logs or description] 29 | 2. 30 | 31 | ### Actual result (*) 32 | 33 | 1. [Screenshots, logs or description] 34 | 2. 35 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/developer-experience-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Developer experience issue 3 | about: Issues related to customization, extensibility, modularity 4 | labels: 'Experience' 5 | 6 | --- 7 | 8 | 11 | 12 | ### Summary (*) 13 | 14 | 15 | ### Examples (*) 16 | 17 | 18 | ### Proposed solution 19 | 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Request feature for development 4 | labels: 'Feature Request' 5 | 6 | --- 7 | 8 | 11 | 12 | ### Description (*) 13 | 14 | 15 | ### Expected behavior (*) 16 | 17 | 18 | ### Benefits 19 | 20 | 21 | ### Additional information 22 | 23 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### Description 4 | 5 | 6 | ### Fixed Issues (if relevant) 7 | 8 | 1. https://github.com/mageplaza/magento-2-reports/: Issue title 9 | 2. ... 10 | 11 | ### Manual testing scenarios 12 | 13 | 1. 14 | 2. 15 | 16 | ### Contribution checklist 17 | - [ ] Pull request has a meaningful description of its purpose 18 | - [ ] All commits are accompanied by meaningful commit messages 19 | - [ ] All new or changed code is covered with unit/integration tests (if applicable) 20 | -------------------------------------------------------------------------------- /.github/no-response.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-no-response - https://github.com/probot/no-response 2 | 3 | # Number of days of inactivity before an Issue is closed for lack of response 4 | daysUntilClose: 7 5 | # Label requiring a response 6 | responseRequiredLabel: waiting-customer-response 7 | # Comment to post when closing an Issue for lack of response. Set to `false` to disable 8 | closeComment: > 9 | This issue has been automatically closed because there has been no response 10 | to our request for more information from the original author. With only the 11 | information that is currently in the issue, we don't have enough information 12 | to take action. Please reach out if you have or find the answers we need so 13 | that we can investigate further. 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | php: 3 | - 7.0 4 | - 7.1 5 | sudo: required 6 | dist: trusty 7 | env: 8 | global: 9 | - COMPOSER_BIN_DIR=~/bin 10 | - INTEGRATION_SETS=3 11 | - NODE_JS_VERSION=6 12 | - MAGENTO_HOST_NAME="magento2.travis" 13 | - COMPOSER_MODULE=mageplaza/module-delete-orders 14 | matrix: 15 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=1 16 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=2 17 | - MAGENTO_VERSION=2.2.1 TEST_SUITE=integration INTEGRATION_INDEX=3 18 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=static 19 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=js GRUNT_COMMAND=static 20 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=1 21 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=2 22 | - MAGENTO_VERSION=2.2.2 TEST_SUITE=integration INTEGRATION_INDEX=3 23 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=1 24 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=2 25 | - MAGENTO_VERSION=2.2.5 TEST_SUITE=integration INTEGRATION_INDEX=3 26 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=1 27 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=2 28 | - MAGENTO_VERSION=2.2.6 TEST_SUITE=integration INTEGRATION_INDEX=3 29 | 30 | matrix: 31 | exclude: 32 | - php: 7.0 33 | env: MAGENTO_VERSION=2.2.2 TEST_SUITE=js GRUNT_COMMAND=static 34 | - php: 7.0 35 | env: MAGENTO_VERSION=2.2.2 TEST_SUITE=static 36 | cache: 37 | apt: true 38 | directories: 39 | - "$HOME/.composer/cache" 40 | - "$HOME/.nvm" 41 | addons: 42 | apt: 43 | packages: 44 | - mysql-server-5.6 45 | - mysql-client-core-5.6 46 | - mysql-client-5.6 47 | - postfix 48 | firefox: '46.0' 49 | hosts: 50 | - magento2.travis 51 | before_install: 52 | - git clone https://github.com/magento/magento2 --branch $MAGENTO_VERSION 53 | - cd magento2 54 | - bash ./dev/travis/before_install.sh 55 | install: 56 | - composer install --no-interaction --prefer-dist 57 | - composer require $COMPOSER_MODULE 58 | before_script: 59 | #- cp -f ${TRAVIS_BUILD_DIR}/dev/tests/integration/phpunit.xml.dist dev/tests/integration/ 60 | - echo "vendor/$COMPOSER_MODULE" > dev/tests/static/testsuite/Magento/Test/Less/_files/whitelist/common.txt 61 | - echo "vendor/$COMPOSER_MODULE" > dev/tests/static/testsuite/Magento/Test/Php/_files/whitelist/common.txt 62 | - echo "vendor/$COMPOSER_MODULE/**/*.js" > dev/tests/static/testsuite/Magento/Test/Js/_files/whitelist/magento.txt 63 | - bash ./dev/travis/before_script.sh 64 | script: 65 | - test $TEST_SUITE = "static" && TEST_FILTER='--filter "Magento\\Test\\Php\\LiveCodeTest"' || true 66 | - test $TEST_SUITE = "functional" && TEST_FILTER='dev/tests/functional/testsuites/Magento/Mtf/TestSuite/InjectableTests.php' || true 67 | 68 | 69 | -------------------------------------------------------------------------------- /Block/Adminhtml/System/Config/Manually.php: -------------------------------------------------------------------------------- 1 | toHtml(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | CHANGELOG: https://www.mageplaza.com/releases/delete-orders -------------------------------------------------------------------------------- /Console/Delete.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 81 | $this->orderRepository = $orderRepository; 82 | $this->state = $state; 83 | $this->registry = $registry; 84 | 85 | parent::__construct($name); 86 | } 87 | 88 | /** 89 | * @inheritdoc 90 | */ 91 | protected function configure() 92 | { 93 | $this->setName('order:delete') 94 | ->setDescription('Delete order by id') 95 | ->addArgument(self::ORDER_ID, InputArgument::OPTIONAL, __('Order Id')); 96 | 97 | parent::configure(); 98 | } 99 | 100 | /** 101 | * {@inheritdoc} 102 | */ 103 | protected function execute(InputInterface $input, OutputInterface $output) 104 | { 105 | if (!$this->_helperData->isEnabled()) { 106 | $output->writeln('Please enable the module.'); 107 | 108 | return; 109 | } 110 | 111 | $this->state->setAreaCode(Area::AREA_ADMINHTML); 112 | $this->registry->unregister('isSecureArea'); 113 | $this->registry->register('isSecureArea', true); 114 | 115 | $orderId = $input->getArgument(self::ORDER_ID); 116 | try { 117 | /** delete order*/ 118 | $this->orderRepository->deleteById($orderId); 119 | /** delete order data on grid report data related*/ 120 | $this->_helperData->deleteRecord($orderId); 121 | 122 | $output->writeln('The delete order process has been successful!'); 123 | return 0; 124 | } catch (Exception $e) { 125 | $output->writeln("{$e->getMessage()}"); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Delete/Manually.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 95 | $this->orderRepository = $orderRepository; 96 | $this->logger = $logger; 97 | $this->_orderManagement = $orderManagement; 98 | $this->_email = $email; 99 | $this->_storeManager = $storeManager; 100 | 101 | parent::__construct($context); 102 | } 103 | 104 | /** 105 | * @return ResponseInterface|Redirect|ResultInterface 106 | */ 107 | public function execute() 108 | { 109 | $resultRedirect = $this->resultRedirectFactory->create(); 110 | $storeId = $this->getRequest()->getParam('store'); 111 | $status = ['processing', 'pending', 'fraud']; 112 | $orderCollection = $this->_helperData->getMatchingOrders($storeId); 113 | 114 | if ($orderCollection->getSize()) { 115 | $successDelete = 0; 116 | $errorOrders = []; 117 | 118 | foreach ($orderCollection->getItems() as $order) { 119 | try { 120 | if ($this->_helperData->versionCompare('2.3.0')) { 121 | if (in_array($order->getStatus(), $status, true)) { 122 | $this->_orderManagement->cancel($order->getId()); 123 | } 124 | if ($order->getStatus() === 'holded') { 125 | $this->_orderManagement->unHold($order->getId()); 126 | $this->_orderManagement->cancel($order->getId()); 127 | } 128 | } 129 | 130 | $this->orderRepository->delete($order); 131 | $this->_helperData->deleteRecord($order->getId()); 132 | $successDelete++; 133 | } catch (Exception $e) { 134 | $errorOrders[$order->getId()] = $order->getIncrementId(); 135 | $this->logger->error($e->getMessage()); 136 | } 137 | } 138 | 139 | if ($successDelete) { 140 | $this->messageManager->addSuccessMessage(__('Success! ' . $successDelete . ' orders have been deleted')); 141 | } 142 | 143 | if (count($errorOrders)) { 144 | $this->messageManager->addErrorMessage(__( 145 | 'The following orders cannot being deleted. %1', 146 | implode(', ', $errorOrders) 147 | )); 148 | } 149 | } else { 150 | $this->messageManager->addNoticeMessage(__('No order has been deleted!')); 151 | } 152 | 153 | return $resultRedirect->setUrl($this->_redirect->getRefererUrl()); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Order/Delete.php: -------------------------------------------------------------------------------- 1 | resultRedirectFactory->create(); 52 | $objectManager = ObjectManager::getInstance(); 53 | $orderManagement = $objectManager->create('Magento\Sales\Api\OrderManagementInterface'); 54 | $status = ['processing', 'pending', 'fraud']; 55 | $helper = $this->_objectManager->get(Data::class); 56 | if (!$helper->isEnabled()) { 57 | $this->messageManager->addError(__('Cannot delete the order.')); 58 | 59 | return $resultRedirect->setPath('sales/order/view', [ 60 | 'order_id' => $this->getRequest()->getParam('order_id') 61 | ]); 62 | } 63 | 64 | $order = $this->_initOrder(); 65 | if ($order) { 66 | try { 67 | if ($helper->versionCompare('2.3.0')) { 68 | if (in_array($order->getStatus(), $status)) { 69 | $orderManagement->cancel($order->getId()); 70 | } 71 | if ($order->getStatus() === 'holded') { 72 | $orderManagement->unHold($order->getId()); 73 | $orderManagement->cancel($order->getId()); 74 | } 75 | } 76 | /** delete order*/ 77 | $this->orderRepository->delete($order); 78 | /** delete order data on grid report data related*/ 79 | $helper->deleteRecord($order->getId()); 80 | 81 | $this->messageManager->addSuccessMessage(__('The order has been deleted.')); 82 | } catch (LocalizedException $e) { 83 | $this->messageManager->addErrorMessage($e->getMessage()); 84 | 85 | return $resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]); 86 | } catch (Exception $e) { 87 | $this->messageManager->addErrorMessage(__('An error occurred while deleting the order. Please try again later.')); 88 | $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); 89 | 90 | return $resultRedirect->setPath('sales/order/view', ['order_id' => $order->getId()]); 91 | } 92 | } 93 | 94 | return $resultRedirect->setPath('sales/*/'); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /Controller/Adminhtml/Order/MassDelete.php: -------------------------------------------------------------------------------- 1 | collectionFactory = $collectionFactory; 96 | $this->orderRepository = $orderRepository; 97 | $this->helper = $dataHelper; 98 | $this->logger = $logger; 99 | $this->_orderManagement = $orderManagement; 100 | } 101 | 102 | /** 103 | * @param AbstractCollection $collection 104 | * 105 | * @return Redirect|ResponseInterface|ResultInterface 106 | */ 107 | protected function massAction(AbstractCollection $collection) 108 | { 109 | if ($this->helper->isEnabled()) { 110 | $deleted = 0; 111 | $status = ['processing', 'pending', 'fraud']; 112 | /** @var OrderInterface $order */ 113 | foreach ($collection->getItems() as $order) { 114 | try { 115 | if ($this->helper->versionCompare('2.3.0')) { 116 | if (in_array($order->getStatus(), $status, true)) { 117 | $this->_orderManagement->cancel($order->getId()); 118 | } 119 | if ($order->getStatus() === 'holded') { 120 | $this->_orderManagement->unHold($order->getId()); 121 | $this->_orderManagement->cancel($order->getId()); 122 | } 123 | } 124 | /** delete order*/ 125 | $this->orderRepository->delete($order); 126 | /** delete order data on grid report data related*/ 127 | $this->helper->deleteRecord($order->getId()); 128 | 129 | $deleted++; 130 | } catch (Exception $e) { 131 | $this->logger->critical($e); 132 | $this->messageManager->addErrorMessage(__( 133 | 'Cannot delete order #%1. Please try again later.', 134 | $order->getIncrementId() 135 | )); 136 | } 137 | } 138 | 139 | if ($deleted) { 140 | $this->messageManager->addSuccessMessage(__('A total of %1 order(s) has been deleted.', $deleted)); 141 | } 142 | } 143 | 144 | /** @var Redirect $resultRedirect */ 145 | $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); 146 | $resultRedirect->setPath($this->getComponentRefererUrl()); 147 | 148 | return $resultRedirect; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /Cron/Manually.php: -------------------------------------------------------------------------------- 1 | _helperData = $helperData; 106 | $this->_email = $email; 107 | $this->_storeManager = $storeManager; 108 | $this->orderRepository = $orderRepository; 109 | $this->state = $state; 110 | $this->registry = $registry; 111 | $this->logger = $logger; 112 | $this->_orderManagement = $orderManagement; 113 | } 114 | 115 | /** 116 | * @throws LocalizedException 117 | */ 118 | public function process() 119 | { 120 | $status = ['processing', 'pending', 'fraud']; 121 | foreach ($this->_storeManager->getStores() as $store) { 122 | $storeId = $store->getId(); 123 | if (!$this->_helperData->isEnabled($storeId)) { 124 | continue; 125 | } 126 | 127 | $orderCollection = $this->_helperData->getMatchingOrders($storeId); 128 | if ($numOfOrders = $orderCollection->getSize()) { 129 | $this->registry->unregister('isSecureArea'); 130 | $this->registry->register('isSecureArea', true); 131 | $errorOrders = []; 132 | 133 | foreach ($orderCollection->getItems() as $order) { 134 | try { 135 | if ($this->_helperData->versionCompare('2.3.0')) { 136 | if (in_array($order->getStatus(), $status, true)) { 137 | $this->_orderManagement->cancel($order->getId()); 138 | } 139 | if ($order->getStatus() === 'holded') { 140 | $this->_orderManagement->unHold($order->getId()); 141 | $this->_orderManagement->cancel($order->getId()); 142 | } 143 | } 144 | $this->orderRepository->delete($order); 145 | $this->_helperData->deleteRecord($order->getId()); 146 | } catch (Exception $e) { 147 | $errorOrders[$order->getId()] = $order->getIncrementId(); 148 | $this->logger->error($e->getMessage()); 149 | } 150 | } 151 | 152 | if ($this->_email->isEnabledEmail($storeId)) { 153 | if (!$this->state->getAreaCode()) { 154 | $this->state->setAreaCode(Area::AREA_FRONTEND); 155 | } 156 | 157 | $templateParams = [ 158 | 'num_order' => $numOfOrders, 159 | 'success_order' => $numOfOrders - count($errorOrders), 160 | 'error_order' => count($errorOrders) 161 | ]; 162 | 163 | $this->_email->sendEmailTemplate($templateParams, $storeId); 164 | } 165 | } 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /Helper/Data.php: -------------------------------------------------------------------------------- 1 | orderResourceFactory = $orderResourceFactory; 66 | $this->orderCollectionFactory = $orderCollectionFactory; 67 | 68 | parent::__construct($context, $objectManager, $storeManager); 69 | } 70 | 71 | /** 72 | * Get order collection which matching the delete config condition 73 | * 74 | * @param null $storeId 75 | * @param int $limit 76 | * 77 | * @return Collection 78 | */ 79 | public function getMatchingOrders($storeId = null, $limit = 1000) 80 | { 81 | $orderCollection = $this->orderCollectionFactory->create() 82 | ->addFieldToFilter('status', ['in' => $this->getOrderStatusConfig($storeId)]) 83 | ->addFieldToFilter('customer_group_id', ['in' => $this->getOrderCustomerGroupConfig($storeId)]); 84 | 85 | $storeIds = $this->getStoreViewConfig($storeId); 86 | if (!in_array(Store::DEFAULT_STORE_ID, $storeIds, true)) { 87 | $orderCollection->addFieldToFilter('store_id', ['in' => $storeIds]); 88 | } 89 | 90 | if ($total = $this->getOrderTotalConfig($storeId)) { 91 | $orderCollection->addFieldToFilter('base_grand_total', ['lteq' => $total]); 92 | } 93 | 94 | if ($dayBefore = $this->getPeriodConfig($storeId)) { 95 | $orderCollection->addFieldToFilter('created_at', ['lteq' => $this->setDate($dayBefore)]); 96 | } 97 | 98 | if ($limit) { 99 | $orderCollection->getSelect()->limit($limit); 100 | } 101 | 102 | if ($this->getShippingCountryType($storeId) === Country::SPECIFIC) { 103 | $orderCollection->getSelect() 104 | ->joinLeft( 105 | ['soa' => $orderCollection->getTable('sales_order_address')], 106 | 'main_table.entity_id = soa.parent_id', 107 | [] 108 | ) 109 | ->where('soa.country_id IN (?)', $this->getCountriesConfig($storeId)) 110 | ->where('soa.address_type IN (?)', 'shipping'); 111 | } 112 | 113 | return $orderCollection; 114 | } 115 | 116 | /** 117 | * @param $orderId 118 | */ 119 | public function deleteRecord($orderId) 120 | { 121 | /** @var Order $resource */ 122 | $resource = $this->orderResourceFactory->create(); 123 | $connection = $resource->getConnection(); 124 | 125 | /** delete invoice grid record via resource model*/ 126 | $connection->delete( 127 | $resource->getTable('sales_invoice_grid'), 128 | $connection->quoteInto('order_id = ?', $orderId) 129 | ); 130 | 131 | /** delete shipment grid record via resource model*/ 132 | $connection->delete( 133 | $resource->getTable('sales_shipment_grid'), 134 | $connection->quoteInto('order_id = ?', $orderId) 135 | ); 136 | 137 | /** delete creditmemo grid record via resource model*/ 138 | $connection->delete( 139 | $resource->getTable('sales_creditmemo_grid'), 140 | $connection->quoteInto('order_id = ?', $orderId) 141 | ); 142 | } 143 | 144 | /** 145 | * @param $days 146 | * 147 | * @return false|string 148 | */ 149 | public function setDate($days) 150 | { 151 | return date('Y-m-d H:i:s', strtotime('-' . $days . ' days')); 152 | } 153 | 154 | /** 155 | * @param null $storeId 156 | * 157 | * @return mixed 158 | */ 159 | public function getOrderStatusConfig($storeId = null) 160 | { 161 | return explode(',', $this->getScheduleConfig('order_status', $storeId)); 162 | } 163 | 164 | /** 165 | * @param null $storeId 166 | * 167 | * @return mixed 168 | */ 169 | public function getOrderCustomerGroupConfig($storeId = null) 170 | { 171 | return explode(',', (string)$this->getScheduleConfig('customer_groups', $storeId)); 172 | } 173 | 174 | /** 175 | * @param null $storeId 176 | * 177 | * @return array 178 | */ 179 | public function getStoreViewConfig($storeId = null) 180 | { 181 | return explode(',', $this->getScheduleConfig('store_views', $storeId)); 182 | } 183 | 184 | /** 185 | * @param null $storeId 186 | * 187 | * @return mixed 188 | */ 189 | public function getShippingCountryType($storeId = null) 190 | { 191 | return $this->getScheduleConfig('country', $storeId); 192 | } 193 | 194 | /** 195 | * @param null $storeId 196 | * 197 | * @return array 198 | */ 199 | public function getCountriesConfig($storeId = null) 200 | { 201 | return explode(',', $this->getScheduleConfig('specific_country', $storeId)); 202 | } 203 | 204 | /** 205 | * @param null $storeId 206 | * 207 | * @return mixed 208 | */ 209 | public function getOrderTotalConfig($storeId = null) 210 | { 211 | return $this->getScheduleConfig('order_under', $storeId); 212 | } 213 | 214 | /** 215 | * @param null $storeId 216 | * 217 | * @return mixed 218 | */ 219 | public function getPeriodConfig($storeId = null) 220 | { 221 | return $this->getScheduleConfig('day_before', $storeId); 222 | } 223 | 224 | /** 225 | * @param $code 226 | * @param null $storeId 227 | * 228 | * @return mixed 229 | */ 230 | public function getScheduleConfig($code, $storeId = null) 231 | { 232 | return $this->getModuleConfig('schedule/' . $code, $storeId); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /Helper/Email.php: -------------------------------------------------------------------------------- 1 | transportBuilder = $transportBuilder; 70 | $this->_helperData = $helperData; 71 | 72 | parent::__construct($context, $objectManager, $storeManager); 73 | } 74 | 75 | /** 76 | * @param array $templateParams 77 | * @param null $storeId 78 | * 79 | * @return $this 80 | */ 81 | public function sendEmailTemplate($templateParams = [], $storeId = null) 82 | { 83 | try { 84 | $toEmails = $this->getToEmail($storeId); 85 | foreach ($toEmails as $toEmail) { 86 | $transport = $this->transportBuilder 87 | ->setTemplateIdentifier($this->getTemplate($storeId)) 88 | ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId]) 89 | ->setTemplateVars($templateParams) 90 | ->setFrom($this->getSender($storeId)) 91 | ->addTo($toEmail) 92 | ->getTransport(); 93 | 94 | $transport->sendMessage(); 95 | } 96 | } catch (Exception $e) { 97 | $this->_logger->critical($e->getMessage()); 98 | } 99 | 100 | return $this; 101 | } 102 | 103 | /** 104 | * ======================================= Email Configuration ================================================== 105 | * 106 | * @param string $code 107 | * @param null $storeId 108 | * 109 | * @return mixed 110 | */ 111 | public function getConfigEmail($code = '', $storeId = null) 112 | { 113 | $code = ($code !== '') ? '/' . $code : ''; 114 | 115 | return $this->getConfigValue(static::CONFIG_MODULE_PATH . self::EMAIL_CONFIGURATION . $code, $storeId); 116 | } 117 | 118 | /** 119 | * @param null $storeId 120 | * 121 | * @return bool 122 | */ 123 | public function isEnabledEmail($storeId = null) 124 | { 125 | if ($this->_helperData->isEnabled()) { 126 | return (bool) $this->getConfigEmail('enabled', $storeId); 127 | } 128 | 129 | return false; 130 | } 131 | 132 | /** 133 | * @param null $storeId 134 | * 135 | * @return string 136 | */ 137 | public function getSender($storeId = null) 138 | { 139 | return $this->getConfigEmail('sender', $storeId); 140 | } 141 | 142 | /** 143 | * @param null $storeId 144 | * 145 | * @return string 146 | */ 147 | public function getTemplate($storeId = null) 148 | { 149 | return $this->getConfigEmail('template', $storeId); 150 | } 151 | 152 | /** 153 | * @param null $storeId 154 | * 155 | * @return array 156 | */ 157 | public function getToEmail($storeId = null) 158 | { 159 | return explode(',', $this->getConfigEmail('to', $storeId)); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2016-present Mageplaza Co. Ltd. 2 | 3 | This License is entered by Mageplaza to govern the usage or redistribution of Mageplaza software. This is a legal agreement between you (either an individual or a single entity) and Mageplaza for Mageplaza software product(s) which may include extensions, templates and services. 4 | 5 | By purchasing, installing, or otherwise using Mageplaza products, you acknowledge that you have read this License and agree to be bound by the terms of this Agreement. If you do not agree to the terms of this License, do not install or use Mageplaza products. 6 | 7 | The Agreement becomes effective at the moment when you acquire software from our site or receive it through email or on data medium or by any other means. Mageplaza reserves the right to make reasonable changes to the terms of this license agreement and impose its clauses at any given time. 8 | 9 | 1. GRANT OF LICENSE: By purchasing a product of Mageplaza: 10 | 11 | 1. Customer will receive source code open 100%. 12 | 13 | 2. Customer will obtain a License Certificate which will remain valid until the Customer stops using the Product or until Mageplaza terminates this License because of Customer’s failure to comply with any of its Terms and Conditions. Each License Certificate includes a license serial which is valid for one live Magento installation only and unlimited test Magento installations. 14 | 15 | 3. You are allowed to customize our products to fit with your using purpose. 16 | 17 | 4. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS 18 | 19 | 5. Installation and Use 20 | 21 | 6. For each new Software installation, you are obliged to purchase a separate License. You are not permitted to use any part of the code in whole or part in any other software or product or website. You are legally bound to preserve the copyright information intact including the text/link at bottom. 22 | 23 | 2. Distribution: You are not allowed to distribute Mageplaza software to third parties. Any distribution without our permission, including non commercial distribution is considered as violation of this Agreement and entails liability, according to the current law. You may not place the Software onto a server that allows access to the Software via a public network or the Internet for distribution purposes. 24 | 25 | 3. Rental: You may not give, sell, sub-license, rent, lease or lend any portion of the Software to anyone. 26 | 27 | 4. Compliance with Applicable Laws: You must comply with all applicable laws regarding use of software products. Mageplaza software and a portion of it are protected by copyright laws and international copyright treaties, as well as other intellectual property laws and treaties. Accordingly, customer is required to treat the software like any other copyrighted material. Any activity violating copyright law will be prosecuted according to the current law. We retain the right to revoke the license of any user holding an invalid license. 28 | 29 | 5. TERMINATION: Without prejudice to any other rights, Mageplaza may terminate this License at any time if you fail to comply with the terms and conditions of this License. In such event, it constitutes a breach of the agreement, and your license to use the program is revoked and you must destroy all copies of Mageplaza products in your possession. After being notified of termination of your license, if you continue to use Mageplaza software, you hereby agree to accept an injunction to prevent you from its further use and to pay all costs (including but not limited to reasonable attorney fees) to enforce our revocation of your license and any damages suffered by us because of your misuse of the Software. We are not bound to return you the amount spent for purchase of the Software for the termination of this License. 30 | 31 | 6. LIMITATION OF LIABILITY: In no event shall Mageplaza be liable for any damages (including, without limitation, lost profits, business interruption, or lost information) rising out of ‘Authorized Users’ use of or inability to use the Mageplaza products, even if Mageplaza has been advised of the possibility of such damages. In no event will Mageplaza be liable for prosecution arising from use of the Software against law or for any illegal use. 32 | 33 | The latest License: https://www.mageplaza.com/LICENSE.txt -------------------------------------------------------------------------------- /Model/Config/Backend/Order/Frequency.php: -------------------------------------------------------------------------------- 1 | _runModelPath = $runModelPath; 94 | $this->_configValueFactory = $configValueFactory; 95 | $this->messageManager = $messageManager; 96 | 97 | parent::__construct( 98 | $context, 99 | $registry, 100 | $config, 101 | $cacheTypeList, 102 | $resource, 103 | $resourceCollection, 104 | $data 105 | ); 106 | } 107 | 108 | /** 109 | * @return Value 110 | */ 111 | public function afterSave() 112 | { 113 | $time = $this->getData('groups/schedule/fields/time/value'); 114 | $frequency = $this->getData('groups/schedule/fields/frequency/value'); 115 | 116 | if ($frequency != (string)ValueConfig::DISABLE) { 117 | $cronExprArray = [ 118 | (int) $time[1], //Minute 119 | (int) $time[0], //Hour 120 | $frequency === \Magento\Cron\Model\Config\Source\Frequency::CRON_MONTHLY ? '1' : '*', //Day of the Month 121 | '*', //Month of the Year 122 | $frequency === \Magento\Cron\Model\Config\Source\Frequency::CRON_WEEKLY ? '1' : '*', //Day of the Week 123 | ]; 124 | 125 | $cronExprString = join(' ', $cronExprArray); 126 | 127 | try { 128 | $this->_configValueFactory->create() 129 | ->load(self::CRON_STRING_PATH, 'path') 130 | ->setValue($cronExprString) 131 | ->setPath(self::CRON_STRING_PATH) 132 | ->save(); 133 | 134 | $this->_configValueFactory->create() 135 | ->load(self::CRON_MODEL_PATH, 'path') 136 | ->setValue($this->_runModelPath) 137 | ->setPath(self::CRON_MODEL_PATH) 138 | ->save(); 139 | } catch (Exception $e) { 140 | $this->messageManager->addErrorMessage(__('We can\'t save the cron expression. %1', $e->getMessage())); 141 | } 142 | } 143 | 144 | return parent::afterSave(); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Model/Config/Source/Country.php: -------------------------------------------------------------------------------- 1 | '', 'label' => '