[AX2012 R3]關於Alerts

AX2012提供兩種類型的Alert,Change-based alert和Due-date-based alert,前者用於在對新建記錄、刪除記錄、記錄的某個指定字段被改變的時候發出提醒,後者則是用於監視記錄日期類型的某個字段,在超期指定的日期後發出提醒。在記錄的編輯form或者list page上右鍵菜單中咱們能找到「Create alert rule」菜單項,經過它打開alert規則建立窗口。規則建立窗口裏咱們能夠選擇alert要發給誰,只能是一個特定的用戶,不能是一個用戶組,若是通知須要發送給多個用戶只能建立多個alert規則了。另外在咱們能夠勾選「Send email」將通知經過郵件的方式發送給用戶,要使用這個功能必須設置好Alert郵件模板,首先在Organization administration>Setup>Email-template建立一個Alert的郵件模板(非系統郵件模板),郵件模板中能夠添加佔位符變量,在生成具體的郵件時指向真實的數據。Alert郵件模板的例子能夠在https://technet.microsoft.com/en-us/library/aa834376.aspx找到。建立好郵件模板後,咱們還須要到Organization administration>Setup>Alerts>Alert parameter選擇這個郵件模板爲咱們的Alert郵件模板。全部的通知規則咱們能夠在Organization administration>Setup>Alerts>Alert rules找到,在這裏能夠管理建立好的通知規則,使能或者刪除規則等。通知規則列表有一列叫作Organiztion-wide,這個不是能手工修改的,若是咱們對公司無關的表(好比workers、products)添加規則時會自動打勾。html

通知規則建立好後不等於在記錄改變時你就能收到Alert消息,咱們還須要配置兩個Batch job,由它們來處理髮出通知消息。一個是 System administration>Periodic>Alerts> Change based alerts,由它處理change-based通知。另外一個是 System administration>Periodic>Alerts>Due date alerts,由它出來due-date-based通知。ide

先來看Change-based的批處理任務,它運行的類是EventJobCUD,它只是判斷EventCUD表中是否要處理的Alert事件,若是有則交由EventJobCUDTask處理。EventJobCUDTask讀取EventCUD須要處理的記錄的用戶ID,經過runas切換到該用戶運行EventJobCUDTask.runCudEventsForUser(),runCudEventsForUser依次讀取該用戶相關的EventCUD記錄,而後交由EventProcessorCUD處理。EventProcessorCUD針對事件的類型(更新、刪除、建立、主鍵更改)作不一樣的處理,好比更新事件,它從EventCUD的Data字段(Container類型)剝離出被監視記錄字段的字段ID、新老值,建立EventTypeCUD對象,保存更新字段的新老值,隨後根據通知規則中的通知類型建立相應的EventAction,最後生成相應的事件通知保存在EventInbox表中。若是指定了使用郵件通知,會建立EventActionEmail對象,它負責生成佔位符對象數據映射,交由SysEmailTable或者SysEmailSystemTable生成實際的郵件放到SysOutgoingEmailTable等候發送。處理成功後相關記錄在EventCUD中被刪除。這裏只是對處理過程作了簡單的陳述,實際的過程要複雜得多,須要處理表繼承已經通知規則中指定的記錄過濾查詢等。函數

能夠看出change-based通知的核心是處理EventCUD的記錄,那麼這個表中的數據是從哪裏來的呢?微軟的解釋是使用database log來檢測記錄更改,alert模塊在xApplication類的EventInsert、EventUpdate、EventDelete註冊本身的回調函數,若是通知規則中涉及到的表發生變化將更改記錄到EventCUD表。能夠看到的是若是咱們添加一個通知規則,在表DatabaseLog中會相應增長一條記錄,記錄對哪一個表作EventXXX類型的log。System administration > Setup > Database > Database log setup看不到這些記錄,這個form不顯示和EventXXX類型的DatabaseLog。在通知規則監視的表記錄修改後,其修改記錄在System administration > Inquries > Database > Database log也是看不到的,可是在EventCUD中會增長相關記錄。xApplication是系統類,看不到具體是如何實現的。ui

