Как проводятся документы в типовых конфигурациях от 1С: дополнение

13.02.23

Разработка - Механизмы типовых конфигураций

Вот и до меня дошел обновленный механизм проведения документов. С прошлой статьи механизм сильно изменился, и решено было кратко описать нововведения и изменения по сравнению с тем, что было раньше. А также разобрать создание и добавления в УМ (учетный механизм) регистра накопления и неподчиненного регистратору регистра сведений. Поэтому в этой статье могут быть опущены какие-то ключевые моменты.

Вот и до меня дошел обновленный механизм проведения документов. С прошлой статьи механизм сильно изменился, и решено было кратко описать нововведения  и изменения по сравнению с тем, что было раньше. А также разобрать создание и добавления в УМ (учетный механизм) регистра накопления и неподчиненного регистратору регистра сведений. Поэтому в этой статье могут быть опущены какие-то ключевые моменты. Механизм был разобран на версии ERP 2.5.9. Но думаю, что на других современных конфигурациях он такой же.

Ниже сначала будут описаны нудные моменты, которые были мной отмечены как новые отличия, и если хотите, можете сразу перейти к практике доработки в пункт 3.

1. Основные сведения о новом механизме проведения документов.

Был разобран новый механизм проведения. Выявлены следующие отличия:
Теперь основные алгоритмы механизма вынесены в общий модуль ПроведениеДокументов.

В событии ПередЗаписью() вызывается процедура: ПроведениеДокументов.ПередЗаписьюДокумента(ЭтотОбъект, РежимЗаписи, РежимПроведения);
Которая инициализирует свойства, необходимые для проведения документа.

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

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

В механизме проведения участвуют учетные механизмы конфигурации, которые описаны в функции ПроведениеДокументов. УчетныеМеханизмыКонфигурации(). Каждому механизму соответствует свое имя модуля менеджера или общего модуля, затем в модуле механизма определяются параметры механизма:


 


В т.ч. подчиненные (движимые регистры), по которым документ делает движения.

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

Перед записью движений если есть производные движения учетный механизм может вызывать процедуру ПередЗаписьюДвиженийДокумента() из модуля учетного механизма.

После записи движений если есть производные движения учетный механизм может вызывать процедуру ПослеЗаписиДвиженийДокумента() из модуля учетного механизма.

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

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

2. Важные моменты, которые стоит учитывать в новом механизме.

Важные моменты, которые стоит учитывать в новом механизме:

  • Регистры выносим в учетные механизмы по областям использования в документах (Закупки, Продажи, Взаиморасчеты и т.д.). Например пример_Закупки будет использоваться в документах закупки и содержать в себе регистры, используемые в этих документах. Определение движимых регистров не обязательно означает, что документ должен делать движения по этим регистрам.
  • Если в движимых регистрах документа есть распределение движений по периоду (к примеру, списание ОС), то при доработке требуется учесть в механизме контроля дат изменений (сам метод ТекстыЗапросовКонтрольДатыЗапретаПоТаблицеИзменений() обязательно должен быть определен в модуле учетного механизма).
  • Если необходимо выполнить отложенные движения по регистру, то добавляем через параметры учетного механизма в массив КонтрольныеРегистрыЗаданий.

3. Добавление нового документа пример_ТестовыйДокумент и регистра накопления пример_ТестовыйРегистр.

Добавим документ пример_ТестовыйДокумент, регистр накопления пример_ТестовыйРегистр. Сделаем у регистра регистратором новый документ.

3.1. Модуль объекта документа пример_ТестовыйДокумент
В модуле объекта в обработчиках ПередЗаписью, ПриЗаписи, ОбработкаПроведения, ОбработкаУдаленияПроведения добавим вызовы процедур из общего модуля ПроведениеДокументов:

 
 3.1.

 

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

Процедура ПриЗаписи(Отказ)
    ПроведениеДокументов.ПриЗаписиДокумента(ЭтотОбъект, Отказ);
КонецПроцедуры

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    ПроведениеДокументов.ОбработкаПроведенияДокумента(ЭтотОбъект, Отказ);
КонецПроцедуры

Процедура ОбработкаУдаленияПроведения(Отказ)
    ПроведениеДокументов.ОбработкаУдаленияПроведенияДокумента(ЭтотОбъект, Отказ);
КонецПроцедуры

 

3.2. Общий модуль нового учетного механизма пример_ПроведениеДокументовЛокализация
Для регистрации учетного механизма добавим модуль пример_ПроведениеДокументовЛокализация и в нем опишем процедуру:

 
 3.2.1.

 

