module.exports = function(Self) { Self.validateCredit = function(credit) { return credit >= 0; }; Self.validateBinded('credit', Self.validateCredit, { message: 'The credit must be an integer greater than or equal to zero', allowNull: false, // FIXME: Ignored by loopback when it's false allowBlank: false }); Self.validateGrade = function(grade) { return typeof grade === 'undefined' || grade >= 0; }; Self.validateBinded('grade', Self.validateGrade, { message: 'The grade must be an integer greater than or equal to zero', allowNull: true }); async function validateNullGrade(err, done) { let filter = { fields: ['grade'], where: { creditClassification: this.creditClassification }, order: 'created DESC' }; let insurance = await Self.findOne(filter); if (insurance && (!insurance.grade && this.grade || insurance.grade && !this.grade)) err(); done(); } Self.validateAsync('nullGrade', validateNullGrade, { message: 'The grade must be similar to the last one' }); Self.messageSend = async function(data, accessToken) { let filter = { include: { relation: 'classification', scope: { fields: ['client'], include: { relation: 'customer', scope: { fields: ['name', 'salesPersonFk'], include: { relation: 'salesPerson', scope: { fields: 'userFk', include: { relation: 'user', scope: { fields: ['name'] } } } } } } } } }; let ctx = {req: {accessToken: accessToken}}; let insurance = await Self.findById(data.id, filter); let customer = insurance.classification().customer(); if (!customer.salesPerson()) return; let salesPersonId = customer.salesPerson().user().id; let grade = data.grade ? `(Grado ${data.grade})` : '(Sin grado)'; let params = { recipientFk: salesPersonId, message: `He cambiado el crédito asegurado del ` + `cliente "${customer.name}" a ${data.credit} € ${grade}` }; Self.app.models.Message.send(ctx, params); }; // Update from transaction misses ctx accessToken. // Fixed passing accessToken from method messageSend() Self.observe('after save', async function(ctx) { if (ctx.options.accessToken) await Self.messageSend(ctx.instance, ctx.options.accessToken); }); };