При изучении механизмов сложных расчетов по знаменитому учебнику М.Г. Радченко и Е.В. Хрусталевой «1С:Предприятие 8.3. Практическое пособие разработчика», многие начинающие специалисты сталкиваются с досадной проблемой. При попытке проведения документа НачисленияСотрудникам система выдает синтаксическую ошибку в общем модуле ПроведениеРасчетов. Ошибка указывает на ожидание символа закрывающей скобки, однако простая расстановка скобок не решает проблему по существу.
Давайте подробно разберем, почему возникает эта ошибка, в чем заключается опечатка авторов и как правильно реализовать алгоритм расчета оклада, чтобы он работал корректно в реальной базе данных.
Рассмотрим фрагмент кода, который обычно вызывает затруднения. В печатных версиях пособия (особенно в издании 2013 года и некоторых последующих тиражах) на странице 590 представлен листинг 18.5. В нем содержится следующая строка:
// Ошибочный вариант из печатного пособия
ЗаписьРегистра.Результат = (ЗаписьРегистра.ИсходныеДанные
ВыборкаРезультата.Норма)*ВыборкаРезультата.Факт;
Проанализируем ситуацию: платформа 1С при компиляции модуля видит открывающую скобку, после которой идет переменная ЗаписьРегистра.ИсходныеДанные. Сразу за ней следует еще одна переменная ВыборкаРезультата.Норма без какого-либо математического оператора между ними. Для конфигуратора это выглядит так, будто программист забыл закрыть скобку после первой переменной или не указал действие, которое нужно совершить.
Как справедливо отмечают опытные разработчики, в этой формуле пропущен оператор деления. Чтобы расчет стал математически верным и синтаксически правильным, необходимо добавить символ /.
Исправленный вариант кода в общем модуле ПроведениеРасчетов должен выглядеть следующим образом:
// Исправленный вариант кода
Иначе
// Рассчитать оклад по фактическому периоду и исходным данным
ЗаписьРегистра.Результат = (ЗаписьРегистра.ИсходныеДанные / ВыборкаРезультата.Норма) * ВыборкаРезультата.Факт;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Выполнен расчет: " + ЗаписьРегистра.Регистратор
+ " - " + ЗаписьРегистра.ВидРасчета
+ " - " + ЗаписьРегистра.Сотрудник;
Сообщение.Сообщить();
КонецЕсли;
Важный нюанс: Не забудьте вызвать метод Сообщить() для объекта СообщениеПользователю, иначе текст о выполнении расчета не будет выведен в окно сообщений.
Чтобы не просто копировать код, а понимать его работу, выясним причину использования именно такой формулы. В контексте главы 18 учебника мы работаем с регистром расчета ОсновныеНачисления.
ЗаписьРегистра.ИсходныеДанные — это ресурс регистра, в который при проведении документа записывается сумма оклада сотрудника за ПОЛНЫЙ месяц (установленная в трудовом договоре).ВыборкаРезультата.Норма — это значение, полученное из виртуальной таблицы данных графика. Оно представляет собой количество рабочих дней (или часов) в месяце согласно графику работы сотрудника.ВыборкаРезультата.Факт — это фактически отработанное время. Система рассчитывает его автоматически на основе периода действия записи и с учетом вытесняющих видов расчета (например, если сотрудник был на больничном, эти дни исключаются из факта).Таким образом, выражение (ЗаписьРегистра.ИсходныеДанные / ВыборкаРезультата.Норма) позволяет нам вычислить стоимость одного рабочего дня, которую мы затем умножаем на количество фактически отработанных дней.
Часто исправление одной опечатки в формуле не решает всех проблем. Проанализируем сопутствующие факторы, которые могут привести к неверному результату или ошибкам проведения:
Проверьте свойства ресурсов Результат и ИсходныеДанные в вашем регистре расчета. Если для них установлен тип Число с длиной 15 и точностью 0, то при делении оклада на норму дней дробная часть будет отсекаться. Это приведет к огромным погрешностям в расчетах. Рекомендуется устанавливать точность не менее 2 знаков.
В тексте запроса, который формирует ВыборкаРезультата, обязательно должны быть заданы псевдонимы для полей. Если в запросе вы назвали поле ЗначениеПериодДействия как Факт, а ЗначениеГрафика как Норма, то и в коде нужно обращаться к ним именно так. Если псевдонимы отсутствуют или отличаются, вы получите ошибку "Поле объекта не обнаружено".
Обратите внимание на завершающую часть листинга 18.5. После цикла обхода записей обязательно должен присутствовать вызов метода записи набора:
НаборыЗаписей.Записать(Истина);
Если передать параметр Ложь или забыть про этот метод, изменения в ресурсе Результат не будут сохранены в базе данных, хотя в отладчике вы будете видеть, что переменная рассчитана верно.
Работа с учебными пособиями требует критического подхода. Опечатки в коде — это отличная возможность для начинающего разработчика проявить внимательность и глубже разобраться в логике платформы. Рассмотрим это как практическое упражнение по отладке. Для минимизации подобных проблем в будущем, рекомендуем сверять код из печатной книги с демонстрационной конфигурацией, которая обычно прилагается к пособию, или использовать актуальную версию материалов на сайте 1С:ИТС, где ошибки оперативно исправляются.