#Область СлужебныйПрограммныйИнтерфейс
// Описывает учетные механизмы используемые в локализуемой конфигурации.
// Параметры:
//  МеханизмыКонфигурации - Структура - список учетных механизмов,
//              где Ключ - имя механизма, а Значение - модуль реализующий интерфейс проведения.
//
Процедура ДополнитьУчетныеМеханизмыКонфигурации(МеханизмыКонфигурации) Экспорт
    //++ Локализация
    МеханизмыКонфигурации.Вставить("пример_ТестовыйУчетныйМеханизм", "пример_ТестовыйУчетныйМеханизмСервер");
    //-- Локализация
КонецПроцедуры
#КонецОбласти

 

В общем модуле ПроведениеДокументов в функции УчетныеМеханизмыКонфигурации() добавим вызов нашего модуля локализации:

 
 3.2.2.
 // Описывает учетные механизмы используемые в конфигурации.
//
// Возвращаемое значение:
//     Структура Из КлючИЗначение - Где:
//             * Ключ - Строка - Имя механизма
//             * Значение - Строка - Имя модуля менеджера
Функция УчетныеМеханизмыКонфигурации() Экспорт
    МеханизмыКонфигурации = Новый Структура;
    // тут определение типовых механизмов конфигурации
    пример_ПроведениеДокументовЛокализация.ДополнитьУчетныеМеханизмыКонфигурации(МеханизмыКонфигурации);
    Возврат МеханизмыКонфигурации;
КонецФункции

 

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

 
 3.3.

 

#Область ПрограммныйИнтерфейс
#Область Проведение
// Формирует параметры для проведения документа по регистрам учетного механизма через общий механизм проведения.
//
// Параметры:
//  Документ - ДокументОбъект - записываемый документ
//  Свойства - ФиксированнаяСтруктура - свойства документа (См. ПроведениеДокументов.СвойстваДокумента).
//
// Возвращаемое значение:
//  Структура - параметры учетного механизма (См. ПроведениеДокументов.ПараметрыУчетногоМеханизма()).
//
Функция ПараметрыДляПроведенияДокумента(Документ, Свойства) Экспорт
    Параметры = ПроведениеДокументов.ПараметрыУчетногоМеханизма();
    // Проведение
    Если Свойства.РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
        Параметры.ПодчиненныеРегистры.Добавить(Метаданные.РегистрыНакопления.пример_ТестовыйРегистр);
    КонецЕсли;
    // Контроль
    Если Свойства.РежимЗаписи <> РежимЗаписиДокумента.Запись Тогда
        Параметры.КонтрольныеРегистрыИзменений.Добавить(Метаданные.РегистрыНакопления.пример_ТестовыйРегистр);
    КонецЕсли;
    Возврат Параметры;
КонецФункции
// Процедура формирования движений по подчиненным регистрам
//
// Параметры:
//    ТаблицыДляДвижений - Структура - таблицы данных документа
//    Движения - КоллекцияДвижений - коллекция наборов записей движений документа
//    Отказ - Булево - признак отказа от проведения документа.
//
Процедура ОтразитьДвижения(ТаблицыДляДвижений, Движения, Отказ) Экспорт
    Если Отказ Тогда
        Возврат;
    КонецЕсли;
    ПроведениеДокументов.ОтразитьДвижения(ТаблицыДляДвижений, Движения, "пример_ТестовыйРегистр");
КонецПроцедуры

// Формирует тексты запросов для контроля изменений записанных движений регистров.
//
// Параметры:
//  Запрос - Запрос - запрос, хранящий параметры используемые в списке запросов
//  ТекстыЗапроса - СписокЗначений - список текстов запросов и их имен.
//  Документ - ДокументОбъект - записываемый документ.
//
Процедура ИнициализироватьДанныеКонтроляИзменений(Запрос, ТекстыЗапроса, Документ) Экспорт
    Если ПроведениеДокументов.ЕстьЗаписиВТаблице(Документ, "Движенияпример_ТестовыйРегистрИзменение") Тогда
        ТекстЗапроса =
            "ВЫБРАТЬ
            |    ТаблицаОстатков.Склад КАК Склад,
            |    ТаблицаОстатков.Номенклатура КАК Номенклатура,
            |    ТаблицаОстатков.КоличествоОстаток КАК Количество
            |ИЗ
            |    РегистрНакопления.пример_ТестовыйРегистр.Остатки(
            |            ,
            |            Склад В
            |                (ВЫБРАТЬ
            |                    Таблица.Склад КАК Склад
            |                ИЗ
            |                    Движенияпример_ТестовыйРегистрИзменение КАК Таблица)) КАК ТаблицаОстатков
            |ГДЕ
            |    ТаблицаОстатков.КоличествоОстаток < 0";
        ТекстыЗапроса.Добавить(ТекстЗапроса, "Ошибкипример_ТестовыйРегистр");
    КонецЕсли;
