[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经过邮件发送出去。对象

相关文章
相关标签/搜索