1. Установка DataReducer

1.1 Системные требования

  • Операционная система: Windows 10 x64 / DEB-based Linux x64
  • 1C:Предприятие 8 - Версия 8.3.9 или старше

1.2 Схема развертывания

Процесс развертывания DataReducer состоит из следующих этапов:
  • Публикация интерфейса OData информационных баз 1С на веб-сервере.
  • Запуск сервисов rserve и rapport в Docker-контейнерах.
  • Установка и настройка приложения DataReducer Console.

Далее каждый из этих этапов будет подробно описан.

Схема развертывания

1.3 Публикация интерфейса OData информационных баз 1С на веб-сервере

Для интеграции с «1С:Предприятием» DataReducer Console использует протокол OData. Для работы с ним стандартный интерфейс OData каждой из информационных баз должен быть опубликован на веб-сервере.

Шаг 1. Запустите Конфигуратор от имени Администратора. В меню Конфигуратора «Администрирование → Публикация на веб-сервере» поставьте флажок «Публиковать стандартный интерфейс OData». Более подробную информацию о настройке веб-сервера можно получить на сайте 1С:ИТС.

Шаг 2. Выберите объекты информационной базы, доступ к которым может быть предоставлен через автоматический REST-сервис. Это осуществляется с помощью типовой обработки «Настройка автоматического REST-сервиса». В некоторых конфигурациях эта обработка может отсутствовать. В этом случае для включения объектов в состав стандартного интерфейса OData следует воспользоваться методом глобального контекста УстановитьСоставСтандартногоИнтерфейсаOData(). Соответствующий код может быть выполнен во внешней обработке. Например,

&НаСервере
Процедура КомандаНаСервере()
    МассивОбъектов = Новый Массив();

    МассивОбъектов.Добавить(Метаданные.РегистрыРасчета.Начисления);
    МассивОбъектов.Добавить(Метаданные.РегистрыРасчета.Удержания);

    Для Каждого Справочник Из Метаданные.Справочники Цикл
        МассивОбъектов.Добавить(Справочник);
    КонецЦикла;

    УстановитьСоставСтандартногоИнтерфейсаOData(МассивОбъектов); 
КонецПроцедуры

1.4 Запуск сервисов rserve и rapport в Docker-контейнерах

Docker-образ datareducer/rserve включает интерпретатор R, сервер Rserve, ряд других библиотек и пакетов.

Docker-образ datareducer/rapport содержит веб-приложение rapport, которое предназначено для публикации отчетов DataReducer в различных форматах. Веб-приложение выполняется в среде Apache Tomcat.

Шаг 1. Скачайте с официального сайта дистрибутив Docker для вашей операционной системы и установите его.

Шаг 2.Скопируйте полученный вами каталог «docker_compose» в хост-систему. Убедитесь, что у вас есть все файлы, необходимые для развертывания сервисов:


Подкаталог datareducer_model содержит файл модели веб-приложения. При развертывании этот каталог будет примонтирован к файловой системе контейнера rapport.

Файл rserve_pwd.txt содержит имя и пароль пользователя rserve. Измените их, после чего также отредактируйте значения настроек «rserve-user» и «rserve-password» в файле datareducer.properties.

Измените пароль Администратора веб-приложения rapport в файле tomcat-users.xml.

Шаг 3. В файле docker-compose.yml отредактируйте пути к каталогам хост-системы, которые будут примонтированы к Docker-контейнерам (см. листинг ниже). Первый каталог предназначен для обмена файлами между сервисом rserve и хостом. Второй содержит файл модели веб-приложения (см. шаг 2). Замените символы тильды «~» на абсолютные пути к нужным каталогам.

version: "3.6"

services:
  rserve:
    image: datareducer/rserve
    ports:
      - "6311:6311"
    networks:
      - webnet
    volumes:
      - ~:/mnt/host
      - webapp-files:/mnt/webapp-files
    secrets:
      - source: rserve_pwd
        mode: 0440

  rapport:
    image: datareducer/rapport
    ports:
      - "8080:8080"
    networks:
      - webnet
    volumes:
      - ~/datareducer_model:/usr/local/tomcat/webapps/rapport/WEB-INF/model
      - webapp-files:/usr/local/tomcat/webapps/rapport/files
    secrets:
      - source: rapport_props
        target: /usr/local/tomcat/webapps/rapport/WEB-INF/datareducer.properties
        uid: '1000'
        gid: '1000'
        mode: 0440
      - source: rapport_users
        target: /usr/local/tomcat/conf/tomcat-users.xml
        uid: '1000'
        gid: '1000'
        mode: 0440
    configs:
      - source: rapport_web
        target: /usr/local/tomcat/webapps/rapport/WEB-INF/web.xml
        uid: '1000'
        gid: '1000'
        mode: 0440

networks:
  webnet:

volumes:
  webapp-files:

secrets:
  rserve_pwd:
    file: ./rserve_pwd.txt
  rapport_props:
    file: ./datareducer.properties
  rapport_users:
    file: ./tomcat-users.xml

configs:
  rapport_web:
    file: ./web.xml

Шаг 4. Откройте терминал, перейдите в каталог «docker_compose» и введите следующие команды:

$ docker swarm init