КонецПроцедуры

// Выводит сообщения пользователю при наличии ошибок контроля изменений записанных движений регистров.
//
// Параметры:
//  РезультатыКонтроля - Структура - таблицы с результатами контроля изменений
//  Документ - ДокументОбъект - записываемый документ
//  Отказ - Булево - признак отказа от проведения документа.
//
Процедура СообщитьОРезультатахКонтроляИзменений(РезультатыКонтроля, Документ, Отказ) Экспорт
    Если ПроведениеДокументов.ЕстьЗаписиВТаблице(Документ, "Движенияпример_ТестовыйРегистрИзменение") Тогда
        ШаблонСообщенияПоСкладуИНоменклатуре = НСтр("ru = 'По складу %1 и номенклатуре %2 списывается больше чем есть на остатках на %3'");
        Для каждого СтрокаОшибки Из РезультатыКонтроля.Ошибкипример_ТестовыйРегистр Цикл
            Если ЗначениеЗаполнено(СтрокаОшибки.Количество) Тогда
                ТекстСообщения = СтрШаблон(ШаблонСообщенияПоСкладуИНоменклатуре, СтрокаОшибки.Склад, СтрокаОшибки.Номенклатура, -СтрокаОшибки.Количество);
                ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ТекстСообщения, Документ,,, Отказ);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры

// Дополняет текст запроса механизма проверки даты запрета по таблице изменений.
// 
// Параметры:
//     Запрос - Запрос - используется для установки параметров запроса.
// 
// Возвращаемое значение:
//    Соответствие - соответствие имен таблиц изменения регистров и текстов запросов.
//    
Функция ТекстыЗапросовКонтрольДатыЗапретаПоТаблицеИзменений(Запрос) Экспорт
    СоответствиеТекстовЗапросов = Новый Соответствие();
    Возврат СоответствиеТекстовЗапросов;
КонецФункции
#КонецОбласти
#КонецОбласти

 

Функция ПараметрыДляПроведенияДокумента() содержит в себе определение параметров проведения и контроля по регистру пример_ТестовыйРегистр.

В процедуре ОтразитьДвижения() добавим отражение движений по новому регистру пример_ТестовыйРегистр. Процедура отражает движения только по подчиненным регистрам.

В процедуре ИнициализироватьДанныеКонтроляИзменений() добавим инициализацию данных для контроля.

В процедуре СообщитьОРезультатахКонтроляИзменений() сообщим, если контроль сработал.

В функцию ТекстыЗапросовКонтрольДатыЗапретаПоТаблицеИзменений() при необходимости добавим текст запросов контроля даты запрета изменений.

3.4. Модуль менеджера документа пример_ТестовыйДокумент
В модуле менеджера документа пример_ТестовыйДокумент в процедуре ЗарегистрироватьУчетныеМеханизмы() необходимо описать используемые учетные механизмы:

 
 3.4.1.

 


// Описывает учетные механизмы используемые в документе для регистрации в механизме проведения.
//
// Параметры:
//  МеханизмыДокумента - Массив - список имен учетных механизмов, для которых будет выполнена
//              регистрация в механизме проведения.
//
Процедура ЗарегистрироватьУчетныеМеханизмы(МеханизмыДокумента) Экспорт
    МеханизмыДокумента.Добавить("пример_ТестовыйУчетныйМеханизм");
КонецПроцедуры

 


Затем в процедуре ДополнительныеИсточникиДанныхДляДвижений() определить дополнительные источники данных:

 
 3.4.2.

 

Функция ДополнительныеИсточникиДанныхДляДвижений(ИмяРегистра) Экспорт
    ИсточникиДанных = Новый Соответствие;
    Возврат ИсточникиДанных; 
КонецФункции

 


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

 
 3.4.3.

 

