Skip to main content
Version: 13.x (Current)

Notification Manager Usage

This sections illustrates how to use the Notification Manager.

As you may recall from the overview you can send notifications in two different ways:

  • manually: by sending a request to the POST /send endpoint, passing the channels, recipients, template, … in the request body;
  • automatically when specific events occur, by calling the POST /notification-events.

You can create, update or delete notification settings through the endpoints described in the following section:

HTTP API

POST /send

With this API you can send a new message to your users through different channels.

Request

The body of the request should have the following shape.

  • channels (required) - array of strings: list of channels you want to send you message over. Possible values are email, sms, push, voice and whatsapp.
caution

This list has to be a subset of the activeChannels property specified in the service configuration.

  • recipients - array of string: list of unique identifiers of the users you want to send your messages to. Required if clusters is not defined.

  • clusters - array of string: users' clusters you want to send your messages to. Required if recipients is not defined.

  • messageTitle - string: title of the message. It will be used as title for e-mails and push notifications. Required if templateId is not defined. It will be ignored if templateId is defined. It supports interpolation.

  • messageContent - string: content of the message. It will be used as content for e-mails, sms, push and voice notifications. Required if templateId is not defined. It will be ignored if templateId is defined. It supports interpolation.

  • templateId - ObjectId: id of the template to be used for composing the message. Required if messageTitle and messageContent are not defined, or, if you are sending a Whatsapp message.

  • data - object: data used for messages interpolation.

  • emailAttachments - array of strings: list of filenames that should be sent as mail attachments. The filename must be the same as that used in the file service to download it. It is possible to send attachments no larger than 15 MB. If no File Service is declared in the environment variables an error will be thrown.

    :::tip If you use a template in which some attachments are listed, they will be merged with the attachments specified in the emailAttachments property of the request body (i.e. both the attachments specified in the template and in the body will be sent.) :::

  • emailCarbonCopies - array of strings: list of email addresses that should be included as carbon copies (CC). Any invalid email addresses will be ignored. Available since version 1.4.0.

  • emailBlindCarbonCopies - array of strings: list of email addresses that should be included as blind carbon copies (BCC). Any invalid email addresses will be ignored. Available since version 1.4.0.

  • emailSender - string: email address of the message sender. This value overwrites the email set in the service configuration. Available since version 2.1.0.

Response

Exceptions

If something goes wrong during the request, the response will have a 4xx or 5xx status code and the following payload:

{
"statusCode": "400",
"error": "Bad request",
"message": "Exception description"
}

Success

A successful response (status code 200) is issued if the process of messages sending starts without errors. However, it is still possible that the dispatch of some messages to some users fails on some channels. The body of the response will contain a list of those failures, with a brief explanation of the error, if applicable.

{
"failures": [
{
"userId": "auth0|userId",
"channel": "whatsapp",
"error": "Error: Missing required template name for WhatsApp message"
}
]
}

POST /saga/send

With this API you can send a new message to your users through different channels directly with a Flow manager command. You should avoid calling this endpoint in a different way.

Body

It has the same structure of a Flow Manager command.

Response

Exceptions

If something goes wrong during the request, the response will have a 4xx or 5xx status code and the following payload:

{
"statusCode": "400",
"error": "Bad Request",
"message": "Exception description"
}

Moreover, if enabled by configuration, it sends an event with failEventlabel as messageLabel and empty messagePayload.

Success

A successful response (status code 200) with an empty body is issued if the process of messages sending starts without errors.

Moreover, if enabled by configuration, it sends an event with successEventlabel as messageLabel and empty messagePayload.

POST /notification-events/

caution

v2.3.0. Since v2.3.0 the endpoint accepts arbitrary fields in the request body JSON object, that are automatically merged inside the event payload. If a field with the same name already exists in the event payload, the corresponding value will be overwritten.

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint allows you to notify that an event occurred and trigger the sending of notifications according to the notification settings.

This endpoint takes care of routing the request to the appropriate handler depending on the event:

  1. if a custom handler is registered for the event, the event payload will be passed to the registered handler;
  2. if no custom handler is registered for the event, the event payload will be passed to a default handler, if available;
  3. otherwise, the event will be considered as not processable, a response with 400 status code will be returned and and a record will be created in the events CRUD.
danger

The event settings are loaded once at startup, so please note that, if you change anything in the event settings CRUD, including updating the handler name or schema or deleting the settings entirely, the effects will be visible only after the service has been restarted.

After an handler is found, the event is validated against its schema. All default events have a schema to be validated against, but it is not mandatory to provide a schema for custom events; if none is specified in the corresponding Event settings document, no validation is performed.

This endpoint creates a record in the notifications CRUD you can later query using the returned _id to check the actual messages sent to the users on the various channels.

Request body

The request body must be a JSON object with the fields described in the the following table.

NameTypeRequiredDescription
namestringYesEvent name.
idstringNoEvent identifier (must be unique across the system).
keystringNoEvent key (ID of the main resource associated to the event, like an appointment or plan).
metadataObjectNoEvent metdata, to provide additional details to the event handler.
payloadObjectNoEvent payload

Response

A successful response (status code 200) is issued if the notifications were processed without errors. However, it is still possible that the dispatch of some messages to some users fails on some channels. The body of the response will contain the list of the notifications sent, to allow the client to check if failures occurred sending the messages.

{
"_id": "ID of the notification created in the notifications CRUD",
"notifications": []
}

If there is no handler available to process the event, the response will return a 400 status code and a payload looking like this:

{
"statusCode": "400",
"error": "Bad Request",
"message": "Unknown event"
}

If any other error occurs, the response will return a 4xx or 5xx status code and a payload looking like this:

{
"statusCode": "400",
"error": "Bad Request",
"message": "Error description"
}

GET /notifications/

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the GET / endpoint of the notifications CRUD.

GET /notifications/count

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET /count endpoint of the notifications CRUD.

GET /notifications/:id

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the GET /:id endpoint of the notifications CRUD.

GET /notification-settings/

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the GET / endpoint of the notification settings CRUD.

GET /notification-settings/:id

This endpoint is a proxy to the GET /:id endpoint of the notification settings CRUD.

GET /notification-settings/count

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET /count endpoint of the notification settings CRUD.

PATCH /notification-settings/:id

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the PATCH /:id endpoint of the notification settings CRUD.

