NotifyModule

In this article, we will understand how to use Notify module end to end to add new notifications to modules and send notifications from those modules.

Module authors have a greater responsibility for processing notifications from the system. Therefore they need to make many decisions and provide the required information to notify the module. Decision points for module authors

  • Decide events and scenarios for notifications.
  • Decide on required template shortcodes.
  • Decide if the notification setting is editable or not
  • Decide whether notification settings can be edited by Notify or the module itself.
  • Decide whether the notification is allowed for all channels or restricted channels.
  • Decide short and long template content for notifications
  • Decide receiver category and template for them

Once all these decision points have been made, module authors can use methods provided by NotifyModule to seed notification details and inform Notify to process the notifications.

Add/Update notifications

getShortCodes

Use the getShortCodes method to get a list of available shortcodes and check not to add some shortcodes.

NotifyModule::getShortCodes()
//output
 [
     [
       "id" => 1,
       "key_name" => "receiver_name",
       "shortcode" => "{!! $receiver_name !!}",
       "desc_lang_key" => "receiver_name_desc_key",
       "plugin_name" => null,
       "created_at" => "2022-10-08 15:09:14",
       "updated_at" => "2022-10-08 15:09:14",
     ],
     [
       "id" => 2,
       "key_name" => "system_link",
       "shortcode" => "{!! $system_link !!}",
       "desc_lang_key" => "system_link_desc_key",
       "plugin_name" => null,
       "created_at" => "2022-10-08 15:09:14",
       "updated_at" => "2022-10-08 15:09:14",
     ],
     ...
]

createOrUpdateGlobalShortCodes

Use this method to add the shortcodes in the system, which can be used for all the templates globally for all modules and plugins.

The method accepts the array containing a list of shortcodes and details.

  • key_name: key which will be passed in notify event payload
  • shortcode: shortcode which will be replaced with values in the templates

to see the usage check addGlobalShortCodes method of database\seeds\v_5_0_0\NotifySeeder

NotifyModule::createOrUpdateGlobalShortCodes([
   ['key_name' => 'receiver_name', 'shortcode' => '{!! $receiver_name !!}'],
   ['key_name' => 'system_link', 'shortcode' => '{!! $system_link !!}']
])
//outputs all the shortcodes
[
     [
       "id" => 1,
       "key_name" => "receiver_name",
       "shortcode" => "{!! $receiver_name !!}",
       "desc_lang_key" => "receiver_name_desc_key",
       "plugin_name" => null,
       "created_at" => "2022-10-08 15:09:14",
       "updated_at" => "2022-10-08 15:09:14",
     ],
     [
       "id" => 2,
       "key_name" => "system_link",
       "shortcode" => "{!! $system_link !!}",
       "desc_lang_key" => "system_link_desc_key",
       "plugin_name" => null,
       "created_at" => "2022-10-08 15:09:14",
       "updated_at" => "2022-10-08 15:09:14",
     ],
    ...
]

validateEventDataArray

Use this method to validate the prepared data for adding the notifications. The method accepts the array as the first parameter and the key as the second parameter, which it will use to validate prepared data. Returns true if data is appropriately false otherwise.

NotifyModule::validateEventDataArray([
    [
        'event' => 'custom_alerts',
        'module' => 'users',
        'class_name' => 'App\Notify\Controllers\NotifyResolver\UserResolverController',
        'plugin_name' => null,
        'restricted_channels' => null,
        'is_editing_allowed' => 0,
        'scenarios' => [
            [
                'scenario' => 'custom_alerts',
                'categories' => [
                    [
                        'category' => 'common_templates',
                        'templates' => [
                            [
                                'template' => 'custom_alerts_notify_template',
                                'subject' => '{!! $subject !!}',
                                'long_message' => '{!! $message_content !!}',
                                'short_message' => '{!! $message_content !!}',
                                'shortcodes' => [
                                    ['key_name' => 'message_content', 'shortcode' => '{!! $message_content !!}'],
                                    ['key_name' => 'subject', 'shortcode' => '{!! $subject !!}'],
                                ]
                            ]
                        ],
                        'persons' => [
                            ['person' => 'custom']
                        ],
                        'active_channels' => [
                            'email' => ['custom'],
                            'in-app' => ['custom']
                        ]
                    ],
                ],
            ],
        ]
    ]
],'events')
//output 
true


