🔥 Горящие вакансии
Все статьи

Производительный режим RLS в 1С

Эту и другие технические статьи написали наши программисты 1С и получили за них премии. Если вы тоже работаете с 1С и любите делиться опытом, приходите разработчиком в Neti

Функционал подсистемы УправлениеДоступом позволяет работать с RLS в двух режимах: стандартном и производительном. Оба режима RLS в 1С имеют свои преимущества и недостатки.

RLS в 1С

Для гибкой настройки прав пользователей в конфигурациях на базе БСП (подсистема УправлениеДоступом) реализован механизм настройки доступа на уровне записей (RLS). Этот механизм позволяет ограничивать доступ не только по видам объектов (для конкретных справочников, документов…), но и по данным в этих объектах (т.е., например, ограничить список документов только по одной организации или по конкретному менеджеру).

Функционал подсистемы УправлениеДоступом позволяет работать с RLS в двух режимах: стандартном и производительном. Каждый из режимов имеет свои преимущества и недостатки относительно другого. Основные из них будут рассмотрены в тексте далее.

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

Ограничения RLS описываются в роли для конкретного объекта. Например, ограничение на чтение документа _ДемоСчетНаОплатуПокупателю в роли
_ДемоЧтениеДокументовПокупателей описывается следующим образом:

Производительный режим RLS в 1С

Производительный режим RLS в 1С

Производительный режим RLS в 1С

Как мы видим, для описания ограничений используются специальные шаблоны. В данном случае #ДляОбъекта и #ПоЗначениям. Шаблоны, которые могут быть использованы в роли необходимо описать на вкладке “Шаблоны ограничений”:

Производительный режим RLS в 1С

В свою очередь, эти шаблоны можно скопировать из поставляемой роли ИзменениеУчастниковГруппДоступа.

Рассмотрим текст ограничения доступа подробнее.

#Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
#ДляОбъекта("")
#Иначе
#ПоЗначениям( "Документ._ДемоСчетНаОплатуПокупателю", "","",
"_ДемоОрганизации", "Организация",
"_ДемоГруппыПартнеров","Партнер", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","")
#КонецЕсли

Как мы видим, выбор шаблона зависит от параметра &ОграничениеДоступаНаУровнеЗаписейУниверсально, который как раз и определяет режим, в котором должно использоваться RLS — стандартный или производительный. Значение этого параметра хранится в параметрах сеанса, а в самой базе выбрать режим можно двумя способами:

1. Зайти в раздел Администрирование — Настройки пользователей и прав — Группы доступа — Вариант работы — Производительный

Производительный режим RLS в 1С

2. В окне “Все функции” изменить значение константы “Ограничивать доступ на уровне записей универсально” на ИСТИНА, если нужен производительный режим и, соответственно на ЛОЖЬ, если стандартный.

Производительный режим RLS в 1С

Соответственно, если &ОграничениеДоступаНаУровнеЗаписейУниверсально = ЛОЖЬ, то будет использоваться стандартный метод и выполняться код

#ПоЗначениям( "Документ._ДемоСчетНаОплатуПокупателю", "","",
"_ДемоОрганизации", "Организация",
"_ДемоГруппыПартнеров","Партнер", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "","", "",""),

а если &ОграничениеДоступаНаУровнеЗаписейУниверсально = ИСТИНА, то будет использоваться производительный метод и выполняться код

#ДляОбъекта("").

Подробнее о синтаксисе и использовании шаблонов можно почитать в их описании.

При стандартном режиме ограничение прописывается прямо в роли (установлен отбор по разрешенным организации и партнеру). Эти отборы добавляются к итоговому запросу при обращении к СУБД. При наличии нескольких ролей с описанными ограничениями все условия собираются в один запрос, растет количество левых соединений, повышается риск неправильного использования индексов, выбора неоптимального плана выполнения запроса, что значительно его усложняет и замедляет выполнение. А так как при стандартном режиме работы ограничения рассчитываются “на лету” при каждом обращении к данным (формирование списков справочников и документов, их открытие и записи), то работа пользователя может значительно замедлиться из-за сложности сформированного запроса.

Эту проблему решает включение производительного режима. При нём все отборы и ограничения не добавляются в запрос, раздувая его, а предварительно рассчитываются в некоторые ключи доступа и в итоговый запрос попадают только они, что увеличивает производительность. О ключах и их расчете подробнее далее.