$ docker stack deploy -c docker-compose.yml datareducer

После успешного выполнения последней команды вы должны увидеть следующий вывод:

Creating    network     datareducer_webnet
Creating    secret      datareducer_rapport_users 
Creating    secret      datareducer_rserve_pwd 
Creating    secret      datareducer_rapport_props 
Creating    config      datareducer_rapport_web 
Creating    service     datareducer_rserve 
Creating    service     datareducer_rapport

Шаг 5. Проверьте, что сервисы правильно настроены. Для этого откройте браузер и перейдите по адресу http://localhost:8080/rapport/

Вы должны увидеть страницу ресурсов DataReducer:


Перейдите по ссылке с наименованием ресурса «iris»:


1.5 Установка и настройка DataReducer Console

Установите программу DataReducer Console, запустите её и откройте окно настроек через главное меню программы: «Правка → Настройки»:


Введите настройки в соответствии со значениями, выбранными вами в разделе 1.4. Перед сохранением настроек убедитесь, что у текущего пользователя есть права на запись в каталог программы.

Проверьте подключение к сервису rserve. Для этого в главном меню выберите «Инструменты → Проверить подключение к Rserve». При успешном подключении вы увидите версию R:


Проверьте подключение к сервису rapport. Для этого в главном меню выберите «Файл → Получить модель с сервера», затем «Файл → Загрузить модель на сервер». Эти операции должны выполняться без ошибок.

2. Работа с DataReducer Console

2.1 Подключение информационных баз и загрузка метаданных

В DataReducer Console вы можете одновременно работать с данными нескольких информационных баз. Для того, чтобы открыть окно подключения информационной базы, выберите пункт главного меню «Правка → Добавить базу 1С» или нажмите соответствующую кнопку на панели списка информационных баз.

Окно подключения ИБ

Дерево метаданных подключённой информационной базы загружается при её выделении в списке информационных баз или при выборе пункта «Загрузить метаданные» в контекстном меню этого списка.

Форма списка ИБ

В дереве метаданных отображаются только те объекты, которые пользователь включил в состав стандартного интерфейса OData данной информационной базы (см. п. 1.3).


2.2 Интерфейс главного окна программы

Главное окно программы
  1. Список информационных баз
  2. Дерево метаданных
  3. Вкладка скрипта R
  4. Наборы данных скрипта R
  5. Область вывода сообщений
  6. Таблица данных
  7. Область вывода графики

2.3 Формирование наборов данных

Для того, чтобы создать новый скрипт R, выберите пункт главного меню «Правка → Добавить скрипт R» или нажмите соответствующую кнопку на панели списка скриптов R. При создании нового скрипта автоматически открывается его вкладка.

Для создания набора данных, содержащего данные объектов информационной базы «1С:Предприятия», воспользуйтесь контекстным меню дерева метаданных.

Создание набора данных

Выбранный объект будет добавлен в наборы данных скрипта R, вкладка которого открыта и активна в настоящий момент.

Двойным кликом по строке списка наборов данных скрипта R откройте окно созданного набора для его редактирования.

Доступные настройки зависят от типа объекта, которому соответствует набор данных.

Ниже приведены описания общих для всех объектов настроек.

Панель настроек и параметров

Панель настроек и параметров

Наименование набора данных — идентификатор, по которому будет осуществляться обращение к набору данных в теле скрипта R.

Время кэширования (минут) — время хранения результатов выполнения запроса в кэше. Устанавливается отдельно для каждого набора данных. Например, для Констант имеет смысл установить более продолжительное время кэширования.

Вы можете отключить кэширование данного набора данных, введя в это поле значение «0».

Учитывать ограничения доступа — выборка только тех объектов информационной базы, к которым пользователь имеет доступ.

Панель выбора полей (измерений)

Панель выбора полей (измерений)

По умолчанию в запрос включаются все поля объекта. Для ограничения их состава оставьте в правой таблице только выбранные поля.

Отметьте флажок «Представление», если вы хотите, чтобы в набор данных было включено представление поля. Например, для поля «Организация_Key» с типом GUID в набор данных будет включена колонка с именем «Организация____Presentation», содержащая наименования организаций.

Панель отбора

Панель отбора

Панель содержит инструменты для создания и редактирования дерева разбора логического выражения отбора данных. Для того, чтобы добавить к отбору простое логическое выражение, нажмите кнопку «Добавить фильтр».

Фильтры могут быть сгруппированы. Для этого выделите два или более фильтра с помощью клавиши «Ctrl» и нажмите кнопку «Сгруппировать».

Колонки:

  1. Колонка группы — логический оператор, выбирается из выпадающего списка из значений «И», «Или». Может принимать значение «Не», если логическое выражение инвертировано. Для инверсии фильтра (или группы) выделите строку фильтра (или группы) и нажмите кнопку «Инвертировать».
  2. Поле — выбирается из выпадающего списка. После имени поля в квадратных скобках указан его тип. Для обозначения полей составного типа к имени типа добавляется символ «c», например, «[string, c]». (Для полей составных типов предусмотрен специальный формат значения, см. далее).
  3. Оператор — оператор сравнения. Выбирается из выпадающего списка.
  4. Значение — вводится вручную в соответствии с типом поля. Для полей с типом «boolean» принимаются значения «true» или «false». Значения полей составных типов вводятся с использованием функции «cast». Например, cast(guid'd341d2be-b3b1-11dc-a100-0011d85708ff', 'Catalog_СтатьиДвиженияДенежныхСредств'). Предусмотрен графический инструмент ввода значений полей составных типов.

  5. Ввоз значения составного типа

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

  6. Комментарий — произвольный комментарий к фильтру. Например, расшифровка значения с типом GUID.