NotifyModule::validateEventDataArray([
[
        'event' => 'custom_alerts',
        'module' => 'users',
        'scenarios' => [
            [
                'scenario' => 'custom_alerts',
                'categories' => [
                    [
                        'category' => 'common_templates',
                        'templates' => [
                            [
                                'template' => 'custom_alerts_notify_template',
                                'subject' => '{!! $subject !!}',
                                'long_message' => '{!! $message_content !!}',
                                'short_message' => '{!! $message_content !!}',
                                'shortcodes' => [
                                    ['key_name' => 'message_content', 'shortcode' => '{!! $message_content !!}'],
                                    ['key_name' => 'subject', 'shortcode' => '{!! $subject !!}'],
                                ]
                            ]
                        ],
                        'persons' => [
                            ['person' => 'custom']
                        ],
                        'active_channels' => [
                            'email' => ['custom'],
                            'in-app' => ['custom']
                        ]
                    ],
                ],
            ],
        ]
    ]
],'events')
//output
false

 

addEvents

Once you have all the decision points ready, you need to prepare the array containing details of the notification and use the addEvents method for seeding or updating the notifications in the system. Do verify the event data array using the validateEventDataArray method to avoid errors. addEvents method accepts the array containing the list of the events and required data. Event data includes details like the below (check database\seeds\v_5_0_0\alerts.php for more).

NotifyModule::addEvents($events)

// where $event is as below
[
    [
        'event' => 'ticket_created',
        'module' => 'tickets',
        'class_name' => 'App\Notify\Controllers\NotifyResolver\TicketUserResolverController',
        'plugin_name' => null,
        'restricted_channels' => null,
        'scenarios' => [
            [
                'scenario' => 'ticket_created_alert',
                'categories' => [
                    [
                        'category' => 'agent_templates',
                        'templates' => [
                            [
                                'template' => 'new_ticket_alert_template',
                                'subject' => '#{!! $ticket_number !!} | New ticket has been created',
                                'long_message' => '<div style="width: 100%!important; margin: 0; padding: 0;"><div style="padding: 15px; line-height: 18px; font-family: Lucida Grande,Verdana,Arial,sans-serif; font-size: 12px; color: #444444;"><p>Hello {!! $receiver_name !!},<br /><br />New ticket with ID: {!! $ticket_number !!} has been created in our helpdesk.<br /><br /><strong>Client Details</strong><br /><strong>Name:</strong> {!! $client_name !!}<br /><strong>E-mail:</strong> {!! $client_email !!}<br /><br /><strong>Message</strong><br />{!! $message_content !!}</p>Kind regards,<br />{!! $system_name !!}</p></div></div>',
                                'short_message' => '#{!! $ticket_number !!} : New ticket has been created in the system',
                                'shortcodes' => [
                                    ['key_name' => 'ticket_link', 'shortcode' => '{!! $ticket_link !!}'],
                                    ['key_name' => 'ticket_number', 'shortcode' => '{!! $ticket_number !!}']
                                ]
                            ]
                        ],
                        'persons' => [
                            ['person' => 'admins'],
                            ['person' => 'department_managers'],
                            ['person' => 'department_members'],
                            ['person' => 'team_members'],
                            ['person' => 'team_leads'],
                        ],
                        'active_channels' => [
                            'email' => ['department_managers', 'team_leads'],
                            'in-app' => ['department_managers', 'team_leads']
                        ]
                    ],
                ],
            ],
        ...
        ]
    ],
    ...
]
//Structure of the notify event data array
[
    [
        'event' => name of event,
        'module' => name of module
        'class_name' => receiver resolver class
        'plugin_name' => null or name of the plugin,
        'restricted_channels' => name of the channels or null,
        'is_editing_allowed' => 0 (optional)
        'has_custom_settings' => false (optional)
        'scenarios' => [
            [
                'scenario' => name of scenario,
                'categories' => [
                    [
                        'category' => template category,
                        'templates' => [
                            [
                                'template' => template keys,
                                'subject' => notification template subject
                                'long_message' => notification template long content
                                'short_message' => notification template short content
                                'shortcodes' => [
                                    ['key_name' => key of shortcode, 'shortcode' => shortcode in template],
                                    ...
                                ]
                            ]
                        ],
                        'persons' => [
                            ['person' => person type name (e.g. admins, assigned_agents etc.)],
                            ...
                        ],
                        'active_channels' => [
                            channel name => [person types]
                            'email' => ['admins', 'assigned_agents'],
                            ...
                        ]
                    ],
                ],
                ....
            ],
            ...
        ]
    ],
]
  • event (string): name of the event
  • module (string): name of the module
  • class_name (string): name of the class which resolves the receiver used for the notifications. Each module must provide it if they have a custom resolver. Else use the default ones available in notify
  • plugin_name (string) : plugin name
  • restricted_channels (string): comma-separated channel names
  • is_editing_allowed (boolean): Optional if settings not editable
  • has_custom_settings (boolean): Optional if the module itself will handle settings
  • scenarios (array):
    • scenario (string): name of the scenario
    • categories (array)
      • category (string): name of template category
      • templates (array)
        • template (string): name of the template
        • subject (string): subject of the notification
        • long_message (string): long content of notification template
        • short_message (string): short content of notification template
        • shortcodes (array): shortcode array
      • persons (array): an array containing person types
      • active_channels (array): an array containing channel to keep notifications active