// Возвращает таблицы для движений, необходимые для проведения документа по регистрам учетных механизмов.
//
// Параметры:
//  Документ - ДокументСсылка - ссылка на документ, по которому необходимо получить данные
//  Регистры - Структура - список имен регистров, для которых необходимо получить таблицы
//  ДопПараметры - Структура - дополнительные параметры для получения данных, определяющие контекст проведения.
//
// Возвращаемое значение:
//  Структура - коллекция элементов - таблиц значений - данных для отражения в регистр.
//
Функция ДанныеДокументаДляПроведения(Документ, Регистры, ДопПараметры = Неопределено) Экспорт
    Если ДопПараметры = Неопределено Тогда
        ДопПараметры = ПроведениеДокументов.ДопПараметрыИнициализироватьДанныеДокументаДляПроведения();
    КонецЕсли;
    Запрос            = Новый Запрос;
    ТекстыЗапроса    = Новый СписокЗначений;
    Если Не ДопПараметры.ПолучитьТекстыЗапроса Тогда
        ////////////////////////////////////////////////////////////////////////////
        // Создадим запрос инициализации движений
        ЗаполнитьПараметрыИнициализации(Запрос, Документ);
        ////////////////////////////////////////////////////////////////////////////
        // Сформируем текст запроса
        ТекстЗапросаТаблицапример_ТестовыйРегистр(Запрос, ТекстыЗапроса, Регистры);
    КонецЕсли;
    Возврат ПроведениеДокументов.ИнициализироватьДанныеДокументаДляПроведения(Запрос, ТекстыЗапроса, ДопПараметры);
КонецФункции
Процедура ЗаполнитьПараметрыИнициализации(Запрос, ДокументСсылка)
    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
    Запрос.УстановитьПараметр("Ссылка", ДокументСсылка);
    Запрос.Текст =
    "ВЫБРАТЬ
    |    пример_ТестовыйДокумент.Дата КАК Период
    |ИЗ
    |    Документ.пример_ТестовыйДокумент КАК пример_ТестовыйДокумент
    |ГДЕ
    |    пример_ТестовыйДокумент.Ссылка = &Ссылка";
    Реквизиты = Запрос.Выполнить().Выбрать();
    Реквизиты.Следующий();
    Запрос.УстановитьПараметр("Период", Реквизиты.Период);
КонецПроцедуры

Функция ТекстЗапросаТаблицапример_ТестовыйРегистр(Запрос, ТекстыЗапроса, Регистры)
    ИмяРегистра = "пример_ТестовыйРегистр";
    Если НЕ ПроведениеДокументов.ТребуетсяТаблицаДляДвижений(ИмяРегистра, Регистры) Тогда
        Возврат "";
    КонецЕсли; 
    ТекстЗапроса = "ВЫБРАТЬ
                   |    ТаблицаТовары.НомерСтроки КАК НомерСтроки,
                   |    ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) КАК ВидДвижения,
                   |    &Период КАК Период,
                   |    ТаблицаТовары.Ссылка.Склад КАК Склад,
                   |    ТаблицаТовары.Номенклатура КАК Номенклатура,
                   |    ТаблицаТовары.Количество КАК Количество,
                   |    ТаблицаТовары.Сумма КАК Сумма
                   |ИЗ
                   |    Документ.пример_ТестовыйДокумент.ТоварыПриход КАК ТаблицаТовары
                   |ГДЕ
                   |    ТаблицаТовары.Ссылка = &Ссылка
                   |
                   |ОБЪЕДИНИТЬ ВСЕ
                   |
                   |ВЫБРАТЬ
                   |    ТаблицаТовары.НомерСтроки,
                   |    ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход),
                   |    &Период,
                   |    ТаблицаТовары.Ссылка.Склад,
                   |    ТаблицаТовары.Номенклатура,
                   |    ТаблицаТовары.Количество,
                   |    ТаблицаТовары.Сумма
                   |ИЗ
                   |    Документ.пример_ТестовыйДокумент.ТоварыРасход КАК ТаблицаТовары
                   |ГДЕ
                   |    ТаблицаТовары.Ссылка = &Ссылка";
    ТекстыЗапроса.Добавить(ТекстЗапроса, ИмяРегистра);
    Возврат ТекстЗапроса;
КонецФункции

 

3.5. Модуль набора записей регистра накопления пример_ТестовыйРегистр
В модуле набора записей регистра пример_ТестовыйРегистр опишем стандартные события ПередЗаписью и ПослеЗаписи. Тут все как в старом механизме:

 
3.5. 

 