После окончания настройки набора данных нажмите кнопку «Загрузить» и проверьте результат выполнения запроса к сервису OData.

Окно набора данных

Сформированный URL-адрес ресурса выводится в области вывода сообщений в главном окне программы.


2.4 Использование параметров

Параметры могут применяться:

  • в теле скрипта
  • в полях на панели «Настроек и параметров» окна набора данных
  • в колонке «Значение» на панелях «Отбора» окна набора данных
  • в теле HTTP-шаблона ресурса

Имена параметров в теле скрипта и в полях окна набора данных должны начинаться с символа «&». Например, &periodBegin.

В теле HTTP-шаблона имена параметров указываются в соответствии с синтаксисом шаблонизатора FreeMarker. Например, ${periodBegin}

Значения параметров вводятся на панели «Параметры» формы скрипта R.

Список параметров скрипта

При нажатии на кнопку «Дозаполнить параметры» в таблицу будут добавлены параметры, для которых ещё не введены значения (и удалены отсутствующие параметры).

Если установить галочку «Доступно в запросе», то данный параметр будет включен в параметры HTTP-запроса, и клиент веб-приложения сможет изменять значение параметра.

Пространство имён параметров общее для всех наборов данных одного и того же скрипта.

Предопределенные параметры:

name
наименование скрипта
description
описание скрипта
resourceName
имя ресурса HTTP
requestId
идентификатор запроса к ресурсу HTTP, генерируется случайным образом

3. Публикация отчетов

3.1 Загрузка модели на сервер

Моделью называется совокупность всех скриптов в DataReducer. После создания модели в DataReducer Console её можно загрузить на сервер для публикации результатов выполнения скриптов в веб.

Для загрузки модели на сервер в главном меню программы выберите «Файл → Загрузить модель на сервер». Модель на сервере будет заменена новой моделью без возможности восстановления. Перезагрузка сервера для инициализации новой модели не требуется.

Аналогично в DataReducer Console можно получить модель с сервера. Для этого в главном меню выберите «Файл → Получить модель с сервера».

Для каждого скрипта в DataReducer Console указываются настройки веб-доступа. Веб-ресурс, соответствующий скрипту, становится доступен только при установленном флаге «Веб-доступ». Также можно изменить имя ресурса.


3.2 Обращение к ресурсам

Все скрипты, на вкладке «Веб-доступ» которых установлен соответствующий флаг, выводятся в списке ресурсов на главной странице веб-приложения (при наличии у пользователя прав на их просмотр).

Обращение к ресурсам осуществляется по их именам, заданным в DataReducer Console. Например, http://localhost:8080/rapport/analysis1

Если скрипт содержит параметры (см. раздел 2.4), их значения можно передать в запросе. Например, http://localhost:8080/rapport/analysis1?periodBegin=2017-01-01T00:00:00&periodEnd=2017-03-31T23:59:59

Данные ресурса можно получить в трёх различных форматах: HTML, XML или JSON. По умолчанию данные возвращаются в формате HTML. Для получения XML или JSON соответствующий тип содержимого нужно указать в заголовке «Accept» запроса.


3.3 Шаблон вывода данных ресурса

При получении данных ресурса в формате HTML выводится только название, описание скрипта и таблица данных. Шаблон страницы ресурса, используемый по умолчанию, можно изменить. Для этого нужно снять галочку «Шаблон по умолчанию» в DataReducer Console.

Веб-приложение использует шаблонизатор FreeMarker.

В теле шаблона можно использовать параметры скрипта R (см. раздел 2.4) в соответствии с синтаксисом FreeMarker. Например,

Период: с ${periodBegin?keep_before('T')} по ${periodEnd?keep_before('T')}

, где periodBegin и periodEnd — это имена параметров скрипта R. В данном примере на странице будут выведены даты начала и конца периода с отброшенным временем. О синтаксисе FreeMarker можно прочесть в официальной документации шаблонизатора.


3.4 Публикация изображений и других файлов

Созданные в R файлы, предназначенные для публикации, сохраняйте в каталоге /mnt/webapp-files , соответствующем каталогу файлов веб-приложения.

Внутри этого каталога рекомендуется создавать подкаталоги /mnt/webapp-files/&resourceName/&requestId для того чтобы разграничить файлы разных ресурсов и запросов (см. п.п. 2.4, 4.1).

На эти каталоги должны быть установлены права доступа (см. п. 3.5).


3.5 Разграничение доступа к ресурсам

Для каждого ресурса можно указать роли пользователей, которые должны иметь к нему доступ. Список ролей находится на вкладке «Веб-доступ» программы DataReducer Console. Перед использованием роли она должна быть определена в конфигурации Apache Tomcat.