A valid notification setting must satisfy the following conditions:

  • No multiple notification settings are allowed with the same combination of event name, template name and users selectors;
  • All the notification settings channels must be enabled at the service or event level;
  • The notification settings template must exist and must support all the selected channels
  • The hours field must not have duplicated values
  • The emitters field must not have duplicated values
  • The reminders field must not have duplicated values

POST /notification-settings/

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the POST / endpoint of the notification settings CRUD.

A notification setting can target any combination of a single user, group, role or cluster, which means that any combination of the following fields can be set in the request body: user, cluster, role or group.

A valid notification setting must satisfy the following conditions:

  • No multiple notification settings are allowed with the same combination of event name, template name and users selectors;
  • All the notification settings channels must be enabled at the service or event level;
  • The notification settings template must exist and must support all the selected channels
  • The hours field must not have duplicated values
  • The emitters field must not have duplicated values
  • The reminders field must not have duplicated values

DELETE /notification-settings/:id

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint is a proxy to the DELETE /:id endpoint of the notification settings CRUD.

GET /user-notification-settings/

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint returns the notification settings of the logged user, meaning those that match at least one of the following conditions:

  • the user field contains the user ID;
  • the group field contains a group the user belongs to;
  • the role field contains a role assigned to the user;
  • the cluster field contains a cluster the user belongs to.

The endpoint request and response specifications are the same as for the GET /notification-settings/ endpoint. The endpoint does not support pagination, so it can only return the first 200 results.

PATCH /user-notification-settings/:id

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint allows the logged user to edit the notification settings having its user ID in the user field.

caution

Since the logged user can only modify his/her own settings, the notification setting user can not be updated through this endpoint. Any attempt to do so will result in a response with a 400 HTTP status code.

The endpoint request and response specifications are the same as for the PATCH /notification-settings/:id endpoint.

DELETE /user-notification-settings/:id

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint allows the logged user to delete a notification setting having its user ID in the user field.

The endpoint request and response specifications are the same as for the DELETE /notification-settings/:id endpoint.

GET /user/events/

info

v2.1.0. The response schema has been updated and is not compatible with previous versions.

info

v2.0.0. This endpoint is available only since v2.0.0.

This endpoint returns the event settings that apply to events visible to the logged user.

If a default event has no settings, it will be considered visible to all users and the supported channels will include all the active channels from the service configuration.

An event is visible to the user if and only if the user belongs to at least one of the groups listed in the userGroups fields of the CRUD for an event or no userGroups is specified.

The supported channels are automatically filtered to be a subset of the active channels from the service configuration.

The enabled channels are automatically filtered to be a subset of the supported channels.

Response

If the request is processed correctly, the service returns a response with a 200 status code and a list of events looking like this:

[
{
"eventName": "AM/AppointmentCreated/v1",
"supportedChannels": [
"voice",
"push"
],
"enabledChannels": [
"voice"
]
}
]

Each event has the properties described in the following table.

NameTypeDescription
eventNamestringName of the event.
supportedChannelsstring[]The supported channels from the event settings CRUD or the active channels from the service configuration.
enabledChannelsstring[]The channels enabled for the event in the notification settings targeting the user.

PATCH /user/notification-settings/

info

v2.1.0. This endpoint is available only since version 2.1.0.

Update all the notification settings targeting a specific event and user (and optionally roles, groups and clusters).

If no user notification settings is updated, a new one is created targeting the given event and user. The template name will be inherited from the notification settings with highest precedence that targets the user group, role or cluster.

Request

The request body must provide the event name (eventName) and the list of enabled channels (enabledChannels).

{
"eventName": "AM/AppointmentCreated/v1",
"enabledChannels": ["email", "sms"]
}

For each notification setting targeting the logged user and the given event, the channels (channels) are overwritten with the enabled channels.

Response

If the request is processed correctly, the endpoint returns a 200 HTTP status code and a response containing the number of notification settings updated.

If the service encounters an error processing the request, it responds with the appropriate status code (3xx, 4xx or 5xx) and a JSON body looking like this:

{
"statusCode": "500",
"error": "Internal Server Error",
"message": "An error occurred while processing the request"
}

Here are the most common errors:

  • if the user is not authenticated, the service returns a 401 (Unauthorized) error;
  • if the event is not visible to the user, the service returns a 403 (Unauthorized) error;
  • if the user tries to enable an unsupported channel, the service returns a 400 (Bad Request) error;
  • if a new user notification settings must be created but there are no notification settings to inherit the template name from, the service returns a 400 (Bad Request) error.

GET /event-settings

info

v2.1.0. This endpoint is available only since v2.1.0.

This endpoint is a proxy to the GET / endpoint of the event settings CRUD.

DELETE /event-settings/:id

info

v2.1.0. This endpoint is available only since v2.1.0.

The endpoint provides a way to delete event settings without the need to restart the microservice in order to register the change.

This endpoint acts as a proxy to the DELETE /:id endpoint of the event settings CRUD.

After deleting successfully the event settings, the routing table is automatically updated, restoring the default handler for the event, if available.

POST /event-settings

info

v2.1.0. This endpoint is available only since v2.1.0.

The endpoint provides a way to create new event settings without the need to restart the microservice in order to register them.

This endpoint acts as a proxy to the POST / endpoint of the event settings CRUD

After inserting successfully an event settings in the CRUD, the routing configuration is automatically updated if any of the following fields are set in the new event settings:

  • eventSchema
  • handlerName
  • handlerConfig

Since the event settings must be unique for a given event, identified by the eventName field, the endpoint does not create a new record and returns 409 when an event settings for the same event already exists.

PATCH /event-settings/:id

info

v2.1.0. This endpoint is available only since v2.1.0.

The endpoint provides a way to update an event settings without the need to restart the microservice in order to register the changes.

This endpoint acts as a proxy to the PATCH /:id endpoint of the event settings CRUD

After updating successfully an event settings in the CRUD, the routing configuration is automatically updated if any of the following fields are updated in the new event settings:

  • eventSchema
  • handlerName
  • handlerConfig

GET /templates/

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET / endpoint of the templates CRUD.

GET /templates/count

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET /count endpoint of the templates CRUD.

GET /templates/:id

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET /:id endpoint of the templates CRUD.

POST /templates/

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the POST / endpoint of the templates CRUD.

A valid template must satisfy the following conditions:

  • it must have a unique name;
  • only one among emailMessage and emailHtmlMessage fields can be defined;
  • if the pushData field is set, pushTitle, pushSubtitle and pushMessage must not be defined;
  • if pushTitle, pushSubtitle and/or pushMessage are set, pushData must not be set.

