|
Microsoft Dynamics NAV (Navision) Application Server - одна из компонент технологической платформы Microsoft Dynamics NAV (Navision). Application Server позволяет внешним клиентам\приложениям получить доступ к бизнес-логике Microsoft Dynamics NAV (Navision). Application Server может быть запущен как Служба (Service) windows. Существуют варианты Application Server как для “родного” (native) формата базы данных так и для MS SQL формата. Application Server широко применяется в е-решениях платформы Microsoft Dynamics NAV (Navision) (Commerce Portal – web портал, Commerce Gateway – шлюз обмена данными на основе Biztalk Server), а так задействуется при взаимодействие со складскими радио-терминалами (модуль ADCS – автоматизированная система сбора данных). Программист может использовать Application Server в самых разных целях. Очень полезно посмотреть, например, реализацию простейшего webservice: http://www.mibuso.com/dlinfo.asp?FileID=353 (взаимодействие с Application Server происходит путем обмена сообщениями XML-формата, передача сообщений идет через MSMQ - Microsoft Message Queue). Я же постараюсь представить пример использования Microsoft Dynamics NAV (Navision) Application Server в качестве службы отчетов. Иначе говоря, ежедневно в заданный срок, без участия пользователя, формируем отчет и сохраняем его в виде .html файла. Здесь стоит отметить, что возможность запуска отчетов через Application Server появилась уже в версии Microsoft Dynamics NAV (Navision) 3.60. Отчеты в Microsoft Dynamics NAV (Navision) могут использоваться не только для выборки данных, но и для их коррекции. Так же через Application Server можно запускать на выполнение программные блоки (codeunit), что позволит скажем реализовать отложенный учет документов и т.д. Стоит сказать, что Application Server способен оперировать только кодом не вызывающим GUI окна, т.е. окна запроса ввода от пользователя, сообщения о ходе выполнения процесса. Это надо предусмотреть в коде запускаемых отчетов или codeunit-ов путем ввода соответствующих логических ветвлений. Итак, у нас есть: - Product CD c Microsoft Navision 3.70 A (именно в таком виде русская 3.70 появилась на рынке в мае 2004)
- Продвинутая лицензия с возможностями разработки.
Для чистоты эксперимента упомяну, что я все проделывал на: - Windows XP SP1 (русская) + доступные обновления
- Имя компьютера FINN-MOB
- Сеть к компьютеру не подключена (потребуется поставить Microsoft Loopback Adapter (Адаптер Microsoft замыкания на себя))
- Память 128 mb (лучше конечно иметь побольше памяти)
Инсталляция КлиентаЗапускаем Product CD, кстати на этом диске не только инсталлятор, но и куча полезных вещей: документация (правда в основном только по инсталляции, администрированию, интеграции, частично по программированию…), дополнительные интерфейсы, devkit и т.п. Инсталлируем клиента Microsoft Navision. Примечание: документации по инсталляции всех описываемых компонент присутствует на диске. Далее идут несколько screenshot-ов процесса инсталляции клиента. 



Клиент ставиться сразу и для коннекта к базе данных native формата и к базе данных MS SQL (на самом деле это два разных запускаемых файла fin.exe и finsql.exe). Если говорить о бизнес-логике, то она общая для обоих форматов (хотя очень редко в коде кое-где попадаются ветвления по типу БД) . Код представляющий собой бизнес-логику, т.е. codeuint-ы, а так же мета-данные и т.п. хранятся непосредственно в БД, в случае MS SQL это BLOB поля. Примечание: в MS SQL таблицы Navision – это обычные таблицы MS SQL, т.е. доступны для внешних запросов. В принципе, установив только клиента, уже можно работать в однопользовательском режиме с базой native формата или коннектиться к SQL Server. Инсталлируем Navision Database Server За основу примера я решил взять native формат БД. Мне потребуется два соединения: одно соединение займет NAS, на другом я буду иметь возможность запускать обычного клиента. Т.к. каждое дополнительное соединение в Microsoft Navision стоит денег хочется отметить, что к счастью один NAS и одно соединение для него бесплатно (обычного клиента по этому “халявному” соединению не пустит) входит в базовую конфигурацию системы. К слову, хочется заметить о такой засаде: если у нас в рамках БД несколько фирм, а фирма с точки зрения Microsoft Navision практически полностью автономная единица со своим набором таблиц и т.п., то надо четко осознавать что один NAS работает после запуска только для одной фирмы – той фирмы что указана в start-up параметрах. В такой ситуации может потребоваться докупать дополнительные NAS-ы. Далее инсталлируем сервер БД для native формата (сервер navision для windows). Опять-таки несколько screenshot-ов процесса инсталляции сервера. 







