обновление документа

  • Автор темы nadezdaMP
  • Дата начала
N

nadezdaMP

Гость
#1
есть документ, на нем поля типа computed в которое подставляются значения из другого дока.
документы отображаются в представлении.

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

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

можно было бы заместо них использовать
поля Computed for display, но тогда их нельзя будет отображать в представлении.

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

Akupaka

А че я?.. О.о
04.10.2007
3 360
2
34
Kiev, Ukraine
#2
надеюсь понятно обьяснила.
не надейся )))

как сделать автообновление полей в документе при изменении их в доке?
имеется в виду, при изменении бэк-эндового дока, взятого из бд, а не из уи?
есть тяжелый метод nd.ComputeWithForm(), либо прописать нужный код для вычисления-обновления нужных полей и запускать его.
 
N

nadezdaMP

Гость
#3
имеется в виду, при изменении бэк-эндового дока, взятого из бд, а не из уи?
да, именно так

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

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
37
Латвиджа, Рига
#4
При сохранении того документа из которого читаются поля пробегаемся по отображающим документам и обновляем по мере надобности в них поля.
Computed поля выкидываем, как класс :)
 
N

nadezdaMP

Гость
#5
пробегаемся по отображающим документам
получается можно создать коллекцию документов, в которых используются вычисляемые поля, например по их форме, пробежаться по каждому документу, и

обновляем по мере надобности в них поля.
как обновить Computed поля? простым ReplaceItemValue?

Computed поля выкидываем, как класс
это как? и зачем?
в первый раз столкнулась с такой задачей, обьясните пожалуйста.
 

hosm

* so what *
18.05.2009
2 442
9
42
Kiev, Ukraine
#6
Omh
Это все замечательно, если не знать, что мы работаем на лотусе :)
А про доступ к отображающим документам забыли? А вдруг мы не авторы в них?
 

TIA

:-)
Lotus team
15.05.2009
790
1
#7
nadezdaMP
см.ещё @Command( [ToolsRefreshAllDocs] ) . Может, пригодится.
 
#8
как сделать автообновление полей в документе при изменении их в доке???? так , чтобы в представлении для документа они тоже обновлялись.
малой кровью - никак. Как вы правильно заметили - при открытии документа можно отображать соотв. связное значение(CFD), но в индекс вида его запихнуть не получится. Это архитектурная особенность domino
Вы хотите классического реляционного отношения primary-secondary, а его нету...
Вам необходимо вручную поймать изменение поля в primary документе и обновить соотв. поля в secondary.
Обычно пишется агент, который синхронизирует соотв. поля - строит коллекцию документов, в которых используется старое значение и прописывает в них новое.
Условие запуска такого агента сильно зависит от логики приложения - от "postSave в UI" до "по расписанию" на сервере. В клинических случаях юзают серверные extension-ы, но надеюсь что до этого у вас не дойдет :)
 

hosm

* so what *
18.05.2009
2 442
9
42
Kiev, Ukraine
#10
Klido
это уже получше, но надо правильно настроить время запуска, чтоб не привело к сейв-конфликтам.
В общем, тут действительно надо балансировать исходя из возможностей приложения.
Вот turumbay выше очень правильно сказал.

nadezdaMP
Меняем обычные поля действительно через ReplaceItemValue.
Если ридерс-авторс, то лучше при замене указывать явно IsReaders/IsAuthors.
 
N

nadezdaMP

Гость
#11
вопрос, как определить ОТОБРАЖАЮЩИЕСЯ документы?
 

hosm

* so what *
18.05.2009
2 442
9
42
Kiev, Ukraine
#12
а как они определяются у Вас в системе, как понимают, что значение надо вычитать из другого документа?
Ну, например, дочерние документы или есть какое-то поле-связь?
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
2
34
Kiev, Ukraine
#13
то есть? а подробнее расскажите, как это сделать пожалуйста
Надя, все правильно, с пом ReplaceItemValue можно заменить значение любого итема (!) независимо от наличия одноименного поля на форме, которая его отображает и типа этого поля.
Если тебе надо изменить компутед-поля только изменяемого документа, то пишется приммерно такой код:

Код:
sub ComputeMyItems(ADoc as NotesDocument)
' например, значение поля Computed1 высчитывает по формуле: Item1 + " ABC", где Item1 - однозначное текст поле
ADoc.ReplaceItemValue("Computed1", ADoc.GetItemValue("Item1")(0) & " ABC")
' или так, тогда даже не обязательно однозначное поле
ADoc.ReplaceItemValue("Computed1", Evaluate({Item1 + " ABC"}, ADoc))
end sub