PATCH /templates/:id

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the PATCH /:id endpoint of the templates CRUD.

A valid template must satisfy the following conditions:

  • it must have a unique name;
  • only one among emailMessage and emailHtmlMessage fields can be defined;
  • if the pushData field is set, pushTitle, pushSubtitle and pushMessage must not be defined;
  • if pushTitle, pushSubtitle and/or pushMessage are set, pushData must not be set.

DELETE /templates/:id

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the DELETE /:id endpoint of the templates CRUD.

POST /templates/state

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the POST /state endpoint of the templates CRUD.

GET /notification-messages/

caution

This endpoint is available in preview, breaking changes could be introduced in next minor versions. Please check the CHANGELOG before upgrading.

info

v2.4.0. This endpoint requires the Notification Messages MongoDB view.

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET / of Notification Messages MongoDB view and returns the messages matching the given query.

Given a notification like this:

{
"_id": "663ccd65dee93b2a6a6885d1",
"event": "Update appointment"{
"_id": "663ccd63dee93b2a6a6885d0",
"name": ,
"payload": {
"recipient": "663ccce5dee93b2a6a6885ty",
"templateName": "update-appointment"
},
"source": {
"channel": "http",
"requestId": "6e4ddc4eda4ce1f422b285a80da3128a"
},
"status": "RECEIVED"
},
"recipient": "663ccce5dee93b2a6a6885ty",
"messages": [
{
"channel": "email",
"templateName": "new-appointment",
"status": "SUCCESS"
},
{
"channel": "sms",
"templateName": "new-appointment",
"status": "FAILED"
}
]
}

the following messages would be returned:

[
{
"_id": "663ccd65dee93b2a6a6885d1-fea80f2db003d4ebc4536023814aa885",
"event": "Update appointment",
"recipient": "663ccce5dee93b2a6a6885ty",
"channel": "email",
"templateName": "new-appointment",
"status": "SUCCESS"
},
{
"_id": "663ccd65dee93b2a6a6885d1-0956d2fbd5d5c29844a4d21ed2f76e0c",
"event": "Update appointment",
"recipient": "663ccce5dee93b2a6a6885ty",
"channel": "sms",
"templateName": "new-appointment",
"status": "FAILED"
},
{
"_id": "812rcd65dee93b2a6a9845z98-3a685826dee20d9afd3bc637b0615adb",
"event": "New appointment",
"recipient": "675cdse5dee93b2a6a64565rf",
"channel": "email",
"templateName": "new-appointment",
"status": "SUCCESS"
}
]

GET /notification-messages/count

caution

This endpoint is available in preview, breaking changes could be introduced in next minor versions. Please check the CHANGELOG before upgrading.

info

v2.4.0. This endpoint requires the Notification Messages MongoDB view.

info

v2.3.0. This endpoint is available only since v2.3.0.

This endpoint is a proxy to the GET /count endpoint of the Notification Messages MongoDB view and returns the number of messages matching the given query.

Custom handler API

info

v2.0.0. Custom handlers are available only since v2.0.0.

info

To set reminders you need to have an instance of the Timer Service running and the TIMER_SERVICE_URL environment variable set accordingly.

The following section provides usage details about the API you can access inside a custom handler to perform common tasks, like:

buildMessages

buildMessages(service, notificationSettings)

This function takes as input a list of notification settings and build the messages to send according to the constraint of sending at most one message with a given template on each channel.

The function clusters the notification settings according to the template name and channel and return, for each cluster, the specifications of the message to send, something like this:

{
"channel": "email",
"templateName": "doctor-new-appointment"
}

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
queryYesA list of notification settings

Return value

A list of messages specifications, where each message uses a different channel and/or template.

[
{
"channel": "email",
"templateName": "doctor-new-appointment"
},
{
"channel": "sms",
"templateName": "doctor-new-appointment"
},
{
"channel": "email",
"templateName": "patient-updated-appointment"
},
]

getNotificationSettings

async getNotificationSettings(service, event, user, emitters)

This function takes an event (required), a user (optional) and a list of emitters (optional) and return the notification settings that apply to the event and, if provided, to the given user and emitters.

A notification setting applies to an event if its eventName matches the event name (event.name).

A notification setting applies to a user if all the following conditions are satisfied:

  • if the user id (user.id) is specified, the rule must target the same user, i.e. the user field must match the user.id;
  • if the user belongs to one or more groups (user.groups), the rule must target one of these groups, i.e. the group field must match one of the values in the user.groups field;
  • if the user belongs to one or more clusters (user.clusters), the rule must target one of these clusters, i.e. the cluster field must match one of the values in the user.clusters field;
  • if the user has one or more roles (user.roles), the rule must target one of these roles, i.e. the role field must match one of the values in the user.roles field.

A notification setting applies to the given list of emitters if its emitters field contains at least one of the given emitters.

The list of notification settings is sorted according to the following precedence (from highest to lowest).

  1. user: settings targeting a specific user have precedence over rules targeting clusters, roles and/or groups;
  2. cluster: settings targeting a cluster have precedence over rules targeting roles and/or groups;
  3. role: settings targeting a role have precedence over rules targeting groups;
  4. group.

Notification settings with the same precedence (for example, rules targeting a specific user) are recursively sorted based on the precedence of the remaining fields (for example, rules targeting a user are sorted again to have rules targeting a cluster before rules targeting groups and roles and so forth).

For example, if we had some notification settings targeting:

  • a single doctor (user);
  • a single doctor (user) in a hospital (clusters);
  • all doctors (groups) in a hospital (clusters);
  • all doctors (groups) that can sign patient's discharge (roles);
  • all doctors (groups)

they would be sorted as follows:

  1. a single doctor (user) in a hospital (clusters);
  2. a single doctor (user);
  3. all doctors (groups) in a hospital (clusters);
  4. all doctors (groups) that can sign patient's discharge (roles);
  5. all doctors (groups).

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
eventYesEvent with id, name and payload
userNoA user from the users CRUD
emittersNoOne or more emitters, as an array of strings

Return value

An array of CRUD notification settings sorted by precedence (see the Overview section for further details about precedence and sorting).

The function throws an error if the CRUD service does not respond correctly or any other kind of fatal error occurs.

mergeNotificationSettings

mergeNotificationSettings(service, notificationSettings)

This function takes a list of CRUD notification settings and filters them according to the following criteria:

  1. Remove all settings with IGNORE rule;
  2. Discard the settings with SEND rule that have lower precedence;
  3. Discard the rules that define one or more sending hours not matching the current time.

