Почему в ЗУП при заполнении регистрации переработок возникает ошибка «Таблица не найдена ВТНормоВремяПоУчетуВремениСУчетомПредела»?

Программист 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

Разберем типичную и крайне неприятную ошибку, возникающую в программе 1С:Зарплата и Управление Персоналом (начиная с релиза 3.1.38.92 и выше). При заполнении документа РегистрацияПереработок по конкретному сотруднику или списку сменщиков программа аварийно прерывает работу со следующим сообщением в стеке вызовов:

«Ошибка при вызове метода контекста (Выполнить) ... Ошибка во время выполнения встроенного языка по причине: {(31, 2)}: Таблица не найдена "ВТНормоВремяПоУчетуВремениСУчетомПредела"».

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

Анализ архитектурной причины сбоя

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

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

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

Пошаговая локализация проблемы в отладчике

Разберем по шагам, как выявить источник ошибки и убедиться, что виновником является устаревшее расширение:

  1. Проверим запуск без расширений. Быстро исключим влияние стороннего кода: запустим сеанс «1С:Предприятия» с командным ключом /NoExtensions (или снимем активность расширений в конфигураторе). Если при таком запуске документ заполняется штатно, источник ошибки на 100% локализован в одном из расширений.
  2. Установим точку останова в типовом коде. Откроем общий модуль РасчетЗарплатыРасширенный, перейдем к процедуре ПоказателиСуммированногоУчетаСотрудниковЗаПериод на строку вызова запроса (в районе строки 13956): РезультатЗапроса = Запрос.Выполнить(); Запустим документ РегистрацияПереработок и добавим сотрудника с суммированным учетом времени.
  3. Исследуем состав временных таблиц. При остановке на указанной строке откроем окно «Вычислить выражение» (Shift+F9) и проверим коллекции МВТ: Запрос.МенеджерВременныхТаблиц.Таблицы Развернем список созданных таблиц. В корректно работающей базе среди прочих таблиц должна присутствовать ВТНормоВремяПоУчетуВремениСУчетомПредела. Если ее в списке нет, значит, предшествующая генерация запроса была нарушена.
  4. Проверим переопределение метода. Встанем на вызов процедуры ДополнитьЗапросВТПоказателейПоУчетуВремени в коде общего модуля, нажмем правую кнопку мыши и выберем пункт меню «Показать переопределения метода в расширениях» либо выполним глобальный поиск по конфигурации и расширениям. Это покажет, какое именно расширение перехватывает управление.

Обратите внимание: если отладчик не заходит внутрь модуля расширения, проверьте свойства расширения в дереве метаданных. При установленном флажке «Безопасный режим» платформа может блокировать отладку серверных модулей расширения в зависимости от настроек сеанса.

Сравнение запросов: что изменилось в типовом механизме

Посмотрим на фрагмент пакета запроса, который формируется в старой и новой редакциях процедуры ДополнитьЗапросВТПоказателейПоУчетуВремени. Старый вариант запроса, оставшийся в заброшенном расширении, заканчивался объединением графиков и календарей:


ВЫБРАТЬ
	ЕСТЬNULL(ВТДанныеГрафика.Сотрудник, ВТДанныеПроизводственногоКалендаря.Сотрудник) КАК Сотрудник,
	ЕСТЬNULL(ВТДанныеГрафика.НормаЧасов, 0) + ЕСТЬNULL(ВТДанныеПроизводственногоКалендаря.НормаЧасов, 0) КАК НормаЧасов
ПОМЕСТИТЬ ВТНормоВремяПоУчетуВремени
ИЗ
	ВТДанныеПроизводственногоКалендаря КАК ВТДанныеПроизводственногоКалендаря
		ПОЛНОЕ СОЕДИНЕНИЕ ВТДанныеГрафика КАК ВТДанныеГрафика
		ПО ВТДанныеПроизводственногоКалендаря.Сотрудник = ВТДанныеГрафика.Сотрудник;
////////////////////////////////////////////////////////////////////////////////
УНИЧТОЖИТЬ ВТУчетРабочегоВремениСГрафиками

В обновленном релизе ЗУП после создания таблицы ВТНормоВремяПоУчетуВремени типовой алгоритм добавляет дополнительную ветку запроса, которая учитывает пределы переработок и формирует ВТНормоВремяПоУчетуВремениСУчетомПредела. Поскольку директива &Вместо полностью отсекает типовой код, новая таблица в менеджер не попадает вовсе.

Способы исправления и правильная методика доработки

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

Решение 1. Актуализация кода в расширении

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

Решение 2. Отказ от директивы &Вместо в пользу &ИзменениеИКонтроль

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

Перепишем метод с использованием директивы &ИзменениеИКонтроль:

  1. Заменим директиву &Вместо на &ИзменениеИКонтроль("ДополнитьЗапросВТПоказателейПоУчетуВремени").
  2. В теле метода оставим типовой код актуального релиза, обрамив свои изменения специальными тегами #Вставить и #Удалить.

Благодаря этому механизму при следующем обновлении типовой конфигурации платформа 1С автоматически выполнит сверку исходного метода. Если код метода в ЗУП снова изменится, расширение выдаст предупреждение о невозможности применения, защитив базу от некорректных расчетных данных и скрытых ошибок.

Решение 3. Очистка кэша после обновления

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

  1. Очистим локальный кэш конфигурации на клиентском рабочем месте (каталоги в %LOCALAPPDATA%\1C\1cv8 и %APPDATA%\1C\1cv8).
  2. В клиент-серверном варианте перезапустим рабочие процессы сервера «1С:Предприятия», чтобы сбросить кэш скомпилированных модулей и планов запросов СУБД.
← На главную