Как обеспечить уникальность использования ресурсов (машин и сотрудников) в течение дня в 1С?

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

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

Анализ проблемы уникальности в регистрах сведений

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

Проанализируем пример: если мы создадим запись, где в одном наборе измерений указаны Машина А, Водитель Б и Грузчик В, то система запретит создать точно такую же комбинацию. Однако она разрешит создать запись, где будет та же Машина А, но другой водитель. С точки зрения логики бизнеса это ошибка — машина-то уже занята! Выясним причину: для платформы комбинация (А+Б+В) и (А+Г+Д) — это разные ключи записи. Чтобы решить эту задачу правильно, нам нужно изменить подход к структуре хранения данных.

Метод 1. Использование регистра сведений с нормализацией строк

Вместо того чтобы пытаться уместить весь состав бригады в одну строку регистра, мы применим метод атомарных записей. Это наиболее архитектурно верный способ для использования РегистраСведений.

Рассмотрим по шагам реализацию этого метода:

  1. Создадим РегистрСведений с названием ЗанятостьРесурсов.
  2. В качестве основного измерения установим поле Ресурс. Тип этого поля должен быть составным (включать справочники ТранспортныеСредства и Сотрудники) или использовать ОпределяемыйТип.
  3. Вторым измерением сделаем Период (если контроль нужен по времени) или Дата (если ресурс бронируется на весь день).
  4. При проведении документа «Наряд» мы будем записывать в этот регистр не одну строку, а несколько.

Посмотрим на пример кода в модуле документа при обработке проведения:


Процедура ОбработкаПроведения(Отказ, Режим)
    
    Движения.ЗанятостьРесурсов.Записывать = Истина;
    
    // 1. Добавляем запись для машины
    НоваяЗапись = Движения.ЗанятостьРесурсов.Добавить();
    НоваяЗапись.Период = Дата;
    НоваяЗапись.Ресурс = Объект.Автомобиль;
    
    // 2. Добавляем запись для водителя
    НоваяЗапись = Движения.ЗанятостьРесурсов.Добавить();
    НоваяЗапись.Период = Дата;
    НоваяЗапись.Ресурс = Объект.Водитель;
    
    // 3. Добавляем записи для грузчиков (циклом по табличной части)
    Для Каждого СтрокаГрузчик Из Объект.Грузчики Цикл
        НоваяЗапись = Движения.ЗанятостьРесурсов.Добавить();
        НоваяЗапись.Период = Дата;
        НоваяЗапись.Ресурс = СтрокаГрузчик.Сотрудник;
    КонецЦикла;

КонецПроцедуры

При таком подходе, если Машина А уже была записана в регистр другим документом на эту же дату, система 1С сама выбросит исключение «Запись с такими ключевыми полями уже существует», так как измерение Ресурс совпадет. Это встроенный механизм платформы, который гарантирует 100% уникальность без написания сложных запросов.

Метод 2. Использование регистра накопления (Метод «Остатков»)

Иногда разработчики предпочитают использовать РегистрНакопления. Этот метод основывается на идее, что каждый ресурс — это единица товара, которую мы «отгружаем» при создании наряда и «возвращаем» при его завершении. Рассмотрим, как это реализовать.

Создадим РегистрНакопления (вид — Остатки) под названием ДоступностьРесурсов. В измерениях укажем Ресурс, а в ресурсах — Количество. При проведении документа наряда будем делать движение «Расход» с количеством 1. При закрытии наряда — «Приход» с количеством 1.

Важный момент: Чтобы этот метод работал, необходимо включить в свойствах документа Удаление движений: Удалять автоматически при перепроведении и настроить контроль остатков. Если при попытке провести «Расход» остаток по ресурсу станет меньше нуля (уйдет в минус), проведение должно быть заблокировано.

Проанализируем плюсы и минусы этого метода. Плюс заключается в гибкости: вы можете легко увидеть, кто из сотрудников сейчас свободен, просто построив отчет по остаткам. Минус — риск «зависания» ресурса. Если по какой-то причине документ прихода не будет проведен, сотрудник навсегда останется в системе «занятым».

Метод 3. Программная проверка пересечения интервалов

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

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

Пример логики запроса для проверки:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Занятость.Ресурс КАК Ресурс
    |ИЗ
    |	РегистрСведений.ЗанятостьРесурсов КАК Занятость
    |ГДЕ
    |	Занятость.Ресурс В(&СписокРесурсов)
    |	И Занятость.ДатаНачала < &КонецРаботы
    |	И Занятость.ДатаОкончания > &НачалоРаботы
    |	И Занятость.Регистратор <> &Ссылка";

Обратите внимание: условие Занятость.Регистратор <> &Ссылка критически важно. Без него при перепроведении уже существующего документа система будет «натыкаться» на свои собственные старые записи и выдавать ошибку занятости.

Обеспечение целостности данных: Блокировки

Рассмотрим ситуацию в многопользовательском режиме: два диспетчера одновременно открывают наряды и выбирают одну и ту же машину. В момент нажатия кнопки «Провести» оба документа начинают проверку. Если не использовать блокировки, оба документа могут «увидеть», что машина свободна, и успешно записать данные. Это называется «состоянием гонки».

Для предотвращения этой ситуации необходимо использовать объект БлокировкаДанных. Мы должны заблокировать записи регистра по конкретным ресурсам перед тем, как выполнять проверку их занятости. Посмотрим, как это выглядит в коде:


Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ЗанятостьРесурсов");
ЭлементБлокировки.УстановитьПараметр("Ресурс", Объект.Автомобиль);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();

// Только после этого выполняем запрос на проверку занятости или запись данных

Резюме и рекомендации

Подводя итог, можно выделить следующие правила проектирования систем контроля занятости в 1С:

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

← На главную