The process by which precedence is given to the notification settings is explained in the getNotificationSettings method description.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
notificationSettingsYesList of Crud Notification Settings

Return value

An array of CRUD notification settings.

getRecipients

async getRecipients(service, query)

This function takes a CRUD query for the users CRUD and return the users having any of the given ids, roles, groups and clusters. If multiple filters are passed, for example ids and groups, the function returns all the user having any of the given ids and any of the given groups.

note

You can’t currently search for recipients that belongs to all the given groups, roles and/or clusters. The function currently returns the user that belongs to any group, role and cluster.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
queryYesA CRUD query object to filter CRUD users

The query can have any combination of the following fields:

{
"ids": ["john.doe", "mark.greene"],
"roles": ["sign-discharge"],
"groups": ["doctors", "administrators"],
"clusters": ["mia-care-clinic", "mia-care-hospital"]
}

Here are some examples:

  • all the doctors (groups) from an hospital (clusters);
{
"groups": ["doctors"],
"clusters": ["mia-care-center"]
}
  • all the doctors (groups) from one of the hospitals (clusters)
{
"groups": ["doctors"],
"clusters": ["mia-care-center-1", "mia-care-center-2"]
}
  • the user dr.mario.rossi (ids)
{
"ids": ["dr.mario.rossi"],
}
  • the user dr.mario.rossi (ids) with role sign-report (roles)
{
"ids": ["dr.mario.rossi"],
"roles": ["sign-report"]
}
  • all the doctors and/or administrators
{
"groups": ["doctors", "administrators"],
}

Return value

An array of CRUD users.

The function throws an error if the CRUD service does not respond correctly or any other kind of fatal error occurs.

sendMessages

info

v2.3.0. Custom attachments specified in the message attachments field will be sent if the email channel is specified.

async sendMessages(service, event, user, messages)

This functions takes as input a list of messages for a given user and event, like those generated by the buildMessages utility function, and sends them using the specified channels and templates. If one or more attachments are specified in combination with the email channel, those attachments will be sent together with template attachments. If the list of messages is empty, no record is stored in the notifications CRUD.

In the message templates you can use the following variables for interpolation:

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
eventYesAn event with id, name and payload
userYesA user from the users CRUD
messagesYesA list of notification messages with channel, template and attachments

Return value

A CRUD notification, containing all the details about the messages sent.

The function throws an error if the CRUD service returns an error or any other fatal error occurs, with a notable exception: if an error occurs sending a specific message, the error details are included in the returned notification.

sendNotification

async sendNotification(service, event, user, notification)

This function takes an event, a user and a notification setting, send all the messages and return the details about the notification sent.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
eventYesEvent with id, name and payload
userYesA user from the users CRUD
notificationYesA CRUD notification setting

Return value

A CRUD notification, containing all the details about the messages sent.

The function throws an error if the CRUD service returns an error or any other fatal error occurs, with a notable exception: if an error occurs sending a specific message, the error details are included in the returned notification.

buildReminders

buildReminders(service, user, notificationSettings, eventDateTime)

This function takes as input a list of notification settings and a user, and compute the reminders to send by merging all the values in the reminders field of the notification settings into a single set of values.

The reminders are scheduled subtracting the respective duration from the passed isoEventDate.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
userYesA user from the users CRUD
notificationSettingsYesA list of notification settings
eventDateTimeYesEvent date to compute reminders from, expressed as ISO 8601 date-time string

Return value

A list of reminders specifications, each one having an expirationDate and optionally a schedule.

, recipients[
{"schedule": "P1D", "expirationDate": "2023-06-24T09:30:00Z", "recipients": ["patientId"]},
{"schedule": "PT1H", "expirationDate": "2023-06-25T08:30:00Z", "recipients": ["doctorId"]},
]

setReminders

async setReminders(service, event, user, reminders)

This functions takes as input a list of reminders for a given user and event, like those generated by the buildReminders utility function, and schedule them by calling the Timer Service. If the list of reminders is empty, no record is stored in the notifications CRUD.

For each provided reminder, at the expiration date the Timer Service will send a request to the POST /notification-events/.

For example, if we have the following reminder:

{
"expirationDate": "2023-09-02T09:30:00.000Z",
"schedule": "P1D",
"recipients": ["customer-id"],
"triggers": ["notification-setting-12345"]
}

the body of the request sent to the Timer Service would look like this:

{
"payload": {
"id": "f5a9ed5f-c6c2-44e6-85a4-1bd64458a4c0",
"key": "order-12345",
"name": "ACME/OrderCreated/v1",
"metadata": {
"reminder": {
"expirationDate": "2023-09-02T09:30:00.000Z",
"schedule": "P1D",
"recipients": ["customer-id"],
"triggers": ["notification-setting-12345"]
}
},
"payload": {},
"source": "http",
"status": "PROCESSED"
},
"startDate": "2023-09-02T09:30:00.000Z",
"expirationIntervalMs": 1,
"applicantService": "notification-manager",
"outputMode": {
"type": "rest",
"method": "post",
"protocol": "http",
"hostname": "https://www.example.com/notification-manager",
"path": "/notification-events/",
},
}
danger

If the original event had a reminder field in the metadata section, its original value would be overwritten by the given notification reminder object.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
eventYesEvent with id, name and payload
userYesA user from the users CRUD
remindersYesA CRUD notification setting

Return value

A notification, containing all the details about the scheduled reminders in the reminders field.

If an error occurs scheduling a specific reminder, the error details are included in the returned notification.

If an error occurs saving the notification into the CRUD, an error is thrown and the client can decide how to handle it.

abortReminders

async abortReminders(service, event, user, query)

This function searches for the reminders matching the given event, user and query and abort all the active reminders.

  1. Fetch the notifications that satisfy the following conditions:
    1. the event name matches any of the query.eventName, if provided;
    2. the event key matches the event.key;
    3. the participant matches the user.id;
    4. there is at least one reminder.
  2. For each notification, filter the reminders that satisfy the following conditions:
    1. the status field is ACTIVE;
    2. the expirationId field is set.
  3. For each active reminder, call the POST /abort endpoint of the Timer Service:
    1. if the Timer Service returns a successfull response, set the reminder status to ABORTED;
    2. if the Timer Service returns an error, catch it and leave the reminder status to ACTIVE.
  4. Update the notification reminders in the CRUD.

Parameters

Parameter nameDescription
serviceFastify decorated instance
eventEvent with id, name and payload
userA user from the users CRUD
queryAn object containing a list of event names that should be included in the search

