HTTP, Ajax, JSON: Один год Pet-проекту на 1С

21.02.24

Интеграция - WEB-интеграция

Как 1С может стать площадкой для хобби и что из этого может получиться.

Пет-проекты - вещь в сообществе 1С непопулярная. Нет в этом ничего удивительного, нет, собственно, ничего и предосудительного. Даже небольшие проекты, благодаря этому, получают одобрение - я считаю, это правильно

Например, бот математического тренажера //infostart.ru/1c/articles/1946557/

У меня тоже есть такой проект. За год он немного разросся, лежит на GitHub, а из под его крыла вышли довольно тепло принятые VKEnterprise и TelegramEnterprise (а сейчас, в общем то, и используются как основа этого проекта). Короче, грех не рассказать. К тому же, тут (или в связанных статьях) я постараюсь поделиться конкретными практиками, которым я научился в процессе, дать ответы на вопросы, на которые я в свое время ответы не нашел. Особенно касательно http-сервисов.

 

Сразу стоит оговориться...

 

Есть ли вообще такие направления для индивидуальных проектов, где 1С может себя показать? Ответ на данный вопрос, на самом деле, совсем не сложен. 1С довольно сильно ограничен в своих возможностях, но из этого и выходит небольшое количество вариантов для его использования. Конечно, сразу отлетают desktop и mobile приложения для конечных потребителей - 1С на текущий момент создать конечный продукт не позволяет, не позволяет и включить лицензию в стоимость продукта. В каком-то смысле таким "Десктопом" занимается сама 1С, франчайз, а еще 1С:Совместимо и маркетплейс Инфостарта. Но я тут скорее имею в виду варез в классическом понимании. Отлетают инструменты, игры, графические редакторы, etc. А что же остается? Для себя я разделил подходящие варианты на 2 категории:

Первая - персональные системы автоматизации. Это не самодостаточный софт в целом, скорее инструмент, который позволяет присосаться к уже существующей большой системе и качать из нее гешефт - автоматизировать рутину по работе с данными путем использования API или другими способами интеграции. Это может быть трэйдинг-бот на бирже, CMS для социальной сети, админ. панели, накопители, сборщики статистики и данных из отдельных источников, разного рода спамилкий, фермы ботов и прочая мерзость. 1С реально хорош в этом. Регламентные задания, http-сервисы и запросы, автоматический формирующийся интерфейс, освобождающий от необходимости клепать формы на новые таблицы в СУБД, СКД и в целом RAD подход, будто бы для этого и были созданы. 

Вторая категория - бэк для Web или мобильного приложения. Тут все, конечно, не так радужно. Во-первых, этот бэк будет сравнительно не очень шустрый и будет требовать сравнительно больше ресурсов, чем специально заточенные под это технологии. Во-вторых, упоротое лицензирование требует лицензий на пиковое значение одновременных подключений, что, конечно, абсурд. Если кратко: первое частично лечится максимальной оптимизацией и разгрузкой 1С на другие службы там, где это возможно. Второе частично лечится околонулевым временем жизни соединения и поставкой СЕРВЕР-МИНИ на 5 подключений. Жить можно. Однако, дабы это не выглядело как история про мышей и кактус, нужно отметить и очевидные плюсы: все тот же RAD и работа с интерфейсом, база которого создается автоматически, но, при необходимости, позволяет создать себе очень гибкую в настройке и допиливании панель администрирования, автоматическое управление переиспользованием соединений, абсолютно элементарный и очевидный в настройке маппинг (как по адресам, так и по видам запросов), максимально возможная простота работы с данными в базе. Работа по верх IIS/Apache может не всем нравится, но позволяет не городить велосипедов, а настраивается (во всяком случае IIS) так же очень просто.

В любом случае, чтобы вы не выбрали, пет-проект - это буквально опыт. Он здесь первичен, и даже конечный результат не так важен. В данном случае, это опыт работы с платформой 1С.

 

Так что там за проект?

 

Мой проект называется Two-Digit Athenaeum. Состоит он из трех частей: бота, сайта и CMSки. Но это технически. Для конечного пользователя это такое сообщество-библиотека, где есть группа в ВК, канал в Telegram и сайт, а чат-бот раздает книжки.

Начать стоит с соц. сетей:

 

Aioniotis CMS

 

Есть группа в ВК и канал в Телеграм (наполнение одинаковое). В них есть всякий околокнижный контент - мягкое привлечение внимания к онлайн библиотеке. Цитаты там, статьи, реклама книг. Уже была моя статья про ImageMagick, я там немного показывал. Прикинув способности моей силы воли на каждодневное ведение сообщества, я решил на нее не полагаться, а использовать SMM платформу или некую CMS, вроде SMMPlanner. Подобные сервисы как правило онлайн, особо широким функционалом не отличаются, зато все, поголовно, на ежемесячной подписке. 

А самое главное - ни о каком накоплении базы контента речи не идет. Сервис как бы сохраняет историю публикаций внутри себя, но экспортировать не дает. 

 

 

Переиспользовать старые материалы, заново собирая их из файлов на облаке как в первый раз, показалось вариантом неприемлемым, вот и появилась Aioniotis CMS. В начале она правда не была чисто CMS, но об этом потом. Сейчас она выглядит вот так: 

 

 

Но мишура это, конечно, не главное. В основе своей все равно лежит простой как палка принцип очереди:

 

1. Добавляется новый пост, попадает в конец очереди

2. В нужное время срабатывает регламент и публикует пост из начала очереди (т.е. самый старый) 

3. Если неопубликованные посты кончаются, то берется самый старый ранее опубликованный пост.

4. В итоге, если перестать добавлять новые посты, то 1Ска будет крутить по кругу те, что есть. 

 

Есть еще много чего, но основа такая. Под  капотом у этой конфы упомянутые в начале VKEnterprise и TelegramEnterprise, изначально внутри нее и создававшиеся. Есть функционал создания простых постов картинка+текст, всяких интересных комплексных постов с обработкой изображений, вроде этого:

 

 

 

Есть механизм пересылки сообщений. Так, например, Телеграм не позволяет загружать через API файлы размером >100 МБ. Но никто не мешает загружать их обычным способом на какой-нибудь приватный канал, а потом пересылать по номеру сообщения

 

Функция ПереслатьСообщение(Знач Сообщество, Знач IDОригинала) Экспорт
    
    РеквизитыСообщества = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(Сообщество
       , "ТГ_token,ТГ_chat_id,ТГ_КаналАрхив");
       
    IDОригинала         = МетодыРаботыHttp.ЧислоВСтроку(IDОригинала);
    Токен               = РеквизитыСообщества.ТГ_token;
    КудаID              = РеквизитыСообщества.ТГ_chat_id;
    ОткудаID            = РеквизитыСообщества.ТГ_КаналАрхив;

    _Параметры = Новый Структура;
    _Параметры.Вставить("chat_id"       , КудаID);
    _Параметры.Вставить("from_chat_id"  , ОткудаID);
    _Параметры.Вставить("message_id"    , IDОригинала);
    
    Ответ = МетодыРаботыHttp.Get("api.telegram.org/bot" + Токен + "/forwardMessage", _Параметры);
    
    Возврат Ответ;