sub SomeSub()
dim doc as notesDocument
...
call doc.ReplaceItemValue("Item1", "SomeValue1")
call ComputeMyItems(doc)
print doc.GetItemValue("Computed1")(0) ' prints: SomeValue1 ABC
...
end sub
или же, если форма не тяжелая, т.е. вычисляемых полей не много, и обработка не большого кол-ва обновляемых доков, то просто:
Код:
sub SomeSub()
dim doc as notesDocument
...
call doc.ReplaceItemValue("Item1", "SomeValue1")
call doc.ComputeWithForm(...)
print doc.GetItemValue("Computed1")(0) ' prints: SomeValue1 ABC
...
end sub
ВСЕМ:
откуда вы взяли, что нужно обрабатывать какие-то коллекции? О.о
Вы хотите классического реляционного отношения primary-secondary
где это написано было?
 
N

nadezdaMP

Гость
#15
в документе1 есть вычисляемое поле типа Computed, которое использует данные из документа2.
есть поле связь, которое содержится в обоих документах, по нему сейчас работаю.
 

Akupaka

А че я?.. О.о
04.10.2007
3 360
2
34
Kiev, Ukraine
#16
"У медведицы было три медвежонка: Умка, Глупка и Тупка" (с) :)
туплю я что-то...

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

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

все сильно усложняется, если приложение распределенное, чем сильнее распределено, тем сложнее каскадное обновление.
 

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
37
Латвиджа, Рига
#17
Не всё так плохо.
Обычно хватает скрипта, который отслеживает изменения ключевых полей в главном документе (через глобальные переменные или ещё как) + запуск скрипта/агента на PostSave при изменении ключевых полей.

Такого мехнизма, кмк, хватает в 80% случаев
 
N

nadezdaMP

Гость
#18
осталось только шефу обьяснить, что это она нетривиальная :D

база пока одна единственная.
на форме документа2, из которого берутся поля для вычисления полей в документе1 (в продолжение вышестоящей задачи) добавила следующий код
Код:
Sub Querysave(Source As Notesuidocument, Continue As Variant)
If Not (source.IsNewDoc) Then			 ' на редактирование
cat_name$ = Source.Document.GetItemValue("cat_name")(0)  'то на что заменить
item = Source.Document.GetItemValue("doc_uid")(0)			  'ссылка на документ 

Set s = New NotesSession
Set db = s.CurrentDatabase
Set ndcoll = db.FTSearch("comp",0)
Set doc = ndcoll.GetFirstDocument
While Not doc Is Nothing
If item = doc.GetItemValue("typeid")(0) Then				  ' если доки связаны
cp_name$ = doc.GetItemValue("cp_name")(0)
cp_typename$ = doc.GetItemValue("cp_typename")(0)
If cp_name$ = cp_typename$ Then
cp$ = Strleftback(cp_name$, "/ ")	  ' необходимые преобразования
new_cp$ = cp$ + "/ " + cat_name$
Call doc.ReplaceItemValue("cp_name", new_cp$)	' заменить поля
Call doc.ReplaceItemValue("cp_typename", new_cp$)
Call doc.Save(True, False)
End If
End If
Set doc = ndcoll.GetNextDocument(doc)
Wend
End If
End Sub
столкнулась только с неприятной особенностью что придется перестраивать индекс в представленнии, где используется документ1 для поиска в нем по измененному значению, иначе будет искать по значению поля, которое было до изменения.

Всем спасибо за советы))
 

TIA

:-)
Lotus team
15.05.2009
790
1
#19
Советы
1. Лучше перенести код в PostSave, а то есть возможность отменить сохранение (continue=false или конфликт сохранения)
2. Проверить, что поле cat_name изменилось за время редактирования, иначе дальнейшие операции бессмыслены
3. Не использовать FTSearch. Полнотекстовый индекс обновляется с существенной задержкой
4. Связанные документы искать по виду через getAllDocumentByKey. Вид должен иметь первую колонку отсортированную по typeid.
5. Что-то тут не логично. Можт Source.Document должен быть где-то вместо doc?
cp_name$ = doc.GetItemValue("cp_name")(0)
cp_typename$ = doc.GetItemValue("cp_typename")(0)
If cp_name$ = cp_typename$ Then
 

Omh

Well-Known Member
Lotus team
04.07.2007
2 210
1
37
Латвиджа, Рига
#20
Ну как бэ вдогонку:
1. Лучше сделать переменную дока и в него присвоить Source.Document, что бы не дёргать несколько раз Source
2. db сдесь можно получить из doc.ParentDatabase, что бы зря не декларить session
3. А где переменные задекларены или без Option Declare пишешь? :D