Процедура добавления новой роли:

1. Отредактируйте файл конфигурации tomcat-users.xml:

<?xml version="1.0" encoding="UTF-8"?>

<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">

  <role rolename="DataReducerAdministrator"/>
  <role rolename="FinanceDirector"/>

  <user username="admin" password="admin" roles="DataReducerAdministrator"/>
  <user username="ivanov" password="123456" roles="FinanceDirector"/>

</tomcat-users>

2. Добавьте информацию о новой роли в файл web.xml. Роли доступа к ресурсу назначаются в программе DataReducer Console, но если скрипт генерирует файлы, к которым будет открыт доступ по сети (например, изображения), права на них должны быть установлены отдельно:

<?xml version="1.0" encoding="UTF-8"?>
...
     <security-constraint>
        <web-resource-collection>
            <web-resource-name>Список ресурсов</web-resource-name>
            <description>Должен быть доступен всем авторизованным пользователям.</description>
            <url-pattern>/</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>DataReducerAdministrator</role-name>
            <role-name>FinanceDirector</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Каталог файлов</web-resource-name>
            <url-pattern>/files/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>DataReducerAdministrator</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Файлы отчета по анализу поступлений</web-resource-name>
            <url-pattern>/files/analysis1/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>DataReducerAdministrator</role-name>
            <role-name>FinanceDirector</role-name>
        </auth-constraint>
    </security-constraint>
...
    <security-role>
        <description>Финансовый директор</description>
        <role-name>FinanceDirector</role-name>
    </security-role>
    
</web-app>

3. Обновите файл конфигурации tomcat-users.xml сервиса rapport с помощью следующих команд:

$ docker secret create datareducer_rapport_users_v2 ./tomcat-users.xml

$ docker service update \
--secret-rm datareducer_rapport_users \
--secret-add source=rapport_users_v2,target=/usr/local/tomcat/conf/tomcat-users.xml,uid=1000,gid=1000,mode=0440 \
datareducer_rapport

4. Обновите файл конфигурации web.xml сервиса rapport с помощью следующих команд:

$ docker config create datareducer_rapport_web_v2 ./web.xml

$ docker service update \
--config-rm datareducer_rapport_web \
--config-add source=datareducer_rapport_web_v2,target=/usr/local/tomcat/webapps/rapport/WEB-INF/web.xml,uid=1000,gid=1000,mode=0440 \
datareducer_rapport

$ docker config rm datareducer_rapport_web

Пользователю с ролью «DataReducerAdministrator» доступны все ресурсы.

Более подробно о механизмах аутентификации контейнера Apache Tomcat читайте в его документации.

4. Примеры использования DataReducer

4.1 Пример 1: Консолидация данных из разных источников

Требуется выполнить план-фактный анализ поступлений денежных средств компании за квартал. Компания состоит из двух юридических лиц — организаций «УноФарма» и «ПортоФарма». Бухгалтерский учёт организаций ведётся в двух разных информационных базах «1С:Бухгалтерия предприятия 3.0».

Отчет Факт УноФарма Отчет Факт ПортоФарма

Запланированные значения поступлений необходимо получить из таблицы Excel, в которой отражены суммарные данные по всем организациям.

Отчет План

Шаги решения поставленной задачи в программе «DataReducer Console»

  1. Добавляем настройки подключения к информационным базам «УноФарма» и «ПортоФарма». Интерфейс OData этих баз предварительно должен быть опубликован на веб-сервере и настроен в соответствии с документацией платформы «1С:Предприятие» (см. п. 1.3). В DataReducer можно одновременно работать с данными любого количества информационных баз. Список подключенных баз отображается в главном окне программы (см. п. 2.2).
  2. После подключения информационной базы, DataReducer Console выводит дерево её метаданных. Дерево метаданных включает все сущности, доступные через интерфейс OData (справочники, регистры, виртуальные таблицы и пр.). Для свойств сущностей выводится их тип. Для свойств с ссылочным типом выводится связанная сущность.
  3. Создаём новый скрипт R и открываем его. Каждый скрипт открывается в отдельной вкладке.
  4. Находим в дереве метаданных информационной базы «УноФарма» виртуальную таблицу оборотов регистра бухгалтерии «Хозрасчётный» и через контекстное меню добавляем её в наборы данных скрипта R. Повторяем для информационной базы «ПортоФарма». Любой набор данных можно открыть в отдельном окне и загрузить данные для просмотра.
  5. Поочерёдно открываем окна созданных наборов данных и вводим настройки запросов. Перечень доступных настроек зависит от типа объекта, которому соответствует набор данных. Начало и конец периода получения оборотов регистра бухгалтерии «Хозрасчетный» задаём в виде параметров «&periodBegin» и «&periodEnd». Значения этих параметров будут общими для всех наборов данных скрипта R (см. п. 2.4).
  6. Пишем код на языке R (см. листинг). Обращение к наборам данных осуществляется по их именам.
  7. Выполняем скрипт. На экран выводятся сообщения о ходе выполнения, в том числе сформированные запросы REST-сервису «1С:Предприятия». В области вывода графики выводится построенная диаграмма. Результаты выполнения скрипта (таблицу данных и диаграмму) можно сохранить в файлы, используя методы языка R (см. п. 5).