КонецФункции

//Метод формирования картинки для лекции
Функция СформироватьЛекцию(Знач Аудио) Экспорт
    
    ФайлСпр         = Справочники.Файлы.Лекция;
    ФотоЛекции      = ИнструментарийВызовСервера.ЗначениеРеквизитаОбъекта(ФайлСпр, "Файл").Получить();
    ФотоВФ          = ПолучитьИмяВременногоФайла("png");
    ФотоЛекции.Записать(ФотоВФ);
    
    РеквизитыЛекции = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(Аудио
        , "Источник,Наименование,ОтступАвтора");    
        
    НачальныйОтступ = 123;
    ОтступАвтора    = Строка(НачальныйОтступ + РеквизитыЛекции.ОтступАвтора);    
    Источник        = Строка(РеквизитыЛекции.Источник);
    Наименование    = РеквизитыЛекции.Наименование;
    
    Текст = СтрРазделить(Наименование, " ", Ложь);
    НаименованиеСтрокой     = "";
    ЧастьТекста             = "";
    Н                       = 0;
    ОграничениеПоСимволам   = 19;
    
    Для Н = 0 По Текст.ВГраница() - 1 Цикл
        
        НаименованиеСтрокой = НаименованиеСтрокой + Текст[Н] + " ";
        ЧастьТекста         = ЧастьТекста  + Текст[Н] + " ";
        
        Если СтрДлина(ЧастьТекста + Текст[Н + 1]) > ОграничениеПоСимволам Тогда
            НаименованиеСтрокой = НаименованиеСтрокой + "\n";
            ЧастьТекста  = "";
        КонецЕсли;
        
    КонецЦикла;        
    
    НаименованиеСтрокой = НаименованиеСтрокой + Текст[Текст.ВГраница()];
    
    ИмяСкрипта   = ПолучитьИмяВременногоФайла(".ps1");
    ТекстСкрипта = Новый ТекстовыйДокумент();
    
    ТекстСкрипта.УстановитьТекст(
    "magick "
    + ФотоВФ
    + " -pointsize 96 -fill white -font Sylfaen -gravity West -annotate +650-20 '"
    + НаименованиеСтрокой
    + "' "
    + ФотоВФ
    + Символы.ПС
    + "magick "
    + ФотоВФ
    + " -pointsize 40 -fill silver -font Tahoma -gravity West -annotate +650+"
    + ОтступАвтора
    +" '"
    + Источник
    + "' "
    + ФотоВФ    
    );
    
    ТекстСкрипта.Записать(ИмяСкрипта, КодировкаТекста.UTF8);
    
    КодВозврата = 0;
    ЗапуститьПриложение("powershell -file " + ИмяСкрипта, , Истина, КодВозврата);
    
    КартинкаДвоичные = Новый ДвоичныеДанные(ФотоВФ);
    
    УдалитьФайлы(ФотоВФ);
    УдалитьФайлы(ИмяСкрипта);
    Возврат КартинкаДвоичные;
    
КонецФункции


Вообще, конечно, полет фантазии возможности 1С допускают невероятный и все SMM-системы выглядят после нее как дети. В частности, это касается возможности делать периодический контент или контент, основанный на случайных значениях. Например, раз в 10 дней у меня в группе появляется рекламный пост, который создается на основе случайной книги из каталога на основе генератора случайных чисел. Т.е. выбираются данные случайной книги из базы, а на основе её данных ImageMagick клеит баннер

 
 Код создания рекламы книги
 

 

И много всяких других штук. Дальше я еще кое что покажу, но пока хочу напомнить, что:

Эта конфа есть на GitHub как EDT проект. Там же можно узнать больше про реализованный функционал

https://github.com/Bayselonarrend/2athenaeum

Ну а теперь про другие штуки:

 
 Очередь постов

 Левая часть - подготовленные посты не в очереди, правая - очередь. Посты разбиты на уровни, от которых зависит время публикации. У меня это вечер (I), обед (II) и ночь (III)

 

 
 Пост

Обычный пост выглядит вот так:

 

 

Текст формируется по шаблону из автора, произведения и самой цитаты (просто программно прописаны, в зависимости от типа справочника содержания). Для картинки я сохраняю путь, но вообще она хранится в ХранилищеЗначения как двоичные данные, чтобы наверняка не потерять. Текст на картинку наносится автоматический при помощи ImageMagick, ссылка на статью была выше

 
 Аналитика

 Каждое утро запускается регламент, запрашивающий статистику у VK API. Эта статистика отлично ложится на возможности СКД, позволяя анализировать состояние сообщества.

 

 
 Данные о сообществе

 Если вас волнует вопрос, какое количество информации требуется для использования VK и Telegram API - то вот они, слева направо:


 

 

Athenaeum.digital

 

Теперь перейдем к сайту. В самом начале, говоря про 1С как бэк, речь шла про максимальный перенос функционала куда угодно из 1С. Обусловлено это несколькими факторами:

1. 1С это, очевидно, не самый высокопроизводительный низкоуровневый язык и даже не платформа, заточенная под веб.

2. 1С долго (относительно) стартует сеанс, а когда стартует их много, то все это (пусть и только юридически) требует лицензий.

При таком раскладе Server-side рендер (когда бэк формирует html целиком и просто его отдает, не используя обработку на стороне клиента) становится еще более пещерным и непотребным, чем он существует в наше время для остальных платформ.

 

Вопрос со структурой сайта я решил так:

1. Сайт расположен на neocities. Это сервис для публикации статических веб-сайтов, как любой бесплатный хостинг. Закидываешь файлики и все. За 5$ в месяц он дает кучу места и позволяет установить свое доменное имя. Там, в первую очередь, хранятся html макеты страниц. Это вполне может быть заменено на IIS/Apache/nginx без доп. обработчиков вообще, но я хотел уменьшить нагрузку не только на 1С, но и на железо сервера. Плюс сайт не падает при проблемах с сервером, а наоборот - внизу слева есть зеленый значек, который становится красным, если мой сервер недоступен - показывает, что бот работать сейчас не будет.

 

 

