Складской учет для OpenCart / ocStore

При помощи СКИФ вы можете вести складской и финансовый учет, интегрированный с вашим интернет-магазином на OpenCart. СКИФ устанавливается на вашем сайте, поэтому вы имеете полный контроль над базой данных и возможность дорабатывать систему для своих потребностей.

Схема интеграции:

из СКИФ в OpenCart передаются производители, категории, товары и остатки (см. ниже о вариантах синхронизации изображений)

из OpenCart в СКИФ передаются интернет-заказы и данные о покупателях.


Как добавить складской учет к своему магазину на OpenCart:

Вы можете выполнить установку и настройку самостоятельно по инструкции ниже или заказать нам. Для настройки интеграции под Ваши требования, напишите на адрес biz@webnice.biz или запросите обратный звонок.
1 Скачайте СКИФ
Запросите дистрибутив СКИФ для установки на своем сайте. В ответ сразу придет ссылка на скачивание.

2 Установите СКИФ
Установите СКИФ на своём сайте по инструкции на отдельный домен, поддомен или в подпапку сайта с установленным OpenCart.
Важно! Установка СКИФ должна быть на том же аккаунте хостинга, а таблицы СКИФ в той же базе данных, что и OpenCart. Таблицы СКИФ имеют собственный префикс, поэтому никак не могут нарушить работу OpenCart.

3 Приобретите модуль синхронизации
Купите модуль в нашем каталоге плагинов. Сразу после оплаты на Ваш email придет архив с файлами модуля.

