Коллеги, посоветуйте.
Как нумеровать документы в отдельном поле, чтобы избежать задвоения номера?
Сделал по простому нумерацию чеков ККМ в Рознице.
Если в чеке есть номенклатура определенного вида, то номер присваиваем, иначе ничего не делаем.

Как сделал я: Подписку на событие ПередЗаписью, и в ней я делаю анализ и установку значения в поле НомерДоговора.
Это поле типа Число. При необходимости установить новый, я беру последний и прибавляю 1.

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

Посоветуйте как избежать таких ситуаций?
Хранить номер в регистре сведений (чек,номердоговора) и ставить БлокировкуДанных при записи?
---
все константы это одна таблица и в некоторых СУБД блокировка будет на всю таблицу. РС с 1 записью все же более выгодно смотрится.
---
своя нумерация в пределах дня? Может воспользоваться моментом времени для подсчета количества введенных за день документов и присвоения нового номера?
---
Может воспользоваться моментом времени для подсчета количества введенных за день документов и присвоения нового номера?
Есть особенность момента времени, документы проведенные в одну и ту же секунду располагаются в произвольном порядке, а не в порядке их физического создания.
---
при записи плохой вариант. данные реквизитов уже записаны в транзакцию и изменять реквизиты документа уже не желательно.
Далее, при каждой записи будет повторно получать новый номер, или городить дополнительные проверки.
Если номер документа не выставляется принудительно вручную/программно, то оптимальный обработчик будет ПриУстановкеНовогоНомера.
Ну и как предлагали сами завести РС непериодический независимый с ресурсом Номер. И использовать блокировку данных.
---
Хранить номер в регистре сведений (чек,номердоговора) и ставить БлокировкуДанных при записи?
Именно так и никак иначе.
Блокировка будет регистра сведений, хранящего последний номер - она не будет длинной, т.к. будет только при запросе нового номера.
---
Если ставить блокировку данных при записи, мало вероятно, но при одновременном чтении одних и тех же данных конкурирующими транзакциями могут возникнуть следующие проблемы одновременного доступа т.е если две транзакции, взяв в качестве первоисточника начальное значение этих данных, то в системе останутся изменения внесенные той транзакцией, которая записала свои изменения последней, поскольку эти изменения заменят собой все изменения, внесенные до этого. Как то так :)
---
Как варианты:
1. Отключить контроль уникальности, сделать свой, запускать процесс перенумерации ежедневно в конце дня
2. Сделать регистр для проверки актуального номера, чтобы первый чек при попытке записи делал запись в регистре, а второй смотрел в регистр и формировал следующий номер
---
НомерДоговора используется при печати документа клиенту. Я не могу его менять опосля.
Мимо короче.
Видимо я сам себе предложил самый оптимальный вариант.
---
У документа Автонумерация = Ложь, Контроль уникальности выставляете в зависимости от целей вашей задачи.

Перед записью формируете Номер как душе угодно: добавляете проверку на заполненность, если номер пустой - формируете по правилу/алгоритму, если номер заполнен, то опять смотрим, требуется ли сверять часть номера? Если например по правилу номер (префикс) отличается, то меняете номер на новый и т.п.
---
ПриУстановкеНовогоНомера
У меня номер выставляется при соблюдении определенного условия. Вот я думаю, что блокировка мой выход. Ведь в обработчике все равно будет тот же самый запрос к базе и последующая запись. Т.е. возможен и в этом варианте параллельный ввод одного номера.

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

(8) Номер Чека мне надо оставить, а мой НомерДоговора - я либо присваиваю, либо нет. По соблюдению условия.
---
условие выложите, может в нем проблема?
Самый простой вариант решения вашей проблемы с дублями - кто выбивает чек? Касса? Каждой кассе присвоить префикс, добавляет его в номер. Одна касса одномоментно не сможет напечатать несколько чеков. И даже если Касса1 и Касса2 в 14:34:25 распечатают чеки, у первой номер будет К120210126143425, у второй К20210126143425 - никакого дубля не будет.

Запросами считать количество документов все-таки долго, проще ко времени и префиксам привязаться.
---
Клиент оказывает услуги. Номенклатура трех видов. На один вид номенклатуры нумеровать договора не надо.
А остальные два вида услуг - каждый чек это отдельный договор. Вот я и нумерую всплошную договора. Нельзя в моем случае префиксы использовать, клиент поставил задачу так.

Поэтому я перед установкой ищу из табличной части номенклатуру, по которой чеки не нумеруются. Если запрос вернул пустой результат, то присваиваю НомерДоговора.
---
что значит нельзя? Т.е. если в один момент времени пробиваются 2 чека с одинаковым видом, то какой номер должен быть по логике клиента? Зачастую задачу ставят люди далекие от нюансов, либо им на самом деле все равно, добавится там что-то в номере или нет. Главное, чтобы их набор символов в номере присутствовал. :)

По задаче - значит делайте так, чтобы то, что вы рассчитываете перед записью уже было посчитано в форме документа перед записью. Добавьте реквизит "Вид договора" (или как правильно его назвать), который вы установите ещё из формы. Но в любом случае от одномоментно пробитых чеков это вас никак не спасет.
---
Клиент бюджетный, там строгие правила. Вот хотим сплошную нумерацию договоров цифрами по нужным нам чекам. Все. Никаких префиксов, уидов и прочего. Тут мы даже не обсуждаем.
---
конечно блокировка необходима. Это даже не обсуждается.
Проблема дублей из-за того, что во время транзакции запись происходит в саму транзакцию и по факту она не видна другим вне транзакции. Можно упрощенно считать что записи еще нет в базе.