На предшествующем слайде выбираем файл со своей продвинутой лицензией. 
Клиент navision и сервер native формата (или сервер navision) установлены. Далее требуется установить собственно Navision Application Server (NAS). Инсталлируем Navision Application Server Ниже идут screenshot-ы процесса инсталляции NAS. 




По предшествующему слайду видно что NAS сразу ставить для обоих форматов БД (на самом деле это два разных запускаемых файла nas.exe и nassql.exe). В процессии инсталляции NAS, инсталлируется так же и MMC консоль (Microsoft Management Console), а-ля Enterprise Manager у MS SQL. Через эту консоль (Navision Application Server Manager) удобно администрить NAS, сервер Navision и т.п. Настраиваем консоль администратора Далее наполним Navision Application Server Manager содержанием. Ниже идут соответствующие screenshot-ы. 






Ниже подключим к этой же консоли Snap-In (оснастку) сервера Navision (Snap-In был проинсталлирован при установке сервера Navision). 





Подключим для удобства к этой же консоли Просмотр cобытий (Event Viewer) и Службы (Services). 

Консоль приобретет следующий вид. 
Мы видим интересующие нас службы числом три: Microsoft Business Solutions – Navision Application Server FINN-MOB-CLASSIC, Microsoft Business Solutions – Navision Application Server FINN-MOB-SQL, Microsoft Business Solutions – Navision Database Server FINN-MOB. Эти службы по умолчанию имеют Тип запуска Авто и запускаются под локальной системной учетной записью. Для удобства демонстрации я предлагаю изменить Тип запуска на Вручную (у всех трех служб). 


Перейдем в ветку Navision Database Server Manager и запустим сервер FINN-MOB по кнопке Start Service. 
Просмотрим, что за сообщения выбросила наша Служба (Service) в Просмотр событий (Event Viewer). 

Предупреждение происходит в виду отсутствии публикации нашего сервера в Active Directory. Игнорируем его. Далее перейдем в ветку Navision Application Server Manager и попытаемся запустить сервер FINN-MOB-CLASSIC по кнопке Start Service…. Это сделать не удается. 
Просмотрим, что за сообщения выбросила наша Служба (Service) в Просмотр событий (Event Viewer). 

Предупреждение говорит о том, что отсутствует некий параметр для Codeunit 1 Trigger 99. И ведь верно Start-Up параметр при запуске Application Server был пустой и как следствие стартовать Application Server не удалось, см. следующую ошибку. 
Остановим Службу Navision Database Server FINN-MOB что бы зря память не отъедала. Этап инсталляций закончен. Создаем и корректируем нужные объекты Navision Приступаем собственно к работе с Microsoft Dynamics NAV (Navision). Сервер Microsoft Dynamics NAV (Navision) у нас остановлен, но ничего страшного запустим систему в однопользовательском режиме. Предлагаю все работы по написанию кода провести в однопользовательском режиме, а потом уже запускать и Navision Database Server и Navision Application Server. 
Ниже, на всякий случай, привожу параметры коннекта, пароль у ADMIN пустой. Примечание: по умолчанию база ставится в папку C:\Program Files\Microsoft Business Solutions-Navision\Client. 

