|
15.12.2010, 16:03 | #1 |
Участник
|
Профессионалы, подскажите есть в Навижн какая-нить функция, с помощью которой можно узнать была ли запись модифицирована, и если жа, то какие именно поля подверглись корректировке?
Ситуация: есть таблица Customer. К ней форма F50191 (Карточка клиента). В таблице (соотвественно и в форме тоже) есть два поля: Information и Note (текстовые). Задача в следующем: нужно в триггере OnModifyRecord() устроить проверку: если у юзера в его настройках Responsibility Center не совпадает с аналогичным полем в карточке клиента, то этому юзеру можно менять только указанные два поля (Information и Note). При попытке изменить другие поля выдается сообщение об ошибке. На настоящий момент такой юзер вообще не может ничего менять в карточке. Как решить поставленную задачу "малой кровью"? |
|
15.12.2010, 17:19 | #2 |
Участник
|
1. Надо включить ChangeLog для таблицы 18 для всех полей, или по крайней мере для всех полей, которые user может изменить в карточке клиента.
(Administration > Application Setup > General > Change Log) 2. В кодеюните 423 Change Log Management прописываете программный код: если таблица=18 то: 2.1 берёте customer'a (можно взять Customer."No." из RecRef.RECORDID) и смотрите его Respons.Center 2.2 берёте USER'а и смотрите его Respons.Center 2.3 если Respons.Center user'a отличается от Respons.Center customer'a то проверяете, какое поле было изменено ==> например в функции InsertLogEntry() (в том же CU 423 Change Log Management ) передаётся параметер FldRef, ======> Если FldRef.NUMBER <> номер поля Information и FldRef.NUMBER <> номер поля Note то выдаём требуемый ERROR(). Весь фокус в том, что ChangeLog-функционал реагирует/срабатывает только на изменения, вносимые user'ом руками и на изменения из программного кода не реагирует, ( типа customer.MODIFY(TRUE); что вам как раз и нужно. |
|
15.12.2010, 18:14 | #3 |
Участник
|
Цитата:
Сообщение от AlexB
1. Надо включить ChangeLog для таблицы 18 для всех полей, или по крайней мере для всех полей, которые user может изменить в карточке клиента.
(Administration > Application Setup > General > Change Log) 2. В кодеюните 423 Change Log Management прописываете программный код: если таблица=18 то: 2.1 берёте customer'a (можно взять Customer."No." из RecRef.RECORDID) и смотрите его Respons.Center 2.2 берёте USER'а и смотрите его Respons.Center 2.3 если Respons.Center user'a отличается от Respons.Center customer'a то проверяете, какое поле было изменено ==> например в функции InsertLogEntry() (в том же CU 423 Change Log Management ) передаётся параметер FldRef, ======> Если FldRef.NUMBER <> номер поля Information и FldRef.NUMBER <> номер поля Note то выдаём требуемый ERROR(). Весь фокус в том, что ChangeLog-функционал реагирует/срабатывает только на изменения, вносимые user'ом руками и на изменения из программного кода не реагирует, ( типа customer.MODIFY(TRUE); что вам как раз и нужно. |
|
16.12.2010, 00:46 | #4 |
Участник
|
Цитата:
Чтобы ловить, в каком поле user имеет право изменения делать, а в каком нет и т.д, надо прописывать программный код в каждом поле таблицы в OnValidate()-триггере (по крайней мере вызов соответствующей функции). Представьте, что этот функционал вам нужен и в других таблицах, потом весь этот код надо при update не забывать и MERGE'вать. У меня была похожая задача и по этой причине я прописал код в одном единственном месте- в CU 423: и прекрасно работает, и минимум изменений в стандартном функционале. |
|
16.12.2010, 15:39 | #5 |
Участник
|
Да! Забыла написать! Т.к. поменяла CU 423, то сообщение об ошибке в триггере OnModifyRecord (формы 50191) пришлось закомментарить.
|
|
16.12.2010, 15:17 | #6 |
Участник
|
Цитата:
LogModification(VAR RecRef : RecordRef;VAR xRecRef : RecordRef) IF NOT IsLogActive(RecRef.NUMBER,0,1) THEN EXIT; IF RecRef.NUMBER = 18 THEN BEGIN // Machen das nur für Tabelle 18 - Customer BenutzerEinrRec.GET(USERID); xFldRef := xRecRef.FIELDINDEX(65); //65 - Index vom Feld "Resposibility Center" CustRespCtr := xFldRef.VALUE; END; FOR i := 1 TO RecRef.FIELDCOUNT DO BEGIN FldRef := RecRef.FIELDINDEX(i); xFldRef := xRecRef.FIELDINDEX(i); IF IsNormalField(RecRef.NUMBER,FldRef.NUMBER) THEN IF FORMAT(FldRef.VALUE) <> FORMAT(xFldRef.VALUE) THEN //SSG.JK. BEGIN IF RecRef.NUMBER = 18 THEN BEGIN IF (BenutzerEinrRec."Sales Resp. Ctr. Filter" <> '') THEN IF (FldRef.NAME <> 'Information') AND (FldRef.NAME <> 'Note') AND (FldRef.NAME <> 'Last Date Modified') THEN IF (STRPOS(BenutzerEinrRec."Sales Resp. Ctr. Filter",COPYSTR(CustRespCtr,1,4)) = 0) THEN BEGIN ERROR('Änderung von %1 nicht möglich: Dieser Debitor ist einer anderen Zuständigkeitseinheit zugeordnet!',FldRef.NAME); EXIT; END; END; //SSG.JK. IF IsLogActive(RecRef.NUMBER,FldRef.NUMBER,1) THEN InsertLogEntry(FldRef,xFldRef,RecRef,1); END; Теперь при попытке покинуть измененную карточку клиента выдается сообщение об ошибке. НО! тем не менее изменения сохраняются и если мы еще раз выйдем из карточки клиента, то уже система не "мявкает",т.к. по ее логике уже ничего и не поменялось. В рез-те имеем: измененное поле в карточке клиента, которое на самом деле менять было нельзя. ;-/ Что делать? Переносить-такии код в др.место или ...? Какие есть варианты? Где я опять накосячила? |
|
16.12.2010, 15:43 | #7 |
Участник
|
Цитата:
Сообщение от Kadawrik
[Теперь при попытке покинуть измененную карточку клиента выдается сообщение об ошибке. НО! тем не менее изменения сохраняются и если мы еще раз выйдем из карточки клиента, то уже система не "мявкает",т.к. по ее логике уже ничего и не поменялось. В рез-те имеем: измененное поле в карточке клиента, которое на самом деле менять было нельзя. ;-/
Что делать? Переносить-такии код в др.место или ...? Какие есть варианты? Где я опять накосячила? |
|
16.12.2010, 20:30 | #8 |
Участник
|
Цитата:
Сообщение от Kadawrik
Теперь при попытке покинуть измененную карточку клиента выдается сообщение об ошибке. НО! тем не менее изменения сохраняются и если мы еще раз выйдем из карточки клиента, то уже система не "мявкает",т.к. по ее логике уже ничего и не поменялось. В рез-те имеем: измененное поле в карточке клиента, которое на самом деле менять было нельзя. ;-/
Что делать? Переносить-такии код в др.место или ...? Какие есть варианты? Где я опять накосячила? 1. Косяк в коде один есть: надо писать не xFldRef := xRecRef.FIELDINDEX(65); //65 - Index vom Feld "Resposibility Center" а xFldRef := xRecRef.FIELD(65); //65 - Index vom Feld "Resposibility Center" 2. Я на вскидку вставил в моей БД в CU 423 ваш код (с корректировкой в П 1.): После подтверждения ошибки система возвращает в поле прежнее значение (до изменения), как и должно быть после ERROR, всё работает. Ошибка вылетает после изменения в поле при попытке перейти к другому customer или закрыть карточку. Важное примечание: после любых изменений в коде (т. е. в программном коде, имеющем отношение к CU 423): ---- в открывайте навижен сновa, чтобы CU 423 заметил эти изменения: CU423 это SingleInstanece-Codeunit. |
|
16.12.2010, 23:23 | #9 |
Участник
|
Цитата:
Цитата:
2. Я на вскидку вставил в моей БД в CU 423 ваш код (с корректировкой в П 1.):
После подтверждения ошибки система возвращает в поле прежнее значение (до изменения), как и должно быть после ERROR, всё работает. Ошибка вылетает после изменения в поле при попытке перейти к другому customer или закрыть карточку. Собака порылась в коде триггера OnModify() таблицы 18: На домашнем компе Навижн нет, потому по памяти напишу что там примерно было: OnModify() IF Name <> xRec.Name OR Address <> xRec.Address OR Contakt <> xRec.Contakt и т.д. ...перечислины куча полей с контактными данными клиента THEN BEGIN MODIFY; вызывается процедура, которая записывает контактные данные в какую-то доп.таблицу Вот это самое MODIFY и портит всю малину. Если меняется какое-то поле из приведенного выше IF'а, тогда сообщение об ошибке появляется, но новое значение тем не менее сохраняется. Если меняю любое другое поле (кроме Information или Note), тогда появляется сообщение об ошибке и введенное новое значение сбрасывается (т.е. работает так, как Вы и описывали) Цитата:
Важное примечание: после любых изменений в коде (т. е. в программном коде, имеющем отношение к CU 423):
---- в открывайте навижен сновa, чтобы CU 423 заметил эти изменения: CU423 это SingleInstanece-Codeunit. Теперь буду знать, что это не мое предположение, а действительно так и есть |
|
15.12.2010, 18:53 | #10 |
Administrator
|
|
|
16.12.2010, 15:29 | #11 |
Участник
|
Это "отгрызть" не проблема , т.к. код предельно прост:
Form - OnModifyRecord() : Boolean BenutzerEinrRec.GET(USERID); IF (BenutzerEinrRec."Sales Resp. Ctr. Filter" <> '') THEN IF (STRPOS(BenutzerEinrRec."Sales Resp. Ctr. Filter", COPYSTR("Responsibility Center",1,4)) = 0) OR (Rec."Responsibility Center" <> xRec."Responsibility Center") THEN ERROR('Änderung nicht möglich: Dieser Debitor ist einer anderen Zuständigkeitseinheit zugeordnet!'); Это - триггер OnModifyRecord формы 50191 (Карточка клиента) |
|
06.01.2011, 15:38 | #12 |
Administrator
|
да, в DocFlowNAV именно так.
проверяются два рефа (старый и новый), а в настройках сказано какое поле контролировать, при каких условиях, ругаться или предупреждать. |
|