Dynamics AX 2009 Alert system

Dynamics AX 2009 Alert system

提醒(alert)在AX中指针对于用户所关注的事件,用户可以设置一个规则,系统定期查看这些规则,并根据规则来检查是否满足触发事件的条件。在满足触发条件时,通过弹出式窗体或邮件的形式通知用户,你说关注的事件有了新的变化。

在设置提醒规则(alert rule)前,请考虑你在什么时候或什么情况下需要提醒。在确定了什么事件发生时你需要提醒后,找到引起这个事件发生的数据所在的form,然后创建提醒规则。

事件可以是指定字段的日期即将到期或特定的修改发生。事件的类型是预先设置好的,根据字段内容的不同,可以使用的事件类型也不同。比如,如果你想设置规则的字段是‘开始日期’,那么可用的事件就是‘到期’。如果你想设置规则的字段是‘成本中心’,那么‘到期’这一事件类型将不可用,但可以使用‘修改’事件。

事件类型可以概括为三类

1.        日期到期事件:但日期满足规则时提醒。

2.        修改事件:但特定字段被修改时提醒。

3.        创建或删除事件:但新建或删除记录时提醒。

规则:

规则是用来控制什么样的事件可以触发提醒,也即只有当发生的事件满足特定的条件时才提醒你。

比如,你想在一个采购订单的状态被更新为‘接收’时收到提醒,那么事件就是:采购订单状态更新为‘接收’。

然后,你需要确定哪些采购订单的状态更新为‘接收’时触发事件,这里的‘哪些采购订单’就是我们要设置的规则。如所有订单、当前订单或满足特定过滤条件的采购订单。

提醒规则的有效范围:

提醒规则可以包含一个过期日期,如果当前日期超出了过期日期,那么该提醒规则的状态将变更为‘不可用’。

下面,我们演示设置一个所有采购订单,当其采购数量发生变化时,通过弹出式窗体提醒用户的提醒规则。

a.     打开采购订单,将光标定位到采购订单行上的数量,右键打开快捷菜单,选择‘创建提醒规则’。

     Dynamics AX 2009 Alert system_第1张图片

b.    在弹出的创建提醒规则表格中,设置提醒规则:

Field是触发事件的字段。

Event是事件类型。

点击‘Select’设置过滤规则,这里我们设置为所有采购订单。

Alert me until设置过期日期。

Subject为提醒的标题,message为提醒的内容。

UserId是要被提醒的用户。

Show pop-ups指使用弹出式窗体提醒用户。

点击Create alert rule表格上的OK按钮完成提醒规则的创建。

Dynamics AX 2009 Alert system_第2张图片

c.     管理规则:

通过Basic/Setup/Alerts/Manage alert rules打开管理规则的窗体,在这里可以修改、创建或删除规则。

 Dynamics AX 2009 Alert system_第3张图片

添加Batch job Batch job list

到这里,提醒规则以及创建成功。下一步,我们需要将处理该规则的batch job添加到batch job listing中。

对于基于修改的事件,通过Change based alerts表格来添加到batch job list,访问路径为:Basic/Periodic/Alerts/Change based alerts

Change based alerts表格中,勾选batch processing表示将该batch job 添加到batch job list。选择一个Batch group。根据实际情况决定是否勾选Private

Dynamics AX 2009 Alert system_第4张图片

点击Recurrence设置batch job 运行的次数和事件间隔:

Dynamics AX 2009 Alert system_第5张图片

对于日期过期类型的事件,使用Due date alerts表格来添加到batch job list,访问路径为:Basic/Periodic/Alerts/Due date alerts

 

Change based alerts表格中设置好所有字段后,点击OK,该batch job就会被添加到batch job list中。通过Basic/Batch job list – user可以查看batch job list

Dynamics AX 2009 Alert system_第6张图片

这里有一点需要注意,对于提醒,我们并不需要运行Batch processing,因为用来处理提醒的batch都被设置为在服务器端运行,服务器端运行的batch,在其被添加到batch job list中后,系统会自动定期运行。所以,现在我们只需要修改采购订单的采购数量,就可以看到提醒了。在AX主窗体右下角可以看到一个铃铛图标出现,点击就可以看到提醒,点击General标签页查看详细内容。

