Автоматический номер

  • Автор темы 1KIA
  • Дата начала
1

1KIA

#1
Что необходимо исправить:
Есть вьюха N с полем NN в нем заполняется номер 1, 2, 3, ... 151, 152...
есть форма с полем Number, которое должно заполнятся автоматически. Оно заполняется в POstOpen
Код:
	Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim item As NotesItem
Set db = session.CurrentDatabase
Set view = db.GetView( "N" )
Set doc = view.GetFirstDocument

If (Not(doc Is Nothing) And (source.IsNewDoc) ) Then 
Set item = doc.GetFirstItem( "NN" )
doc.nm= Int(item.Text )+1
Call Source.FieldSetText("Number",item.Text ) 
End If
Set note = Source.Document
Проблема в том, что если пользователи открывают одновременно карточку и заполняют данне, то номера у них одинаковые.
Как сделать, чтобы номер временно резервировался, т.к. пользователь может 10 минут подумать и закрыть не сохранив документ. В такой ситуации документ не должен создаться и номер должен быть свободен

Если при сохранении
Код:
If Source.IsNewDoc Then
Set item = doc.GetFirstItem( "nm" )
doc.nm= Int(item.Text )+1
Call doc.save(True,True)
то постоянно на 1 больше, если убрать +1, тогда одинаковые номера
 

Gandliar

Lotus team
16.02.2004
341
8
#2
1. Например получать номер в момент сохранения документа, думаю это правильнее всего.

2. Иначе создавать документ номера. Причем обозначать его в резерв, при закрытии документа его освобождать если несохранен. При создании нового номера проверять в первую очередь освобожденные.

3. Сделать сложный номер типа 1.1.1 где последний сегмент номер дока от этого пользователя ;)
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#3
Считаю что нумерацию вообще надо вынести в серверный агент.
1. Если у всех документов нумерация сквозная - есть вероятность что пользователь не "увидит" все документы
2. Если пользователь может передумать и не сохранить документ... следовательно сквозная нумерация нарушится... то почему бы не нумеровать документ после сохранения, а затем информировать пользователя о присвоении номера?
 
1

1KIA

#5
2. понмаю, что это именно то что нужно, но слишком сложно
3. не подходит

1. т.е. делать все на QuerySave?
 

Gandliar

Lotus team
16.02.2004
341
8
#6
2. понмаю, что это именно то что нужно, но слишком сложно
3. не подходит

1. т.е. делать все на QuerySave?
В момент QuerySave, после проверки всех нужных полей, присваиваете номер, если он еще не присвоен.
Если пользователю например надо распечатать док с номером - в кнопку печать добавить предупреждение что хотите ли сохранить если номер еще не присвоен.
 
1

1KIA

#7
в такой способ все равно создает одинаковые номера
 
I
#8
Почитайте то что посоветовал turumbay.


Если хотите простую реализацию без обработки сервером можно добавить в базу небольшой справочник который хранит учетные номера для каждого из возможных видов документа (желательно для каждого вида - свой документ). Добавлять номер надо при сейве. Пишем в справочник. меняем себе, оба сейвим. Можно добавить что-то типо такого чтобы не наткнутся на одновременное сохранение

Код:
Do	
Set docNum = ' получаем документ последнего рег. номера
lastNum = ' получаем сам рег. номер
inc = IncreaseNumberByDoc(docNum) ' увеличиваем номер в док-те рег. номера
Loop While inc = False
'присваиваем документу номер

Function IncreaseNumberByDoc(doc As Variant) As Variant
IncreaseNumberByDoc = False
Call doc.ReplaceItemValue("LastRegNumber", doc.GetItemValue("LastRegNumber")(0) + 1)
If doc.Save(False, False) = False Then
IncreaseNumberByDoc = False
Else
IncreaseNumberByDoc = True
End If	
End Function
 

Gandliar

Lotus team
16.02.2004
341
8
#9
в такой способ все равно создает одинаковые номера

Еще раз.

Имеется ввиду работа с одним сервером.
Есть документ настройки хранящий номер.

При попытке сохранения, если док новый, ищем док настройки, добавляем номер+1, пытаемся сохранить flag=docConfig.Save(false, false)
если flag = true то значит сохранили, записываем номер в текущий док и сохраняем его.
если flag = false можем попытаться раз 30 считать док заново (чтобы получить новый номер) еще сохранить, если прокатило, то сохраняем если и через 30 раз ниче - то надо выдать мессадж звать разработчика разбираться, в чем дело и док не сохранять.
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 599
277
#10
-серверный агент и очередь
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 599
277
#12
и эта... UNID - тоже номер ;)
 
1
#13
если делать серверным агентом, то при QuerySave добавляю
Код:
		Set agent = db.GetAgent("Number")
Call agent.RunOnServer(Doc.NoteID)
а в агенте :
Код:
Set doc = db.GetDocumentByID(agent.ParameterDocID)
Set db = session.CurrentDatabase
Set view = db.GetView( "N" )
Set doc = view.GetFirstDocument

