Альтернативный способ записи в регистры

20.10.20

Разработка - Механизмы платформы 1С

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

При первичной постановке задачи было требование «упростить перезаполненные регистра(ов) за прошлые периоды при его(их) расширении», но при реализации удалось получить гораздо больше плюсов, чем изначально ставилось, а именно:

Профит:

  • Быстрое перепроведение документов по одному или нескольким определенным регистрам, не трогая все остальные регистры.
  • Избежание взаимоблокировок из-за перекрестного захвата ресурсов.
  • Всегда четкое понимание, где располагаются алгоритмы, формирующий движения в регистре.
  • Возможность «плавного» перехода на способ проведения описанный в данной статье.

Допущения:

  • Предполагается использовать данную методику только для новых регистров добавляемых или добавленных ранее в конфигурацию – типовые регистры не трогаем.

Реализация:

 
 Модуль объекта (Документа)
 
 Общий модуль ОбщегоНазначенияПоРегистрам (Сервер, Вызов сервера)
 
 Модуль менеджера Регистра

Комментарии:

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

ОбщегоНазначенияПоРегистрам.СформироватьДвижения(Отказ, РежимПроведения, Ссылка);
 
 Ответы на возможные вопросы

Напоследок:

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

Реклама:

Используя Многопоточность. Универсальный «Менеджер потоков» 2.1 - можно дополнительно ускорить перепроведение документов с помощью данной методики.

Проведение регистры перепроведение

См. также

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

Эта небольшая статья - некоторого рода шпаргалка по файловым потокам: как и зачем с ними работать, какие преимущества это дает.

23.06.2024    7511    bayselonarrend    20    

154

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

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    5965    dsdred    16    

80

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Бесплатно (free)

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

24.01.2024    17799    YA_418728146    26    

71

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    23786    SeiOkami    48    

135

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

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14779    YA_418728146    7    

166
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. awk 744 20.10.20 17:05 Сейчас в теме
Немного критики...

Регистры должны иметь уникальные имена в рамках одного регистратора (не допускать один и тот же идентификатор, например, регистра сведений и регистра накоплений)


А пробовали так сделать? Это в принципе не возможно.

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


Как-то очень сложно.... Непонятно преимущество вызова "Божественной функции" из документа, что бы та вызвала функцию из модуля менеджера регистра. По моему, проще, функцию модуля менеджера вызвать напрямую из модуля объекта.

По моему тут нарушен принцип KISS.
Fox-trot; +1 Ответить
2. DarkAn 1093 20.10.20 17:14 Сейчас в теме
(1)
А пробовали так сделать? Это в принципе не возможно.

Я бы не писал если бы не проверил - см. скриншот.


(1)
По моему, проще, функцию модуля менеджера вызвать напрямую из модуля объекта.

Проще, но ни кто не гарантирует, что не будет перекрестного захват ресурсов - что может привести к взаимоблокировке.
Прикрепленные файлы:
4. awk 744 21.10.20 09:03 Сейчас в теме
(2)
Я бы не писал если бы не проверил - см. скриншот.


Вы не правы. Скриншет - не доказательство. Вы не сможете обновить базу.


Маркетинг_2011: Использование одинакового имени для перечисленных ниже объектов недопустимо
РегистрНакопления.Продажи
РегистрСведений.Продажи
При проверке метаданных обнаружены ошибки!
Операция не может быть выполнена.


Проще, но ни кто не гарантирует, что не будет перекрестного захват ресурсов - что может привести к взаимоблокировке.
А в вашем случае кто гарантирует?
6. DarkAn 1093 21.10.20 09:31 Сейчас в теме
(4)
Вы не правы. Скриншет - не доказательство. Вы не сможете обновить базу.

Соглашусь, до сохранения не доводил :) Увидел, что платформа позволяет создать. Уберу.

(4)
А в вашем случае кто гарантирует?

Как минимум запись регистров всегда производиться в в одной последовательности.
Для примера ДокументА и ДокументБ делают запись в 2а одинаковых регистра.
Без разницы как я напишу

ОбщегоНазначенияПоРегистрам.СформироватьДвижения(Отказ, РежимПроведения, Ссылка "Регистр1,Регистр2");

или
ОбщегоНазначенияПоРегистрам.СформироватьДвижения(Отказ, РежимПроведения, Ссылка "Регистр2,Регистр1");


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

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