再來看Due-Date-based的批處理任務,它運行的是EventJobDueDate,它讀取EventRule表中Due-date類型的通知規則的用戶ID,也是runas切換到該用戶執行runDueDateEventsForUser(),在runDueDateEventsForUser中調用EventProcessorDueDate.processRule()來處理當前的EventRule,從EventRule中讀取記錄過濾Query,讀取Query中的記錄,調用EventProcessorDueDate.processRecord()處理記錄,若是日期字段超期,也是根據通知規則中的通知類型建立相應的EventAction,後面的過程和change-based相似了。若是通知規則已經觸發併成功處理,該通知規則會被添加到表EventRuleIgnore中,後續再也不觸發(在EventTypeDue.canExecute()判斷)。spa

在瞭解了Alert如何工做的後,咱們能夠添加自定義的事件類型(EventType)和自定義的事件處理動做(EventAction),能夠參見https://msdn.microsoft.com/en-us/library/aa673670.aspxcode

通知消息是保存在表EventInbox中的,在user options的Notification一節咱們能夠設置接受通知的時間間隔,客戶端按照時間間隔讀取通知消息,若是通知設置了須要顯示彈窗,AX client會彈出彈窗。能夠想見的是直接操做EventInbox來建立用戶通知,網上有不少例子,這裏截取一個(http://daxldsoft.blogspot.com/2012/10/create-custom-alert-for-ax-with-go-to.html):orm

 public static void CreateAlert(str message,  
               str subject,  
               UserId userId = curUserId(),  
               NoYes showPopup = NoYes::Yes,  
               NoYes sendEmail = NoYes::No,  
               Common record = null,  
               str dataSourcename = '',  
               MenuFunction menuFunction = null)  
 {  
   EventInbox inbox;  
   DictTable table;  
   EventContextInformation eci;  
   EventInboxData inboxData;  
   Args args = new Args();  
   List list;  
   EventInboxId inboxId = EventInbox::nextEventId();  
   FormRun formRun;  
   WorkflowRecordCaptionGenerator recordCaptionGenerator;  
   UserInfo userInfo;  
   inboxId = EventInbox::nextEventId();  
   inbox.initValue();  
   inbox.ShowPopup      = showPopup;  
   inbox.Subject       = subject;  
   inbox.Message       = message;  
   inbox.SendEmail      = sendEmail;  
   inbox.EmailRecipient    = SysUserInfo::find().Email;  
   inbox.UserId        = userId;  
   inbox.InboxId       = inboxId;  
   inbox.AlertCreatedDateTime = DateTimeUtil::getSystemDateTime();  
   if (record)  
   {  
     table = new DictTable(record.TableId);  
     eci = new EventContextInformation();  
     if (!menuFunction)  
     {  
       menuFunction = new MenuFunction(table.formRef(),MenuItemType::Display);  
       if (!menuFunction)  
         throw error(strFmt("@SYS104114",table.formRef()));  
     }  
     //Build the data to drill down to from the notification  
     args.menuItemName(menuFunction.name());  
     args.menuItemType(MenuItemType::Display);  
     args.name(menuFunction.object());  
     eci.parmPackedArgs(args);  
     eci.parmAlertBuffer(record);  
     eci.parmAlertFormDsName(dataSourceName);  
     //eci.parmDontUseFormRunFromMenuItem(true);  
     inboxData.InboxId = inboxId;  
     inboxData.DataType = EventInboxDataType::Context;  
     inboxData.Data = eci.pack();  
     inboxData.insert();  
     inbox.AlertTableId = table.id();  
     inbox.ParentTableId = table.id();  
     recordCaptionGenerator = WorkflowRecordCaptionGenerator::construct(record);  
     inbox.AlertedFor = recordCaptionGenerator.caption();  
     list = SysDictTable::getUniqueIndexFields(table.id());  
     if (list)  
     {  
       inbox.keyFieldList(list.pack());  
       inbox.keyFieldData(SysDictTable::mapFieldIds2Values(list,record).pack());  
     }  
     inbox.CompanyId = record.company();  
   }  
   inbox.insert();  
 } 

使用上面的函數來建立Alert:htm

static void Job155(Args _args)  
 {  
   InventTable inventTable;  
   select firstOnly inventTable;  
   DEVUtils::CreateAlert("message", "subject", curUserId(), true, false, inventTable, "InventTable", new MenuFunction(menuitemDisplayStr(EcoResProductDetailsExtended), MenuItemType::Display));  
 }  

上面的CreateAlert函數有個sendEmail參數,對應EventInbox的字段SendEmail,把這個參數設置爲true,咱們也不會收到郵件,由於咱們只是標記了這個字段,我沒有找到系統中有好比batch job來將EventInbox經過郵件發送出去。對象

相關文章
相關標籤/搜索