Книга знаний

1С:Предприятие / v8 / Объекты конфигурации / Справочники

v8: Создание своего уникального кода для справочника

Однажды мне понадобилось создать свой уникальный код для справочника, т.к. поле Код было занято. Я столкнулся с тем, что начали появляться дубли кодов, когда пользователи одновременно записывали два элемента справочника. Здесь метод решения этой проблемы.Автор статьи:
Последняя редакция №1 от 20.09.06
URL: http://kb.mista.ru/article.php?id=370

Ключевые слова: запросы,транзакция,конкуренция


Тема горячо обсуждалась здесь: v8: v8: У меня появились дубли уникального кода, что делать?

Процедура ПередЗаписью(Отказ)
        Если Не Отказ И НЕ ЭтоГруппа Тогда
            //Здесь сложное условие определения, нужно ли устанавливать уникальный код.
            Если ЗначениеНеЗаполнено(УникальныйКод) Или ЭтоНовый() ИЛИ ЗначениеНеЗаполнено(Ссылка.ПолучитьОбъект().УникальныйКод) Тогда
                Префикс = СокрЛП(ПланыОбмена.Подразделения.ЭтотУзел().Код);
                УникальныйКод=обПолучитьНовыйКод(Метаданные.Справочники.Договоры, Префикс, "УникальныйКод", Метаданные.Справочники.Договоры.Реквизиты.УникальныйКод.Тип.КвалификаторыСтроки.Длина);
КонецПроцедуры

Функция обПолучитьНовыйКод(МДОбъект, Префикс, Реквизит, Длина) Экспорт //fixin 20060728
    П=обТипОбъектаПоМетаданным(МДОбъект);
    Имя=МДОбъект.Имя;
    Запрос=Новый Запрос("ВЫБРАТЬ
                        |    МАКСИМУМ(Договоры.Код) КАК Зн
                        |ИЗ
                        |    Справочник.Договоры КАК Договоры
                        |ГДЕ
                        |    Договоры.Код ПОДОБНО &Шаблон
                        |
                        |ДЛЯ ИЗМЕНЕНИЯ"); 
    //Очень важно использовать ДЛЯ ИЗМЕНЕНИЯ - чтобы гарантированно код был уникальным
    Запрос.Текст=СтрЗаменить(Запрос.Текст, "Договоры", Имя);
    Запрос.Текст=СтрЗаменить(Запрос.Текст, "Справочник", П.ИмяЕЧ);
    Запрос.Текст=СтрЗаменить(Запрос.Текст, "Код", Реквизит);
    Запрос.УстановитьПараметр("Шаблон", Префикс+"%"); //ПОДОБНО "АВ%", например, хотя логичнее искать цифры
    Выборка=Запрос.Выполнить().Выбрать();
    ДлинаПрефикса=СтрДлина(Префикс);
    Выборка.Следующий();
    Если Выборка.Зн<>Null Тогда
        МаксКод=Число(Сред(Выборка.Зн, ДлинаПрефикса+1));
    Иначе
        МаксКод=0;
    КонецЕсли;
    МаксКод=МаксКод+1; //Увеличиваем максимальный код
    Рез=Префикс+Формат(МаксКод, "ЧЦ="+Формат(Длина-ДлинаПрефикса,"ЧГ=")+"; ЧВН=; ЧГ=");
    Возврат  Рез;
КонецФункции


Итак, важные моменты:
  • Вся запись объекта происходит в одной транзакции, поэтому достаточно использовать ДЛЯ ИЗМЕНЕНИЯ в запросе к договорам, чтобы другие процессы не смогли прочитать справочник договора, пока не завершится транзакция записи
  • На этом я прокололся, поэтому обратите внимание: если при записи происходит ошибка блокировки и пользователь не закрыл карточку, то даже у нового объекта уникальный код уже установлен, т.к. уже прошел код по установке уникального кода. Поэтому используется такое сложное условие для определения нужно ли устанавливать уникальный код.

  • Код отлаживался с помощью запуска двух процессов, один из которых выдавал Предупреждение, все работает ОК.

  • Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
    © Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

    Яндекс.Метрика