Опять же данное замечание работает в том случае если в рамках проведения идет принудительная запись набора. Если же принудительная запись ни когда не делается, то соглашусь, что данного вызова можно не делать и вызов осуществлять сразу из модуля менеджера.
7. awk 744 21.10.20 09:36 Сейчас в теме
(6)Конвенция работает только до тех пор, пока ее соблюдают. А учитывая оговорку "для новых". Есть вполне не нулевая вероятность, что документ "А" вызовет "Божественную функцию", а документ "Б" нет.
8. DarkAn 1093 21.10.20 09:45 Сейчас в теме
(7)Ну а смысл брать на вооружение инструмент и использовать его наполовину? Хочешь - интегрируй и придерживайся правил, не хочешь - Ваше дело.

А "оговорка", относится не к предмету что с сегодняшнего числа, я хочу начать делать проведение подобным образом и вот от сегодняшнего числа я начинаю отсчет "новых". Нет. Новые - это значит все не типовые. И при переходе необходимо будет их все адаптировать.

Кроме того, я же не говорю, что Все должны так делать. Нет. Я предлагаю альтернативу, а уже Ваше решение использовать ее или нет. Кроме того, возможно в данном решении Вы или кто-то другой найдет для себя, что-то новое, или позволит взглянуть на привычные вещи под другим углом.
9. awk 744 21.10.20 09:54 Сейчас в теме
(8)
1. По опыту работы, если что-то можно обойти (а ваш механизм обойти проще, нежели использовать), то его обойдут - это лишь вопрос времени...

Гораздо лучше не пилить все в одно место, а делать что-то типа:

ОбработчикиПроведения = СуперМодуль.ПолучитьОбработчикиПроведения(Объект);
Для Каждого Обработчик Из ОбработчикиПроведения Цикл
   Обработчик.ЗаполнитьДвижения(Объект);
КонецЦикла;



Это позволит не нарушать стандарт используя небезопасную процедуру "Выполнить".
22. DarkAn 1093 21.10.20 17:34 Сейчас в теме
(9) С "Выполнить", хорошее замечание.
Скорректировал :)
12. tamepjlah 3 21.10.20 12:24 Сейчас в теме
(2)
Я бы не писал если бы не проверил - см. скриншот.

А обновить конфигуратор пробовали?
Прикрепленные файлы:
13. DarkAn 1093 21.10.20 12:33 Сейчас в теме
(12) я уже написал (6), что до сохранения не доводил :)
3. artbear 1563 20.10.20 19:36 Сейчас в теме
Интересная схема, конечно.

1 основной минус пока вижу для случаев, когда в один регистр пишут несколько документов.
в коде движения получается спагетти-код
Если ДокументА Тогда
ИначеЕсли ДокументБ Тогда и т.п.

2й минус - возможно, лишние запросы к документу, т.к. передается ссылка на документ в модуль регистра
а в обработке проведения документа доступен объект документа и доп.запросы не всегда нужны.

минус небольшой, т.к. часто все равно делаются доп.запросы

