Бизнес в области промбезопасности, сертификации продукции. Поддержка корпоративного портала ( bitrix ). Интеграция телефонии OkTell.

Внедрение SugarCRM. Импорт cобытий, студентов из excel файлов различного формата.

Строительная компания. Доработка TerraSoft CRM. Автоматизация подбора объектов, расчета стоимости по БТИ, согласования договоров. Экспорт платежей в Navision

Управление коммерческой недвижимостью в Санкт-Петербурге. Интерактивные карты ТЦ "Французский бульвар", "5 Озер", "СитиМолл", "Лондон-Молл". frbulvar.ru/magaziny trk-5ozer.ru/magaziny

Доработка корпоративного портала на bitrix24 с функционалом CRM, ERP. Оптимизация базы данных, бизнес-процессов, документооборота, разработка отчетов ( финансовые итоги, прогнозы, расчет зарплаты )

Производство систем сигнализации и контроля доступа. Доработка Magento магазина

Поставка запчастей. Загрузка фактических продаж и планов в vTigerCRM из BI Pentaho и 1С8. Вывод динамики продаж по менеджерам.

Финансовые услуги. Внедрение SugarCRM, доработка ролевой системы доступа

Поставка ПО. Разработка новой версии магазина ( bitrix ). Интеграция с Google Analytics, Assist, 1С. Хронологический импорт цен. Учет лицензий.

Разработка сайта ( simplaCms ), интеграция со специализированной конфигурацией , настройка учета в разрезе характеристик ( размеры, пробы ) и поставщиков, оптимизация БД

Компания по сбору мусора. Отчеты для контроля оперативной работы менеджеров, операторов, объема продаж, долгов клиентов, расчета зарплаты, бонусов. Обмен данными между корпоративной CRM системой ( Bitrix24 ) и 1С7, 1C8. Взаимодействие с телефонией ( Asterisk )

Внедрение vTiger, интеграция с 1С, получение данных по ИНН из федеральной базы.

namespace iteamo\framework;
require_once(__DIR__ . '/core/app.php');
require_once(__DIR__ . '/libs/traits/withSingleton.php');
/**
 *
 */
class app extends core\app{
public function getLib($key = '', $arParams = [], $arOptions = ['checkParent' => true]) {
  $objLib = parent::getLib($key, $arParams);
  //
  if ($arOptions['checkParent'] && empty($objLib)) {
    if ($this->arClass['name'] != __class__) {
      $parentClass = $this->arClass['parent'];
      $objLib = $parentClass::get()->getLib($key, $arParams, $arOptions);
    }
  }
  //
  return $objLib;
}
//
public function getView($key = '', $arData = [], $arOptions = ['checkParent' => false]) {
  $strView = parent::getView($key, $arData);
  //
  if ($arOptions['checkParent'] && is_null($strView)) {
    if ($this->arClass['name'] != __class__) {
        $parentClass = $this->arClass['parent'];
        $strView = $parentClass::get()->getView($key, $arData, $arOptions);
    }
  }
  //
  return $strView;
}
static public function parsePaths($arItem = []) {
  $arItemResult = [];
  foreach($arItem as $key => $value) {
    if (stripos('prefix' . $key, '[')) {
      $fullPath = '[' . substr_replace($key, '][', stripos($key, '['), 1);
      eval("\$arItemResult" . $fullPath . " = \$value;");
    } else $arItemResult[$key] = $value;
  }
  return $arItemResult;
}
request = {
  getDataFromUrl: function(url) {
    var arData = {};
    if(typeof url != 'undefined' && url.indexOf('?')!== -1) {
      var urlSplit = url.split('?');
      var queryString = urlSplit[1];
      var queryParameters = queryString.split('&');
      for(var index=0; index < queryParameters.length; index++) {
      	var queryParam = queryParameters[index];
      	var queryParamComponents = queryParam.split('=');
      	arData[queryParamComponents[0]] = queryParamComponents[1];
      }
    }
    return arData;
  },
  send: function(path, arData, arParams) {
    if (empty(arData)) arParams = {};
    if (empty(arParams)) arParams = {};
    //
    arParamsDefault = {
      dataType: 'json',
      type: 'GET',
    };
    arParams = jQuery.extend(false, {}, arParamsDefault, arParams);
    //
    var aDeferred = jQuery.Deferred();
		var success = function(data, status, jqXHR) {
      aDeferred.resolve(data);
		}
		var error = function(jqXHR, textStatus, errorThrown){
      aDeferred.reject(textStatus, errorThrown);
		}
    //
    var arDataFromUrl = this.getDataFromUrl(path);
    arData = jQuery.extend(false, {}, arData, arDataFromUrl);
    arParams.data = arData;
    arParams.url = path;
    arParams.timeout = 30000;
		arParams.success = success;
		arParams.error = error;
    //
		jQuery.ajax(arParams);
    //
    return aDeferred.promise();
  },
};
  
templater = {
  parse : function(strTemplate, arData) {
    var strParsedTemplate =
      strTemplate.replace(/\{([a-zA-Z0-9 ]*)\}/g, function(m, key) {
        result = arData[key.trim()];
        return result;
    });
    return strParsedTemplate;
  }
};
init: function (context) {
  window.$this = (context != undefined)?context:this;
  $this.cancelDefaultModulePolling();
  $this.parent.init($this);
},
isPageToInitPhoneLinks: function() {
  var result = false;
  var url = window.location.toString();
  if (/(Leads|Contacts|Accounts|PBXManager)/i.test(url)) {
    result = true;
  }
  return result;
},
isPageToInitCallListeningRecords: function() {
  return $this.isPageToInitPhoneLinks();
},
startCallNotify: function(arResult) {
  var params = {'type' : 'error', 'text' :  app.vtranslate('JS_PBX_OUTGOING_FAILURE')};
  if(arResult.status){
    params = {'type' : 'info', 'text' :  app.vtranslate('JS_PBX_OUTGOING_SUCCESS')};
  } else {
    if(!empty(arResult.arErrors)){
      params.text += ': ' + implode(';', arResult.arErrors);
    }
  }
  notification.show(params);
},
namespace iteamo\framework\libs\traits;
use \iteamo\framework\app;
trait withSingleton {
static public function get($arParams = []) {
  static $objInstances = [];
  $class = get_called_class();
  if (empty($objInstances[$class])) {
    $objInstances[$class] = new $class($arParams);
  }
  return $objInstances[$class];
}
}
public function update($arItem = []) {
  $count = false;
  $arItem = $this->prepareData($arItem);
  $arItems = self::filter($this->arItems, $this->arFilters);
  foreach($arItems as $key => $arItem) {
    $this->arItems[$key] = arrays::mergeUpdate($this->arItems[$key], $arItem);
  }
  $count = count($arItems);
  $this->reset();
  //
  return $count;
}


class entity {
use \iteamo\framework\libs\traits\withEntityInterface{
  \iteamo\framework\libs\traits\withEntityInterface::getItem as traitGetItem;
  \iteamo\framework\libs\traits\withEntityInterface::prepareData as traitPrepareData;
  \iteamo\framework\libs\traits\withEntityInterface::filter as traitFilter;
}
public $arCorrespondence = [];
public $table = '';
public $moduleId = 0;
//
private $dbQueryDriver = null;
/**
 *
 */
public function __construct() {
  include_once 'include/Webservices/Utils.php';
  $this->dbQueryDriver = \iteamo\framework\init::getLib('database/queryDrivers/sql');
}
/**
 *
 */
function filter($arFilters = array()) {
  if (!empty($arFilters['anyPhone'])) {
    $objDb = \PearDatabase::getInstance();