Как в запросе 1С рассчитать отсрочку платежа с учетом только рабочих дней?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

При контроле дебиторской задолженности и определении статуса накладных часто возникает задача расчета крайнего срока оплаты не в календарных, а в рабочих или банковских днях. Стандартная функция языка запросов ДОБАВИТЬКДАТЕ прибавляет календарные дни без исключения выходных и праздников. Разберем, как построить запрос к производственному календарю для корректного учета рабочих дней.

В чем заключается сложность прямого расчета в запросе

В языке запросов 1С отсутствуют встроенные функции для циклического прибавления рабочих смен или вызова процедур общего модуля. Прямое соединение документов с регистром календаря по условию ДатаКалендаря МЕЖДУ Регистратор.Дата И ДОБАВИТЬКДАТЕ(...) не дает нужного результата: такой фильтр отбирает только рабочие дни внутри фиксированного календарного отрезка, а не смещает дату на заданное число рабочих дней вперед.

Для решения задачи применяются два основных подхода в запросах:

  1. Подсчет фактически прошедших рабочих дней между датой накладной и датой среза (анализа) с последующим сравнением с допустимой отсрочкой.
  2. Сквозная нумерация рабочих дней календаря для вычисления точной целевой даты платежа.

Вариант 1. Подсчет рабочих дней в интервале между накладной и датой среза

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

  1. В первой временной таблице Документы соберем реализации и их суммы из регистра накопления взаиморасчетов.
  2. Во второй временной таблице ДатыКалендаря отберем список только рабочих и предпраздничных дней.
  3. В итоговом запросе свяжем накладные с календарем по интервалу дат и сгруппируем строки с подсчетом функции КОЛИЧЕСТВО.

Посмотрим на пример реализации запроса:


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

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    РегламентированныйПроизводственныйКалендарь.ДатаКалендаря КАК ДатаКалендаря
ПОМЕСТИТЬ ДатыКалендаря
ИЗ
    РегистрСведений.РегламентированныйПроизводственныйКалендарь КАК РегламентированныйПроизводственныйКалендарь
ГДЕ
    РегламентированныйПроизводственныйКалендарь.ВидДня В (
        ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Рабочий),
        ЗНАЧЕНИЕ(Перечисление.ВидыДнейПроизводственногоКалендаря.Предпраздничный))
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    Документы.Сумма КАК Сумма,
    Документы.РегистраторДата КАК РегистраторДата,
    Документы.Регистратор КАК Регистратор,
    КОЛИЧЕСТВО(ДатыКалендаря.ДатаКалендаря) КАК ПрошлоРабочихДней,
    ВЫБОР
        КОГДА КОЛИЧЕСТВО(ДатыКалендаря.ДатаКалендаря) <= &Отсрочка
            ТОГДА "Не просрочена"
        ИНАЧЕ "Просрочена"
    КОНЕЦ КАК СтатусНакладной
ИЗ
    Документы КАК Документы
        ЛЕВОЕ СОЕДИНЕНИЕ ДатыКалендаря КАК ДатыКалендаря
        ПО (ДатыКалендаря.ДатаКалендаря МЕЖДУ ДОБАВИТЬКДАТЕ(Документы.РегистраторДата, ДЕНЬ, 1) И &ДатаСреза)
СГРУППИРОВАТЬ ПО
    Документы.Сумма,
    Документы.РегистраторДата,
    Документы.Регистратор

Важные нюансы и граничные условия

Разберем детали, влияющие на точность расчета:

  1. Учет времени документа: в 1С дата документа содержит время (часы, минуты, секунды), а в календаре даты хранятся с временем 00:00:00. Применение конструкции НАЧАЛОПЕРИОДА(Регистратор.Дата, ДЕНЬ) гарантирует корректное вхождение дат в условие МЕЖДУ.
  2. Начало отсчета срока: в соответствии с правилами исчисления сроков (ст. 191 ГК РФ) течение срока начинается со следующего дня после совершения операции. Поэтому в соединении используется смещение начала отсчета: ДОБАВИТЬКДАТЕ(Документы.РегистраторДата, ДЕНЬ, 1). Если считать саму дату документа рабочим днем, срок отсрочки сократится на 1 день.
  3. Заполненность календаря: необходимо следить, чтобы производственный календарь был заполнен на весь анализируемый период, иначе соединение вернет неполное количество рабочих дней.

Вариант 2. Использование механизмов БСП в типовых конфигурациях

В конфигурациях на базе БСП (1С:ERP, КА 2, УТ 11, БП 3.0) структура календарей хранится в справочнике ПроизводственныеКалендари и регистрах сведений ДанныеПроизводственногоКалендаря и КалендарныеГрафики. Для программного расчета срока платежа на встроенном языке рекомендуется использовать функции общего модуля КалендарныеГрафики:


// Получение точной даты платежа с учетом рабочих дней календаря
КрайнийСрок = КалендарныеГрафики.ПолучитьДатуПоКалендарю(Календарь, ДатаДокумента, ДниОтсрочки);

// Получение количества рабочих дней между двумя датами
РабочихДнейПрошло = КалендарныеГрафики.КоличествоДнейПоКалендарю(Календарь, ДатаДокумента, ДатаСреза);

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

← На главную