4 Задайте настройки синхронизации
Скопируйте из блока ниже код с настройками, добавьте его в конец файла wn_settings.php в корне установки СКИФ (это можно сделать через меню "Сервис-Редактор кода") и укажите нужные вам параметры синхронизации. НАСТРОЙКИ СИНХРОНИЗАЦИИ
$sync_opencart=array(
// сборка и версия OpenCart. Возможные значения:
// ocstore1 - для сборки ocStore 1.5 https://ocstore.com/downloads
// ocstore2 - для сборки ocStore 2.3.0.2.3 https://ocstore.com/downloads
// opencart2 - для opencart версии 2.3.0.2 http://opencart-russia.ru/
// opencart3 - для opencart версии 3.0.2.0 http://opencart-russia.ru/
// узнать версию можно в файле index.php в корне установки OpenCart
'version'=>'укажите',
// префикс базы данных интернет-магазина
'shop_prefix'=>'oc_',
// Записывать заказ в таблицу заказов wn_orders: Меню "Торговля-Заказы с сайта"
// без данных о товарах, эта таблица может использоваться для контроля обработки заказов из разных источников
// Укажите код типа заказа из массива $scif_order_fields['type'] в файле настроек wn_settings.php в корне папки установки СКИФ.
// Рекомендуется добавить отдельный, например 2-Интернет-магазин
// Если не задан, заказ не будет копироваться в эту таблицу
//'scif_order_type'=>0,
// код группы в справочнике контрагентов в СКИФ, в которой будут добавляться заказчики интернет-магазина
'scif_contr_group'=>1,
// код группы в справочнике статей движения в СКИФ для импорта статусов заказов из OpenCart. Если 0, то статусы импортироваться и обновляться не будут
'scif_finitem_group'=>6,
// код склада в СКИФ для обновления остатков в OpenCart. Если не задан или установлен в 0, остатки в OpenCart не обновляются
'scif_store'=>1,
// дополнительное условие выборки для обновления категорий товаров в Опенкарт.
// Например, для исключения групп с кодами 1,2 используйте 'AND s.id NOT IN (1,2)'
// Чтобы вообще не обновлять категории, используйте 'AND 0'
//'where_spr_noms_gr'=>'',
// дополнительное условие выборки для обновления производителей в OpenCart. Используйте 'AND 0' чтобы не обновлять производителей
//'where_spr_values'=>'',
// дополнительное условие выборки для обновления товаров в Опенкарт.
// Например, для исключения товаров из групп с кодами 1,2 используйте 'AND s.parent NOT IN (1,2)'
// Чтобы вообще не обновлять товары, используйте 'AND 0'
//'where_spr_noms'=>'',
// раскомментируйте, если нужно отключить обновление цен в OpenCart из СКИФ
//'noupdate_prices'=>true,
// дополнительное условие выборки заказов для импорта в СКИФ. Например, для отладки - загрузка только 10 последних заказов: 'OR 1 ORDER BY o.order_id DESC LIMIT 10';
// или не загружать "незавершенные заказы" - 'AND o.order_status_id>0'
//'where_order'=>'',
// код услуги в СКИФ для добавления строки "Доставка" (добавьте её в справочнике Номенклатура). Если 0 - стоимость услуги вносится в поле "Накладные расходы".
'scif_service_shipping'=>0,
// данные для создания документа в СКИФ (пользователь, организация, контрагент, склад, ответственный),
// если они отличаются от массива $wn_catalog_invoice, указанного в файле настроек wn_settings.php в корне сайта
// array('user_insert'=>1,'org'=>1,'contr'=>1,'store'=>1,'manager'=>1,'type'=>11)
// Пользователь user_insert - ID пользователя СКИФ, от имени которого будут добавляться записи. Для лучшего контроля рекомендуется завести в СКИФ отдельного пользователя
'invoice'=>$wn_catalog_invoice,
// Перечислите через запятую коды статусов заказа из OpenCart, при которых заказ в СКИФ нужно преобразовать в Продажу
// (будут уменьшены остатки товара на складе и увеличена задолженность покупателя)
'statuses_confirmed'=>array(), // например, array(1,3,4)
// Перечислите через запятую коды статусов заказа из OpenCart, при которых в СКИФ нужно внести оплату
'statuses_paid'=>array(), // например, array(5,6,7)
// Перечислите через запятую коды статусов заказа из OpenCart, при которых заказ считается отмененным
// (если в СКИФ была создана Продажа, она будет преобразована в Заказ покупателя, а остатки возвращены на склад)
'statuses_rejected'=>array(), // например, array(8)
// если СКИФ установлен не в подпапку основного сайта, а на отдельный поддомен, скопируйте в переменную https_server константу HTTPS_SERVER из config.php в корне установки OpenCart
'https_server'=>'',
// синхронизировать опции товаров: 0-нет, 1-да. Опции создаются в СКИФ как ОТДЕЛЬНЫЕ товары с названием "Товар // Опция Значение опции"
'use_options'=>0,
// синхронизации изображений: 0-не синхронизировать, 1-хранить и в СКИФ и в OpenCart, 2-хранить в OpenCart по symlink, 3-хранить только в СКИФ (подробнее https://www.webnice.biz/opencart/)
'sync_image'=>0,
// Если задано копирование изображений (sync_image=1), скопируйте в переменную dir_image константу DIR_IMAGE из config.php в корне установки OpenCart
'dir_image'=>'' // имеет вид '/var/www/..../image/' или /home/.../public_html/image/
);

// Модуль синхронизации будет доступен по адресу /scif/?act=sync_opencart и в меню Сервис
$scif_actions[600]=array('name'=>'OpenCart','desc'=>'Синхронизация с OpenCart','file'=>'sync_opencart','menu'=>7);
$scif_actions[601]=array('name'=>'Опция','desc'=>'Добавление опции товаров','file'=>'opencart_option');

