Merge pull request '2319_show_delivery_note' (#320) from 2319_show_delivery_note into dev
gitea/salix/pipeline/head This commit looks good Details

Reviewed-by: Joan Sanchez <joan@verdnatura.es>
This commit is contained in:
Carlos Jimenez Ruiz 2020-06-18 13:40:28 +00:00
commit b8f03f20e1
8 changed files with 148 additions and 4 deletions

View File

@ -14,7 +14,7 @@ module.exports = Self => {
} }
], ],
returns: { returns: {
type: 'string', type: 'Object',
root: true root: true
}, },
http: { http: {
@ -53,6 +53,6 @@ module.exports = Self => {
if (!isAllowed) if (!isAllowed)
throw new UserError(`You don't have enough privileges`, 'ACCESS_DENIED'); throw new UserError(`You don't have enough privileges`, 'ACCESS_DENIED');
return await models.TicketTracking.create(params); return models.TicketTracking.create(params);
}; };
}; };

View File

@ -0,0 +1,50 @@
module.exports = Self => {
Self.remoteMethodCtx('setDelivered', {
description: 'Changes the state of the received ticket ids to delivered',
accessType: 'WRITE',
accepts: [
{
arg: 'ticketIds',
description: 'the array of ticket ids to set as delivered',
type: ['Number'],
required: true,
http: {source: 'body'}
}
],
returns: {
type: 'Object',
root: true
},
http: {
path: `/setDelivered`,
verb: 'POST'
}
});
Self.setDelivered = async(ctx, ticketIds) => {
let userId = ctx.req.accessToken.userId;
let models = Self.app.models;
let state = await models.State.findOne({
where: {
code: 'delivered'
},
fields: ['id', 'name', 'alertLevel', 'code']
});
let worker = await models.Worker.findOne({where: {userFk: userId}});
let promises = [];
for (let id of ticketIds) {
let promise = models.TicketTracking.changeState(ctx, {
stateFk: state.id,
workerFk: worker.id,
ticketFk: id
});
promises.push(promise);
}
await Promise.all(promises);
return state;
};
};

View File

@ -0,0 +1,36 @@
const app = require('vn-loopback/server/server');
describe('ticket setDelivered()', () => {
let ticketOne;
let ticketTwo;
beforeAll(async done => {
let originalTicketOne = await app.models.Ticket.findById(8);
let originalTicketTwo = await app.models.Ticket.findById(10);
originalTicketOne.id = null;
originalTicketTwo.id = null;
ticketOne = await app.models.Ticket.create(originalTicketOne);
ticketTwo = await app.models.Ticket.create(originalTicketTwo);
done();
});
afterAll(async done => {
await app.models.Ticket.destroyById(ticketOne.id);
await app.models.Ticket.destroyById(ticketTwo.id);
done();
});
it('should return the state which has been applied to the given tickets', async() => {
let ctx = {req: {accessToken: {userId: 49}}};
let delivered = await app.models.State.findOne({where: {code: 'delivered'}, fields: ['id']});
let params = [ticketOne.id, ticketTwo.id];
let state = await app.models.TicketTracking.setDelivered(ctx, params);
expect(state.id).toEqual(delivered.id);
});
});

View File

@ -1,5 +1,6 @@
module.exports = function(Self) { module.exports = function(Self) {
require('../methods/ticket-tracking/changeState')(Self); require('../methods/ticket-tracking/changeState')(Self);
require('../methods/ticket-tracking/setDelivered')(Self);
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'}); Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'}); Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'});

View File

@ -89,7 +89,7 @@
<vn-td class="expendable">{{::ticket.province}}</vn-td> <vn-td class="expendable">{{::ticket.province}}</vn-td>
<vn-td> <vn-td>
<span class="chip {{$ctrl.stateColor(ticket)}}"> <span class="chip {{$ctrl.stateColor(ticket)}}">
{{::ticket.state}} {{ticket.state}}
</span> </span>
</vn-td> </vn-td>
<vn-td>{{::ticket.agencyMode}}</vn-td> <vn-td>{{::ticket.agencyMode}}</vn-td>
@ -120,6 +120,13 @@
</vn-data-viewer> </vn-data-viewer>
<div fixed-bottom-right> <div fixed-bottom-right>
<vn-vertical style="align-items: center;"> <vn-vertical style="align-items: center;">
<vn-button class="round sm vn-mb-sm"
icon="print"
ng-show="$ctrl.totalChecked > 0"
ng-click="$ctrl.setDelivered()"
vn-tooltip="Set as delivered and open delivery note(s)"
tooltip-position="left">
</vn-button>
<vn-button class="round sm vn-mb-sm" <vn-button class="round sm vn-mb-sm"
icon="icon-recovery" icon="icon-recovery"
ng-show="$ctrl.totalChecked > 0" ng-show="$ctrl.totalChecked > 0"