Блокировать РС с нумератором придется весь, но по идее там всего одна запись.
На момент блокировки и до конца транзакции РС будет заблокирован. Тут уже смотрите, если запись/проведение чека очень большое, то можно рассматривать альтернативные варианты.
Еще как вариант, можно смотреть в сторону пулов нумерации (еще как альтернатива - префиксы), если требования к строгому порядку номеров нет.
---
Если требований к строгому порядку номеров нет, то РС можно блокировать на момент выдачи нового номера.
---
если требования к строгому порядку номеров нет, то можно обойтись и без РС.
---
Блокировать РС с нумератором придется весь, но по идее там всего одна запись.

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

А я думал вообще в РС хранить номера договоров всех чеков, поэтому и ужаснулся - как мне блокировать потом эту историю целиком...
---
Зачем вам история номеров? :)
---
А я думал вообще в РС хранить номера договоров всех чеков
нет смысла.
Конечно только номер. И без измерений. Практически константа получится.
---
константа и есть :) Осталось только замерить, что быстрее, чтение и запись константы или чтение и запись регистра сведений.
---
Да, вот понятно кто из нас программист, а кто самоучка с бух.дипломом)
Тогда да, действительно чего бояться этой блокировки?...
Просто подписку на событие перед записью уберу, а воспользуюсь обработкой проведения.

(22) Ради интереса может потом померю и сброшу сюда результат.

spacecraft победил! И Вы insurgut мне уже помогали. Спасибо Вам, коллеги! Я Вашей квалификации восхищаюсь и белой завистью завидую.
---
все константы это одна таблица и в некоторых СУБД блокировка будет на всю таблицу. РС с 1 записью все же более выгодно смотрится.
---
не претендую на истину... добавил константу, добавил регистр, сделал что-то вроде:

```1c
    &НаСервере
    Процедура ПрочитатьУвеличитьКонстанту();

    ПоследнийНомер = Константы._ПоследнийНомер.Получить();
    ПоследнийНомер = ПоследнийНомер + 1;
    Константы._ПоследнийНомер.Установить(ПоследнийНомер);

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

    &НаСервере
    Процедура ПрочитатьУвеличитьРегистр();

    НаборЗаписей = РегистрыСведений._ПоследнийНомер.СоздатьНаборЗаписей();
    НаборЗаписей.Прочитать();
    ПоследнийНомер = НаборЗаписей[0].Номер;
    ПоследнийНомер = ПоследнийНомер + 1;
    НаборЗаписей[0].Номер = ПоследнийНомер;
    НаборЗаписей.Записать();

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

    &НаКлиенте
    Процедура ЗапуститьЗамер(Команда)

    //повторяем 3 раза
    Для ГлобальныйСч = 1 По 3 Цикл

    Дата1 = ТекущаяДата();
    Для Сч = 1 по 2000 Цикл
    ПрочитатьУвеличитьКонстанту();
    КонецЦикла;
    Дата2 = ТекущаяДата();

    Разница = Дата2 - Дата1;

    Сообщить("Время через константы: " + Разница + " сек.");

    Дата1 = ТекущаяДата();
    Для Сч = 1 по 2000 Цикл
    ПрочитатьУвеличитьРегистр();
    КонецЦикла;
    Дата2 = ТекущаяДата();

    Разница = Дата2 - Дата1;

    Сообщить("Время через регистр: " + Разница + " сек.");

    КонецЦикла;

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

В результате константы быстрее...
---
база файловая?
---
в примере да, попробую на клиент-серверном варианте повторить :)
---
еще один не маловажный момент. Запись будет происходить в транзакции, а не в цикле транзакций.
Мало подходит приведенный пример для сравнения с планируемой реализацией.
---
У меня клиент-сервер. Я использовал вариант с РС и его блокировкой.
Использовал процедуру модуля объекта документа ПриЗаписи(). Все работает, осталось в бою проверить.
---
я уже говорил, что в обработчике ПриЗаписи не желательно изменять реквизит объекта.
Все же рекомендовал бы использовать обработчик ПриУстановкеНовогоНомера, или ПередЗаписью. Во втором случае еще желательно добавить проверку на наличие уже установленного номера, чтобы при перезаписи не изменять номер.
---
Да, Вы правы, я спешке забыл. Спасибо! Исправлю.
---
Уже давно отдельные таблицы на каждую константу, с 8.2.14 еще кажись
---
Ок, еще вариант: формирование уникального номера. Стандартный УИД большой, можно чем-то поменьше воспользоваться...
---
Сегодня внедрил это дело. В событие ПередЗаписью. Использовал РС и БлокировкуДанных.

Пару раз в день получили проблему: при оплате картой не выходил чек на фискальнике. Т.е. слип чек вылазит, а потом ошибка.

Я вот думаю не в блокировке ли моей дело? Не должно же по идее.
Подумал: может записывают чек в одно время, на одной кассе идет запись чека, блокируется мой РС с номером договора, а другая касса к нему же обращается, срабатывает блокировка и чек на ФР не бьется.

Завтра уберу на день блокировку. Погляжу.
---
если время транзакции большое, то можно установку номера с блокировкой делать в обработчике модуля формы ПередЗаписьюНаСервере. Он до транзакции выполняется. Тут конечно будет дополнительная работа с БД, но как вариант можно рассматривать. Только там обращение к реквизитам не через Объект, а через параметр обработки ТекущийОбъект.
---
Спасибо! Мои коллеги местные меня успоколили, сказав, что это глюк давний у розницы. Но надо проверить. Если без блокировки будет тихо, то попробую Ваш вариант.