При разработке конфигураций на платформе 1С нередко возникает необходимость контролировать уникальность составных номеров документов или иных бизнес-сущностей. Рассмотрим частую задачу: документ имеет стандартный номер и дополнительный реквизит — Литер (например, значение из перечисления). Требуется сделать так, чтобы в течение одного календарного года сочетание номера и литера (например, «1/А», «1/Б», «1/В») не повторялось, а платформа автоматически блокировала создание дублей.
Проанализируем ситуацию, с которой сталкиваются разработчики при первоначальной настройке регистра сведений. Если попытаться создать измерение Дата вручную и добавить его в ключ регистра вместе с измерениями Номер и Литер, то платформа перестанет выдавать ошибку о дублировании данных в разные дни.
Выясним причину такого поведения: в 1С ключ уникальности записи формируется из всех полей, входящих в состав измерений. У периодического регистра сведений системное поле Период уже выполняет роль измерения. Если добавить еще одно пользовательское измерение Дата, уникальность начинает проверяться по набору Период + Дата + Номер + Литер. В результате документы с одинаковыми номерами и литерами, проведенные в разные дни года, имеют разную дату и успешно записываются в систему без ошибок.
Чтобы встроенный механизм 1С автоматически отслеживал уникальность значений в течение года, разберем по шагам правильный алгоритм настройки регистра сведений в конфигураторе:
Периодичность в значение В пределах года. При такой настройке платформа автоматически приводить значение стандартного реквизита Период к началу года (01 января 00:00:00) для любой создаваемой записи.Дата. Для отслеживания времени в периодических регистрах используется исключительно реквизит Период.Номер (тип Строка ограниченной длины);Литер (тип ПеречислениеСсылка...).При таком подходе ключ уникальности записей базы данных будет состоять из набора Период (начало года) + Номер + Литер. Все документы, проводимые в течение одного календарного года, получат одинаковое приведенное значение периода, и при попытке записать дублирующее сочетание номера и литера платформа сгенерирует ошибку уникальности.
Рассмотрим важную техническую деталь работы платформы 1С при выборе режима записи:
1. Независимый регистр сведений: Первичный ключ СУБД состоит из полей Период и всех составных измерений. Платформа 1С гарантирует контроль уникальности комбинации измерений между совершенно разными документами на уровне базы данных.
2. Регистр, подчиненный регистратору: Первичный ключ записи формируется по полям Регистратор и НомерСтроки. В этом случае платформенный контроль уникальности измерений работает только внутри одного документа (в рамках одного набора записей). Если два разных документа попытаются записать одинаковые «Номер» и «Литер» за один год в подчиненный регистр, платформа не выдаст ошибку автоматически.
Рекомендация: Для гарантированного автоматического контроля уникальности сочетания полей между разными документами используйте независимый периодический регистр сведений, а запись в него производите программно из обработки проведения документов.
Посмотрим на альтернативный способ решения задачи. Контроль уникальности комбинации полей можно выполнить без создания дополнительного регистра сведений — прямо в событии ОбработкаПроведения модуля документа с помощью запроса.
Проанализируем пример кода для модуля документа:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Док.Ссылка КАК Ссылка
|ИЗ
| Документ.ПриходнаяНакладная КАК Док
|ГДЕ
| Док.Дата МЕЖДУ &НачалоГода И &КонецГода
| И Док.Номер = &Номер
| И Док.Литер = &Литер
| И Док.Ссылка <> &Ссылка";
Запрос.УстановитьПараметр("НачалоГода", НачалоГода(ПроводимыйДокумент.Дата));
Запрос.УстановитьПараметр("КонецГода", КонецГода(ПроводимыйДокумент.Дата));
Запрос.УстановитьПараметр("Номер", СокрЛП(ПроводимыйДокумент.Номер));
Запрос.УстановитьПараметр("Литер", ПроводимыйДокумент.Литер);
Запрос.УстановитьПараметр("Ссылка", ПроводимыйДокумент.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
ВызватьИсключение "Документ с таким номером и литером уже зарегистрирован в текущем году!";
КонецЕсли;
Для предотвращения обхода проверки из-за случайных пробелов или разного регистра букв рекомендуется всегда нормализовать текстовые поля перед проверкой и записью с помощью функций СокрЛП() и ВРЕГ().