Процедура ПередЗаписью(Отказ, Замещение)
    
    Если ОбменДанными.Загрузка Или Не ПроведениеДокументов.РассчитыватьИзменения(ДополнительныеСвойства) Тогда
        Возврат;
    КонецЕсли;
    
    БлокироватьДляИзменения = Истина;
    
    // Текущее состояние набора помещается во временную таблицу "ДвиженияОстаткиДрагметалловПередЗаписью",
    // чтобы при записи получить изменение нового набора относительно текущего.

    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("Регистратор", Отбор.Регистратор.Значение);
    Запрос.УстановитьПараметр("ЭтоНовый",    ДополнительныеСвойства.СвойстваДокумента.ЭтоНовый);
    Запрос.МенеджерВременныхТаблиц = ДополнительныеСвойства.МенеджерВременныхТаблиц;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    Таблица.Склад КАК Склад,
    |    Таблица.Номенклатура КАК Номенклатура,
    |    ВЫБОР
    |        КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    |            ТОГДА Таблица.Количество
    |        ИНАЧЕ -Таблица.Количество
    |    КОНЕЦ КАК КоличествоПередЗаписью,
    |    ВЫБОР
    |        КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    |            ТОГДА Таблица.Сумма
    |        ИНАЧЕ -Таблица.Сумма
    |    КОНЕЦ КАК СуммаПередЗаписью
    |ПОМЕСТИТЬ Движенияпример_ТестовыйРегистрПередЗаписью
    |ИЗ
    |    РегистрНакопления.пример_ТестовыйРегистр КАК Таблица
    |ГДЕ
    |    Таблица.Регистратор = &Регистратор
    |    И НЕ &ЭтоНовый";
    Запрос.Выполнить();
    
КонецПроцедуры

Процедура ПриЗаписи(Отказ, Замещение)
    Если ОбменДанными.Загрузка Или Не ПроведениеДокументов.РассчитыватьИзменения(ДополнительныеСвойства) Тогда
        Возврат;
    КонецЕсли;
    
    // Рассчитывается изменение нового набора относительно текущего с учетом накопленных изменений
    // и помещается во временную таблицу.
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("Регистратор", Отбор.Регистратор.Значение);
    Запрос.МенеджерВременныхТаблиц = ДополнительныеСвойства.МенеджерВременныхТаблиц;
    Запрос.Текст =
    "ВЫБРАТЬ
    |    ТаблицаИзменений.Склад КАК Склад,
    |    ТаблицаИзменений.Номенклатура КАК Номенклатура,
    |    СУММА(ТаблицаИзменений.Количество) КАК Количество,
    |    СУММА(ТаблицаИзменений.Сумма) КАК Сумма
    |ПОМЕСТИТЬ Движенияпример_ТестовыйРегистрИзменение
    |ИЗ
    |    (ВЫБРАТЬ
    |        Таблица.Склад КАК Склад,
    |        Таблица.Номенклатура КАК Номенклатура,
    |        Таблица.КоличествоПередЗаписью КАК Количество,
    |        Таблица.СуммаПередЗаписью КАК Сумма
    |    ИЗ
    |        Движенияпример_ТестовыйРегистрПередЗаписью КАК Таблица
    |    
    |    ОБЪЕДИНИТЬ ВСЕ
    |    
    |    ВЫБРАТЬ
    |        Таблица.Склад,
    |        Таблица.Номенклатура,
    |        ВЫБОР
    |            КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    |                ТОГДА -Таблица.Количество
    |            ИНАЧЕ Таблица.Количество
    |        КОНЕЦ,
    |        ВЫБОР
    |            КОГДА Таблица.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
    |                ТОГДА -Таблица.Сумма
    |            ИНАЧЕ Таблица.Сумма
    |        КОНЕЦ
    |    ИЗ
    |        РегистрНакопления.пример_ТестовыйРегистр КАК Таблица
    |    ГДЕ
    |        Таблица.Регистратор = &Регистратор) КАК ТаблицаИзменений
    |
    |СГРУППИРОВАТЬ ПО
    |    ТаблицаИзменений.Склад,
    |    ТаблицаИзменений.Номенклатура
    |
    |ИМЕЮЩИЕ
    |    (СУММА(ТаблицаИзменений.Количество) <> 0
    |        ИЛИ СУММА(ТаблицаИзменений.Сумма) <> 0)
    |;
    |
    |////////////////////////////////////////////////////////////////////////////////
    |УНИЧТОЖИТЬ Движенияпример_ТестовыйРегистрПередЗаписью";
    
    МассивРезультатовЗапроса = Запрос.ВыполнитьПакет();
    РезультатЗапроса = МассивРезультатовЗапроса[0]; // РезультатЗапроса
    Выборка = РезультатЗапроса.Выбрать();
    ЕстьИзменения = Выборка.Следующий() И Выборка.Количество > 0;
    ПроведениеДокументов.ЗарегистрироватьТаблицуКонтроля(ДополнительныеСвойства,
        "Движенияпример_ТестовыйРегистрИзменение", ЕстьИзменения);
