Часто при разработке конфигураций для учета аренды или проката возникает задача: при возврате объекта автоматически рассчитать количество дней проката и сумму к оплате. Для этого нам необходимо получить дату выдачи объекта клиенту. Рассмотрим подробнее, почему возникают сложности при попытке извлечь дату из виртуальных таблиц регистра накопления, и проанализируем правильные способы решения этой задачи.
Многие разработчики пытаются найти дату документа в виртуальной таблице Остатки регистра накопления и сталкиваются с тем, что реквизита Период там просто нет. Выясним причину этого ограничения:
Остатки хранит только сводные итоги на определенный момент времени. Архитектурно она не содержит поля с датой, так как текущий остаток может складываться из множества приходных и расходных документов за разные даты.Обороты поле Период по умолчанию скрыто. Оно становится доступным для выбора только в том случае, если в параметрах виртуальной таблицы явно задать параметр Периодичность (например, указать значение День, Месяц, Авто или Запись).Если архитектура на базе регистра накопления уже утверждена, разберем по шагам, как можно вытащить нужную нам дату:
Период, хранящее дату и время каждого движения. Отобрав записи по конкретному объекту проката с видом движения «Приход» и применив агрегатную функцию МАКСИМУМ, мы сможем найти точную дату последней выдачи оборудования.ДокументВыдачи, с типом ссылки на документ передачи. В этом случае при запросе к виртуальной таблице Остатки мы получим саму ссылку на партионный документ. Дату можно будет прочитать напрямую через неё: ДокументВыдачи.Дата.Для задач отслеживания текущего местоположения оборудования и времени его выдачи использование исключительно регистров накопления часто бывает избыточным, так как они созданы в первую очередь для количественного или суммового учета. Проанализируем более грамотные подходы:
1. Использование механизма "Ввод на основании"
Самый простой подход, не требующий сложных запросов к регистрам — создавать документ возврата на основании документа передачи. При вводе на основании мы имеем прямой доступ к данным документа-основания и можем сразу перенести дату выдачи, объект проката и цену в новый документ.
2. Использование регистра сведений
Более правильной архитектурой для фиксации состояний является использование регистра сведений с периодичностью По позиции регистратора (или В пределах секунды). В качестве измерения будет выступать ОбъектПроката, а в качестве ресурсов — Статус (например: передан клиенту, на складе) и Клиент. При таком подходе запрос к виртуальной таблице СрезПоследних автоматически вернет самую актуальную запись по выбранному объекту, а её системное поле Период и будет датой начала проката.
В управляемых формах 1С действует жесткое разделение на клиентский и серверный контекст. Попытка выполнить запрос к регистру прямо в процедуре &НаКлиенте (как это часто делают новички) приведет к ошибке. Также грубым нарушением является чтение набора записей без запроса через объектную модель на сервере, так как это вызывает блокировки и падение производительности.
Разберем по шагам корректный алгоритм получения данных:
&НаКлиенте при изменении объекта проката мы вызываем серверную функцию.&НаСервереБезКонтекста, чтобы не передавать на сервер весь тяжелый контекст формы документа.Посмотрим на пример правильной структуры кода:
&НаСервереБезКонтекста
Функция ПолучитьДатуВыдачи(ОбъектПроката)
// Здесь должен быть Запрос к регистру сведений СрезПоследних
// или к физической таблице регистра накопления с функцией МАКСИМУМ(Период).
// Возвращаем найденную дату.
Возврат ДатаВыдачи;
КонецФункции
&НаКлиенте
Процедура ОбъектыПрокатаОбъектПрокатаПриИзменении(Элемент)
ТекущиеДанные = Элементы.ОбъектыПроката.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
// Получаем данные с сервера
ДатаПоступления = ПолучитьДатуВыдачи(ТекущиеДанные.ОбъектПроката);
Цена = РаботаСоСправочниками.ПолучитьЦенаЗаСутки(ТекущиеДанные.ОбъектПроката);
// Выполняем расчет на клиенте
Если ЗначениеЗаполнено(ДатаПоступления) Тогда
КоличествоДнейВПрокате = Окр((ТекущаяДата() - ДатаПоступления) / (3600 * 24), 0);
Если КоличествоДнейВПрокате < 1 Тогда
КоличествоДнейВПрокате = 1; // минимум 1 день
КонецЕсли;
ТекущиеДанные.Сумма = КоличествоДнейВПрокате * Цена;
КонецЕсли;
КонецПроцедуры
Используя такие подходы, вы сможете выстроить грамотную архитектуру учета прокатного оборудования без потерь производительности и проблем с получением необходимых дат.