Here's an example of a query to abort reminders related to the ACME/OrderCreated/v1 and ACME/OrderShipped/v1 events:

{
"eventName": ["ACME/OrderCreated/v1", "ACME/OrderShipped/v1"]
}

Return value

An array of updated notifications.

mergeNotifications

mergeNotifications(service, event, user, notifications)

This function merges one or more notifications referring a given user and event, by creating a new notification for the given user and event with all the messages, reminders and failures from all the given notifications.

Parameters

Parameter nameRequiredDescription
serviceYesFastify decorated instance
eventYesNotification event
userYesA user from the users CRUD
notificationsYesAn array of CRUD notification settings

Return value

This function returns a new notification for the given user and event with all the messages, reminders and failures from all the given notifications. If no notification is provided, a new notification with zero messages, reminders and failures is returned. If exactly one notification is provided, the exact same notification is returned.

Event handlers

This section illustrates how events are processed by the default handlers available in the Notification Manager.

All the events mentioned in the following sections follow this naming convention:

<product>/<event>/<version>

where:

  • product represent the name, usually abbreviated and in upper case, of the Mia Care product for which the event was originally designed, like AM (Appointment Manager) or TMM (Therapy and Monitoring Manager);
  • event: the name, usually in camel case, of the event, like appointment created (AppointmentCreated) or therapy updated (TherapyUpdated);
  • version: the version of the event, which should be incremented every time a breaking change to the metadata or payload schema is introduced.
tip

You can override a default event handlers by providing a custom handler for any of the events discussed below.

AM/AppointmentCreated/v1

This event is fired when a new appointment is created in the AM and it looks like this:

{
"name": "AM/AppointmentCreated/v1",
"key": "appointment-12345",
"metadata": {
"userFields": ["resourceId", "participantIds"]
},
"payload": {
"startDate": "2023-08-01T09:30:00Z",
"endDate": "2023-08-01T10:15:00Z",
"resourceId": "auth0|dr.mario.rossi",
"participantIds": [
"auth0|jenny.king",
"auth0|dr.mark.greene"
],
"...": "..."
}
}

When the handler receives such an event it performs the following operations:

  1. retrieve the list of participant IDs from the metadata.userFields and fetch the users details by calling the getRecipients utility function;
  2. for each participant:
    1. fetch the notification settings that applies by calling the getNotificationSettings utility function
    2. merge the notification settings by calling the mergeNotificationSettings utility function
    3. get the messages to send by calling the buildMessages utility function
    4. send the messages by calling the sendMessages utility function
    5. get the reminders to send by calling the buildReminders utility function
    6. set the reminders by calling the setReminders function and passing an event with the same payload and metadata of the original, but with name AM/AppointmentReminder/v1

AM/AppointmentReminder/v1

After an appointment is created or updated and the reminders scheduled, the Timer Service sends to the NM at the appropriate times a new event named AM/AppointmentReminder/v1. The event looks like this:

{
"name": "AM/AppointmentReminder/v1",
"metadata": {
"reminder": {
"schedule": "PT1H",
"expirationDate": "2022-06-04T23:00:00Z",
"recipients": ["auth0|dr.mark.greene"]
},
"userFields": ["resourceId", "participantIds"]
},
"payload": {
"startDate": "2023-08-01T09:30:00Z",
"endDate": "2023-08-01T10:15:00Z",
"resourceId": "auth0|dr.mario.rossi",
"participantIds": [
"auth0|joe.hart",
"auth0|dr.mark.greene"
],
"...": "..."
}
}

The event should include in the metadata.reminder field the schedule that triggered this event. The value is a time duration expressed as ISO 8601 duration string.

When the handler receives such an event it performs the following operations:

  1. retrieve the list of participant IDs from the event.metadata.reminder.participants field and fetch the users detail by calling the getRecipients function;
  2. for each participant:
    1. fetch the notification settings that applies by calling the getNotificationSettings function;
    2. filter the notification settings having the event.metadata.reminder.schedule among the reminders, if provided;
    3. merge the notification settings by calling the mergeNotificationSettings utility function
    4. build the messages to send by calling the buildMessages utility function
    5. send the messages by calling the sendMessages utility function

AM/AppointmentDeleted/v1

When an appointment is deleted the AM sends to the NM a new event named AM/AppointmentDeleted/v1 that looks like this:

{
"name": "AM/AppointmentDeleted/v1",
"metadata": {
"userFields": ["resourceId","participantIds"]
},
"payload": {
"startDate": "2023-08-01T09:30:00Z",
"endDate": "2023-08-01T10:15:00Z",
"resourceId": "auth0|dr.mario.rossi",
"participantIds": [
"auth0|mary.shelley",
"auth0|dr.mark.greene"
],
"...": "..."
}
}

When the handler receives such an event it performs the following operations:

  1. retrieve the list of participant IDs from the metadata.userFields and fetch the users details by calling the getRecipients utility function;
  2. for each user:
    1. fetch the notification settings that apply by calling the getNotificationSettings utility function;
    2. merge the notification settings by calling the mergeNotificationSettings utility function
    3. get the messages to send by calling the buildMessages utility function
    4. send the messages by calling the sendMessages utility function
    5. abort all active reminders scheduled when the appointment was created or updated by calling the abortReminders utility functions.

AM/AppointmentUpdated/v1

This event is triggered by an update to an appointment that is performed by a request to the PATCH /appointments/:id of the Appointment Manager. The event looks like this:

{
"name": "AM/AppointmentUpdated/v1",
"metadata": {
"userFields": ["resourceId","participantIds"]
},
"payload": {
"originalAppointment": {
"startDate": "2023-08-01T09:30:00Z",
"endDate": "2023-08-01T10:15:00Z",
"resourceId": "auth0|dr.mario.rossi",
"participantIds": [
"auth0|lucia.verdi",
"auth0|dr.luigi.rossi"
],
"...": "..."
},
"currentAppointment": {
"startDate": "2023-08-01T09:30:00Z",
"endDate": "2023-08-01T10:15:00Z",
"resourceId": "auth0|dr.mario.rossi",
"participantIds": [
"auth0|lucia.verdi",
"auth0|dr.marta.rossi"
],
"...": "..."
}
}
}