КонецПроцедуры

 

4. Добавление нового независимого регистра сведений пример_ТестовыйНезависимыйРегистр.

4.1. Общий модуль нового учетного механизма пример_ТестовыйУчетныйМеханизмСервер
Добавим в функции ПараметрыДляПроведенияДокумента() в массив НезависимыеРегистры метаданные нового независимого регистра:

 
 4.1.

 

Функция ПараметрыДляПроведенияДокумента(Документ, Свойства) Экспорт
Параметры = ПроведениеДокументов.ПараметрыУчетногоМеханизма();
// Проведение
Если Свойства.РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
Параметры.ПодчиненныеРегистры.Добавить(Метаданные.РегистрыНакопления.пример_ТестовыйРегистр);
           Параметры.НезависимыеРегистры.Добавить(Метаданные.РегистрыСведений.пример_ТестовыйНезависимыйРегистр);
КонецЕсли;
// Контроль
Если Свойства.РежимЗаписи <> РежимЗаписиДокумента.Запись Тогда
    Параметры.КонтрольныеРегистрыИзменений.Добавить(Метаданные.РегистрыНакопления.пример_ТестовыйРегистр);
КонецЕсли;
Возврат Параметры;
КонецФункции

 

Добавим новую процедуру ЗаписатьДанные(), которая формирует движения по независимым регистрам оперативного учета товаров организаций:

 

 

// Процедура формирования движений по независимым регистрам оперативного учета товаров организаций.
//
// Параметры:
//    ТаблицыДляДвижений - Структура - таблицы данных документа
//    Документ - ДокументСсылка - ссылка на документ
//    МенеджерВременныхТаблиц - МенеджерВременныхТаблиц - менеджер временных таблиц документа
//    Отказ - Булево - признак отказа от проведения документа.
//
Процедура ЗаписатьДанные(ТаблицыДляДвижений, Документ, МенеджерВременныхТаблиц, Отказ) Экспорт
    Если Отказ Тогда
        Возврат;
    КонецЕсли;
    ИмяТаблицы = "Таблица" + "пример_ТестовыйНезависимыйРегистр";
    Если ТаблицыДляДвижений.Свойство(ИмяТаблицы)
        И ЗначениеЗаполнено(ТаблицыДляДвижений[ИмяТаблицы]) Тогда
        Для Каждого СтрокаТаблицы Из ТаблицыДляДвижений[ИмяТаблицы] Цикл
            МенеджерЗаписи = РегистрыСведений.пример_ТестовыйНезависимыйРегистр.СоздатьМенеджерЗаписи();
            ЗаполнитьЗначенияСвойств(МенеджерЗаписи, СтрокаТаблицы);
            МенеджерЗаписи.Записать(Истина);
        КонецЦикла;
    КонецЕсли; 
КонецПроцедуры

 

4.2. Модуль менеджера документа пример_ТестовыйДокумент
Доработки в модуле менеджера документа пример_ТестовыйДокумент дополнительно, аналогично старому:

 
 4.2.

 

// Возвращает таблицы для движений, необходимые для проведения документа по регистрам учетных механизмов.
//
// Параметры:
//  Документ - ДокументСсылка - ссылка на документ, по которому необходимо получить данные
//  Регистры - Структура - список имен регистров, для которых необходимо получить таблицы
//  ДопПараметры - Структура - дополнительные параметры для получения данных, определяющие контекст проведения.
//
// Возвращаемое значение:
//  Структура - коллекция элементов - таблиц значений - данных для отражения в регистр.
//
Функция ДанныеДокументаДляПроведения(Документ, Регистры, ДопПараметры = Неопределено) Экспорт
    Если ДопПараметры = Неопределено Тогда
        ДопПараметры = ПроведениеДокументов.ДопПараметрыИнициализироватьДанныеДокументаДляПроведения();
    КонецЕсли;
    Запрос            = Новый Запрос;
    ТекстыЗапроса    = Новый СписокЗначений;
    Если Не ДопПараметры.ПолучитьТекстыЗапроса Тогда
        ////////////////////////////////////////////////////////////////////////////
        // Создадим запрос инициализации движений
        ЗаполнитьПараметрыИнициализации(Запрос, Документ);
        ////////////////////////////////////////////////////////////////////////////
        // Сформируем текст запроса
        ТекстЗапросаТаблицапример_ТестовыйРегистр(Запрос, ТекстыЗапроса, Регистры);
        ТекстЗапросаТаблицапример_ТестовыйНезависимыйРегистр(Запрос, ТекстыЗапроса, Регистры);    
    КонецЕсли;
    Возврат ПроведениеДокументов.ИнициализироватьДанныеДокументаДляПроведения(Запрос, ТекстыЗапроса, ДопПараметры);
