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

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

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

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

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

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

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

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

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

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

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

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

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();