Generate Icml in settings tab

This commit is contained in:
max-baranikov 2021-07-27 13:25:44 +03:00 committed by GitHub
parent a17286474d
commit 72639aadbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1284 additions and 264 deletions

1
.gitignore vendored
View File

@ -4,6 +4,7 @@ retailcrm/views/css/less/*.map
retailcrm/views/css/*.css
retailcrm/views/css/*.map
!retailcrm/views/css/*.min.css
retailcrm/views/js/*.map
retailcrm/config*.xml
retailcrm/custom
coverage.xml

38
doc/1. Setup/Catalog.md Normal file
View File

@ -0,0 +1,38 @@
# Catalog
## Generate Icml
По кнопке Generate now можно вручную сгенерировать каталог. Для сгенерированного каталога отображается время его
последней генерации, количество товаров и торговых предложений. Если с момента генерации прошло более 4-х часов, то
будет отображено соответствующее уведомление.
## Update URL
При загрузке страницы выполняется проверка URL адреса файла Icml каталога, указанного в настройках магазина в CRM. Если
адрес в системе не совпадает с фактическим адресом сгенерированного файла, то на странице отображается соответствующее
уведомление и кнопка, позволяющая обновить URL.
## Jobs run
Задачи генерации каталога и обновления URL выполняются через **JobManager**
в [`force` режиме](../2.%20Workflow/CLI%20&%20Job%20Manager/Job%20Manager.md#force-option).
## Multistore
При включенной опции **Multistore** есть возможность запустить процесс генерации каталога/обновления URL сразу для
нескольких или всех магазинов. Для этого нужно перейти в контекст конкретной группы или всех магазинов и нажать
соответствующую кнопку.
В контексте группы отображается информация о каталогах для каждого магазина, входящего в эту группу. Можно перейти в
контекст конкретного магазина, кликнув по его имени.
## Manage site settings
Можно перейти в настройки каталога в CRM, кликнув по `Manage site settings`. Если не удалось сформировать ссылку на
настройки каталога, то вместо этого для магазина будет предоставлена ссылка на список всех магазинов CRM
## Errors
При наличии каких либо проблем с каталогом — отсутствие файла, устаревший файл или несовпадение URL,
вкладка `Icml catalog` будет подсвечиваться красным цветом, сигнализируя об ошибках. В случае отсутствия файла каталога
в первые 4 часа после установки и первичной настройки модуля ошибка возникать не будет

View File

@ -0,0 +1,6 @@
# Job Manager
## Force option
Режим принудительного запуска позволяет запустить задачу независимо от того, запущена ли сейчас другая задача через Job
Manager. Запущенная таким образом задача не блокирует работу Job Manager

View File

@ -1,2 +1,9 @@
# Icml
При генерации каталога подсчитывается количество продуктов и торговых предложений. Это сохраняется в
настройку `RETAILCRM_ICML_INFO` в базу данных CMS.
Дата генерации каталога берется непосредственно из содержимого файла из
строки `<yml_catalog date="2021-07-17 19:12:46">`
Методы по работе с сохраненными настройками и файлом вынесены в класс `RetailcrmCatalogHelper`

View File

@ -1,2 +1,6 @@
# Multistore
## Context Switcher
Класс `RetailcrmContextSwitcher` отвечает за переключение текущего контекста, а также позволяет запустить какую-нибудь
функцию поочередно для всех магазинов в текущем контексте (в рамках одного магазина, одной группы или всех магазинов)

View File

@ -38,6 +38,7 @@
*/
class RetailcrmCatalog
{
public $default_lang;
public $default_currency;
public $default_country;
@ -105,6 +106,9 @@ class RetailcrmCatalog
public function getOffers()
{
$productsCount = 0;
$offersCount = 0;
$id_lang = $this->default_lang;
$homeCategory = $this->home_category;
@ -156,6 +160,7 @@ class RetailcrmCatalog
if (empty($categoriesLeft)) {
continue;
}
$productsCount++;
if ($this->version == "1.3") {
$available_for_order = $product['active'] && $product['quantity'];
@ -206,6 +211,7 @@ class RetailcrmCatalog
$offers = Product::getProductAttributesIds($product['id_product']);
if (!empty($offers)) {
$offersCount+= count($offers);
$productForCombination = new Product($product['id_product']);
foreach ($offers as $offer) {
@ -298,6 +304,7 @@ class RetailcrmCatalog
);
}
} else {
$offersCount++;
$pictures = array();
$covers = Image::getImages($id_lang, $product['id_product'], null);
@ -343,6 +350,8 @@ class RetailcrmCatalog
$start += $limit;
} while ($start < $count && count($products) > 0);
RetailcrmCatalogHelper::setIcmlFileInfo($productsCount, $offersCount);
}
private static function getProductsCount(
@ -430,4 +439,5 @@ class RetailcrmCatalog
return $parentId;
}
}

View File

@ -0,0 +1,149 @@
<?php
/**
* MIT License
*
* Copyright (c) 2020 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* 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 <mail@simlachat.com>
* @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 RetailcrmCatalogHelper
{
const ICML_INFO_NAME = 'RETAILCRM_ICML_INFO';
public static function getIcmlFileDate()
{
$date = null;
$filePath = self::getIcmlFilePath();
if (!file_exists($filePath) || ($fileHandler = fopen($filePath, 'rb')) === false) {
return null;
}
while ($line = fgets($fileHandler)) {
if (strpos($line, 'yml_catalog date=') !== false) {
preg_match_all('/date="([\d\- :]+)"/', $line, $matches);
if (count($matches) == 2) {
$date = $matches[1][0];
}
break;
}
}
fclose($fileHandler);
return $date;
}
public static function getIcmlFileLink()
{
return _PS_BASE_URL_ . '/' . self::getIcmlFilename();
}
public static function getIcmlFileName()
{
$isMultiStoreActive = Shop::isFeatureActive();
$shop = Context::getContext()->shop;
if ($isMultiStoreActive) {
$icmlFileName = 'simla_' . $shop->id . '.xml';
} else {
$icmlFileName = 'simla.xml';
}
return $icmlFileName;
}
public static function getIcmlFilePath()
{
return _PS_ROOT_DIR_ . '/' . self::getIcmlFileName();
}
public static function getIcmlFileInfo()
{
$icmlInfo = json_decode((string)Configuration::get(self::ICML_INFO_NAME), true);
if (json_last_error() != JSON_ERROR_NONE) {
$icmlInfo = array();
}
$lastGenerated = DateTime::createFromFormat('Y-m-d H:i:s', self::getIcmlFileDate());
if ($lastGenerated instanceof DateTime) {
$icmlInfo['lastGenerated'] = $lastGenerated;
$now = new DateTime();
/** @var DateInterval $diff */
$diff = $lastGenerated->diff($now);
$icmlInfo['lastGeneratedDiff'] = array(
'days' => $diff->days,
'hours' => $diff->h,
'minutes' => $diff->i
);
$icmlInfo['isOutdated'] = (
$icmlInfo['lastGeneratedDiff']['days'] > 0
|| $icmlInfo['lastGeneratedDiff']['hours'] > 4
);
}
$api = RetailcrmTools::getApiClient();
if ($api !== null) {
$reference = new RetailcrmReferences($api);
$site = $reference->getSite();
$icmlInfo['isUrlActual'] = !empty($site['ymlUrl']) && $site['ymlUrl'] === self::getIcmlFileLink();
if (!empty($site['catalogId'])) {
$icmlInfo['siteId'] = $site['catalogId'];
}
}
return (array)$icmlInfo;
}
public static function getIcmlFileInfoMultistore()
{
return RetailcrmContextSwitcher::runInContext(array(self::class, 'getIcmlFileInfo'));
}
/**
* @param int $productsCount
* @param int $offersCount
*/
public static function setIcmlFileInfo($productsCount, $offersCount)
{
$icmlInfo = array(
'productsCount' => $productsCount,
'offersCount' => $offersCount
);
Configuration::updateValue(self::ICML_INFO_NAME, (string)json_encode($icmlInfo));
}
}

View File

