diff --git a/modules/client/back/methods/client/sendSms.js b/modules/client/back/methods/client/sendSms.js new file mode 100644 index 000000000..18651c65c --- /dev/null +++ b/modules/client/back/methods/client/sendSms.js @@ -0,0 +1,55 @@ + +module.exports = Self => { + Self.remoteMethodCtx('sendSms', { + description: 'Log the message in clientLog and call the send method', + accessType: 'WRITE', + accepts: [{ + arg: 'id', + type: 'Number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + }, + { + arg: 'destination', + type: 'String', + required: true, + }, + { + arg: 'message', + type: 'String', + required: true, + }], + returns: { + type: 'Object', + root: true + }, + http: { + path: `/:id/sendSms`, + verb: 'POST' + } + }); + + Self.sendSms = async(ctx, id, destination, message) => { + const userId = ctx.req.accessToken.userId; + + let sms = await Self.app.models.Sms.send(ctx, id, destination, message); + let logRecord = { + originFk: id, + userFk: userId, + action: 'insert', + changedModel: 'sms', + newInstance: { + destinationFk: id, + destination: destination, + message: message, + statusCode: sms.statusCode, + status: sms.status + } + }; + + await Self.app.models.ClientLog.create(logRecord); + + return sms; + }; +}; diff --git a/modules/client/back/methods/sms/send.js b/modules/client/back/methods/sms/send.js index e56b5567e..af956650d 100644 --- a/modules/client/back/methods/sms/send.js +++ b/modules/client/back/methods/sms/send.js @@ -3,7 +3,7 @@ const xmlParser = require('xml2js').parseString; const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { - Self.remoteMethodCtx('send', { + Self.remoteMethod('send', { description: 'Sends SMS to a destination phone', accessType: 'WRITE', accepts: [{ @@ -83,7 +83,6 @@ module.exports = Self => { }; const sms = await Self.create(newSms); - if (statusCode != 200) throw new UserError(`We weren't able to send this SMS`); diff --git a/modules/client/back/models/client.js b/modules/client/back/models/client.js index 73626b408..9b9db7161 100644 --- a/modules/client/back/models/client.js +++ b/modules/client/back/models/client.js @@ -24,6 +24,7 @@ module.exports = Self => { require('../methods/client/canBeInvoiced')(Self); require('../methods/client/uploadFile')(Self); require('../methods/client/lastActiveTickets')(Self); + require('../methods/client/sendSms')(Self); // Validations diff --git a/modules/client/back/models/sms.json b/modules/client/back/models/sms.json index aa9737478..cb6936d90 100644 --- a/modules/client/back/models/sms.json +++ b/modules/client/back/models/sms.json @@ -1,11 +1,7 @@ { "name": "Sms", "description": "Sms sent to client", - "base": "Loggable", - "log": { - "model":"ClientLog", - "relation": "recipient" - }, + "base": "VnModel", "options": { "mysql": { "table": "sms" @@ -45,11 +41,6 @@ "type": "belongsTo", "model": "Account", "foreignKey": "senderFk" - }, - "recipient": { - "type": "belongsTo", - "model": "Client", - "foreignKey": "destinationFk" } } } diff --git a/modules/client/front/sms/index.js b/modules/client/front/sms/index.js index b68171ce5..1bf2fb99c 100644 --- a/modules/client/front/sms/index.js +++ b/modules/client/front/sms/index.js @@ -28,7 +28,7 @@ class Controller extends Component { onResponse(response) { if (response === 'accept') { - this.$http.post(`Sms/send`, this.sms).then(res => { + this.$http.post(`Clients/${this.$params.id}/sendSms`, this.sms).then(res => { this.vnApp.showMessage(this.$translate.instant('SMS sent!')); if (res.data) this.emit('send', {response: res.data}); diff --git a/modules/ticket/back/methods/ticket/sendSms.js b/modules/ticket/back/methods/ticket/sendSms.js new file mode 100644 index 000000000..f4fe82315 --- /dev/null +++ b/modules/ticket/back/methods/ticket/sendSms.js @@ -0,0 +1,55 @@ + +module.exports = Self => { + Self.remoteMethodCtx('sendSms', { + description: 'Log the message in ticketLog and call the send method', + accessType: 'WRITE', + accepts: [{ + arg: 'id', + type: 'Number', + required: true, + description: 'The ticket id', + http: {source: 'path'} + }, + { + arg: 'destination', + type: 'String', + required: true, + }, + { + arg: 'message', + type: 'String', + required: true, + }], + returns: { + type: 'Object', + root: true + }, + http: { + path: `/:id/sendSms`, + verb: 'POST' + } + }); + + Self.sendSms = async(ctx, id, destination, message) => { + const userId = ctx.req.accessToken.userId; + + let sms = await Self.app.models.Sms.send(ctx, id, destination, message); + let logRecord = { + originFk: id, + userFk: userId, + action: 'insert', + changedModel: 'sms', + newInstance: { + destinationFk: id, + destination: destination, + message: message, + statusCode: sms.statusCode, + status: sms.status + } + }; + + await Self.app.models.TicketLog.create(logRecord); + + return sms; + }; +}; diff --git a/modules/ticket/back/models/ticket.js b/modules/ticket/back/models/ticket.js index 8ba2bfb0d..45284d60d 100644 --- a/modules/ticket/back/models/ticket.js +++ b/modules/ticket/back/models/ticket.js @@ -28,6 +28,7 @@ module.exports = Self => { require('../methods/ticket/canHaveStowaway')(Self); require('../methods/ticket/recalculateComponents')(Self); require('../methods/ticket/deleteStowaway')(Self); + require('../methods/ticket/sendSms')(Self); Self.observe('before save', async function(ctx) { if (ctx.isNewInstance) return; diff --git a/modules/ticket/front/descriptor/index.html b/modules/ticket/front/descriptor/index.html index 3632d37f1..f47f3d6ef 100644 --- a/modules/ticket/front/descriptor/index.html +++ b/modules/ticket/front/descriptor/index.html @@ -193,7 +193,7 @@ - + + +
+
Send SMS
+ + + + + + + + + + + {{'Characters remaining' | translate}}: {{$ctrl.charactersRemaining()}} + + +
+
+ + + + + \ No newline at end of file diff --git a/modules/ticket/front/sms/index.js b/modules/ticket/front/sms/index.js new file mode 100644 index 000000000..1f2c7f9c0 --- /dev/null +++ b/modules/ticket/front/sms/index.js @@ -0,0 +1,48 @@ +import ngModule from '../module'; +import Component from 'core/lib/component'; +import './style.scss'; + +class Controller extends Component { + constructor($element, $scope, $http, $translate, vnApp) { + super($element, $scope); + + this.$scope = $scope; + this.$http = $http; + this.$translate = $translate; + this.vnApp = vnApp; + } + + open() { + this.$scope.SMSDialog.show(); + } + + charactersRemaining() { + let elementMaxLength; + let textAreaLength; + const element = this.$scope.message; + + textAreaLength = element.input.textLength; + elementMaxLength = element.maxlength; + return elementMaxLength - textAreaLength; + } + + onResponse(response) { + if (response === 'accept') { + this.$http.post(`Tickets/${this.$params.id}/sendSms`, this.sms).then(res => { + this.vnApp.showMessage(this.$translate.instant('SMS sent!')); + + if (res.data) this.emit('send', {response: res.data}); + }); + } + } +} + +Controller.$inject = ['$element', '$scope', '$http', '$translate', 'vnApp']; + +ngModule.component('vnTicketSms', { + template: require('./index.html'), + controller: Controller, + bindings: { + sms: '<', + } +}); diff --git a/modules/ticket/front/sms/index.spec.js b/modules/ticket/front/sms/index.spec.js new file mode 100644 index 000000000..cc76d4ce1 --- /dev/null +++ b/modules/ticket/front/sms/index.spec.js @@ -0,0 +1,51 @@ +import './index'; + +describe('Client', () => { + describe('Component vnClientSms', () => { + let controller; + let $httpBackend; + let $element; + + beforeEach(ngModule('client')); + + beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + let $scope = $rootScope.$new(); + $element = angular.element(''); + controller = $componentController('vnClientSms', {$element, $scope}); + controller.client = {id: 101}; + })); + + describe('onResponse()', () => { + it('should perform a POST query and show a success snackbar', () => { + const ticketId = 11; + let params = {destinationFk: 101, destination: 111111111, message: 'My SMS'}; + controller.sms = {destinationFk: 101, destination: 111111111, message: 'My SMS'}; + + spyOn(controller.vnApp, 'showMessage'); + $httpBackend.when('POST', `Ticket/${ticketId}/sendSms`, params).respond(200, params); + $httpBackend.expect('POST', `Sms/send`, params).respond(params); + + controller.onResponse('accept'); + $httpBackend.flush(); + + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!'); + }); + }); + + describe('charactersRemaining()', () => { + it('should return the characters remaining in a element', () => { + controller.$scope.message = { + input: { + textLength: 50 + }, + maxlength: 150 + }; + + let result = controller.charactersRemaining(); + + expect(result).toEqual(100); + }); + }); + }); +}); diff --git a/modules/ticket/front/sms/locale/es.yml b/modules/ticket/front/sms/locale/es.yml new file mode 100644 index 000000000..f26c8ba24 --- /dev/null +++ b/modules/ticket/front/sms/locale/es.yml @@ -0,0 +1,5 @@ +Send SMS: Enviar SMS +Destination: Destinatario +Message: Mensaje +SMS sent!: ¡SMS enviado! +Characters remaining: Carácteres restantes \ No newline at end of file diff --git a/modules/ticket/front/sms/style.scss b/modules/ticket/front/sms/style.scss new file mode 100644 index 000000000..89723b196 --- /dev/null +++ b/modules/ticket/front/sms/style.scss @@ -0,0 +1,5 @@ +@import "variables"; + +.SMSDialog { + min-width: 25em +} \ No newline at end of file