2. Все данные, которые не зависят от пользователя, тоже хранятся там. Например, у меня есть 100 книг и у каждой должна быть своя страница. На neocities лежит book.html - универсальный единый макет для всех книг. Каждой книге присвоен код, а при переходе по book?id=A123B, выполняется JS код, понимающий, что в макет book.html, в данном случае, нужно вставить данные о книге под кодом A123B. За этой информацией он лезет в JSON файлы, хранящиеся в определенной структуре. Хранятся они на, собственно, neocities в отдельных папках. А вот попадают они туда как раз из 1С. Когда в 1С добавляется новая книга, то там при помощи СоздатьКаталог() и ЗаписьJSON формируются новая папка и JSON-файл, которые заливаются на neocities (подключается по webdav как сетевой диск) в определенном, понятном js скрипту, формате. Вот и все. Если нужно изменить информацию, файл перезаписывается. 1С его выгружает один раз (+ режет при помощи ImageMagick обложку на несколько копий разного размера для оптимизации под разные экраны) и обращений к серверу никаких никогда не идет.

 

Процедура ОбновитьСтраницыКниг(СписокКниг) Экспорт 
    
    КаталогСайта = ИнструментарийВызовСервера.ЗначениеРеквизитаОбъекта(Справочники.Сайты.Athenaeum, "ПапкаДанныхСайта");
    
    Для Каждого Книга Из СписокКниг Цикл
        
        ПоляКниги  = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(Книга
            , "Наименование,Автор,Описание,Код,НаСайте");
   
        ПоляАвтора = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(ПоляКниги.Автор
            , "Имя,Фамилия,Код");
        
        Если Не ПоляКниги.НаСайте Тогда
            Продолжить;    
        КонецЕсли;
        
        СтруктураКниги = Новый Структура;
        СтруктураКниги.Вставить("title"         , ПоляКниги.Наименование);
        СтруктураКниги.Вставить("author"        , ПоляАвтора.Имя + " " + ПоляАвтора.Фамилия);
        СтруктураКниги.Вставить("description"   , СтрЗаменить(ПоляКниги.Описание, Символы.ПС, "<br/>"));
        СтруктураКниги.Вставить("id"            , ПоляКниги.Код);
        СтруктураКниги.Вставить("author_id"     , ПоляАвтора.Код);
        
        ПутьККниге       = КаталогСайта + "\books\" + ПоляКниги.Код;
        КаталогКниги     = Новый Файл(ПутьККниге);
        
        Если Не КаталогКниги.Существует() Тогда
            СоздатьКаталог(ПутьККниге);
        КонецЕсли;
        
        ДД = Книга.КартинкаДвоичные.Получить();
        ДД.Записать(КаталогКниги.ПолноеИмя + "\0.webp");
        
        МетодыОбработкиИзображений.СоздатьКарточки(КаталогКниги.ПолноеИмя + "\0.webp");
        ИнструментарийВызовСервера.JSONВФайл(СтруктураКниги, ПутьККниге + "\data.json"); 

    КонецЦикла;
    
КонецПроцедуры

 

 

Код JS, который разбирает эту информацию и пихает в нужные поля на странице:

 

