diff --git a/202/build.xml b/202/build.xml
index abe4c0da..280530d0 100644
--- a/202/build.xml
+++ b/202/build.xml
@@ -5,7 +5,7 @@
-
+
diff --git a/classes/ShoppingfeedApi.php b/classes/ShoppingfeedApi.php
index 98ab96e2..39e9b5b9 100644
--- a/classes/ShoppingfeedApi.php
+++ b/classes/ShoppingfeedApi.php
@@ -22,6 +22,7 @@
use ShoppingFeed\Sdk\Api\Catalog\InventoryUpdate;
use ShoppingFeed\Sdk\Api\Catalog\PricingUpdate;
+use ShoppingFeed\Sdk\Api\Order\Document\Invoice;
use ShoppingFeed\Sdk\Api\Order\Identifier\Id;
use ShoppingFeed\Sdk\Api\Order\Operation;
use ShoppingFeed\Sdk\Client\Client;
@@ -314,6 +315,12 @@ public function updateMainStoreOrdersStatus($taskOrders, $shoppingfeed_store_id
new Id((int) $taskOrder['id_internal_shoppingfeed'])
);
continue 2;
+ case Shoppingfeed::ORDER_OPERATION_UPLOAD_DOCUMENTS:
+ $operation->uploadDocument(
+ new Id((int) $taskOrder['id_internal_shoppingfeed']),
+ new Invoice($taskOrder['payload']['uri'])
+ );
+ continue 2;
}
}
diff --git a/classes/ShoppingfeedTaskOrder.php b/classes/ShoppingfeedTaskOrder.php
index 31a66de0..e012cab3 100644
--- a/classes/ShoppingfeedTaskOrder.php
+++ b/classes/ShoppingfeedTaskOrder.php
@@ -27,6 +27,8 @@ class ShoppingfeedTaskOrder extends ObjectModel
{
const ACTION_SYNC_STATUS = 'SYNC_STATUS';
+ const ACTION_UPLOAD_INVOICE = 'UPLOAD_INVOICE';
+
// As in, "check the ticket related to the Order Status synchronization"
const ACTION_CHECK_TICKET_SYNC_STATUS = 'CHECK_TICKET_SYNC_STATUS';
@@ -60,7 +62,11 @@ class ShoppingfeedTaskOrder extends ObjectModel
'validate' => 'isGenericName',
'required' => true,
'unique' => true,
- 'values' => [self::ACTION_SYNC_STATUS, self::ACTION_CHECK_TICKET_SYNC_STATUS],
+ 'values' => [
+ self::ACTION_SYNC_STATUS,
+ self::ACTION_CHECK_TICKET_SYNC_STATUS,
+ self::ACTION_UPLOAD_INVOICE,
+ ],
],
'id_order' => [
'type' => ObjectModel::TYPE_INT,
diff --git a/classes/actions/ShoppingfeedOrderSyncActions.php b/classes/actions/ShoppingfeedOrderSyncActions.php
index 5b265071..2eaac026 100644
--- a/classes/actions/ShoppingfeedOrderSyncActions.php
+++ b/classes/actions/ShoppingfeedOrderSyncActions.php
@@ -386,6 +386,78 @@ public function prepareTaskOrdersSyncStatus()
return true;
}
+ public function prepareTaskOrdersSyncInvoice()
+ {
+ if (empty($this->conveyor['id_shop'])) {
+ ProcessLoggerHandler::logError(
+ $this->l('No ID Shop found.', 'ShoppingfeedOrderSyncActions'),
+ 'Order'
+ );
+
+ return false;
+ }
+ if (empty($this->conveyor['taskOrders'])) {
+ ProcessLoggerHandler::logInfo(
+ $this->l('No Task Orders to prepare.', 'ShoppingfeedOrderSyncActions'),
+ 'Order'
+ );
+
+ return false;
+ }
+
+ $taskOrders = $this->conveyor['taskOrders'];
+ $this->conveyor['preparedTaskOrders'] = [];
+
+ foreach ($taskOrders as $taskOrder) {
+ /** @var $taskOrder ShoppingfeedTaskOrder */
+ $logPrefix = self::getLogPrefix($taskOrder->id_order);
+ $order = new Order($taskOrder->id_order);
+ $sfOrder = ShoppingfeedOrder::getByIdOrder($taskOrder->id_order);
+
+ if (!Validate::isLoadedObject($order)) {
+ ProcessLoggerHandler::logError(
+ $logPrefix . ' ' .
+ $this->l('Order could not be loaded.', 'ShoppingfeedOrderSyncActions'),
+ 'Order',
+ $taskOrder->id_order
+ );
+ Registry::increment('syncStatusErrors');
+ continue;
+ }
+
+ if (empty($sfOrder->id_internal_shoppingfeed)) {
+ ProcessLoggerHandler::logError(
+ $logPrefix . ' ' .
+ $this->l('No SF Order id set.', 'ShoppingfeedOrderSyncActions'),
+ 'Order',
+ $taskOrder->id_order
+ );
+ Registry::increment('syncStatusErrors');
+ continue;
+ }
+
+ foreach ($order->getInvoicesCollection() as $invoice) {
+ $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, Context::getContext()->smarty);
+ $file = _PS_MODULE_DIR_ . 'shoppingfeed/views/tmp/' . $invoice->id . '.pdf';
+ $isInvoiceExist = file_put_contents($file, $pdf->render(false));
+
+ if ($isInvoiceExist) {
+ $this->conveyor['preparedTaskOrders'][Shoppingfeed::ORDER_OPERATION_UPLOAD_DOCUMENTS][] = [
+ 'id_internal_shoppingfeed' => $sfOrder->id_internal_shoppingfeed,
+ 'taskOrder' => $taskOrder,
+ 'file' => $file,
+ 'operation' => Shoppingfeed::ORDER_OPERATION_UPLOAD_DOCUMENTS,
+ 'payload' => [
+ 'uri' => $file,
+ ],
+ ];
+ }
+ }
+ }
+
+ return true;
+ }
+
protected function initCarrierFinder()
{
return new CarrierFinder();
@@ -460,6 +532,71 @@ public function sendTaskOrdersSyncStatus()
return true;
}
+ public function sendTaskOrdersSyncInvoice()
+ {
+ if (empty($this->conveyor['id_shop'])) {
+ ProcessLoggerHandler::logError(
+ $this->l('No ID Shop found.', 'ShoppingfeedOrderSyncActions'),
+ 'Order'
+ );
+
+ return false;
+ }
+
+ if (empty($this->conveyor['preparedTaskOrders'])) {
+ ProcessLoggerHandler::logError(
+ $this->l('No prepared Task Orders found.', 'ShoppingfeedOrderSyncActions'),
+ 'Order'
+ );
+
+ return false;
+ }
+
+ $shoppingfeedApi = ShoppingfeedApi::getInstanceByToken($this->conveyor['id_token']);
+ if ($shoppingfeedApi == false) {
+ ProcessLoggerHandler::logError(
+ $this->l('Could not retrieve Shopping Feed API.', 'ShoppingfeedOrderSyncActions'),
+ 'Order'
+ );
+
+ return false;
+ }
+
+ foreach ($this->conveyor['preparedTaskOrders'] as $preparedTaskOrders) {
+ $result = $shoppingfeedApi->updateMainStoreOrdersStatus($preparedTaskOrders, $this->conveyor['shoppingfeed_store_id']);
+
+ if (!$result) {
+ continue;
+ }
+
+ $batchId = current($result->getBatchIds());
+ if (empty($batchId) === true) {
+ continue;
+ }
+
+ foreach ($preparedTaskOrders as $preparedTaskOrder) {
+ $taskOrder = $preparedTaskOrder['taskOrder'];
+ $taskOrder->batch_id = $batchId;
+ $taskOrder->action = ShoppingfeedTaskOrder::ACTION_CHECK_TICKET_SYNC_STATUS;
+ $taskOrder->save();
+
+ ProcessLoggerHandler::logSuccess(
+ static::getLogPrefix($taskOrder->id_order) . ' ' . $this->l('Ticket created to upload an order invoice', 'ShoppingfeedOrderSyncActions'),
+ 'Order',
+ $taskOrder->id_order
+ );
+
+ $this->conveyor['successfulTaskOrders'][] = $taskOrder;
+ unlink($preparedTaskOrder['file']);
+ }
+ }
+ if (empty($this->conveyor['successfulTaskOrders'])) {
+ return false;
+ }
+
+ return true;
+ }
+
public function prepareTaskOrdersCheckTicketsSyncStatus()
{
if (empty($this->conveyor['taskOrders'])) {
diff --git a/controllers/admin/AdminShoppingfeedOrderImportRules.php b/controllers/admin/AdminShoppingfeedOrderImportRules.php
index b541a71e..b259d9a9 100644
--- a/controllers/admin/AdminShoppingfeedOrderImportRules.php
+++ b/controllers/admin/AdminShoppingfeedOrderImportRules.php
@@ -193,8 +193,8 @@ public function renderOrderSyncForm($order_sync_available, $order_import_availab
$orderShippedState['selected'] = [];
$orderCancelledState['selected'] = [];
- $orderDeliveredState['selected'] = [];
$orderRefundedState['selected'] = [];
+ $orderDeliveredState['selected'] = [];
$orderShippedState['unselected'] = [];
$orderCancelledState['unselected'] = [];
$orderRefundedState['unselected'] = [];
@@ -543,6 +543,13 @@ function ($c) {
],
];
+ if ($this->module->isUploadOrderDocumentReady()) {
+ $fields_form['form']['form']['input'][] = [
+ 'type' => 'shoppingfeed_marketplace_switch_list',
+ 'marketplaces' => \ShoppingfeedAddon\OrderInvoiceSync\Hub::getInstance()->getMarketplaces(),
+ ];
+ }
+
$helper = new HelperForm();
$helper->fields_value = [
Shoppingfeed::ORDER_IMPORT_ENABLED => !$order_import_available ? false : Configuration::get(Shoppingfeed::ORDER_IMPORT_ENABLED),
@@ -648,6 +655,16 @@ public function saveOrdersConfig()
);
}
+ if (Tools::getValue('order_invoice_sync_marketplace')) {
+ foreach (Tools::getValue('order_invoice_sync_marketplace') as $id => $isEnabled) {
+ if ((int) $isEnabled) {
+ \ShoppingfeedAddon\OrderInvoiceSync\Hub::getInstance()->enable($id);
+ } else {
+ \ShoppingfeedAddon\OrderInvoiceSync\Hub::getInstance()->disable($id);
+ }
+ }
+ }
+
$orderStatusesShipped = Tools::getValue('status_shipped_order');
if (!$orderStatusesShipped) {
$orderStatusesShipped = [];
diff --git a/controllers/front/syncOrder.php b/controllers/front/syncOrder.php
index 5d9c361c..8b8caf59 100644
--- a/controllers/front/syncOrder.php
+++ b/controllers/front/syncOrder.php
@@ -200,6 +200,65 @@ public function syncOrderStatus()
$this->processMonitor->getProcessObjectModelId()
);
}
+ // Start upload invoices
+ ProcessLoggerHandler::logInfo(
+ $logPrefix . ' ' . $this->module->l('Process start : Order invoice sync', 'syncOrder'),
+ $this->processMonitor->getProcessObjectModelName(),
+ $this->processMonitor->getProcessObjectModelId()
+ );
+
+ $failedSyncStatusTaskOrders = [];
+ $successfulSyncTaskOrders = [];
+ try {
+ Registry::set('syncStatusErrors', 0);
+
+ /** @var ShoppingfeedHandler $orderStatusHandler */
+ $orderStatusHandler = new ActionsHandler();
+ $orderStatusHandler->setConveyor([
+ 'id_shop' => $token['id_shop'],
+ 'id_token' => $token['id_shoppingfeed_token'],
+ 'order_action' => ShoppingfeedTaskOrder::ACTION_UPLOAD_INVOICE,
+ 'shoppingfeed_store_id' => $token['shoppingfeed_store_id'],
+ ]);
+ $orderStatusHandler->addActions(
+ 'getTaskOrders',
+ 'prepareTaskOrdersSyncInvoice',
+ 'sendTaskOrdersSyncInvoice'
+ );
+
+ if ($orderStatusHandler->process('ShoppingfeedOrderSync')) {
+ $processData = $orderStatusHandler->getConveyor();
+ $failedSyncStatusTaskOrders = isset($processData['failedTaskOrders']) ? $processData['failedTaskOrders'] : [];
+ $successfulSyncTaskOrders = isset($processData['successfulTaskOrders']) ? $processData['successfulTaskOrders'] : [];
+
+ ProcessLoggerHandler::logSuccess(
+ sprintf(
+ $logPrefix . ' ' . $this->module->l('%d tickets created; %d tickets not created; %d errors', 'syncOrder'),
+ count($successfulSyncTaskOrders),
+ count($failedSyncStatusTaskOrders),
+ Registry::get('syncStatusErrors')
+ ),
+ $this->processMonitor->getProcessObjectModelName(),
+ $this->processMonitor->getProcessObjectModelId()
+ );
+ }
+
+ ProcessLoggerHandler::logInfo(
+ $logPrefix . ' ' . $this->module->l('Process finished : Order invoice sync', 'syncOrder'),
+ $this->processMonitor->getProcessObjectModelName(),
+ $this->processMonitor->getProcessObjectModelId()
+ );
+ } catch (Throwable $e) {
+ ProcessLoggerHandler::logError(
+ sprintf(
+ $logPrefix . ' ' . $this->module->l('Error : %s', 'syncOrder'),
+ $e->getMessage() . ' ' . $e->getFile() . ':' . $e->getLine()
+ ),
+ $this->processMonitor->getProcessObjectModelName(),
+ $this->processMonitor->getProcessObjectModelId()
+ );
+ }
+ // End upload invoices
// Send mail
try {
diff --git a/shoppingfeed.php b/shoppingfeed.php
index 220516a9..cd3a08fa 100644
--- a/shoppingfeed.php
+++ b/shoppingfeed.php
@@ -16,6 +16,9 @@
* @copyright Since 2019 Shopping Feed
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
*/
+
+use ShoppingfeedAddon\OrderInvoiceSync\Hub;
+
if (!defined('_PS_VERSION_')) {
exit;
}
@@ -106,6 +109,8 @@ class Shoppingfeed extends \ShoppingfeedClasslib\Module
const ORDER_OPERATION_DELIVER = 'deliver';
+ const ORDER_INVOICE_SYNC_MARKETPLACES = 'SHOPPINGFEED_ORDER_INVOICE_SYNC_MARKETPLACES';
+
public $extensions = [
\ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerExtension::class,
\ShoppingfeedClasslib\Extensions\ProcessMonitor\ProcessMonitorExtension::class,
@@ -1245,6 +1250,41 @@ public function hookActionValidateOrder($params)
\ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::closeLogger();
}
+ protected function addOrderTask($id_order, $action)
+ {
+ $logPrefix = ShoppingfeedOrderSyncActions::getLogPrefix($id_order);
+ try {
+ \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::logInfo(
+ sprintf(
+ $logPrefix . ' ' .
+ $this->l('Process started Order %s ', 'ShoppingfeedOrderActions'),
+ $id_order
+ ),
+ 'Order',
+ $id_order
+ );
+ $handler = new \ShoppingfeedClasslib\Actions\ActionsHandler();
+ $handler
+ ->setConveyor([
+ 'id_order' => $id_order,
+ 'order_action' => $action,
+ ])
+ ->addActions('saveTaskOrder')
+ ->process('shoppingfeedOrderSync');
+ } catch (Exception $e) {
+ \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::logInfo(
+ sprintf(
+ $logPrefix . ' ' . $this->l('Order %s not registered for synchronization: %s', 'ShoppingfeedOrderActions'),
+ $id_order,
+ $e->getMessage() . ' ' . $e->getFile() . ':' . $e->getLine()
+ ),
+ 'Order',
+ $id_order
+ );
+ }
+ \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::closeLogger();
+ }
+
/**
* Saves an order for status synchronization
*
@@ -1264,53 +1304,29 @@ public function hookActionOrderStatusPostUpdate($params)
}
$order = new Order($params['id_order']);
-
- // Check if the new status calls for an update with Shopping Feed
+ /** @var OrderState $newOrderStatus */
$newOrderStatus = $params['newOrderStatus'];
$shipped_status = json_decode(Configuration::get(Shoppingfeed::SHIPPED_ORDERS, null, null, $order->id_shop));
$cancelled_status = json_decode(Configuration::get(Shoppingfeed::CANCELLED_ORDERS, null, null, $order->id_shop));
$refunded_status = json_decode(Configuration::get(Shoppingfeed::REFUNDED_ORDERS, null, null, $order->id_shop));
$delivered_status = json_decode(Configuration::get(Shoppingfeed::DELIVERED_ORDERS, null, null, $order->id_shop));
- if (!in_array($newOrderStatus->id, $shipped_status)
- && !in_array($newOrderStatus->id, $cancelled_status)
- && !in_array($newOrderStatus->id, $refunded_status)
- && !in_array($newOrderStatus->id, $delivered_status)
+
+ if (in_array($newOrderStatus->id, $shipped_status)
+ || in_array($newOrderStatus->id, $cancelled_status)
+ || in_array($newOrderStatus->id, $refunded_status)
+ || in_array($newOrderStatus->id, $delivered_status)
) {
- return;
+ $this->addOrderTask($shoppingFeedOrder->id_order, ShoppingfeedTaskOrder::ACTION_SYNC_STATUS);
}
- $logPrefix = ShoppingfeedOrderSyncActions::getLogPrefix($shoppingFeedOrder->id_order);
- try {
- \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::logInfo(
- sprintf(
- $logPrefix . ' ' .
- $this->l('Process started Order %s ', 'ShoppingfeedOrderActions'),
- $shoppingFeedOrder->id_order
- ),
- 'Order',
- $shoppingFeedOrder->id_order
- );
- $handler = new \ShoppingfeedClasslib\Actions\ActionsHandler();
- $handler
- ->setConveyor([
- 'id_order' => $params['id_order'],
- 'order_action' => ShoppingfeedTaskOrder::ACTION_SYNC_STATUS,
- ])
- ->addActions('saveTaskOrder')
- ->process('shoppingfeedOrderSync');
- } catch (Exception $e) {
- \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::logInfo(
- sprintf(
- $logPrefix . ' ' . $this->l('Order %s not registered for synchronization: %s', 'ShoppingfeedOrderActions'),
- $params['id_order'],
- $e->getMessage() . ' ' . $e->getFile() . ':' . $e->getLine()
- ),
- 'Order',
- $params['id_order']
- );
+ if ($this->isUploadOrderDocumentReady()) {
+ if ($newOrderStatus->invoice) {
+ $marketplace = Hub::getInstance()->findByName($shoppingFeedOrder->name_marketplace);
+ if ($marketplace && $marketplace->isEnabled()) {
+ $this->addOrderTask($shoppingFeedOrder->id_order, ShoppingfeedTaskOrder::ACTION_UPLOAD_INVOICE);
+ }
+ }
}
-
- \ShoppingfeedClasslib\Extensions\ProcessLogger\ProcessLoggerHandler::closeLogger();
}
/**
@@ -1569,4 +1585,9 @@ public function addIndexToPreloadingTable()
return $result;
}
+
+ public function isUploadOrderDocumentReady()
+ {
+ return false;
+ }
}
diff --git a/src/OrderInvoiceSync/Hub.php b/src/OrderInvoiceSync/Hub.php
new file mode 100644
index 00000000..e4b5fc7b
--- /dev/null
+++ b/src/OrderInvoiceSync/Hub.php
@@ -0,0 +1,164 @@
+
+ * @copyright Since 2019 Shopping Feed
+ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ */
+
+namespace ShoppingfeedAddon\OrderInvoiceSync;
+
+if (!defined('_PS_VERSION_')) {
+ exit;
+}
+
+use Configuration;
+use Db;
+use DbQuery;
+use Shoppingfeed;
+
+class Hub
+{
+ protected $db;
+
+ protected $marketplaces = [];
+
+ protected static $instance = null;
+
+ protected function __construct()
+ {
+ $this->db = Db::getInstance();
+ $this->initMarketplaces();
+ }
+
+ public static function getInstance()
+ {
+ if (!self::$instance) {
+ self::$instance = new self();
+ }
+
+ return self::$instance;
+ }
+
+ public function getMarketplaces()
+ {
+ return $this->marketplaces;
+ }
+
+ /**
+ * @return Marketplace|null
+ */
+ public function find($id)
+ {
+ return isset($this->marketplaces[$id]) ? $this->marketplaces[$id] : null;
+ }
+
+ public function findByName($name)
+ {
+ return $this->find($this->buildId($name));
+ }
+
+ public function enable($id)
+ {
+ $marketplace = $this->find($id);
+
+ if (!$marketplace) {
+ return false;
+ }
+ if ($marketplace->isEnabled()) {
+ return true;
+ }
+
+ $this->marketplaces[$marketplace->getId()] = new Marketplace(
+ $marketplace->getId(),
+ $marketplace->getName(),
+ true
+ );
+
+ return $this->update();
+ }
+
+ public function disable($id)
+ {
+ $marketplace = $this->find($id);
+
+ if (!$marketplace) {
+ return false;
+ }
+ if (false === $marketplace->isEnabled()) {
+ return true;
+ }
+
+ $this->marketplaces[$marketplace->getId()] = new Marketplace(
+ $marketplace->getId(),
+ $marketplace->getName(),
+ false
+ );
+
+ return $this->update();
+ }
+
+ protected function initMarketplaces()
+ {
+ $result = $this->db->executeS(
+ (new DbQuery())
+ ->from('shoppingfeed_carrier')
+ ->groupBy('name_marketplace')
+ ->select('name_marketplace')
+ );
+ $configurations = json_decode(
+ Configuration::getGlobalValue(Shoppingfeed::ORDER_INVOICE_SYNC_MARKETPLACES),
+ true
+ );
+
+ if (empty($result)) {
+ return;
+ }
+
+ foreach ($result as $row) {
+ $id = $this->buildId($row['name_marketplace']);
+ $this->marketplaces[$id] = new Marketplace(
+ $id,
+ $row['name_marketplace'],
+ (empty($configurations[$id]['isEnabled']) ? false : $configurations[$id]['isEnabled'])
+ );
+ }
+ }
+
+ protected function buildId($name_marketplace)
+ {
+ return md5(
+ trim(
+ (string) $name_marketplace
+ )
+ );
+ }
+
+ protected function update()
+ {
+ $settings = [];
+
+ foreach ($this->marketplaces as $marketplace) {
+ $settings[$marketplace->getId()] = [
+ 'name' => $marketplace->getName(),
+ 'isEnabled' => $marketplace->isEnabled(),
+ ];
+ }
+
+ return Configuration::updateGlobalValue(
+ Shoppingfeed::ORDER_INVOICE_SYNC_MARKETPLACES,
+ json_encode($settings)
+ );
+ }
+}
diff --git a/src/OrderInvoiceSync/Marketplace.php b/src/OrderInvoiceSync/Marketplace.php
new file mode 100644
index 00000000..ee2ccee0
--- /dev/null
+++ b/src/OrderInvoiceSync/Marketplace.php
@@ -0,0 +1,53 @@
+
+ * @copyright Since 2019 Shopping Feed
+ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ */
+
+namespace ShoppingfeedAddon\OrderInvoiceSync;
+
+if (!defined('_PS_VERSION_')) {
+ exit;
+}
+
+class Marketplace
+{
+ protected $id = '';
+ protected $name = '';
+ protected $isEnabled = false;
+
+ public function __construct($id, $name, $isEnabled)
+ {
+ $this->id = (string) $id;
+ $this->name = (string) $name;
+ $this->isEnabled = (bool) $isEnabled;
+ }
+
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ public function isEnabled()
+ {
+ return $this->isEnabled;
+ }
+}
diff --git a/upgrade/install-2.0.0.php b/upgrade/install-2.0.0.php
new file mode 100644
index 00000000..2826c49a
--- /dev/null
+++ b/upgrade/install-2.0.0.php
@@ -0,0 +1,31 @@
+
+ * @copyright Since 2019 Shopping Feed
+ * @license https://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ */
+
+use ShoppingfeedClasslib\Install\ModuleInstaller;
+
+function upgrade_module_2_0_0($module)
+{
+ /**
+ * @var Shoppingfeed $module
+ */
+ $installer = new ModuleInstaller($module);
+ $installer->installObjectModel(ShoppingfeedToken::class);
+
+ return true;
+}
diff --git a/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro.tpl b/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro.tpl
index d48e6c56..3826d5f6 100644
--- a/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro.tpl
+++ b/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro.tpl
@@ -134,6 +134,48 @@
+ {elseif $input.type == 'shoppingfeed_marketplace_switch_list'}
+
{else}
{$smarty.block.parent}
{/if}
diff --git a/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro_178.tpl b/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro_178.tpl
index 917066a0..a8a820c1 100644
--- a/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro_178.tpl
+++ b/views/templates/admin/shoppingfeed_order_import_rules/order_status_syncro_178.tpl
@@ -134,6 +134,48 @@
+ {elseif $input.type == 'shoppingfeed_marketplace_switch_list'}
+
{else}
{$smarty.block.parent}
{/if}