// Функция обработки заказов в СКИФ в зависимости от статуса заказа в OpenCart. Настройте как Вам требуется.
// (при каких статусах мы преобразуем заказ в Продажу (списываем остатки), вносим оплату, расформировываем и т.д.)
function my_proccess_orders() {
global $row, $sync_opencart;
 if (!$row['scif_id']) { // еще нет заказа в СКИФ, создаем его
 doc_create();
  if (!$row['scif_id']) { return false; } // ошибка создания заказа
 } else { // проверим, не изменился ли состав заказа
 doc_change();
 }
 // Для заданного в параметре 'statuses_confirmed' перечня статусов преобразуем Заказ покупателя в Продажу
 // (списываем остатки со склада и увеличиваем задолженность покупателя)
 if (isset($sync_opencart['statuses_confirmed']) AND in_array($row['order_status_id'],$sync_opencart['statuses_confirmed'])) {
 doc_change_type(2);
 }
 // Для заданного в параметре 'statuses_paid' перечня статусов внесем оплату
 if (isset($sync_opencart['statuses_paid']) AND in_array($row['order_status_id'],$sync_opencart['statuses_paid'])) {
 // Оплату можно внести только на Продажу, поэтому, сначала проверим, что заказ уже преобразован в Продажу
 doc_change_type(2);
 // Внесем оплату
 doc_payment();
 // В функции также можно указать счет/кассу зачисления и статью движения: doc_payment($account=1, $finitem=0)
 // Например, в зависимости от способа оплаты в OpenCart, внесем оплату на расчетный счет (код 2) или в кассу (код 1)
 // doc_payment(($row['payment_code']=='sberbank'?2:1));
 }
 // Для заданного в параметре 'statuses_rejected' перечня статусов преобразуем Продажу в Заказ покупателя
 // (остатки будут возвращены на склад, а задолженность покупателя по данному заказу аннулирована)
 if (isset($sync_opencart['statuses_rejected']) AND in_array($row['order_status_id'],$sync_opencart['statuses_rejected'])) {
 doc_change_type(11);
 }
// обновим статус (статью движения) заказа в СКИФ
doc_update_status();
}

// Пользовательская обработка полей OpenCart, отсутствующих в СКИФ
// (в карточке товара в СКИФ мы будем видеть код соответствующего ему товара в базе OpenCart и возможность менять поля OpenCart, а также добавлять опции товара)
// Файл sync_spritem.php имеет открытый код, вы можете дополнять и видоизменять его под свои потребности.
$sprs[5]['userfields']=array(
'opencart'=>array('name'=>'OpenCart:','type'=>'virtual','my_edit_field'=>'opencart','my_process_field'=>'opencart')
);
function my_edit_field($key,$val,$cur_val='') {
global $db, $act, $t, $row, $sync_opencart;
$return='';
 switch ($val['my_edit_field']) {
 case 'opencart':
 $sync_func='my_edit_field';
 require WN_PATH_INCLUDES.'sync_opencart/sync_spritem.php';
 break;
 }
return $return;
}
function my_process_field($key,$val,$cur_val='') {
global $db, $act, $t, $sync_opencart;
$return='';
 switch ($val['my_process_field']) {
 case 'opencart':
 $sync_func='my_proccess_field';
 require WN_PATH_INCLUDES.'/sync_opencart/sync_spritem.php';
 break;
 }
return $return;
}
Импорт заказов
Вы можете настроить как сохранять и обрабатывать в СКИФ заказы из OpenCart.
По умолчанию, в СКИФ создается документ "Заказ покупателя". Этот документ является "счетом на оплату", при его создании остатки на складе не уменьшаются и задолженность клиента не увеличивается. Используйте этот вариант, если требуется, чтобы поступившие из интернета-магазина заказы сначала проверил/обработал ваш менеджер. Для формирования из заказа документа отгрузки, просто измените в нём "Вид документа" с "Заказ покупателя" на "Продажа". После этого товары спишутся со склада, а сумма долга покупателя увеличится на сумму документа. Вы также можете задать создание сразу документа "Продажа", для этого замените в файле настроек wn_settings.php в корне установки СКИФ значение "type" в массиве $wn_catalog_invoice с 11 на 2.

Рекомендуется настроить пользовательскую обработку заказов в функции my_proccess_orders(), код которой приведен выше. Для этого задайте в массиве настроек коды статусов заказов из OpenCart, при которых документ нужно преобразовать в "Продажу" (параметр "statuses_confirmed"), внести оплату (параметр "statuses_paid") или расформировать (параметр "statuses_rejected").

Если в массиве настроек $sync_opencart задать параметр scif_order_type, все заказы из OpenCart, кроме создания документа "Продажа/Заказ покупателя", будут дополнительно сохраняться в журнал "Торговля-Заказы с сайта" (без данных о товарах). Этот журнал может использоваться для контроля обработки заказов из разных источников.
Варианты синхронизации изображений
Вариант синхронизации изображений задаётся в переменной sync_image и может иметь следующие значения:
0 (не синхронизировать), 1 (хранить и в СКИФ и в OpenCart), 2 (хранить в OpenCart по symlink), 3 (хранить только в СКИФ). Подробнее об этих вариантах:

0 - Не синхронизировать.
Изображения не будут синхронизироваться. Вы будете вводить товары в СКИФ, а изображения нужно будет загружать в панели управления OpenCart. Этот вариант может быть удобен, если загрузкой изображений на сайте занимается другой человек.

1 - Хранить и в СКИФ и в OpenCart.
Изображения, загруженные в СКИФ, будут копироваться из папки СКИФ в папку OpenCart.
Минус этого способа в том, что изображения на сайте будут храниться в двух копиях, занимая лишнее место на диске.
Плюс в том, что данный вариант никак не вмешивается в работу OpenCart, поэтому подойдет, если изображения, загруженные ранее в OpenCart используются другими сервисами или плагинами.
Для использования данного способа скопируйте из скрипта config.php в корне установки OpenCart значение константы 'DIR_IMAGE' и вставьте его в параметр dir_image массива $sync_opencart.

2 - Хранить в OpenCart по symlink.
СКИФ будет загружать изображения в стандартную директорию загрузки изображений OpenCart, при этом изображения будут храниться в одной копии и будут доступны и в СКИФ и в OpenCart. Этот вариант является оптимальным для большинства случаев. Для его использования проделайте следующее:
2.1. Переместите папки /img/scif1/ и /img/scif1_orig/ со всем их содержимым из директории установки СКИФ в папку /image/catalog/ в директории установки OpenCart
2.2. Создайте на их месте две ссылки с именами scif1 и scif1_orig, ссылающиеся на соответствующие адреса перемещенных папок. (Ссылки можно создать в файловом менеджере из панели управления хостингом. Для панели ISPManager 5 меню Главное - Менеджер файлов, кнопка Создать, Тип: Ссылка)

3 - Хранить только в СКИФ.
OpenCart будет использовать изображения, загруженные в СКИФ. Изображения будут храниться только в папке СКИФ, что сэкономит место на вашем хостинге, но для данного способа требуется внести некоторые изменения в скрипты OpenCart. Эти изменения разрешают использовать другую папку для изображений вместо стандартной /images/catalog/ и использовать в качестве картинок файлы с расширением img. Для использования данного способа скачайте архив и следуйте инструкции в файле readme.txt из архива.

5 Проверьте настройки
Перейдите на страницу /scif/?act=sync_opencart (или через меню Сервис-OpenCart) чтобы проверить настройки. Если в OpenCart ранее были внесены товары, вы сможете выполнить импорт справочников и остатков.

6 Выполните импорт (если необходимо)
Если в вашем интернет-магазине есть внесенные ранее товары и производители, вы можете импортировать их в СКИФ. Для этого на странице /scif/?act=sync_opencart нажмите ссылку "Импорт справочников из OpenCart". После импорта данных, если в настройках вами была задана синхронизация изображений, вам будет предложено скопировать все картинки.
ИМПОРТ СПРАВОЧНИКОВ ИЗ OPENCART
1. Обратите внимание, что в СКИФ по умолчанию в справочниках названия групп, элементов и SEO URL (ЧПУ) должны быть уникальными. В справочнике товаров, кроме того, уникальным должно быть поле "Штрихкод" (barcode). Для успешного импорта, обеспечьте уникальность этих полей в OpenCart или уберите условие уникальности в СКИФ. Чтобы убрать условие уникальности, в phpmyadmin измените тип индексов `name` и `parent_name` с UNIQUE на INDEX.

2. В СКИФ по умолчанию в справочнике номенклатуры разрешено только два уровня вложенности. Если структура ваших категорий в OpenCart имеет больше уровней, добавьте в конец файла настроек wn_settings.php в корне установки СКИФ следующую строку, она разрешит неограниченный уровень вложенности групп для справочника товаров:
$sprs[5]['multilevel']=true;

