Custom Business Logic on Record Create

Hi

I am going to break this into two sections. Firstly, a bare minimum requirement. Secondly, an “ideal”, more complicated requirement.

First
Upon a new entry being put into a table of mine (“Favourites”) via a mobile app POSTing data, i’d like backendless to do a simple HTTP Post request to https://exp.host/--/api/v2/push/send with a body like:

[
	{
	"to": "ExponentPushToken[zzjgmSH_RfMFuj2RiiwY_B]",
	"title": "Test Title",
	"body": "[User's name] has favourited an article"
}.
	{
	"to": "ExponentPushToken[zzjgmSH_RfMFuj2RiiwY_E]",
	"title": "Test Title",
	"body": "[User's name] has favourited an article"
},
	{
	"to": "ExponentPushToken[zzjgmSH_RfMFuj2RiiwY_H]",
	"title": "Test Title",
	"body": "[User's name] has favourited an article"
}

]

The tokens are stored in a field in the users table. I need backendless to select user tokens where the users have a matching code in the “organisationCode” field compared to the user that is POSTing data.

So far i have added this in my backend event handler area

Can someone now advise on the JS code i’d need to send a push notification simply saying:

“[User’s name] has favourited an article” ?


Second

Ideally upon a new favourite being put in to the system i actually need backendless to:

  1. Populate a “notifictions” table with this body:
    {
    “attach” : “[potential link to an image goes here]”,
    “description” : “just favourited an article”,
    “organisationCode” : “e8xqdl”,
    “type” : “like”,
    “userName” : “John Smith”,
    “ownerId” : “94A40363-4F7E-F774-FF87-B64760001A00”
    }

  2. Once the above is POSTed ^ , then POST to {{backendlessAPIurl}}/{{Application ID}}/{{REST API Key}}/data/{{Table Name}}/{{Data Object ID}}/{{Data Relation Name}}

with

{"userLink" : "[user_ objectId]" }

where user_objectId is the backendless object ID for that user

This is to add a link to the users table for every entry in the notifications table.

  1. Push to the URL as mentioned in the “First” section of this post to trigger push notifications

hey Alan,
For sending data to external host from Business Logic you can use Backendless.Request, for example:

// it's your ApiService/Method
fooBar(){
    return Backendless.Request.post('https://exp.host/--/api/v2/push/send', [...here is your request data])
}

you can find more info to how to use Backendless.Request here https://github.com/Backendless/Request

according to sending PushNotification
if you are using our api for sending pushes the docs will be helpful for you https://backendless.com/docs/js/doc.html#push_overview

Thanks Vladimir.

I am using expo push service because its far easier than using the backendless one for expo react native projects - which requires detaching from expo etc.

Can you also advise me on how i retrieve data from other tables ?

sure, here is a doc for Data https://backendless.com/docs/js/doc.html#advanced-object-retrieval

Is there a way to add logic for after create, that adds a link in a relation field on that data table?

Otherwise the client needs to POST once to create the record, then POST a 2nd time

with

{{API Host}}/{{Application ID}}/{{REST API Key}}/data/{{Table Name}}/{{Data Object ID}}/{{Data Relation Name}}

and a body of

{
“objectId” : “006X91BA-7AD9-E160-FFBC-087XXC859E00”
}

or similar

Also, after i have made a new DataQueryBuilder, how do i setProperties of a linked field?

For example
queryBuilder.setProperties("description", "userLink.Name")

yes, it’s possible, just add a relation to an object like described in the docs: https://backendless.com/docs/js/doc.html#data_relations_api_set_add_js

Backendless.ServerCode.Persistence.afterCreate('YouTableName', async function(req, res) {
     return Backendless.Data.of('ParentTable').addRelation({objectId: 'parentObjectId' }, 'myRelationName', ['childObjectId']).then(() => res.result)
})

Also, after i have made a new DataQueryBuilder, how do i setProperties of a linked field?