View File

@ -4,6 +4,37 @@ import UserError from 'core/lib/user-error';
import './style.scss'; import './style.scss';
export default class Controller extends Section { export default class Controller extends Section {
constructor($element, $, vnReport) {
super($element, $);
this.vnReport = vnReport;
}
setDelivered() {
const checkedTickets = this.checked;
let ids = [];
for (let ticket of checkedTickets)
ids.push(ticket.id);
this.$http.post('TicketTrackings/setDelivered', ids).then(res => {
let state = res.data;
for (let ticket of checkedTickets) {
ticket.stateFk = state.id;
ticket.state = state.name;
ticket.alertLevel = state.alertLevel;
ticket.alertLevelCode = state.code;
}
this.openDeliveryNotes(ids);
});
}
openDeliveryNotes(ids) {
for (let id of ids) {
this.vnReport.show('delivery-note', {
ticketId: id,
});
}
}
openBalanceDialog() { openBalanceDialog() {
const checkedTickets = this.checked; const checkedTickets = this.checked;
const description = []; const description = [];
@ -125,6 +156,7 @@ export default class Controller extends Section {
return [minHour, maxHour]; return [minHour, maxHour];
} }
} }
Controller.$inject = ['$element', '$scope', 'vnReport'];
ngModule.component('vnTicketIndex', { ngModule.component('vnTicketIndex', {
template: require('./index.html'), template: require('./index.html'),

View File

@ -1,6 +1,7 @@
import './index.js'; import './index.js';
describe('Component vnTicketIndex', () => { describe('Component vnTicketIndex', () => {
let controller; let controller;
let $httpBackend;
let $window; let $window;
let tickets = [{ let tickets = [{
id: 1, id: 1,
@ -21,7 +22,8 @@ describe('Component vnTicketIndex', () => {
beforeEach(ngModule('ticket')); beforeEach(ngModule('ticket'));
beforeEach(inject(($componentController, _$window_) => { beforeEach(inject(($componentController, _$window_, _$httpBackend_) => {
$httpBackend = _$httpBackend_;
$window = _$window_; $window = _$window_;
const $element = angular.element('<vn-ticket-index></vn-ticket-index>'); const $element = angular.element('<vn-ticket-index></vn-ticket-index>');
controller = $componentController('vnTicketIndex', {$element}); controller = $componentController('vnTicketIndex', {$element});
@ -85,6 +87,21 @@ describe('Component vnTicketIndex', () => {
}); });
}); });
describe('setDelivered()/openDeliveryNotes()', () => {
it('should perform a post to setDelivered and open tabs with the delivery notes', () => {
controller.$.model = {data: tickets, refresh: () => {}};
$window.open = jest.fn();
$httpBackend.expect('POST', 'TicketTrackings/setDelivered').respond('ok');
controller.setDelivered();
$httpBackend.flush();
expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[1].id}`);
expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[2].id}`);
});
});
describe('checked()', () => { describe('checked()', () => {
it('should return an array of checked tickets', () => { it('should return an array of checked tickets', () => {
controller.$.model = {data: tickets}; controller.$.model = {data: tickets};

View File

@ -2,6 +2,7 @@ Weekly tickets: Tickets programados
Go to lines: Ir a lineas Go to lines: Ir a lineas
Not available: No disponible Not available: No disponible
Payment on account...: Pago a cuenta... Payment on account...: Pago a cuenta...
Set as delivered and open delivery note(s): Marcar como servido/s y abrir albarán/es
Closure: Cierre Closure: Cierre
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
Filter by selection: Filtro por selección Filter by selection: Filtro por selección