Как мы видим, в ограничении роли для производительного режима не описаны никакие условия, нет никакой информации о видах доступа, по которым необходимо ограничивать данные. Где же они указаны? Для этого в подсистеме УправлениеДоступом предусмотрена специальная экспортная процедура ПриЗаполненииОграниченияДоступа(), который описывается в модуле менеджера объекта, указанного в роли.

Так, для документа _ДемоСчетНаОплатуПокупателю эта процедура описана следующим образом:

Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
| И ЗначениеРазрешено(Партнер)";КонецПроцедуры

Здесь мы видим, что ограничение описывается с помощью некоторых типов ограничения (РазрешитьЧтениеИзменение) и функций ограничений (ЗначениеРазрешено()). Это нужно понимать так: пользователю будет разрешено читать и изменять документ _ДемоСчетНаОплатуПокупателю, когда ему будут разрешены значения организации и партнера, указанные в этом документе.

Примечание. Подробно о типах, функциях, синтаксисе ограничений описано на сайте ИТС в разделе — Инструкции по разработке на 1С

— Библиотека стандартных подсистем 3.1.6. Документация

— Глава 3. Настройка и использование подсистем при разработке конфигурации

— Управление доступом

— Разработка ограничений прав доступа

Далее в статье рассмотрим кратко лишь некоторые.

Некоторые типы ограничений

Типы ограничения могут быть:

  • РазрешитьЧтениеИзменение
  • РазрешитьИзменениеЕслиРазрешеноЧтение
  • РазрешитьИзменение 

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

  • ЗначениеРазрешено(<Реквизит> [<проверяемые типы>] [, <уточнение сравнения 1> [, <уточнение сравнения 2>] …]), где проверяемые типы могут быть (значения непроверяемых типов запрещены, если не уточнены отдельно):

— ТОЛЬКО <Имя таблицы>;
— ТОЛЬКО (<Имя таблицы 1>, <Имя таблицы 2>, … );
— КРОМЕ <Имя таблицы>;
— КРОМЕ (<Имя таблицы 1>, <Имя таблицы 2>, … );

  • Уточнение сравнения может быть:

— ПустаяСсылка КАК Ложь/Истина;
— Неопределено КАК Ложь/Истина;
— Null КАК Ложь/Истина;
— Отключено КАК Ложь/Истина (только для функции ЗначениеРазрешено);
— <Таблица> КАК Ложь/Истина (например, Справочник.Проекты КАК Истина).

Также существуют следующие функции:

  • ЧтениеОбъектаРазрешено
  • ЧтениеСпискаРазрешено
  • ИзменениеОбъектаРазрешено
  • ИзменениеСпискаРазрешено

Синтаксис этих функций аналогичен функции ЗначениеРазрешено().

Эти функции необходимо использовать, когда необходимо установить доступность (чтение/изменение) объекта в зависимости от доступности его реквизита. Например, документ _ДемоСчетНаОплатуПокупателю должен быть доступен, когда доступен его реквизит Организация. В таком случае ограничение будет описано как:

Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт
Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЧтениеОбъектаРазрешено(Организация)";
КонецПроцедуры
  • ДляВсехСтрок(<Условие>)

Функция выполняет проверку в строках с помощью логического «И». Используется для одновременного выполнения условия во всех строках табличной части объекта.

  • ДляОднойИзСтрок(<Условие>)

Функция выполняет проверку в строках с помощью логического «ИЛИ». Используется для выполнения условия хотя бы в одной строке табличной части объекта.

Примеры возможных ограничений

Организация и контрагент в шапке документа:

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
|И ЗначениеРазрешено(Контрагент)";

Организация в шапке документа, контрагент в табличной части, достаточно одного разрешенного контрагента:

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
|И ЗначениеРазрешено(Поставщики.Контрагент)";

Организация в шапке документа, контрагент в табличной части, достаточно одного разрешенного контрагента (если табличная часть пустая, тогда доступ по контрагенту разрешен):

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
|И ЗначениеРазрешено(Поставщики.Контрагент, Null КАК Истина)";

Организация в шапке документа, контрагент в табличной части, и требуется, чтобы все контрагенты были разрешены (если табличная часть пустая, тогда доступ по контрагенту запрещен):

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
|И ДляВсехСтрок(ЗначениеРазрешено(Поставщики.Контрагент))";

Организация и контрагент в табличной части, при этом достаточно, чтобы любая из пар организации с контрагентом была разрешена:

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Поставщики.Организация)
|И ЗначениеРазрешено(Поставщики.Контрагент)";