Dynamics AX 2009 Alert system_第7张图片

 

从开发人员的角度,我们可以这样描述整个流程:

1.       新创建一个提醒规则(alert rule),系统会向表EventRule添加一条新记录,同时检查键值为UserId +Company 的记录是否存在于表EventCompanyRule,如果不存在,就新建一条。

2.       当修改(update,insert,delete)记录时,表的对应方法(如 insert, update, delete)会调用xRecord的对应方法,在xRecord中会根据提醒规则,调用类Application来向表EventCUD添加事件。添加事件包含了内容,company,但不会添加userId,并且该条EventCUD的状态为Hold.

如下图是在修改采购订单采购数量时插入事件的方法调用堆栈:

Dynamics AX 2009 Alert system_第8张图片

3.       通过Basic/Periodic/Alerts/Change based alerts Due date alerts将处理提醒规则的batch job添加到batch job listing

4.       基于修改的提醒是由类EventJobCUD来处理的,而EventJobCUDrunsImpersonated设置为true,表示该Job是运行在服务器端的。运行在服务器端的batch job不需要运行batch processing,只要batch job 被添加到batch job listing,服务器就会自动运行该Job了。

5.       batch job运行时,我们是在某一公司下运行的,通过EventCompanyRule找到在该公司下有提醒规则的所有用户,将EventCUD中的每一个事件拷贝一份给每一个有提醒规则的用户(新的eventCUD会包含userId),新的EventCUD的状态将是Waiting,然后删除原来的EventCUD

对于新的EventCUD中的每一个用户,以该用户的权限来遍历他所关联的所有事件,处理每一个事件并删除该事件(这里的处理指根据事件来提醒用户)。

6.       在处理完所有事件以后,检查是否有因冲突而未处理完的事件(这些事件的状态为Excuting),将这些事件的状态更改为Waited,等待下一次batch job运行时继续处理。

7.       基于日期期限的事件处理是由EventJobDueDate来完成的,同样,他的runsImpersonated被设置为true

8.       对于每一个拥有基于日期期限事件的用户,遍历他的所有基于日期期限的规则,根据规则中过滤数据的条件(query),检查每一条记录,如果满足事件触发条件,就做对应的处理。在处理完事件后,检查规则设置的运行次数和到期时间,如果规则过期或已经运行了规定次数,则将规则设置为不可用。

下面是使用代码创建Alert规则的演示:

以下代码参考了:http://www.benjagroup.dk/blog/2008/04/dynamics-ax-alerts-in-x.html