3 зачем делается отдельная транзакция для записи каждого регистра, если нет внешней транзакции?
ведь фактически получается, что может быть рассинхронизация записей в регистры для одного документа (

либо сделать общую транзакцию на запись всех регистров
либо дать возможность управления в основном методе
5. DarkAn 1093 21.10.20 09:14 Сейчас в теме
(3)
1 основной минус пока вижу для случаев, когда в один регистр пишут несколько документов.
в коде движения получается спагетти-код


Соглашусь, можно превратить в спагетти-код, но ни кто не запрещает в рамках модуля менеджера сделать вспомогательные процедуры и функции:

Если ДокументА Тогда
    ОбработкаДокументаА(Ссылка)
ИначеЕсли ДокументБ Тогда и т.п.
    ОбработкаДокументаБ(Ссылка)
...


Процедура ОбработкаДокументаА(Ссылка)
...
КонецПроцедуры
Показать



(3)
2й минус - возможно, лишние запросы к документу, т.к. передается ссылка на документ в модуль регистра
а в обработке проведения документа доступен объект документа и доп.запросы не всегда нужны.


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

3 зачем делается отдельная транзакция для записи каждого регистра, если нет внешней транзакции?

Это сделано специально, т.к. проведение по регистру можно делать отдельной обработкой и ни кто не гарантирует, что программист не забудет в ней заключить проведение в транзакцию. А это может привести к грязному чтению.
10. SlavaKron 21.10.20 10:14 Сейчас в теме
При отсутствии внешней транзакции, если получаем отказ на каком-нибудь наборе не первом из списка, получается, предыдущие наборы останутся записанными?
11. artbear 1563 21.10.20 10:56 Сейчас в теме
(10) ага, я про это и написал в своем сообщении (3) (
14. DarkAn 1093 21.10.20 12:36 Сейчас в теме
(10) В данном случае "да", но это уже работа не в типовом проведении, а скорее с помощью дополнительно обработки. Тут Вы можете сами организовать "внешнюю транзакцию" если она необходима, а можете не организовывать, но тогда подобные коллизии на совести программиста.
15. SlavaKron 21.10.20 12:42 Сейчас в теме
(14) Тогда эти транзакции – "медвежья услуга" программисту. Процедура должна делать только то, что ее просят.
16. DarkAn 1093 21.10.20 13:00 Сейчас в теме
(15) Предположим есть документ проводимый по нескольким регистрам. При стандартном проведении будет работать внешняя транзакция. В модуле менеджера регистра, мы считаем, что движения всегда делаются во время проведения и ни о каких проверках о транзакции тут речи быть не должно мы их тут и не описываем.

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

Для каждого Ссылка из Ссылки Цикл
    ОбщегоНазначенияПоРегистрам.СформироватьДвижения(Отказ, РежимПроведения, Ссылка "НашРегистр");
КонецЦикла;

И все. Данные за прошлые периоды будут перезаполнены и перезаписаны (конечно если эти данные есть).

А транзакция необходима, как я уже писал выше, для того чтобы когда будет выполнятся запись данных в регистр, через обработку, не происходило грязного чтения.
17. artbear 1563 21.10.20 13:11 Сейчас в теме
(16) я уже предлагал самый простой способ - дать возможность управления транзакцией вызывающему коду.
пусть клиент-разработчик сам решает, как и когда юзать транзакции, тогда точно не будет проблем при использовании продукта.
19. karpik666 3853 21.10.20 14:11 Сейчас в теме
(16) а если это движения по партиям? Зачем запускать процедуру перепроведения, если нужно заполнить только определенное поле? Какая-то сомнительная полезность.
20. DarkAn 1093 21.10.20 14:22 Сейчас в теме
(19) А если это не движения по партиям? Регистры разве используются только для партий?

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

Мы в свое время столкнулись с подобной необходимостью, реализовали, делимся.
Нет необходимости не используйте. Есть необходимость нездоровье.

Регистр сведений мы тоже (что уж греха таить) вычищали в 0, когда необходимо было поправить только 1 значение в 1 записи, а ИР под руками не было.
21. karpik666 3853 21.10.20 14:30 Сейчас в теме
(20) Сама идея перепроводить документы закрытых периодов - сомнительна, и мало жизнеспособна. А вдруг что-то поменяется в суммах или записях?
Я вот думал, где же этот код можно использовать, и так не и не придумал.
В современных конфигурациях процедура проведения разделена на 3 этапа, инициализация таблиц движения в модуле менеджера документа, подготовка таблиц регистра к записи, и непосредственная запись.
И получается, куда же код можно вставить? Типовой документ мы не поменяем, так как это еще больше усложняет поддержку конфигурации. В самописный документ - тоже, так как стилистика разработки будет отличаться. В собственную самописную конфигурацию? А кто ее потом будет поддерживать, и действительно ли плюсы перевешивают, чтобы использовать именно такой способ разработки.
27. SlavaKron 24.10.20 11:54 Сейчас в теме
(16)
А транзакция необходима, как я уже писал выше, для того чтобы когда будет выполнятся запись данных в регистр, через обработку, не происходило грязного чтения.

Запись набора и так происходит в транзакции.
28. DarkAn 1093 26.10.20 09:48 Сейчас в теме
(27)
Запись набора и так происходит в транзакции.

Перед записью, иногда бывает чтение и набор для записи строиться на основании прочитанных данных. Если читать их без транзакции (обработкой) - можно прочитать что-то не нужное :)
18. DarkAn 1093 21.10.20 13:13 Сейчас в теме
(17) не проблема, пусть каждый использует так как ему удобно.
23. mixsture 22.10.20 08:35 Сейчас в теме
Последовательность идентификаторов регистров в 4ом параметре, никак не влияет на их запись. Записываться они будут в порядке следования в метаданных.

А как же механики вроде "сначала запишем в регистр СписанныеТовары, а потом по содержимому этого регистра будем делать движения в других регистрах"?
24. awk 744 22.10.20 09:59 Сейчас в теме
(23) Мдя... Проблема... Стандарт гласит: "Объекты должны быть отсортированы по алфавиту"....

Могу предложить следующий выход:

ОбщийМодуль.СуперМодульПереопределяемый


Функция ПолучитьМассивРегистровДляОбработки(Регистратор, Движения) Экспорт
  РегистрыПоддерживающиеФункционал = Новый Массив();
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыСведений.Регистр1);
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыСведений.Регистр2);
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыНакопления.Регистр3);

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

  Результат.Сортировать("Приоритет");
  Возврат Результат;

