diff --git a/Api/Data/PushOrderMetadataInterface.php b/Api/Data/PushOrderMetadataInterface.php
new file mode 100644
index 0000000..e6510fb
--- /dev/null
+++ b/Api/Data/PushOrderMetadataInterface.php
@@ -0,0 +1,31 @@
+logger = $logger;
+ $this->scopeConfig = $scopeConfig;
+ $this->pushOrderMetadataRepository = $pushOrderMetadataRepository;
+ $this->_curl = $_curl;
+ $this->orderRepository = $orderRepository;
+ }
+
+ public function execute()
+ {
+ if (!$this->scopeConfig->getValue(self::XML_PATH_ENABLED,ScopeInterface::SCOPE_STORE)) {
+ return $this;
+ }
+ $timeToCompare = date("Y-m-d H:i:s", strtotime('-1 days'));
+ foreach ($this->pushOrderMetadataRepository->getUnprocessedList() as $pushOrderMetadata) {
+ try {
+ if ($pushOrderMetadata->getCreatedAt() < $timeToCompare) {
+ throw new Exception(sprintf("Too late for push: %s < %s", $pushOrderMetadata->getCreatedAt(), $timeToCompare));
+ }
+ $message = $this->pushOrder($pushOrderMetadata->getOrderId());
+ } catch (Exception $e) {
+ $this->logger->error("Picqer push order error: " . $e->getMessage());
+ $message = $e->getMessage();
+ }
+ $this->pushOrderMetadataRepository->setProcessed($pushOrderMetadata, $message);
+ }
+
+ return $this;
+ }
+
+ private function pushOrder($orderId)
+ {
+ $order = $this->orderRepository->get((int)$orderId);
+
+ $subDomain = $this->scopeConfig->getValue('picqer_integration_options/webhook_settings/picqer_subdomain');
+ $magentoKey = $this->scopeConfig->getValue('picqer_integration_options/webhook_settings/connection_key');
+
+ if (empty($subDomain) || empty($magentoKey)) {
+ throw new Exception("Module is not fully configured");
+ }
+
+ $orderData = [];
+ $orderData['increment_id'] = $order->getIncrementId();
+ $orderData['picqer_magento_key'] = $magentoKey;
+
+ $this->_curl->setHeaders([
+ 'Content-Type' => 'application/json'
+ ]);
+
+ $this->_curl->setOptions([
+ CURLOPT_TIMEOUT => 2 // in seconds
+ ]);
+
+ $this->_curl->post(sprintf('https://%s.picqer.com/webshops/magento2/orderPush/%s', trim($subDomain), trim($magentoKey)), json_encode($orderData));
+
+ return $this->_curl->getBody();
+ }
+
+}
diff --git a/Model/PushOrderMetadata.php b/Model/PushOrderMetadata.php
new file mode 100644
index 0000000..360c12b
--- /dev/null
+++ b/Model/PushOrderMetadata.php
@@ -0,0 +1,55 @@
+_init(Model::class);
+ }
+
+ public function getId()
+ {
+ return $this->getData(PushOrderMetadataInterface::COLUMN_ID);
+ }
+
+ public function getOrderId()
+ {
+ return $this->getData(PushOrderMetadataInterface::COLUMN_ORDER_ID);
+ }
+
+ public function getCreatedAt()
+ {
+ return $this->getData(PushOrderMetadataInterface::COLUMN_CREATED_AT);
+ }
+
+ public function setOrderId($orderId)
+ {
+ $this->setData(PushOrderMetadataInterface::COLUMN_ORDER_ID, (int)$orderId);
+ return $this;
+ }
+
+ public function setOrderStatus($orderStatus)
+ {
+ $this->setData(PushOrderMetadataInterface::COLUMN_ORDER_STATUS, (string)$orderStatus);
+ return $this;
+ }
+
+ public function setStatus($status)
+ {
+ $this->setData(PushOrderMetadataInterface::COLUMN_STATUS, (int)$status);
+ return $this;
+ }
+
+ public function setMessage($message)
+ {
+ $this->setData(PushOrderMetadataInterface::COLUMN_MESSAGE, (string)$message);
+ return $this;
+ }
+
+}
diff --git a/Model/PushOrderMetadataRepository.php b/Model/PushOrderMetadataRepository.php
new file mode 100644
index 0000000..6ff477c
--- /dev/null
+++ b/Model/PushOrderMetadataRepository.php
@@ -0,0 +1,80 @@
+resourceModel = $resourceModel;
+ $this->collectionFactory = $collectionFactory;
+ $this->pushOrderMetadataFactory = $pushOrderMetadataFactory;
+ }
+
+ public function setProcessed(PushOrderMetadataInterface $pushOrderMetadata, $message)
+ {
+ $pushOrderMetadata->setMessage((string)$message);
+ $pushOrderMetadata->setStatus(PushOrderMetadataInterface::STATUS_PROCESSED);
+ return $this->save($pushOrderMetadata);
+ }
+
+ /**
+ * @param $id
+ * @return PushOrderMetadataInterface
+ * @throws LocalizedException
+ */
+ public function getById($id)
+ {
+ $model = $this->pushOrderMetadataFactory->create();
+ $this->resourceModel->load($model, (int)$id, PushOrderMetadataInterface::COLUMN_ID);
+ if (!$model->getId()) {
+ throw new LocalizedException(__('Unable to find item'));
+ }
+ return $model;
+ }
+
+ function getUnprocessedList()
+ {
+ $list = [];
+ /** @var Collection $collection */
+ $collection = $this->collectionFactory->create();
+ $collection->addFieldToFilter(PushOrderMetadataInterface::COLUMN_STATUS, ['eq' => PushOrderMetadataInterface::STATUS_UNPROCESSED]);
+ foreach ($collection as $item) {
+ $model = $this->getById((int)$item->getId());
+ $list[$model->getId()] = $model;
+ }
+ return $list;
+ }
+
+ function save(PushOrderMetadataInterface $pushOrderMetadata)
+ {
+ $this->resourceModel->save($pushOrderMetadata);
+ return $this->getById((int)$pushOrderMetadata->getId());
+ }
+}
diff --git a/Model/ResourceModel/PushOrderMetadata.php b/Model/ResourceModel/PushOrderMetadata.php
new file mode 100644
index 0000000..8b5ee5c
--- /dev/null
+++ b/Model/ResourceModel/PushOrderMetadata.php
@@ -0,0 +1,14 @@
+_init('picqer_push_order_metadata', 'id');
+ }
+
+}
diff --git a/Model/ResourceModel/PushOrderMetadata/Collection.php b/Model/ResourceModel/PushOrderMetadata/Collection.php
new file mode 100644
index 0000000..9d67012
--- /dev/null
+++ b/Model/ResourceModel/PushOrderMetadata/Collection.php
@@ -0,0 +1,18 @@
+_init(Model::class, ResourceModel::class);
+ }
+}
+
+
+
diff --git a/Observer/CollectOrderSaveEvent.php b/Observer/CollectOrderSaveEvent.php
new file mode 100644
index 0000000..f830109
--- /dev/null
+++ b/Observer/CollectOrderSaveEvent.php
@@ -0,0 +1,64 @@
+scopeConfig = $scopeConfig;
+ $this->pushOrderMetadataInterfaceFactory = $pushOrderMetadataInterfaceFactory;
+ $this->pushOrderMetadataRepository = $pushOrderMetadataRepository;
+ $this->logger = $logger;
+ }
+
+ public function execute(Observer $observer)
+ {
+ if (!$this->scopeConfig->isSetFlag(PushOrder::XML_PATH_ENABLED)) {
+ return;
+ }
+
+ try {
+ $order = $observer->getEvent()->getOrder();
+ /** @var PushOrderMetadataInterface $pushOrderMetadata */
+ $pushOrderMetadata = $this->pushOrderMetadataInterfaceFactory->create();
+ $pushOrderMetadata->setOrderId($order->getId());
+ $pushOrderMetadata->setOrderStatus($order->getStatus());
+ $this->pushOrderMetadataRepository->save($pushOrderMetadata);
+ } catch (\Exception $e) {
+ $this->logger->error("Can not create PushOrderMetadata instance: " . $e->getMessage());
+ }
+
+ }
+}
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 245bbd0..4f8efdf 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -21,6 +21,13 @@
+
+
+ Magento\Config\Model\Config\Source\Yesno
+ 0
+ Push orders to `Picqer` by cron instead `On Save Order`
+
diff --git a/etc/cron_groups.xml b/etc/cron_groups.xml
new file mode 100644
index 0000000..c6bc02d
--- /dev/null
+++ b/etc/cron_groups.xml
@@ -0,0 +1,14 @@
+
+
+
+
+ 10
+ 20
+ 10
+ 10
+ 60
+ 600
+ 1
+
+
diff --git a/etc/crontab.xml b/etc/crontab.xml
new file mode 100644
index 0000000..0ad1c3c
--- /dev/null
+++ b/etc/crontab.xml
@@ -0,0 +1,9 @@
+
+
+
+
+ * * * * *
+
+
+
diff --git a/etc/db_schema.xml b/etc/db_schema.xml
new file mode 100644
index 0000000..e50639c
--- /dev/null
+++ b/etc/db_schema.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/di.xml b/etc/di.xml
new file mode 100644
index 0000000..fa4f903
--- /dev/null
+++ b/etc/di.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/etc/events.xml b/etc/events.xml
index 4f0f352..3d8e203 100644
--- a/etc/events.xml
+++ b/etc/events.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file