When the handler receives such an event it performs the following operations:

  1. retrieve the list of participant IDs from the metadata.userFields and fetch the users details;
  2. cluster the participant IDs in the following groups:
    1. new participants: if the user ID is in the updated appointment, but not in the original;
    2. existing participants: if the user ID is in both the updated and original appointment;
    3. deleted participants: if the user ID is in the original appointment, but not in the updated version;
  3. for each participant:
    1. fetch the notification settings that apply by calling the getNotificationSettings utility function with the correct event:
      1. for new participants, AM/AppointmentCreated/v1 as event name and the updated appointment as payload;
      2. for existing participants, the original event;
      3. for deleted participants, AM/AppointmentDeleted/v1 as event name and the original appointment as payload;
    2. merge the notification settings by calling the mergeNotificationSettings utility function;
    3. for deleted participants, and for existing participants if the appointment has been rescheduled, abort the reminders by calling the abortReminders utility function;
    4. get the messages to send by calling the buildMessages utility function;
    5. send the messages by calling the sendMessages utility function with the correct event:
      1. for new participants, AM/AppointmentCreated/v1 as event name and the updated appointment as payload;
      2. for existing participants, the original event;
      3. for deleted participants, AM/AppointmentDeleted/v1 as event name and the original appointment as payload;
    6. for new participants, and for existing participants if the appointment has been rescheduled:
      1. get the reminders to send by calling the buildReminders utility function;
      2. set the reminders by calling the setReminders function and passing an event with the updated appointment as payload and name AM/AppointmentReminder/v1.

IC/ResourceForbiddenEvent/v1

This event is fired when a resource integrity violation is detected by the [IC][integrity-checker] and the event looks like this:

{
"id": "8f77103f-9466-418b-b9e9-478054f82900",
"key": "medical-reports/628fa7713d35760c790b8f30",
"name": "IC/ResourceForbiddenEvent/v1",
"payload": {
"collectionName": "medical-reports",
"resourceUuid": "628fa7713d35760c790b8f30",
"operation": {
"updatedFields": {
"signedDocument": "61669154bea7010012c9ebd2.pdf"
}
},
"resource": {
"_id": "628fa7713d35760c790b8f30",
"creatorId": "auth0|dr.lucia.viola",
"createdAt": "2022-05-26T16:14:41.621Z",
"updaterId": "auth0|dr.andrea.rossi",
"updatedAt": "2022-05-26T16:14:41.621Z",
"__STATE__": "PUBLIC",
"formSchemaId": "628f6ec74301f05c9d3c9257",
"signedDocument": "61669154bea7010012c9ebd2.pdf",
"data": {},
"uuid": "KGWfJ31BL4mgVpu"
}
}
}

When the handler receives such an event it performs the following operations:

  1. fetch the notification settings that apply to the event by calling the getNotificationSettings utility function;
  2. merge the notification settings by calling the mergeNotificationSettings utility function;
  3. fetch all the users targeted by the notification settings;
  4. for each user:
    1. build the messages to send by calling the buildMessages utility function;
    2. send the messages by calling the sendMessages utility function;

TMM/MonitoringCreated/v1

This event is fired when a new monitoring plan is created in the TMM and the event looks like this:

{
"id": "06efe38d-0e46-4863-9bb4-4c11ff63c912",
"key": "blood-pressure-monitoring-12345",
"name": "TMM/MonitoringCreated/v1",
"metadata": {
"excludeUsers": ["jill.marlowe"],
"includeUsers": ["dr.john.watson"]
},
"payload": {
"planName": "Blood pressure monitoring",
"prototypeId": "bloodPressure",
"notes": "Takes the blood",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mark.greene",
"patientId": "jill.marlowe",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
"thresholds": [
{
"propertyName": "minimumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 60
},
{
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
}
]
}
}

When the handler receives such an event it performs the following operations:

  1. fetch the details of the doctor and patient by calling the getRecipients utility function and passing the values of the doctorId and patientId as ids;
  2. remove the users in metadata.excludeUsers from the participants;
  3. add the users in metadata.includeUsers to the participants;
  4. for each user:
    1. fetch the notification settings by calling the getNotificationSettings utility function;
    2. merge the notification settings by calling the mergeNotificationSettings utility function;
    3. get the messages to send by calling the buildMessages utility function and passing the merged notification settings as argument;
    4. send the messages by calling the sendMessages utility function;
    5. compute the first event date according to the monitoring plan;
    6. build the reminders by calling buildReminders;
    7. schedule the reminders by calling the setReminders for the TMM/MonitoringReminder/v1 event;
    8. merge the user notifications by calling the mergeNotifications.

TMM/MonitoringDeleted/v1

This event is fired when a monitoring plan is deleted in the TMM and the event looks like this:

{
"id": "da03558a-f283-4d9b-b1c7-50282716802c",
"key": "blood-pressure-monitoring-12345",
"name": "TMM/MonitoringDeleted/v1",
"metadata": {
"excludeUsers": ["lucy.heart"],
"includeUsers": ["dr.john.watson"]
},
"payload": {
"planName": "Blood pressure monitoring",
"prototypeId": "bloodPressure",
"notes": "Takes the blood",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mark.greene",
"patientId": "lucy.heart",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
"thresholds": [
{
"propertyName": "minimumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 60
},
{
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
}
]
}
}

When the handler receives such an event it performs the following operations:

  1. add the doctor (payload.doctorId) and patient (payload.patientId) to the list of notification recipients;
  2. add the user IDs in the metadata.includeUsers field to the recipients list, if present;
  3. remove the user IDs in the metadata.excludeUsers field from the recipients list, if present;
  4. for each recipient:
    1. fetch and merge the notification settings that applies to the given event and participant;
    2. build and send the messages to the participant;
    3. abort all active reminders scheduled when the monitoring was created or updated or a recurring reminder was set.

The fourth step relies on the notification utils available in all handlers to perform most of the operations.

TMM/MonitoringUpdated/v1

This event is fired when a monitoring plan is updated in the TMM and the event looks like this:

{
"name": "TMM/MonitoringUpdated/v1",
"metadata": {
"excludeUsers": ["dr.mario.rossi"],
"includeUsers": []
},
"payload": {
"originalMonitoring": {
"planName": "Blood pressure monitoring",
"prototypeId": "bloodPressure",
"notes": "Takes the blood",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mario.rossi",
"patientId": "lucia.viola",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
"thresholds": [
{
"propertyName": "minimumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 60,
},
{
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
}
]
},
"currentMonitoring": {
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-07-01T00:00:00Z",
"each": ["monday", "wednesday", "friday"],
"doctorId": "dr.andrea.verdi",
"patientId": "lucia.viola",
"...": "...",
}
}
}