Check different alerts.php files in seeds and NotifySeeder for code-level understanding.

Handle custom notification settings

Notifications can be of three types: (see database\seeds\v_5_0_0\alerts.php)

  • Always on, users can not deactivate it, so it will not have settings. E.g., password reset. [defined in non_editable_events]
  • Editable by Notify via default settings. E.g., ticket creation notifications. [defined in base_alerts]
  • Editable by the module itself for each entity. Notify the module itself will handle settings. E.g., SLA escalations and ticket status update. [defined in custom_alerts]

To handle custom editable notification settings, module authors can use the below methods.

getModuleAlertSettings

Use getModuleAlertSettings to get the saved custom settings for the module. The method accepts the event’s name with custom settings and the id of the entity of the module. The method will return the saved or default details for the event, which custom module authors can use to show the settings in the front end by sending it as API response.

NotifyModule::getModuleAlertSettings('ticket_status_changed', 1)
//output
[
     "ticket_status_changed" => [
       "name" => "ticket_status_changed_lang_key",
       "description" => "ticket_status_changed_desc_key",
       "allowedChannels" => [
         [
           "id" => 1,
           "channel" => "email",
           "lang_key" => "email_lang_key",
           "desc_lang_key" => "email_notification_channel_template_description",
           "icon" => "fas fa-envelope",
           "system_default" => 0,
           "template_types" => "long",
           "event_listener_class" => "App\Events\NotifyToEmail",
           "plugin_name" => null,
           "created_at" => "2022-10-08 15:09:14",
           "updated_at" => "2022-10-08 15:09:14",
           "pivot" => [
             "event_id" => 8,
             "channel_id" => 1,
           ],
         ],
         [
           "id" => 2,
           "channel" => "in-app",
           "lang_key" => "in-app_lang_key",
           "desc_lang_key" => "in_app_desc_key",
           "icon" => "far fa-bell",
           "system_default" => 0,
           "template_types" => "short",
           "event_listener_class" => "App\Events\NotifyToInApp",
           "plugin_name" => null,
           "created_at" => "2022-10-08 15:09:14",
           "updated_at" => "2022-10-08 15:09:14",
           "pivot" => [
             "event_id" => 8,
             "channel_id" => 2,
           ],
         ],
       ],
       "associates" => [
         [
           "name" => "admins_lang_key",
           "description" => "admins_desc_key",
           "associate_id" => 59,
           "channels" => [
             1,
           ],
         ],
         [
           "name" => "department_managers_lang_key",
           "description" => "department_managers_desc_key",
           "associate_id" => 60,
           "channels" => [],
         ],
         [
           "name" => "department_members_lang_key",
           "description" => "department_members_desc_key",
           "associate_id" => 61,
           "channels" => [],
         ],
         [
           "name" => "team_members_lang_key",
           "description" => "team_members_desc_key",
           "associate_id" => 62,
           "channels" => [],
         ],
         [
           "name" => "team_leads_lang_key",
           "description" => "team_leads_desc_key",
           "associate_id" => 63,
           "channels" => [],
         ],
         [
           "name" => "requester_lang_key",
           "description" => "requester_desc_key",
           "associate_id" => 64,
           "channels" => [
             1,
           ],
         ],
         [
           "name" => "assigned_agent_lang_key",
           "description" => "assigned_agent_desc_key",
           "associate_id" => 65,
           "channels" => [
             1,
           ],
         ],
       ],
     ],
]