КонецФункции
Функция ТекстЗапросаТаблицапример_ТестовыйНезависимыйРегистр(Запрос, ТекстыЗапроса, Регистры)
    ИмяРегистра = "пример_ТестовыйНезависимыйРегистр";
    Если Не ПроведениеДокументов.ТребуетсяТаблицаДляДвижений(ИмяРегистра, Регистры) Тогда
        Возврат "";
    КонецЕсли;
    ТекстЗапроса =
    "ВЫБРАТЬ
    |    ВложенныйЗапрос.Документ КАК Документ,
    |    СУММА(ВложенныйЗапрос.ОбщаяСумма) КАК ОбщаяСумма
    |ИЗ
    |    (ВЫБРАТЬ
    |        пример_ТестовыйДокументТоварыПриход.Ссылка КАК Документ,
    |        СУММА(пример_ТестовыйДокументТоварыПриход.Сумма) КАК ОбщаяСумма
    |    ИЗ
    |        Документ.пример_ТестовыйДокумент.ТоварыПриход КАК пример_ТестовыйДокументТоварыПриход
    |    ГДЕ
    |        пример_ТестовыйДокументТоварыПриход.Ссылка = &Ссылка
    |    
    |    СГРУППИРОВАТЬ ПО
    |        пример_ТестовыйДокументТоварыПриход.Ссылка
    |    
    |    ОБЪЕДИНИТЬ ВСЕ
    |    
    |    ВЫБРАТЬ
    |        пример_ТестовыйДокументТоварыРасход.Ссылка,
    |        СУММА(пример_ТестовыйДокументТоварыРасход.Сумма)
    |    ИЗ
    |        Документ.пример_ТестовыйДокумент.ТоварыРасход КАК пример_ТестовыйДокументТоварыРасход
    |    ГДЕ
    |        пример_ТестовыйДокументТоварыРасход.Ссылка = &Ссылка
    |    
    |    СГРУППИРОВАТЬ ПО
    |        пример_ТестовыйДокументТоварыРасход.Ссылка) КАК ВложенныйЗапрос
    |
    |СГРУППИРОВАТЬ ПО
    |    ВложенныйЗапрос.Документ";
    ТекстыЗапроса.Добавить(ТекстЗапроса, ИмяРегистра);
    Возврат ТекстЗапроса;
КонецФункции

 

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

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

infostart.ru/public/1185321/

infostart.ru/1c/articles/1343740/

проведение механизм проведения учетный механизм добавление нового документа добавление нового регистра накопления добавление нового регистра сведений

См. также

СКД Механизмы типовых конфигураций Запросы Программист Платформа 1С v8.3 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Россия Бесплатно (free)

Работая с типовыми отчетами в конфигурациях «Зарплата и управление персоналом, редакция 3», «Зарплата и кадры государственного учреждения, редакция 3» и подобных, в схемах компоновки данных можно встретить конструкции запросов, которые обращаются к некоторым виртуальным таблицам.

20.08.2024    1872    PROSTO-1C    0    

18

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:Комплексная автоматизация 2.х Россия Бесплатно (free)

Эта ошибка была обнаружена мной в типовой конфигурации 1С:Комплексная автоматизация 2 (2.5.16.115), БСП версия 3.1.9.302. Возникает она после того, как вы добавляете в расширение бизнес-процесс или задачу, выполняете обновление идентификаторов метаданных расширений, но ошибка при записи любого элемента справочника "Профили групп доступа" всё равно остаётся.

01.07.2024    1916    Vidz    0    

11

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Очень часто в написании кода требуется обращаться к предопределённым значениям. Если идёт обращение к типовым предопределённым значениям, то проблем не возникает.

24.06.2024    1172    olja-ljaaa    0    

3

Механизмы типовых конфигураций Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Проблемы при создании ресурсной спецификации. Связь настроек спецификации и настроек структуры заказа в ЕРП 2.5.

06.05.2024    1284    It-digit    1    

2