If (Not(doc Is Nothing) And (source.IsNewDoc) ) Then 
Set item = doc.GetFirstItem( "NN" )
doc.nm= Int(item.Text )+1
Call Source.FieldSetText("Number",item.Text ) 
End If
т.е. в агент то что было на QuerySave
или уже необходимо агент делать по другому принципу?
 

lmike

нет, пердело совершенство
Lotus team
27.08.2008
6 599
277
#15
я не понимаю почему:
-не использовать UINID (или @Unique) - чем не номер?
-для синхронизации использовать серверные очереди, а не контроль конфликта (если возникает вопрос как- то лучше не нужно, хотя это не сложно)
 

NickProstoNick

Статус как статус :)
Lotus team
22.08.2008
1 809
21
#16
если делать серверным агентом, то при QuerySave добавляю
Код:
		Set agent = db.GetAgent("Number")
Call agent.RunOnServer(Doc.NoteID)
а в агенте :
Код:
Set doc = db.GetDocumentByID(agent.ParameterDocID)
Set db = session.CurrentDatabase
Set view = db.GetView( "N" )
Set doc = view.GetFirstDocument

If (Not(doc Is Nothing) And (source.IsNewDoc) ) Then 
Set item = doc.GetFirstItem( "NN" )
doc.nm= Int(item.Text )+1
Call Source.FieldSetText("Number",item.Text ) 
End If
т.е. в агент то что было на QuerySave
или уже необходимо агент делать по другому принципу?
Агент надо запускать после сохранения его пользователем иначе возможен конфликт.
У меня нумерация работает так.
Есть вид с уже пронумерованными доками, отсортированный "последний сверху"
Агент берет последний док.. и к номеру +1
 

Xalet

Well-known member
08.08.2008
410
0
#17
Поднять локкинг, создать документы по формам с номерами, искать нужный док, проверять лок, лочить, считывать номер, вписывать следующий, сохранять, снимать лок.
 
1
#18
помогите, запуталась просто невероятно
на поле Numb1 , одно отображает данные номера
на POstOpen проверяю
Код:
		If( note.GetItemValue( "Numb1" )(0) = "" ) Then
Call proceduraNumber()
End If
proceduraNumber:
Код:
Dim viewNumber As NotesView
Set viewNumber = db.GetView( "$Number" )

Dim iNumber As String
iNumber = GetNewNumber

'уникаленость 
Dim notUnique As Boolean
notUnique = True
Dim existingBug As NotesDocument
Dim x As Integer

'Проверка уникальности
While( notUnique )
x=x+1

Set existingBug = viewNumber.GetDocumentByKey( iNumber, True )
If( existingBug Is Nothing ) Then
notUnique = False

If iNumber="" Then 
iNumber = GetNewNumber
Else 
Call note.ReplaceItemValue( "Number1", iNumber )
End If

Else
issueNumber = GetNewNumber
End If

If( x=100 ) Then
Exit Sub
End If

Wend
GetNewNumber:
Код:
Dim item As NotesItem

Set db = session.CurrentDatabase
Set view = db.GetView( "$Number" )
Set doc = view.GetFirstDocument
If Not(doc Is Nothing) Then 
Set item = doc.GetFirstItem( "Number1" )
doc.INumber= Int(item.Text )
GetNewNumber=item.Text 
End If
ни при открытии , ни при сохранении поле не заполняется
 

Xalet

Well-known member
08.08.2008
410
0
#19
это документ? Если да, то до первого сохранения его не существует. Соответственно

Call note.ReplaceItemValue( "Number1", iNumber )
If( note.GetItemValue( "Numb1" )(0) = "" ) Then
это вообще не отработает. Надо с уидоком работать либо на постсэйв перевесить. По алгоритмам - похоже на бред... Номер найдется уникальный и впишется в документ. Если тут же не сохоанить, то есть вероятность, что кто-то найдет такой же. На кьюэрисэйв больший шанс сохоанить уникальность, но тоже с вероятными ошибками. И да... Как оно отработает, если пользователи из реплик локальных будут работать?
 
1
#20
запуталась окончательно.
Возвращаюсь назад, а то уже и вовсе ничего не работает
на QueryOpen
Код:
	Dim session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim item As NotesItem
Set db = session.CurrentDatabase
Set view = db.GetView( "number" )
Set doc = view.GetFirstDocument

If (Not(doc Is Nothing) And (source.IsNewDoc) ) Then 
Set item = doc.GetFirstItem( "nn" )
doc.nm= Int(item.Text )+1
Call Source.FieldSetText("Number",item.Text ) 
End If
на QuerySave
Код:
	If Source.IsNewDoc Then
Dim db As NotesDatabase
Dim view As NotesView
Set db = session.CurrentDatabase
Set view = db.GetView( "number" )
Set doc = view.GetFirstDocument
If Not(doc Is Nothing) Then 
Set item = doc.GetFirstItem( "nn" )
doc.nm= Int(item.Text )+1
Call doc.save(True,True)
End If
почему он здесь не проверяется, вот если 1чел уже сохранил, то 2-й по идее должен сохранять +1 номер

помогите...
мне просто необходимо, чтобы номер был виден сразу, но затем если кто-то успел сохраниться, то номер изменился