/*Create an alert rule for the given employee * This will notify the employee 1 day before a journal is due. */ public static void DaveAlerts() { PurchLine purchLine; QueryBuildDataSource purchLine_ds; EventRule eventRule; DictTable dictTable; DictField dictField; /* Actions (Alert,Email) */ List actions = new List(Types::Integer); /* Filter for alert rule */ boolean saveQuery = true; Query filterQuery; QueryBuildRange respRange; /* Type Value, all types are prefixed with EventType */ EventTypeCUD eventType = new EventTypeCUD(); /* Context, The EventContextInformation class packs and unpacks context information that is needed to drill down to a specific record in a form. */ Args args; FormRun purchTableForm; EventContextInformation eci = new EventContextInformation(); /* tmpEventAlertField */ Map fds2EventBuildValidAlertFields; // Map holding valid alert field instances per formDataSource tmpEventAlertField tmpEventAlertField; /*The EventBuildValidAlertFields class is used to build a temporary TmpEventAlertField table that holds a record for each valid control in the specified FormRun on the dataset specified by the FormDataSource. */ EventBuildValidAlertFields eventBuildValidAlertFields; //int tableId; //int fieldId; str formName; int eventTypeId; int controlId; str fieldLabel; ; dictTable = new DictTable(tablenum(PurchLine)); dictField = new DictField(dictTable.id(), fieldname2id(dictTable.id(),"PurchQty")); formName = formstr(PurchTable); eventTypeId = classnum(EventTypeCUD); /* PurchTable form */ args = new args(); args.name(formstr(PurchTable)); purchTableForm = classFactory.formRunClass(args); purchTableForm.init(); args.menuItemType(MenuItemType::Display); args.menuItemName(formName); controlId = purchTableForm.design().controlName("PurchLine_PurchQty").id(); /* Alert Field data */ if (!fds2EventBuildValidAlertFields) fds2EventBuildValidAlertFields = new Map(Types::Integer,Types::Class); if (!fds2EventBuildValidAlertFields.exists(purchTableForm.dataSource(2).id())) { fds2EventBuildValidAlertFields.insert(purchTableForm.dataSource(2).id(), EventBuildValidAlertFields::newFormDataSource( purchTableForm, purchTableForm.dataSource(2), false) ); } /* get tmpEventAlertField by control's ID */ eventBuildValidAlertFields = fds2EventBuildValidAlertFields.lookup(purchTableForm.dataSource(2).id()); tmpEventAlertField = eventBuildValidAlertFields.parmTmpEventAlertField(); select firstonly tmpEventAlertField where tmpEventAlertField.ControlId == controlId; if (tmpEventAlertField) { fieldLabel = tmpEventAlertField.Label; } else { return; } ttsbegin; /* ----- Create the Alert Rule ------ */ /* Setup Event Rule */ actions.addEnd(classNum(EventActionAlert)); actions.addEnd(classnum(EventActionEmail)); eventRule.RuleId = NumberSeq::newGetNum(CompanyInfo::numRefParmId()).num(); eventRule.UserId = curuserid(); eventRule.TypeId = eventTypeId; eventRule.AlertTableId = dictTable.id(); eventRule.AlertFieldId = fieldid2ext(dictField.id(),1); eventRule.PrimTableId = dictTable.id(); eventRule.Until = EventUntil::Always; eventRule.Enabled = NoYes::Yes; eventRule.AlertQbdsNo = 1; eventRule.FormName = formName; eventRule.TypeTrigger = EventTypeTrigger::FieldChanged; eventRule.RuleCondition = EventRuleCondition::All; eventRule.AlertFieldLabel = tmpEventAlertField.Label; eventRule.DeleteRefRecId = 0; eventRule.ShowPopup = NoYes::Yes; eventRule.SendEmail = NoYes::No; eventRule.Subject = "subject"; eventRule.Message = "message"; eventRule.ActionIds = actions.pack(); eventRule.insert(); /* Setup Event Rule end */ /* Filter data */ filterQuery = new Query(); purchLine_ds = filterQuery.addDataSource(tablenum(PurchLine)); respRange = purchLine_ds.addRange(fieldnum(PurchLine, PurchId)); respRange.value("*"); eventRule.filterQuery(filterQuery); /* Filter data end */ /* Value data */ eventType.setRule(eventRule); eventType.parmTypeTrigger(EventTypeTrigger::FieldChanged); //eventType.parmXValue(1); // this is use when we use due date alert (Due in 1 calender day) eventRule.typeValue(eventType.pack()); /* Value data end */ /* Context data */ eci.parmPackedArgs(args); eci.setEventRuleId(eventRule.RuleId); eci.parmFormControlName("PurchLine_PurchQty"); eci.parmFormRun(purchTableForm); eci.parmAlertFormDsName("PurchLine"); eventRule.contextInfo(eci.pack()); /* Context data end */ /* Alert Field data */ if (!fds2EventBuildValidAlertFields) fds2EventBuildValidAlertFields = new Map(Types::Integer,Types::Class); if (!fds2EventBuildValidAlertFields.exists(purchTableForm.dataSource(2).id())) { fds2EventBuildValidAlertFields.insert( purchTableForm.dataSource(2).id(), EventBuildValidAlertFields::newFormDataSource(purchTableForm, purchTableForm.dataSource(2),false) ); } tmpEventAlertField = fds2EventBuildValidAlertFields.lookup(purchTableForm.dataSource(2).id()).label2TmpEventAlertField(fieldLabel); eventRule.alertField([tmpEventAlertField]); /* Alert Field data end */ ttscommit; }

你可能感兴趣的:(list,服务器,filter,Integer,processing,Types)