КонецФункции

Показать


ОбщийМодуль.СуперМодульПовторногоИспользования


Функция ПолучитьМассивРегистровДляОбработки(Регистратор, Движения) Экспорт
  Возврат СуперМодульПереопределяемый.ПолучитьМассивРегистровДляОбработки(Регистратор, Движения);
КонецФункции



РегистрыСведений.Регистр1.МодульОбъекта


Процедура ПроверитьВозможностьОбработки(Регистратор, Обработчики) Экспорт
   Если РегистраторПохожНаНечтоЭдакое(Регистратор) Тогда
      Обработчики.Добавить();
      Обработчик.Приоритет = 1;
      Обработчик.Обработчик= РегистрСведений.Регистр1;
   ИначеЕсли РегистраторПохожНаНечтоРазэдакое(Регистратор) Тогда
      Обработчики.Добавить();
      Обработчик.Приоритет = 2;
      // Кто сказал, что можно только менеджеры регистров можно пихать любую хрень. Например: Обработчик.Обработчик= Обработки.ОбработкаРегистра1.Создать();
      Обработчик.Обработчик= Обработки.ОбработкаРегистра1;
   Иначе
      ВызватьИсключение СтрШаблон("Ожидали эдакое или разэдакое, а получили хрень в виде %1", Регистратор);
   КонецЕсли;
КонецПроцедуры

Показать
25. DarkAn 1093 22.10.20 10:42 Сейчас в теме
(24) Про модуль повторного использования - хорошая идея.
26. awk 744 22.10.20 10:47 Сейчас в теме
(25) В
Функция ПолучитьМассивРегистровДляОбработки(Регистратор, Движения) Экспорт
  РегистрыПоддерживающиеФункционал = Новый Массив();
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыСведений.Регистр1);
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыСведений.Регистр2);
  РегистрыПоддерживающиеФункционал.Добавить(РегистрыНакопления.Регистр3);

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

  Результат.Сортировать("Приоритет");
  Возврат Результат;

КонецФункции
Показать
Ошибка. Надо:
Функция ПолучитьМассивРегистровДляОбработки(Регистратор, Движения) Экспорт
  РегистрыПоддерживающиеФункционал = Новый Массив();
  РегистрыПоддерживающиеФункционал.Добавить(Метаданные.РегистрыСведений.Регистр1);
  РегистрыПоддерживающиеФункционал.Добавить(Метаданные.РегистрыСведений.Регистр2);
  РегистрыПоддерживающиеФункционал.Добавить(Метаданные.РегистрыНакопления.Регистр3);

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

  Результат.Сортировать("Приоритет");
  Возврат Результат;

КонецФункции
Показать


Тяжело писать в блокноте и без таба...
29. Infsams654 26.10.20 17:41 Сейчас в теме
ООП. Объект пишет то что считает нужным, а не хранилище (в данном случае регистр) определяет что и как записывать : // Алгоритм проведения - в зависимости от того что пишем. Это тогда при добавлении новых документов нужно будет всегда менять проведение в этом месте
30. DarkAn 1093 27.10.20 10:47 Сейчас в теме
(29)
ООП. Объект пишет то что считает нужным, а не хранилище (в данном случае регистр) определяет что и как записывать : // Алгоритм проведения - в зависимости от того что пишем. Это тогда при добавлении новых документов нужно будет всегда менять проведение в этом месте

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