@ -159,7 +159,7 @@ class RetailcrmCli
private function runJob($jobName, $shopId)
{
try {
$result = RetailcrmJobManager::runJob($jobName, true, true, $shopId);
$result = RetailcrmJobManager::runJob($jobName, true, false, $shopId);
RetailcrmLogger::output(sprintf(
'Job %s was executed, result: %s',
$jobName,
@ -372,6 +372,7 @@ class RetailcrmCli
return array(
'RetailcrmAbandonedCartsEvent',
'RetailcrmIcmlEvent',
'RetailcrmIcmlUpdateUrlEvent',
'RetailcrmSyncEvent',
'RetailcrmInventoriesEvent',
'RetailcrmExportEvent',

View File

@ -0,0 +1,129 @@
<?php
/**
* MIT License
*
* Copyright (c) 2020 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* 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 <mail@simlachat.com>
* @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 RetailcrmContextSwitcher
{
/**
* @var int
*/
private static $contextShopType;
/**
* @var Shop
*/
private static $contextShop;
/**
* Runs given callback function in all context shops
*
* @param callable $callback
* @param array $arguments Arguments that will be passed to callback function
* @return array
*/
public static function runInContext($callback, $arguments = array())
{
$result = array();
self::storeContext();
foreach (self::getShops() as $shop) {
self::setShopContext(intval($shop['id_shop']));
$result[intval($shop['id_shop'])] = call_user_func_array($callback, $arguments);
}
self::restoreContext();
return $result;
}
private static function storeContext()
{
static::$contextShopType = Shop::getContext();
static::$contextShop = Context::getContext()->shop;
}
private static function restoreContext()
{
switch (static::$contextShopType) {
case Shop::CONTEXT_GROUP:
$contextShopId = static::$contextShop->id_shop_group;
break;
case Shop::CONTEXT_SHOP:
$contextShopId = static::$contextShop->id;
break;
default:
$contextShopId = null;
break;
}
try {
Shop::setContext(static::$contextShopType, $contextShopId);
} catch (PrestaShopException $e) {
RetailcrmLogger::writeCaller(__METHOD__, 'Unable to set shop context');
}
Context::getContext()->shop = static::$contextShop;
}
/**
*
* Change shop in the context
*
* @param $id_shop
*/
public static function setShopContext($id_shop)
{
try {
Shop::setContext(Shop::CONTEXT_SHOP, $id_shop);
} catch (PrestaShopException $e) {
RetailcrmLogger::writeCaller(__METHOD__, 'Unable to set shop context');
}
Context::getContext()->shop = new Shop($id_shop);
}
/**
* @return array
*/
public static function getShops()
{
$idShop = Shop::getContextShopID();
if (Shop::isFeatureActive() && $idShop === null) {
return Shop::getShops(true, Shop::getContextShopGroupID(true));
} else {
return array(Shop::getShop($idShop));
}
}
}

View File

@ -74,8 +74,7 @@ class RetailcrmJobManager
* RetailcrmJobManager::startJobs(
* array(
* 'jobName' => DateInterval::createFromDateString('1 hour')
* ),
* true
* )
* );
*
* File `jobName.php` must exist in retailcrm/job and must contain everything to run job.
@ -84,27 +83,24 @@ class RetailcrmJobManager
* any delay - in other words, jobs without interval will be executed every time.
*
* @param array $jobs Jobs list
* @param bool $runOnceInContext Use require_once instead of require
*
* @throws \Exception
*/
public static function startJobs(
$jobs = array(),
$runOnceInContext = true
$jobs = array()
) {
RetailcrmLogger::writeDebug(__METHOD__,'starting JobManager');
static::execJobs($jobs, $runOnceInContext);
static::execJobs($jobs);
}
/**
* Run scheduled jobs with request
*
* @param array $jobs
* @param bool $runOnceInContext
*
* @throws \Exception
*/
public static function execJobs($jobs = array(), $runOnceInContext = false)
public static function execJobs($jobs = array())
{
$current = date_create('now');
$lastRuns = array();
@ -185,7 +181,7 @@ class RetailcrmJobManager
if (isset($shouldRunAt) && $shouldRunAt <= $current) {
RetailcrmLogger::writeDebug(__METHOD__, sprintf('Executing job %s', $job));
$result = RetailcrmJobManager::runJob($job, $runOnceInContext);
$result = RetailcrmJobManager::runJob($job);
RetailcrmLogger::writeDebug(
__METHOD__,
sprintf('Executed job %s, result: %s', $job, $result ? 'true' : 'false')
@ -198,39 +194,25 @@ class RetailcrmJobManager
if ($exception instanceof RetailcrmJobManagerException
&& $exception->getPrevious() instanceof \Exception
) {
$lastRunsDetails[$job] = [
'success' => false,
'lastRun' => new \DateTime('now'),
'error' => [
'message' => $exception->getPrevious()->getMessage(),
'trace' => $exception->getPrevious()->getTraceAsString(),
],
];
static::handleError(
$exception->getPrevious()->getFile(),
$exception->getPrevious()->getMessage(),
$exception->getPrevious()->getTraceAsString(),
$job
);
} else {
$lastRunsDetails[$job] = [
'success' => false,
'lastRun' => new \DateTime('now'),
'error' => [
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
],
];
static::handleError(
$exception->getFile(),
$exception->getMessage(),
$exception->getTraceAsString(),
$job
);
$exception = $exception->getPrevious();
}
$lastRunsDetails[$job] = [
'success' => false,
'lastRun' => new \DateTime('now'),
'error' => [
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
],
];
static::handleError(
$exception->getFile(),
$exception->getMessage(),
$exception->getTraceAsString(),
$job
);
self::clearCurrentJob($job);
}
}
@ -261,6 +243,50 @@ class RetailcrmJobManager
static::unlock();
}
/**
* Run job in the force mode so it will run even if there's another job running
*
* @param $jobName
* @return bool
* @throws Exception
*/
public static function execManualJob($jobName)
{
try {
$result = static::runJob($jobName, false, true, Shop::getContextShopID());
if ($result) {
static::updateLastRunDetail($jobName, [
'success' => true,
'lastRun' => new \DateTime('now'),
'error' => null,
]);
}
return $result;
} catch (\Exception $exception) {
if ($exception instanceof RetailcrmJobManagerException
&& $exception->getPrevious() instanceof \Exception
) {
$exception = $exception->getPrevious();
}
RetailcrmLogger::printException($exception, '', false);
self::updateLastRunDetail($jobName, [
'success' => false,
'lastRun' => new \DateTime('now'),
'error' => [
'message' => $exception->getMessage(),
'trace' => $exception->getTraceAsString(),
],
]);
throw $exception;
}
}
/**
* Extracts jobs last runs from db
*
@ -319,6 +345,17 @@ class RetailcrmJobManager
Configuration::updateGlobalValue(self::LAST_RUN_NAME, (string)json_encode($lastRuns));
}
/**
* @param string $jobName
* @param Datetime|null $data
* @throws Exception
*/
public static function updateLastRun($jobName, $data)
{
$lastRuns = static::getLastRuns();
$lastRuns[$jobName] = $data;
static::setLastRuns($lastRuns);
}
/**
* Extracts jobs last runs from db
@ -361,7 +398,7 @@ class RetailcrmJobManager
}
foreach ($lastRuns as $job => $details) {
if ($details['lastRun'] instanceof DateTime) {
if (isset($details['lastRun']) && $details['lastRun'] instanceof DateTime) {
$lastRuns[$job]['lastRun'] = $details['lastRun']->format(DATE_RFC3339);
} else {
$lastRuns[$job]['lastRun'] = null;
@ -371,41 +408,40 @@ class RetailcrmJobManager
Configuration::updateGlobalValue(self::LAST_RUN_DETAIL_NAME, (string)json_encode($lastRuns));
}
/**
* @param string $jobName
* @param array $data
* @throws Exception
*/
public static function updateLastRunDetail($jobName, $data)
{
$lastRunsDetails = static::getLastRunDetails();
$lastRunsDetails[$jobName] = $data;
static::setLastRunDetails($lastRunsDetails);
}
/**
* Runs job
*
* @param string $job
* @param bool $once
* @param bool $cliMode
* @param bool $force
* @param int $shopId
*
* @return bool
* @throws \RetailcrmJobManagerException
*/
public static function runJob($job, $once = false, $cliMode = false, $shopId = null)
public static function runJob($job, $cliMode = false, $force = false, $shopId = null)
{
$jobName = self::escapeJobName($job);
$jobFile = implode(
DIRECTORY_SEPARATOR,
array(_PS_ROOT_DIR_, 'modules', 'retailcrm_custom','classes', 'lib', 'events', $jobName . '.php')
);
if (!file_exists($jobFile)) {
$jobFile = implode(
DIRECTORY_SEPARATOR,
array(_PS_ROOT_DIR_, 'modules', 'retailcrm', 'lib', 'events', $jobName . '.php')
);
if (!file_exists($jobFile)) {
throw new \RetailcrmJobManagerException('Cannot find job', $job);
}
}
try {
return static::execHere($jobName, $jobFile, $once, $cliMode, $shopId);
return static::execHere($jobName, $cliMode, $force, $shopId);
} catch (\RetailcrmJobManagerException $exception) {
throw $exception;
} catch (\Exception $exception) {
throw new RetailcrmJobManagerException($exception->getMessage(), $jobFile, array(), 0, $exception);
throw new RetailcrmJobManagerException($exception->getMessage(), $job, array(), 0, $exception);
}
}
@ -601,15 +637,17 @@ class RetailcrmJobManager
* @param string $phpScript
* @param bool $once
* @param bool $cliMode
* @param bool $force
* @param int $shopId
*
* @return bool
* @throws \RetailcrmJobManagerException
*/
private static function execHere($jobName, $phpScript, $once = false, $cliMode = false, $shopId = null)
private static function execHere($jobName, $cliMode = false, $force = false, $shopId = null)
{
set_time_limit(static::getTimeLimit());
if (!$cliMode) {
if (!$cliMode && !$force) {
ignore_user_abort(true);
if (version_compare(phpversion(), '7.0.16', '>=') &&
@ -624,16 +662,9 @@ class RetailcrmJobManager
}
}
if ($once) {
require_once($phpScript);
} else {
require($phpScript);
}
if (!class_exists($jobName)) {
throw new \RetailcrmJobManagerException(sprintf(
'The job file "%s" has been found, but job class "%s" was not present in there.',
$phpScript,
'The job class "%s" was not found.',
$jobName
));
}
@ -648,6 +679,7 @@ class RetailcrmJobManager
}
$job->setCliMode($cliMode);
$job->setForce($force);
$job->setShopId($shopId);
self::registerShutdownHandler();

View File

@ -122,6 +122,22 @@ class RetailcrmLogger
}
}
/**
* Output error info to stdout
*
* @param $exception
* @param string $header
*/
public static function printException($exception, $header = 'Error while executing a job: ', $toOutput = true)
{
$method = $toOutput ? 'output' : 'writeNoCaller';
self::$method(sprintf('%s%s', $header, $exception->getMessage()));
self::$method(sprintf('%s:%d', $exception->getFile(), $exception->getLine()));
self::$method('');
self::$method($exception->getTraceAsString());
}
/**
* Write debug log record
*
@ -179,6 +195,11 @@ class RetailcrmLogger
return self::getLogDir() . '/retailcrm_' . self::getLogFilePrefix() . '_' . date('Y_m_d') . '.log';
}
/**
* Returns log files directory based on current Prestashop version
*
* @return string
*/
public static function getLogDir()
{
$logDir = version_compare(_PS_VERSION_, '1.7', '<') ? '/log' : '/var/logs';
@ -205,9 +226,47 @@ class RetailcrmLogger
}
/**
* Removes module log files from var/logs which is older than 30 days
* Removes module log files that are older than 30 days
*/
public static function clearObsoleteLogs()
{
$logFiles = self::getLogFiles();
foreach ($logFiles as $logFile) {
if (filemtime($logFile) < strtotime('-30 days')) {
unlink($logFile);
}
}
}
/**
* Retrieves log files basic info for advanced tab
*
* @return array
*/
public static function getLogFilesInfo()
{
$fileNames = [];
$logFiles = self::getLogFiles();
foreach ($logFiles as $logFile) {
$fileNames[] = [
'name' => basename($logFile),
'path' => $logFile,
'size' => number_format(filesize($logFile), 0, '.', ' ') . ' bytes',
'modified' => date('Y-m-d H:i:s', filemtime($logFile)),
];
}
return $fileNames;
}
/**
* Retrieves log files paths
*
* @return Generator|void
*/
private static function getLogFiles()
{
$logDir = self::getLogDir();
@ -218,40 +277,19 @@ class RetailcrmLogger
$handle = opendir($logDir);
while (($file = readdir($handle)) !== false) {
if (self::checkFileName($file) !== false) {
$path = "$logDir/$file";
if (filemtime($path) < strtotime('-30 days')) {
unlink($path);
}
yield "$logDir/$file";
}
}
}
public static function getLogFilesInfo()
{
$fileNames = [];
$logDir = self::getLogDir();
if (!is_dir($logDir)) {
return;
}
$handle = opendir($logDir);
while ($file = readdir($handle) !== false) {
if (self::checkFileName($file) !== false) {
$path = "$logDir/$file";
$fileNames[] = [
'name' => $file,
'path' => $path,
'size' => number_format(filesize($path), 0, '.', ' ') . ' bytes',
'modified' => date('Y-m-d H:i:s', filemtime($path)),
];
}
}
closedir($handle);
return $fileNames;
}
/**
* Checks if given logs filename relates to the module
*
* @param string $file
* @return false|string
*/
public static function checkFileName($file)
{
$logDir = self::getLogDir();

View File

@ -43,6 +43,9 @@ class RetailcrmReferences
public $carriers;
public $payment_modules = array();
/**
* @var bool|RetailcrmApiClientV5|RetailcrmProxy $api
*/
private $api;
public function __construct($client)
@ -340,6 +343,48 @@ class RetailcrmReferences
return $crmPaymentTypes;
}
public function getSite()
{
try {
$response = $this->api->credentials();
if (!($response instanceof RetailcrmApiResponse) || !$response->isSuccessful()
|| $response['siteAccess'] !== 'access_selective'
|| count($response['sitesAvailable']) !== 1
|| !in_array('/api/reference/sites', $response['credentials'])
|| !in_array('/api/reference/sites/{code}/edit', $response['credentials'])
) {
RetailcrmLogger::writeCaller(
__METHOD__,
sprintf(
'ShopID=%s: Error with CRM credentials: need an valid apiKey assigned to one certain site',
Shop::getContextShopID()
)
);
return null;
}
$response = $this->api->sitesList();
if ($response instanceof RetailcrmApiResponse && $response->isSuccessful()
&& $response->offsetExists('sites') && $response['sites']) {
return current($response['sites']);
}
} catch (Exception $e) {
RetailcrmLogger::writeCaller(
__METHOD__,
sprintf(
'Error: %s',
$e->getMessage()
)
);
}
return null;
}
public function getStores()
{
$storesShop = $this->getShopStores();

View File

@ -479,6 +479,7 @@ class RetailcrmTools
if (!empty($apiUrl) && !empty($apiKey)) {
return new RetailcrmProxy($apiUrl, $apiKey, RetailcrmLogger::getLogFile());
}
RetailcrmLogger::writeCaller(__METHOD__, 'Set api key & url first');
return null;
}
@ -758,17 +759,6 @@ class RetailcrmTools
return true;
}
/**
* Change shop in the context
*
* @param $id_shop
*/
public static function setShopContext($id_shop)
{
Shop::setContext(Shop::CONTEXT_SHOP, $id_shop);
Context::getContext()->shop = new Shop($id_shop);
}
/**
* Call custom filters for the object
*
@ -808,4 +798,47 @@ class RetailcrmTools
return $object;
}
/**
* @param $name
* @return array|false|mixed
*/
public static function getConfigurationByName($name)
{
$idShop = Shop::getContextShopID(true);
$idShopGroup = Shop::getContextShopGroupID(true);
$sql = 'SELECT *
FROM ' . _DB_PREFIX_ . 'configuration c
WHERE NAME = \'' . pSQL($name) . '\'
AND ( ' .
($idShop ? 'c.id_shop = \'' . pSQL($idShop) . '\' OR ' : '') .
($idShopGroup ? '( c.id_shop IS NULL AND c.id_shop_group = \'' . pSQL($idShopGroup) . '\') OR ' : '') . '
(c.id_shop IS NULL AND c.id_shop_group IS NULL)
)
ORDER BY c.id_shop DESC, c.id_shop_group DESC
LIMIT 1
';
try {
return current(Db::getInstance()->executeS($sql));
} catch (PrestaShopDatabaseException $e) {
return array();
}
}
/**
* @param $name
* @return DateTime|false
*/
public static function getConfigurationCreatedAtByName($name)
{
$config = self::getConfigurationByName($name);
if (empty($config)) {
return false;
}
return DateTime::createFromFormat('Y-m-d H:i:s', $config['date_add']);
}
}

View File

@ -58,7 +58,7 @@ class RetailcrmAbandonedCartsEvent extends RetailcrmAbstractEvent implements Ret
}
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
$syncCartsActive = Configuration::get(RetailCRM::SYNC_CARTS_ACTIVE);
@ -71,8 +71,6 @@ class RetailcrmAbandonedCartsEvent extends RetailcrmAbstractEvent implements Ret
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
continue;
}

View File

