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

Тема в разделе "Lotus - Программирование", создана пользователем nadezdaMP, 1 дек 2009.

  1. nadezdaMP

    nadezdaMP Гость

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

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

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

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

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

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    не надейся )))

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

    nadezdaMP Гость

    да, именно так

    то есть? а подробнее расскажите, как это сделать пожалуйста.
     
  4. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    При сохранении того документа из которого читаются поля пробегаемся по отображающим документам и обновляем по мере надобности в них поля.
    Computed поля выкидываем, как класс :)
     
  5. nadezdaMP

    nadezdaMP Гость

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

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

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

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    Omh
    Это все замечательно, если не знать, что мы работаем на лотусе :)
    А про доступ к отображающим документам забыли? А вдруг мы не авторы в них?
     
  7. TIA

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    nadezdaMP
    см.ещё @Command( [ToolsRefreshAllDocs] ) . Может, пригодится.
     
  8. turumbay

    Регистрация:
    13 мар 2009
    Сообщения:
    625
    Симпатии:
    2
    малой кровью - никак. Как вы правильно заметили - при открытии документа можно отображать соотв. связное значение(CFD), но в индекс вида его запихнуть не получится. Это архитектурная особенность domino
    Вы хотите классического реляционного отношения primary-secondary, а его нету...
    Вам необходимо вручную поймать изменение поля в primary документе и обновить соотв. поля в secondary.
    Обычно пишется агент, который синхронизирует соотв. поля - строит коллекцию документов, в которых используется старое значение и прописывает в них новое.
    Условие запуска такого агента сильно зависит от логики приложения - от "postSave в UI" до "по расписанию" на сервере. В клинических случаях юзают серверные extension-ы, но надеюсь что до этого у вас не дойдет :)
     
  9. Klido

    Klido Гость

    а агент, подписанный сервером?
     
  10. hosm

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    Klido
    это уже получше, но надо правильно настроить время запуска, чтоб не привело к сейв-конфликтам.
    В общем, тут действительно надо балансировать исходя из возможностей приложения.
    Вот turumbay выше очень правильно сказал.

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

    nadezdaMP Гость

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

    hosm * so what *

    Регистрация:
    18 май 2009
    Сообщения:
    2.450
    Симпатии:
    7
    а как они определяются у Вас в системе, как понимают, что значение надо вычитать из другого документа?
    Ну, например, дочерние документы или есть какое-то поле-связь?
     
  13. Akupaka

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    Надя, все правильно, с пом ReplaceItemValue можно заменить значение любого итема (!) независимо от наличия одноименного поля на форме, которая его отображает и типа этого поля.
    Если тебе надо изменить компутед-поля только изменяемого документа, то пишется приммерно такой код:

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

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Мыслим глобально
     
  15. nadezdaMP

    nadezdaMP Гость

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

    Akupaka А че я?.. О.о

    Регистрация:
    4 окт 2007
    Сообщения:
    3.373
    Симпатии:
    2
    "У медведицы было три медвежонка: Умка, Глупка и Тупка" (с) :)
    туплю я что-то...

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

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

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

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Не всё так плохо.
    Обычно хватает скрипта, который отслеживает изменения ключевых полей в главном документе (через глобальные переменные или ещё как) + запуск скрипта/агента на PostSave при изменении ключевых полей.

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

    nadezdaMP Гость

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

    база пока одна единственная.
    на форме документа2, из которого берутся поля для вычисления полей в документе1 (в продолжение вышестоящей задачи) добавила следующий код
    Код (Text):
    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 для поиска в нем по измененному значению, иначе будет искать по значению поля, которое было до изменения.

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

    TIA :-)
    Lotus team

    Регистрация:
    15 май 2009
    Сообщения:
    790
    Симпатии:
    0
    Советы
    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
     
  20. Omh

    Omh Lotus team
    Lotus team

    Регистрация:
    4 июл 2007
    Сообщения:
    2.210
    Симпатии:
    0
    Ну как бэ вдогонку:
    1. Лучше сделать переменную дока и в него присвоить Source.Document, что бы не дёргать несколько раз Source
    2. db сдесь можно получить из doc.ParentDatabase, что бы зря не декларить session
    3. А где переменные задекларены или без Option Declare пишешь? :D
     
Загрузка...

Поделиться этой страницей