#1475 no borrar servicios de tickets no editables

This commit is contained in:
Carlos Jimenez Ruiz 2019-05-29 13:06:42 +02:00
parent 2c012b084a
commit 40654f94c4
10 changed files with 49 additions and 34 deletions

View File

@ -117,7 +117,7 @@ describe('Client balance path', () => {
let result = await nightmare
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
expect(result).toContain('50');
expect(result).toEqual('€50.00');
});
it('should now click on the Clients button of the top bar menu', async() => {

View File

@ -3,13 +3,13 @@ import createNightmare from '../../helpers/nightmare';
describe('Ticket services path', () => {
const nightmare = createNightmare();
const invoiceTicketId = 10;
const invoicedTicketId = 10;
describe('as employee', () => {
beforeAll(() => {
nightmare
.loginAndModule('employee', 'ticket')
.accessToSearchResult(invoiceTicketId)
.accessToSearchResult(invoicedTicketId)
.accessToSection('ticket.card.service');
});
@ -31,15 +31,16 @@ describe('Ticket services path', () => {
.waitToClick(selectors.ticketService.saveServiceButton)
.waitForLastSnackbar();
expect(result).toEqual('You cannot add or modify services to an invoiced ticket');
expect(result).toEqual(`The current ticket can't be modified`);
});
});
describe('as administrative', () => {
let editableTicketId = 13;
beforeAll(() => {
nightmare
.loginAndModule('administrative', 'ticket')
.accessToSearchResult(13)
.accessToSearchResult(editableTicketId)
.accessToSection('ticket.card.service');
});
@ -78,7 +79,6 @@ describe('Ticket services path', () => {
it('should create a new description then add price then create the service', async() => {
const result = await nightmare
.waitToClick(selectors.ticketService.firstAddDescriptionButton)
.write(selectors.ticketService.newDescriptionInput, 'accurate description')
.waitToClick(selectors.ticketService.saveDescriptionButton)
.write(selectors.ticketService.firstPriceInput, 999)
@ -127,7 +127,7 @@ describe('Ticket services path', () => {
expect(result).toEqual('Data saved!');
});
it('should confirm the service was sucessfully removed', async() => {
it(`should confirm the service wasn't sucessfully removed`, async() => {
const result = await nightmare
.reloadSection('ticket.card.service')
.waitForNumberOfElements(selectors.ticketService.serviceLine, 0)

View File

@ -44,5 +44,5 @@
"Invalid TIN": "Invalid Tax number",
"This ticket can't be invoiced": "This ticket can't be invoiced",
"The value should be a number": "The value should be a number",
"You cannot add or modify services to an invoiced ticket": "You cannot add or modify services to an invoiced ticket"
"The current ticket can't be modified": "The current ticket can't be modified"
}

View File

@ -85,5 +85,6 @@
"INFINITE_LOOP": "Existe una dependencia entre dos Jefes",
"The sales of the current ticket can't be modified": "Las lineas de este ticket no pueden ser modificadas",
"The sales of the receiver ticket can't be modified": "Las lineas del ticket al que envias no pueden ser modificadas",
"NO_AGENCY_AVAILABLE": "No hay agencias disponibles"
"NO_AGENCY_AVAILABLE": "No hay agencias disponibles",
"The current ticket can't be modified": "El ticket actual no puede ser modificado"
}

View File

@ -41,7 +41,7 @@ export default class Controller {
}
onPassChange(response) {
if (response == 'ACCEPT')
if (response == 'ACCEPT') {
try {
if (!this.newPassword)
throw new Error(`Passwords can't be empty`);
@ -56,6 +56,7 @@ export default class Controller {
this.vnApp.showError(this.$translate.instant(e.message));
return false;
}
}
return true;
}

View File

@ -24,9 +24,8 @@ module.exports = Self => {
where: {ticketFk: ticketFk}
});
let alertLevel = state ? state.alertLevel : null;
let exists = await Self.app.models.Ticket.findOne({
where: {id: ticketFk},
fields: ['isDeleted', 'clientFk'],
let ticket = await Self.app.models.Ticket.findById(ticketFk, {
fields: ['isDeleted', 'clientFk', 'refFk'],
include: [{
relation: 'client',
scope: {
@ -37,10 +36,12 @@ module.exports = Self => {
}]
});
if (exists && exists.client().type().code !== 'normal')
return true;
const isDeleted = ticket && ticket.isDeleted;
const isOnDelivery = (alertLevel && alertLevel > 0);
const isNotNormalClient = ticket && ticket.client().type().code == 'normal';
const isInvoiced = ticket && ticket.refFk;
if (!exists || exists.isDeleted == 1 || (alertLevel && alertLevel > 0))
if (!ticket || ((isDeleted || isOnDelivery) && isNotNormalClient) || isInvoiced)
return false;
return true;

View File

@ -5,9 +5,18 @@ module.exports = Self => {
let changes = ctx.currentInstance || ctx.instance;
if (changes) {
let ticketId = changes.ticketFk;
let ticket = await Self.app.models.Ticket.findById(ticketId);
if (ticket.refFk)
throw new UserError('You cannot add or modify services to an invoiced ticket');
let isEditable = await Self.app.models.Ticket.isEditable(ticketId);
if (!isEditable)
throw new UserError(`The current ticket can't be modified`);
}
});
Self.observe('before delete', async ctx => {
const models = Self.app.models;
const service = await models.TicketService.findById(ctx.where.id);
const isEditable = await Self.app.models.Ticket.isEditable(service.ticketFk);
if (!isEditable)
throw new UserError(`The current ticket can't be modified`);
});
};

View File

@ -7,8 +7,7 @@
</vn-crud-model>
<vn-watcher
vn-id="watcher"
data="$ctrl.services"
form="form">
data="$ctrl.services">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large>

View File

@ -1,4 +1,5 @@
import ngModule from '../module';
import UserError from 'core/lib/user-error';
class Controller {
constructor($http, $scope, $stateParams, vnApp, $translate, $element) {
@ -53,22 +54,18 @@ class Controller {
onNewServiceTypeResponse(response) {
if (response == 'ACCEPT') {
try {
if (!this.newServiceType.name)
throw new Error(`Name can't be empty`);
if (!this.newServiceType.name)
throw new UserError(`Name can't be empty`);
this.$http.post(`/api/TicketServiceTypes`, this.newServiceType).then(response => {
this.services[this.currentServiceIndex].description = response.data.name;
});
} catch (err) {
this.vnApp.showError(this.$translate.instant(err.message));
return err;
}
this.$http.post(`/api/TicketServiceTypes`, this.newServiceType).then(response => {
this.services[this.currentServiceIndex].description = response.data.name;
});
}
}
onSubmit() {
this.$scope.watcher.check();
this.$scope.model.save().then(() => {
this.$scope.watcher.notifySaved();
this.$scope.model.refresh();

View File

@ -1,4 +1,5 @@
import './index.js';
import UserError from 'core/lib/user-error';
describe('Ticket component vnTicketService', () => {
let controller;
@ -38,11 +39,17 @@ describe('Ticket component vnTicketService', () => {
});
describe('onNewServiceTypeResponse', () => {
it(`should throw an error`, () => {
it(`should throw an error if the new service description is empty`, () => {
controller.newServiceType = {name: undefined};
let error = controller.onNewServiceTypeResponse('ACCEPT');
expect(error.message).toEqual(`Name can't be empty`);
let error;
try {
controller.onNewServiceTypeResponse('ACCEPT');
} catch (e) {
error = e.message;
}
expect(error).toBe(`Name can't be empty`);
});
it('should set the description of the selected service upon service type creation', () => {