For example
queryBuilder.setProperties("description", "userLink.Name")

Unfortunately, you can’t specify field of relation items, but you can handle that with BusinessLogic, just remove fields what you don’t want to send to the client in your ApiService or EventHandler

I don’t understand.

If i want to send a message body of “John Smith has favourited an article” to https://exp.host/--/api/v2/push/send

Then on the table in question when a notification entry gets created i am going to ultimately need to get description, userLink.deviceToken and userLink.name to generate that message and send the right token to https://exp.host/--/api/v2/push/send .

It generally sounds like i just can’t do that, so i am going to have to get the client to do all the logic

no, I mean you can’t load specific fields of related object, for example
you have class Address with the next field { city, code } and class User { name, email, address:Address }
and you try to load the user object, you can filter fields only of the top object through setProperties(‘name’) method, but for relations it won’t work

and as I understand now you just want to load some parent object with child object in a single api call, and then use property of related object, for loading relations you should use setRelated(‘userLink’) method

This is a notifications object if doing a simple GET of that table.

So i am just trying to do queryBuilder.setProperties("description", "userLink.Name", "userLink.deviceToken");

i just don’t know the proper notation

looks like you have “autoload” enabled for the “userLink” column
Data%20Browser%20-%20new_app%20-%20Backendless%202018-09-14%2018-00-26

Yeah, so how do i reference that !?

sorry, but I’m not sure that I understand your question, I can see that you already able to retrieve the object with “userLink” relation and there are properties “name” and “deviceToken”, and you can use it

const userName = yourObject.userLink.name
const deviceToken = yourObject.userLink.deviceToken

if you are looking for a way to get only these two fields “name” and “deviceToken” of “userLink” from the server, as I said before it’s not impossible, props filtering is applied only for the top object, not for sub-objects (relations)

Hi Valdimir

I am just getting familiar with how all of this works.

So i have created a new afterCreate event handler on my notifications table

Right now all i have done is:

/**
* @param {Object} req The request object contains information about the request
* @param {Object} req.context The execution context contains an information about application, current user and event
* @param {Notifications} req.item An item to create
*
* @param {Object} res The response object
* @param {Notifications} res.result Created item
* @param {Object} res.error
*/
Backendless.ServerCode.Persistence.afterCreate('Notifications', function(req, res) {
  //add your code here
  
Backendless.Logging.setLogReportingPolicy( 1, 1 );
var logger = Backendless.Logging.getLogger( "MyLogger");
logger.info( "informational log message" ); 
logger.warn( "warning message" ); 
logger.debug( "debug message" ); 
logger.error( "error message" ); 
  
  var notificationQueryBuilder = Backendless.DataQueryBuilder.create();
  
  
 
 // set query builder properties
// queryBuilder.setXXXX
  notificationQueryBuilder.setProperties("description", "userLink");
  notificationQueryBuilder.setWhereClause("userLink.organisationCode = 'req.context.user.organisationCode'");

 
Backendless.Data.of( "Notifications" ).find( notificationQueryBuilder )
 .then( function( objectArray ) {
   logger.info("queryBuilderObjectIs", objectArray)
  })
 .catch( function( error ) {
 });
  
  
}, true);

as far as i understand. Logger items should appear in my logs, that will be in files > logging ?

yeah, it should be there, as well you can see the logs messages in real-time, just go Manage → Logging → RT

btw, you have a some mistake

notificationQueryBuilder.setWhereClause("userLink.organisationCode = 'req.context.user.organisationCode'");

you should change it to

notificationQueryBuilder.setWhereClause(`userLink.organisationCode = '${req.context.user.organisationCode}'`);

OK thanks, corrected.

Nothing is appearing in logs.

I am correct in thinking the function will be triggered upon a new entry being made in the notifications table?

did you create a new “Notifications” via API call (SDKs | REST) or via DevConsole in Data Browser?