The payload must have both the original and the updated version of the monitoring plan, in order for the handler to correctly identify the messages to send and the reminders to abort or schedule. In the example above, we are both changing the participants (doctorId) and the plan schedule (endDate, each).

When the handler receives such an event it performs the following operations:

  1. cluster the user IDs (doctorId, patientId) in three groups:
    1. new participants: if the user ID is in the updated monitoring, but not in the original;
    2. existing participants: if the user ID is in both the updated and original monitoring;
    3. old participants: if the user ID is in the original monitoring, but not in the updated version;
  2. add the user IDs in the metadata.includeUsers field to the list of existing recipients, if present;
  3. remove the user IDs in the metadata.excludeUsers field from any recipients list, if present;
  4. fetch the user details of all the participants;
  5. for each new participant, using TMM/MonitoringCreated/v1 as event name and the updated monitoring as payload:
    1. fetch and merge the notification settings that applies to the event;
    2. build and send the messages to the participant;
  6. for each old participant, using TMM/MonitoringDeleted/v1 as event name and the original monitoring as payload:
    1. fetch and merge the notification settings that applies to the event;
    2. build and send the messages to the participant;
    3. abort all active reminders scheduled when the monitoring was created or previously updated;
  7. for each existing participant:
    1. fetch and merge the notification settings that applies to the given event and participant;
    2. build and send the messages to the participant;
    3. abort all active reminders scheduled when the monitoring was created or updated;
    4. build and schedule all the reminders, using TMM/MonitoringReminder/v1 as reminder event name and the current appointment as payload.

The last four steps rely on the notification utils available in all handlers to perform most of the operations.

TMM/MonitoringReminder/v1

This event is fired when the patient is notified about an ongoing monitoring plan in the TMM and the event looks like this:

{
"id": "06efe38d-0e46-4863-9bb4-4c11ff63c912",
"key": "blood-pressure-monitoring-12345",
"name": "TMM/MonitoringReminder/v1",
"metadata": {
"reminder": {
"schedule": "PT1H",
"expirationDate": "2022-06-04T23:00:00Z",
"recipients": ["jill.marlowe"]
}
},
"payload": {
"planName": "Blood pressure monitoring",
"prototypeId": "bloodPressure",
"notes": "Takes the blood",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mark.greene",
"patientId": "jill.marlowe",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
"thresholds": [
{
"propertyName": "minimumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 60
},
{
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
}
]
}
}

This handler automatically schedules the next reminder according to the following criteria:

  • if the plan has a daily schedule (the each field contains day), the reminders are sent at the beginning of each day;
  • if the plan has a weekly schedule (the each field contains one or more weekdays, like monday or friday), the reminders are sent at the beginning of each day of the week specified in the plan.

The reminders are scheduled if and only if the monitoring plan is still active on a given day and are sent the desired time before midnight UTC, for example one hour.

tip

The notification settings for monitoring reminders should set a single reminder no more than a few hours before each day the patient needs to take action, particularly if the plan has a daily schedule.

Given the monitoring plan shown above, for example, and the following notification setting:

{
"eventName": "TMM/MonitoringReminder/v1",
"channels": ["email", "sms"],
"templateName": "patient-monitoring-reminder",
"user": "jill.marlowe",
"reminders": ["PT1H"]
}

we would send the following reminders:

  • May 31st, 2022 at 23:00 UTC (reminder for June 1st, one hour earlier than midnight UTC);
  • June 1st, 2022 at 23:00 UTC (reminder for June 2nd, one hour earlier than midnight UTC);
  • etc.
  • June 14th, 2022 at 23:00 UTC (reminder for June 15th, one hour earlier than midnight UTC).

When the handler receives such an event it performs the following operations:

  1. add the user IDs from the reminder recipients (metadata.reminder.recipients) to the list of notification recipients;
  2. for each recipient:
    1. fetch and merge the notification settings that apply to the given event and user;
    2. filter the notification settings whose reminders field contains the reminder schedule (metadata.reminders.schedule);
    3. build and send the messages to the participant;
    4. build and schedule the next reminders, according to the notification settings and using the same event.

TMM/ThresholdExceeded/v1

This event is fired when a detection submitted by a patient exceeds one or more thresholds associated to a monitoring plan in the TMM and the event looks like this:

{
"id": "f303f2e9-f37b-4565-91e4-628e36872df5",
"key": "blood-pressure-monitoring-12345",
"name": "TMM/ThresholdExceeded/v1",
"payload": {
"plan": {
"planName": "Blood pressure monitoring",
"prototypeId": "bloodPressure",
"notes": "Takes the blood",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "auth0|doctorId",
"patientId": "auth0|patientId",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
"thresholds": [
{
"propertyName": "minimumBloodPressure",
"thresholdOperator": "lt",
"thresholdValue": 80
},
{
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
}
]
},
"detection": {
"planType": "monitoring",
"planId": "blood-pressure-monitoring-12345",
"isCompliant": true,
"value": {
"minimumBloodPressure": 80,
"maximumBloodPressure": 130
},
"observedAt": "2022-06-01T10:00:00.000Z",
"doctorId": "auth0|doctorId",
"patientId": "auth0|patientId",
},
"validations": [
{
"threshold": {
"propertyName": "minimumBloodPressure",
"thresholdOperator": "lt",
"thresholdValue": 80
},
"value": 82,
"status": "OK"
},
{
"threshold": {
"propertyName": "maximumBloodPressure",
"thresholdOperator": "gt",
"thresholdValue": 120
},
"value": 130,
"status": "KO",
"error": "maximumBloodPressure_gt_120",
"message": "minimumBloodPressure' is greater than 120"
}
]
}
}

When the handler receives such an event it performs the following operations:

  1. add the doctor (payload.doctorId) to the list of notification recipients;
  2. add the user IDs in the metadata.includeUsers field to the recipients list, if present;
  3. remove the user IDs in the metadata.excludeUsers field from the recipients list, if present;
  4. for each recipient:
    1. fetch and merge the notification settings that applies to the given event and participant;
    2. build and send the messages to the participant.

TMM/TherapyCreated/v1

This event is fired when a new therapy is created in the TMM and the event looks like this:

{
"id": "f303f2e9-f37b-4565-91e4-628e36872df5",
"key": "high-blood-pressure-therapy-12345",
"name": "TMM/TherapyCreated/v1",
"metadata": {
"includeUsers": ["auth0|anotherDoctorId"],
"excludeUsers": ["auth0|doctorId"]
},
"payload": {
"planName": "Drug therapy",
"prototypeId": "medication",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"hours": ["10:00"],
"doctorId": "auth0|doctorId",
"patientId": "auth0|patientId",
"adherenceStatus": "enabled",
"adherenceToleranceTime": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90
}
}