7 Автоматизируйте синхронизацию (по желанию)
Проверьте работу синхронизации, нажав кнопку "Выполнить синхронизацию" внизу страницы. Если всё в порядке (не выводится никаких ошибок, товары и остатки из СКИФ перенеслись в OpenCart, а заказы из OpenCart в СКИФ), вы можете задать выполнение синхронизации в автоматическом режиме по расписанию через планировщик CRON. Для выполнение через планировщик добавьте вызов скрипта /cron/sync.php с нужным вам расписанием в CRON на своем хостинге.
Проверить, что синхронизация по планировщику выполняется корректно, можно на странице /scif/?act=sync_opencart. Внизу после кнопки "Выполнить синхронизацию" будет выводиться время последней успешной синхронизации.


Это всё! Теперь Ваш складской учет и интернет-магазин автоматически синхронизируются!
Остались вопросы или нужна доработка синхронизации под Ваши потребности? Напишите нам biz@webnice.biz


P.S. Персональные настройки и доработки
Важным преимуществом нахождения базы и скриптов системы учета на вашем собственном сайте является то, что вы можете настраивать и дорабатывать систему под свои индивидуальные потребности. Вы можете делать это самостоятельно или заказывать нам. Ниже мы приводим примеры кода расширения функционала интеграции. РАСШИРЕНИЕ ФУНКЦИОНАЛА
Вывод в СКИФ полей из OpenCart и поиск по ним.
Например, сделаем возможность вывода в списке номенклатуры СКИФ поля "Модель" и поиска по нему. Обратите внимание, что в таблице товаров СКИФ этого поля нет. В коде ниже мы приводим пример подключения к таблице товаров СКИФ таблицы товаров OpenCart. Добавьте в файл настроек wn_settings.php в корне установки СКИФ следующий код (это можно сделать через меню "Сервис-Редактор кода"):
// собственный вывод справочника
$sprs[5]['my_sprlist']='join';
function my_sprlist($type,$row=array()) {
global $t, $prices, $stores, $m, $head, $count_prices, $count_stores, $s, $p, $sync_opencart;
 switch ($t) {
 case 5: // номенклатура
  switch ($type) {
  case 'head':
  $count_prices=count($prices);
  $count_stores=count($stores);
   if ($m==1) { // форма множественного подбора (в документ)
   $return='<th>Уп.</th><th>Модель</th><th>Статус</th><th data-sorter="false">Кол-во</th><th data-sorter="false">Цена</th><th>'.$stores[$s]['name'].'</th>';
   } else {  // форма списка
   $head=''; // здесь перезаписываем head с Код и Наименование для добавления rowspan
   $return='<th rowspan="2">Код</th><th rowspan="2">Наименование</th><th rowspan="2">Модель</th><th rowspan="2">Статус</th>
   <th colspan="'.$count_prices.'" align="center">Цены</th>
   <th colspan="'.$count_stores.'" align="center">Остатки</th>
   </tr>
   <tr>';
    // цены
    foreach ($prices AS $key=>$val) {
    $return.='<th align="right">'.$val['name'].'</th>';
    }
    // остатки на складах
    foreach ($stores AS $key=>$val) {
    $return.='<th align="right">'.$val['name'].'</th>';
    }
   }
  break;
  case 'sql':
  $return=', s.packing1 AS packing, o.model, o.status';
   foreach ($prices AS $key=>$val) {
   $return.=', s.price'.$key;
   }
   foreach ($stores AS $key=>$val) {
   $return.=', s.store'.$key;
   }
  break;
  case 'join':
  $return='LEFT JOIN '.$sync_opencart['shop_prefix'].'product o ON s.shop_id=o.product_id';
  break;
  case 'row':
   if ($m==1) { // форма множественного подбора (в документ)
   $return='<td>'.$row['packing'].'</td>
   <td>'.($row['model']?$row['model']:'&nbsp;').'</td>
   <td class="status-'.($row['status']?'yes">+':'no">-').'</td>
   <td><input type="number" id="quant'.$row['id'].'" value="1" class="numeric"></td>
   <td><input type="number" id="price'.$row['id'].'" value="'.(float)$row['price'.$p].'" class="numeric"></td>
   <td align="right">'.quant($row['store'.$s]).'</td>';
   } else {
   $return='<td>'.($row['model']?$row['model']:'&nbsp;').'</td><td class="status-'.($row['status']?'yes">+':'no">-').'</td>';
    // цены
    foreach ($prices AS $key=>$val) {
    $return.='<td align="right">'.$row['price'.$key].'</td>';
    }
    // остатки на складах
    foreach ($stores AS $key=>$val) {
    $return.='<td align="right">'.quant($row['store'.$key]).'</td>';
    }
   }
  break;
  }
 break;
 }
return $return;
}

