Создание документа ввода начальных остатков
В нашей информационной базе, как, впрочем, и в любой другой, обязательно следует предусмотреть возможность ввода начальных остатков в регистры. Это необходимо для того, чтобы пользователи могли начать работу с нашей информационной базой не с "чистого листа", а с некоторого "исходного состояния", которое было в их прежней системе учета (пусть даже они вели учет на бумаге).
Задача ввода начальных остатков отличается от прочих алгоритмов изменения состояния регистров нашей информационной базы тем, что подразумевает изменение данных непосредственно в регистрах, без использования каких-либо промежуточных алгоритмов (заполнения документов данными, проведения документов, контроля правильности данных, указанных в документах и пр.).
Рассмотрим пример ввода начальных остатков регистра накопления "ОстаткиМатериалов". Для выполнения этой задачи мы создадим документ, в котором будем вручную редактировать его движения по регистру "ОстаткиМатериалов" прямо в форме документа.
Откроем конфигуратор и создадим новый объект конфигурации Документ с именем "ВводНачальныхОстатковНоменклатуры". На закладке "Движения" запретим проведение документа (поскольку сами будем формировать записи регистра), и отметим, что движения документа будут находиться в регистре накопления "ОстаткиМатериалов". После этого перейдем на закладку "Формы" и создадим основную форму документа. [477]
Раздвинем форму вниз и разместим в ней табличное поле c командной панелью. Зададим имя табличного поля "ОстаткиМатериалов" и тип значения "РегистрНакопленияНаборЗаписей.ОстаткиМатериалов":
В свойствах табличного поля укажем, что источником данных для него будут являться движения документа по регистру "ОстаткиМатериалов":
[478]
Удалим из табличного поля колонки "Регистратор" и "Активность" (они нам не понадобятся), и изменим размеры формы и расположение элементов управления:
Запустим 1С:Предприятие в режиме отладки и проверим работу нашего документа.
Введем в документ следующие данные:
Обратите внимание на то, что дата документа не совпадает с датами отдельных записей, которые мы создаем в движениях документа. [479]
Нажмем "Записать", и из формы списка документа откроем движения нашего документа в регистре "ОстаткиМатериалов" (кнопка "Перейти").
Вы видите, что записи регистра накопления в точности соответствуют тем, которые мы создали в документе:
Таким образом, мы добились поставленной цели: с одной стороны, задавая дату документа, мы можем фиксировать момент внесения изменений в записи регистра, с другой стороны – для каждой создаваемой нами записи регистра, мы можем указать индивидуальное значение поля "Период".
Теперь займемся "ужесточением" требований, предъявляемых к тому, как наш документ формирует записи регистра, и рассмотрим два типичных варианта.
Первое требование, которое мы реализуем, будет заключаться в том, что записи регистра должны формироваться той же датой, что и дата документа. Иначе говоря, синхронизируем дату движений с датой документа.
Для этого в обработчик события "Перед записью" формы документа добавим следующий текст:
Для Каждого ЗаписьРегистра Из Движения.ОстаткиМатериалов Цикл
ЗаписьРегистра.Период = Дата;
КонецЦикла;
КонецПроцедуры [480]
Можно сказать, что мы достигли поставленной цели, но лишь в ситуации, когда запись документа выполняется интерактивными средствами.
Если программно вызвать метод Записать() у объекта нашего документа, он будет записан без участия формы документа. Это значит, что событие "При записи" формы документа вызвано не будет, и наш код обработчика не отработает.
Чтобы предусмотреть возможность синхронизации периода движений документа с датой документа и в случае программной записи объекта Документ, следует использовать обработчик события "Перед записью" объекта документ, а не формы документа. [481]
Событие "Перед записью", в случае интерактивной записи документа, сначала будет вызвано у формы документа, а затем объекта документа (смотри схему событий в раздел "Последовательность событий при записи документа из форм документа" на странице 581). Поэтому вернемся в конфигуратор удалим из модуля формы добавленный нами текст и создадим обработчик события "Перед записью" в модуле объекта документ:
//Определить нужно ли обновлять дату в движениях
ОбновитьДатуДвижений = ЭтоНовый() Или Движения.ОстаткиМатериалов.Модифицированность();
Если Не ОбновитьДатуДвижений Тогда // Проверить, что дата изменилась
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ТекущийДокумент", Ссылка);
Запрос.Текст =
"ВЫБРАТЬ
| ВводНачальныхОстатковНоменклатуры.Дата
|ИЗ
| Документ.ВводНачальныхОстатковНоменклатуры КАК ВводНачальныхОстатковНоменклатуры
|ГДЕ
| ВводНачальныхОстатковНоменклатуры.Ссылка = &ТекущийДокумент";
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
ОбновитьДатуДвижений = Выборка.Дата <> Дата;
КонецЕсли;
//Установить всем новую дату, если нужно
Если ОбновитьДатуДвижений Тогда
Если Не Движения.ОстаткиМатериалов.Выбран() И Не Движения.ОстаткиМатериалов.Модифицированность() Тогда
Движения.ОстаткиМатериалов.Прочитать();
КонецЕсли;
Для Каждого ЗаписьРегистра Из Движения.ОстаткиМатериалов Цикл
ЗаписьРегистра.Период = Дата;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Поясним содержание обработчика. Если записывается новый документ или были изменены его движения – следует обновить дату движений. В противном случае мы считываем запросом дату документа из базы данных и сравниваем ее с датой, установленной у записываемого объекта. Если даты разные – также следует обновить дату движений.
Перед установкой даты мы проверяем, был ли прочитан набор записей в свойстве "Движения" объекта и изменялся ли он. Если оба этих условия ложны – это значит, что набор записей в свойстве "Движения" объекта пуст, и это состояние не связано с его изменением. В этом случае, чтобы предотвратить ошибочное удаление записей в регистре (перезапись пустым набором записей), мы предварительно читаем движения из регистра в набор записей в свойстве "Движения". Затем, как и в предыдущем случае, устанавливаем нужную дату для всех записей этого набора. При выполнении записи объекта Документ, этот набор будет записан в регистр накопления.
Запустим 1С:Предприятие в режиме отладки и убедимся, что указав новую дату для нашего документа и записав его, мы получим движения в регистре накопления с новой датой.
В процессе записи нашего документа можно управлять не только периодом записей регистра накопления, но и значениями других полей регистра.
Например, по аналогичному принципу может быть создан документ "Операция", позволяющий вводить ручные операции в регистр бухгалтерии. При этом, вероятно, кроме управления периодом записей регистра, вам потребуется управлять значением поля "Активность" ("включать" и "выключать" проводки документа) и т.д.
В заключение следует сказать, что выбор обработчика, в котором будет размещен текст процедуры, зависит от логики работы создаваемого объекта. Если конфигурация не предусматривает программной записи объекта – можно выбрать обработчик модуля формы. Если предполагается и программная модификация объекта – следует выбирать обработчик модуля объекта.
Заметьте, что оба эти способа не исключают модификацию записей регистра через объект Регистр<...>НаборЗаписей.<имя регистра>. Поэтому, если логика конфигурации подразумевает возможность программной модификации объекта набор записей, код обработки [483] следует размещать в обработчике события набора записей. Все попытки изменить данные регистра будут сведены, в конечном счете, к записи именно набора записей. [484]