Как в 1С 7.7 найти ближайшую дату платежа по заданным дням недели?

Программист 1С v7.7 Управленческий учет
← На главную

В процессе разработки платежных календарей или систем автоматического планирования оплат в среде 1С:Предприятие 7.7 часто возникает задача определения следующей корректной даты. Например, если контрагент принимает платежи только по понедельникам и средам, системе нужно вычислить ближайший такой день, начиная от текущей даты или даты документа.

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

Метод 1: Циклический перебор дат

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

Рассмотрим реализацию функции, которая принимает исходную дату и список разрешенных дней недели. В 1С 7.7 для работы с днями недели используется функция НомерДняНедели(), которая возвращает значения от 1 (понедельник) до 7 (воскресенье).

Пример кода с использованием объекта СписокЗначений:


Функция ПолучитьБлижайшийДеньПлатежа(ВыбДата, СписокДнейОплаты)
    // Определяем номер дня недели для текущей даты
    ТекДеньНедели = НомерДняНедели(ВыбДата);
    БлижайшаяДата = ВыбДата;
    
    // Запускаем цикл поиска. 
    // Метод Принадлежит() вернет 1, если день найден в списке
    Пока СписокДнейОплаты.Принадлежит(ТекДеньНедели) = 0 Цикл
        // В 7.7 прибавление 1 к дате означает прибавление одного дня
        БлижайшаяДата = БлижайшаяДата + 1;
        ТекДеньНедели = НомерДняНедели(БлижайшаяДата);
    КонецЦикла;
    
    Возврат БлижайшаяДата;
КонецФункции

Важное замечание: Перед запуском такого цикла обязательно проверьте, что СписокДнейОплаты не пуст. Если в настройках контрагента не указано ни одного платежного дня, программа уйдет в бесконечный цикл. Рекомендуется добавить условие Если СписокДнейОплаты.РазмерСписка() = 0 Тогда Возврат '00.00.00'; КонецЕсли;.

Метод 2: Математический расчет разницы дней

Если нам известен только один конкретный день недели (например, мы всегда платим по четвергам), можно обойтись без цикла, вычислив разницу по формуле. Для этого используется оператор остатка от деления %.

Проанализируем алгоритм расчета:

  1. Вычисляем текущий номер дня недели.
  2. Находим разницу между целевым днем и текущим.
  3. Применяем формулу: (ЦелевойДень - ТекущийДень + 7) % 7.
  4. Если результат равен 0, это означает, что сегодня и есть нужный день. Если нам нужно найти строго следующую дату, результат 0 следует заменить на 7.

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

Метод 3: Использование строковой маски

Довольно элегантный способ для 1С 7.7 — хранение графика в виде строки из 7 символов, где "1" означает платежный день, а "0" — выходной. Например, "1010000" (Пн и Ср).

Чтобы найти ближайший день, мы можем "удвоить" эту строку: "10100001010000". Затем, начиная с позиции, соответствующей текущему дню недели, мы ищем первую единицу с помощью функции Найти(). Количество символов до найденной единицы и будет количеством дней, которые нужно прибавить к текущей дате.

Особенности платформы 7.7 при работе с датами

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

Итоговый пример вызова функции

Разберем ситуацию, когда у контрагента в реквизитах справочника стоят флажки Пн, Вт, Ср, Чт, Пт. Нам нужно собрать их в список и найти дату платежа:


СписокДней = СоздатьОбъект("СписокЗначений");
Если Контрагент.ПлатПонедельник = 1 Тогда СписокДней.ДобавитьЗначение(1); КонецЕсли;
Если Контрагент.ПлатСреда = 1 Тогда СписокДней.ДобавитьЗначение(3); КонецЕсли;

Если СписокДней.РазмерСписка() > 0 Тогда
    ДатаПлатежа = ПолучитьБлижайшийДеньПлатежа(РабочаяДата(), СписокДней);
    Сообщить("Ближайшая оплата: " + ДатаПлатежа);
Иначе
    Сообщить("У контрагента не настроен график платежей!");
КонецЕсли;

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

← На главную