// Поиск по полю "Модель" в справочнике номенклатуры
$sprs[5]['filter_fields']['model']=array('name'=>'Модель','func'=>true);
$sprs[5]['filter_fields']['name_model']=array('name'=>'Название-Модель','func'=>true);
function my_filter_fields($t,$field,$filter) {
 switch ($t) {
 case 5: // Номенклатура
  switch ($field) {
  case 'model':
  return 'o.model LIKE "%'.$filter.'%"';
  break;
  case 'name_model':
  return 'CONCAT(s.name," ",o.model) LIKE "%'.$filter.'%"';
  break;
  }
 }
}
После этого в справочнике номенклатуры в СКИФ появятся поля "Модель" и "Статус" из OpenCart, а в списке полей фильтров появятся варианты "Модель" и "Название-Модель" (для сводного поиска как по названию так и по модели).

Стили оформления в зависимости от данных.
В СКИФ можно задать разное оформление в зависимости от данных. В примере ниже для справочника номенклатуры задается разный цвет в зависимости от "Статуса" товара в OpenCart. А для журнала документов разный фон колонки "Статья движения", в зависимости от статуса заказа в OpenCart.
// собственные стили
function scif_meta() {
global $act, $t, $meta;
 // стиль колонок в справочнике номенклатуры
 if ($act=='sprlist' AND $t==5) {
 $meta.='<style type="text/css">
 td.status-yes { text-align:center; color: green; }
 td.status-no  { text-align:center; color:red; }
 </style>';
 } elseif ($act=='doclist') {
 $meta.='<style type="text/css">
 tr.finitem45 td:nth-child(15) { background-color:#bf0000; color:#ffffff; }
 tr.finitem47 td:nth-child(15) { background-color:#ffffff; color:#00007f; }
 </style>';
 }
}

Работа с листом ожидания OpenCart (плагин WaitList) из СКИФ.
После сохранения документов "Оприходование" или "Покупка" проверим и выведем сообщение, если товары из листа ожидания появились в наличии. Можно выполнить email-рассылку клиентам по листу ожидания прямо из СКИФ со страницы ?act=opencart_waitlist.
$scif_actions[650]=array('name'=>'OpenCart Waitlist','desc'=>'Рассылка уведомлений по листу ожидания OpenCart','file'=>'opencart_waitlist','menu'=>7);
function scif_after_act() {
global $db, $act, $row_new, $sync_opencart;
 if ($act=='docitem' AND !empty($_POST['submit']) AND in_array($row_new['type'],array(1,3))) {
 $waitlist=$db->sql_fetch_row($db->sql_query('SELECT COUNT(DISTINCT w.product_id)
 FROM `'.$sync_opencart['shop_prefix'].'waitlist` w
 JOIN `'.SCIF_PREFIX.'spr_noms` n ON w.product_id=n.shop_id
 WHERE n.store'.$sync_opencart['scif_store'].'>0'));
  if ($waitlist AND $waitlist[0]) {
  echo '<div class="panel_top"><span style="color:red">Внимание!</span> Есть <b>'.$waitlist[0].'</b> товара(ов) в наличии из <a href="?act=opencart_waitlist" target="_blank">Листа ожидания</a></div>';
  }
 }
}

Большие примеров кода смотрите в FAQ.


P.P.S. Дистрибутив СКИФ включает также собственный интернет-магазин, который напрямую интегрирован с системой учета. Если вы только выбираете движок для своего интернет-магазина, просто установите СКИФ и у вас будет складской учет, сайт и интернет-магазин. Подробнее.
Вы также можете при помощи СКИФ организовать работу второго интернет-магазина, отдельного от OpenCart, например, для акцента на других товарных категориях. Данные всех магазинов будут аккумулированы в единой системе учета.
Закажите интеграцию складского учета с OpenCart из формы заказа или отправив письмо на адрес biz@webnice.biz