AXForum  
Вернуться   AXForum > Microsoft Dynamics NAV > NAV: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.12.2010, 16:03   #1  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Профессионалы, подскажите есть в Навижн какая-нить функция, с помощью которой можно узнать была ли запись модифицирована, и если жа, то какие именно поля подверглись корректировке?

Ситуация: есть таблица Customer. К ней форма F50191 (Карточка клиента). В таблице (соотвественно и в форме тоже) есть два поля: Information и Note (текстовые).
Задача в следующем: нужно в триггере OnModifyRecord() устроить проверку: если у юзера в его настройках Responsibility Center не совпадает с аналогичным полем в карточке клиента, то этому юзеру можно менять только указанные два поля (Information и Note). При попытке изменить другие поля выдается сообщение об ошибке.
На настоящий момент такой юзер вообще не может ничего менять в карточке.
Как решить поставленную задачу "малой кровью"?
Старый 15.12.2010, 17:19   #2  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
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  
Fordewind is offline
Fordewind
Участник
 
1,134 / 10 (3) +
Регистрация: 01.12.2005
Цитата:
Сообщение от 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); что вам как раз и нужно.
Есть такая штука CurrentFieldNo. Она возвращает номер поля в котором стоит юзер. И ею можно заменить ChangeLog в данном случае
Старый 15.12.2010, 18:53   #4  
Sancho is offline
Sancho
Administrator
Аватар для Sancho
Лучший по профессии 2017
Лучший по профессии 2009
 