@ -41,6 +41,7 @@ require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
abstract class RetailcrmAbstractEvent implements RetailcrmEventInterface
{
private $cliMode;
private $force;
private $shopId;
/**
@ -66,6 +67,14 @@ abstract class RetailcrmAbstractEvent implements RetailcrmEventInterface
$this->cliMode = (bool)$mode;
}
/**
* @param mixed $force
*/
public function setForce($force)
{
$this->force = (bool)$force;
}
/**
* Sets context shop id.
*
@ -84,8 +93,7 @@ abstract class RetailcrmAbstractEvent implements RetailcrmEventInterface
*/
protected function isRunning()
{
return (strcmp(RetailcrmJobManager::getCurrentJob(), $this->getName() === 0))
|| (strcmp(RetailcrmCli::getCurrentJob(), $this->getName() === 0));
return !$this->force && (RetailcrmJobManager::getCurrentJob() !== '' || RetailcrmCli::getCurrentJob() !== '');
}
/**
@ -95,6 +103,10 @@ abstract class RetailcrmAbstractEvent implements RetailcrmEventInterface
*/
protected function setRunning()
{
if($this->force) {
return true;
}
if ($this->cliMode) {
return RetailcrmCli::setCurrentJob($this->getName());
}

View File

@ -60,6 +60,13 @@ interface RetailcrmEventInterface
*/
public function setCliMode($mode);
/**
* Sets force mode to true. Force mode here stands for any execution outside of JobManager & CLI context.
*
* @param bool $force
*/
public function setForce($force);
/**
* Sets context shop id.
*

View File

@ -54,13 +54,11 @@ class RetailcrmExportEvent extends RetailcrmAbstractEvent implements RetailcrmEv
$shops = $this->getShops();
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
continue;
}

View File

@ -53,21 +53,13 @@ class RetailcrmIcmlEvent extends RetailcrmAbstractEvent implements RetailcrmEven
$shops = $this->getShops();
$isMultiStoreActive = Shop::isFeatureActive();
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
$job = new RetailcrmCatalog();
$data = $job->getData();
if ($isMultiStoreActive) {
$icmlFileName = 'simla_' . $shop['id_shop'] . '.xml';
} else {
$icmlFileName = 'simla.xml';
}
$icml = new RetailcrmIcml($shop['name'], _PS_ROOT_DIR_ . '/' . $icmlFileName);
$icml = new RetailcrmIcml($shop['name'], RetailcrmCatalogHelper::getIcmlFilePath());
$icml->generate($data[0], $data[1]);
}

View File

@ -0,0 +1,95 @@
<?php
/**
* MIT License
*
* Copyright (c) 2020 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* 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 <mail@simlachat.com>
* @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.
*/
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
class RetailcrmIcmlUpdateUrlEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
{
/**
* @inheritDoc
*/
public function execute()
{
if ($this->isRunning()) {
return false;
}
$this->setRunning();
$shops = $this->getShops();
foreach ($shops as $shop) {
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
if (!file_exists(RetailcrmCatalogHelper::getIcmlFilePath())) {
continue;
}
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
continue;
}
$reference = new RetailcrmReferences($api);
$site = $reference->getSite();
if (empty($site)) {
continue;
}
$newYmlUrl = RetailcrmCatalogHelper::getIcmlFileLink();
$siteCode = $site['code'];
if ($newYmlUrl !== $site['ymlUrl']) {
$api->sitesEdit([
'code' => $siteCode,
'ymlUrl' => $newYmlUrl,
]);
}
}
return true;
}
/**
* @inheritDoc
*/
public function getName()
{
return 'RetailcrmIcmlUpdateUrlEvent';
}
}

View File

@ -54,7 +54,7 @@ class RetailcrmInventoriesEvent extends RetailcrmAbstractEvent implements Retail
$shops = $this->getShops();
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
if (!Configuration::get(RetailCRM::ENABLE_BALANCES_RECEIVING)) {
RetailcrmLogger::writeDebug(

View File

@ -61,7 +61,7 @@ class RetailcrmMissingEvent extends RetailcrmAbstractEvent implements RetailcrmE
}
$orderInstance = new Order($options['o']);
RetailcrmTools::setShopContext($orderInstance->id_shop);
RetailcrmContextSwitcher::setShopContext($orderInstance->id_shop);
$apiUrl = Configuration::get(RetailCRM::API_URL);
$apiKey = Configuration::get(RetailCRM::API_KEY);

View File

@ -54,7 +54,7 @@ class RetailcrmSyncEvent extends RetailcrmAbstractEvent implements RetailcrmEven
$shops = $this->getShops();
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
if (!Configuration::get(RetailCRM::ENABLE_HISTORY_UPLOADS)) {
RetailcrmLogger::writeDebug(

View File

@ -54,13 +54,11 @@ class RetailcrmUpdateSinceIdEvent extends RetailcrmAbstractEvent implements Reta
$shops = $this->getShops();
foreach ($shops as $shop) {
RetailcrmTools::setShopContext(intval($shop['id_shop']));
RetailcrmContextSwitcher::setShopContext(intval($shop['id_shop']));
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set api key & url first');
continue;
}

View File

@ -83,6 +83,8 @@ class RetailcrmSettingsTemplate extends RetailcrmAbstractTemplate
$params['currentJob'] = Configuration::get(RetailcrmJobManager::CURRENT_TASK);
$params['currentJobCli'] = Configuration::get(RetailcrmCli::CURRENT_TASK_CLI);
$params['retailcrmLogsInfo'] = RetailcrmLogger::getLogFilesInfo();
$params['catalogInfoMultistore'] = RetailcrmCatalogHelper::getIcmlFileInfoMultistore();
$params['shopsInfo'] = RetailcrmContextSwitcher::getShops();
$params['errorTabs'] = $this->module->validateStoredSettings();
}

View File

@ -63,6 +63,7 @@ class RetailCRM extends Module
const SYNC_CARTS_STATUS = 'RETAILCRM_API_SYNCHRONIZED_CART_STATUS';
const SYNC_CARTS_DELAY = 'RETAILCRM_API_SYNCHRONIZED_CART_DELAY';
const UPLOAD_ORDERS = 'RETAILCRM_UPLOAD_ORDERS_ID';
const RUN_JOB = 'RETAILCRM_RUN_JOB';
const EXPORT_ORDERS = 'RETAILCRM_EXPORT_ORDERS_STEP';
const EXPORT_CUSTOMERS = 'RETAILCRM_EXPORT_CUSTOMERS_STEP';
const UPDATE_SINCE_ID = 'RETAILCRM_UPDATE_SINCE_ID';
@ -81,6 +82,7 @@ class RetailCRM extends Module
const JOBS_NAMES = [
'RetailcrmAbandonedCartsEvent' => 'Abandoned Carts',
'RetailcrmIcmlEvent' => 'Icml generation',
'RetailcrmIcmlUpdateUrlEvent' => 'Icml update URL',
'RetailcrmSyncEvent' => 'History synchronization',
'RetailcrmInventoriesEvent' => 'Inventories uploads',
'RetailcrmClearLogsEvent' => 'Clearing logs'
@ -245,6 +247,7 @@ class RetailCRM extends Module
Configuration::deleteByName('RETAILCRM_LAST_CUSTOMERS_SYNC') &&
Configuration::deleteByName(RetailcrmJobManager::LAST_RUN_NAME) &&
Configuration::deleteByName(RetailcrmJobManager::LAST_RUN_DETAIL_NAME) &&
Configuration::deleteByName(RetailcrmCatalogHelper::ICML_INFO_NAME) &&
Configuration::deleteByName(RetailcrmJobManager::IN_PROGRESS_NAME) &&
Configuration::deleteByName(RetailcrmJobManager::CURRENT_TASK) &&
Configuration::deleteByName(RetailcrmCli::CURRENT_TASK_CLI) &&
@ -276,6 +279,8 @@ class RetailCRM extends Module
$token = Configuration::get(static::API_KEY);
if (Tools::isSubmit('submit' . $this->name)) {
// todo all those vars & ifs to one $command var and check in switch
$jobName = (string)(Tools::getValue(static::RUN_JOB));
$ordersIds = (string)(Tools::getValue(static::UPLOAD_ORDERS));
$exportOrders = (int)(Tools::getValue(static::EXPORT_ORDERS));
$exportCustomers = (int)(Tools::getValue(static::EXPORT_CUSTOMERS));
@ -285,6 +290,8 @@ class RetailCRM extends Module
if (!empty($ordersIds)) {
$output .= $this->uploadOrders(RetailcrmTools::partitionId($ordersIds));
} elseif (!empty($jobName)) {
$this->runJobMultistore($jobName);
} elseif (!empty($exportOrders)) {
return $this->export($exportOrders);
} elseif (!empty($exportCustomers)) {
@ -401,6 +408,43 @@ class RetailCRM extends Module
}
}
/**
* @param string $jobName
* @return string
*/
public function runJob($jobName)
{
$jobNameFront = (empty(static::JOBS_NAMES[$jobName]) ? $jobName : static::JOBS_NAMES[$jobName]);
try {
if (RetailcrmJobManager::execManualJob($jobName)) {
return $this->displayConfirmation(sprintf(
'%s %s',
$this->l($jobNameFront),
$this->l('was completed successfully')
));
} else {
return $this->displayError(sprintf(
'%s %s',
$this->l($jobNameFront),
$this->l('was not executed')
));
}
} catch (Exception $e) {
return $this->displayError(sprintf(
'%s %s: %s',
$this->l($jobNameFront),
$this->l('was completed with errors'),
$e->getMessage()
));
}
}
public function runJobMultistore($jobName)
{
RetailcrmContextSwitcher::runInContext(array($this, 'runJob'), array($jobName));
}
/**
* @param int $step
* @param string $entity
@ -420,7 +464,6 @@ class RetailCRM extends Module
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
return RetailcrmJsonResponse::invalidResponse('Set API key & URL first');
}
@ -453,7 +496,6 @@ class RetailCRM extends Module
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
return RetailcrmJsonResponse::invalidResponse('Set API key & URL first');
}
@ -1124,6 +1166,10 @@ class RetailCRM extends Module
}
}
if (!$this->validateCatalogMultistore()) {
$output[] = 'catalog';
}
return $output;
}
@ -1144,6 +1190,49 @@ class RetailCRM extends Module
return true;
}
/**
* Catalog info validator
*
* @return bool
*/
public function validateCatalog()
{
$icmlInfo = RetailcrmCatalogHelper::getIcmlFileInfo();
if (!$icmlInfo || !isset($icmlInfo['lastGenerated'])) {
$urlConfiguredAt = RetailcrmTools::getConfigurationCreatedAtByName(self::API_KEY);
if ($urlConfiguredAt instanceof DateTime) {
$now = new DateTime();
/** @var DateInterval $diff */
$diff = $urlConfiguredAt->diff($now);
if (($diff->days * 24 + $diff->h) > 4) {
return false;
}
}
} elseif ($icmlInfo['isOutdated'] || !$icmlInfo['isUrlActual']) {
return false;
}
return true;
}
/**
* Catalog info validator for multistore
*
* @return bool
*/
private function validateCatalogMultistore()
{
$results = RetailcrmContextSwitcher::runInContext(array($this, 'validateCatalog'));
$results = array_filter($results, function ($item) {
return !$item;
});
return empty($results);
}
/**
* Settings form validator
*
@ -1298,6 +1387,7 @@ class RetailCRM extends Module
'synchronizedCartStatusName' => static::SYNC_CARTS_STATUS,
'synchronizedCartDelayName' => static::SYNC_CARTS_DELAY,
'uploadOrders' => static::UPLOAD_ORDERS,
'runJobName' => static::RUN_JOB,
'consultantScriptName' => static::CONSULTANT_SCRIPT,
'enableCorporateName' => static::ENABLE_CORPORATE_CLIENTS,
'enableHistoryUploadsName' => static::ENABLE_HISTORY_UPLOADS,

View File

@ -8,6 +8,9 @@ $_MODULE['<{retailcrm}prestashop>retailcrm_876f23178c29dc2552c0b48bf23cd9bd'] =
$_MODULE['<{retailcrm}prestashop>retailcrm_6bd461d1fc51b3294c6513cecc24758d'] = 'Los pedidos han sido cargados con éxito';
$_MODULE['<{retailcrm}prestashop>retailcrm_9a7fc06b4b2359f1f26f75fbbe27a3e8'] = 'No todos los pedidos se han cargado con existo';
$_MODULE['<{retailcrm}prestashop>retailcrm_e7244a5e543ba692ebc495aee934ee9b'] = 'Orden omitida por inexistencia: %s';
$_MODULE['<{retailcrm}prestashop>retailcrm_474b50f70e008454f1f2bf0d63f5262a'] = 'se completó con éxito';
$_MODULE['<{retailcrm}prestashop>retailcrm_7f3df1b66ce2d61ae3d31c97ac08b065'] = 'no fue ejecutado';
$_MODULE['<{retailcrm}prestashop>retailcrm_8bc2706bb353ba02b05135127122e406'] = 'se completó con errores ';
$_MODULE['<{retailcrm}prestashop>retailcrm_b9b2d9f66d0112f3aae7dbdbd4e22a43'] = 'La dirección del CRM es incorrecta o está vacía';
$_MODULE['<{retailcrm}prestashop>retailcrm_942010ef43f3fec28741f62a0d9ff29c'] = 'La clave CRM es incorrecta o está vacía';
$_MODULE['<{retailcrm}prestashop>retailcrm_1bd340aeb42a5ee0318784c2cffed8a9'] = 'La versión seleccionada de la API no está disponible';
@ -23,6 +26,76 @@ $_MODULE['<{retailcrm}prestashop>retailcrm_d5bb7c2cb1565fb1568924b01847b330'] =
$_MODULE['<{retailcrm}prestashop>retailcrm_9d3095e54f694bb41ef4a3e62ed90e7a'] = 'Tras 30 minutos';
$_MODULE['<{retailcrm}prestashop>retailcrm_dfb403fd86851c7d9f97706dff5a2327'] = 'Tras 45 minutos';
$_MODULE['<{retailcrm}prestashop>retailcrm_4b5e6470d5d85448fcd89c828352d25e'] = 'Tras 1 hora';
$_MODULE['<{retailcrm}prestashop>settings_2b65c584b7b4d7bd19d36f7d2b690c6a'] = 'Catálogo Icml';
$_MODULE['<{retailcrm}prestashop>settings_c2cc7082a89c1ad6631a2f66af5f00c0'] = 'Conexión';
$_MODULE['<{retailcrm}prestashop>settings_065ab3a28ca4f16f55f103adc7d0226f'] = 'Los métodos del envío';
$_MODULE['<{retailcrm}prestashop>settings_33af8066d3c83110d4bd897f687cedd2'] = 'Los estados de pedidos';
$_MODULE['<{retailcrm}prestashop>settings_bab959acc06bb03897b294fbb892be6b'] = 'Los métodos de pago';
$_MODULE['<{retailcrm}prestashop>settings_7a1920d61156abc05a60135aefe8bc67'] = 'Por defecto';
$_MODULE['<{retailcrm}prestashop>settings_20cacc01d0de8bc6e9c9846f477e886b'] = 'Subir pedidos';
$_MODULE['<{retailcrm}prestashop>settings_6bcde6286f8d1b76063ee52104a240cf'] = 'Carritos abandonados';
$_MODULE['<{retailcrm}prestashop>settings_52a13123e134b8b72b6299bc14a36aad'] = 'Daemon Collector';
$_MODULE['<{retailcrm}prestashop>settings_71098155ccc0a0d6e0b501fbee37e7a9'] = 'LiveChat';
$_MODULE['<{retailcrm}prestashop>settings_9b6545e4cea9b4ad4979d41bb9170e2b'] = 'Avanzado';
$_MODULE['<{retailcrm}prestashop>settings_061b368c43f85d3fe2c7ccc842883a40'] = 'La configuración de la conexión';
$_MODULE['<{retailcrm}prestashop>settings_22a65bd0ef1919aa4e6dee849a7a2925'] = 'Simla.com URL';
$_MODULE['<{retailcrm}prestashop>settings_656a6828d7ef1bb791e42087c4b5ee6e'] = 'API key';
$_MODULE['<{retailcrm}prestashop>settings_8ffa3281a35a0d80fef2cac0fa680523'] = 'Habilitar la carga del historial';
$_MODULE['<{retailcrm}prestashop>settings_65dd9f6e8bf4eaf54c3dc96f011dade1'] = 'Recibir las existencias del Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_f8d7c52aa84f358caedb96fda86809da'] = 'Permitir el soporte a clientes corporativos';
$_MODULE['<{retailcrm}prestashop>settings_6c3c1845e109a9ef67378effea0c0503'] = 'Activar solo si está habilitada la opción \"Clientes corporativos\" en Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_917afe348e09163269225a89a825e634'] = 'Sincronización de carritos de compradores';
$_MODULE['<{retailcrm}prestashop>settings_d8e002d770b6f98af7b7ae9a0e5acfe9'] = 'Crear pedidos para carritos abandonados de compradores';
$_MODULE['<{retailcrm}prestashop>settings_35b5a9139a54caeb925556ceb2c38086'] = 'Estado del pedido para carritos abandonados de compradores';
$_MODULE['<{retailcrm}prestashop>settings_9b9cf9f8778f69b4c6cf37e66f886be8'] = 'Elige el estado';
$_MODULE['<{retailcrm}prestashop>settings_a0d135501a738c3c98de385dc28cda61'] = 'Cargar carritos abandonados';
$_MODULE['<{retailcrm}prestashop>settings_27096e1243f98e1b3300f57ff1c76456'] = 'Elige la demora';
$_MODULE['<{retailcrm}prestashop>settings_1f8246b1e6ada8897902eff8d8cd8f35'] = 'está desactualizado';
$_MODULE['<{retailcrm}prestashop>settings_4a15f35e8d386dd1d96faa83c1e44a22'] = 'Actualizar URL';
$_MODULE['<{retailcrm}prestashop>settings_5b55e5aeb08a372d36f7e4b7b35d1cd1'] = 'URL del catalogo Icml en Prestashop y en %s no coinciden';
$_MODULE['<{retailcrm}prestashop>settings_06aa6fa8bdc2078e7e1bd903e70c8f6a'] = 'esta conectado';
$_MODULE['<{retailcrm}prestashop>settings_7892a1894478824c07b62af2df839291'] = 'Más de 7 días';
$_MODULE['<{retailcrm}prestashop>settings_8277e0910d750195b448797616e091ad'] = 'd';
$_MODULE['<{retailcrm}prestashop>settings_2510c39011c5be704182423e3a695e91'] = 'h';
$_MODULE['<{retailcrm}prestashop>settings_d8bd79cc131920d5de426f914d17405a'] = 'min';
$_MODULE['<{retailcrm}prestashop>settings_3baa7e02e09dba2ba2a188a7c9a055cb'] = 'pasado desde la última ejecución';
$_MODULE['<{retailcrm}prestashop>settings_068f80c7519d0528fb08e82137a72131'] = 'Productos';
$_MODULE['<{retailcrm}prestashop>settings_9461bed8b71377318436990e57106729'] = 'Ofertas';
$_MODULE['<{retailcrm}prestashop>settings_64ef97a8fe9db8b672287a53c5d836f2'] = 'aún no se generó';
$_MODULE['<{retailcrm}prestashop>settings_79c07dbacf542d283944685e1538a1bb'] = 'Presione el botón de abajo para generar el %s';
$_MODULE['<{retailcrm}prestashop>settings_cc84d5b49b62c0959f1af64bffaec3b7'] = 'Generar ahora';
$_MODULE['<{retailcrm}prestashop>settings_4e537de8dd108eafec4c37603c8ab7fb'] = 'Administrar tipos de entrega';
$_MODULE['<{retailcrm}prestashop>settings_5b385947acf10ac0c5521161ce96aaa7'] = 'Elige la entrega';
$_MODULE['<{retailcrm}prestashop>settings_c0fd6d31d096a5845f1d1abb4c132b7d'] = 'Administrar estados de pedidos';
$_MODULE['<{retailcrm}prestashop>settings_dd53d9b3603b3279b25c74f6f3f189a4'] = 'Administrar tipos de pago';
$_MODULE['<{retailcrm}prestashop>settings_7dcc1208fa03381346955c6732d9ea85'] = 'Elige el tipo';
$_MODULE['<{retailcrm}prestashop>settings_6f1f9a3e435963417d08849fbef139c1'] = 'Ingrese los ID de los pedidos para cargar en Simla.com, divididos por una coma. También puede especificar rangos, como \"1-10\". Se permite subir hasta 10 pedidos a la vez.';
$_MODULE['<{retailcrm}prestashop>settings_acfa058ec9e6e4745eddc0cae3f0f881'] = 'Identificador del pedido';
$_MODULE['<{retailcrm}prestashop>settings_91412465ea9169dfd901dd5e7c96dd99'] = 'Subir';
$_MODULE['<{retailcrm}prestashop>settings_f4af7f6987dfee28741ce77ff2d09d46'] = 'Exportar pedidos y clientes';
$_MODULE['<{retailcrm}prestashop>settings_418faff1c9df0d297ff586ac3230be97'] = 'Puede exportar todos los pedidos y clientes de CMS a Simla.com presionando el botón \"Exportar\". Este proceso puede llevar mucho tiempo y es necesario que mantenga la pestaña abierta hasta que termine.';
$_MODULE['<{retailcrm}prestashop>settings_7442e29d7d53e549b78d93c46b8cdcfc'] = 'Pedidos';
$_MODULE['<{retailcrm}prestashop>settings_e6d0e1c8fc6a4fcf47869df87e04cd88'] = 'Clientes';
$_MODULE['<{retailcrm}prestashop>settings_f8f36c02fa6f370808135c66cfc788aa'] = 'Clientes sin pedidos';
$_MODULE['<{retailcrm}prestashop>settings_0095a9fa74d1713e43e370a7d7846224'] = 'Exportar';
$_MODULE['<{retailcrm}prestashop>settings_4d3d769b812b6faa6b76e1a8abaece2d'] = 'Active';
$_MODULE['<{retailcrm}prestashop>settings_f75d8fa5c89351544d372cf90528ccf2'] = 'Clave de la página web';
$_MODULE['<{retailcrm}prestashop>settings_c9cc8cce247e49bae79f15173ce97354'] = 'Guardar';
$_MODULE['<{retailcrm}prestashop>settings_4f18e3f1c9941a6ec5a38bc716c521b4'] = 'Código que necesita insertar en la web';
$_MODULE['<{retailcrm}prestashop>settings_ec3028a12402ab7f43962a6f3a667b6e'] = 'Modo de depuración';
$_MODULE['<{retailcrm}prestashop>settings_9082f68bc90113d8950e4ed7fe8fa0a4'] = 'Administrador de tareas';
$_MODULE['<{retailcrm}prestashop>settings_9194de58ce560c095f02cefc1c1c61e6'] = 'Nombre de la tarea';
$_MODULE['<{retailcrm}prestashop>settings_05a3a24340b7b9cc8d4e08f0ef4f4dd9'] = 'Última ejecución';
$_MODULE['<{retailcrm}prestashop>settings_ec53a8c4f07baed5d8825072c89799be'] = 'Estado';
$_MODULE['<{retailcrm}prestashop>settings_0be8406951cdfda82f00f79328cf4efc'] = 'Comentario';
$_MODULE['<{retailcrm}prestashop>settings_fe5b6cd4d7a31615bbec8d1505089d87'] = 'StackTrace';
$_MODULE['<{retailcrm}prestashop>settings_b2d37ae1cedf42ff874289b721860af2'] = 'Registros';
$_MODULE['<{retailcrm}prestashop>settings_34082694d21dbdcfc31e6e32d9fb2b9f'] = 'Nombre del archivo';
$_MODULE['<{retailcrm}prestashop>settings_a4b7f1864cfdb47cd05b54eb10337506'] = 'Fecha de modificación';
$_MODULE['<{retailcrm}prestashop>settings_6f6cb72d544962fa333e2e34ce64f719'] = 'Tamaño';
$_MODULE['<{retailcrm}prestashop>settings_06df33001c1d7187fdd81ea1f5b277aa'] = 'Comportamiento';
$_MODULE['<{retailcrm}prestashop>settings_801ab24683a4a8c433c6eb40c48bcd9d'] = 'Descargar';
$_MODULE['<{retailcrm}prestashop>settings_61b0ada67b7f40bf3d40dcc88ae4f3e6'] = 'Descargar todo';
$_MODULE['<{retailcrm}prestashop>index_dd259436b3f29f0ba1778d220b343ec9'] = 'Simla.com es un servicio para tiendas online, el cual ayuda a dejar de perder pedidos y así mejorar las ganancias de tu comercio online en todas las etapas del embudo de ventas.';
$_MODULE['<{retailcrm}prestashop>index_c7476a92e20715b855d72b1786a71017'] = 'Tengo una cuenta en Simla.com';
$_MODULE['<{retailcrm}prestashop>index_e81c4e4f2b7b93b481e13a8553c2ae1b'] = 'o';
@ -79,58 +152,3 @@ $_MODULE['<{retailcrm}prestashop>index_95428f32e5c696cf71baccb776bc5c15'] = 'Tra
$_MODULE['<{retailcrm}prestashop>index_e7f9e382dc50889098cbe56f2554c77b'] = 'Tarjeta bancaria';
$_MODULE['<{retailcrm}prestashop>index_7088f1d1d9c91d8b75e9882ffd78540c'] = 'Datos de contacto';
$_MODULE['<{retailcrm}prestashop>index_50f158e2507321f1a5b6f8fb9e350818'] = 'Escríbenos en caso de preguntas o dudas';
$_MODULE['<{retailcrm}prestashop>settings_c2cc7082a89c1ad6631a2f66af5f00c0'] = 'Conexión';
$_MODULE['<{retailcrm}prestashop>settings_065ab3a28ca4f16f55f103adc7d0226f'] = 'Los métodos del envío';
$_MODULE['<{retailcrm}prestashop>settings_33af8066d3c83110d4bd897f687cedd2'] = 'Los estados de pedidos';
$_MODULE['<{retailcrm}prestashop>settings_bab959acc06bb03897b294fbb892be6b'] = 'Los métodos de pago';
$_MODULE['<{retailcrm}prestashop>settings_7a1920d61156abc05a60135aefe8bc67'] = 'Por defecto';
$_MODULE['<{retailcrm}prestashop>settings_20cacc01d0de8bc6e9c9846f477e886b'] = 'Subir pedidos';
$_MODULE['<{retailcrm}prestashop>settings_6bcde6286f8d1b76063ee52104a240cf'] = 'Carritos abandonados';
$_MODULE['<{retailcrm}prestashop>settings_52a13123e134b8b72b6299bc14a36aad'] = 'Daemon Collector';
$_MODULE['<{retailcrm}prestashop>settings_71098155ccc0a0d6e0b501fbee37e7a9'] = 'LiveChat';
$_MODULE['<{retailcrm}prestashop>settings_9b6545e4cea9b4ad4979d41bb9170e2b'] = 'Avanzado';
$_MODULE['<{retailcrm}prestashop>settings_061b368c43f85d3fe2c7ccc842883a40'] = 'La configuración de la conexión';
$_MODULE['<{retailcrm}prestashop>settings_22a65bd0ef1919aa4e6dee849a7a2925'] = 'Simla.com URL';
$_MODULE['<{retailcrm}prestashop>settings_656a6828d7ef1bb791e42087c4b5ee6e'] = 'API key';
$_MODULE['<{retailcrm}prestashop>settings_8ffa3281a35a0d80fef2cac0fa680523'] = 'Habilitar la carga del historial';
$_MODULE['<{retailcrm}prestashop>settings_65dd9f6e8bf4eaf54c3dc96f011dade1'] = 'Recibir las existencias del Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_f8d7c52aa84f358caedb96fda86809da'] = 'Permitir el soporte a clientes corporativos';
$_MODULE['<{retailcrm}prestashop>settings_6c3c1845e109a9ef67378effea0c0503'] = 'Activar solo si está habilitada la opción \"Clientes corporativos\" en Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_917afe348e09163269225a89a825e634'] = 'Sincronización de carritos de compradores';
$_MODULE['<{retailcrm}prestashop>settings_d8e002d770b6f98af7b7ae9a0e5acfe9'] = 'Crear pedidos para carritos abandonados de compradores';
$_MODULE['<{retailcrm}prestashop>settings_35b5a9139a54caeb925556ceb2c38086'] = 'Estado del pedido para carritos abandonados de compradores';
$_MODULE['<{retailcrm}prestashop>settings_9b9cf9f8778f69b4c6cf37e66f886be8'] = 'Elige el estado';
$_MODULE['<{retailcrm}prestashop>settings_a0d135501a738c3c98de385dc28cda61'] = 'Cargar carritos abandonados';
$_MODULE['<{retailcrm}prestashop>settings_27096e1243f98e1b3300f57ff1c76456'] = 'Elige la demora';
$_MODULE['<{retailcrm}prestashop>settings_4e537de8dd108eafec4c37603c8ab7fb'] = 'Administrar tipos de entrega';
$_MODULE['<{retailcrm}prestashop>settings_5b385947acf10ac0c5521161ce96aaa7'] = 'Elige la entrega';
$_MODULE['<{retailcrm}prestashop>settings_c0fd6d31d096a5845f1d1abb4c132b7d'] = 'Administrar estados de pedidos';
$_MODULE['<{retailcrm}prestashop>settings_dd53d9b3603b3279b25c74f6f3f189a4'] = 'Administrar tipos de pago';
$_MODULE['<{retailcrm}prestashop>settings_7dcc1208fa03381346955c6732d9ea85'] = 'Elige el tipo';
$_MODULE['<{retailcrm}prestashop>settings_6f1f9a3e435963417d08849fbef139c1'] = 'Ingrese los ID de los pedidos para cargar en Simla.com, divididos por una coma. También puede especificar rangos, como \"1-10\". Se permite subir hasta 10 pedidos a la vez.';
$_MODULE['<{retailcrm}prestashop>settings_acfa058ec9e6e4745eddc0cae3f0f881'] = 'Identificador del pedido';
$_MODULE['<{retailcrm}prestashop>settings_91412465ea9169dfd901dd5e7c96dd99'] = 'Subir';
$_MODULE['<{retailcrm}prestashop>settings_f4af7f6987dfee28741ce77ff2d09d46'] = 'Exportar pedidos y clientes';
$_MODULE['<{retailcrm}prestashop>settings_418faff1c9df0d297ff586ac3230be97'] = 'Puede exportar todos los pedidos y clientes de CMS a Simla.com presionando el botón \"Exportar\". Este proceso puede llevar mucho tiempo y es necesario que mantenga la pestaña abierta hasta que termine.';
$_MODULE['<{retailcrm}prestashop>settings_7442e29d7d53e549b78d93c46b8cdcfc'] = 'Pedidos';
$_MODULE['<{retailcrm}prestashop>settings_e6d0e1c8fc6a4fcf47869df87e04cd88'] = 'Clientes';
$_MODULE['<{retailcrm}prestashop>settings_f8f36c02fa6f370808135c66cfc788aa'] = 'Clientes sin pedidos';
$_MODULE['<{retailcrm}prestashop>settings_0095a9fa74d1713e43e370a7d7846224'] = 'Exportar';
$_MODULE['<{retailcrm}prestashop>settings_4d3d769b812b6faa6b76e1a8abaece2d'] = 'Active';
$_MODULE['<{retailcrm}prestashop>settings_f75d8fa5c89351544d372cf90528ccf2'] = 'Clave de la página web';
$_MODULE['<{retailcrm}prestashop>settings_c9cc8cce247e49bae79f15173ce97354'] = 'Guardar';
$_MODULE['<{retailcrm}prestashop>settings_4f18e3f1c9941a6ec5a38bc716c521b4'] = 'Código que necesita insertar en la web';
$_MODULE['<{retailcrm}prestashop>settings_ec3028a12402ab7f43962a6f3a667b6e'] = 'Modo de depuración';
$_MODULE['<{retailcrm}prestashop>settings_9082f68bc90113d8950e4ed7fe8fa0a4'] = 'Administrador de tareas';
$_MODULE['<{retailcrm}prestashop>settings_9194de58ce560c095f02cefc1c1c61e6'] = 'Nombre de la tarea';
$_MODULE['<{retailcrm}prestashop>settings_05a3a24340b7b9cc8d4e08f0ef4f4dd9'] = 'Última ejecución';
$_MODULE['<{retailcrm}prestashop>settings_ec53a8c4f07baed5d8825072c89799be'] = 'Estado';
$_MODULE['<{retailcrm}prestashop>settings_0be8406951cdfda82f00f79328cf4efc'] = 'Comentario';
$_MODULE['<{retailcrm}prestashop>settings_fe5b6cd4d7a31615bbec8d1505089d87'] = 'StackTrace';
$_MODULE['<{retailcrm}prestashop>settings_b2d37ae1cedf42ff874289b721860af2'] = 'Registros';
$_MODULE['<{retailcrm}prestashop>settings_34082694d21dbdcfc31e6e32d9fb2b9f'] = 'Nombre del archivo';
$_MODULE['<{retailcrm}prestashop>settings_a4b7f1864cfdb47cd05b54eb10337506'] = 'Fecha de modificación';
$_MODULE['<{retailcrm}prestashop>settings_6f6cb72d544962fa333e2e34ce64f719'] = 'Tamaño';
$_MODULE['<{retailcrm}prestashop>settings_06df33001c1d7187fdd81ea1f5b277aa'] = 'Comportamiento';
$_MODULE['<{retailcrm}prestashop>settings_801ab24683a4a8c433c6eb40c48bcd9d'] = 'Descargar';
$_MODULE['<{retailcrm}prestashop>settings_61b0ada67b7f40bf3d40dcc88ae4f3e6'] = 'Descargar todo';

View File

@ -8,6 +8,9 @@ $_MODULE['<{retailcrm}prestashop>retailcrm_876f23178c29dc2552c0b48bf23cd9bd'] =
$_MODULE['<{retailcrm}prestashop>retailcrm_6bd461d1fc51b3294c6513cecc24758d'] = 'Все заказы успешно загружены';
$_MODULE['<{retailcrm}prestashop>retailcrm_9a7fc06b4b2359f1f26f75fbbe27a3e8'] = 'Не все заказы загружены успешно';
$_MODULE['<{retailcrm}prestashop>retailcrm_e7244a5e543ba692ebc495aee934ee9b'] = 'Заказы не найдены и пропущены: %s';
$_MODULE['<{retailcrm}prestashop>retailcrm_474b50f70e008454f1f2bf0d63f5262a'] = 'завершена успешно';
$_MODULE['<{retailcrm}prestashop>retailcrm_7f3df1b66ce2d61ae3d31c97ac08b065'] = 'не была запущена';
$_MODULE['<{retailcrm}prestashop>retailcrm_8bc2706bb353ba02b05135127122e406'] = 'завершена с ошибками';
$_MODULE['<{retailcrm}prestashop>retailcrm_b9b2d9f66d0112f3aae7dbdbd4e22a43'] = 'Некорректный или пустой адрес CRM';
$_MODULE['<{retailcrm}prestashop>retailcrm_942010ef43f3fec28741f62a0d9ff29c'] = 'Некорректный или пустой ключ CRM';
$_MODULE['<{retailcrm}prestashop>retailcrm_1bd340aeb42a5ee0318784c2cffed8a9'] = 'Выбранная версия API недоступна';
@ -23,6 +26,76 @@ $_MODULE['<{retailcrm}prestashop>retailcrm_d5bb7c2cb1565fb1568924b01847b330'] =
$_MODULE['<{retailcrm}prestashop>retailcrm_9d3095e54f694bb41ef4a3e62ed90e7a'] = 'Через 30 минут';
$_MODULE['<{retailcrm}prestashop>retailcrm_dfb403fd86851c7d9f97706dff5a2327'] = 'Через 45 минут';
$_MODULE['<{retailcrm}prestashop>retailcrm_4b5e6470d5d85448fcd89c828352d25e'] = 'Через 1 час';
$_MODULE['<{retailcrm}prestashop>settings_2b65c584b7b4d7bd19d36f7d2b690c6a'] = 'Каталог Icml';
$_MODULE['<{retailcrm}prestashop>settings_c2cc7082a89c1ad6631a2f66af5f00c0'] = 'Соединение';
$_MODULE['<{retailcrm}prestashop>settings_065ab3a28ca4f16f55f103adc7d0226f'] = 'Способы доставки';
$_MODULE['<{retailcrm}prestashop>settings_33af8066d3c83110d4bd897f687cedd2'] = 'Статусы заказов';
$_MODULE['<{retailcrm}prestashop>settings_bab959acc06bb03897b294fbb892be6b'] = 'Способы оплаты';
$_MODULE['<{retailcrm}prestashop>settings_7a1920d61156abc05a60135aefe8bc67'] = 'По умолчанию';
$_MODULE['<{retailcrm}prestashop>settings_20cacc01d0de8bc6e9c9846f477e886b'] = 'Выгрузка заказов';
$_MODULE['<{retailcrm}prestashop>settings_6bcde6286f8d1b76063ee52104a240cf'] = 'Брошенные корзины';
$_MODULE['<{retailcrm}prestashop>settings_52a13123e134b8b72b6299bc14a36aad'] = 'Daemon Collector';
$_MODULE['<{retailcrm}prestashop>settings_71098155ccc0a0d6e0b501fbee37e7a9'] = 'Онлайн-консультант';
$_MODULE['<{retailcrm}prestashop>settings_9b6545e4cea9b4ad4979d41bb9170e2b'] = 'Дополнительно';
$_MODULE['<{retailcrm}prestashop>settings_061b368c43f85d3fe2c7ccc842883a40'] = 'Настройка соединения';
$_MODULE['<{retailcrm}prestashop>settings_22a65bd0ef1919aa4e6dee849a7a2925'] = 'URL адрес Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_656a6828d7ef1bb791e42087c4b5ee6e'] = 'API-ключ';
$_MODULE['<{retailcrm}prestashop>settings_8ffa3281a35a0d80fef2cac0fa680523'] = 'Включить выгрузку истории';
$_MODULE['<{retailcrm}prestashop>settings_65dd9f6e8bf4eaf54c3dc96f011dade1'] = 'Получать остатки из Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_f8d7c52aa84f358caedb96fda86809da'] = 'Включить поддержку корпоративных клиентов';
$_MODULE['<{retailcrm}prestashop>settings_6c3c1845e109a9ef67378effea0c0503'] = 'Активировать только при включенной опции \"Корпоративные клиенты\" в Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_917afe348e09163269225a89a825e634'] = 'Синхронизация корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_d8e002d770b6f98af7b7ae9a0e5acfe9'] = 'Создавать заказы для брошенных корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_35b5a9139a54caeb925556ceb2c38086'] = 'Статус заказа для брошенных корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_9b9cf9f8778f69b4c6cf37e66f886be8'] = 'Выберите статус';
$_MODULE['<{retailcrm}prestashop>settings_a0d135501a738c3c98de385dc28cda61'] = 'Выгружать брошенные корзины';
$_MODULE['<{retailcrm}prestashop>settings_27096e1243f98e1b3300f57ff1c76456'] = 'Выберите задержку';
$_MODULE['<{retailcrm}prestashop>settings_1f8246b1e6ada8897902eff8d8cd8f35'] = 'устарел';
$_MODULE['<{retailcrm}prestashop>settings_4a15f35e8d386dd1d96faa83c1e44a22'] = 'Обновить URL';
$_MODULE['<{retailcrm}prestashop>settings_5b55e5aeb08a372d36f7e4b7b35d1cd1'] = 'URL для ICML каталога в Prestashop и в %s не совпадают';
$_MODULE['<{retailcrm}prestashop>settings_06aa6fa8bdc2078e7e1bd903e70c8f6a'] = 'подключен';
$_MODULE['<{retailcrm}prestashop>settings_7892a1894478824c07b62af2df839291'] = 'Более 7 дней';
$_MODULE['<{retailcrm}prestashop>settings_8277e0910d750195b448797616e091ad'] = 'д';
$_MODULE['<{retailcrm}prestashop>settings_2510c39011c5be704182423e3a695e91'] = 'ч';
$_MODULE['<{retailcrm}prestashop>settings_d8bd79cc131920d5de426f914d17405a'] = 'мин';
$_MODULE['<{retailcrm}prestashop>settings_3baa7e02e09dba2ba2a188a7c9a055cb'] = 'прошло с момента последнего запуска';
$_MODULE['<{retailcrm}prestashop>settings_068f80c7519d0528fb08e82137a72131'] = 'Продукты';
$_MODULE['<{retailcrm}prestashop>settings_9461bed8b71377318436990e57106729'] = 'Торговые предложения';
$_MODULE['<{retailcrm}prestashop>settings_64ef97a8fe9db8b672287a53c5d836f2'] = 'еще не был сгенерирован';
$_MODULE['<{retailcrm}prestashop>settings_79c07dbacf542d283944685e1538a1bb'] = 'Нажмите кнопку ниже чтобы сгенерировать %s';
$_MODULE['<{retailcrm}prestashop>settings_cc84d5b49b62c0959f1af64bffaec3b7'] = 'Генерировать сейчас';
$_MODULE['<{retailcrm}prestashop>settings_4e537de8dd108eafec4c37603c8ab7fb'] = 'Управление типами доставки';
$_MODULE['<{retailcrm}prestashop>settings_5b385947acf10ac0c5521161ce96aaa7'] = 'Выберите доставку';
$_MODULE['<{retailcrm}prestashop>settings_c0fd6d31d096a5845f1d1abb4c132b7d'] = 'Управление статусами заказов';
$_MODULE['<{retailcrm}prestashop>settings_dd53d9b3603b3279b25c74f6f3f189a4'] = 'Управление типами оплаты';
$_MODULE['<{retailcrm}prestashop>settings_7dcc1208fa03381346955c6732d9ea85'] = 'Выберите тип';
$_MODULE['<{retailcrm}prestashop>settings_6f1f9a3e435963417d08849fbef139c1'] = 'Введите идентификаторы заказов для загрузки в Simla.com, разделив их запятыми. Вы также можете указать диапазоны, например \"1-10\". Одновременно можно загружать до 10 заказов.';
$_MODULE['<{retailcrm}prestashop>settings_acfa058ec9e6e4745eddc0cae3f0f881'] = 'ID заказов';
$_MODULE['<{retailcrm}prestashop>settings_91412465ea9169dfd901dd5e7c96dd99'] = 'Выгрузить';
$_MODULE['<{retailcrm}prestashop>settings_f4af7f6987dfee28741ce77ff2d09d46'] = 'Экспортировать заказы и клиентов';
$_MODULE['<{retailcrm}prestashop>settings_418faff1c9df0d297ff586ac3230be97'] = 'Вы можете экспортировать все заказы и клиентов из CMS в Simla.com, нажав кнопку «Экспорт». Этот процесс может занять много времени, и до его завершения необходимо держать вкладку открытой.';
$_MODULE['<{retailcrm}prestashop>settings_7442e29d7d53e549b78d93c46b8cdcfc'] = 'Заказы';
$_MODULE['<{retailcrm}prestashop>settings_e6d0e1c8fc6a4fcf47869df87e04cd88'] = 'Клиенты';
$_MODULE['<{retailcrm}prestashop>settings_f8f36c02fa6f370808135c66cfc788aa'] = 'Клиенты без заказов';
$_MODULE['<{retailcrm}prestashop>settings_0095a9fa74d1713e43e370a7d7846224'] = 'Экспортировать';
$_MODULE['<{retailcrm}prestashop>settings_4d3d769b812b6faa6b76e1a8abaece2d'] = 'Активно';
$_MODULE['<{retailcrm}prestashop>settings_f75d8fa5c89351544d372cf90528ccf2'] = 'Ключ сайта';
$_MODULE['<{retailcrm}prestashop>settings_c9cc8cce247e49bae79f15173ce97354'] = 'Сохранить';
$_MODULE['<{retailcrm}prestashop>settings_4f18e3f1c9941a6ec5a38bc716c521b4'] = 'Код для вставки на сайт';
$_MODULE['<{retailcrm}prestashop>settings_ec3028a12402ab7f43962a6f3a667b6e'] = 'Режим отладки';
$_MODULE['<{retailcrm}prestashop>settings_9082f68bc90113d8950e4ed7fe8fa0a4'] = 'Менеджер задач';
$_MODULE['<{retailcrm}prestashop>settings_9194de58ce560c095f02cefc1c1c61e6'] = 'Имя задачи';
$_MODULE['<{retailcrm}prestashop>settings_05a3a24340b7b9cc8d4e08f0ef4f4dd9'] = 'Последний запуск';
$_MODULE['<{retailcrm}prestashop>settings_ec53a8c4f07baed5d8825072c89799be'] = 'Статус';
$_MODULE['<{retailcrm}prestashop>settings_0be8406951cdfda82f00f79328cf4efc'] = 'Комментарий';
$_MODULE['<{retailcrm}prestashop>settings_fe5b6cd4d7a31615bbec8d1505089d87'] = 'StackTrace';
$_MODULE['<{retailcrm}prestashop>settings_b2d37ae1cedf42ff874289b721860af2'] = 'Лог-файлы';
$_MODULE['<{retailcrm}prestashop>settings_34082694d21dbdcfc31e6e32d9fb2b9f'] = 'Имя файла';
$_MODULE['<{retailcrm}prestashop>settings_a4b7f1864cfdb47cd05b54eb10337506'] = 'Дата изменения';
$_MODULE['<{retailcrm}prestashop>settings_6f6cb72d544962fa333e2e34ce64f719'] = 'Размер';
$_MODULE['<{retailcrm}prestashop>settings_06df33001c1d7187fdd81ea1f5b277aa'] = 'Действия';
$_MODULE['<{retailcrm}prestashop>settings_801ab24683a4a8c433c6eb40c48bcd9d'] = 'Скачать';
$_MODULE['<{retailcrm}prestashop>settings_61b0ada67b7f40bf3d40dcc88ae4f3e6'] = 'Скачать все';
$_MODULE['<{retailcrm}prestashop>index_dd259436b3f29f0ba1778d220b343ec9'] = 'Simla.com — сервис для интернет магазинов, который поможет перестать терять заказы и увеличить доход на всех этапах воронки.';
$_MODULE['<{retailcrm}prestashop>index_c7476a92e20715b855d72b1786a71017'] = 'У меня уже есть аккаунт Simla.com';
$_MODULE['<{retailcrm}prestashop>index_e81c4e4f2b7b93b481e13a8553c2ae1b'] = 'или';
@ -79,58 +152,3 @@ $_MODULE['<{retailcrm}prestashop>index_95428f32e5c696cf71baccb776bc5c15'] = 'Б
$_MODULE['<{retailcrm}prestashop>index_e7f9e382dc50889098cbe56f2554c77b'] = 'Кредитной картой';
$_MODULE['<{retailcrm}prestashop>index_7088f1d1d9c91d8b75e9882ffd78540c'] = 'Наши контакты';
$_MODULE['<{retailcrm}prestashop>index_50f158e2507321f1a5b6f8fb9e350818'] = 'Пишите нам если у Вас есть вопросы';
$_MODULE['<{retailcrm}prestashop>settings_c2cc7082a89c1ad6631a2f66af5f00c0'] = 'Соединение';
$_MODULE['<{retailcrm}prestashop>settings_065ab3a28ca4f16f55f103adc7d0226f'] = 'Способы доставки';
$_MODULE['<{retailcrm}prestashop>settings_33af8066d3c83110d4bd897f687cedd2'] = 'Статусы заказов';
$_MODULE['<{retailcrm}prestashop>settings_bab959acc06bb03897b294fbb892be6b'] = 'Способы оплаты';
$_MODULE['<{retailcrm}prestashop>settings_7a1920d61156abc05a60135aefe8bc67'] = 'По умолчанию';
$_MODULE['<{retailcrm}prestashop>settings_20cacc01d0de8bc6e9c9846f477e886b'] = 'Выгрузка заказов';
$_MODULE['<{retailcrm}prestashop>settings_6bcde6286f8d1b76063ee52104a240cf'] = 'Брошенные корзины';
$_MODULE['<{retailcrm}prestashop>settings_52a13123e134b8b72b6299bc14a36aad'] = 'Daemon Collector';
$_MODULE['<{retailcrm}prestashop>settings_71098155ccc0a0d6e0b501fbee37e7a9'] = 'Онлайн-консультант';
$_MODULE['<{retailcrm}prestashop>settings_9b6545e4cea9b4ad4979d41bb9170e2b'] = 'Дополнительно';
$_MODULE['<{retailcrm}prestashop>settings_061b368c43f85d3fe2c7ccc842883a40'] = 'Настройка соединения';
$_MODULE['<{retailcrm}prestashop>settings_22a65bd0ef1919aa4e6dee849a7a2925'] = 'URL адрес Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_656a6828d7ef1bb791e42087c4b5ee6e'] = 'API-ключ';
$_MODULE['<{retailcrm}prestashop>settings_8ffa3281a35a0d80fef2cac0fa680523'] = 'Включить выгрузку истории';
$_MODULE['<{retailcrm}prestashop>settings_65dd9f6e8bf4eaf54c3dc96f011dade1'] = 'Получать остатки из Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_f8d7c52aa84f358caedb96fda86809da'] = 'Включить поддержку корпоративных клиентов';
$_MODULE['<{retailcrm}prestashop>settings_6c3c1845e109a9ef67378effea0c0503'] = 'Активировать только при включенной опции \"Корпоративные клиенты\" в Simla.com';
$_MODULE['<{retailcrm}prestashop>settings_917afe348e09163269225a89a825e634'] = 'Синхронизация корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_d8e002d770b6f98af7b7ae9a0e5acfe9'] = 'Создавать заказы для брошенных корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_35b5a9139a54caeb925556ceb2c38086'] = 'Статус заказа для брошенных корзин покупателей';
$_MODULE['<{retailcrm}prestashop>settings_9b9cf9f8778f69b4c6cf37e66f886be8'] = 'Выберите статус';
$_MODULE['<{retailcrm}prestashop>settings_a0d135501a738c3c98de385dc28cda61'] = 'Выгружать брошенные корзины';
$_MODULE['<{retailcrm}prestashop>settings_27096e1243f98e1b3300f57ff1c76456'] = 'Выберите задержку';
$_MODULE['<{retailcrm}prestashop>settings_4e537de8dd108eafec4c37603c8ab7fb'] = 'Управление типами доставки';
$_MODULE['<{retailcrm}prestashop>settings_5b385947acf10ac0c5521161ce96aaa7'] = 'Выберите доставку';
$_MODULE['<{retailcrm}prestashop>settings_c0fd6d31d096a5845f1d1abb4c132b7d'] = 'Управление статусами заказов';
$_MODULE['<{retailcrm}prestashop>settings_dd53d9b3603b3279b25c74f6f3f189a4'] = 'Управление типами оплаты';
$_MODULE['<{retailcrm}prestashop>settings_7dcc1208fa03381346955c6732d9ea85'] = 'Выберите тип';
$_MODULE['<{retailcrm}prestashop>settings_6f1f9a3e435963417d08849fbef139c1'] = 'Введите идентификаторы заказов для загрузки в Simla.com, разделив их запятыми. Вы также можете указать диапазоны, например \"1-10\". Одновременно можно загружать до 10 заказов.';
$_MODULE['<{retailcrm}prestashop>settings_acfa058ec9e6e4745eddc0cae3f0f881'] = 'ID заказов';
$_MODULE['<{retailcrm}prestashop>settings_91412465ea9169dfd901dd5e7c96dd99'] = 'Выгрузить';
$_MODULE['<{retailcrm}prestashop>settings_f4af7f6987dfee28741ce77ff2d09d46'] = 'Экспортировать заказы и клиентов';
$_MODULE['<{retailcrm}prestashop>settings_418faff1c9df0d297ff586ac3230be97'] = 'Вы можете экспортировать все заказы и клиентов из CMS в Simla.com, нажав кнопку «Экспорт». Этот процесс может занять много времени, и до его завершения необходимо держать вкладку открытой.';
$_MODULE['<{retailcrm}prestashop>settings_7442e29d7d53e549b78d93c46b8cdcfc'] = 'Заказы';
$_MODULE['<{retailcrm}prestashop>settings_e6d0e1c8fc6a4fcf47869df87e04cd88'] = 'Клиенты';
$_MODULE['<{retailcrm}prestashop>settings_f8f36c02fa6f370808135c66cfc788aa'] = 'Клиенты без заказов';
$_MODULE['<{retailcrm}prestashop>settings_0095a9fa74d1713e43e370a7d7846224'] = 'Экспортировать';
$_MODULE['<{retailcrm}prestashop>settings_4d3d769b812b6faa6b76e1a8abaece2d'] = 'Активно';
$_MODULE['<{retailcrm}prestashop>settings_f75d8fa5c89351544d372cf90528ccf2'] = 'Ключ сайта';
$_MODULE['<{retailcrm}prestashop>settings_c9cc8cce247e49bae79f15173ce97354'] = 'Сохранить';
$_MODULE['<{retailcrm}prestashop>settings_4f18e3f1c9941a6ec5a38bc716c521b4'] = 'Код для вставки на сайт';
$_MODULE['<{retailcrm}prestashop>settings_ec3028a12402ab7f43962a6f3a667b6e'] = 'Режим отладки';
$_MODULE['<{retailcrm}prestashop>settings_9082f68bc90113d8950e4ed7fe8fa0a4'] = 'Менеджер задач';
$_MODULE['<{retailcrm}prestashop>settings_9194de58ce560c095f02cefc1c1c61e6'] = 'Имя задачи';
$_MODULE['<{retailcrm}prestashop>settings_05a3a24340b7b9cc8d4e08f0ef4f4dd9'] = 'Последний запуск';
$_MODULE['<{retailcrm}prestashop>settings_ec53a8c4f07baed5d8825072c89799be'] = 'Статус';
$_MODULE['<{retailcrm}prestashop>settings_0be8406951cdfda82f00f79328cf4efc'] = 'Комментарий';
$_MODULE['<{retailcrm}prestashop>settings_fe5b6cd4d7a31615bbec8d1505089d87'] = 'StackTrace';
$_MODULE['<{retailcrm}prestashop>settings_b2d37ae1cedf42ff874289b721860af2'] = 'Лог-файлы';
$_MODULE['<{retailcrm}prestashop>settings_34082694d21dbdcfc31e6e32d9fb2b9f'] = 'Имя файла';
$_MODULE['<{retailcrm}prestashop>settings_a4b7f1864cfdb47cd05b54eb10337506'] = 'Дата изменения';
$_MODULE['<{retailcrm}prestashop>settings_6f6cb72d544962fa333e2e34ce64f719'] = 'Размер';
$_MODULE['<{retailcrm}prestashop>settings_06df33001c1d7187fdd81ea1f5b277aa'] = 'Действия';
$_MODULE['<{retailcrm}prestashop>settings_801ab24683a4a8c433c6eb40c48bcd9d'] = 'Скачать';
$_MODULE['<{retailcrm}prestashop>settings_61b0ada67b7f40bf3d40dcc88ae4f3e6'] = 'Скачать все';

View File

@ -62,11 +62,10 @@ function upgrade_module_3_3_2($module)
}
foreach ($shops as $shop) {
RetailcrmTools::setShopContext((int) $shop['id_shop']);
RetailcrmContextSwitcher::setShopContext((int) $shop['id_shop']);
$api = RetailcrmTools::getApiClient();
if (empty($api)) {
RetailcrmLogger::writeCaller(__METHOD__, 'Set api key & url first');
continue;
}

View File

@ -9,6 +9,7 @@
font-size: 18px;
margin-bottom: 20px;
}
&__content,
input&__content {
width: 120px;
height: 120px;

View File

@ -12,6 +12,8 @@
@grayBtnHover: rgba(122, 122, 122, 0.15);
@grayBtnActive: fadein(@grayBtnHover, 10%);
@darkGray: #363A41;
@yellow: #fcc94f;
@yellowActive: #edbe4c;
@lightYellow: #fcf3b5;
@shadowGray: #fdd0d0;
@bord: #DFDFDF;
@ -578,6 +580,13 @@ body, html {
&_submit {
min-width: 218px;
}
&_warning {
min-width: 218px;
background: @yellow;
&:hover {
background: @yellowActive;
}
}
}
.toggle-box {
display: none;
@ -607,6 +616,11 @@ body, html {
max-width: 300px;
vertical-align: middle;
}
&__row {
&-bold {
font-weight: bold;
}
}
&-no-wrap {
white-space: nowrap;
}
@ -674,6 +688,7 @@ body, html {
background: #fff;
border: 1px solid rgba(122,122,122,0.15);
position: absolute;
z-index: 5;
top: 20px;
left: 0;
padding: 18px;
@ -696,4 +711,41 @@ body, html {
color: #dd2e44;
}
}
&-alert {
position: relative;
height: 60px;
padding: 0 50px;
line-height: 30px;
&-text {
font-size: 1.5em;
}
&-note {
color: @gray;
font-size: 1.2em;
}
&:before {
display: block;
position: absolute;
left: 0;
top: 0;
padding: 10px 5px;
font: normal normal normal 40px/1 FontAwesome;
}
&-success:before {
content: "\F058";
color: @green;
}
&-warning:before {
content: "\F06A";
color: @yellow;
}
&-danger:before {
content: "\F071";
color: @red;
}
&-info:before {
content: "\F059";
color: @blue;
}
}
}

View File

@ -1 +1 @@
.retail-circle{float:left;width:50%;text-align:center;padding:20px;margin:20px 0}.retail-circle__title{font-size:18px;margin-bottom:20px}input.retail-circle__content{width:120px;height:120px;border-radius:120px;text-align:center;font-size:20px;line-height:60px}.retail-progress{border-radius:60px;border:1px solid rgba(122,122,122,0.15);width:100%;height:60px;overflow:hidden;transition:height .25s ease}.retail-progress__loader{width:0;border-radius:60px;background:#0068FF;color:white;text-align:center;padding:0 30px;font-size:18px;font-weight:600;transition:width .4s ease-in;line-height:60px}.retail-hidden{visibility:hidden;height:0!important}
.retail-circle{float:left;width:50%;text-align:center;padding:20px;margin:20px 0}.retail-circle__title{font-size:18px;margin-bottom:20px}.retail-circle__content,input.retail-circle__content{width:120px;height:120px;border-radius:120px;text-align:center;font-size:20px;line-height:60px}.retail-progress{border-radius:60px;border:1px solid rgba(122,122,122,0.15);width:100%;height:60px;overflow:hidden;transition:height .25s ease}.retail-progress__loader{width:0;border-radius:60px;background:#0068FF;color:white;text-align:center;padding:0 30px;font-size:18px;font-weight:600;transition:width .4s ease-in;line-height:60px}.retail-hidden{visibility:hidden;height:0!important}

File diff suppressed because one or more lines are too long

View File

@ -134,7 +134,7 @@ $(function () {
RetailcrmExportForm.prototype.confirmLeave = function (event) {
event.preventDefault();
e.returnValue = 'Export process has been started';
event.returnValue = 'Export process has been started';
}
RetailcrmExportForm.prototype.exportDone = function () {

View File

@ -34,4 +34,5 @@
* Don't forget to prefix your containers with your own identifier
* to avoid any conflicts with others containers.
*/
$(function(){function t(){if(this.form=$("input[name=RETAILCRM_EXPORT_ORDERS_COUNT]").closest("form").get(0),void 0===this.form)return!1;this.isDone=!1,this.ordersCount=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_ORDERS_COUNT"]').val()),this.customersCount=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_CUSTOMERS_COUNT"]').val()),this.ordersStepSize=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_ORDERS_STEP_SIZE"]').val()),this.customersStepSize=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_CUSTOMERS_STEP_SIZE"]').val()),this.ordersStep=0,this.customersStep=0,this.submitButton=$(this.form).find('button[id="export-orders-submit"]').get(0),this.progressBar=$(this.form).find('div[id="export-orders-progress"]').get(0),this.submitAction=this.submitAction.bind(this),this.exportAction=this.exportAction.bind(this),this.exportDone=this.exportDone.bind(this),this.initializeProgressBar=this.initializeProgressBar.bind(this),this.updateProgressBar=this.updateProgressBar.bind(this),$(this.submitButton).click(this.submitAction)}t.prototype.submitAction=function(t){t.preventDefault(),this.initializeProgressBar(),this.exportAction()},t.prototype.exportAction=function(){let t={submitretailcrm:1,ajax:1};this.ordersStep*this.ordersStepSize<this.ordersCount?(this.ordersStep++,t.RETAILCRM_EXPORT_ORDERS_STEP=this.ordersStep):this.customersStep*this.customersStepSize<this.customersCount?(this.customersStep++,t.RETAILCRM_EXPORT_CUSTOMERS_STEP=this.customersStep):(t.RETAILCRM_UPDATE_SINCE_ID=1,this.isDone=!0);let s=this;$.ajax({url:this.form.action,method:this.form.method,timeout:0,data:t}).done(function(t){return s.isDone?s.exportDone():(s.updateProgressBar(),void s.exportAction())})},t.prototype.initializeProgressBar=function(){$(this.submitButton).addClass("retail-hidden"),$(this.progressBar).removeClass("retail-hidden").append($("<div/>",{class:"retail-progress__loader",text:"0%"})),window.addEventListener("beforeunload",this.confirmLeave)},t.prototype.updateProgressBar=function(){let t=this.ordersStep*this.ordersStepSize;t>this.ordersCount&&(t=this.ordersCount);let s=this.customersStep*this.customersStepSize;s>this.customersCount&&(s=this.customersCount);var e=t+s,i=this.ordersCount+this.customersCount,r=Math.round(100*e/i);$(this.progressBar).find(".retail-progress__loader").text(r+"%"),$(this.progressBar).find(".retail-progress__loader").css("width",r+"%"),$(this.progressBar).find(".retail-progress__loader").attr("title",e+"/"+i)},t.prototype.confirmLeave=function(t){t.preventDefault(),e.returnValue="Export process has been started"},t.prototype.exportDone=function(){window.removeEventListener("beforeunload",this.confirmLeave),alert("Export is done")},window.RetailcrmExportForm=t});
$(function(){function t(){if(this.form=$("input[name=RETAILCRM_EXPORT_ORDERS_COUNT]").closest("form").get(0),void 0===this.form)return!1;this.isDone=!1,this.ordersCount=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_ORDERS_COUNT"]').val()),this.customersCount=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_CUSTOMERS_COUNT"]').val()),this.ordersStepSize=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_ORDERS_STEP_SIZE"]').val()),this.customersStepSize=parseInt($(this.form).find('input[name="RETAILCRM_EXPORT_CUSTOMERS_STEP_SIZE"]').val()),this.ordersStep=0,this.customersStep=0,this.submitButton=$(this.form).find('button[id="export-orders-submit"]').get(0),this.progressBar=$(this.form).find('div[id="export-orders-progress"]').get(0),this.submitAction=this.submitAction.bind(this),this.exportAction=this.exportAction.bind(this),this.exportDone=this.exportDone.bind(this),this.initializeProgressBar=this.initializeProgressBar.bind(this),this.updateProgressBar=this.updateProgressBar.bind(this),$(this.submitButton).click(this.submitAction)}t.prototype.submitAction=function(t){t.preventDefault(),this.initializeProgressBar(),this.exportAction()},t.prototype.exportAction=function(){let t={submitretailcrm:1,ajax:1};this.ordersStep*this.ordersStepSize<this.ordersCount?(this.ordersStep++,t.RETAILCRM_EXPORT_ORDERS_STEP=this.ordersStep):this.customersStep*this.customersStepSize<this.customersCount?(this.customersStep++,t.RETAILCRM_EXPORT_CUSTOMERS_STEP=this.customersStep):(t.RETAILCRM_UPDATE_SINCE_ID=1,this.isDone=!0);let s=this;$.ajax({url:this.form.action,method:this.form.method,timeout:0,data:t}).done(function(t){return s.isDone?s.exportDone():(s.updateProgressBar(),void s.exportAction())})},t.prototype.initializeProgressBar=function(){$(this.submitButton).addClass("retail-hidden"),$(this.progressBar).removeClass("retail-hidden").append($("<div/>",{class:"retail-progress__loader",text:"0%"})),window.addEventListener("beforeunload",this.confirmLeave)},t.prototype.updateProgressBar=function(){let t=this.ordersStep*this.ordersStepSize;t>this.ordersCount&&(t=this.ordersCount);let s=this.customersStep*this.customersStepSize;s>this.customersCount&&(s=this.customersCount);var e=t+s,i=this.ordersCount+this.customersCount,r=Math.round(100*e/i);$(this.progressBar).find(".retail-progress__loader").text(r+"%"),$(this.progressBar).find(".retail-progress__loader").css("width",r+"%"),$(this.progressBar).find(".retail-progress__loader").attr("title",e+"/"+i)},t.prototype.confirmLeave=function(t){t.preventDefault(),t.returnValue="Export process has been started"},t.prototype.exportDone=function(){window.removeEventListener("beforeunload",this.confirmLeave),alert("Export is done")},window.RetailcrmExportForm=t});
//# sourceMappingURL=retailcrm-export.min.js.map

View File

@ -0,0 +1,95 @@
/**
* MIT License
*
* Copyright (c) 2020 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* 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 <mail@simlachat.com>
* @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.
*/
$(function () {
function RetailcrmIcmlForm(tabController) {
this.submitButton = $('button[id="generate-icml-submit"]').get(0);
this.updateButton = $('button[id="update-icml-submit"]').get(0);
this.form = $(this.submitButton).closest('form').get(0);
this.icmlField = $(this.form).find('input[name="RETAILCRM_RUN_JOB"]').get(0);
if (typeof this.form === 'undefined') {
return false;
}
this.submitAction = this.submitAction.bind(this);
this.updateAction = this.updateAction.bind(this);
this.setLoading = this.setLoading.bind(this);
this.tabController = tabController;
$(this.submitButton).click(this.submitAction);
$(this.updateButton).click(this.updateAction);
}
RetailcrmIcmlForm.prototype.submitAction = function (event) {
event.preventDefault();
this.setLoading(true);
this.tabController.storeTabInAction(this.form);
$(this.icmlField).val('RetailcrmIcmlEvent');
$(this.form).submit();
};
RetailcrmIcmlForm.prototype.updateAction = function (event) {
event.preventDefault();
this.setLoading(true);
this.tabController.storeTabInAction(this.form);
$(this.icmlField).val('RetailcrmIcmlUpdateUrlEvent');
$(this.form).submit();
};
RetailcrmIcmlForm.prototype.setLoading = function (loading) {
var loaderId = 'retailcrm-loading-fade',
indicator = $('#' + loaderId);
if (indicator.length === 0) {
$('body').append(`
<div id="${loaderId}">
<div id="retailcrm-loader"></div>
</div>
`.trim());
indicator = $('#' + loaderId);
}
indicator.css('visibility', (loading ? 'visible' : 'hidden'));
};
window.RetailcrmIcmlForm = RetailcrmIcmlForm;
});

View File

@ -0,0 +1,42 @@
/**
* MIT License
*
* Copyright (c) 2020 DIGITAL RETAIL TECHNOLOGIES SL
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* 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 <mail@simlachat.com>
* @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.
*/
$(function(){function t(t){if(this.submitButton=$('button[id="generate-icml-submit"]').get(0),this.updateButton=$('button[id="update-icml-submit"]').get(0),this.form=$(this.submitButton).closest("form").get(0),this.icmlField=$(this.form).find('input[name="RETAILCRM_RUN_JOB"]').get(0),void 0===this.form)return!1;this.submitAction=this.submitAction.bind(this),this.updateAction=this.updateAction.bind(this),this.setLoading=this.setLoading.bind(this),this.tabController=t,$(this.submitButton).click(this.submitAction),$(this.updateButton).click(this.updateAction)}t.prototype.submitAction=function(t){t.preventDefault(),this.setLoading(!0),this.tabController.storeTabInAction(this.form),$(this.icmlField).val("RetailcrmIcmlEvent"),$(this.form).submit()},t.prototype.updateAction=function(t){t.preventDefault(),this.setLoading(!0),this.tabController.storeTabInAction(this.form),$(this.icmlField).val("RetailcrmIcmlUpdateUrlEvent"),$(this.form).submit()},t.prototype.setLoading=function(t){var i="retailcrm-loading-fade",o=$("#"+i);0===o.length&&($("body").append(`
<div id="${i}">
<div id="retailcrm-loader"></div>
</div>
`.trim()),o=$("#"+i)),o.css("visibility",t?"visible":"hidden")},window.RetailcrmIcmlForm=t});
//# sourceMappingURL=retailcrm-icml.min.js.map

View File

@ -42,8 +42,7 @@ $(function(){
this.tableSort.init();
this.player.init();
this.tabs.init();
this.uploadForm.init(this.settingsTabs.init());
this.exportForm.init()
this.eventForm.init(this.settingsTabs.init());
this.popup.init();
this.toggleBox();
this.trimConsultant();
@ -220,6 +219,7 @@ $(function(){
'rcrm_tab_payment_types': selectsUpdate,
'rcrm_tab_consultant': mainSubmitHide,
'rcrm_tab_advanced': mainSubmitHide,
'rcrm_tab_catalog': mainSubmitHide,
'rcrm_tab_orders_upload': mainSubmitHide
});
tabs.initializeTabs();
@ -227,23 +227,23 @@ $(function(){
return tabs;
}
},
uploadForm: {
eventForm: {
init: function (tabController) {
if (!(typeof RetailcrmUploadForm === 'undefined')) {
new RetailcrmUploadForm(tabController);
}
}
},
exportForm: {
init: function () {
if (!(typeof RetailcrmIcmlForm === 'undefined')) {
new RetailcrmIcmlForm(tabController);
}
if (!(typeof RetailcrmExportForm === 'undefined')) {
new RetailcrmExportForm();
}
}
},
},
tabs: {
init: function () {
$('.retail-tabs__btn').on('click', this.swithTab);
this.advancedTab();
},
swithTab: function (e) {
e.preventDefault();
@ -256,6 +256,16 @@ $(function(){
.fadeIn(150);
});
$(this).addClass('retail-tabs__btn_active');
},
advancedTab: function () {
let tabElement = document.getElementsByClassName('retail-title_content')[0];
if (tabElement !== undefined) {
tabElement.addEventListener('click', function (evt) {
if (evt.detail === 3) {
$('.retail-menu__btn[data-tab-trigger="rcrm_tab_advanced"]').click();
}
});
}
}
},
popup: {

View File

@ -34,4 +34,5 @@
* Don't forget to prefix your containers with your own identifier
* to avoid any conflicts with others containers.
*/
$(function(){var a={init:function(){this.selects.init(),this.tableSort.init(),this.player.init(),this.tabs.init(),this.uploadForm.init(this.settingsTabs.init()),this.exportForm.init(),this.popup.init(),this.toggleBox(),this.trimConsultant(),this.showSettings()},selects:{init:function(){var t=this;try{$(".jq-select").SumoSelect(),$("li.opt").each((t,e)=>{if(0===$(e).find("label").html().length){let t=$(e).closest("ul").closest("div").parent().find("select");$(e).find("label").html(t.attr("placeholder")),$(e).addClass("disabled")}}),t.update(),$(document).on("change",".jq-select",function(){t.update()})}catch(t){console.warn("Cannot initialize select: "+t.message)}},update:function(){var n={};let t=$(".retail-tab__enabled").find("select:not(#RETAILCRM_API_DELIVERY_DEFAULT, #RETAILCRM_API_PAYMENT_DEFAULT)");t.each((t,e)=>{var i=$(e).val();i&&i.length&&(n[t]=$('option[value="'+$(e).val()+'"]',$(e)).index())});let s=Object.values(n);t.each((i,a)=>{$("option",a).each((t,e)=>{-1===$.inArray(t,s)||void 0!==n[i]&&n[i]==t?a.sumo.enableItem(t):a.sumo.disableItem(t)})})}},tableSort:{init:function(){var n=this;$(".retail-table-sort").each((t,a)=>{$(a).find(".retail-table-sort__switch").each((t,e)=>{const i=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(a,i)})}),$(a).find(".retail-table-sort__asc").each((t,e)=>{const i=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(a,i,"asc")})}),$(a).find(".retail-table-sort__desc").each((t,e)=>{const i=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(a,i,"desc")})}),$(a).find(".retail-table-sort__initial").click()})},sort:function(t,e,i=void 0){let a,n,s,o,r,l,c,d=0;for(n=!0,c=i||"asc";n;){for(n=!1,a=t.rows,s=1;s<a.length-1;s++)if(l=!1,o=a[s].getElementsByTagName("TD")[e],r=a[s+1].getElementsByTagName("TD")[e],"asc"===c){if(o.innerHTML.toLowerCase()>r.innerHTML.toLowerCase()){l=!0;break}}else if("desc"===c&&o.innerHTML.toLowerCase()<r.innerHTML.toLowerCase()){l=!0;break}l?(a[s].parentNode.insertBefore(a[s+1],a[s]),n=!0,d++):void 0===i&&0===d&&"asc"===c&&(c="desc",n=!0)}}},player:{init:function(){window.player={},window.onYouTubeIframeAPIReady=function(){window.player=new YT.Player("player",{height:"100%",width:"100%",videoId:window.RCRMPROMO})};var t=document.createElement("script");t.src="https://www.youtube.com/iframe_api",document.body.appendChild(t)}},settingsTabs:{init:function(){if("undefined"!=typeof RCRMTabs){let t=new RCRMTabs('div[id^="rcrm_tab_"]',".retail-menu__btn","retail-tab__enabled","retail-tab__disabled","retail-menu__btn_active","retail-menu__btn_inactive","tab-trigger",".rcrm-form-submit-trigger");var e={afterActivate:function(){a.selects.update()}},i={beforeActivate:function(){$("#main-submit").hide()},afterDeactivate:function(){$("#main-submit").show()}};return t.tabsCallbacks({rcrm_tab_delivery_types:e,rcrm_tab_order_statuses:e,rcrm_tab_payment_types:e,rcrm_tab_consultant:i,rcrm_tab_advanced:i,rcrm_tab_orders_upload:i}),t.initializeTabs(),t}}},uploadForm:{init:function(t){"undefined"!=typeof RetailcrmUploadForm&&new RetailcrmUploadForm(t)}},exportForm:{init:function(){"undefined"!=typeof RetailcrmExportForm&&new RetailcrmExportForm}},tabs:{init:function(){$(".retail-tabs__btn").on("click",this.swithTab)},swithTab:function(t){t.preventDefault();var e=$(this).attr("href");$(".retail-tabs__btn_active").removeClass("retail-tabs__btn_active"),$(".retail-tabs__item_active").removeClass("retail-tabs__item_active").fadeOut(150,function(){$(e).addClass("retail-tabs__item_active").fadeIn(150)}),$(this).addClass("retail-tabs__btn_active")}},popup:{init:function(){var i=this;$("[data-popup]").on("click",function(t){var e=$(this).data("popup");i.open($(e))}),$(".retail-popup-wrap").on("click",function(t){$(t.target).hasClass("js-popup-close")&&(t=$(this).find(".retail-popup"),i.close(t))})},open:function(t){t&&(t.closest(".retail-popup-wrap").fadeIn(200),t.addClass("open"),player.playVideo())},close:function(t){var e=t.closest(".retail-popup-wrap");t.removeClass("open"),e.fadeOut(200),player.stopVideo()}},toggleBox:function(){$(".toggle-btn").on("click",function(t){t.preventDefault();t=$(this).attr("href"),t=$(t);$(this).closest(".retail-btns").addClass("retail-btns_hide").slideUp(100),t.slideDown(100)})},trimConsultant:function(){let t=$("#rcrm_tab_consultant textarea");t.text(t.text().trim())},showSettings:function(){$(".retail.retail-wrap.hidden").removeClass("hidden")}};a.init()});
$(function(){var i={init:function(){this.selects.init(),this.tableSort.init(),this.player.init(),this.tabs.init(),this.eventForm.init(this.settingsTabs.init()),this.popup.init(),this.toggleBox(),this.trimConsultant(),this.showSettings()},selects:{init:function(){var t=this;try{$(".jq-select").SumoSelect(),$("li.opt").each((t,e)=>{if(0===$(e).find("label").html().length){let t=$(e).closest("ul").closest("div").parent().find("select");$(e).find("label").html(t.attr("placeholder")),$(e).addClass("disabled")}}),t.update(),$(document).on("change",".jq-select",function(){t.update()})}catch(t){console.warn("Cannot initialize select: "+t.message)}},update:function(){var n={};let t=$(".retail-tab__enabled").find("select:not(#RETAILCRM_API_DELIVERY_DEFAULT, #RETAILCRM_API_PAYMENT_DEFAULT)");t.each((t,e)=>{var a=$(e).val();a&&a.length&&(n[t]=$('option[value="'+$(e).val()+'"]',$(e)).index())});let s=Object.values(n);t.each((a,i)=>{$("option",i).each((t,e)=>{-1===$.inArray(t,s)||void 0!==n[a]&&n[a]==t?i.sumo.enableItem(t):i.sumo.disableItem(t)})})}},tableSort:{init:function(){var n=this;$(".retail-table-sort").each((t,i)=>{$(i).find(".retail-table-sort__switch").each((t,e)=>{const a=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(i,a)})}),$(i).find(".retail-table-sort__asc").each((t,e)=>{const a=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(i,a,"asc")})}),$(i).find(".retail-table-sort__desc").each((t,e)=>{const a=$(e).closest("th,td").index();$(e).click(t=>{t.preventDefault(),n.sort(i,a,"desc")})}),$(i).find(".retail-table-sort__initial").click()})},sort:function(t,e,a=void 0){let i,n,s,r,o,l,c,d=0;for(n=!0,c=a||"asc";n;){for(n=!1,i=t.rows,s=1;s<i.length-1;s++)if(l=!1,r=i[s].getElementsByTagName("TD")[e],o=i[s+1].getElementsByTagName("TD")[e],"asc"===c){if(r.innerHTML.toLowerCase()>o.innerHTML.toLowerCase()){l=!0;break}}else if("desc"===c&&r.innerHTML.toLowerCase()<o.innerHTML.toLowerCase()){l=!0;break}l?(i[s].parentNode.insertBefore(i[s+1],i[s]),n=!0,d++):void 0===a&&0===d&&"asc"===c&&(c="desc",n=!0)}}},player:{init:function(){window.player={},window.onYouTubeIframeAPIReady=function(){window.player=new YT.Player("player",{height:"100%",width:"100%",videoId:window.RCRMPROMO})};var t=document.createElement("script");t.src="https://www.youtube.com/iframe_api",document.body.appendChild(t)}},settingsTabs:{init:function(){if("undefined"!=typeof RCRMTabs){let t=new RCRMTabs('div[id^="rcrm_tab_"]',".retail-menu__btn","retail-tab__enabled","retail-tab__disabled","retail-menu__btn_active","retail-menu__btn_inactive","tab-trigger",".rcrm-form-submit-trigger");var e={afterActivate:function(){i.selects.update()}},a={beforeActivate:function(){$("#main-submit").hide()},afterDeactivate:function(){$("#main-submit").show()}};return t.tabsCallbacks({rcrm_tab_delivery_types:e,rcrm_tab_order_statuses:e,rcrm_tab_payment_types:e,rcrm_tab_consultant:a,rcrm_tab_advanced:a,rcrm_tab_catalog:a,rcrm_tab_orders_upload:a}),t.initializeTabs(),t}}},eventForm:{init:function(t){"undefined"!=typeof RetailcrmUploadForm&&new RetailcrmUploadForm(t),"undefined"!=typeof RetailcrmIcmlForm&&new RetailcrmIcmlForm(t),"undefined"!=typeof RetailcrmExportForm&&new RetailcrmExportForm}},tabs:{init:function(){$(".retail-tabs__btn").on("click",this.swithTab),this.advancedTab()},swithTab:function(t){t.preventDefault();var e=$(this).attr("href");$(".retail-tabs__btn_active").removeClass("retail-tabs__btn_active"),$(".retail-tabs__item_active").removeClass("retail-tabs__item_active").fadeOut(150,function(){$(e).addClass("retail-tabs__item_active").fadeIn(150)}),$(this).addClass("retail-tabs__btn_active")},advancedTab:function(){let t=document.getElementsByClassName("retail-title_content")[0];void 0!==t&&t.addEventListener("click",function(t){3===t.detail&&$('.retail-menu__btn[data-tab-trigger="rcrm_tab_advanced"]').click()})}},popup:{init:function(){var a=this;$("[data-popup]").on("click",function(t){var e=$(this).data("popup");a.open($(e))}),$(".retail-popup-wrap").on("click",function(t){$(t.target).hasClass("js-popup-close")&&(t=$(this).find(".retail-popup"),a.close(t))})},open:function(t){t&&(t.closest(".retail-popup-wrap").fadeIn(200),t.addClass("open"),player.playVideo())},close:function(t){var e=t.closest(".retail-popup-wrap");t.removeClass("open"),e.fadeOut(200),player.stopVideo()}},toggleBox:function(){$(".toggle-btn").on("click",function(t){t.preventDefault();t=$(this).attr("href"),t=$(t);$(this).closest(".retail-btns").addClass("retail-btns_hide").slideUp(100),t.slideDown(100)})},trimConsultant:function(){let t=$("#rcrm_tab_consultant textarea");t.text(t.text().trim())},showSettings:function(){$(".retail.retail-wrap.hidden").removeClass("hidden")}};i.init()});
//# sourceMappingURL=retailcrm.min.js.map