Механизмы типовых конфигураций Ценообразование, анализ цен Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Абонемент ($m)

Продолжение темы вынесения кусков повторно-используемого кода в запрос. В прошлый раз мы сделали это с вычислением пользовательских формул. Здесь замахнулись на формулы, задаваемые пользователем запросами.

1 стартмани

11.04.2024    1122    tango    5    

3
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Поручик 4693 13.02.23 12:15 Сейчас в теме
Кодописание ради кодописания. Лишь бы чем-то заняться.
Hogyoku; корум; r2d255; Sodrugestvo; NoRazum; Сисой; bilex; maksa2005; +8 2 Ответить
2. KOTzilla 22 13.02.23 12:35 Сейчас в теме
"которые описаны в функции ПроцедениеДокументов." Очепятка
3. skv_79 380 13.02.23 18:11 Сейчас в теме
4. Asmody 14.02.23 09:36 Сейчас в теме
"1С - это low-code система" - слышали такую мантру?
cheburashka; +1 Ответить
5. glek 120 14.02.23 10:13 Сейчас в теме
Здорово. Спасибо тебе мил человек большое.
6. Сисой 88 14.02.23 11:12 Сейчас в теме
Чего только извращенцы не придумают вместо ООП...
creatermc; cariola; r2d255; +3 Ответить
7. dhurricane 14.02.23 11:16 Сейчас в теме
(6) Так это разные команды. Одни не реализуют поддержку ООП, соответственно другим приходится вот так вот извращаться.
sv_prostomolotov; pavlov_dv; +2 Ответить
14. imiron_ru 108 09.10.24 11:16 Сейчас в теме
(6) а чем тут может помочь ООП, расскажите пжл мне тёмному?
8. AABelyavtsev 19.06.23 14:52 Сейчас в теме
Для чего нужна функция ДополнительныеИсточникиДанныхДляДвижений()?
9. Sardukar 58 13.07.23 04:01 Сейчас в теме
А что такое "производные движения "? А то у меня почему то не отрабатывает ПослеЗаписиДвиженийДокумента()
10. user2064464 11.03.24 13:47 Сейчас в теме
Очень полезный материал. Спасибо большое!
11. DoReMu 5 13.08.24 19:56 Сейчас в теме
Подскажите, а если мне требуется сделать запрос, с его результатом произвести некоторые операции и на основании этого подготовить таблицу с движениями, в какой процедуре это следует делать?
13. baracuda 2 26.09.24 10:27 Сейчас в теме
(11) очень хороший и актуальный вопрос кстати.
15. StarMakc 17.10.24 12:24 Сейчас в теме
(11) я это делал в модуле менеджера документа в ДанныеДокументаДляПроведения(...)
12. baracuda 2 26.09.24 10:27 Сейчас в теме
Спасибо огромное!
Статья очень сильно помогла при добавлении нового документа в erp.
16. Vidz 11 01.12.24 16:27 Сейчас в теме
Спасибо за статью.
Подскажите, а в чём глубинная суть этих самых независимых регистров с точки зрения механизма проведения документов в БСП, как вы считаете??
Я тут маюсь: добавил соответствующи РС, всё настроил. Пользователь проводит док - в нужном РС пусто. Смотрю код процедуры ПроведениеДокументов.ПриЗаписиДокумента:

Процедура ПриЗаписиДокумента(Документ, Отказ) Экспорт
	
	Если СвойстваДокумента(Документ).РежимЗаписи = РежимЗаписиДокумента.Запись Тогда
		ЗаписатьДокумент(Документ, Отказ);
	ИначеЕсли СвойстваДокумента(Документ).РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения Тогда
		ЗаписатьДокумент(Документ, Отказ);
		ПровестиДокумент(Документ, Отказ, Неопределено);	
	КонецЕсли;
		
КонецПроцедуры
Показать


Дык, ежели пользователь будет жмякает провести в моём РС ничего не будет - всегда, потому что РежимЗаписи.Проведение. А мне, по сути, надо чтобы при каждой записи/проведении там была нужная мне запись.
Я понимаю, что можно самому всё сделать, без этих наворотов, но в принцепи, для каких РС такой код будет работать, если пользователь всегда будет жать провести?!
17. Vidz 11 02.12.24 05:33 Сейчас в теме
Нашёл причину проблемы у себя. Всё-таки кое-что забыл прописать:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
	
	ПроведениеДокументов.ОбработкаПроведенияДокумента(ЭтотОбъект, Отказ); // Вот там вызывается запись для независимых РС 

Оставьте свое сообщение