When the handler receives such an event it performs the following operations:

  1. fetch the details of the doctor and patient by calling the getRecipients utility function and passing the values of the doctorId and patientId as ids;
  2. remove the users in metadata.excludeUsers from the participants;
  3. add the users in metadata.includeUsers to the participants;
  4. for each user:
    1. fetch the notification settings by calling the getNotificationSettings utility function;
    2. merge the notification settings by calling the mergeNotificationSettings utility function;
    3. get the messages to send by calling the buildMessages utility function and passing the merged notification settings as argument;
    4. send the messages by calling the sendMessages utility function;
    5. compute the first event date according to the therapy plan;
    6. build the reminders by calling buildReminders;
    7. schedule the reminders by calling the setReminders for the TMM/TherapyReminder/v1p event;
    8. merge the user notifications by calling the mergeNotifications.

TMM/TherapyDeleted/v1

When a therapy is deleted the TMM sends to the NM a new event named TMM/TherapyDeleted/v1 that looks like this:

{
"id": "da03558a-f283-4d9b-b1c7-50282716802c",
"key": "high-blood-pressure-therapy-12345",
"name": "TMM/TherapyDeleted/v1",
"metadata": {
"excludeUsers": ["lucy.heart"],
"includeUsers": ["dr.john.watson"]
},
"payload": {
"planName": "Drug therapy",
"prototypeId": "medication",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"hours": ["10:00"],
"doctorId": "auth0|doctorId",
"patientId": "auth0|patientId",
"adherenceStatus": "enabled",
"adherenceToleranceTime": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
}
}

When the handler receives such an event it performs the following operations:

  1. add the doctor (payload.doctorId) and patient (payload.patientId) to the list of notification recipients;
  2. add the user IDs in the metadata.includeUsers field to the recipients list, if present;
  3. remove the user IDs in the metadata.excludeUsers field from the recipients list, if present;
  4. for each user:
    1. fetch the notification settings that apply by calling the getNotificationSettings utility function;
    2. merge the notification settings by calling the mergeNotificationSettings utility function;
    3. get the messages to send by calling the buildMessages utility function;
    4. send the messages by calling the sendMessages utility function;
    5. abort all active reminders scheduled when the appointment was created or updated or a recurring reminder was set, by calling the abortReminders utility function.

TMM/TherapyUpdated/v1

This event is fired when a therapy is updated in the TMM and the event looks like this:

{
"name": "TMM/TherapyUpdated/v1",
"metadata": {
"excludeUsers": ["dr.mario.rossi"],
"includeUsers": []
},
"payload": {
"originalTherapy": {
"planName": "Blood pressure therapy",
"prototypeId": "bloodPressure",
"notes": "Takes the blood pressure pills",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mario.rossi",
"patientId": "lucia.viola",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
},
"currentTherapy": {
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-07-01T00:00:00Z",
"each": ["monday", "wednesday", "friday"],
"doctorId": "dr.andrea.verdi",
"patientId": "lucia.viola",
"...": "...",
}
}
}

The payload must have both the original and the updated version of the therapy plan, in order for the handler to correctly identify the messages to send and the reminders to abort or schedule. In the example above, we are both changing the participants (doctorId) and the plan schedule (endDate, each).

When the handler receives such an event it performs the following operations:

  1. cluster the user IDs (doctorId, patientId) in three groups:
    1. new participants: if the user ID is in the updated therapy, but not in the original;
    2. existing participants: if the user ID is in both the updated and original therapy;
    3. old participants: if the user ID is in the original therapy, but not in the updated version;
  2. add the user IDs in the metadata.includeUsers field to the list of existing recipients, if present;
  3. remove the user IDs in the metadata.excludeUsers field from any recipients list, if present;
  4. fetch the user details of all the participants;
  5. for each new participant, using TMM/TherapyCreated/v1 as event name and the updated therapy as payload:
    1. fetch and merge the notification settings that applies to the event;
    2. build and send the messages to the participant;
    3. build and schedule all the reminders, using TMM/TherapyReminder/v1 as reminder event name and the current appointment as payload.
  6. for each old participant, using TMM/TherapyDeleted/v1 as event name and the original therapy as payload:
    1. fetch and merge the notification settings that applies to the event;
    2. build and send the messages to the participant;
    3. abort all active reminders scheduled when the therapy was created or previously updated;
  7. for each existing participant:
    1. fetch and merge the notification settings that applies to the given event and participant;
    2. build and send the messages to the participant;
    3. abort all active reminders scheduled when the therapy was created or updated;
    4. build and schedule all the reminders, using TMM/TherapyReminder/v1 as reminder event name and the current appointment as payload.

The last four steps rely on the notification utils available in all handlers to perform most of the operations.

TMM/TherapyReminder/v1

This event is fired when the patient is notified about an ongoing therapy plan in the TMM and the event looks like this:

{
"id": "06efe38d-0e46-4863-9bb4-4c11ff63c912",
"key": "blood-pressure-therapy-12345",
"metadata": {
"reminder": {
"schedule": "PT1H",
"expirationDate": "2022-06-04T23:00:00Z",
"recipients": ["jill.marlowe"]
}
},
"name": "TMM/TherapyReminder/v1",
"payload": {
"planName": "High blood pressure therapy",
"prototypeId": "bloodPressure",
"notes": "Takes the blood pills",
"startDate": "2022-06-01T00:00:00Z",
"endDate": "2022-06-15T00:00:00Z",
"each": ["day"],
"times": 2,
"doctorId": "dr.mark.greene",
"patientId": "jill.marlowe",
"adherenceStatus": "enabled",
"adherenceToleranceFrequency": 1,
"adherenceMinimumPercentage": 90,
"complianceStatus": "enabled",
"complianceMinimumPercentage": 90,
}
}

This handler automatically schedules the next reminder in the same way of the TMM/MonitoringReminder/v1 event handler.

When the handler receives such an event it performs the following operations:

  1. add the user IDs from the reminder recipients (metadata.reminder.recipients) to the list of notification recipients;
  2. for each recipient:
    1. fetch and merge the notification settings that apply to the given event and user;
    2. filter the notification settings whose reminders field contains the reminder schedule (metadata.reminders.schedule);
    3. build and send the messages to the participant;
    4. build and schedule the next reminders, according to the notification settings and using the same event.