При разработке отчетов на Системе компоновки данных (СКД) программисты часто сталкиваются с ситуацией, когда логически верное условие сравнения дат не срабатывает. Типичный пример: необходимо сравнить две даты, отбросив время, чтобы условие Меньше или Равно корректно обрабатывало текущий день. Однако на практике условие может игнорировать равенство и срабатывать только в случае, если одна дата строго меньше другой. Разберем подробно, почему так происходит и как правильно настроить вычисляемые поля.
Первая и самая распространенная причина ошибок — путаница в синтаксисе языка запросов и языка выражений СКД. Проанализируем ситуацию: в консоли запросов мы привыкли писать НАЧАЛОПЕРИОДА(Дата, ДЕНЬ), где ДЕНЬ является зарезервированным словом (ключевым словом СУБД). Однако в вычисляемых полях СКД используется язык выражений, максимально приближенный к встроенному языку 1С.
В выражениях СКД функция НачалоПериода ожидает второй параметр в виде строковой константы. Рассмотрим правильный вариант написания:
НачалоПериода(ДатаПлатежа, "День") <= НачалоПериода(&ТекущаяДата, "День")
Если написать День без кавычек, система попытается найти поле с таким именем, не обнаружит его и может вернуть ошибку или некорректный результат. Стоит отметить, что в СКД для вычисляемых полей существует более "родная" функция, которую мы рекомендуем использовать вместо НачалоПериода для работы с сутками.
Чтобы избежать путаницы с кавычками и типами периодов, в вычисляемых полях гораздо эффективнее использовать функцию НачалоДня(). Она принимает только один параметр — дату — и всегда возвращает время 00:00:00. Проанализируем пример:
НачалоДня(ДатаПлатежа) <= НачалоДня(&ТекущаяДата)
Это выражение идентично по результату функции НачалоПериода с параметром "День", но менее склонно к синтаксическим ошибкам. Однако, если даже после смены функции условие "равно" не отрабатывает, причину нужно искать глубже — в самих данных.
Одной из скрытых причин, по которой условие Дата1 <= Дата2 возвращает Ложь при кажущемся равенстве, является наличие значений NULL. В 1С (и в SQL) любое сравнение с NULL дает неопределенный результат, который в логических выражениях интерпретируется как Ложь. Если в вашем запросе поле ДатаПлатежа не заполнено, условие не выполнится.
Для решения этой проблемы выясним, могут ли данные содержать пустые значения, и применим функцию ЕСТЬNULL. Посмотрим на пример кода в вычисляемом поле:
НачалоДня(ЕСТЬNULL(ДатаПлатежа, ДАТАВРЕМЯ(1, 1, 1))) <= НачалоДня(&ТекущаяДата)
В данном случае, если дата не заполнена, она заменится на минимально возможную дату 1С (01.01.0001), что позволит условию <= отработать корректно, если это логически допустимо в вашей задаче.
Часто программисты объединяют несколько условий в одну строку. Рассмотрим ситуацию, упомянутую в обсуждении: (НачалоДня(ДатаПлатежа) <= НачалоДня(&ТекущаяДата)) И (ДнейОтсрочки > 0). Если даты равны, но поле ДнейОтсрочки равно 0 или не заполнено (NULL), все выражение целиком вернет Ложь.
Разберем по шагам, как локализовать проблему:
И).ДнейОтсрочки.Если визуально кажется, что даты равны, но программа считает иначе, мы рекомендуем применить метод прямой проверки. Для этого:
1. Добавьте в список вычисляемых полей два новых поля: ТестовоеПоле1 и ТестовоеПоле2.
2. В выражения этих полей пропишите те самые функции, которые вы сравниваете:
// ТестовоеПоле1
НачалоДня(ДатаПлатежа)
// ТестовоеПоле2
НачалоДня(&ТекущаяДата)
3. Выведите эти поля в детальные записи отчета. Посмотрите на результат. Часто выясняется, что в одном из полей дата на самом деле пустая, или параметр &ТекущаяДата не инициализирован и содержит значение "01.01.0001 00:00:00".
Проанализируем еще один нюанс: типы данных. Если ДатаПлатежа приходит из базы данных с типом "Дата", а &ТекущаяДата передается из кода как объект "Дата" со временем, то при использовании функций НачалоДня они должны приводиться к единому виду. Однако убедитесь, что параметр &ТекущаяДата в СКД имеет правильный состав даты. В настройках набора данных на закладке "Параметры" проверьте:
Для того чтобы условие сравнения дат в СКД работало стабильно, придерживайтесь следующих правил:
НачалоПериода(Дата, "День").НачалоДня(Дата) для краткости и надежности.NULL через ЕСТЬNULL.ДнейОтсрочки > 0), так как они могут "отсекать" результат при равенстве дат.Соблюдение этих шагов позволит избежать ошибок интерпретации выражений компоновщиком и обеспечит корректную работу ваших отчетов.