function makeBook(){
  
  let booktitle       = document.querySelectorAll('.book-title');  
  let bookauthor      = document.querySelectorAll('.book-author');
  let bookauthorlink  = document.querySelectorAll('.book-authorlink');
  let bookdescription = document.querySelectorAll('.book-description');
  let body            = document.querySelector('body');
  let meta_description  = document.querySelector('meta[name="description"]');
  

    
  let searchParams = new URLSearchParams(window.location.search);
  let id    = searchParams.get('id');
  let uuid  = getCookie('uuid');


  getDataByUrl('/static/books/' + id + '/data.json', true).then(function(response)
  {
    let code                  = document.getElementById('code');
    document.title            = response.title + ' — Two-Digit Athenaeum';
    meta_description.content  = 'Читайте произведение ' + response.title + ', ' + response.author + ' на Two-Digit Athenaeum абсолютно бесплатно через VK или Telegram!'
    
    booktitle.forEach(function(element) {
      element.innerHTML = response.title;
    });
    
     bookauthor.forEach(function(element) {
       if (element.id != 'authorlink')
       {
        element.textContent = response.author;
       }
    }); 
    
    bookauthorlink.forEach(function(element) {
      element.href      = '/author?id=' + response.author_id;
      element.innerHTML = response.author;
    });
    

            
    bookdescription.forEach(function(element) {
      element.innerHTML = response.description;
    }); 
        
    code.innerHTML = String(id) + code.innerHTML;    

    body.style.setProperty('--cover', 'url(/static/books/' + id + '/medium.webp) no-repeat no-repeat center');
        
     
 });

 

В самом начале получаются данные: набор полей, которые необходимо будет заполнять (заголовки, поля описания, поле кода, etc.), id из URL и Cookie. Затем getDataByUrl получает и сериализует JSON из папки по id, заполняет необходимые поля

 

function getDataByUrl(url, isJson) {
 
  return new Promise(function(resolve, reject) {
   
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.setRequestHeader('Cache-Control', 'no-cache, no-store, max-age=0');
    xhr.setRequestHeader('Expires', 'Thu, 1 Jan 1970 00:00:00 GMT');
    xhr.setRequestHeader('Pragma', 'no-cache');
  
    xhr.onload = function() {
      try{
      if (xhr.status === 200) 
      {
        var response = (isJson) ? JSON.parse(xhr.responseText) : xhr.responseText;
        resolve(response);
      } 
      
      else 
      {
        resolve(xhr.status);
      }
      
    }
    
    catch{
        var response = (isJson) ? xhr.responseText : JSON.parse(xhr.responseText);
        resolve(response);
    };
    };
    

  
    xhr.onerror = function() 
    {
      resolve(xhr.status);
    };
  
    xhr.send();
    
  });
}

 

3. Тот минимум, который на файлы не переложишь, (например, авторизация) обрабатывается уже http-сервисами. 

 

 
 Механизм авторизации через Telegram

 

В данном случае, единственное, что можно назвать информацией, приходящее из 1С - это данные пользователя и его список чтения. Процедура абсолютно такая же, как и при заполнении страницы, с той лишь разницей, что URL ведет не к файлу на сайте, а к http-сервису 1С и требует идентификации пользователя. Отправляется ли json из файла или формируется в ответ сервиса, роли не играет - ответ на запрос выглядит точно так же.

 

 

Функция ВернутьДанныеПользователя(Знач Печенька) Экспорт
    
    Попытка
        
    НомерДняНедели = ДеньНедели(ТекущаяДатаСеанса());
    ДеньНедели     = ИнструментарийВызовСервера.ВернутьДеньНедели(НомерДняНедели);
    МассивПоДням   = Новый Массив;
    МассивДней     = Новый Массив;
    МассивЦелей    = Новый Массив;
    СловЗаНеделю   = 0;

    ЗапросБД = Новый Запрос(       
    "ВЫБРАТЬ
    |    АктивныеСеансы.Пользователь КАК Пользователь,
    |    АктивныеСеансы.Пользователь.Наименование КАК ПользовательНаименование,
    |    АктивныеСеансы.Пользователь.Код КАК ПользовательКод,
    |    АктивныеСеансы.Дата КАК Период,
    |    АктивныеСеансы.Пользователь.VK КАК ПользовательVK,
    |    АктивныеСеансы.Пользователь.Telegram КАК ПользовательTelegram,
    |    АктивныеСеансы.Пользователь.ДатаРегистрации КАК ПользовательДатаРегистрации,
    |    СУММА(ВЫБОР
    |        КОГДА ПотоковоеЧтение.Пользователь ЕСТЬ NULL
    |            ТОГДА 0
    |        ИНАЧЕ 1
    |    КОНЕЦ) КАК Завершенные,
    |    АктивныеСеансы.Пользователь.ПерсональныеНастройки.ДневнаяЦель КАК Цель,
    |    АктивныеСеансы.Пользователь.ПерсональныеНастройки.Оповещения КАК Оповещания
    |ПОМЕСТИТЬ ВТ_Пользователь
    |ИЗ
    |    РегистрСведений.АктивныеСеансы КАК АктивныеСеансы
    |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПотоковоеЧтение КАК ПотоковоеЧтение
    |        ПО АктивныеСеансы.Пользователь = ПотоковоеЧтение.Пользователь
    |        И ПотоковоеЧтение.Завершена
    |ГДЕ
    |    АктивныеСеансы.Cookie = &Cookie
    |СГРУППИРОВАТЬ ПО
    |    АктивныеСеансы.Пользователь,
    |    АктивныеСеансы.Дата,
    |    АктивныеСеансы.Пользователь.Наименование,
    |    АктивныеСеансы.Пользователь.Код,
    |    АктивныеСеансы.Пользователь.VK,
    |    АктивныеСеансы.Пользователь.Telegram,
    |    АктивныеСеансы.Пользователь.ДатаРегистрации,
    |    АктивныеСеансы.Пользователь.ПерсональныеНастройки.ДневнаяЦель,
    |    АктивныеСеансы.Пользователь.ПерсональныеНастройки.Оповещения
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ ПЕРВЫЕ 7
    |    ЕСТЬNULL(ДневнойПрогресс.КоличествоСлов, 0) КАК КоличествоСлов,
    |    ЕСТЬNULL(ДневнойПрогресс.День, &ДеньНедели) КАК День,
    |    ЕСТЬNULL(ДневнойПрогресс.Дата, &ТекущаяДата) КАК Дата,
    |    ВТ_Пользователь.Цель КАК Цель
    |ПОМЕСТИТЬ ВТ_Неделя
    |ИЗ
    |    ВТ_Пользователь КАК ВТ_Пользователь
    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ДневнойПрогресс КАК ДневнойПрогресс
    |        ПО ВТ_Пользователь.Пользователь = ДневнойПрогресс.Пользователь
    |
    |УПОРЯДОЧИТЬ ПО
    |    ДневнойПрогресс.Дата УБЫВ");
    
    ЗапросБД.УстановитьПараметр("Cookie"        , Печенька);
    ЗапросБД.УстановитьПараметр("ТекущаяДата"   , ТекущаяДатаСеанса());
    ЗапросБД.УстановитьПараметр("ДеньНедели"    , ДеньНедели);
    
    РезультатЗапроса             = ЗапросБД.ВыполнитьПакетСПромежуточнымиДанными();    
    ВыборкаДетальныеЗаписи       = РезультатЗапроса[0].Выбрать();
    ВыборкаПоДням                = РезультатЗапроса[1].Выбрать();
    
    Пока ВыборкаПоДням.Следующий() Цикл
        
        МассивДней.Вставить(0        , ВыборкаПоДням.День);    
        МассивПоДням.Вставить(0      , ВыборкаПоДням.КоличествоСлов);
        
        СловЗаНеделю = СловЗаНеделю + ВыборкаПоДням.КоличествоСлов;
        
        Если Не ВыборкаПоДням.Цель = 0 Тогда
            МассивЦелей.Вставить(0, ВыборкаПоДням.Цель);
        КонецЕсли;
        
    КонецЦикла;
    
    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
        
        ЕстьVK = ?(ЗначениеЗаполнено(ВыборкаДетальныеЗаписи.ПользовательVK), Истина, Ложь);
        ЕстьTG = ?(ЗначениеЗаполнено(ВыборкаДетальныеЗаписи.ПользовательTelegram), Истина, Ложь);
                
        СтруктураПользователя = Новый Структура;
        СтруктураПользователя.Вставить("name"        , ВыборкаДетальныеЗаписи.ПользовательНаименование);
        СтруктураПользователя.Вставить("id"          , ВыборкаДетальныеЗаписи.ПользовательКод);
        СтруктураПользователя.Вставить("status"      , "ok");
        СтруктураПользователя.Вставить("days"        , МассивДней);
        СтруктураПользователя.Вставить("data"        , МассивПоДням);
        СтруктураПользователя.Вставить("week"        , СловЗаНеделю);
        СтруктураПользователя.Вставить("target"      , МассивЦелей);
        СтруктураПользователя.Вставить("total"       , ПолучитьОбщееЧислоСлов(ВыборкаДетальныеЗаписи.Пользователь));
        СтруктураПользователя.Вставить("VK"          , ЕстьVK);
        СтруктураПользователя.Вставить("Telegram"    , ЕстьTG);
        СтруктураПользователя.Вставить("regdate"     , ВыборкаДетальныеЗаписи.ПользовательДатаРегистрации);
        СтруктураПользователя.Вставить("fin"         , ВыборкаДетальныеЗаписи.Завершенные);
        СтруктураПользователя.Вставить("alert"       , Строка(ВыборкаДетальныеЗаписи.Оповещания));
        
    Иначе
                
        СтруктураПользователя = Новый Структура;
        СтруктураПользователя.Вставить("name"        , "");
        СтруктураПользователя.Вставить("id"          , "");
        СтруктураПользователя.Вставить("status"      , "not_found");    
        
    КонецЕсли;
    
    Возврат СтруктураПользователя;
    
    Исключение
        ИнструментарийВызовСервера.ЗаписьВЖурналИсключений(ОписаниеОшибки());
        Возврат "";
    КонецПопытки;
    
КонецФункции

 

Информация о сеансе хранится в Cookie, по которому потом находится пользователь в регистре сведений. Правда, обрабатывает это не Aioniotis CMS, а третья часть проекта.

 

Последнее про сайт: если у кого-то возник вопрос, может ли 1С полноценно крутить сайт целиком сам, то да, может. Этот сайт, например, тоже проходил несколько итераций, первая из которых была дуболобный Server-Side: html, js и css хранились строками в справочниках, а при запросе на http сервис все это собиралось в одну большую строку и отправлялось обратно. Если какая-то страница требовала ситуативных данных, то в текст ее макета вставлялось нечто вроде @ЗаменитьЗдесь, а в модуле обработки СтрЗаменить("@ЗаменитьЗдесь", НужныеДанные). Такой способ, в целом, тоже имеет право на жизнь, но, конечно, не оптимален. 

 

Ferapont

 

Второй частью непосредственно 1Сного балета проекта является конфигурация бота и API. Изначальной, эта часть была одним целым с CMS, но потом оказалось, что пересекающихся данных у них не так много и держать разрозненный функционал внутри одной конфигурации нет никакого смысла. 

 

 

В первую очередь она отвечает за бота. Бота зовут Ферапонт (@AioniotisBot в Telegram и встроенный прямо в сообщения сообщества в ВК). Это сердце проекта: с его помощью осуществляется регистрация и авторизация на сайте, а так же отправка книг. Я храню тексты книг страницами по 70 слов в табличных частях. Когда пользователь хочет начать читать, он отправляет боту код со страницы или нажимает кнопку там же. Бот присылает ему первую страницу и клавиатуру с двумя кнопками "<-" и "->". Пользователь жмет эти кнопки и бот присылает предыдущую/следующую страницу. Прогресс чтения записывается в РС, а книг можно читать сколько угодно - если вернутся к старой, то чтение начинается с последней прочитанной страницы.

 

 

 

 

 
 Пример кода: формирование текста страницы для отправки

 

Все построено на http-сервисах. Про быстродействие я расскажу ниже, пока скажу лишь что работает без проблем.

 

 

Про Telegram Mini App

 

Сайт и бот - это хорошо. Но с течением времени я заметил, что пользователи не очень хотят лезть на сайт в браузере для поиска необходимых книг - до 80% начатых чтений было лишь от рекламных постов в группе ВК и Telegram-канале. Так как я сам уверенный пользователь своего же продукта, я понимал почему - это просто не удобно. В поиске решения проблемы я наткнулся на технология TMA.

Telegram Mini App - это механизм телеграма, позволяющий по какому-либо событию открывать любой сайт или веб-приложение прямо внутри мессенджера. Это было настоящее спасение, так как я мог буквально воткнуть свой готовый, уже адаптированный для смартфонов, сайт внутрь телеграм, чтобы пользователям не было необходимости открывать его отдельно в браузере. Помимо этого, у TMA доступен и свой отдельный функционал - так, например, пользователю моего бота нет необходимости ни регистрироваться ни авторизоваться при открытии Mini App - механизм позволяет http-сервису в 1С получать информацию о пользователе (TelegramID в частности) прямо в момент открытия приложения. 

При выборе книги приложение закрывается - это также возможность функционала TMA.


Статья про работу с Telegram Mini APP на Инфостарт тут

 

 

Сакральное знание

 

Распинаясь про опыт, было бы странно не рассказать о каких-нибудь интересных фактах из жизни проекта.

 

Hardware

Для начало стоит отметить хардварную часть. Хардварная часть невероятная - вот она:

 

 

Весь этот год на данном чуде техники крутятся 1С, PostgreSQL и Sonarqube. Компьютер очень маленький и бесшумный, оставалось только поставить Windows Server и взять статический IP у провайдера. В нем стоит довольно слабенький 4-х ядерный Intel Alder Lake-N95 на 2.0 GHz, но зато 8 ГБ оперативы. Не буду распылятся - немой вопрос повис в воздухе - что по быстродействию

Это один из ключевых вопросов, ответ на который я не мог найти: насколько вообще http-сервисы жизнеспособны, когда речь идет о публичном сервисе. Для стресс теста своего бота я использовал К6. Он, к сожалению, не доступен для покупки в СНГ больше, но мне и триала хватило. Вот как выглядят данные по моему дефолтному тесту бота: 

1. К6 эмулирует Telegram и присылает на http-сервис json, как прислал бы сам Telegram, сообщая о новом сообщении

2. json разбирается, делаются чтения и запись в БД, формируется json с ответом и отправляется новым POST запросом на Telelgram API 

 

 

Что мы тут видим?

Голубая линия - время ответа. В начале оно проседает из-за создания нового соединения. Фиолетовая линия означает количество запросов в секунду. На протяжении почти всего теста она держится на отметках около 30 - больше 1С не успевает обрабатывать. Всего тест длится 3 минуты 30 секунд - 1С за это время успевает обработать 4152 запроса, ну и не падает нигде, тоже хорошо. Я не знаю, насколько это много или мало в сравнении, думаю не очень много, но если смотреть на вещи реально - имей я сервис, востребованный на 30 запросов в секунду 24 часа в сутки 7 дней в неделю, думаю, у меня был бы сервер получше. Немного отмечу, что происходит на графике:

 

 

На чем просадки? 80% времени на больших нагрузках занимают МенеджерЗаписи.Прочитать и МенеджерЗаписи.Записать (у меня этим записывается информация о новой прочитанной странице и дневном прогрессе пользователя - около 75% процентов потребления времени по замеру производительности). При этом, при низкой загрузке ЦП, эти действия не занимают значительного времени, так что не исключено, что проблема может быть на стороне СУБД. Была еще попытка использования фоновых заданий, но оказалось, что 4-х ядерному процессору в 100% загрузки не особо интересно, в каком потоке тормозить, так что от этой идеи почти целиком пришлось отказаться - лишь тратилось время на поднятие ФЗ. Осталось только одно - запись различных неоперативных данных, которые можно не ждать, а уже отправить пользователю ответ.

 

 

Так выглядит JSON, отправляемый на сервис. Он может показаться небольшим, но по нему происходит:

1. Поиск пользователя по chat_id (запрос к справочнику)

2. Поиск книги по text: 7547G (запрос к справочнику)

3. Поиск, читал ли данный пользователь уже данную книгу (запрос к МЗ)

4. Отправка нужной страницы (поиск по табличной части элемента из п.2, http-запрос)

5. Запись прогресса - первая страница прочитана (МЗ.Прочитать, МЗ.Записать)

6. Запись общего дневного прогресса пользователя для дашборда в профиле (МЗ.Прочитать, МЗ.Записать)

Быстро или медленно? Достаточно для небольшого проекта. 

 

Автотесты

 

Автоматизированное тестирование в 1С набирает популярность. Однако когда речь идет об общедоступном API, оно становится не то что очень важным, а жизненно необходимым. Например, я хочу оптимизировать метод отправки сообщений в Телеграм. Как мне узнать наверняка, что я ничего не сломал в процессе? Пользователь проекта отличается от сотрудника компании: он не сделает тикет - он просто больше не придет. И вот я поменял отправку сообщений в Телеграм, рефакторинг сделал, все дела. Теперь мне нужно проверить, например, регистрацию: удалить Telegram ID у своего пользователя, зайти на сайт, нажать кнопку входа, посмотреть результат, удалить нового пользователя, вернуть id своему. А потом мне надо проверить вход, отправку книги и отправку книги во время входа.

 

Со временем таких действий становится все больше и проводить десятки тестов руками после каждой новой строчки кода нет никаких сил. Вот какая схема тестирования спасла в этом проекте меня:

  • Есть константа ЗаписыватьТесты. Когда она Истина - все сервисы, где прописано условие проверки этой константы, начинают записывать свои запросы в специальный справочник как:
    • Имя Метода
    • JSON тела, если есть (Строкой)
    • Заголовки (как есть из HttpСервисЗапрос - в ХранилищеЗначений)
    • Параметры запроса (как есть из HttpСервисЗапрос - в ХранилищеЗначений)
      Процедура ЗаписатьТест(Запрос, Метод) Экспорт
          
          Попытка
              
              Если Не Константы.ЗаписыватьТесты.Получить() Тогда
                  Возврат;
              КонецЕсли;
              
              UID = Строка(Новый УникальныйИдентификатор);
              
              НовыйТест = Справочники.АвтотестыСервисов.СоздатьЭлемент();
              НовыйТест.Код                    = UID;
              НовыйТест.Наименование           = "Тест " + UID;
              НовыйТест.ВходнойJSON            = Запрос.ПолучитьТелоКакСтроку();
              НовыйТест.ХранилищеЗаголовков    = Новый ХранилищеЗначения(Запрос.Заголовки);
              НовыйТест.ХранилищеПараметров    = Новый ХранилищеЗначения(Запрос.ПараметрыЗапроса);
              НовыйТест.Метод                  = Метод;
              НовыйТест.URL                    = Запрос.БазовыйURL + Запрос.ОтносительныйURL;
              НовыйТест.Записать();
              
          Исключение
              ИнструментарийВызовСервера.ЗаписьВЖурналИсключений(ОписаниеОшибки());
          КонецПопытки;
          
      КонецПроцедуры

       

  • После записи этот тест можно запустить.
    Процедура ЗапускТеста(Тест, UIDГруппы = "") Экспорт
        
        РеквизитыТеста  = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(Тест, "ВходнойJSON,Метод,URL,Определитель");
        JSONЗапроса     = РеквизитыТеста.ВходнойJSON;
        URL             = РеквизитыТеста.URL;
        UID             = Строка(Новый УникальныйИдентификатор);
        Определитель    = РеквизитыТеста.Определитель;
        ДопПараметры    = Новый Соответствие;
        Ошибка          = "";
        
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ
            |    АвтотестыСервисовЗаменяемыеПараметры.Параметр КАК Параметр,
            |    АвтотестыСервисовЗаменяемыеПараметры.Значение КАК Значение
            |ИЗ
            |    Справочник.АвтотестыСервисов.ЗаменяемыеПараметры КАК АвтотестыСервисовЗаменяемыеПараметры
            |ГДЕ
            |    АвтотестыСервисовЗаменяемыеПараметры.Ссылка = &Тест";
        
        Запрос.УстановитьПараметр("Тест", Тест);
        
        РезультатЗапроса         = Запрос.Выполнить();    
        ВыборкаДетальныеЗаписи   = РезультатЗапроса.Выбрать();
        
        Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
            JSONЗапроса = СтрЗаменить(JSONЗапроса, "@" + ВыборкаДетальныеЗаписи.Параметр, ВыборкаДетальныеЗаписи.Значение);  
        КонецЦикла;
        
        Попытка
                    
            Заголовки            = Тест.ХранилищеЗаголовков.Получить();    
            ПараметрыЗапроса     = Новый Соответствие(Тест.ХранилищеПараметров.Получить());    
    		ВыполнитьПредобработку(Определитель, JSONЗапроса, ПараметрыЗапроса, ДопПараметры);
            
            Ответ     = МетодыРаботыHttp.ЗапросПоПараметрамСервиса(Заголовки, ПараметрыЗапроса, URL, JSONЗапроса);
            Пройден   = ВыполнитьПостОбработку(Определитель, Ответ, ДопПараметры);
            
        Исключение
            
            Пройден = Ложь;
            Ошибка  = ОписаниеОшибки();
            
        КонецПопытки;
        
        МЗ = РегистрыСведений.ВыполнениеТестов.СоздатьМенеджерЗаписи();
        МЗ.Период        = ТекущаяДатаСеанса();
        МЗ.UID           = UID;
        МЗ.UIDГруппы     = UIDГруппы;
        МЗ.Тест          = Тест;
        МЗ.Пройден       = Пройден;
        МЗ.Ошибка        = Ошибка;
        МЗ.Записать(Истина);
        
    КонецПроцедуры
    

     

  • В процессе запуска он проходит 3 этапа
    • Процедура предобработки - специально написанная процедура, добавленная в перечень процедур предобработки для конкретного теста. В нее попадают записанные в Спр. данные и их можно обработать. Можно обработать и что-нибудь другое. Так, например, при запуске теста регистрации, данная процедура чистит Telegram ID у моего пользователя, чтобы зарегистрировался новый, сохраняя его в доп. параметры для последующей сверки.
      Процедура РегистрацияТелеграм_Пред(ТелоЗапроса, ДопПараметры)
          
          Актор = Справочники.Пользователи.ЭтотПользователь;
          
          ПользовательТестирования = Актор.ПолучитьОбъект();
          
          ДопПараметры.Вставить("Telegram", ПользовательТестирования.Telegram);
          
          ПользовательТестирования.Telegram = "";
          ПользовательТестирования.Записать();
      	
      	ТелоДвоичное    = ПолучитьДвоичныеДанныеИзСтроки(ТелоЗапроса, "UTF-8");
          СтруктураТела   = МетодыРаботыHttp.JsonВСтруктуру(ТелоДвоичное, "UTF-8");
          
          Печенька = СтруктураТела["message"]["text"];
          Печенька = СтрЗаменить(Печенька, "/start ", "");
          
          ДопПараметры.Вставить("Печенька", Печенька);
          
      КонецПроцедуры

       

    • Общая процедура отправки запроса на свой сервис, создающая запрос из сохраненных (и, возможно, подредактированных в предыдущем пункте) данных
      Функция ЗапросПоПараметрамСервиса(Знач Заголовки, Знач Параметры, Знач URL, Знач Тело = "") Экспорт
          
          СтруктураURL     = РазбитьURL(URL);
          Соединение       = Новый HTTPСоединение(СтруктураURL["Сервер"], 443, , , , 60, Новый ЗащищенноеСоединениеOpenSSL());
          Запрос           = Новый HTTPЗапрос(СтруктураURL["Адрес"] + ПараметрыЗапросаВСтроку(Параметры));
      
          Для Каждого Заголовок Из Заголовки Цикл
              Если Не Заголовок.Ключ = "Content-Length" Тогда
                  Запрос.Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение);
              КонецЕсли;
          КонецЦикла;
      	
      	Если ЗначениеЗаполнено(Тело) Тогда
      		Запрос.УстановитьТелоИзСтроки(Тело, "UTF-8");
      		Ответ = Соединение.ОтправитьДляОбработки(Запрос);
      	Иначе
      		Ответ = Соединение.Получить(Запрос);
      	КонецЕсли;
      
          Возврат Ответ;
          
      КонецФункции

       

    • Процедура постобработки - специально написанная процедура, добавленная в перечень процедур предобработки для конкретного теста. В нее попадает Ответ от сервиса и доп. параметры из пред. обработки. Если вернуться к примеру с регистрацией, то тут я достаю сохраненный ранее ID, ищу в базе, создался ли новый пользователь с таким, после чего удаляю этого нового пользователя и возвращаю ID своему. Ошибку в прохождении теста я определяею Если Тогда ВызватьИсключение.
      Функция РегистрацияТелеграм_Пост(Ответ, ДопПараметры)
           
          Телеграм    = ДопПараметры.Получить("Telegram");
      	Печенька    = ДопПараметры.Получить("Печенька"); 
          
          Если Не ЗначениеЗаполнено(Телеграм) Тогда
      		ВызватьИсключение "Не получен ID";	
      	КонецЕсли;
      	
      	Если Не ЗначениеЗаполнено(Печенька) Тогда
      		ВызватьИсключение "Не получена Печенька";	
      	КонецЕсли;
      	
      	ПроверкаСеанса(Печенька);
          ПроверкаНовогоПользователя(Телеграм, "Telegram");
          
          Возврат Истина;
      
      КонецФункции
      
      
      Процедура ПроверкаСеанса(Знач Печенька)
      	
      	ПользовательИБ = МетодыApiСайта.ВернутьПользователяПоCookie(Печенька);
      	
      	Если ЗначениеЗаполнено(ПользовательИБ) Тогда
      		
      		МЗ = РегистрыСведений.АктивныеСеансы.СоздатьМенеджерЗаписи();
      		МЗ.Cookie       = Печенька;
      		МЗ.Пользователь = ПользовательИБ;
      		МЗ.Удалить();
      		
      	Иначе
      		
      		ВызватьИсключение "Сеанс не создан. Cookie = '" + Печенька + "'";
      		
      	КонецЕсли;
      
      КонецПроцедуры
      
      
      Процедура ПроверкаНовогоПользователя(Знач ID, Знач СоцСеть)
      	
      	ПользовательИБ  = Справочники.Пользователи.НайтиПоРеквизиту(СоцСеть, ID); 
      	   
          Если ЗначениеЗаполнено(ПользовательИБ) Тогда
              
              ПользовательИБ.ПолучитьОбъект().Удалить();
              
              ПользовательТестирования = Справочники.Пользователи.ЭтотПользователь.ПолучитьОбъект();
              ПользовательТестирования[СоцСеть] = ID;
              ПользовательТестирования.Записать();
              
          Иначе 
              
              ВызватьИсключение "Пользователь не зарегистрирован. ID = '" + ID + "'";
              
          КонецЕсли;
      
      КонецПроцедуры

       

Информация о выполнении или невыполнении пишется в РС.

 

Пример работы с Ajax

Весь athenaeum.digital построен на ajax - возможности js отправлять http запросы. Понятно, что http запросы и так отправляются, когда вы переходите на сайт, но при помощи js эти запросы можно отправлять в нужный момент и обрабатывать полученные ответы без перезагрузки страницы. Один пример этого уже был в блоке про сайт, где страница заполнялась из JSON, а здесь будет еще один, более подробно.

Обработка нажатия на кнопку отправки книги

 

 

 

function ping(url) {
  
  return new Promise(function(resolve, reject) {
    
    var xhr = new XMLHttpRequest();
    xhr.open('GET', url , true);
    xhr.setRequestHeader('Athenaeum-Source', document.location.pathname);

    xhr.onload = function() {
      
      if (xhr.status === 200) 
      {
        resolve(true);
      } 
      else 
      {
        resolve(false);
      }
    };

    xhr.onerror = function() {
      resolve(false);
    };

    xhr.send();
  });
} 



  tg.onclick = function(event) {
        let session = getCookie("uuid");
        event.preventDefault(); 
        ping('https://api.athenaeum.digital/u/hs/bot/sendBook?cookie=' + session + '&book=' + id + '&social=tg').then(function(success){         
          if(success) {showMessage('Отправлено!', 'success')}
          else        {showMessage('Ошибка! Проверьте, подключен ли у вас аккаунт данной социальной сети и повторите попытку позже', 'danger')}
          });   
      };    

 

В начале есть функция Ping - она создает самый простой Get запрос по переданному URL: создается объект типа XMLHttpRequest, определяется тип запроса и URL, после чего запрос отправляется. Если статус 200 - возвращает Истина, иначе Ложь. Далее идет назначение обработчика нажатия (onclick) для кнопки с именем tg. Переменной session присваивается значения Cookie, после чего через функцию ping GET запрос улетает по адресу http-сервиса 1С. В зависимости от ответа (200/ не 200), выводится сообщение на экран. 1С принимает запрос и начинает его обрабатывать:

 

Функция takeStartsendData(Запрос) Экспорт
	
	МетодыТестирования.ЗаписатьТест(Запрос, "takeStartsendData");
	
    Ответ = Новый HTTPСервисОтвет(200);
    
    Попытка
        
    Печенька             = Запрос.ПараметрыЗапроса.Получить("cookie");
    Количество           = Запрос.ПараметрыЗапроса.Получить("book");
    Назначение           = Запрос.ПараметрыЗапроса.Получить("social");
    ПользовательИБ       = ВернутьПользователяПоCookie(Печенька);
    
    ПоляПользователя     = ИнструментарийВызовСервера.ЗначенияРеквизитовОбъекта(ПользовательИБ
        , "Telegram,VK,РазрешилПисатьVK");
    
    ЗапретТГ = (Назначение = "tg" 
        И Не ЗначениеЗаполнено(ПоляПользователя.Telegram));
    ЗапретВК = (Назначение = "vk" 
        И (Не ЗначениеЗаполнено(ПоляПользователя.VK) Или Не ПоляПользователя.РазрешилПисатьVK));
    
    Если ЗапретТГ ИЛИ ЗапретВК Тогда        
        Ответ = Новый HTTPСервисОтвет(400);
        Возврат Ответ;
    КонецЕсли;

 

В самом начале получаются параметры, которые можно заметить в URL функции ping js скрипта.

 

Несколько очень важных моментов при работе с Ajax

1. На сервере обязательно должен быть SSL-сертификат. Ajax работает только под https

2. Если домен сайта и домен api не совпадают, то api должен возвращать заголовок Access-Control-Allow-Origin с адресом сайта. Так, например, у меня api (сервисы 1С) располагается на поддомене api.athenaeum.digital, а сам сайт на athenaeum.digital. В таких случаях браузер ругается на CORS и ничего не работает. У меня (и у вас, если вы используете IIS) это решается добавлением стандартного заголовка ко всем ответам


 

3. В современных браузерах политика CORS так же требует соблюдения еще одного правила. Перед любым запросом, который отправляется при помощи Ajax, отправляется запрос типа Option. Если ответ на этот запрос не 200, то дальнейшие действия не выполняются. Решается это легко: в любом шаблоне http-сервиса, нацеленном на работу с Ajax, нужно просто добавить метод типа Option с ответом в 200 (код обработчика по умолчанию)

 

 

Ну, а пока это все. Если вас интересуют ответы на конкретные вопросы, то задавайте. Возможно, на некоторые из них вам ответят статьи про Telegram, VK и ImageMagick. Ну и, конечно же, код на GitHub

 

Спасибо за внимание!

 

 

 Мой GitHub:     https://gitub.com/Bayselonarrend 
 Лицензия MIT:   https://mit-license.org

 

web интеграция Telegram VK сайт соц. сети

См. также

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    17985    18    22    

17

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

7200 руб.

04.05.2021    20124    13    19    

18

WEB-интеграция 8.3.8 Конфигурации 1cv8 Автомобили, автосервисы Беларусь Украина Россия Казахстан Управленческий учет Платные (руб)

Расширение предназначено для конфигурации "1С:Предприятие 8. Управление Автотранспортом. ПРОФ". Функционал модуля: 1. Заполнение регистров сведений по подсистеме "Мониторинг", а именно: события по мониторингу, координаты по мониторингу, пробег и расход по мониторингу, текущее местоположение ТС по мониторингу 2. Заполнение путевого листа: пробег по мониторингу, время выезда/заезда, табличная часть ГСМ, места стоянок по геозонам. 3. Отчеты по данным загруженным в регистры сведений. 4. Предусмотрена автоматическая загрузка данных в фоновом режиме (условия работы данной загрузке читайте в описании товара) Модуль работает без включенной константы по настройкам мониторинга. Модуль формы предоставляется с открытым кодом, общий модуль защищен. Любой заинтересованный пользователь, имеет возможность скачать демо-версию расширения.

22656 руб.

25.05.2021    14547    42    8    

18

WEB-интеграция Программист Руководитель проекта Платформа 1С v8.3 Конфигурации 1cv8 1С:Франчайзи, автоматизация бизнеса Платные (руб)

Расширение значительно упрощает написание API на 1С. Веб программисты получают простой и понятный доступ к 1С. Описание API создаётся автоматически и представляется в виде удобном как для человека, так и для программной обработки.

24000 руб.

27.09.2024    1688    1    0    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. cheshirshik 70 27.11.23 17:55 Сейчас в теме
Статья интересная. Тоже занимаюсь самобытными проектами на 1С. Честно говоря читая статью, я так и не понял 1С-ка хорошая или плохая? Если плохая, то зачем ее использовать на своих проектах?

За публикацию плюсик, за публикацию на гитхабе плюсик в карму. :-)
2. bayselonarrend 2136 27.11.23 19:34 Сейчас в теме
(1)Спасибо. Не хорошая и не плохая - со своими плюсами и минусами. Если готов мириться с лицензированием и быстродействием сверхвысокоуровневого языка, то получаешь платформу для очень быстрой разработки с невероятным уровнем абстракции. Многие недооценивают подобные моменты, но когда ты пишешь что-то для себя, то в первую очередь не хватает мотивации, а от фронта работ опускаются руки. У 1С от начала разработки до первого результата время сокращенно максимально. Мое мнение, что лучше, все таки, реализовать что-нибудь на простой платформе, пусть и в ущерб производительности, чем не реализовать ничего на крутом невероятном языке.