1,294 / 221 (10) ++++++
Регистрация: 11.01.2006
Цитата:
Сообщение от Kadawrik Посмотреть сообщение
...
На настоящий момент такой юзер вообще не может ничего менять в карточке.
сначала надо будет отгрызть это, дебаггер вам в помощь
Старый 16.12.2010, 00:46   #5  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
Цитата:
Сообщение от Fordewind Посмотреть сообщение
Есть такая штука CurrentFieldNo. Она возвращает номер поля в котором стоит юзер. И ею можно заменить ChangeLog в данном случае
CurrfiеldNo хорошая вещь, но в OnModify()-триггере таблицы всегда равен 0.
Чтобы ловить, в каком поле user имеет право изменения делать, а в каком нет и т.д, надо прописывать программный код в каждом поле таблицы в OnValidate()-триггере (по крайней мере вызов соответствующей функции). Представьте, что этот функционал вам нужен и в других таблицах, потом весь этот код надо при update не забывать и MERGE'вать. У меня была похожая задача и по этой причине я прописал код в одном единственном месте- в CU 423: и прекрасно работает, и минимум изменений в стандартном функционале.
Старый 16.12.2010, 15:17   #6  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от AlexB Посмотреть сообщение
Весь фокус в том, что ChangeLog-функционал реагирует/срабатывает только на изменения, вносимые user'ом руками и на изменения из программного кода не реагирует,
( типа customer.MODIFY(TRUE); что вам как раз и нужно.
Сделала как Вы сказали. В CU 423 процедуру изменила след. образом: (мои "нововведения" выделены синим)

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:29   #7  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от Sancho Посмотреть сообщение
сначала надо будет отгрызть это, дебаггер вам в помощь
Это "отгрызть" не проблема , т.к. код предельно прост:


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 (Карточка клиента)
Старый 16.12.2010, 15:39   #8  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Да! Забыла написать! Т.к. поменяла CU 423, то сообщение об ошибке в триггере OnModifyRecord (формы 50191) пришлось закомментарить.
Старый 16.12.2010, 15:43   #9  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от Kadawrik Посмотреть сообщение
[Теперь при попытке покинуть измененную карточку клиента выдается сообщение об ошибке. НО! тем не менее изменения сохраняются и если мы еще раз выйдем из карточки клиента, то уже система не "мявкает",т.к. по ее логике уже ничего и не поменялось. В рез-те имеем: измененное поле в карточке клиента, которое на самом деле менять было нельзя. ;-/
Что делать?
Переносить-такии код в др.место или ...? Какие есть варианты? Где я опять накосячила?
Может тогда имеет смысл оставить CU 423 по-старому, а всю процедуру проверки перенести в триггер OnModify() Таблицы 18? (т.е. прописываем код для проверки только в одном месте и OnValidate по каждому полю трогать не будем)
Старый 16.12.2010, 20:30   #10  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
Цитата:
Сообщение от 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   #11  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от AlexB Посмотреть сообщение
1. Косяк в коде один есть:
надо писать не

xFldRef := xRecRef.FIELDINDEX(65); //65 - Index vom Feld "Resposibility Center"

а

xFldRef := xRecRef.FIELD(65); //65 - Index vom Feld "Resposibility Center"
У меня с FieldIndex(65) работает. 65 - это действительно индекс поля в таблице, а не номер его.

Цитата:
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.
Спасибо за подсказку. Я это "правило" уже эмпирическим путем выяснила, когда сегодня с дебагером отлаживала и не могла понять, почему CU сохраняю, а ошибка старая лезет и дебагер старый текст показывает
Теперь буду знать, что это не мое предположение, а действительно так и есть
Старый 17.12.2010, 13:14   #12  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
Цитата:
Сообщение от Kadawrik Посмотреть сообщение
Вот это самое MODIFY и портит всю малину. Если меняется какое-то поле из приведенного выше IF'а, тогда сообщение об ошибке появляется, но новое значение тем не менее сохраняется. Если меняю любое другое поле (кроме Information или Note), тогда появляется сообщение об ошибке и введенное новое значение сбрасывается (т.е. работает так, как Вы и описывали)
В моей таблице 18 в ОnModify() тот же код что и у вас с тем же MODIFY. Меняю значение в Name на новое: после ошибки в Name стоит опять старое значение.
Посмитрите, может у вас в OnModifyRecord() в форме что-нибудь прописано, может где-нибудь у вас ещё и COMMIT затесался?
Старый 19.12.2010, 15:47   #13  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от AlexB Посмотреть сообщение
В моей таблице 18 в ОnModify() тот же код что и у вас с тем же MODIFY. Меняю значение в Name на новое: после ошибки в Name стоит опять старое значение.
Посмитрите, может у вас в OnModifyRecord() в форме что-нибудь прописано, может где-нибудь у вас ещё и COMMIT затесался?
Нашла COMMIT!
В таблице 18 в модуле:

ValidateShortcutDimCode(FieldNumber : Integer;VAR ShortcutDimCode : Code[20])
DimMgt.ValidateDimValueCode(FieldNumber,ShortcutDimCode);
DimMgt.SaveDefaultDim(DATABASE::Customer,"No.",FieldNumber,ShortcutDimCode);
//Logging of field modifications: commit instead of modify (modify purges parts of log)
//MODIFY;
COMMIT;


Комментарий и исправление сделано программистом, работавшим до меня (должна сказать, что в фирме, где я работаю, вообще очень много изменений в Навижн в отличие от типовой конфигурации)
В данном случае мне не совсем понятен смысл исправления, сделанного программистом ;-/
С какой целью!? (где тут смайлик, пожимающий плечами?
Старый 19.12.2010, 16:02   #14  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Вот триггер OnModifyRecord() формы 50191 (через которую мы редактируем карточку клиента):


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!');


Последняя строка с ERROR закомментарена мной в связи с изменениями в CU 423.
Старый 20.12.2010, 12:01   #15  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
Моё личное мнение:
программист, заменивший в функции ValidateShortcutDimCode() MODIFY на COMMIT, просто ловил какую-то ошибку связанную с dimensions и забыл просто-напросто вернуть программный код в первоначальное состояние. В стандартной Т.18 имеется COMMIT в одном единственном месте, в функции ShоwContact(), но там он нужен и с вашей проблемой это никак не сваязано.
Попробуйте убрать COMMIT и протестировать (не забыть открыть навижен заново).

Код из OnModifyRecord() уберите полностью, там уж действительно ничего прописывать не надо.
Старый 20.12.2010, 15:48   #16  
Kadawrik is offline
Kadawrik
Участник
 
279 / 11 (1) +
Регистрация: 04.11.2010
Цитата:
Сообщение от AlexB Посмотреть сообщение
Моё личное мнение:
программист, заменивший в функции ValidateShortcutDimCode() MODIFY на COMMIT, просто ловил какую-то ошибку связанную с dimensions и забыл просто-напросто вернуть программный код в первоначальное состояние. В стандартной Т.18 имеется COMMIT в одном единственном месте, в функции ShоwContact(), но там он нужен и с вашей проблемой это никак не сваязано.
Не похоже, что он что-то тестировал, т.к. это изменение описано в триггере Documentation() и ему приписана новая версия. К тому же шеф сказал, чтобы я лучше исправления в T18.OnModify внесла, и не трогала CU и COMMIT.
Я так и сделала. Теперь всё работает даже с коммит

Цитата:
Попробуйте убрать COMMIT и протестировать (не забыть открыть навижен заново).
Пробовала, работает. Но ...см. выше

Цитата:
Код из OnModifyRecord() уберите полностью, там уж действительно ничего прописывать не надо.
Код уже убрала. Он там сейчас действительно ни к чему.

Спасибо Вам огромное за помощь и поддержку
Старый 23.12.2010, 11:41   #17  
Lates is offline
Lates
Участник
 
207 / 10 (1) +
Регистрация: 08.02.2007
Почему-то вспомнился DocFlowNav.
Там такие вещи (и много других) очень удобно настраиваются.
Почти без программирования.
Не подумайте, что реклама.
Просто положительные воспоминания
Старый 06.01.2011, 00:49   #18  
alexb_imported is offline
alexb_imported
Участник
 
256 / 12 (1) ++
Регистрация: 25.08.2006
Цитата:
Сообщение от Lates Посмотреть сообщение
Почему-то вспомнился DocFlowNav.
Там такие вещи (и много других) очень удобно настраиваются.
Почти без программирования.
Приведённый мной здесь как вариант реагирования на изменения в опр. таблице+опр. поле в CU 412 - тоже минимум программирования.
Не видел DocFlowNav, но предположу, что сам программный код для реагирования на изменения в опр. таблице+опр. поле там не короче.
Само собой, когда требуется реагировать на изменения во многих таблицах/полях можно настроить требуемые таблицы+поля в отведённых для этого парочке таблиц+форм
(что я в моём проекте и сделал, добавив такие вещи: как реагировать (MESSAGE/ERROR), реагирование при определённом условии (определённый FieldValue / определённый Filter) и.т.д).
Но, повторюсь, сам программный код отслеживания в DocFlowNav по объёму вряд ли будет меньше.
Старый 06.01.2011, 15:38   #19  
Sancho is offline
Sancho
Administrator
Аватар для Sancho
Лучший по профессии 2017
Лучший по профессии 2009
 
1,294 / 221 (10) ++++++
Регистрация: 11.01.2006
да, в DocFlowNAV именно так.
проверяются два рефа (старый и новый), а в настройках сказано какое поле контролировать, при каких условиях, ругаться или предупреждать.
 


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 14:31.