mirror of
https://github.com/retailcrm/prestashop-module.git
synced 2025-03-01 19:03:14 +03:00
proper cron & cli support, separated logs for different execution contexts (#65)
* proper cron & cli support, separated logs for separate execution contexts * different job-scope locks for cli and manager * proper signal handling pass * add proper cli path * trick prestashop into thinking that we're calling getProducts from back office * create order on edit if it's not present in retailCRM * prevent discount to be higher than total * fix for striped logging
This commit is contained in:
parent
d4f9e0b762
commit
1be638a970
@ -1,3 +1,9 @@
|
||||
## v3.0.5
|
||||
* Возможность установки регулярных задач в `cron`, CLI-интерфейс для запуска задач вручную
|
||||
* Теперь при отсутствии редактируемого заказа в retailCRM он будет создаваться (ранее попытка редактирования приводила к ошибке)
|
||||
* Доработана механика выгрузки брошенных корзин для большего соответствия ожиданиям API PrestaShop
|
||||
* Исправление ошибки округления скидки в заказе
|
||||
|
||||
## v3.0.4
|
||||
* Проверка корректности генерации категорий в ICML
|
||||
|
||||
|
54
retailcrm/cli.php
Normal file
54
retailcrm/cli.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
declare(ticks = 1);
|
||||
|
||||
require_once __DIR__ . '/lib/RetailcrmCli.php';
|
||||
|
||||
function retailcrmCliInterruptHandler($signo) {
|
||||
RetailcrmLogger::output('WARNING: Interrupt received, stopping...');
|
||||
RetailcrmCli::clearCurrentJob(null);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (php_sapi_name() == 'cli') {
|
||||
$cli = new RetailcrmCli(__FILE__);
|
||||
$cli->execute('retailcrmCliInterruptHandler');
|
||||
} else {
|
||||
include_once __DIR__ . DIRECTORY_SEPARATOR . 'index.php';
|
||||
}
|
@ -86,14 +86,7 @@ class RetailcrmJobsModuleFrontController extends ModuleFrontController
|
||||
*/
|
||||
protected function getData()
|
||||
{
|
||||
RetailcrmJobManager::startJobs(
|
||||
array(
|
||||
'RetailcrmAbandonedCartsEvent' => null,
|
||||
'RetailcrmIcmlEvent' => new \DateInterval('PT4H'),
|
||||
'RetailcrmSyncEvent' => new \DateInterval('PT7M'),
|
||||
'RetailcrmInventoriesEvent' => new \DateInterval('PT15M')
|
||||
)
|
||||
);
|
||||
RetailcrmJobManager::startJobs(RetailCRM::getJobs());
|
||||
|
||||
return array('success' => true);
|
||||
}
|
||||
|
233
retailcrm/lib/RetailcrmCli.php
Normal file
233
retailcrm/lib/RetailcrmCli.php
Normal file
@ -0,0 +1,233 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
|
||||
date_default_timezone_set(@date_default_timezone_get());
|
||||
}
|
||||
|
||||
require_once(dirname(__FILE__) . '/../../../config/config.inc.php');
|
||||
require_once(dirname(__FILE__) . '/../../../init.php');
|
||||
require_once(dirname(__FILE__) . '/../bootstrap.php');
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class RetailcrmCli
|
||||
*
|
||||
* @author DIGITAL RETAIL TECHNOLOGIES SL <mail@simlachat.com>
|
||||
* @license GPL
|
||||
* @link https://retailcrm.ru
|
||||
*/
|
||||
class RetailcrmCli
|
||||
{
|
||||
const CURRENT_TASK_CLI = 'RETAILCRM_JOB_CURRENT_CLI';
|
||||
|
||||
/** @var string CLI path */
|
||||
private $cliPath;
|
||||
|
||||
/**
|
||||
* RetailcrmCli constructor.
|
||||
*
|
||||
* @param string $cliPath
|
||||
*/
|
||||
public function __construct($cliPath)
|
||||
{
|
||||
RetailcrmLogger::setCloneToStdout(true);
|
||||
$this->cliPath = $cliPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run cli routine. Callable can be passed which will be used to handle terminate signals.
|
||||
*
|
||||
* @param callable|int|null $signalsHandler
|
||||
*/
|
||||
public function execute($signalsHandler = null)
|
||||
{
|
||||
if (function_exists('pcntl_signal')) {
|
||||
if (function_exists('pcntl_async_signals')) {
|
||||
pcntl_async_signals(true);
|
||||
}
|
||||
|
||||
if (function_exists('pcntl_signal_dispatch')) {
|
||||
pcntl_signal_dispatch();
|
||||
}
|
||||
|
||||
if (!empty($signalsHandler) && (is_callable($signalsHandler) || function_exists($signalsHandler))) {
|
||||
pcntl_signal(SIGINT, $signalsHandler);
|
||||
pcntl_signal(SIGTERM, $signalsHandler);
|
||||
pcntl_signal(SIGHUP, $signalsHandler);
|
||||
}
|
||||
} else {
|
||||
RetailcrmLogger::output('WARNING: cannot handle signals properly, force stop can cause problems!');
|
||||
}
|
||||
|
||||
$shortopts = "j:";
|
||||
$longopts = array("job:", "reset-job-manager");
|
||||
$options = getopt($shortopts, $longopts);
|
||||
$jobName = isset($options['j']) ? $options['j'] : (isset($options['job']) ? $options['job'] : null);
|
||||
|
||||
if (isset($options['reset-job-manager'])) {
|
||||
$this->resetJobManager();
|
||||
} elseif (empty($jobName)) {
|
||||
$this->help();
|
||||
} else {
|
||||
$this->runJob($jobName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs provided job
|
||||
*
|
||||
* @param string $jobName
|
||||
*/
|
||||
private function runJob($jobName)
|
||||
{
|
||||
try {
|
||||
$result = RetailcrmJobManager::runJob($jobName, true, true);
|
||||
RetailcrmLogger::output(sprintf(
|
||||
'Job %s was executed, result: %s',
|
||||
$jobName,
|
||||
$result ? 'true' : 'false'
|
||||
));
|
||||
} catch (\Exception $exception) {
|
||||
$this->printStack($exception);
|
||||
self::clearCurrentJob($jobName);
|
||||
} finally {
|
||||
if (isset($result) && $result) {
|
||||
self::clearCurrentJob($jobName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints error details
|
||||
*
|
||||
* @param \Exception $exception
|
||||
*/
|
||||
private function printStack($exception)
|
||||
{
|
||||
RetailcrmLogger::output(sprintf('Error while executing a job: %s', $exception->getMessage()));
|
||||
RetailcrmLogger::output(sprintf('%s:%d', $exception->getFile(), $exception->getLine()));
|
||||
RetailcrmLogger::output();
|
||||
RetailcrmLogger::output($exception->getTraceAsString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints CLI help
|
||||
*/
|
||||
private function help()
|
||||
{
|
||||
RetailcrmLogger::output('Available jobs:');
|
||||
RetailcrmLogger::output();
|
||||
|
||||
foreach (array_keys(RetailCRM::getJobs()) as $job) {
|
||||
RetailcrmLogger::output(sprintf(' - %s', $job));
|
||||
}
|
||||
|
||||
RetailcrmLogger::output();
|
||||
RetailcrmLogger::output('Usage:');
|
||||
RetailcrmLogger::output();
|
||||
RetailcrmLogger::output(sprintf('> php %s -j <job name> - Runs provided job', $this->cliPath));
|
||||
RetailcrmLogger::output(sprintf('> php %s --job <job name> - Runs provided job', $this->cliPath));
|
||||
RetailcrmLogger::output(sprintf(
|
||||
'> php %s --reset-job-manager - Will reset job manager internal timers & current job name',
|
||||
$this->cliPath
|
||||
));
|
||||
RetailcrmLogger::output();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets JobManager
|
||||
*/
|
||||
private function resetJobManager()
|
||||
{
|
||||
try {
|
||||
if (RetailcrmJobManager::reset()) {
|
||||
RetailcrmLogger::output('Job manager internal state was cleared.');
|
||||
} else {
|
||||
RetailcrmLogger::output('Job manager internal state was NOT cleared.');
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
$this->printStack($exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current running job. Every job must call this in CLI in order to work properly.
|
||||
* Current running job will be cleared automatically after job was finished (or crashed).
|
||||
* That way, JobManager will maintain it's data integrity and will coexist with manual runs and cron.
|
||||
*
|
||||
* @param string $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function setCurrentJob($job)
|
||||
{
|
||||
return (bool) Configuration::updateValue(self::CURRENT_TASK_CLI, $job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current job or empty string if there's no jobs running at this moment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCurrentJob()
|
||||
{
|
||||
return (string) Configuration::get(self::CURRENT_TASK_CLI);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears current job (job name must be provided to ensure we're removed correct job).
|
||||
*
|
||||
* @param string|null $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearCurrentJob($job)
|
||||
{
|
||||
if (Configuration::hasKey(self::CURRENT_TASK_CLI)) {
|
||||
if (is_null($job) || self::getCurrentJob() == $job) {
|
||||
return Configuration::deleteByName(self::CURRENT_TASK_CLI);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -59,6 +59,7 @@ class RetailcrmJobManager
|
||||
{
|
||||
const LAST_RUN_NAME = 'RETAILCRM_LAST_RUN';
|
||||
const IN_PROGRESS_NAME = 'RETAILCRM_JOBS_IN_PROGRESS';
|
||||
const CURRENT_TASK = 'RETAILCRM_JOB_CURRENT';
|
||||
|
||||
/**
|
||||
* Entry point for all jobs.
|
||||
@ -157,7 +158,11 @@ class RetailcrmJobManager
|
||||
|
||||
if (isset($shouldRunAt) && $shouldRunAt <= $current) {
|
||||
RetailcrmLogger::writeDebug(__METHOD__, sprintf('Executing job %s', $job));
|
||||
RetailcrmJobManager::runJob($job, $runOnceInContext);
|
||||
$result = RetailcrmJobManager::runJob($job, $runOnceInContext);
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
sprintf('Executed job %s, result: %s', $job, $result ? 'true' : 'false')
|
||||
);
|
||||
$lastRuns[$job] = new \DateTime('now');
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
@ -167,6 +172,11 @@ class RetailcrmJobManager
|
||||
$exception->getTraceAsString(),
|
||||
$job
|
||||
);
|
||||
self::clearCurrentJob($job);
|
||||
} finally {
|
||||
if (isset($result) && $result) {
|
||||
self::clearCurrentJob($job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -248,39 +258,29 @@ class RetailcrmJobManager
|
||||
*
|
||||
* @param string $job
|
||||
* @param bool $once
|
||||
* @param bool $cliMode
|
||||
*
|
||||
* @return bool
|
||||
* @throws \RetailcrmJobManagerException
|
||||
*/
|
||||
public static function runJob($job, $once = false)
|
||||
public static function runJob($job, $once = false, $cliMode = false)
|
||||
{
|
||||
$jobName = self::escapeJobName($job);
|
||||
$jobFile = implode(
|
||||
DIRECTORY_SEPARATOR,
|
||||
array(_PS_ROOT_DIR_, 'modules', 'retailcrm', 'lib', 'events', self::escapeJobName($job) . '.php')
|
||||
array(_PS_ROOT_DIR_, 'modules', 'retailcrm', 'lib', 'events', $jobName . '.php')
|
||||
);
|
||||
|
||||
if (!file_exists($jobFile)) {
|
||||
throw new \RetailcrmJobManagerException('Cannot find job', $job);
|
||||
}
|
||||
|
||||
static::execPHP($jobFile, $once);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs PHP file
|
||||
*
|
||||
* @param string $fileCommandLine
|
||||
* @param bool $once
|
||||
*
|
||||
* @throws \RetailcrmJobManagerException
|
||||
*/
|
||||
private static function execPHP($fileCommandLine, $once = false)
|
||||
{
|
||||
$error = null;
|
||||
|
||||
try {
|
||||
static::execHere($fileCommandLine, $once);
|
||||
return static::execHere($jobName, $jobFile, $once, $cliMode);
|
||||
} catch (\RetailcrmJobManagerException $exception) {
|
||||
throw $exception;
|
||||
} catch (\Exception $exception) {
|
||||
throw new RetailcrmJobManagerException($exception->getMessage(), $fileCommandLine);
|
||||
throw new RetailcrmJobManagerException($exception->getMessage(), $jobFile);
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,6 +300,71 @@ class RetailcrmJobManager
|
||||
return (string)base64_encode(json_encode($jobs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current running job. Every job must call this in order to work properly.
|
||||
* Current running job will be cleared automatically after job was finished (or crashed).
|
||||
* That way, JobManager will maintain it's data integrity and will coexist with manual runs and cron.
|
||||
*
|
||||
* @param string $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function setCurrentJob($job)
|
||||
{
|
||||
return (bool) Configuration::updateValue(self::CURRENT_TASK, $job);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current job or empty string if there's no jobs running at this moment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getCurrentJob()
|
||||
{
|
||||
return (string) Configuration::get(self::CURRENT_TASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears current job (job name must be provided to ensure we're removed correct job).
|
||||
*
|
||||
* @param string|null $job
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function clearCurrentJob($job)
|
||||
{
|
||||
if (Configuration::hasKey(self::CURRENT_TASK)) {
|
||||
if (is_null($job) || self::getCurrentJob() == $job) {
|
||||
return Configuration::deleteByName(self::CURRENT_TASK);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets JobManager internal state. Doesn't work if JobManager is active.
|
||||
*
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
$result = true;
|
||||
|
||||
if (Configuration::hasKey(self::CURRENT_TASK)) {
|
||||
$result = Configuration::deleteByName(self::CURRENT_TASK);
|
||||
}
|
||||
|
||||
if (Configuration::hasKey(self::LAST_RUN_NAME)) {
|
||||
$result = $result && Configuration::deleteByName(self::LAST_RUN_NAME);
|
||||
}
|
||||
|
||||
self::unlock();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes error to log and returns 500
|
||||
*
|
||||
@ -327,25 +392,34 @@ class RetailcrmJobManager
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes php script in this context, without hanging up request
|
||||
* Executes job without hanging up request (if executed by a hit).
|
||||
* Returns execution result from job.
|
||||
*
|
||||
* @param string $jobName
|
||||
* @param string $phpScript
|
||||
* @param bool $once
|
||||
* @param bool $cliMode
|
||||
*
|
||||
* @return bool
|
||||
* @throws \RetailcrmJobManagerException
|
||||
*/
|
||||
private static function execHere($phpScript, $once = false)
|
||||
private static function execHere($jobName, $phpScript, $once = false, $cliMode = false)
|
||||
{
|
||||
ignore_user_abort(true);
|
||||
set_time_limit(static::getTimeLimit());
|
||||
|
||||
if (version_compare(phpversion(), '7.0.16', '>=') &&
|
||||
function_exists('fastcgi_finish_request')
|
||||
) {
|
||||
if (!headers_sent()) {
|
||||
header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
}
|
||||
if (!$cliMode) {
|
||||
ignore_user_abort(true);
|
||||
|
||||
fastcgi_finish_request();
|
||||
if (version_compare(phpversion(), '7.0.16', '>=') &&
|
||||
function_exists('fastcgi_finish_request')
|
||||
) {
|
||||
if (!headers_sent()) {
|
||||
header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
}
|
||||
|
||||
fastcgi_finish_request();
|
||||
}
|
||||
}
|
||||
|
||||
if ($once) {
|
||||
@ -353,6 +427,27 @@ class RetailcrmJobManager
|
||||
} 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,
|
||||
$jobName
|
||||
));
|
||||
}
|
||||
|
||||
$job = new $jobName();
|
||||
|
||||
if (!($job instanceof RetailcrmEventInterface)) {
|
||||
throw new \RetailcrmJobManagerException(sprintf(
|
||||
'Class "%s" must implement RetailcrmEventInterface',
|
||||
$jobName
|
||||
));
|
||||
}
|
||||
|
||||
$job->setCliMode($cliMode);
|
||||
|
||||
return $job->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -47,6 +47,18 @@ if (!defined('_PS_VERSION_')) {
|
||||
*/
|
||||
class RetailcrmLogger
|
||||
{
|
||||
static $cloneToStdout;
|
||||
|
||||
/**
|
||||
* Set to true if you want all output to be cloned into STDOUT
|
||||
*
|
||||
* @param bool $cloneToStdout
|
||||
*/
|
||||
public static function setCloneToStdout($cloneToStdout)
|
||||
{
|
||||
self::$cloneToStdout = $cloneToStdout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write entry to log
|
||||
*
|
||||
@ -55,16 +67,22 @@ class RetailcrmLogger
|
||||
*/
|
||||
public static function writeCaller($caller, $message)
|
||||
{
|
||||
error_log(
|
||||
sprintf(
|
||||
'[%s] @ [%s] %s' . PHP_EOL,
|
||||
date(DATE_RFC3339),
|
||||
$caller,
|
||||
$message
|
||||
),
|
||||
3,
|
||||
static::getErrorLog()
|
||||
$result = sprintf(
|
||||
'[%s] @ [%s] %s' . PHP_EOL,
|
||||
date(DATE_RFC3339),
|
||||
$caller,
|
||||
$message
|
||||
);
|
||||
|
||||
error_log(
|
||||
$result,
|
||||
3,
|
||||
static::getLogFile()
|
||||
);
|
||||
|
||||
if (self::$cloneToStdout) {
|
||||
self::output($result, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,15 +92,34 @@ class RetailcrmLogger
|
||||
*/
|
||||
public static function writeNoCaller($message)
|
||||
{
|
||||
error_log(
|
||||
sprintf(
|
||||
'[%s] %s' . PHP_EOL,
|
||||
date(DATE_RFC3339),
|
||||
$message
|
||||
),
|
||||
3,
|
||||
static::getErrorLog()
|
||||
$result = sprintf(
|
||||
'[%s] %s' . PHP_EOL,
|
||||
date(DATE_RFC3339),
|
||||
$message
|
||||
);
|
||||
|
||||
error_log(
|
||||
$result,
|
||||
3,
|
||||
static::getLogFile()
|
||||
);
|
||||
|
||||
if (self::$cloneToStdout) {
|
||||
self::output($result, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output message to stdout
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $end
|
||||
*/
|
||||
public static function output($message = '', $end = PHP_EOL)
|
||||
{
|
||||
if (php_sapi_name() == 'cli') {
|
||||
echo $message . $end;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -103,16 +140,34 @@ class RetailcrmLogger
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns error log path
|
||||
* Returns log file path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getErrorLog()
|
||||
public static function getLogFile()
|
||||
{
|
||||
if (!defined('_PS_ROOT_DIR_')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return _PS_ROOT_DIR_ . '/retailcrm.log';
|
||||
return _PS_ROOT_DIR_ . '/retailcrm_' . self::getLogFilePrefix() . '.log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns log file prefix based on current environment
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function getLogFilePrefix()
|
||||
{
|
||||
if (php_sapi_name() == 'cli') {
|
||||
if (isset($_SERVER['TERM'])) {
|
||||
return 'cli';
|
||||
} else {
|
||||
return 'cron';
|
||||
}
|
||||
}
|
||||
|
||||
return 'web';
|
||||
}
|
||||
}
|
@ -359,7 +359,7 @@ class RetailcrmTools
|
||||
$apiKey = Configuration::get(RetailCRM::API_KEY);
|
||||
|
||||
if (!empty($apiUrl) && !empty($apiKey)) {
|
||||
return new RetailcrmProxy($apiUrl, $apiKey, RetailCRM::getErrorLog());
|
||||
return new RetailcrmProxy($apiUrl, $apiKey, RetailcrmLogger::getLogFile());
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -38,23 +38,33 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmAbandonedCartsEvent implements RetailcrmEventInterface
|
||||
class RetailcrmAbandonedCartsEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
$syncCartsActive = Configuration::get(RetailCRM::SYNC_CARTS_ACTIVE);
|
||||
|
||||
if (empty($syncCartsActive)) {
|
||||
return;
|
||||
RetailcrmLogger::writeCaller(__METHOD__, 'Abandoned carts is disabled, skipping...');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$api = RetailcrmTools::getApiClient();
|
||||
|
||||
if (empty($api)) {
|
||||
RetailcrmLogger::writeCaller('abandonedCarts', 'set api key & url first');
|
||||
return;
|
||||
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RetailcrmCartUploader::init();
|
||||
@ -63,8 +73,15 @@ class RetailcrmAbandonedCartsEvent implements RetailcrmEventInterface
|
||||
RetailcrmCartUploader::$syncStatus = Configuration::get(RetailCRM::SYNC_CARTS_STATUS);
|
||||
RetailcrmCartUploader::setSyncDelay(Configuration::get(RetailCRM::SYNC_CARTS_DELAY));
|
||||
RetailcrmCartUploader::run();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmAbandonedCartsEvent';
|
||||
}
|
||||
}
|
||||
|
||||
$event = new RetailcrmAbandonedCartsEvent();
|
||||
$event->execute();
|
||||
|
92
retailcrm/lib/events/RetailcrmAbstractEvent.php
Normal file
92
retailcrm/lib/events/RetailcrmAbstractEvent.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?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');
|
||||
|
||||
abstract class RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
private $cliMode;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
abstract public function execute();
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
throw new InvalidArgumentException("Not implemented.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets cli mode to true. CLI mode here stands for any execution outside of JobManager context.
|
||||
*
|
||||
* @param bool $mode
|
||||
*/
|
||||
public function setCliMode($mode)
|
||||
{
|
||||
$this->cliMode = (bool) $mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if current job is running now
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isRunning()
|
||||
{
|
||||
return (strcmp(RetailcrmJobManager::getCurrentJob(), $this->getName() === 0))
|
||||
|| (strcmp(RetailcrmCli::getCurrentJob(), $this->getName() === 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets current job as active based on execution context.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function setRunning()
|
||||
{
|
||||
if ($this->cliMode) {
|
||||
return RetailcrmCli::setCurrentJob($this->getName());
|
||||
}
|
||||
|
||||
return RetailcrmJobManager::setCurrentJob($this->getName());
|
||||
}
|
||||
}
|
@ -39,9 +39,24 @@
|
||||
interface RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* Execute event
|
||||
* Executes event. Event MUST return true if it was executed. False should be returned only when event
|
||||
* found out that it's already running.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function execute();
|
||||
|
||||
/**
|
||||
* Returns event name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Sets cli mode to true. CLI mode here stands for any execution outside of JobManager context.
|
||||
*
|
||||
* @param bool $mode
|
||||
*/
|
||||
public function setCliMode($mode);
|
||||
}
|
||||
|
@ -38,18 +38,25 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmExportEvent implements RetailcrmEventInterface
|
||||
class RetailcrmExportEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
$api = RetailcrmTools::getApiClient();
|
||||
|
||||
if (empty($api)) {
|
||||
RetailcrmLogger::writeCaller('orderHistory', 'set api key & url first');
|
||||
exit();
|
||||
RetailcrmLogger::writeCaller(__METHOD__, 'Set API key & URL first');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$orders = array();
|
||||
@ -84,11 +91,8 @@ class RetailcrmExportEvent implements RetailcrmEventInterface
|
||||
$orders[] = $orderBuilder->buildOrderWithPreparedCustomer();
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
RetailcrmLogger::writeCaller('export', $exception->getMessage());
|
||||
RetailcrmLogger::writeNoCaller($e->getTraceAsString());
|
||||
|
||||
if (PHP_SAPI == 'cli') {
|
||||
echo $exception->getMessage() . PHP_EOL;
|
||||
}
|
||||
RetailcrmLogger::writeNoCaller($exception->getTraceAsString());
|
||||
RetailcrmLogger::output($exception->getMessage());
|
||||
}
|
||||
|
||||
time_nanosleep(0, 500000000);
|
||||
@ -101,8 +105,15 @@ class RetailcrmExportEvent implements RetailcrmEventInterface
|
||||
foreach ($orders as $chunk) {
|
||||
$api->ordersUpload($chunk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmExportEvent';
|
||||
}
|
||||
}
|
||||
|
||||
$event = new RetailcrmExportEvent();
|
||||
$event->execute();
|
||||
|
@ -38,20 +38,33 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmIcmlEvent implements RetailcrmEventInterface
|
||||
class RetailcrmIcmlEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
$job = new RetailcrmCatalog();
|
||||
$data = $job->getData();
|
||||
|
||||
$icml = new RetailcrmIcml(Configuration::get('PS_SHOP_NAME'), _PS_ROOT_DIR_ . '/retailcrm.xml');
|
||||
$icml->generate($data[0], $data[1]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmIcmlEvent';
|
||||
}
|
||||
}
|
||||
|
||||
$event = new RetailcrmIcmlEvent();
|
||||
$event->execute();
|
||||
|
@ -38,33 +38,49 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmInventoriesEvent implements RetailcrmEventInterface
|
||||
class RetailcrmInventoriesEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
if (!Configuration::get(RetailCRM::ENABLE_BALANCES_RECEIVING)) {
|
||||
RetailcrmLogger::writeDebug(
|
||||
'RetailcrmInventoriesEvent',
|
||||
'Balances receiving is not enabled, skipping...'
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$apiUrl = Configuration::get(RetailCRM::API_URL);
|
||||
$apiKey = Configuration::get(RetailCRM::API_KEY);
|
||||
|
||||
if (!empty($apiUrl) && !empty($apiKey)) {
|
||||
RetailcrmInventories::$api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log');
|
||||
RetailcrmInventories::$api = new RetailcrmProxy($apiUrl, $apiKey, RetailcrmLogger::getLogFile());
|
||||
} else {
|
||||
RetailcrmLogger::writeCaller('inventories', 'set api key & url first');
|
||||
exit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RetailcrmInventories::loadStocks();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmInventoriesEvent';
|
||||
}
|
||||
}
|
||||
|
||||
if (Configuration::get(RetailCRM::ENABLE_BALANCES_RECEIVING)) {
|
||||
$event = new RetailcrmInventoriesEvent();
|
||||
$event->execute();
|
||||
} else {
|
||||
RetailcrmLogger::writeDebug(
|
||||
'RetailcrmInventoriesEvent',
|
||||
'Balances receiving is not enabled, skipping...'
|
||||
);
|
||||
}
|
||||
|
@ -38,29 +38,37 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmMissingEvent implements RetailcrmEventInterface
|
||||
class RetailcrmMissingEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
$shortopts = 'o:';
|
||||
$options = getopt($shortopts);
|
||||
|
||||
if (!isset($options['o'])) {
|
||||
echo ('Parameter -o is missing');
|
||||
exit();
|
||||
echo 'Parameter -o is missing';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$apiUrl = Configuration::get(RetailCRM::API_URL);
|
||||
$apiKey = Configuration::get(RetailCRM::API_KEY);
|
||||
|
||||
if (!empty($apiUrl) && !empty($apiKey)) {
|
||||
$api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log');
|
||||
$api = new RetailcrmProxy($apiUrl, $apiKey, RetailcrmLogger::getLogFile());
|
||||
} else {
|
||||
echo('Set api key & url first');
|
||||
exit();
|
||||
echo 'Set api key & url first';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$delivery = json_decode(Configuration::get(RetailCRM::DELIVERY), true);
|
||||
@ -97,7 +105,7 @@ class RetailcrmMissingEvent implements RetailcrmEventInterface
|
||||
$order['lastName'] = $orderCustomer->lastname;
|
||||
$order['email'] = $orderCustomer->email;
|
||||
} else {
|
||||
exit();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -195,8 +203,12 @@ class RetailcrmMissingEvent implements RetailcrmEventInterface
|
||||
}
|
||||
|
||||
$api->ordersEdit($order);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmMissingEvent';
|
||||
}
|
||||
}
|
||||
|
||||
$event = new RetailcrmMissingEvent();
|
||||
$event->execute();
|
||||
|
@ -38,36 +38,51 @@
|
||||
|
||||
require_once(dirname(__FILE__) . '/../RetailcrmPrestashopLoader.php');
|
||||
|
||||
class RetailcrmSyncEvent implements RetailcrmEventInterface
|
||||
class RetailcrmSyncEvent extends RetailcrmAbstractEvent implements RetailcrmEventInterface
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->setRunning();
|
||||
|
||||
if (!Configuration::get(RetailCRM::ENABLE_HISTORY_UPLOADS)) {
|
||||
RetailcrmLogger::writeDebug(
|
||||
__METHOD__,
|
||||
'History uploads is not enabled, skipping...'
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$apiUrl = Configuration::get(RetailCRM::API_URL);
|
||||
$apiKey = Configuration::get(RetailCRM::API_KEY);
|
||||
RetailcrmHistory::$default_lang = (int) Configuration::get('PS_LANG_DEFAULT');
|
||||
|
||||
if (!empty($apiUrl) && !empty($apiKey)) {
|
||||
RetailcrmHistory::$api = new RetailcrmProxy($apiUrl, $apiKey, _PS_ROOT_DIR_ . '/retailcrm.log');
|
||||
RetailcrmHistory::$api = new RetailcrmProxy($apiUrl, $apiKey, RetailcrmLogger::getLogFile());
|
||||
} else {
|
||||
RetailcrmLogger::writeCaller('orderHistory', 'set api key & url first');
|
||||
exit();
|
||||
RetailcrmLogger::writeCaller(__METHOD__, 'Set api key & url first');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RetailcrmHistory::customersHistory();
|
||||
RetailcrmHistory::ordersHistory();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'RetailcrmSyncEvent';
|
||||
}
|
||||
}
|
||||
|
||||
if (Configuration::get(RetailCRM::ENABLE_HISTORY_UPLOADS)) {
|
||||
$event = new RetailcrmSyncEvent();
|
||||
$event->execute();
|
||||
} else {
|
||||
RetailcrmLogger::writeDebug(
|
||||
'RetailcrmSyncEvent',
|
||||
'History uploads is not enabled, skipping...'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -116,7 +116,7 @@ class RetailCRM extends Module
|
||||
{
|
||||
$this->name = 'retailcrm';
|
||||
$this->tab = 'export';
|
||||
$this->version = '3.0.4';
|
||||
$this->version = '3.0.5';
|
||||
$this->author = 'DIGITAL RETAIL TECHNOLOGIES SL';
|
||||
$this->displayName = $this->l('retailCRM');
|
||||
$this->description = $this->l('Integration module for retailCRM');
|
||||
@ -128,7 +128,7 @@ class RetailCRM extends Module
|
||||
$this->apiKey = Configuration::get(static::API_KEY);
|
||||
$this->ps_versions_compliancy = array('min' => '1.6.1.0', 'max' => _PS_VERSION_);
|
||||
$this->psVersion = Tools::substr(_PS_VERSION_, 0, 3);
|
||||
$this->log = static::getErrorLog();
|
||||
$this->log = RetailcrmLogger::getLogFile();
|
||||
$this->module_key = 'dff3095326546f5fe8995d9e86288491';
|
||||
$this->assetsBase =
|
||||
Tools::getShopDomainSsl(true, true) .
|
||||
@ -186,7 +186,7 @@ class RetailCRM extends Module
|
||||
$api = new RetailcrmProxy(
|
||||
$apiUrl,
|
||||
$apiKey,
|
||||
static::getErrorLog()
|
||||
RetailcrmLogger::getLogFile()
|
||||
);
|
||||
|
||||
$clientId = Configuration::get(static::CLIENT_ID);
|
||||
@ -946,20 +946,6 @@ class RetailCRM extends Module
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns error log path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getErrorLog()
|
||||
{
|
||||
if (!defined('_PS_ROOT_DIR_')) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return _PS_ROOT_DIR_ . '/retailcrm.log';
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from modules list cache
|
||||
*
|
||||
@ -1148,6 +1134,21 @@ class RetailCRM extends Module
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns jobs list
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getJobs()
|
||||
{
|
||||
return array(
|
||||
'RetailcrmAbandonedCartsEvent' => null,
|
||||
'RetailcrmIcmlEvent' => new \DateInterval('PT4H'),
|
||||
'RetailcrmSyncEvent' => new \DateInterval('PT7M'),
|
||||
'RetailcrmInventoriesEvent' => new \DateInterval('PT15M')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronized cartsIds time choice
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user