Листинг примера 1:

001  # Обрабатываем данные информационной базы ООО "УноФарма".
002  
003  # Создаём таблицу данных, выбирая нужные нам поля набора данных "AccountingRegister_Хозрасчетный_Turnover1" 
004  # (соответствующего виртуальной таблице оборотов регистра бухгалтерии "Хозрасчетный").
005  
006  ib1 <- AccountingRegister_Хозрасчетный_Turnover1[c('ExtDimension1____Presentation',
007           'ExtDimension1_Type', 'ExtDimension2____Presentation', 'ExtDimension2_Type', 'СуммаTurnoverDr')]
008  
009  # Статья движения д/с может быть записана в разные реквизиты - Субконто1 или Субконто2.
010  # Разбиваем данные на два набора, соответствующих первому и второму случаю.
011  # Затем, объединяя эти наборы, получаем таблицу данных с отдельным столбцом статей движения д/с.
012  
013  ib1_1 <- subset(ib1, ib1$ExtDimension1_Type == 'StandardODATA.Catalog_СтатьиДвиженияДенежныхСредств',
014           select=c(ExtDimension1____Presentation, СуммаTurnoverDr))
015  
016  ib1_2 <- subset(ib1, ib1$ExtDimension2_Type == 'StandardODATA.Catalog_СтатьиДвиженияДенежныхСредств',
017           select=c(ExtDimension2____Presentation, СуммаTurnoverDr))
018  
019  fact1 <- merge(ib1_1, ib1_2, by.x=c('ExtDimension1____Presentation', 'СуммаTurnoverDr'),
020           by.y=c('ExtDimension2____Presentation', 'СуммаTurnoverDr'), all = TRUE)
021  
022  # Выполняем те же операции для информационной базы ООО "ПортоФарма".
023  
024  ib2 <- AccountingRegister_Хозрасчетный_Turnover2[c('ExtDimension1____Presentation',
025           'ExtDimension1_Type', 'ExtDimension2____Presentation', 'ExtDimension2_Type', 'СуммаTurnoverDr')]
026  
027  ib2_1 <- subset(ib2, ib2$ExtDimension1_Type == 'StandardODATA.Catalog_СтатьиДвиженияДенежныхСредств',
028           select=c(ExtDimension1____Presentation, СуммаTurnoverDr))
029  
030  ib2_2 <- subset(ib2, ib2$ExtDimension2_Type == 'StandardODATA.Catalog_СтатьиДвиженияДенежныхСредств',
031           select=c(ExtDimension2____Presentation, СуммаTurnoverDr))
032  
033  fact2 <- merge(ib2_1, ib2_2, by.x=c('ExtDimension1____Presentation', 'СуммаTurnoverDr'),
034           by.y=c('ExtDimension2____Presentation', 'СуммаTurnoverDr'), all = TRUE)
035  
036  # Объединяем данные двух информационных баз и суммируем значения поступлений по статьям.
037  
038  fact <- merge(fact1, fact2, , all=TRUE)
039  
040  if (nrow(fact) > 0) fact <- aggregate(fact[, 2], by=list(fact[, 1]), sum)
041  
042  # Переименовываем столбцы.
043  
044  names(fact)[1] <- 'СтатьяДДС'
045  names(fact)[2] <- 'Факт'
046  
047  # Считываем фактические данные поступлений д/с из файла Excel.
048  # Файл расположен в каталоге, примонтированном к Docker-контейнеру сервиса Rserve в точке /mnt/host.
049  
050  library(xlsx)
051  plan <- read.xlsx('/mnt/host/План_1кв.xlsx', 1)
052  
053  # Объединяем таблицы плановых и фактических данных.
054  
055  pf <- merge(plan, fact, by=1, all=TRUE)
056  
057  # Рассчитываем абсолютные и относительные отклонения фактических значений от плановых
058  # и помещаем результаты в новые колонки.
059  
060  pf$ОтклонениеАбс <-  pf$Факт - pf$План
061  pf$ОтклонениеОтн <-  round((pf$Факт - pf$План) / pf$Факт, digits = 2)
062  
063  # Подготавливаем данные для построения диаграммы.
064  
065  # Приводим таблицу данных к нужному формату 
066  # (функция melt() преобразует данные в такой формат, что переменные "План" и "Факт"
067  # располагаются в собственных строках вместе с переменными "СтатьяДДС", их идентифицирующими.
068  
069  library(reshape2)
070  names(pf)[1] <- 'СтатьяДДС'
071  pf.m <- melt(pf[,1:3], id.var='СтатьяДДС')
072  
073  # Для экономии места на диаграмме разбиваем названия статей по словам.
074  
075  pf.m$СтатьяДДС <- gsub("\\s","\n", pf.m$СтатьяДДС)
076  
077  # Стоим столбчатую диаграмму. Указываем вид диаграммы - с группировкой, 
078  # горизонтальное расположение и размер шрифта.
079  
080  library(ggplot2)
081  chart <- ggplot(pf.m, aes(x = СтатьяДДС, y = value, fill = variable)) + geom_bar(stat='identity', position = 'dodge') +
082          coord_flip() + theme(text = element_text(size=13))
083  
084  # Устанавливаем шрифт, используемый в диаграмме.
085  # Шрифт должен быть установлен в системе (в Docker-контейнере сервиса Rserve)
086  
087  CairoFonts(regular='Free Helvetian:style=Regular')
088  
089  # Выводим диаграмму на экран.
090  
091  print(chart)
092  dev.off()
093  
094  # Создаем каталог для хранения файлов в точке монтирования /mnt/webapp-files,
095  # соответствующей каталогу файлов веб-приложения.
096  
097  resourceDir <- '/mnt/host/&resourceName'
098  requestDir <- paste(resourceDir, '&requestId', sep='/')
099  dir.create(resourceDir)
100  dir.create(requestDir)
101  
102  # Записываем диаграмму в файл.
103  
104  chartFile <- paste(requestDir, 'chart.png', sep='/')
105  CairoPNG(chartFile, width =520, height=360)
106  print(chart)
107  dev.off()
108  
109  # Записываем таблицу данных в файл Excel.
110  
111  xlsxFile <- paste(requestDir, 'ПланФакт.xlsx', sep='/')
112  write.xlsx(pf, xlsxFile, row.names = FALSE)
113  
114  # Выводим таблицу данных.
115  pf

