#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 let result = await nightmare
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText'); .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() => { 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', () => { describe('Ticket services path', () => {
const nightmare = createNightmare(); const nightmare = createNightmare();
const invoiceTicketId = 10; const invoicedTicketId = 10;
describe('as employee', () => { describe('as employee', () => {
beforeAll(() => { beforeAll(() => {
nightmare nightmare
.loginAndModule('employee', 'ticket') .loginAndModule('employee', 'ticket')
.accessToSearchResult(invoiceTicketId) .accessToSearchResult(invoicedTicketId)
.accessToSection('ticket.card.service'); .accessToSection('ticket.card.service');
}); });
@ -31,15 +31,16 @@ describe('Ticket services path', () => {
.waitToClick(selectors.ticketService.saveServiceButton) .waitToClick(selectors.ticketService.saveServiceButton)
.waitForLastSnackbar(); .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', () => { describe('as administrative', () => {
let editableTicketId = 13;
beforeAll(() => { beforeAll(() => {
nightmare nightmare
.loginAndModule('administrative', 'ticket') .loginAndModule('administrative', 'ticket')
.accessToSearchResult(13) .accessToSearchResult(editableTicketId)
.accessToSection('ticket.card.service'); .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() => { it('should create a new description then add price then create the service', async() => {
const result = await nightmare const result = await nightmare
.waitToClick(selectors.ticketService.firstAddDescriptionButton)
.write(selectors.ticketService.newDescriptionInput, 'accurate description') .write(selectors.ticketService.newDescriptionInput, 'accurate description')
.waitToClick(selectors.ticketService.saveDescriptionButton) .waitToClick(selectors.ticketService.saveDescriptionButton)
.write(selectors.ticketService.firstPriceInput, 999) .write(selectors.ticketService.firstPriceInput, 999)
@ -127,7 +127,7 @@ describe('Ticket services path', () => {
expect(result).toEqual('Data saved!'); 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 const result = await nightmare
.reloadSection('ticket.card.service') .reloadSection('ticket.card.service')
.waitForNumberOfElements(selectors.ticketService.serviceLine, 0) .waitForNumberOfElements(selectors.ticketService.serviceLine, 0)

View File

@ -44,5 +44,5 @@
"Invalid TIN": "Invalid Tax number", "Invalid TIN": "Invalid Tax number",
"This ticket can't be invoiced": "This ticket can't be invoiced", "This ticket can't be invoiced": "This ticket can't be invoiced",
"The value should be a number": "The value should be a number", "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", "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 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", "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) { onPassChange(response) {
if (response == 'ACCEPT') if (response == 'ACCEPT') {
try { try {
if (!this.newPassword) if (!this.newPassword)
throw new Error(`Passwords can't be empty`); throw new Error(`Passwords can't be empty`);
@ -56,6 +56,7 @@ export default class Controller {
this.vnApp.showError(this.$translate.instant(e.message)); this.vnApp.showError(this.$translate.instant(e.message));
return false; return false;
} }
}
return true; return true;
} }

View File

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

View File

@ -5,9 +5,18 @@ module.exports = Self => {
let changes = ctx.currentInstance || ctx.instance; let changes = ctx.currentInstance || ctx.instance;
if (changes) { if (changes) {
let ticketId = changes.ticketFk; let ticketId = changes.ticketFk;
let ticket = await Self.app.models.Ticket.findById(ticketId); let isEditable = await Self.app.models.Ticket.isEditable(ticketId);
if (ticket.refFk) if (!isEditable)
throw new UserError('You cannot add or modify services to an invoiced ticket'); 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-crud-model>
<vn-watcher <vn-watcher
vn-id="watcher" vn-id="watcher"
data="$ctrl.services" data="$ctrl.services">
form="form">
</vn-watcher> </vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" compact> <form name="form" ng-submit="$ctrl.onSubmit()" compact>
<vn-card pad-large> <vn-card pad-large>

View File

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

View File

@ -1,4 +1,5 @@
import './index.js'; import './index.js';
import UserError from 'core/lib/user-error';
describe('Ticket component vnTicketService', () => { describe('Ticket component vnTicketService', () => {
let controller; let controller;
@ -38,11 +39,17 @@ describe('Ticket component vnTicketService', () => {
}); });
describe('onNewServiceTypeResponse', () => { describe('onNewServiceTypeResponse', () => {
it(`should throw an error`, () => { it(`should throw an error if the new service description is empty`, () => {
controller.newServiceType = {name: undefined}; 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', () => { it('should set the description of the selected service upon service type creation', () => {