Просто понимаю, что если бы пришлось писать, например, на C#, рисовать руками все формы всех таблиц под WPF, подключать ко всему этому отдельную SQL базу, под которую пришлось бы писать для каждой таблицы объект, сайт писать на ASP.NET и т.д., ну я бы, скорее всего, даже не брался бы.
SirAlex; fatman78; mrChOP93; belant-1с; LeXXeR; cheshirshik; +6 Ответить
3. cheshirshik 70 27.11.23 19:53 Сейчас в теме
(2) Я тоже на 1С перешел с языка высокого уровня. Это был Делфи. Там я так же рисовал все формы и объекты руками. Времени уходило в разы больше. Поэтому перешел в 1С.

Я тоже считаю 1С не хорошим и не плохим. Все зависит от задач. Конечно у 1С свои ограничения, но многие рутинные моменты реализованы разрабами 1С и их с нуля делать уже не надо. Ну например ВЕБ клиент.
bayselonarrend; +1 Ответить
4. SerVer1C 817 28.11.23 01:09 Сейчас в теме
(2) Для абстрагирования от СУБД давно придумали всякие Entity и прочее. Думаю, что и для WPF существуют кодогенераторы. 1с тоже не сладкая конфета, когда нужно сделать конкретный интерфейс, а когда ты ограничен десятком контролов, то сильно не размахнешься. И сайт у вас не на 1с крутится, и скрипты не на bsl написаны.
6. bayselonarrend 2136 28.11.23 08:56 Сейчас в теме
(4) Entity Framework не поможет когда нужно сделать нечто вроде формы списка: с подгрузкой строк при скролле и универсальными отборами по всей таблице. Кодогенераторы есть конечно, но они даже и близко не создают тебе к таблице форму, класс, набор стандартных методов под поля разных типов и не встраивают это все как раздел на общей форме приложения. Сайт не на 1С крутится и я написал о том, что можно его крутить (если это так можно назвать) на 1С, формируя html полотно из строк в справочниках. Но при этом, у меня 1С обслуживает API, возвращая динамические данные и формирует из справочников в 2 клика всю статику, необходимую для работы сайта. Никто не мешает мне не формировать эту статику и писать файлами на сервер, а отдавать каждый раз http-сервисами, просто я так не захотел. Про какие скрипты речь идет я, если честно, вообще не понял
cheshirshik; +1 Ответить
5. user1681028 25 28.11.23 04:55 Сейчас в теме
(1) А я использую 1С в качестве бекенда для разработки полностью готового прототипа web приложения и потом как панель управления сайтом/приложением. Той легкости проектирования и внесения изменений, удобство отладки, нигде не встречал. А вот когда все работает как нужно, вся структура бекенда со всеми таблицами определена, уже переписываю, на mongo или sql.
oleg-x; cheshirshik; +2 Ответить
Оставьте свое сообщение