Результат

На данном примере были продемонстрированы основные инструменты программы «DataReducer Console» для импорта данных информационных баз «1С:Предприятия» и некоторые методы языка R для обработки этих данных. Были получены и агрегированы данные из трёх разных источников: двух информационных баз «1С: Бухгалтерия предприятия 3.0» и файла Excel. С помощью пакета ggplot2 была построена столбчатая диаграмма, отображающая отклонения фактических значений показателей от плановых.

Диаграмма

Теперь опубликуем веб-отчет, содержащий результаты анализа.

В строке №97 листинга скрипта изменяем каталог сохранения файлов на /mnt/webapp-files , соответствующий каталогу файлов веб-приложения (см. п. 1.4).

На вкладке «Веб-доступ» скрипта ставим галочку «Веб-доступ». При необходимости на этой вкладке можно изменить имя веб-ресурса и определить роли доступа.

В главном меню программы выбираем «Файл → Загрузить модель на сервер». Список ресурсов модели, к которым открыт веб-доступ, появится на главной странице веб-приложения:


Страница отчета с шаблоном по умолчанию:


Добавим на страницу ресурса период отчета, ссылку на скачивание данных в формате Excel и сгенерированную в R диаграмму. Для этого внесём изменения в шаблон страницы ресурса.

На вкладке «Веб-доступ» скрипта снимаем галочку «Шаблон по умолчанию». После этого шаблон страницы можно редактировать:


Добавляем в контейнер <body> следующие элементы:

<p><i>Период: с ${periodBegin?keep_before('T')} по ${periodEnd?keep_before('T')}</i></p>

<p><a href="/rapport/files/${resourceName}/${requestId}/ПланФакт.xlsx">Сохранить в Excel</a></p>

<p><img src="/rapport/files/${resourceName}/${requestId}/chart.png" class="img-responsive"></p>

После повторной загрузки модели на сервер мы увидим новую страницу ресурса:


4.2 Пример 2: Статистические функции языка R и HTML-виджеты

Основное назначение языка R – статистические вычисления. Если перед вами стоит задача статистического анализа данных «1С:Предприятия», то лучшего инструмента, чем R не найти.

В данном примере мы попробуем предсказать значение показателя прибыли от продаж по значениям показателей дебиторской и кредиторской задолженностей с помощью линейной регрессии.

Также мы построим интерактивный график, на который выведем как известные, так и прогнозные значения показателей. График будет иметь формат HTML и может быть опубликован в веб-отчете DataReducer.

Для построения регрессионной модели воспользуемся данными учета компании за 16 предыдущих кварталов. Эти данные мы получим из информационной базы «1С:ERP Управление предприятием 2».

Введём обозначения переменных и определим источники данных.

prib — Прибыль от продаж (зависимая переменная)

Прибыль от продаж = Выручка от продаж - Себестоимость продаж - Коммерческие и управленческие расходы

Источники данных: обороты регистров накопления «Выручка и себестоимость продаж» и «Прочие расходы».

deb — Дебиторская задолженность (независимая переменная)

Источники данных: остатки регистра накопления «Расчеты с клиентами по документам».

kred — Кредиторская задолженность (независимая переменная)

Источники данных: остатки регистра накопления «Расчеты с поставщиками по документам».

Таким образом, каждому кварталу будет соответствовать четыре набора данных по числу запросов к регистрам информационной базы. Необходимо получить данные по 16-ти периодам, значит, всего будет выполнено 64 запроса.

Формируем наборы данных, используя дерево метаданных информационной базы и конструкторы запросов.

Наборы данных

Наблюдение по каждому кварталу и итоговую таблицу данных для анализа создаём следующим образом:

