Как исправить ошибки при расчете невыходов и перерасчетах в 18 занятии учебника Радченко

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

Занятие 18 в «Практическом пособии разработчика» М.Г. Радченко — это один из самых сложных этапов для новичка. Механизм сложных периодических расчетов требует понимания взаимодействия множества объектов: Планов видов расчета, Регистров расчета и документов. Ошибки, связанные с тем, что «невыход не вытесняет оклад» или «результат не записывается в базу», являются классическими. Разберем подробно, почему возникают эти проблемы и как их правильно решить.

Анализ механизма вытеснения

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

Проанализируем настройки: в Плане видов расчета ОсновныеНачисления на закладке «Расчет» обязательно должен стоять флаг «Использовать период действия». Далее, в списке видов расчета для Оклад необходимо перейти на закладку «Вытесняющие» и добавить туда Невыход. Без этой связи система будет считать, что сотрудник работал весь месяц, независимо от введенных документов прогула. Проверьте, что у самого Невыхода также включено использование периода действия, иначе механизм вытеснения не сработает.

Проблема «пустого» проведения и записи движений

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

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


Процедура ОбработкаПроведения(Отказ, Режим)
    // 1. Сначала формируем движения (записываем периоды и виды расчета)
    Движения.ОсновныеНачисления.Записывать = Истина;
    Для Каждого ТекСтрокаНачисления Из Начисления Цикл
        Движение = Движения.ОсновныеНачисления.Добавить();
        Движение.Сотрудник = ТекСтрокаНачисления.Сотрудник;
        Движение.ВидРасчета = ТекСтрокаНачисления.ВидРасчета;
        Движение.ПериодДействияНачало = ТекСтрокаНачисления.ДатаНачала;
        Движение.ПериодДействияКонец = ТекСтрокаНачисления.ДатаОкончания;
        Движение.ПериодРегистрации = НачалоМесяца(Дата);
    КонецЦикла;
    
    // 2. Важный момент: записываем пустые записи, чтобы создать 'сетку' для расчета
    Движения.ОсновныеНачисления.Записать();
    
    // 3. Теперь вызываем расчет, который будет делать запросы к уже записанным данным
    ПровестиРасчет(Движения.ОсновныеНачисления);
КонецПроцедуры

Если пропустить вызов Движения.ОсновныеНачисления.Записать(), то при обращении к виртуальным таблицам (например, ДанныеГрафика) внутри процедуры ПровестиРасчет, система не найдет актуальных записей, и выборка будет пустой. Именно это часто приводит к тому, что переменные в отладчике принимают неопределенные значения.

Использование фактического периода действия в запросах

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

Рассмотрим правильный подход к построению запроса для расчета суммы оклада:


ВЫБРАТЬ
    Регистратор.НомерСтроки КАК НомерСтроки,
    Регистратор.ВидРасчета.Параметр КАК Оклад,
    ДанныеГрафика.ЗначениеФактическийПериодДействия КАК ОтработаноДней,
    ДанныеГрафика.ЗначениеПериодДействия КАК НормаДней
ИЗ
    РегистрРасчета.ОсновныеНачисления.ДанныеГрафика(Регистратор = &Ссылка) КАК ДанныеГрафика

Обратите внимание на поле ЗначениеФактическийПериодДействия. Если оно возвращает 0 или NULL, значит, настройки вытеснения не применились или график работы не заполнен. Выясним причину: проверьте свойства самого Регистра Расчета. У него должен быть указан «График» (обычно это Регистр сведений ГрафикиРаботы) и «Значение графика» (ресурс Значение). Если эта связь разорвана, 1С не знает, сколько рабочих дней в указанном периоде.

Разбор ошибки «Ошибка чтения значения»

Эта ошибка в контексте 18-го занятия часто возникает при попытке обращения к полям выборки запроса, если запрос не вернул строк. Рассмотрим ситуацию: вы проводите документ по сотруднику Гусакову, в котором указан только невыход. Программа пытается рассчитать оклад, обращается к выборке, но так как оклада в этом документе нет (или он в другом документе), выборка пуста. Попытка прочитать Выборка.Результат без проверки Выборка.Следующий() приведет к краху или некорректному значению.

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

Механизм перерасчетов

Перерасчеты — еще одна «мистическая» зона для студентов. Автор сообщения отмечает, что перерасчет не учитывается. Проанализируем ситуацию: таблица перерасчетов в 1С заполняется системой автоматически только в том случае, если в Регистре Расчета настроены измерения, по которым отслеживается зависимость.

Для корректной работы перерасчетов выполним следующие шаги:

  1. Откроем объект «Перерасчет» (в составе регистра расчета ОсновныеНачисления).
  2. Проверим настройку «Ведущие виды расчета». Если для Оклада ведущим назначен Невыход, то при записи Невыхода система сама добавит запись в таблицу перерасчетов для соответствующего сотрудника.
  3. В отчете по перерасчетам убедимся, что запрос идет именно к таблице РегистрРасчета.ОсновныеНачисления.Перерасчет, а не просто к основной таблице регистра.

Практические советы по изучению занятия 18

Как справедливо отмечено в обсуждении на форуме, при работе с книгой Радченко важно не просто «перебивать» код, а понимать логику каждого действия. Рассмотрим методику, которая поможет закрепить материал:

  1. После того как вы написали код по книге, попробуйте изменить условия задачи. Например, добавьте новый вид расчета «Премия процентом» и настройте его зависимость от «Оклада».
  2. Активно используйте Консоль запросов. Перед тем как вставлять запрос в код модуля, выполните его в консоли, подставив ссылку на документ вручную. Это позволит увидеть, какие именно цифры (НормаДней, ОтработаноДней) выдает система.
  3. Изучайте Синтаксис-помощник для методов ПолучитьДанныеГрафика() и ПолучитьБазу(). Это фундаментальные методы для блока начислений.

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

← На главную