Вот он Microsoft Dynamics NAV (Navision) 3.70 во всей красе. Не буду подробно останавливать на различных типах объектов Microsoft Dynamics NAV (Navision) и путей их создания, все это очень четко и кратко расписано во флэш: http://www.navision.ru/files/Flash/navision/intro.htm. Полезный краткий справочник по функциям можно увидеть http://www.mibuso.com/dlinfo.asp?FileID=288. Для начала приведу диаграмму запуска Application Server: 1. Specify the domain account to run the service 2. servername (connect to server) and database (only for NASSQL) 3. company (connect to company) 4. Windows login (account/password) 5. startupparameter (trigger 99, codeunit 1) 6. application codeunit (single instance codeunit) Из диаграммы видно, что точкой входа для обращения к бизнес-логике системы через Application Server является codeunit 1 и запускаемый, исходя из значения startupparameter, application codeunit (single instance). Свойство single instance это свойство codeunit и его присвоение приводит к своего рода глобальности(единственности) экземпляра объекта в разрезе фирмы. Мы создадим три новых объекта и откорректируем два имеющихся. Чуть подробнее. Создадим Codeunit 90000 Sample Dispatcher – это будет у нас тот самый application codeunit (single instance). Для выполнения непосредственно кода запуска отчета и прочих сопутствующих вещей создадим Codeunit 90001 Sample Run Report. Так же нам потребуется создать таблицу для хранения списка задач (расписание запуска), это Таблица 90000 Sample Task. Мы откорректируем Codeunit 1 (вставим в него обработку нового параметра запуска). Ну и, наконец, тот отчет, на запуске которого мы будем тренироваться, так же потребует привнесения изменений, это Отчет 105 Customer - Summary Aging (Клиент - Сумм. Сроки Задолж.). Перечень создаваемых и корректируемых объектов представлен на screenshot-е ниже: 
Первым шагом создаем таблицу 90000 Sample Task. См. следующий screenshot. 
Поле Тип Задачи (Task Type) будет иметь для примера два значения R00105_V1 и R00105_V2 (т.е. задача по запуску отчета 105 с двумя вариантами параметров). Поле Время Запуска (Run Time) это время ежедневного запуска задания. Примечание: для упрощения картины мира не связываюсь с расписанием запуска в разрезе дней недели. После запуска задания заполняются поля Последний Запуск (Last Run), Следующий Запуск (Next Run), Последний Запуск Статус (Last Run Status), при чем Статус может иметь значения None,OK,ERR (OK-задание завершилось успехов, ERR-произошла ошибка, None-первоначальное значение поля). Кроме того, для отслеживания истории запусков мы будем после каждого запуска задания кидаться сообщениями. Эти сообщения можно будет просматривать через Просмотр событий (Event Viewer). Пример заполнения таблицы представлен на следующем screenshot-е. 
Поле Next Run будет корректироваться в момент изменения поля Last Run и поля Run Time. Сам код пропишем в триггер OnValidate() соответствующих полей. Вернемся к дизайну таблицы 90000 и войдем в код поля Run Time. 