001  # Получаем значения показателей для каждого квартала
002  Q1_2014 <- data.frame(
003          period = "&Q1_2014_end",
004          prib   = Q1_2014_ВыручкаИСебестоимость[1, c("СуммаВыручкиTurnover")] -
005                   Q1_2014_ВыручкаИСебестоимость[1, c("СтоимостьTurnover")] -
006                   Q1_2014_ПрочиеРасходы[1, c("СуммаTurnover")],
007          deb    = Q1_2014_РасчетыСКлиентами[1, c("ДолгBalance")],
008          kred   = abs(Q1_2014_РасчетыСПоставщиками[1, c("ДолгBalance")])
009  )
010  Q2_2014 <- data.frame(
011          period = "&Q2_2014_end",
012          prib   = Q2_2014_ВыручкаИСебестоимость[1, c("СуммаВыручкиTurnover")] -
013                   Q2_2014_ВыручкаИСебестоимость[1, c("СтоимостьTurnover")] -
014                   Q2_2014_ПрочиеРасходы[1, c("СуммаTurnover")],
015          deb    = Q2_2014_РасчетыСКлиентами[1, c("ДолгBalance")],
016          kred   = abs(Q2_2014_РасчетыСПоставщиками[1, c("ДолгBalance")])
017  )

(...)

131 # Объединяем все наблюдения в одну таблицу 132 df <- rbind(Q1_2014, Q2_2014, Q3_2014, Q4_2014, Q1_2015, Q2_2015, Q3_2015, Q4_2015, 133 Q1_2016, Q2_2016, Q3_2016, Q4_2016, Q1_2017, Q2_2017, Q3_2017, Q4_2017)

«Q1_2014_ВыручкаИСебестоимость», «Q1_2014_ПрочиеРасходы» и пр. - это имена, которые мы дали наборам данных, соответствующим виртуальным таблицам регистров накопления. «СуммаВыручкиTurnover», «СтоимостьTurnover» и пр. - имена полей этих таблиц, формируемые платформой 1С. Периоды задаем в виде параметров (см. п. 2.4).

Смотрим полученную таблицу данных:

Таблица данных

Создадим интерактивный график изменения показателей по кварталам. Для этого воспользуемся пакетом «dygraphs», предоставляющем R-программисту возможности одноименной JavaScript-библиотеки:

135  # Приводим данные к формату xts
136  library(xts)
137  data_xts <- xts(df[,-1], order.by=as.POSIXct(df[,1]))
138  
139  # Строим график
140  library(dygraphs)
141  graph <- dygraph(data_xts, width=750, height=350) %>%
142      dySeries("prib", label = "Прибыль") %>%
143      dySeries("deb", label = "Деб_зад") %>%
144      dySeries("kred", label = "Кред_зад") %>%
145      dyOptions(drawPoints=TRUE, pointSize=2, drawAxesAtZero=TRUE, labelsKMB=TRUE) %>%
146      dyRangeSelector()
147  
148  # Сохраняем виджет с графиком 
149  library(htmlwidgets)
150  saveWidget(graph, file="/mnt/host/prib.html", selfcontained = TRUE)


Создаём линейную модель и предварительно оцениваем её:

155  model <- lm(data=df, prib~deb+kred)
156  paste(capture.output(print(summary(model))), collapse='\n')
Линейная модель

Как видно из последнего столбца таблицы, коэффициенты при переменных deb и kred статистически значимо отличаются от нуля при p < 0.01 и p < 0.001, соответственно. Это указывает на то, что и дебиторская и кредиторская задолженности влияют на показатель прибыли от продаж. Взятые вместе, они на 57% описывают изменения показателя (Multiple R-squared: 0.571).

Теперь проверим данные и посмотрим, можем ли мы нашу модель улучшить.

Для этого воспользуемся методами, реализованными в пакете car (пакет уже установлен в Docker-контейнере rserve).

Проверим, что ошибки регрессии нормально распределены (одна из предпосылок линейной регрессии, которые должны выполняться, чтобы мы могли считать модель адекватной). Выполним это графически, построив Q-Q график, или график Квантиль-Квантиль:

160  library(car)
161  qq <- qqPlot(model, labels = row.names(df), simulate = TRUE, main = "Q-Q plot")
162  print(qq)
163  dev.off()
График Квантиль-Квантиль

На графике хорошо видно, что одно из наблюдений выпадает из доверительных границ (изображенных пунктирными линиями) — это т. н. «выброс», т. е. наблюдение, которое плохо предсказывается моделью.

Удаляем «выброс» и снова оцениваем модель:

165  # Удаляем "выброс"
166  df1 <- df[-c(12),]
167  
168  # Снова оцениваем модель
169  model1 <- lm(data=df1, prib~deb+kred)
170  paste(capture.output(print(summary(model1))), collapse='\n')

Как мы видим, после удаления «выброса» значимость коэффициентов при независимых переменных увеличилась и модель в целом стала лучше соответствовать данным (Multiple R-squared: 0.793).

Проверим выполнение всех остальных предпосылок линейной регрессии при помощи функции gvlma() из пакета gvlma.

173  library(gvlma)
174  gvmodel <- gvlma(model1)
175  paste(capture.output(print(summary(gvmodel))), collapse='\n')

Воспользуемся моделью для предсказания прибыли от продаж за три последующих квартала:

177  # Создаем таблицу с плановыми данными дебиторской и кредиторской задолженностей
178  # и приводим её к формату xts
179  q1_2018_plan <- data.frame(period="2018-03-31T23:59:59", deb=&deb_plan1, kred=&kred_plan1)
180  q2_2018_plan <- data.frame(period="2018-06-30T23:59:59", deb=&deb_plan2, kred=&kred_plan2)
181  q3_2018_plan <- data.frame(period="2018-09-30T23:59:59", deb=&deb_plan3, kred=&kred_plan3)
182  plan_df <- rbind(q1_2018_plan, q2_2018_plan, q3_2018_plan)
183  plan_xts <- xts(plan_df[,-1], order.by=as.POSIXct(plan_df[,1]))
184  
185  # Предсказываем прибыль от продаж
186  predicted <- predict(model1, newdata=plan_xts, interval="prediction")

Предсказанные значения показателя, а также доверительные интервалы, выводим на интерактивный график:

191  # Объединяем все наборы данных
192  combined <- cbind(data_xts, plan_xts, predicted)
193  
194  # Строим новый график
195  graph1 <- dygraph(combined, width=750, height=350) %>%
196      dySeries("prib", label = "Прибыль", color="red") %>%
197      dySeries("deb", label = "Деб_зад", color = "blue") %>%
198      dySeries("kred", label = "Кред_зад", color = "green") %>%
199      dySeries("deb.1", label = "Деб_зад_план", color = "blue", strokePattern="dashed") %>%
200      dySeries("kred.1", label = "Кред_зад_план", color = "green", strokePattern="dashed") %>%
201      dySeries(c("lwr", "fit", "upr"), label = "Прибыль_прогноз", color = "red", strokePattern="dashed") %>%
202      dyEvent("2018-03-31", "Прогноз", labelLoc = "bottom", color="red", strokePattern="dotted") %>%
203      dyLegend(width = 300) %>%
204      dyOptions(drawPoints=TRUE, pointSize=2, drawAxesAtZero=TRUE, labelsKMB=TRUE) %>%
205      dyRangeSelector()
206  
207  # Создаем каталог для хранения файлов в точке монтирования /mnt/webapp-files,
208  # соответствующей каталогу файлов веб-приложения.
209  resourceDir <- '/mnt/webapp-files/&resourceName'
210  requestDir <- paste(resourceDir, '&requestId', sep='/')
211  dir.create(resourceDir)
212  dir.create(requestDir)
213  
214  # Сохраняем виджет с новым графиком в каталоге для публикации
215  graphPath <- paste(requestDir, 'prib_predicted.html', sep='/')
216  saveWidget(graph1, file=graphPath, selfcontained = TRUE)



Подробнее о методах, используемых в данном примере:

  • Лысенко М.В., Лысенко Ю.В., Якушев А.А., Согрина Н.С. «Cтатистический анализ дебиторской и кредиторской задолженности при оперативном прогнозировании прибыли от продаж» // Фундаментальные исследования. – 2016. – № 12-4. – С. 884-890
  • Цикл видео-лекций Демешева Б.Б. по курсу Эконометрики
  • Кабаков Р.И. «R в действии. Анализ и визуализация данных в программе R» / пер. с англ. Полины А. Волковой. – М.: ДМК Пресс, 2014. – 588 с.: ил.

5. Конструкции языка R для выполнения типовых задач

Вывод результата выполнения скрипта (таблицы данных)

DataReducer Console выводит в главном окне программы ту таблицу данных, идентификатор которой является последним оператором скрипта R. Эта же таблица выводится на веб-странице соответствующего ресурса (при использовании шаблона по умолчанию).

Вывод текстовой информации

Если вместо таблицы данных требуется вывести форматированный текст (например, описание линейной модели), нужно воспользоваться функцией capture.output(). Например, вместо summary(model) следует ввести:

paste(capture.output(print(summary(model))), collapse='\n')

Чтение файлов Excel

Docker-образ datareducer/rserve содержит пакет xlsx для работы с таблицами Excel. Для чтения файла Excel воспользуйтесь функцией read.xlsx(). Например,

library(xlsx)
plan <- read.xlsx('/home/docker/План_1кв.xlsx', 1)

Первый аргумент функции в примере — путь к файлу в каталоге /mnt/host Docker-контейнера (см. п. 1.4). Второй аргумент — индекс листа.

Запись в файл Excel

Для записи таблицы данных в файл Excel воспользуйтесь функцией write.xlsx(). Например,

library(xlsx)
write.xlsx(pf, '/home/docker/ПланФакт.xlsx', row.names = FALSE)

Вывод диаграммы на экран

Для работы с графикой используется пакет Cairo. Для вывода диаграммы на экран после функции print() введите dev.off(). Также рекомендуется указать используемый в диаграмме шрифт:

CairoFonts(regular='Free Helvetian:style=Regular')
print(chart)
dev.off()

Ширина и высота диаграммы вводится в соответствующих полях области вывода графики главного окна программы.

Запись диаграммы в файл

Для этого воспользуйтесь функцией CairoPNG(), после которой, так же как и для вывода графики на экран, нужно ввести print() и dev.off():

CairoPNG('/home/docker/chart.png', width=520, height=360)
print(chart)
dev.off()

Ширина и высота диаграммы в этом случае вводятся в качестве аргументов функции CairoPNG().