View File

@ -42,7 +42,12 @@
<link rel="stylesheet" href="{$assets|escape:'htmlall':'UTF-8'}/css/retailcrm-upload.min.css">
<link rel="stylesheet" href="{$assets|escape:'htmlall':'UTF-8'}/css/retailcrm-export.min.css">
<link rel="stylesheet" href="{$assets|escape:'htmlall':'UTF-8'}/css/styles.min.css">
<title>Simla.com</title>
{assign var="systemName" value="Simla.com"}
{capture name="catalogTitleName"}{l s='Icml catalog' mod='retailcrm'}{/capture}
{assign var="catalogTitleName" value=$smarty.capture.catalogTitleName}
<title>{$systemName|escape:'htmlall':'UTF-8'}</title>
<div class="retail retail-wrap hidden">
{include file='./module_messages.tpl'}
<div class="retail-container retail-column">
@ -55,13 +60,14 @@
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_default_types" class="retail-menu__btn retail-menu__btn_big{if in_array('deliveryDefault', $errorTabs) || in_array('paymentDefault', $errorTabs)} retail-menu__btn_error{/if}"><span>{l s='Default' mod='retailcrm'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_orders_upload" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive"><span>{l s='Upload orders' mod='retailcrm'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_carts_sync" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive"><span>{l s='Abandoned carts' mod='retailcrm'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_catalog" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive{if in_array('catalog', $errorTabs)} retail-menu__btn_error{/if}"><span>{$catalogTitleName|escape:'htmlall':'UTF-8'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_daemon_collector" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive"><span>{l s='Daemon Collector' mod='retailcrm'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm&item=consultant" data-tab-trigger="rcrm_tab_consultant" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive"><span>{l s='Online consultant' mod='retailcrm'}<span/></a>
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" data-tab-trigger="rcrm_tab_advanced" class="retail-menu__btn retail-menu__btn_big retail-menu__btn_inactive retail-menu__btn_hidden"><span>{l s='Advanced' mod='retailcrm'}<span/></a>
</div>
</aside>
<article class="retail-column__content">
<h1 class="retail-title retail-title_content">Simla.com</h1>
<h1 class="retail-title retail-title_content">{$systemName|escape:'htmlall':'UTF-8'}</h1>
<div class="retail-form retail-form_main">
<form class="rcrm-form-submit-trigger" action="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm" method="post" id="submitretailcrm-form">
<input type="hidden" name="submitretailcrm" value="1" />
@ -121,6 +127,97 @@
</select>
</div>
</div>
<div id="rcrm_tab_catalog">
<div class="retail-form__title">
{$catalogTitleName|escape:'htmlall':'UTF-8'}
{if $catalogInfoMultistore|count == 1}
{assign var='catalogInfo' value=$catalogInfoMultistore[$catalogInfoMultistore|@key] }
<a href="{$url|cat:'/admin/sites/'|escape:'htmlall':'UTF-8'}{if $catalogInfo.siteId}{$catalogInfo.siteId|cat:'/edit#t-catalog'|escape:'htmlall':'UTF-8'}{/if}"
target="_blank"
class="retail-form__title_link">{l s='Manage site settings' mod='retailcrm'}</a>
{/if}
</div>
{foreach from=$catalogInfoMultistore key=catalogShopId item=catalogInfo}
<div class="retail-form__title" style="margin-top: 50px;">
{if $catalogInfoMultistore|count > 1}
<a href="{$url_post|escape:'htmlall':'UTF-8'}&amp;configure=retailcrm&rcrmtab=rcrm_tab_catalog&setShopContext=s-{$catalogShopId|escape:'htmlall':'UTF-8'}">{$shopsInfo[$catalogShopId].name|escape:'htmlall':'UTF-8'}</a>
<a href="{$url|cat:'/admin/sites/'|escape:'htmlall':'UTF-8'}{if $catalogInfo.siteId}{$catalogInfo.siteId|cat:'/edit#t-catalog'|escape:'htmlall':'UTF-8'}{/if}"
target="_blank"
class="retail-form__title_link">{l s='Manage site settings' mod='retailcrm'}</a>
{/if}
</div>
{if $catalogInfo and $catalogInfo.lastGenerated}
{if $catalogInfo.isOutdated }
<div class="retail-alert retail-alert-danger">
<div class="retail-alert-text">
{$catalogTitleName|escape:'htmlall':'UTF-8'} {l s='is outdated' mod='retailcrm'}
</div>
{elseif !$catalogInfo.isUrlActual}
{assign var="showUpdateButton" value=true}
<div class="retail-alert retail-alert-warning">
<div class="retail-alert-text">
{l s='URL for Icml catalog file in Prestashop and in %s do not match' mod='retailcrm' sprintf=[$systemName]}
</div>
{else}
<div class="retail-alert retail-alert-success">
<div class="retail-alert-text">
{$catalogTitleName|escape:'htmlall':'UTF-8'} {l s='connected' mod='retailcrm'}
</div>
{/if}
<div class="retail-alert-note">
{$catalogInfo.lastGenerated|date_format:"%Y-%m-%d %H:%M:%S"|escape:'htmlall':'UTF-8'}
</div>
</div>
<div class="retail-form__row">
<div class="retail-form__label">
<span style="font-weight: bold; font-size: 1.3em;">
{if $catalogInfo.lastGeneratedDiff.days > 7}
{l s='More than 7 days' mod='retailcrm'}
{else}
{if $catalogInfo.lastGeneratedDiff.days > 0}
{$catalogInfo.lastGeneratedDiff.days|escape:'htmlall':'UTF-8'} {l s='d' mod='retailcrm'}.
{/if}
{if $catalogInfo.lastGeneratedDiff.hours > 0}
{$catalogInfo.lastGeneratedDiff.hours|escape:'htmlall':'UTF-8'} {l s='h' mod='retailcrm'}.
{/if}
{$catalogInfo.lastGeneratedDiff.minutes|escape:'htmlall':'UTF-8'} {l s='min' mod='retailcrm'}.
{/if}
</span>
{l s='passed since last run' mod='retailcrm'}
</div>
<div class="retail-form__label">
<span style="font-weight: bold; font-size: 1.3em;">
{$catalogInfo.productsCount|default:'---'|escape:'htmlall':'UTF-8'}
</span>
{l s='Products' mod='retailcrm'}
<span style="font-weight: bold; font-size: 1.3em;">
{$catalogInfo.offersCount|default:'---'|escape:'htmlall':'UTF-8'}
</span>
{l s='Offers' mod='retailcrm'}
</div>
</div>
{else}
<div class="retail-alert retail-alert-warning">
<div class="retail-alert-text">
{$catalogTitleName|escape:'htmlall':'UTF-8'} {l s='was not generated yet' mod='retailcrm'}
</div>
<div class="retail-alert-note">
{l s='Press the below button to generate the %s' mod='retailcrm' sprintf=[$catalogTitleName]}
</div>
</div>
{/if}
{/foreach}
<input type="hidden" name="{$runJobName|escape:'htmlall':'UTF-8'}" value="">
<div class="retail-form__row retail-form__row_submit"
style="text-align: center; height: 60px; margin-bottom: 20px; margin-top: 50px; clear:both;">
<button id="update-icml-submit"
class="btn btn_invert btn_warning"
style="outline: none;{if !$showUpdateButton} display: none;{/if}">{l s='Update URL' mod='retailcrm'}</button>
<button id="generate-icml-submit"
class="btn btn_invert btn_submit"
style="outline: none;{if $showUpdateButton} display: none;{/if}">{l s='Generate now' mod='retailcrm'}</button>
</div>
</div>
<div id="rcrm_tab_delivery_types">
<div class="retail-form__title">
{l s='Delivery' mod='retailcrm'}
@ -302,7 +399,7 @@
</thead>
<tbody>
{foreach from=$lastRunDetails key=key item=item}
<tr class="retail-table__row-top">
<tr class="{if $key === $currentJob || $key === $currentJobCli} retail-table__row-bold{/if}">
<td>
{if isset($jobsNames[$key]) }
<span title="{$key|escape:'htmlall':'UTF-8'}">{l s=$jobsNames[$key] mod='retailcrm'}</span>
@ -415,5 +512,6 @@
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/vendor/jquery.sumoselect.min.js"></script>
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/retailcrm-tabs.min.js"></script>
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/retailcrm-upload.min.js"></script>
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/retailcrm-icml.min.js"></script>
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/retailcrm-export.min.js"></script>
<script src="{$assets|escape:'htmlall':'UTF-8'}/js/retailcrm.min.js"></script>