Четко видно что имеет место триггер Run Time – OnValidate() и триггер Last Run – OnValidate(). Эти триггера будут отрабатывать в момент коррекции(присвоения) значения обычным способом через интерфейс, а также если идем через код при коррекции(присвоении) значения функцией VALIDATE. Приведу код триггеров: Run Time - OnValidate() IF TIME < Rec."Run Time" THEN Rec."Next Run" := CREATEDATETIME(TODAY,Rec."Run Time") ELSE Rec."Next Run" := CREATEDATETIME(TODAY+1,Rec."Run Time");
Last Run - OnValidate() Rec."Next Run" := CREATEDATETIME(DT2DATE(Rec."Last Run")+1,Rec."Run Time"); Вторым шагом подкорректируем Отчет 105 Customer - Summary Aging (Клиент - Сумм. Сроки Задолж.). Как я уже говорил в самом начале Application Server предназначен для запуска объектов, которые не порождают графические окна. Отчет нам надо поправить так, что бы в случае запуска через Application Server он не выводил окно запроса параметров, так же нам потребуется написать функцию SetParam по заданию параметров из кода. Войдем в дизайн отчета 105. 
Стоя в Dataitems-ах на пустой (третьей строке), нажмем F9 и в итоге попадем в код событийных триггеров отчета. См. ниже. 
В триггер OnInitReport() мы вставили код: // SAMPLE > NAS Rep IF NOT GUIALLOWED THEN BEGIN CurrReport.USEREQUESTFORM:=FALSE; END; // SAMPLE < NAS Rep Смысл кода простой если у нас запуск через Application Server, то форму запроса параметров отчета не выводить. Примечание: обратите внимание, что весь новый код в не созданных мною объектах я помечаю метками SAMPLE. Так же создадим функцию SetParam. Идем через Вид\C/AL Globals\Functions. 
У функции два параметра (MyPeriodStartDate, MyPeriodLength). Выходим на окно задания параметров них по кнопке Locals. 
Сам код функции SetParam следующий: // SAMPLE > NAS Rep PeriodStartDate[2] := MyPeriodStartDate; PeriodLength := MyPeriodLength; // SAMPLE < NAS Rep Третьим шагом создаем Codeunit 90001 Sample Run Report. Войдем в дизайн codeunit 90001. 
Посмотрим переменные: 
Так же стоит отметить что весь код сосредоточен у нас в вспомогательной функции RunReport. 
Приведу написанный код: RunReport() RepOk : Boolean SampleTask.RESET; SampleTask.SETCURRENTKEY("Run Time"); SampleTask.SETFILTER("Next Run",'<=%1',CURRENTDATETIME); WITH SampleTask DO BEGIN IF FIND('-') THEN REPEAT IF "Task Type" IN ["Task Type"::R00105_V1,"Task Type"::R00105_V2] THEN BEGIN CASE "Task Type" OF "Task Type"::R00105_V1: BEGIN EVALUATE(MyDateFormula,'<1M>'); Rep00105.SetParam(WORKDATE,MyDateFormula); Customer.RESET; Customer.SETFILTER("Customer Posting Group",'РОССИЯ'); Rep00105.SETTABLEVIEW(Customer); END; "Task Type"::R00105_V2: BEGIN EVALUATE(MyDateFormula,'<1M>'); Rep00105.SetParam(WORKDATE,MyDateFormula); Customer.RESET; Customer.SETFILTER("Customer Posting Group",'ЗАРУБЕЖ'); Rep00105.SETTABLEVIEW(Customer); END; END; // CASE "Task Type" RepOk := Rep00105.SAVEASHTML ('C:\'+FORMAT("Task Type")+' ('+FORMAT("Entry No.")+') '+Rep00105.OBJECTID+' '+ FORMAT(TODAY)+' '+'.html'); MyLastRunDateTime := CURRENTDATETIME; IF RepOk THEN BEGIN IF NOT GUIALLOWED THEN MESSAGE ('OK %1 (%2) %3 %4', SampleTask."Task Type","Entry No.",Rep00105.OBJECTID,MyLastRunDateTime); "Last Run Status" := "Last Run Status"::OK; END ELSE BEGIN IF NOT GUIALLOWED THEN MESSAGE ('ERR %1 (%2) %3 %4', SampleTask."Task Type","Entry No.",Rep00105.OBJECTID,MyLastRunDateTime); "Last Run Status" := "Last Run Status"::ERR; END; VALIDATE("Last Run",MyLastRunDateTime); MODIFY; CLEAR(Rep00105); END; // "Task Type" IN ["Task Type"::R00105_V1,"Task Type"::R00105_V2] UNTIL NEXT = 0; END; // with SampleTask Собственно сам скелет алгоритма может быть представлен так: SampleTask.RESET; SampleTask.SETCURRENTKEY("Run Time"); SampleTask.SETFILTER("Next Run",'<=%1',CURRENTDATETIME); WITH SampleTask DO BEGIN IF FIND('-') THEN REPEAT IF "Task Type" IN ["Task Type"::R00105_V1,"Task Type"::R00105_V2] THEN BEGIN CASE "Task Type" OF // задаем параметры отчета END; // CASE "Task Type"
RepOk := Rep00105.SAVEASHTML(................)
MyLastRunDateTime := CURRENTDATETIME; IF RepOk THEN BEGIN // отправляем сообщение и присваиваем статус OK END ELSE BEGIN // отправляем сообщение и присваиваем статус ERR END; VALIDATE("Last Run",MyLastRunDateTime); MODIFY; CLEAR(Rep00105); END; // "Task Type" IN ["Task Type"::R00105_V1,"Task Type"::R00105_V2] UNTIL NEXT = 0; END; // with SampleTask Код построен, так что мы будем знать только об успехе или не успехе запуска Rep00105.SAVEASHTML, т.е. без детализации ошибки. В то же время в случае ошибки в одном из заданий система не прервется и продолжит обработку последующих задач. Отправляемые сообщение впоследствии можем смотреть через Просмотр событий (Event Viewer). Четвертым шагом создаем Codeunit 90000 Sample Dispatcher. Войдем в дизайн codeunit 90000. Убедимся что проставлено свойство SingleInstance. 