Организация и контрагент в табличной части, при этом требуется, чтобы все пары организации с контрагентом были разрешены:

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ДляВсехСтрок(
| ЗначениеРазрешено(Поставщики.Организация)
| И ЗначениеРазрешено(Поставщики.Контрагент))";

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

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ДляОднойИзСтрок(ЗначениеРазрешено(Поставщики.Организация))
|И ДляОднойИзСтрок(ЗначениеРазрешено(Поставщики.Контрагент))";

Отправитель – измерение составного типа, при этом требуется проверять только ссылки Справочник.Склады:

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Отправитель ТОЛЬКО Справочник.Склады)";

Отличительная особенность производительного режима RLS в 1С

Вернёмся к основной отличительной особенности производительного режима RLS в 1С. Она заключается в том, что в этом режиме расчет прав происходит предварительно и записывается в специальные таблицы (справочник и регистры сведений). Это позволяет достичь высокой производительности запросов с RLS, так как добавляет простой и статический фрагмент к текстам запросов в ролях. За счет этого обеспечивается одинаково хорошая скорость работы при различной прикладной логике ограничений доступа, при различных условиях и их комбинациях. Но, так как предварительный расчет прав доступа занимает некоторое время, поэтому изменения в правах вступают в силу с некоторой задержкой.

Для хранения этих предварительно рассчитанных данных (ключей) используются следующие таблицы:

  • справочник КлючиДоступа
  • регистр сведений КлючиДоступаКОбъектам
  • регистр сведений КлючиДоступаПользователей

Справочник КлючиДоступа имеет структуру:

Производительный режим RLS в 1С

В реквизитах Значение1 — Значение5 хранятся комбинации конкретных значений доступа. В зависимости от ограничений каждого конкретного типа объектов конфигурации состав значений разный. Например, как упоминалось выше, для документа _ДемоСчетНаОплатуПокупателю определено ограничение по Организации и Партнеру. Соответственно, будут сформированы ключи с возможными комбинациями организации и партнера.

В реквизит Хэш реквизит рассчитывается специальный хеш функции. Он позволяет быстро понять, существует ли уже в системе ключ с такой комбинацией значений или нет.

Структура регистров следующая:

Производительный режим RLS в 1С

Причем Объект РС КлючиДоступаКОбъектам имеет тип ОпределяемыйТип.ВладелецЗначенийКлючейДоступа, которые содержит в себе ссылки на все объекты, которые могут быть ограничены с помощью RLS.

Регистр ключей доступа к объектам, а также сами ключи доступа обновляются регламентно. Регистр ключей доступа пользователей в измерении Пользователь содержит справочник ключей пользователей, к которым применяется ограничение, а также справочник ключей доступа к объектам.

Таким образом при проверке ограничений доступа вне зависимости от количества настроенных для конкретного проверяемого объекта видов доступа запрос всегда будет дополняться одним соединением с регистром «Ключи доступа к объектам» по проверяемому объекту и с регистром «Ключи доступа пользователей» по текущему пользователю:

Производительный режим RLS в 1С

Обновление ключей объектов и ключей доступа к ним выполняются регламентным заданием. А также оно может быть запущено из обработки “Обновление доступа на уровне записей”:

Производительный режим RLS в 1С

Эта обработка позволяет запускать процесс обновления ключей вручную, а также настраивать и контролировать процесс выполнения.

Запуск обработки выполняется по кнопке

Производительный режим RLS в 1С

Можно настроить обновление ключей по определенным объектам. Эта настройка выполняется по кнопке Ещё — Ручное управление… На этой форме можно выбрать конкретные справочники, документы или регистры, по которым необходимо обновить ключи, отметить их флажками, после этого запланировать обновление и запустить обработку:

Производительный режим RLS в 1С

Также есть возможность выводить более подробную информацию о ходе выполнения обработки

Производительный режим RLS в 1С

Для удобного написания и контроля текстов ограничений в комплекте поставки есть специальная обработка УправлениеДоступом:

Производительный режим RLS в 1С

Она позволяется в пользовательском режиме, без редактирования конфигурации формировать и проверять тексты ограничения доступа для объектов. Для этого необходимо во вкладке “Разработка ограничений доступа” необходимо выбрать список, ограничение на который нужно отредактировать:

Производительный режим RLS в 1С

После этого на форму загрузится текст ограничений из процедуры ПриЗаполненииОграниченияДоступа, а также шаблон ограничения в роли, а также кнопки для проверки текста вставки его в код:

Производительный режим RLS в 1С

При наличии ошибки в тексте ограничения и нажатии на кнопку “Проверить” появляется вкладка “(ошибки)”, в которой описаны ошибка как самого текста, так и всего внедрения механизма ограничений по записям для объекта:

