Данная статья описывает один из примеров решения типовой задачи пользователей программ 1С. В статье рассмотрено решение реальной задачи, поставленной нам заказчиком. Стояла задача автоматизировать бухгалтерский учет в компании, занимающейся оптовой торговле спортивными товарами. В компании внедрялась программа 1С:Бухгалтерия 8.0. Дело в том, что 1С, разрабатывая конфигурацию, оставили простор для добавления любого необходимого функционала. Клиентом была поставлена задача: обеспечить бухгалтеру, работающему по двум организациям, осуществление проведения вновь созданного документа для разных организаций.
Надо сделать небольшое отступление и рассказать, как устроены права доступа к данным в программе 1С 8.0. В платформе существует несколько уровней доступа пользователей к данным. Основной – это ограничение по ролям. Роль – это объект конфигурации, в котором настраивается ограничение на чтение, запись, удаление, изменение и прочие типовые операции с объектами конфигурации. Например, создаем роль «Кладовщик» и настраиваем в этой роли доступ к объектам, связанным только со складскими бизнес операциями. Так же существует возможность разграничение доступа на уровне записей и полей. Такой подход удобно использовать, когда нужно ограничить доступ к части групп и элементов справочника, информации в отчете и т. д. Например, одни пользователи в справочнике контрагенты видят только поставщиков, а другие только покупателей, или пользователю позволено видеть остатки товаров только по одной из организаций. Более подробное описание системы прав в 1С 8.0 можно прочесть здесь http://v8.1c.ru/overview/PlRights.htm. Зачастую, но не всегда, этого бывает достаточно для работы пользователей и спокойствия начальства за конфиденциальность информации. Нам нужно найти способ, который позволит выполнять проведение документа без контроля прав пользователя, не изменяя типовые настройки прав, и позволит видеть бухгалтеру проводки только по «своей» организации. Такая необходимость разделения доступа к данным в программе 1С:Бухгалтерия 8.0 существует, в частности, у компаний с филиальной сетью, когда бухгалтеру в программе разрешается просматривать данные только «своего» филиала.
Прочитав первоисточник, мы выбираем привилегированный модуль. Проводить документ мы будем на сервере приложения из привилегированного модуля. Как это сделать? Решение казалось слишком очевидным. Надо перехватить событие, возникающее перед записью объекта и провести документ на сервере. Оказалось это не так просто сделать:
#Если Сервер Тогда
#КонецЕсли
Надо заметить, что выделять надо все процедуры целиком, так как код компилируется только на стороне сервера, а на стороне клиента он полностью выпадает. Если же нам требуется выполнить код на клиенте, то нужно использовать следующую инструкцию препроцессора:
#Если Клиент Тогда
#КонецЕсли
Но в нашей задаче выполнять проведение мы будем в Привилегированном модуле, то есть все наши процедуры автоматически будут выполняться только на сервере. Сказано – сделано. Создаем общий модуль и в нем пишем свою процедуру проведения. Вернее сказать, достаточно вызвать метод объекта Записать() и все проведение будет выполнено на сервере. Но это еще не все. В целях безопасности, в платформе реализован следующий механизм выполнения кода на стороне сервера. В качестве параметров используемых в процедурах привилегированного модуля нельзя передавать объекты. Это значит, что подобная конструкция на сервере приложения в клиент-серверном варианте работать не будет (в файловом варианте работы программы подобных ограничений нет).
Мы можем передать ссылку на объект. Но у нового объекта еще нет ссылки. Из всех рассмотренных вариантов нам больше всего понравилось решение с XML- сериализацией. Мы знаем, что объект подвержен XML-сериализации, то есть мы можем конвертировать объект в XML запись и передать ее на сервер, а там инвертировать обратно и проводить документ на стороне сервера без помех. Но и здесь надо быть очень внимательным, чтобы не ошибиться в дальнейших действиях. Согласно объектной модели программирования в среде 1С 8.0 при программном создании объекта получаем не сам объект, а лишь его экземпляр в физической памяти. Это значит, что передавая на сервер объект, мы создаем в памяти сервера его точную копию. У нас получается два объекта (один объект связан с реквизитами на форме документа, а другой программно переданный на сервер) и оба связаны с одним документом в базе данных. Чтобы не было путаницы с данными, в 1С предусмотрен механизм версионности объектов. Перед записью объекта в базу данных идет сверка версии экземпляра объекта с версией записи в базе и если версии совпадают, то измененный объект записывается в базу и версия записи изменяется. В противном случае срабатывает исключение. При программном проведении это может нам помешать. До проведения объекта на сервере, надо разблокировать запись базы данных, записать документ, а после соединить запись с основным реквизитом формы документа, для того, чтобы пользователь мог, при необходимости, дальше работать с ним. В результате всех перечисленных требований у нас получился следующий механизм проведения.
В привилегированном модуле создаем следующую функцию, которая будет нам возвращать ссылку на измененный объект: