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

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

Часто при разработке конфигураций для учета аренды или проката возникает задача: при возврате объекта автоматически рассчитать количество дней проката и сумму к оплате. Для этого нам необходимо получить дату выдачи объекта клиенту. Рассмотрим подробнее, почему возникают сложности при попытке извлечь дату из виртуальных таблиц регистра накопления, и проанализируем правильные способы решения этой задачи.

Почему в виртуальных таблицах нет поля «Период»?

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

  1. В платформе 1С таблица Остатки хранит только сводные итоги на определенный момент времени. Архитектурно она не содержит поля с датой, так как текущий остаток может складываться из множества приходных и расходных документов за разные даты.
  2. В виртуальной таблице Обороты поле Период по умолчанию скрыто. Оно становится доступным для выбора только в том случае, если в параметрах виртуальной таблицы явно задать параметр Периодичность (например, указать значение День, Месяц, Авто или Запись).

Способы получения даты через регистр накопления

Если архитектура на базе регистра накопления уже утверждена, разберем по шагам, как можно вытащить нужную нам дату:

  1. Обращение к физической таблице регистра. Вместо использования виртуальных таблиц выполните запрос к основной физической таблице регистра. В ней всегда присутствует системное поле Период, хранящее дату и время каждого движения. Отобрав записи по конкретному объекту проката с видом движения «Приход» и применив агрегатную функцию МАКСИМУМ, мы сможем найти точную дату последней выдачи оборудования.
  2. Использование измерения-документа. Добавим в регистр накопления новое измерение, например ДокументВыдачи, с типом ссылки на документ передачи. В этом случае при запросе к виртуальной таблице Остатки мы получим саму ссылку на партионный документ. Дату можно будет прочитать напрямую через неё: ДокументВыдачи.Дата.

Оптимальные архитектурные решения

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

1. Использование механизма "Ввод на основании"

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

2. Использование регистра сведений

Более правильной архитектурой для фиксации состояний является использование регистра сведений с периодичностью По позиции регистратора (или В пределах секунды). В качестве измерения будет выступать ОбъектПроката, а в качестве ресурсов — Статус (например: передан клиенту, на складе) и Клиент. При таком подходе запрос к виртуальной таблице СрезПоследних автоматически вернет самую актуальную запись по выбранному объекту, а её системное поле Период и будет датой начала проката.

Правильное выполнение расчетов в управляемых формах

В управляемых формах 1С действует жесткое разделение на клиентский и серверный контекст. Попытка выполнить запрос к регистру прямо в процедуре &НаКлиенте (как это часто делают новички) приведет к ошибке. Также грубым нарушением является чтение набора записей без запроса через объектную модель на сервере, так как это вызывает блокировки и падение производительности.

Разберем по шагам корректный алгоритм получения данных:

  1. В процедуре &НаКлиенте при изменении объекта проката мы вызываем серверную функцию.
  2. Эта функция должна располагаться под директивой &НаСервереБезКонтекста, чтобы не передавать на сервер весь тяжелый контекст формы документа.
  3. В функцию передается ссылка на выбранный объект проката. На сервере выполняется быстрый запрос к регистру (сведений или накопления), который возвращает дату передачи.
  4. Полученная дата возвращается на клиент, где происходит расчет разницы дат.

Посмотрим на пример правильной структуры кода:


&НаСервереБезКонтекста
Функция ПолучитьДатуВыдачи(ОбъектПроката)
    
    // Здесь должен быть Запрос к регистру сведений СрезПоследних
    // или к физической таблице регистра накопления с функцией МАКСИМУМ(Период).
    // Возвращаем найденную дату.
    Возврат ДатаВыдачи;
    
КонецФункции

&НаКлиенте
Процедура ОбъектыПрокатаОбъектПрокатаПриИзменении(Элемент)
    
    ТекущиеДанные = Элементы.ОбъектыПроката.ТекущиеДанные;
    Если ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем данные с сервера
    ДатаПоступления = ПолучитьДатуВыдачи(ТекущиеДанные.ОбъектПроката);
    Цена = РаботаСоСправочниками.ПолучитьЦенаЗаСутки(ТекущиеДанные.ОбъектПроката);
    
    // Выполняем расчет на клиенте
    Если ЗначениеЗаполнено(ДатаПоступления) Тогда
        КоличествоДнейВПрокате = Окр((ТекущаяДата() - ДатаПоступления) / (3600 * 24), 0);
        Если КоличествоДнейВПрокате < 1 Тогда
            КоличествоДнейВПрокате = 1; // минимум 1 день
        КонецЕсли;
        ТекущиеДанные.Сумма = КоличествоДнейВПрокате * Цена;
    КонецЕсли;
    
КонецПроцедуры

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

← На главную