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