//NOTE
associate_id and channel_id are important for updating the settings.

To check usage, see the below reference files

Backend API formatting

  • app/Http/Controllers/Admin/helpdesk/StatusController
  • app/Http/Controllers/Common/TicketsWrite/ApiEnforcerController
  • app/Traits/EnforcerHelper

Frontend usage

  • StatusCreateEdit.vue
  • SlaCreateEdit.vue

postModuleAlertSettings

Use this method to update the custom notification settings by the module. The method required the id of the custom module entity, E.g., ticket status id as the first parameter and an array in a proper format containing settings details for channels and receivers.

NotifyModule::postModuleAlertSettings([
    [
        "associate" => "59"
        "channels" => [
            [
                "channel_id" => 1
            ]
        ]
    ], [
        "associate" => "60"
        "channels" => []
    ], [
        "associate" => "61"
        "channels" => []
    ], [
        "associate" => "62"
        "channels" => []
    ], [
        "associate" => "63"
        "channels" => []
    ], [
        "associate" => "64"
        "channels" => [
            [
                "channel_id" => 1
            ]
        ]
    ], [
        "associate" => "65"
        "channels" => [
            [
                "channel_id" => 1
            ]
        ]
    ]
])
//Note
associate is the same as associate_id and channel_id recived from the getModuleAlertSettings

To check usage, see the below reference files.

For posted API response and formatting before the method call

  • app/Http/Controllers/Admin/helpdesk/StatusController
  • app/Notify/Controllers/NotifyFoundation/NotifyModuleController
  • app/Traits/EnforcerHelper

For payload, send in the API from frontend

  • StatusCreateEdit.vue
  • SlaCreateEdit.vue

To understand API response and payload, check SLA and ticket status settings page.

Dispatch Notify event for processing notifications.

notify

NotifyModule offers a simple method that modules can utilize to send notifications without worrying about checking the settings,  who are the receivers of the notifications and which templates to use for the notifications. Module authors can tweak the arguments for the method to modify the behavior of notification processing. Notify module accepts the following parameters

  • event (string): name of the event, e.g., ticket creation
  • scenarios (array): underlying scenarios for the event, e.g., ticket creation acknowledgment and ticket creation alert
  • payloadData (array): array which modules must pass with different required and optional keys as explained below
    • eventModel (model): A model for which we send notifications, for example, tickets, users, etc. (required)
    • variables (array): Array containing key and values of shortcodes for replacing in the templates. (required)
    • actor (user model/null): detail of user acting. (optional)
    • action_link (string): Needed if notification will have an entry for in-app. (optional)
    • notify_queue (string): Queue name to dispatch notify event. Module authors can pass their custom names, but the queue processing command needs to be modified accordingly. (optional)
    • person type (collection of users): For notifying custom users or specific users, pass the type name and user collection. See App\Listeners\ReportExportListener (optional)
    • notifying_department (integer id): Id of the department to resolve outgoing email. (optional)
    • attachments: For sending attachments like images and files. (optional)
    • send_to_actor (boolean): Decides whether the actor will receive the notification or not. (optional)
  • customModel (Model): required if notifying for custom settings events like ticket status change or SLA escalations.
  • channels (array): optional parameter to explicitly restrict the notification to send on specific channels.

Module authors can fire the notify event using the facade method wherever required in the module, ensuring the payload is following the contract. Search NotifyModule::notify throughout the project for code-level understanding.

//notify event firing for new user registration in AuthController
NotifyModule::notify('new_user_registration_confirmation', ['new_user_registration_confirmation'], [
    'eventModel' => $user,
    'variables' => ['new_user_name' => $user->full_name, 'new_user_email' => $user->email, 'user_password' => $passwordString],
]);

 

Summary

Module authors can use methods offered by NotifyModule to add new notifications. They must follow the contract to provide required information for adding and processing notifications via Notify.