To Define a Custom Subscriber Type for Business Events
To define the actions that the system should perform once a business event has occurred, you specify the subscribers of this business event on the Subscribers tab of the Business Events (SM302050) form. A subscriber of a business event is an entity that the system processes when the business event occurs. The subscriber types available in the system include import scenarios, email notifications, mobile push notifications, and mobile SMS notifications. You can define a custom subscriber type for business events, as described in this topic.
Attention: A custom subscriber type can be implemented in a project of your
MYOB Acumatica extension library. You cannot include the custom subscriber type in a Code
item of a customization project.
For more information on business events, see Business Events: General Information.
Creation of a Custom Subscriber Type for Business Events
- Define a class that implements the PX.BusinessProcess.Subscribers.ActionHandlers.IEventAction interface, which is a subscriber that the system executes once the business event has occurred.
- In the class that implements the IEventAction interface,
implement the following methods and properties of the interface:
- The Id property, which is the GUID that identifies
the subscriber. For the predefined subscriber types, the system assigns
the value of this property to a new subscriber created by a user. The
property uses the following
syntax.
Guid Id { get; set; }
- The Name property, which is the name of the
subscriber of the custom type. For the predefined subscriber types, a
user specifies the value of this property on the form that corresponds
to the subscriber. For example, for email notifications, the user
specifies the value of this property in the
Description box on the Email Templates (SM204003) form. Use the
following syntax for the
property.
string Name { get; }
- The Process method, which implements the actions that
the system should perform once the business event has occurred. For
example, for email notifications, the method inserts values in the
notification template and sends the notification. The method uses the
following
syntax.
void Process(MatchedRow[] eventRows, CancellationToken cancellation);
- The Id property, which is the GUID that identifies
the subscriber. For the predefined subscriber types, the system assigns
the value of this property to a new subscriber created by a user. The
property uses the following
syntax.
- Define a class that implements the PX.BusinessProcess.Subscribers.Factories.IBPSubscriberActionHandlerFactory interface, which creates and executes the subscriber.
- In the class that implements the
IBPSubscriberActionHandlerFactory interface, implement
the following methods and properties of the interface:
- The CreateActionHandler method, which creates a
subscriber with the specified ID. Use the following syntax for the
method.
IEventAction CreateActionHandler(Guid handlerId, bool stopOnError, IEventDefinitionsProvider eventDefinitionsProvider);
- The GetHandlers method, which retrieves the list of
subscribers of the custom type. This list is displayed in the lookup
dialog box in the Subscriber ID column on the
Subscribers tab of the Business Events (SM302050) form. The method
uses the following
syntax.
IEnumerable<BPHandler> GetHandlers(PXGraph graph);
- The RedirectToHandler method, which performs
redirection to the subscriber. For example, for email notifications, the
method opens the Email Templates form,
which displays the subscriber (which is a notification template) with
the specified ID. Use the following syntax for the
method.
void RedirectToHandler(Guid? handlerId);
- The Type property, which is a
string
identifier of the subscriber type that is exactly four characters long. The value of this property is stored in the database. The property uses the following syntax.string Type { get; }
- The TypeDescription property, which is a
string
label of the subscriber type. A user views this value in the Type column on the Subscribers tab of the Business Events form. Use the following syntax for the property.string TypeDescription { get; }
Tip: If you want an action to be displayed in the Create Subscriber menu on the toolbar of the Subscribers tab of the Business Events (SM302050) form, instead of implementing the IBPSubscriberActionHandlerFactory interface, implement the IBPSubscriberActionHandlerFactoryWithCreateAction interface, which also provides methods and properties that define the creation action. - The CreateActionHandler method, which creates a
subscriber with the specified ID. Use the following syntax for the
method.
- Compile your MYOB Acumatica extension library with the implementation of the classes.
- Open MYOB Acumatica and test the new subscriber type.
Example
The following code shows an example of the implementation of a custom subscriber
type. This custom subscriber writes the body of the notification to a text
file.
using System;
using System.Collections.Generic;
using System.Linq;
using PX.BusinessProcess.Subscribers.ActionHandlers;
using PX.BusinessProcess.Subscribers.Factories;
using PX.BusinessProcess.Event;
using PX.BusinessProcess.DAC;
using PX.BusinessProcess.UI;
using System.Threading;
using PX.Data;
using PX.Common;
using PX.SM;
using System.IO;
using PX.Data.Wiki.Parser;
using PX.PushNotifications;
namespace CustomSubscriber
{
//The custom subscriber that the system executes once the business event
//has occurred
public class CustomEventAction : IEventAction
{
//The GUID that identifies a subscriber
public Guid Id { get; set; }
//The name of the subscriber of the custom type
public string Name { get; protected set; }
//The notification template
private readonly Notification _notificationTemplate;
//The method that writes the body of the notification to a text file
//once the business event has occurred
public void Process(MatchedRow[] eventRows,
CancellationToken cancellation)
{
using (StreamWriter file =
new StreamWriter(@"C:\tmp\EventRows.txt"))
{
var graph = PXGenericInqGrph.CreateInstance(
_notificationTemplate.ScreenID);
var parameters = @eventRows.Select(
r => Tuple.Create<IDictionary<string, object>,
IDictionary<string, object>>(
r.NewRow?.ToDictionary(c => c.Key.FieldName, c => c.Value),
r.OldRow?.ToDictionary(c => c.Key.FieldName,
c => (c.Value as ValueWithInternal)?.ExternalValue ??
c.Value))).ToArray();
var body = PXTemplateContentParser.ScriptInstance.Process(
_notificationTemplate.Body, parameters, graph, null);
file.WriteLine(body);
}
}
//The CustomEventAction constructor
public CustomEventAction(Guid id, Notification notification)
{
Id = id;
Name = notification.Name;
_notificationTemplate = notification;
}
}
//The class that creates and executes the custom subscriber
class CustomSubscriberHandlerFactory :
IBPSubscriberActionHandlerFactoryWithCreateAction
{
//The method that creates a subscriber with the specified ID
public IEventAction CreateActionHandler(Guid handlerId,
bool stopOnError, IEventDefinitionsProvider eventDefinitionsProvider)
{
var graph = PXGraph.CreateInstance<PXGraph>();
Notification notification = PXSelect<Notification,
Where<Notification.noteID,
Equal<Required<Notification.noteID>>>>
.Select(graph, handlerId).AsEnumerable().SingleOrDefault();
return new CustomEventAction(handlerId, notification);
}
//The method that retrieves the list of subscribers of the custom type
public IEnumerable<BPHandler> GetHandlers(PXGraph graph)
{
return PXSelect<Notification, Where<Notification.screenID,
Equal<Current<BPEvent.screenID>>,
Or<Current<BPEvent.screenID>, IsNull>>>
.Select(graph).FirstTableItems.Where(c => c != null)
.Select(c => new BPHandler { Id = c.NoteID, Name = c.Name,
Type = LocalizableMessages.CustomNotification });
}
//The method that performs redirection to the subscriber
public void RedirectToHandler(Guid? handlerId)
{
var notificationMaint =
PXGraph.CreateInstance<SMNotificationMaint>();
notificationMaint.Message.Current =
notificationMaint.Notifications.
Search<Notification.noteID>(handlerId);
PXRedirectHelper.TryRedirect(notificationMaint,
PXRedirectHelper.WindowMode.New);
}
//A string identifier of the subscriber type that is
//exactly four characters long
public string Type
{
get { return "CTTP"; }
}
//A string label of the subscriber type
public string TypeName
{
get { return LocalizableMessages.CustomNotification; }
}
//A string identifier of the action that creates
//a subscriber of the custom type
public string CreateActionName
{
get { return "NewCustomNotification"; }
}
//A string label of the button that creates
//a subscriber of the custom type
public string CreateActionLabel
{
get { return LocalizableMessages.CreateCustomNotification; }
}
//The delegate for the action that creates
//a subscriber of the custom type
public Tuple<PXButtonDelegate, PXEventSubscriberAttribute[]>
getCreateActionDelegate(BusinessProcessEventMaint maintGraph)
{
PXButtonDelegate handler = (PXAdapter adapter) =>
{
if (maintGraph.Events?.Current?.ScreenID == null)
return adapter.Get();
var graph = PXGraph.CreateInstance<SMNotificationMaint>();
var cache = graph.Caches<Notification>();
var notification = (Notification)cache.CreateInstance();
var row = cache.InitNewRow(notification);
row.ScreenID = maintGraph.Events.Current.ScreenID;
cache.Insert(row);
var subscriber = new BPEventSubscriber();
var subscriberRow =
maintGraph.Subscribers.Cache.InitNewRow(subscriber);
subscriberRow.Type = Type;
subscriberRow.HandlerID = row.NoteID;
graph.Caches[typeof(BPEventSubscriber)].Insert(subscriberRow);
PXRedirectHelper.TryRedirect(graph,
PXRedirectHelper.WindowMode.NewWindow);
return adapter.Get();
};
return Tuple.Create(handler,
new PXEventSubscriberAttribute[]
{new PXButtonAttribute {
OnClosingPopup = PXSpecialButtonType.Refresh}});
}
}
//Localizable messages
[PXLocalizable]
public static class LocalizableMessages
{
public const string CustomNotification = "Custom Notification";
public const string CreateCustomNotification = "Custom Notification";
}
}
To test this example, do the following:
- Add this code to an MYOB Acumatica extension library. For details on creating the library, see To Create an Extension Library.
- Make sure that the following references are added to the project of the
extension library:
- PX.Data
- PX.Common
- PX.Common.Std
- PX.BusinessProcess
- Create a business event on the Business Events (SM302050) form. For details on the creation of a business event, see Business Events: General Information.
- On the Subscribers tab, make sure Custom Notification is available in the Type column.
- Select Custom Notification in the Type column. Make sure the list in the Subscriber ID column is empty.
- On the table toolbar, make sure is available.
- Click Email Templates (SM204003) form opens. . Make sure the
- On the Email Templates form, create a notification template with a message that is not empty on the Messages tab. For details about notification templates, see Email Templates.
- Make sure the created notification template is added to the Subscribers tab of the Business Events form as the Custom Notification subscriber and save the business event.
- Make changes in the system to trigger the business event that you have configured.
- Make sure the text file (in this example, C:\tmp\EventRows.txt) contains the body of the notification.