Механизм использования плагинов при всех своих положительных сторонах имеет существенный недостаток - возможность совершения ошибок, при случайном запуске не в том окружении для которого он предназначен.
Чтобы избежать таких ситуаций следует делать проверки в самом начале процедуры. ...
ARM |
PATH |
NAME |
00 |
|
АРМ Главного бухгалтера |
01 |
BANK\ |
Расчетные и валютные счета |
02 |
CASH\ |
Касса.Подотчетные лица |
03 |
SCLAD\ |
Товары.Готовая продукция |
05 |
REAL\ |
Управление продажами |
06 |
OC\ |
Учет основных средств и НМА |
09 |
ZAPAS\ |
Учет материалов и МБП |
MG |
SHOP\ |
Магазин |
14 |
SALARY\ |
Учет заработной платы |
TZ |
TZ\ |
Торговый зал |
TV |
TOVAR\ |
Учет закупок |
PD |
PODATOK\ |
Налоговая накладная |
EX |
EXCHANGE\ |
Модуль обмена данными |
CN |
CONTRACT\ |
Расчеты.Договоры. |
TX |
TAXI\ |
Экспорт налоговых форм |
IP |
PLAN\ |
Планирование закупок |
DS |
MOBILE\ |
Мобильная торговля |
MR |
MENU_R\ |
Питание |
Пример использования:
//Если запуск разрешен только в модуле "Зарплата"
IF !GLOBALTASK="14"
ALERT("Ошибка! Вызов плагина должен осуществляться из модуля 'ЗАРПЛАТА'!")
RETURN
ENDIF
//Если запуск разрешен только в модулях "Товары" и "Учет материалов"
IF !GLOBALTASK $ "0309"
ALERT("Ошибка! .....только из модуля 'ТОВАРЫ' или "УЧЕТ МАТЕРИАЛОВ"!")
RETURN
ENDIF
На этом необходимость в проверках не закончилась. В модулях имеется несколько реестров, из которых возможен вызов плагина. Сложно предугадать, что произойдет если любознательный пользователь или новый администратор БД начнет проверять на запуск все найденные hrb-файлы в реестре документов.
Безопасность превыше всего! Поэтому, помимо контроля вызова плагина "по модулю", следует делать контроль по реестру и событию.
Все плагины хранятся в одной таблице feval.dbf, поле treestr определяет реестр, к которому приписана спецфункция пользователя.
Узнать значение feval->treestr нетрудно. Для этого в режиме спецфункций следует вызвать режим доступа к отладочной информации по ALT-INS.
Из условия скопа (фильтра по значению индекса) определяем, что при вызове плагина из реестра лицевых счетов следует выполнять проверку условия:
IF !UPPER(feval->treestr)="14CARDSPRI"
RETURN
ENDIF
Следует учесть, что имеет место быть следующее:
//feval->treestr="14CARDSPRI " длина - 20 символов
UPPER(feval->treestr)="14CARDSPRI" // .T.
UPPER(feval->treestr)=="14CARDSPRI" // .F.
UPPER(ALLTRIM(feval->treestr))=="14CARDSPRI" // .T.
UPPER(ALLTRIM(feval->treestr))="14CARDSPRI" // .T.
а также:
//exact = .f.
UPPER(feval->treestr)="" // .T.
UPPER(feval->treestr)=="" // .F.
UPPER(ALLTRIM(feval->treestr))=="" // .F.
UPPER(ALLTRIM(feval->treestr))="" // .T.
//exact = .t.
UPPER(feval->treestr)="" // .F.
UPPER(feval->treestr)=="" // .F.
UPPER(ALLTRIM(feval->treestr))=="" // .F.
UPPER(ALLTRIM(feval->treestr))="" // .F.
При сравнении строк желательно придерживаться следующих правил:
- не использовать оператор = , применять == (совершенно равно)
- не использовать <>, применять != (неравно) либо ! с ==
Переписываем условия:
//
IF !GLOBALTASK=="14" // либо GLOBALTASK!="14"
ALERT("Ошибка! Вызов плагина должен осуществляться из модуля 'ЗАРПЛАТА'!")
RETURN
ENDIF
//
IF !UPPER(ALLTRIM(feval->treestr))=="14CARDSPRI"
RETURN
ENDIF
Но и это еще не все. В реестрах присутствует параметр, устанавливающий событие, по которому происходит запуск. Значение параметра хранится в символьном поле CALL единичной длины.
В ходе экспериментов для реестра лицевых счетов установлены условия:
По требованию |
feval->call==" " |
позиционирование по Ctrl-F7 |
feval->call=="6" |
позиционирование по Shift-F7 |
feval->call=="7" |
вход в реестр |
feval->call=="8" |
И вот как будет выглядеть код из предыдущего примера.
FUNCTION select2006()
// Проверка по модулю
IF !GLOBALTASK=="14" // либо GLOBALTASK!="14"
ALERT("Ошибка вызова по модулю! Вызов плагина должен осуществляться из модуля 'ЗАРПЛАТА'!")
RETURN NIL
ENDIF
// Проверка по реестру
IF !UPPER(ALLTRIM(feval->treestr))=="14CARDSPRI"
ALERT("Ошибка! Вызов не из реестра лицевых счетов!")
RETURN NIL
// Проверка по событию
ELSEIF !feval->Call==" "
ALERT("Ошибка! Вызов не по требованию!")
RETURN NIL
ENDIF
// теперь собственно сам код
// сохраняем окружение
DBPUSH()
//открываем базу, на случай вызова не из реестра лицевых счетов
IF !(NETUSE("u_cardspri",LOADPATH()+'salary\cardspri.dbf'))
//Выход на случай ошибки
RETURN NIL
ENDIF
//блокируем таблицу
u_cardspri->(FLock())
// т.к. replace обрабатывает все записи таблицы по условию, цикл не нуже
// сбрасываем все отметки
Replace check WITH .F. FOR .T.
// устанавливаем отметки по условию
Replace check WITH .T. ;
FOR (dismdate>CTOD('01/01/2006') .AND. dismdate<=CTOD('31/12/2006'));
.OR. dismdate=CTOD('')
// снимаем блокировку
u_cardspri->(DBUNLOCK())
// закрываем таблицу
u_cardspri->(DBCLOSEAREA())
// возвращаемся в прежнюю область
DBPOP()
RETURN NIL
Замечательно, но еще не все.
Осталось найти ответы на вопросы: Как передавать параметры? Как контроллировать работу плагина? С каким результатом завершилась процедура? Сколько времени, сколько записей ....?
Об этом далее...