Редактирование регистров вручную

В 1С:Предприятии 8 существует возможность организовать в форме редактирование пользователем записей любого регистра, в том числе, и для подчиненного регистратору. Данная возможность соответствует общему подходу, принятому в 1С:Предприятии 8 в отношении модификации записей регистров. Система допускает и программное, и интерактивное изменение записей регистра без какого-либо участия регистратора (документа).  Для выполнения таких изменений достаточно указать только ссылку на регистратор, чтобы определить значение отбора записей регистра.

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

В качестве примера рассмотрим создание документа "РучнаяОперация" для изменения данных регистра "УчетНоменклатуры".

Прежде всего, следует запретить проведение документа "РучнаяОперация". Работа стандартного механизма проведения документов нам, в данном случае, будет не нужна, поскольку мы собираемся вручную изменять записи в регистре накопления.
Затем, несмотря на то, что документ "РучнаяОперация" не проводится, следует указать, что движения документа будут находиться в регистре накопления "УчетНоменклатуры". Это необходимо для того, чтобы в форме документа нам был доступен для редактирования набор записей регистра накопления, содержащий движения документа "РучнаяОперация". Данная ситуация как раз очень хорошо иллюстрирует тот факт, что изменение записей регистра может выполняться не только при проведении документа, но и другими способами.

После этого в форме документа "РучнаяОперация" следует расположить табличное поле с командной панелью. Тип значения этого табличного поля должен быть "РегистрНакопленияНаборЗаписей.УчетНоменклатуры". Затем следует указать, что источником данных для этого табличного поля будут являться движения документа "РучнаяОперация" по регистру "УчетНоменклатуры":



Все, по большому счету, ручная операция готова. Можно в режиме "1С:Предприятие" создать новый документ, и используя пиктограммы командной панели, связанной с табличным полем, вручную редактировать набор записей этого документа.

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

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

Таким образом, мы рассмотрели общий случай создания ручной операции. Однако логика конкретного прикладного решения может накладывать различные ограничения на создаваемую ручную операцию. Одним из самых распространенных ограничений является требование синхронизации даты движений с датой самого документа.
Самым простым способом такой синхронизации является принудительная установка нужной даты движений в модуле формы документа:

Копировать в буфер обмена
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)

	Для Каждого ЗаписьРегистра Из Движения.УчетНоменклатуры Цикл

		ЗаписьРегистра.Период = Дата;

	КонецЦикла;

КонецПроцедуры

Если теперь в режиме "1С:Предприятие" перезаписать созданные ранее документы "РучнаяОперация", можно убедиться, что дата движений будет синхронизирована с датой документа.

Такой способ синхронизации является самым простым и не учитывает возможность программной записи документа "РучнаяОперация". В самом деле, при программном вызове метода Записать() у объекта документа, он будет записан без участия формы документа. Это значит, что событие "При записи" формы документа вызвано не будет, и наш код обработчика не отработает. Чтобы предусмотреть возможность синхронизации периода движений документа с датой документа и в случае программной записи объекта документ, следует использовать обработчик события Перед записью() объекта документ, а не формы документа.

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

Копировать в буфер обмена
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) 

	// Определить нужно ли обновлять дату в движениях
	ОбновитьДатуДвижений = ЭтоНовый() Или Движения.УчетНоменклатуры.Модифицированность(); 
	Если Не ОбновитьДатуДвижений Тогда 

		// Проверить, что дата изменилась 
		Запрос = Новый Запрос; 
		Запрос.УстановитьПараметр("ТекущийДокумент", Ссылка); 


		Запрос.Текст = 
				"ВЫБРАТЬ 
				| Дата 
				|ИЗ 
				| Документ.ВводНачальныхОстатков 
				|ГДЕ Ссылка = &ТекущийДокумент"; 


		Выборка = Запрос.Выполнить().Выбрать(); 
		Выборка.Следующий(); 
		ОбновитьДатуДвижений = Выборка.Дата <> Дата;

	КонецЕсли; 

	// Установить всем новую дату, если нужно 
	Если ОбновитьДатуДвижений Тогда 

		Если Не Движения.УчетНоменклатуры.Выбран() И Не Движения.УчетНоменклатуры.Модифицированность() Тогда 

			Движения.УчетНоменклатуры.Прочитать(); 

		КонецЕсли; 
		Для Каждого ЗаписьРегистра Из Движения.УчетНоменклатуры Цикл 

			ЗаписьРегистра.Период = Дата; 

		КонецЦикла; 

	КонецЕсли; 

КонецПроцедуры

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

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

Перед установкой даты мы проверяем, был ли прочитан набор записей в свойстве "Движения" объекта и изменялся ли он. Если оба этих условия ложны – это значит, что набор записей в свойстве "Движения" объекта пуст, и это состояние не связано с его изменением. В этом случае, чтобы предотвратить ошибочное удаление записей в регистре (перезапись пустым набором записей), мы предварительно читаем движения из регистра в набор записей в свойстве "Движения". Затем, как и в предыдущем случае, устанавливаем нужную дату для всех записей этого набора. При выполнении записи объекта документ, этот набор будет записан в регистр накопления.

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

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

В заключение следует сказать, что выбор обработчика, в котором будет размещен текст процедуры, зависит от логики работы создаваемого объекта. Если конфигурация не предусматривает программной записи объекта – можно выбрать обработчик модуля формы. Если предполагается и программная модификация объекта – следует выбирать обработчик модуля объекта.

Заметьте, что оба эти способа не исключают модификацию записей регистра через объект "Регистр<…>НаборЗаписей.<имя регистра>". Поэтому, если логика конфигурации подразумевает возможность программной модификации объекта набор записей, код обработки следует размещать в обработчике события набора записей. Все попытки изменить данные регистра будут сведены, в конечном счете, к записи именно набора записей.