В 1С:Документообороте достаточно мощный инструментарий для параметрических настроек как по видам документов, так и по шаблонам процессов. Однако бывают ситуации, когда необходимо расширить возможности типовой конфигурации 1С:Документооборот, но при этом не хочется снимать конфигурацию с поддержки.
Для этих задач может хорошо подойти механизм бизнес-событий.
Бизнес-событие – это отражение факта, что произошло некоторое важное для организации событие, которое подтверждено изменением данных в информационной базе. И к таким событиям можно привязать обработчики на встроенном языке 1С.
Использование бизнес-событий в 1С:Документооборот в клиент-серверном варианте на живых примерах подробно рассмотрена в видеокурсе.
Приведем пример бизнес-событий: входящему документу присвоен регистрационный номер. С точки зрения организации это означает, что документ полностью зарегистрирован и готов для дальнейшей работы.
В конфигурации уже предусмотрены готовые бизнес-события, они формируются автоматически и используются для разных механизмов (например, по видам событий «Создание задачи» и «Выполнение задачи» могут быть настроены автоматические уведомления).
Для готовых видов бизнес-событий можно создать свои обработчики этих стандартных событий, чтобы расширить функционал системы.
А также можно создать свои собственные бизнес-события и привязать к ним обработчики событий.
Бизнес-события состоят из нескольких частей:
- детекторы событий (типовые и пользовательские),
- реестр произошедших событий,
- обработчики событий (типовые и пользовательские).
Детекторы используются для того, чтобы обнаруживать события. Как только детектор «сработал», записывается новое бизнес-событие. Затем новое бизнес-событие в соответствии с подписками на него будет обработано специальными обработчиками.Обработка одного события происходит в границах одной транзакции. После успешной обработки событие получает статус Задание выполнено. Если событие обработано с ошибками, программа предпримет попытку обработать его несколько раз, а затем удалит, если исправить эту ошибку окажется невозможным.
Если хоть один обработчик событий завершит свою операцию с ошибкой, то обработка всех событий и все действия других обработчиков будут отменены. Во всех случаях информация о результатах обработки будет записана в журнал регистрации.
По необработанным событиям будет произведена попытка выполнения обработчиков 3 раза. Необработанные бизнес-события будут храниться в регистре сведений «Произошедшие бизнес-события», чтобы администратор мог разобраться с причинами ошибок и устранить их. Обработанные бизнес-события будут храниться определенное кол-во дней (указывается в настройках программы), а потом будут удалены.
Чтобы включить механизм бизнес-событий нужно в настройках программы активировать настройку «Использовать бизнес-события».
Далее можно использовать типовые бизнес-события такие, как:
- Возобновление процесса
- Добавление в категорию
- Завершение процесса
- Задача выполнена
- Захват файла для редактирования
- Изменение брони
- Изменение внутреннего документа
- Изменение входящего документа
- Изменение значения показателя процесса
- Изменение исходящего документа
- Изменение мероприятия
- Изменение отсутствия
- Изменение проекта
- Изменение проектной задачи
- Изменение состава комплекта
- Изменение файла
- Назначение ответственным за документ
- Освобождение файла
- Остановка процесса
- Отмена выполнения задачи
- Перенаправление задачи
- Перерегистрация внутреннего документа
- Перерегистрация входящего документа
- Перерегистрация исходящего документа
- Подошел срок задачи
- Получение входящего письма
- Прерывание процесса
- Просрочена задача
- Регистрация внутреннего документа
- Регистрация входящего документа
- Регистрация исходящего документа
- Создание брони
- Создание внутреннего документа
- Создание входящего документа
- Создание задачи
- Создание исходящего документа
- Создание контрагента
- Создание мероприятия
- Создание отсутствия
- Создание проекта
- Создание проектной задачи
- Создание сообщения
- Создание файла
- Старт процесса
Кроме типовых бизнес-событий в системе можно добавлять свои события. Для этого необходимо сделать следующее:
- В справочнике «Виды бизнес-событий» добавить новое бизнес-событие.
- Создать детектор для этого события. У детектора установить флаг «Детектор включен».
- Создать дополнительный обработчик. Установить у обработчика флаг «Обработчик включен». Настроить у обработчика подписку на событие.
Рассмотрим самый простой вариант привязки типового обработчика к типовому событию.
Открываем шаблон процесса. Переходим на форму назначения видам документов.
На закладке «Автоматический запуск» указываем событие «Создание внутреннего документа».
Создадим новый документ. Открываем регистр сведений «Произошедшие бизнес-события». Видим, что наше событие пока не обработано.
После обработки события данный справочник будет выглядеть следующим образом. Видим, что по внутреннего документу был запущен комплексный процесс.
Рассмотрим теперь более сложный случай привязки типового события к своему обработчику.
Открываем в разделе «Настройка и администрирование» справочник «Дополнительные обработчики».
Создаем новый обработчик бизнес-события. Заполняем его наименование, описание и код обработки события. Устанавливаем флаг «Обработчик включен».
Указываем подписку для данного обработчика.
Теперь при создании нового внутреннего документа у нас будет не только запускаться комплексный процесс по шаблону, но и производиться его дополнительная обработка.
Поскольку к одному событию теперь привязано два обработчика, то возникает вопрос: в каком порядке будут выполняться обработчики? Порядок вызова обработчиков не определен, поэтому нужно при использовании нескольких обработчиков предусматривать все возможные порядки запуска.
Использование бизнес-событий в 1С:Документооборот в клиент-серверном варианте на живых примерах подробно рассмотрена в видеокурсе.
Бизнес-события
Как сделать, чтобы по документу при наступлении определенного условия автоматически стартовал процесс.
В системе 1С: Документооборот существует понятие бизнес-событий (событий произошедших в программе). Для того чтобы можно было использовать этот механизм, необходимо его включить в настройках программы:
Для классификации таких событий есть специальный справочник «Виды бизнес событий» (сами же события система записывает в регистр сведений «Произошедшие бизнес-события»). Также важными частями механизма бизнес-событий являются детекторы бизнес-событий и обработчики бизнес-событий, но о них ниже.
Рассмотрим пример – нужно автоматически отправлять в обработку все зарегистрированные служебные записки, файлы которых сотрудники подписали электронной подписью. Тогда условием будет – документ зарегистрирован, файл документа подписан электронной подписью, и по данному документу нет комплексного процесса «Обработка записки».
Создадим вид для бизнес-события, которое будет формироваться при наступлении данного условия.
Теперь нужно добавить «Детектор бизнес-события». Детектор бизнес-события — это как раз та часть механизма, которая отслеживает выполнение условия и создает соответствующее событие в системе.
Добавим новый детектор в справочнике «Детекторы бизнес-событий». В его карточке укажем вид бизнес-события, который создали ранее. В поле «Выражение на встроенном языке» необходимо написать код, который проверяет, есть ли хотя бы один объект, для которого условие истинно. Если есть, то переменной «Результат» нужно присвоить значение Истина. В этом случае система создаст бизнес-событие с указанным видом.
ВАЖНО: Если не установлен флаг «Детектор включен», код детектора исполняться не будет!
В нашем случае нужен запрос, который проверяет, что есть документы с выполненным условием (к документу приложен файл, подписанный электронной подписью и по этому документу нет процессов обработки). Если такие документы есть — значит наше событие произошло. Таким образом событие будет сгенерировано, когда в системе есть один или несколько документов, для которых все условия выполнились, и по ним нужно стартовать процесс.
Код детектора:
ВидыДокументов = Новый Массив;
ВидыДокументов.Добавить(Справочники.ВидыВнутреннихДокументов.НайтиПоНаименованию(«Служебная записка», Истина));
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
|ИЗ
| Справочник.ВнутренниеДокументы КАК ВнутренниеДокументы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Файлы КАК Файлы
| ПО ВнутренниеДокументы.Ссылка = Файлы.ВладелецФайла
| ЛЕВОЕ СОЕДИНЕНИЕ БизнесПроцесс.КомплексныйПроцесс.Предметы КАК КомплексныйПроцессПредметы
| ПО ВнутренниеДокументы.Ссылка = КомплексныйПроцессПредметы.Предмет
|ГДЕ
| КомплексныйПроцессПредметы.Предмет ЕСТЬ NULL
| И ВнутренниеДокументы.ВидДокумента В(&ВидыДокументов)
| И НЕ ВнутренниеДокументы.ПометкаУдаления
| И Файлы.ПодписанЭП = ИСТИНА
| И НЕ Файлы.ПометкаУдаления»;
Запрос.УстановитьПараметр(«ВидыДокументов», ВидыДокументов);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Результат = Истина;
КонецЕсли;
Выполнение детекторов и формирование событий выполняет регламентное задание «Обработка детекторов бизнес-событий». Это задание исполняется один раз в минуту и выполняет все детекторы событий с флагом Включен.
Далее необходимо выполнить обработку сформированных бизнес-событий. В нашем случае это запуск процессов по документам. Для обработки бизнес-события в программе используется справочник «Дополнительные обработчики-бизнес событий».
В нем также необходимо написать код на встроенном языке, который будет выполнять необходимые действия. В нашем случае фрагмент кода должен находить конкретные документы, для которых выполнились условия, и создавать для них процессы.
Код обработчика:
ВидыДокументов.Добавить(Справочники.ВидыВнутреннихДокументов.НайтиПоНаименованию(«Служебная записка», Истина));
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| ВнутренниеДокументы.Ссылка
|ИЗ
| Справочник.ВнутренниеДокументы КАК ВнутренниеДокументы
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Файлы КАК Файлы
| ПО ВнутренниеДокументы.Ссылка = Файлы.ВладелецФайла
| ЛЕВОЕ СОЕДИНЕНИЕ БизнесПроцесс.КомплексныйПроцесс.Предметы КАК КомплексныйПроцессПредметы
| ПО ВнутренниеДокументы.Ссылка = КомплексныйПроцессПредметы.Предмет
|ГДЕ
| КомплексныйПроцессПредметы.Предмет ЕСТЬ NULL
| И ВнутренниеДокументы.ВидДокумента В(&ВидыДокументов)
| И НЕ ВнутренниеДокументы.ПометкаУдаления
| И Файлы.ПодписанЭП = ИСТИНА
| И НЕ Файлы.ПометкаУдаления»;
Запрос.УстановитьПараметр(«ВидыДокументов», ВидыДокументов);
РезультатЗапроса = Запрос.Выполнить();
Если Не РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
ШаблонПроцесса = Справочники.ШаблоныКомплексныхБизнесПроцессов.НайтиПоНаименованию(«Обработка записок», Истина);
Пока Выборка.Следующий() Цикл
Документ = Выборка.Ссылка;
БизнесПроцессОбъект = БизнесПроцессы.КомплексныйПроцесс.СоздатьБизнесПроцесс();
БизнесПроцессОбъект.ЗаполнитьПоШаблонуИПредмету(ШаблонПроцесса, Документ, Документ.Подготовил);
БизнесПроцессОбъект.Записать();
Если ПолучитьФункциональнуюОпцию(«ИспользоватьФоновыйСтартПроцессов») Тогда
РегистрыСведений.ПроцессыДляЗапуска.ДобавитьПроцессДляФоновогоСтарта(БизнесПроцессОбъект.Ссылка);
Иначе
БизнесПроцессОбъект.Старт();
КонецЕсли;
КонецЦикла;
КонецЕсли;
Обработчик бизнес-события и бизнес-событие необходимо связать между собой при помощи команды Подписки
в панели навигации обработчика. В открывшемся списке нужно нажать Создать и указать ссылку на созданный ранее вид бизнес-события.
После этого необходимо проверить работу детектора и обработчика, если код написан без ошибок — новые события будут появляться и обрабатываться встроенным механизмом.
Отлаживать же механизм можно частями — проконтролировать появление новых событий можно, открыв регистр сведений «Произошедшие бизнес события» (все события механизм запишет сюда), срабатывание обработчика можно увидеть тут-же по появлению флага «Обработано», а саму правильность кода обработчика — по появлению запланированного результата (в нашем примерe — создан процесс по документу).
<?php // Полная загрузка сервисных книжек, создан 2023-01-05 12:44:55
global $wpdb2;
global $failure;
global $file_hist;
///// echo '<H2><b>Старт загрузки</b></H2><br>';
$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
///// echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}
$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
///// echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}
/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
///// echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
///// echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist); ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7]; ////получаем размер файла
$m_mtime_file=$masiv_data_file[9]; ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file
///// echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
///// echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
///// echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);
if ($results)
{ foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));
////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
///// echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
///// echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}
////загружаем данные
$table='vin_history'; // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация // (путь от корня web-сервера)
$delim=';'; // Разделитель полей в CSV файле
$enclosed='"'; // Кавычки для содержимого полей
$escaped='
Related Posts
Получение логина и пароля техподдержки 1С из базы
Класс для вывода отчета в Excel
Счет-фактура для УПП
Библиотека классов для создания внешней компоненты 1С на C#
Акт об оказании услуг (со скидками) — внешняя печатная форма для Управление торговлей 11.1.10.86
Прайс-лист с артикулом в отдельной колонке
1 Comment
-
А как сделать в обратку? Например, исполнитель запросил перенос сроков. В процессе срок поменялся, а в документе остался прежний срок.
Reply ↓
Leave a Comment
Ваш адрес email не будет опубликован. Обязательные поля помечены *
Перейти к основному содержанию
Автоматическое создание входящего документа из исходящего в 1С Документооборот
Статья описывает подход к автоматизации создания и регистрации входящих документов при регистрации исходящих при взаимодействии в системе 1С Документооборот двух организаций. Статья даёт ответы на следующие вопросы:
- Как запрограммировать и настроить дополнительные обработчики бизнес-событий?
- Как автоматизировать взаимодействие двух организаций в 1С Документооборот при обмене корреспонденцией?
- Как программно создавать входящие документы?
- Как копировать файлы из одного документа в другой?
- Как программно регистрировать документы?
Цель – исключить ручное заведение входящих документов при отправке исходящего документа между организациями, работающими в системе.
Для создания нового обработчика необходимо войти в меню Настройка и администрирование – Дополнительные обработчики, создать новый дополнительный обработчик бизнес-события и назвать его «автосоздание_входящих».
Далее необходимо заполнить код обработчика и выбрать ответственного.
// ИНН первой организации (организация 1)
ИНН1 = "1111111111";
// ИНН второй организации (организация 2)
ИНН2 = "2222222222";
// Предполагается, что для каждой организации используется свой вид входящего документа
// Название вида входящего документа для Организации 1
НазваниеВидаВходящего1="Входящий Организация 1";
// Название вида входящего документа для Организации 2
НазваниеВидаВходящего2="Входящий Организация 2";
// проверка исходящего на предмет взаимодействия Организации 1 и Организации 2
ПроверкаПрошла = Истина;
Исходящий = Событие.Источник;
Если Не (Исходящий.Организация.ИНН = ИНН1 Или Исходящий.Организация.ИНН = ИНН2) Тогда
ПроверкаПрошла = Ложь;
КонецЕсли;
Если Не (Исходящий.Получатели[0].Получатель.ИНН = ИНН1 Или
Исходящий.Получатели[0].Получатель.ИНН = ИНН2) Тогда
ПроверкаПрошла = Ложь;
КонецЕсли;
Если ПроверкаПрошла Тогда
входящий = Справочники.ВходящиеДокументы.СоздатьЭлемент();
входящий.ДатаСоздания = ТекущаяДата();
входящий.Наименование = Исходящий.Наименование;
входящий.Заголовок = Исходящий.Заголовок;
входящий.Содержание = Исходящий.Содержание;
входящий.Отправитель = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН",
Исходящий.Организация.ИНН);
входящий.Подписал =
Справочники.КонтактныеЛица.НайтиПоНаименованию(Исходящий.Подписал.Наименование,,,входящий.Отправитель);
// создавать контактное лицо, если оно не найдено
Если входящий.Подписал.Пустая() И Не Исходящий.Подписал.Пустая() Тогда
эл = Справочники.КонтактныеЛица.СоздатьЭлемент();
эл.Владелец = входящий.Отправитель;
эл.Наименование = Исходящий.Подписал.Наименование;
Попытка
эл.Записать();
Исключение
КонецПопытки;
входящий.Подписал = эл.Ссылка;
КонецЕсли;
входящий.ИсходящаяДата = Исходящий.ДатаРегистрации;
входящий.ИсходящийНомер = Исходящий.РегистрационныйНомер;
входящий.Организация = Справочники.Организации.НайтиПоРеквизиту("ИНН",
Исходящий.Получатели[0].Получатель.ИНН);
// поиск пользователя по наименованию контактного лица из исходящего документа
// предполагается, что контактные лица организаций заведены с такими же наименованиями
// как пользователи организаций
входящий.Адресат =
Справочники.Пользователи.НайтиПоНаименованию(Исходящий.Получатели[0].Адресат.Наименование);
входящий.Подразделение = входящий.Адресат.Подразделение;
входящий.СпособПолучения = Исходящий.Получатели[0].СпособОтправки;
входящий.СрокИсполнения = Исходящий.СрокИсполнения;
входящий.Проект = Исходящий.Проект;
Если входящий.Организация.ИНН=ИНН2 Тогда
входящий.ВидДокумента =
Справочники.ВидыВходящихДокументов.НайтиПоНаименованию(НазваниеВидаВходящего2);
Иначе
входящий.ВидДокумента =
Справочники.ВидыВходящихДокументов.НайтиПоНаименованию(НазваниеВидаВходящего1);
КонецЕсли;
входящий.Записать();
// автоматическая регистрация входящего документа
Нумератор = Нумерация.ПолучитьНумераторДокумента(входящий);
ВыполнятьРегистрацию = Ложь;
Если ЗначениеЗаполнено(Нумератор) Тогда
//Автоматическая регистрация возможна, входящий документ ещё не зарегистрирован.
ВыполнятьРегистрацию = Истина;
КонецЕсли;
Если ВыполнятьРегистрацию Тогда
ТекущийПользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
входящий.ДатаРегистрации = Исходящий.ДатаРегистрации;
СтруктураПараметров =
НумерацияКлиентСервер.ПолучитьПараметрыНумерации(входящий);
Нумерация.СформироватьЧисловойНомерДокумента(СтруктураПараметров, входящий.ЧисловойНомер);
ОписанияОшибок = Новый СписокЗначений;
СтруктураПараметров =
НумерацияКлиентСервер.ПолучитьПараметрыНумерации(входящий);
Нумерация.СформироватьСтроковыйНомерДокумента(СтруктураПараметров,
входящий.РегистрационныйНомер, ОписанияОшибок);
Если ЗначениеЗаполнено(входящий.РегистрационныйНомер) Тогда
// успешно сформирован номер
входящий.Зарегистрировал = ПараметрыСеанса.ТекущийПользователь;
Иначе
Объект.ДатаРегистрации = '00010101';
КонецЕсли;
Делопроизводство.ЗаписатьСостояниеДокумента(входящий.Ссылка, ТекущаяДатаСеанса(),
Перечисления.СостоянияДокументов.Зарегистрирован, ПараметрыСеанса.ТекущийПользователь);
входящий.Записать();
КонецЕсли;
// копировать файлы из источника (Исходящий) в приёмник (созданный входящий)
МассивФайлов = Новый Массив();
исх_файлы = Справочники.Файлы.Выбрать(,,Новый Структура("ВладелецФайла", Исходящий));
Пока исх_файлы.Следующий() Цикл
МассивФайлов.Добавить(исх_файлы.Ссылка);
КонецЦикла;
Если МассивФайлов.Количество()>0 Тогда
РаботаСФайламиВызовСервера.СкопироватьФайлы(МассивФайлов, входящий.Ссылка);
КонецЕсли;
КонецЕсли;
После создания обработчика на вкладке «Подписки» формы обработчика добавляем подписку на событие «Регистрация исходящего документа».
Подписка предназначена для связи вида бизнес-события и обработчика. В данном случае выбран предопределенный вид события.
После настройки остаётся установить флаг «Обработчик влючен» на форме обработчика.
Первичный анализ событий и результатов работы обработчика можно производить с использованием регистра сведений «Произошедшие бизнес-события» (меню Все функции — регистры сведений).
Для каждого зарегистрированного события после его обработки дополнительным обработчиком бизнес-событий устанавливается либо флаг «Обработано», либо флаг «Не удалось обработать».
Дополнительный анализ при неудачной обработке можно производить с использованием журнала регистрации изменений.
Тэги:
- Статьи
- 1С
- документооборот
- программирование