Производительный режим RLS в 1С

Производительный режим RLS в 1С

 

Несколько конкретных примеров внедрения

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

— создать новый документ ТестовыйДокументСОграничениями

Производительный режим RLS в 1С

— добавить объект в определяемые типы ВладелецЗначенийКлючейДоступа и ВладелецЗначенийКлючейДоступаДокумент.

Примечание. В определяемый тип ВладелецЗначенийКлючейДоступаДокумент добавляются документы. Справочники нужно добавить в ВладелецЗначенийКлючейДоступаОбъект, регистры сведений — в ВладелецЗначенийКлючейДоступаНаборЗаписей, регистры расчета — в ВладелецЗначенийКлючейДоступаНаборЗаписейРегистраРасчета.

— в процедуру ПриЗаполненииСписковСОграничениемДоступа общего модуля УправлениеДоступомПереопределяемый вставить текст

Списки.Вставить(Метаданные.Документы.ТестовыйДокументСОграничениями, Истина);
Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт

…
Списки.Вставить(Метаданные.Документы.ТестовыйДокументСОграничениями, Истина);
КонецПроцедуры

— на форме документа в обработчики ПриЧтенииНаСервере и ПослеЗаписиНаСервере добавить следующий код:

&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
// СтандартныеПодсистемы.УправлениеДоступом
Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.УправлениеДоступом") Тогда
МодульУправлениеДоступом = ОбщегоНазначения.ОбщийМодуль("УправлениеДоступом");
МодульУправлениеДоступом.ПриЧтенииНаСервере(ЭтотОбъект, ТекущийОбъект);
КонецЕсли;
// Конец СтандартныеПодсистемы.УправлениеДоступом
КонецПроцедуры
&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
// СтандартныеПодсистемы.УправлениеДоступом
УправлениеДоступом.ПослеЗаписиНаСервере(ЭтотОбъект, ТекущийОбъект, ПараметрыЗаписи);
// Конец СтандартныеПодсистемы.УправлениеДоступом
КонецПроцедуры

— создать новые роли для чтения и добавления/изменения нового документа: ЧтениеТестовыхДокументовСОграничениями и ДобавлениеИзменениеТестовыхДокументовСОграничениями. Для них определить соответствующие права (чтение, добавление, изменение), скопировать шаблон ограничений ДляОбъекта() из роли ИзменениеУчастниковГруппДоступа и прописать код ограничения доступа для необходимых прав:

#Если &ОграничениеДоступаНаУровнеЗаписейУниверсально #Тогда
#ДляОбъекта("")
#Иначе
ИСТИНА
#КонецЕсли

Примечание. В данном конкретном случае принимаем, что производительный режим RLS используется, поэтому ограничение для обычного режима не прописываем и в соответствующей ветке прописываем просто ИСТИНА.

Производительный режим RLS в 1С

  • Нужно для этого документа реализовать ограничение, чтобы были доступны только те документы, в которых доступны организация и подразделение. Необходимо выполнить следующие действия:

— в модуле менеджера документа в процедуре ПриЗаполненииОграниченияДоступа прописать текст ограничения:

Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
| И ЗначениеРазрешено(Подразделение)";
КонецПроцедуры

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

Производительный режим RLS в 1С Производительный режим RLS в 1С Производительный режим RLS в 1С

— создать документы и запустить задание обновления ключей доступа.

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

под полными правами

Производительный режим RLS в 1С

под ограниченными правами

Производительный режим RLS в 1С

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

— в модуле менеджера документа в процедуре ПриЗаполненииОграниченияДоступа прописать текст ограничения:

Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
| И ДляОднойИзСтрок(ЗначениеРазрешено(Запасы.МестоХранения))";
КонецПроцедуры

— добавить вид ограничения в профиль доступа, прописать в группе доступа ограничения по местам хранения, обновить ключи:

Производительный режим RLS в 1С Производительный режим RLS в 1С

В результате под пользователем с ограниченными правами увидим только те документы, у которых доступна организация и в ТЧ Запасы хотя бы в одной строке указан Розничный склад:

Производительный режим RLS в 1С Производительный режим RLS в 1С Производительный режим RLS в 1С Производительный режим RLS в 1С

  • Рассмотрим пример, когда необходимо реализовать ограничение по какому-то новому реквизиту, тип которого не описан в доступных видах доступа. Реализуем такую задачу. Для этого нужно выполнить следующее:

— создать новый справочник ТестовыйРегион. Выполнить для него все те же операции, что и для самого документа ТестовыйДокументСОграничениями (роли можно создать новые или прописать в какие-то существующие, например для чтения/изменения документа. В данном примере это не принципиально. В ПриЗаполненииОграниченияДоступа прописать ограничение на само себя: ЗначениеРазрешено(Ссылка)).

— добавить ссылку и объект ТестовыйРегион в определяемые типы соотстветственно ЗначениеДоступа и ЗначениеДоступаОбъект

— в процедуру ПриЗаполненииВидовДоступа общего модуля УправлениеДоступомПереопределяемый вставить текст:

Процедура ПриЗаполненииСписковСОграничениемДоступа(Списки) Экспорт

…
ВидДоступа = ВидыДоступа.Добавить();
ВидДоступа.Имя = "ТестовыйРегион";
ВидДоступа.Представление = НСтр("ru = 'Тестовый регион'");
ВидДоступа.ТипЗначений = Тип("СправочникСсылка.ТестовыйРегион");
КонецПроцедуры

— запустить обработку ОбновлениеВспомогательныхДанных (из Инструментов разработчика) и  обновить всё.

— добавить новый вид доступа в профиль доступа и определить конкретные ограничения в группе доступа:

Производительный режим RLS в 1С Производительный режим RLS в 1С

— добавить реквизит в документ, вывести на форму, заполнить (скриншот от пользователя с полными правами):

Производительный режим RLS в 1С

— изменить текст ограничения в процедуре ПриЗаполненииОграниченияДоступа документа ТестовыйДокументСОграничениями, чтобы он учитывал новый реквизит:

Процедура ПриЗаполненииОграниченияДоступа(Ограничение) Экспорт

Ограничение.Текст =
"РазрешитьЧтениеИзменение
|ГДЕ
| ЗначениеРазрешено(Организация)
| И ЗначениеРазрешено(ТестовыйРегион)";
КонецПроцедуры

— обновить ключи доступа.

В результате на пользователя с ограниченными правами распространяются ограничения по организациям (ООО Тестовая организация и Новые технологии ООО) и регионам (Центральный и Южный) и он получит такой список документов:

Производительный режим RLS в 1С

Оставить коментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Отправить резюме

    Я согласен на обработку персональных данных в соответствии
    со ст. 9 ФЗ № 152-ФЗ «О персональных данных»

    Отправить резюме

      Я согласен на обработку персональных данных в соответствии
      со ст. 9 ФЗ № 152-ФЗ «О персональных данных»

      Pекомендовать друга

        Отправьте контактные данные вашего друга и предупредите его, что мы с ним свяжемся. Когда друг успешно отработает 3 месяца, вы получите 20 000 ₽.


        Выбрать вакансию
        • Bitrix-разработчик
        • Программист 1С
        • Консультант-аналитик 1С
        • Проекты для команды специалистов 1С
        • Проекты для специалистов 1С
        • Стажёр-программист 1С
        • Ведущий консультант Microsoft Dynamics 365 Sales
        • Руководитель проектов Microsoft Dynamics 365 FO и AX 2012
        • Консультант Microsoft Dynamics AX на зарубежные проекты
        • Ведущий консультант Microsoft Dynamics 365 Finance and Operation
        • Ведущий разработчик Microsoft Dynamics AX на зарубежные проекты
        Я согласен на обработку персональных данных в соответствии
        со ст. 9 ФЗ № 152-ФЗ «О персональных данных»

        Pекомендовать друга

          Отправьте контактные данные вашего друга и предупредите его, что мы с ним свяжемся. Когда друг успешно отработает 3 месяца, вы получите 20 000 ₽.


          Выбрать вакансию
          • Bitrix-разработчик
          • Программист 1С
          • Консультант-аналитик 1С
          • Проекты для команды специалистов 1С
          • Проекты для специалистов 1С
          • Стажёр-программист 1С
          • Ведущий консультант Microsoft Dynamics 365 Sales
          • Руководитель проектов Microsoft Dynamics 365 FO и AX 2012
          • Консультант Microsoft Dynamics AX на зарубежные проекты
          • Ведущий консультант Microsoft Dynamics 365 Finance and Operation
          • Ведущий разработчик Microsoft Dynamics AX на зарубежные проекты
          Я согласен на обработку персональных данных в соответствии
          со ст. 9 ФЗ № 152-ФЗ «О персональных данных»

          Спасибо!

          Мы получили ваше резюме. Менеджер свяжется с вами в течение трех дней

          Горящие вакансии