Нумерация документа своя в отдельном поле

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

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

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

Посоветуйте как избежать таких ситуаций?
Хранить номер в регистре сведений (чек,номердоговора) и ставить БлокировкуДанных при записи?
По теме из базы знаний
Вознаграждение за ответ
Показать полностью
Найденные решения
24. spacecraft 26.01.21 15:22 Сейчас в теме +1 $m
(22) все константы это одна таблица и в некоторых СУБД блокировка будет на всю таблицу. РС с 1 записью все же более выгодно смотрится.
Остальные ответы
Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
3. tolyan_ekb 104 26.01.21 13:30 Сейчас в теме
(1) своя нумерация в пределах дня? Может воспользоваться моментом времени для подсчета количества введенных за день документов и присвоения нового номера?
5. ls600 26.01.21 13:47 Сейчас в теме
(3)
Может воспользоваться моментом времени для подсчета количества введенных за день документов и присвоения нового номера?

Есть особенность момента времени, документы проведенные в одну и ту же секунду располагаются в произвольном порядке, а не в порядке их физического создания.
7. spacecraft 26.01.21 14:17 Сейчас в теме
(1) при записи плохой вариант. данные реквизитов уже записаны в транзакцию и изменять реквизиты документа уже не желательно.
Далее, при каждой записи будет повторно получать новый номер, или городить дополнительные проверки.
Если номер документа не выставляется принудительно вручную/программно, то оптимальный обработчик будет ПриУстановкеНовогоНомера.
Ну и как предлагали сами завести РС непериодический независимый с ресурсом Номер. И использовать блокировку данных.
12. nomad_irk 72 26.01.21 14:46 Сейчас в теме
(1)
Хранить номер в регистре сведений (чек,номердоговора) и ставить БлокировкуДанных при записи?

Именно так и никак иначе.
Блокировка будет регистра сведений, хранящего последний номер - она не будет длинной, т.к. будет только при запросе нового номера.
2. ls600 26.01.21 13:15 Сейчас в теме
Если ставить блокировку данных при записи, мало вероятно, но при одновременном чтении одних и тех же данных конкурирующими транзакциями могут возникнуть следующие проблемы одновременного доступа т.е если две транзакции, взяв в качестве первоисточника начальное значение этих данных, то в системе останутся изменения внесенные той транзакцией, которая записала свои изменения последней, поскольку эти изменения заменят собой все изменения, внесенные до этого. Как то так :)
4. JohnGalt 57 26.01.21 13:42 Сейчас в теме
Как варианты:
1. Отключить контроль уникальности, сделать свой, запускать процесс перенумерации ежедневно в конце дня
2. Сделать регистр для проверки актуального номера, чтобы первый чек при попытке записи делал запись в регистре, а второй смотрел в регистр и формировал следующий номер
6. AlexeyPapanov 459 26.01.21 13:52 Сейчас в теме
(4) НомерДоговора используется при печати документа клиенту. Я не могу его менять опосля.
Мимо короче.
Видимо я сам себе предложил самый оптимальный вариант.
8. insurgut 207 26.01.21 14:30 Сейчас в теме
У документа Автонумерация = Ложь, Контроль уникальности выставляете в зависимости от целей вашей задачи.

Перед записью формируете Номер как душе угодно: добавляете проверку на заполненность, если номер пустой - формируете по правилу/алгоритму, если номер заполнен, то опять смотрим, требуется ли сверять часть номера? Если например по правилу номер (префикс) отличается, то меняете номер на новый и т.п.
9. AlexeyPapanov 459 26.01.21 14:37 Сейчас в теме
(7)
ПриУстановкеНовогоНомера

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

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

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

Запросами считать количество документов все-таки долго, проще ко времени и префиксам привязаться.
13. AlexeyPapanov 459 26.01.21 14:50 Сейчас в теме
(10)
Клиент оказывает услуги. Номенклатура трех видов. На один вид номенклатуры нумеровать договора не надо.
А остальные два вида услуг - каждый чек это отдельный договор. Вот я и нумерую всплошную договора. Нельзя в моем случае префиксы использовать, клиент поставил задачу так.

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

По задаче - значит делайте так, чтобы то, что вы рассчитываете перед записью уже было посчитано в форме документа перед записью. Добавьте реквизит "Вид договора" (или как правильно его назвать), который вы установите ещё из формы. Но в любом случае от одномоментно пробитых чеков это вас никак не спасет.
21. AlexeyPapanov 459 26.01.21 15:06 Сейчас в теме
(16) Клиент бюджетный, там строгие правила. Вот хотим сплошную нумерацию договоров цифрами по нужным нам чекам. Все. Никаких префиксов, уидов и прочего. Тут мы даже не обсуждаем.
14. spacecraft 26.01.21 14:55 Сейчас в теме
(9) конечно блокировка необходима. Это даже не обсуждается.
Проблема дублей из-за того, что во время транзакции запись происходит в саму транзакцию и по факту она не видна другим вне транзакции. Можно упрощенно считать что записи еще нет в базе.

Блокировать РС с нумератором придется весь, но по идее там всего одна запись.
На момент блокировки и до конца транзакции РС будет заблокирован. Тут уже смотрите, если запись/проведение чека очень большое, то можно рассматривать альтернативные варианты.
Еще как вариант, можно смотреть в сторону пулов нумерации (еще как альтернатива - префиксы), если требования к строгому порядку номеров нет.
15. nomad_irk 72 26.01.21 15:00 Сейчас в теме
(14)Если требований к строгому порядку номеров нет, то РС можно блокировать на момент выдачи нового номера.
17. spacecraft 26.01.21 15:03 Сейчас в теме
(15) если требования к строгому порядку номеров нет, то можно обойтись и без РС.
18. AlexeyPapanov 459 26.01.21 15:04 Сейчас в теме
(14)
Блокировать РС с нумератором придется весь, но по идее там всего одна запись.

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

