diff --git a/retailcrm/lib/RetailcrmExport.php b/retailcrm/lib/RetailcrmExport.php
new file mode 100644
index 0000000..8d2d3b0
--- /dev/null
+++ b/retailcrm/lib/RetailcrmExport.php
@@ -0,0 +1,201 @@
+
+ * @copyright 2020 DIGITAL RETAIL TECHNOLOGIES SL
+ * @license https://opensource.org/licenses/MIT The MIT License
+ *
+ * Don't forget to prefix your containers with your own identifier
+ * to avoid any conflicts with others containers.
+ */
+class RetailcrmExport
+{
+
+ /**
+ * Get total count of orders for context shop
+ *
+ * @return int
+ */
+ public static function getOrdersCount()
+ {
+ $sql = 'SELECT count(o.id_order)
+ FROM `' . _DB_PREFIX_ . 'orders` o
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'o');
+
+ return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ }
+
+ /**
+ * Get orders ids from the database
+ *
+ * @param int $start Sets the LIMIT start parameter for sql query
+ * @param int|null $count Sets the count of orders to get from database
+ *
+ * @return Generator
+ * @throws PrestaShopDatabaseException
+ */
+ public static function getOrdersIds($start = 0, $count = null)
+ {
+ if (is_null($count)) {
+ $count = static::getOrdersCount();
+ }
+
+ if ($count > 0) {
+ $loadSize = 5000;
+ $predefinedSql = 'SELECT o.`id_order`
+ FROM `' . _DB_PREFIX_ . 'orders` o
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'o') . '
+ ORDER BY o.`id_order` ASC';
+
+ while ($start <= $count) {
+ $offset = ($start + $loadSize > $count) ? $count - $start : $loadSize;
+
+ $sql = $predefinedSql . '
+ LIMIT ' . (int)$start . ', ' . (int)$offset;
+
+ $orders = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
+
+ if (empty($orders))
+ break;
+
+ foreach ($orders as $order) {
+ yield $order;
+ }
+
+ $start += $offset;
+ }
+ }
+ }
+
+ /**
+ * Get total count of customers without orders for context shop
+ *
+ * @return int
+ */
+ public static function getCustomersCount()
+ {
+ $sql = 'SELECT count(c.id_customer)
+ FROM `' . _DB_PREFIX_ . 'customer` c
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'c') . '
+ AND c.id_customer not in (
+ select o.id_customer
+ from `' . _DB_PREFIX_ . 'orders` o
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'o') . '
+ group by o.id_customer
+ )';
+
+ return (int)Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue($sql);
+ }
+
+ /**
+ * Get customers ids from database
+ *
+ * @param int $start Sets the LIMIT start parameter for sql query
+ * @param null $count Sets the count of customers to get from database
+ * @param bool $withAddressId If set to true, then also return address id in `id_address`
+ *
+ * @return Generator
+ * @throws PrestaShopDatabaseException
+ */
+ public static function getCustomersIds($start = 0, $count = null, $withAddressId = true)
+ {
+ if (is_null($count)) {
+ $count = static::getCustomersCount();
+ }
+
+ if ($count > 0) {
+ $loadSize = 500;
+ $predefinedSql = 'SELECT c.`id_customer`
+ ' . ($withAddressId ? ', a.`id_address`' : '') . '
+ FROM `' . _DB_PREFIX_ . 'customer` c
+ ' . ($withAddressId ? '
+ LEFT JOIN
+ (
+ SELECT
+ ad.`id_customer`,
+ ad.`id_address`
+ FROM
+ `' . _DB_PREFIX_ . 'address` ad
+ INNER JOIN
+ (
+ SELECT
+ `id_customer`,
+ MAX(`date_add`) AS `date_add`
+ FROM
+ `' . _DB_PREFIX_ . 'address`
+ GROUP BY
+ id_customer
+ ) ad2
+ ON
+ ad2.`id_customer` = ad.`id_customer` AND ad2.`date_add` = ad.`date_add`
+ ORDER BY
+ ad.`id_customer` ASC
+ ) a
+ ON
+ a.`id_customer` = c.`id_customer`
+ ' : '') . '
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'c') . '
+ AND c.`id_customer` not in (
+ select o.`id_customer`
+ from `' . _DB_PREFIX_ . 'orders` o
+ WHERE 1
+ ' . Shop::addSqlRestriction(false, 'o') . '
+ group by o.`id_customer`
+ )
+ ORDER BY c.`id_customer` ASC';
+
+
+ while ($start <= $count) {
+ $offset = ($start + $loadSize > $count) ? $count - $start : $loadSize;
+
+ $sql = $predefinedSql . '
+ LIMIT ' . (int)$start . ', ' . (int)$offset;
+
+ $customers = Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS($sql);
+
+ if (empty($customers))
+ break;
+
+ foreach ($customers as $customer) {
+ yield $customer;
+ }
+
+ $start += $offset;
+ }
+ }
+ }
+
+}
diff --git a/retailcrm/lib/events/RetailcrmExportEvent.php b/retailcrm/lib/events/RetailcrmExportEvent.php
index 773bebf..b4e90d1 100644
--- a/retailcrm/lib/events/RetailcrmExportEvent.php
+++ b/retailcrm/lib/events/RetailcrmExportEvent.php
@@ -28,9 +28,9 @@
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
- * @author DIGITAL RETAIL TECHNOLOGIES SL
- * @copyright 2020 DIGITAL RETAIL TECHNOLOGIES SL
- * @license https://opensource.org/licenses/MIT The MIT License
+ * @author DIGITAL RETAIL TECHNOLOGIES SL
+ * @copyright 2020 DIGITAL RETAIL TECHNOLOGIES SL
+ * @license https://opensource.org/licenses/MIT The MIT License
*
* Don't forget to prefix your containers with your own identifier
* to avoid any conflicts with others containers.
@@ -65,7 +65,7 @@ class RetailcrmExportEvent extends RetailcrmAbstractEvent implements RetailcrmEv
}
$orders = array();
- $orderRecords = Order::getOrdersWithInformations();
+ $orderRecords = RetailcrmExport::getOrdersIds();
$orderBuilder = new RetailcrmOrderBuilder();
$orderBuilder->defaultLangFromConfiguration()->setApi($api);
@@ -97,20 +97,64 @@ class RetailcrmExportEvent extends RetailcrmAbstractEvent implements RetailcrmEv
try {
$orders[] = $orderBuilder->buildOrderWithPreparedCustomer();
} catch (\InvalidArgumentException $exception) {
- RetailcrmLogger::writeCaller('export', $exception->getMessage());
+ RetailcrmLogger::writeCaller('export', sprintf('Error while building %s: %s', $record['id_order'], $exception->getMessage()));
RetailcrmLogger::writeNoCaller($exception->getTraceAsString());
RetailcrmLogger::output($exception->getMessage());
}
- time_nanosleep(0, 500000000);
+ time_nanosleep(0, 250000000);
+
+ if (count($orders) == 50) {
+ $api->ordersUpload($orders);
+ $orders = array();
+ }
}
- unset($orderRecords);
+ if (count($orders)) {
+ $api->ordersUpload($orders);
+ }
- $orders = array_chunk($orders, 50);
+ $customers = array();
+ $customersRecords = RetailcrmExport::getCustomersIds();
- foreach ($orders as $chunk) {
- $api->ordersUpload($chunk);
+ foreach ($customersRecords as $record) {
+ $customerId = $record['id_customer'];
+ $addressId = $record['id_address'];
+
+ $cmsCustomer = new Customer($customerId);
+
+ if (Validate::isLoadedObject($cmsCustomer)) {
+ if ($addressId) {
+ $cmsAddress = new Address($addressId);
+
+ $addressBuilder = new RetailcrmAddressBuilder();
+ $address = $addressBuilder
+ ->setAddress($cmsAddress)
+ ->build()
+ ->getDataArray();
+ } else {
+ $address = array();
+ }
+
+ try {
+ $customers[] = RetailcrmOrderBuilder::buildCrmCustomer($cmsCustomer, $address);
+ } catch (\Exception $exception) {
+ RetailcrmLogger::writeCaller('export', sprintf('Error while building %s: %s', $customerId, $exception->getMessage()));
+ RetailcrmLogger::writeNoCaller($exception->getTraceAsString());
+ RetailcrmLogger::output($exception->getMessage());
+ }
+
+ if (count($customers) == 50) {
+ $api->customersUpload($customers);
+ $customers = array();
+
+ time_nanosleep(0, 250000000);
+ }
+ }
+ }
+
+ if (count($customers)) {
+ $api->customersUpload($customers);
}
}