Так же стоит заметить, что в этом codeunit-е мы используем automation переменную Timer c проставленным свойством WithEvents. 

Каждые 30 секунд (временной интервал задается через свойства Timer.Interval) у нашего Timer происходит событие Timer. В обработчике этого события расположен код: Timer::Timer(Milliseconds : Integer) ; CODEUNIT.RUN(CODEUNIT::"Sample Run Report"); Обратите внимание на инициализацию Timer в триггере OnRun(): OnRun() IF ISCLEAR(Timer) THEN CREATE(Timer); Timer.Enabled := FALSE; Timer.Interval := 30*1000; Timer.Enabled := TRUE; MESSAGE(Text000); Text000 это текстовая константа. Эта константа мульти-язычна. См. screenshot. 
Пятым шагом подкорректируем Codeunit 1. Нам требуется добавить в этот codeunit обработку нового параметра запуска. Параметр запуска будет: SAMPLE. Войдем в дизайн codeunit 1 и найдем функцию (триггер) NASHandler. Примечание: ID этого триггера - 99. 

Как видим на предыдущем screenshot-е мы добавили код: IF CGNASStartedinLoop = FALSE THEN CASE Parameter OF // SAMPLE > NAS Rep 'SAMPLE': CODEUNIT.RUN(CODEUNIT::"Sample Dispatcher"); // SAMPLE < NAS Rep Итак, необходимые изменения в коде произведены. Закроем клиента Microsoft Dynamics NAV (Navision). Microsoft Loopback Adapter У Microsoft Dynamics NAV (Navision) для подсоединения обычного клиента к базе данных существует две разновидности аутентификации: аутентификация БД и аутентификация Windows. Что же касается Application Server, то для него актуальна только аутентификация Windows. Иначе говоря, Application Server, как Службу (Service) windows, мы запускаем под определенной учетной записью (синонимы: логин, аккаунт) пользователя Windows. Не знаю почему, но именно для Application Server здесь кроется следующая засада: в случая отсутствия сети (например, на презентации нет возможности подключать сеть) Application Server не сможет инициализироваться. В этих случаях можно эмулировать сетевое подключение через адаптер-заглушку: Microsoft Loopback Adapter (или по-русcки: Адаптер Microsoft замыкания на себя). Предположим у нас это не проделано, т.е. Cетевые подключения выглядят примерно так: 
Войдем в консоль и запустим Сервер FINN-MOB. 
Встанем на ветку NAS\FINN-MOB-CLASSIC, проставим Start-Up Parameter Value: SAMPLE. (не забываем жать кнопку Apply These Settings). См. ниже. 
Далее запустим FINN-MOB-CLASSIC. 
Зайдем в Просмотр событий (Event Viewer). 