А я думал вообще в РС хранить номера договоров всех чеков, поэтому и ужаснулся - как мне блокировать потом эту историю целиком...
19. nomad_irk 72 26.01.21 15:05 Сейчас в теме
(18)Зачем вам история номеров? :)
20. spacecraft 26.01.21 15:06 Сейчас в теме
(18)
А я думал вообще в РС хранить номера договоров всех чеков

нет смысла.
Конечно только номер. И без измерений. Практически константа получится.
22. insurgut 207 26.01.21 15:10 Сейчас в теме
(20) константа и есть :) Осталось только замерить, что быстрее, чтение и запись константы или чтение и запись регистра сведений.
23. AlexeyPapanov 459 26.01.21 15:13 Сейчас в теме
(20) Да, вот понятно кто из нас программист, а кто самоучка с бух.дипломом)
Тогда да, действительно чего бояться этой блокировки?...
Просто подписку на событие перед записью уберу, а воспользуюсь обработкой проведения.

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

spacecraft победил! И Вы insurgut мне уже помогали. Спасибо Вам, коллеги! Я Вашей квалификации восхищаюсь и белой завистью завидую.
24. spacecraft 26.01.21 15:22 Сейчас в теме +1 $m
(22) все константы это одна таблица и в некоторых СУБД блокировка будет на всю таблицу. РС с 1 записью все же более выгодно смотрится.
25. insurgut 207 26.01.21 16:24 Сейчас в теме
(24) не претендую на истину... добавил константу, добавил регистр, сделал что-то вроде:


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

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

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

&НаКлиенте
Процедура ЗапуститьЗамер(Команда)
	
	//повторяем 3 раза
	Для ГлобальныйСч = 1 По 3 Цикл
	
		Дата1 = ТекущаяДата();
		Для Сч = 1 по 2000 Цикл
			ПрочитатьУвеличитьКонстанту();
		КонецЦикла;
		Дата2 = ТекущаяДата();
		
		Разница = Дата2 - Дата1;
		
		Сообщить("Время через константы: " + Разница + " сек.");
		
		
		Дата1 = ТекущаяДата();
		Для Сч = 1 по 2000 Цикл
			ПрочитатьУвеличитьРегистр();
		КонецЦикла;
		Дата2 = ТекущаяДата();
		
		Разница = Дата2 - Дата1;
		
		Сообщить("Время через регистр: " + Разница + " сек.");
		
	КонецЦикла;
	
КонецПроцедуры

Показать


В результате константы быстрее...
Прикрепленные файлы:
26. spacecraft 26.01.21 16:27 Сейчас в теме
27. insurgut 207 26.01.21 16:38 Сейчас в теме
(26) в примере да, попробую на клиент-серверном варианте повторить :)
28. spacecraft 26.01.21 16:51 Сейчас в теме
(27) еще один не маловажный момент. Запись будет происходить в транзакции, а не в цикле транзакций.
Мало подходит приведенный пример для сравнения с планируемой реализацией.
29. AlexeyPapanov 459 26.01.21 16:56 Сейчас в теме
(28) У меня клиент-сервер. Я использовал вариант с РС и его блокировкой.
Использовал процедуру модуля объекта документа ПриЗаписи(). Все работает, осталось в бою проверить.
30. spacecraft 26.01.21 16:59 Сейчас в теме
(29) я уже говорил, что в обработчике ПриЗаписи не желательно изменять реквизит объекта.
Все же рекомендовал бы использовать обработчик ПриУстановкеНовогоНомера, или ПередЗаписью. Во втором случае еще желательно добавить проверку на наличие уже установленного номера, чтобы при перезаписи не изменять номер.
31. AlexeyPapanov 459 26.01.21 17:01 Сейчас в теме
(30) Да, Вы правы, я спешке забыл. Спасибо! Исправлю.
32. davealone 165 26.01.21 17:03 Сейчас в теме
(24) Уже давно отдельные таблицы на каждую константу, с 8.2.14 еще кажись
Ambakollajder; +1 Ответить
11. JohnGalt 57 26.01.21 14:44 Сейчас в теме
Ок, еще вариант: формирование уникального номера. Стандартный УИД большой, можно чем-то поменьше воспользоваться...
33. AlexeyPapanov 459 28.01.21 18:53 Сейчас в теме
Сегодня внедрил это дело. В событие ПередЗаписью. Использовал РС и БлокировкуДанных.

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

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

Завтра уберу на день блокировку. Погляжу.
34. spacecraft 28.01.21 19:12 Сейчас в теме
(33) если время транзакции большое, то можно установку номера с блокировкой делать в обработчике модуля формы ПередЗаписьюНаСервере. Он до транзакции выполняется. Тут конечно будет дополнительная работа с БД, но как вариант можно рассматривать. Только там обращение к реквизитам не через Объект, а через параметр обработки ТекущийОбъект.
35. AlexeyPapanov 459 28.01.21 21:18 Сейчас в теме
(34) Спасибо! Мои коллеги местные меня успоколили, сказав, что это глюк давний у розницы. Но надо проверить. Если без блокировки будет тихо, то попробую Ваш вариант.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот