В свое время, когда только начинал шаги в 1С и изучал, как проводятся документы в конфигурациях на платформе 1С по книге "Разработка управляемого интерфейса" (Хрусталева Е.Ю.), и там были представлены примеры совсем далекие от того, как сейчас проводятся документы в современных конфигурациях от 1С.
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
...
// регистр ЗаказыКлиентов Расход
Движения.ЗаказыКлиентов.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ЗаказыКлиентов.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.ЗаказКлиента = ТекСтрокаТовары.ЗаказКлиента;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Характеристика = ТекСтрокаТовары.Характеристика;
Движение.КодСтроки = ТекСтрокаТовары.КодСтроки;
Движение.Склад = ТекСтрокаТовары.Склад;
Движение.Серия = ТекСтрокаТовары.Серия;
Движение.Заказано = ТекСтрокаТовары.Количество;
Движение.КОформлению = ТекСтрокаТовары.Количество;
Движение.Сумма = ТекСтрокаТовары.Сумма;
КонецЦикла;
...
КонецПроцедуры
Конечно, никто не запрещает продолжать писать движения так, но конечно намного лучше и правильнее использовать типовой подход "Проведения документов" при выполнении процедуры проведения.
Совсем вкратце он выглядит примерно так:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
...
Документы.РеализацияТоваровУслуг.ИнициализироватьДанныеДокумента(Ссылка, ДополнительныеСвойства); // тут мы инициализируем таблицы для регистров
...
ЗаказыСервер.ОтразитьЗаказыКлиентов(ДополнительныеСвойства, Движения, Отказ); // так выполняем запись
...
ПроведениеСерверУТ.ВыполнитьКонтрольРезультатовПроведения(ЭтотОбъект, Отказ); // тут выполняется контроль
...
КонецПроцедуры
Естественно, когда столкнулся с типовыми конфигурациями 1С, то так сразу понять где что инициализируется и что где от чего зависит было сложновато. Порядок следования процедур, функциональность каждой из них, тонкости использования сразу начинающему разработчику бывает трудно охватить, особенно если был опыт работы либо на старых конфигурациях, либо на самописных (сейчас еще они встречаются). Типовой подход при проведении документов сейчас так же важен как использование БСП (Библиотеки стандартных подсистем). Поэтому давайте немного разберем все по полочкам.
Свойства проведения документа.
Во-первых документы должны быть со следующими настройками режима проведения:
Режим проведения обязательно должен быть "Разрешить", а оперативное проведение чаще всего "Запретить". Удаление движения: "Не удалять автоматически" означает, что в "Обработке удаления" документа будут описаны процедуры, в которых явно будет прописано удаление движений при отмене проведения.
Схема проведения в событии "Обработка проведения".
Давайте для примера возьмем документ РегистрацияТранспортныхСредств (В ЕРП И УТ он должен быть). Не будем разбирать на примере документа РеализацияТоваровУслуг или других основных документах, т.к. они достаточно нагружены различными процедурами, которые будут отвлекать от нашей схемы проведения документа.
Сама обработка проведения нашего документа выглядит так:
К самой схеме проведения относятся процедуры:
1. ИнициализироватьДополнительныеСвойстваДляПроведения;
2. ИнициализироватьДанныеДокумента;
3. ПодготовитьНаборыЗаписейКРегистрацииДвижений;
4. ЗагрузитьТаблицыДвижений;
5. ЗаписатьНаборыЗаписей;
6. ОчиститьДополнительныеСвойстваДляПроведения;
Они являются стандартными для всех документов. Поэтому разобрав эту схему в нашем документе, можно будет спокойно ориентироваться в других документах.
Остальные процедуры:
1. РеестрДокументов.ЗаписатьДанныеДокумента;
2. ДокументыПоОС.ЗаписатьДанныеДокумента;
3. СформироватьЗаписиРегистровЗаданий;
Не относятся к схеме и могут отсутствовать в других документах. К примеру РеестрДокументов.ЗаписатьДанныеДокумента (1) используется для хранения реквизитов документов и быстрого доступа к ним, чтобы не обращаться к реквизитам самого документа (к которому у пользователей, к примеру не может быть доступа по RLS, или если и есть то эти права достаточно "тяжело" отрабатывают для SQL сервера). В результате запрос с использованием этого РС отрабатывает быстрее.
Они являются специфичными для документа и могут отсутствовать в других документах.
Давайте разберем по очереди каждую из этих процедур схемы проведения.
1.
Эта процедура инициализирует общие структуры, используемые для проведения документа.
Изменяется свойство ДокументОбъекта ДополнительныеСвойства в которое помещаются свойства:
"ТаблицыДляДвижений" - в него будут записываться таблицы, которые будут загружаться в регистр сведений (о чем речь пойдет далее);
"ДляПроведения" - будут содержаться свойства и реквизиты документы, используемые для проведения: "СтрукутраВременныеТаблицы" - записывается МенеджерВременныхТаблиц, записывается "Режим проведения" - режим проведения нашего документа, "МетаданныеДокумента" - метаданные документа и "Ссылка" - ссылка на текущий документ;
Теперь мы инициализировали данные, которые сможем использовать для проведения.
2.
Эта процедура одна из самых основных.
Сначала в процедуре ЗаполнитьПараметрыИнициализации инициализируются реквизиты документа, которые в будущем могут использоваться к примеру как параметры для таблиц движений регистров.
В начале этой процедуры видно что выбираются реквизиты документа, и устанавливается параметр "Ссылка", чтобы ограничить выборку одним документом, который проводится.
В конце этой процедуры перебираются все колонки РезультатаЗапроса и устанавливаются параметры в Запрос. Наши будущие таблицы движений, которые будут помещены в свойство "ТаблицыДляДвижений", будут использовать эти параметры.
В Функции ЗначенияПараметровПроцедения устанавливаются параметры в Запрос, которые берутся не из реквизитов
Теперь вернемся в процедуру ИнициализироватьДанныеДокумента и увидим несколько однотипных процедур:
По параметрам этих процедур видно, что они одинаковые. И выполняют одинаковую цель - добавляют в тексты запросов для каждого из регистров, по которым будут сформированы движения, которые будут отражены в регистрах.
Названия у них, как правило: "ТекстЗапроса" + "Таблица" + ИмяРегистра, где ИмяРегистра - имя регистра, движения которого будут формироваться этим запросом.
На мой взгляд первые 2 процедуры отступают от общепринятого стандарта формирования таких процедур, и там явно не хватет "ТекстЗапросаТаблица".
Разберем одну из такий процедур (функций):
Вначале проверяется, требуется ли таблица для движений (если в ТекстыЗапроса был ранее добавлен текст по этому регистру, то проверка вернет Ложь - значит не требуется. А далее добавляется текст запроса для текущего регистра в ТекстыЗапроса. В данной процедуре (функции) выбираются параметры, которые мы инициализировали в процедуре ЗаполнитьПараметрыИнициализации. Чаще всего в этих запросах берутся данные из ТЧ из которых формируются движения по номенклатуре, характеристике, количестве и т.д., реже из шапки документов (как в данном случае).
В самом конце процедуры происходит инициализация таблиц для движений.
Тут происходит одно из самых важных действий - выполняется запрос, который выгружает таблицы значений для движений и вставляет их в свойство "ТаблицыДляДвижений" свойства "ДополнительныеСвойства" нашего документа. Причем, все имена полей нашей таблицы для движений должны совпадать с именами полей из регистра, иначе они просто не загрузятся.
(Имена псевдонимов в Тексте запроса и Имена Измерений(Ресурсов, Реквизитов) регистров должны совпадать.
Теперь мы имеем таблицы движений, которые по большому счету осталось только загрузить в регистры.
3.
Данная процедура, как следует из ее описания выполняет 2 основных функции:
1. Очищает наборы записей от старых записей (в настоящее время все менее актуальна, т.к. чаще работают на тонких клиентах, а не на толстых);
2. Взводит флаг записи у регистров, по которым есть ТаблицыДляДвижений с количеством записей более 0. По сути смысл процедуры в строке Объект.Движения[ИмяРегистра].Записывать = Истина.
Также в этой процедуре удаляются регистры, по которым документ является регистратором, но движения пишутся не из модуля документа или отложенно, к примеру, регламентными заданиями.
4.
Загружаются Таблицы для движений из свойства "ТаблицыДляДвижений". По сути самая главная строчка - это Движения[ИмяРегистра].Загрузить(Таблица.Значение). Обратите внимание, что разработчики решили повторно взвести флаг Записывать = Истина, хотя его уже установили на 3 этапе схемы проведения. Все таблицы для проведения должны начинаться с слова "Таблица".
В данном случае загружаются таблицы в цикле, хотя могут также встречаться сразу несколько однотипных процедур с именами "Отразить" + ИмяРегистра, где ИмяРегистра - имя регистра, по которому отражаются движения.
5.
В процедуре ЗаписатьНаборыДанных Записываются движения (строка Объект.Движения.Записать()) и копируются параметры для выполнения регистрации движений (к примеру для использования их в контролях, Объект.Движения.ТоварыОрганизаций.ДополнительныеСвойства.Вставить("РассчитыватьИзменения", Истина)).
6.
Завершающая техническая процедура в которой по факту происходит закрытие МенеджераВременныхТаблиц.
Схема проведения в событии "Обработка удаления проведения".
Схема удаления проведения похожа на обычную схему проведения, только в ней основных процедур не 6 (процедур в обработке проведения "Отразить" + ИмяРегистра (3) может быть несколько), а 4 необходимых только для удаления движений. Тут вызываются процедуры только общего модуля ПроведениеСерверУТ. Если сравнивать с обработкой проведения, то в обработке удаления проведения будут использоваться процедуры 1-3-5-6, ИнициализироватьДанныеДокумента(2) и ОтразитьДвиженияДокумента(4) отсутствуют.
Схема проверки Контролей при проведении документов.
Для того чтобы разобраться с контролями, можно взять, к примеру Документ Акт выполненных работ. В Обработке проведения есть процедуры СформироватьСписокРегистровДляКонтроля и ВыполнитьКОнтрольРезультатовПроведения. Они используются для выполнения контролей по регистрам.
Схема контроля при проведении:
1. СформироватьСписокРегистровДляКонтроля;
2. ВыполнитьКонтрольРезультатовПроведения;
1.
В процедуре видно, что если РежимЗаписи документа = Проведение, то добавляется 2 регистра, по которым будет проходить контроль. В Дополнительные свойства "ДляПроведения" вставляется свойство "РегистрыДляПроведения" с массивом регистров для контроля.
2.
Процедура ВыполнитьКонтрольРезультатовПроведения выполняет контроли по различным регистрам конфигурации.
Тут следует обратить внимание на процедуру ЕстьИзмененияВТаблице, в ней определяется по флагу, есть ли изменения в таблице регистра, если есть, то контроль будет выполняться. Есть ли изменения по данному регистру определяется в самом регистре в модуле набора записей в процедурах ПередЗаписью и ПриЗаписи. ПередЗаписью берутся данные, которые были до, а ПриЗаписи как правило через ОБЪЕДЕНИТЬ ВСЕ берется разница движений, и если разница между движениями есть, то взводится флаг ДвижениеСвободныеОстаткиИзменение, который и проверяется.
Далее добавляются запросы контроллей в один большой пакет запросов, а также в МассивКонтролей добавляются контроли, по которым будут проводится контроли.
В конце процедуры выполняется ПакетЗапросов, и если в есть не пустые результаты запроса из массива результатов, то из МассивКонтролей берется ИмяКонтроля и далее в много условном операторе Если ИначеЕсли ... КонецЕсли для каждого контроля выполняется своя процедура отработки сообщений об ошибках.
Надеюсь в этой статье мне удалось немного упростить ознакомление с типовой схемой проведения для тех, кто только встретился с этим механизмом.