Как видим достучаться до сетки не можем. 
Application Server не инициализируется. Для решения проблемы приступаем к инсталляции адаптера-заглушки: Microsoft Loopback Adapter (или по-русcки: Адаптер Microsoft замыкания на себя). Далее см. screenshot-ы 








Адаптер установлен. Теперь в сетевых подключениях появилось еще одно соединение. 
Останавливаем Application Server и повторяем его запуск. Смотрим появившиеся сообщения. 


Navision Application Server был благополучно запущен. Остановим Службы (Services) Navision Application Server, Navision Database Server. Настройка Прав Обратимся теперь к теме прав доступа. На текущий момент мы запускали клиента Microsoft Dynamics NAV (Navision) только в однопользовательском режиме и заходили в систему под логином ADMIN, т.е. использовали аутентификацию БД. Службы (Services) Navision Database Server и Navision Application Server запускались под локальным системным аккаунтом. 
В нашей текущей базе данных присутствуют только Логины БД, Логинов Windows нет. 

Так же у всех Логинов БД, в частности у ADMIN не проставлены права (роли). 


Предлагаю реализовать следующую схему действий. Дадим пользователю ADMIN максимальные права. Под ADMIN мы будем коннектиться к базе клиентом для произведения кодирования, администрирования и т.п. Сервер Navision по прежнему будет стартовать под локальным системным аккаунтом. Кроме того, создадим в Microsoft Dynamics NAV (Navision) запись для Логин Windows FINN-MOB\user и дадим этому логину ограниченные права (роли) позволяющие работать с объектами Sample, формировать рассматриваемый отчет, считывать данные из нужных таблиц. Application Server будем запускать именно под FINN-MOB\user. Итак приcвоили роль SUPER Логину БД - ADMIN. См. screenshot. 
Далее создаем роль для работы с объектами Sample. 



Создаем в Microsoft Dynamics NAV (Navision) запись о Логин Windows FINN-MOB\user. 
Присваиваем FINN-MOB\user три роли. Это роли: ВСЕ (роль первоначального уровня доступа, присваивается обычно всем пользователям); К&П-Журнал (роль используется, в данном конкретном случае, что бы дать доступ к таблицам, используемым в отчете, например, таблица Валюта и т.д.); ранее созданная роль SAMPLE. 
Меняем аккаунт под которым стартует Служба (Service) Application Server на FINN-MOB\user (.\user). 
С правами разобрались. Далее собственно запуск. Запуск Клиент Microsoft Dynamics NAV (Navision) закрыт. Запускаем через консоль Navision Database Server. 
Далее запустим клиента, но уже не в однопользовательском режиме, а в серверном варианте. Для упрощения запуска создадим соответствующий ярлык. 
В Объект пробито: "C:\Program Files\Microsoft Business Solutions-Navision\Client\fin.exe" servername=FINN-MOB,company=CRONUS Россия ЗАО,ntauthentication=0 Примечание: параметр ntauthentication=0 говорит об использовании аутентификации БД. Запустим клиента через ярлык и внесем изменения в таблицу 90000 Sample Task. Назначим запуск на 12 часов. 
Далее я перевел часы на 11:55 и запустил Navision Application Server. 
Далее идут screenshot-ы полученных сообщений Просмотра событий (Event Viewer): Просмотрим получившиеся .html файлы. Откроем таблицу 90000 Sample Task и просмотрим произошедшие изменения. Все ОК. Закрываем клиента Microsoft Dynamics NAV (Navision), останавливаем обе Службы (Services). Наш пример использования Application Server подошел к концу.
|