Merge branch '2092-ticket_isEditable_refactor' of verdnatura/salix into dev
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2020-03-02 09:41:26 +00:00 committed by Gitea
commit 33158b05f6
11 changed files with 128 additions and 29 deletions

View File

@ -16,7 +16,7 @@ describe('Client isValidClient', () => {
});
it('should call the isValidClient() method with an unexistant id and receive false', async() => {
let id = 999999;
let id = 999;
let result = await app.models.Client.isValidClient(id);
expect(result).toBeFalsy();

View File

@ -34,7 +34,7 @@ describe('ticket-request confirm()', () => {
expect(error.message).toEqual(`That item doesn't exists`);
});
it(`should throw an error if the item is not available`, async() => {
it('should throw an error if the item is not available', async() => {
const requestId = 5;
const itemId = 4;
const quantity = 99999;

View File

@ -32,7 +32,7 @@ module.exports = Self => {
let alertLevel = state ? state.alertLevel : null;
let ticket = await Self.app.models.Ticket.findById(id, {
fields: ['isDeleted', 'clientFk', 'refFk'],
fields: ['clientFk'],
include: [{
relation: 'client',
scope: {
@ -42,13 +42,13 @@ module.exports = Self => {
}
}]
});
const isLocked = await Self.app.models.Ticket.isLocked(id);
const isDeleted = ticket && ticket.isDeleted;
const isOnDelivery = (alertLevel && alertLevel > 0);
const alertLevelGreaterThanZero = (alertLevel && alertLevel > 0);
const isNormalClient = ticket && ticket.client().type().code == 'normal';
const isInvoiced = ticket && ticket.refFk;
const validAlertAndRoleNormalClient = (alertLevelGreaterThanZero && isNormalClient && !isValidRole);
if (!ticket || isInvoiced || isDeleted || (isOnDelivery && isNormalClient && !isValidRole))
if (!ticket || validAlertAndRoleNormalClient || isLocked)
return false;
return true;

View File

@ -0,0 +1,35 @@
module.exports = Self => {
Self.remoteMethod('isLocked', {
description: 'Check if a ticket is invoiced or deleted',
accessType: 'READ',
accepts: [{
arg: 'id',
type: 'number',
required: true,
description: 'the ticket id',
http: {source: 'path'}
}],
returns: {
type: 'boolean',
root: true
},
http: {
path: `/:id/isLocked`,
verb: 'get'
}
});
Self.isLocked = async id => {
const ticket = await Self.app.models.Ticket.findById(id, {
fields: ['isDeleted', 'refFk']
});
const isDeleted = ticket && ticket.isDeleted;
const isInvoiced = ticket && ticket.refFk;
if (!ticket || isInvoiced || isDeleted)
return true;
return false;
};
};

View File

@ -1,13 +1,6 @@
const app = require('vn-loopback/server/server');
describe('ticket isEditable()', () => {
it('should return false if the given ticket is not editable', async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let result = await app.models.Ticket.isEditable(ctx, 2);
expect(result).toEqual(false);
});
it('should return false if the given ticket does not exist', async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let result = await app.models.Ticket.isEditable(ctx, 99999);
@ -15,37 +8,46 @@ describe('ticket isEditable()', () => {
expect(result).toEqual(false);
});
it('should return false if the given ticket isDeleted', async() => {
it(`should return false if the given ticket isn't invoiced but isDeleted`, async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let result = await app.models.Ticket.isEditable(ctx, 19);
let deletedTicket = await app.models.Ticket.findOne({
where: {
invoiceOut: null,
isDeleted: true
},
fields: ['id']
});
let result = await app.models.Ticket.isEditable(ctx, deletedTicket.id);
expect(result).toEqual(false);
});
it('should return true if the given ticket is editable', async() => {
let ctx = {req: {accessToken: {userId: 9}}};
let result = await app.models.Ticket.isEditable(ctx, 16);
expect(result).toEqual(true);
});
it('should be able to edit a deleted or invoiced ticket if the role is salesAssistant', async() => {
it('should not be able to edit a deleted or invoiced ticket even for salesAssistant', async() => {
let ctx = {req: {accessToken: {userId: 21}}};
let result = await app.models.Ticket.isEditable(ctx, 8);
let result = await app.models.Ticket.isEditable(ctx, 19);
expect(result).toEqual(true);
expect(result).toEqual(false);
});
it('should be able to edit a deleted or invoiced ticket if the role is productionBoss', async() => {
it('should not be able to edit a deleted or invoiced ticket even for productionBoss', async() => {
let ctx = {req: {accessToken: {userId: 50}}};
let result = await app.models.Ticket.isEditable(ctx, 8);
let result = await app.models.Ticket.isEditable(ctx, 19);
expect(result).toEqual(true);
expect(result).toEqual(false);
});
it('should not be able to edit a deleted or invoiced ticket if the role is salesPerson', async() => {
it('should not be able to edit a deleted or invoiced ticket even for salesPerson', async() => {
let ctx = {req: {accessToken: {userId: 18}}};
let result = await app.models.Ticket.isEditable(ctx, 8);
let result = await app.models.Ticket.isEditable(ctx, 19);
expect(result).toEqual(false);
});

View File

@ -0,0 +1,34 @@
const app = require('vn-loopback/server/server');
describe('ticket isLocked()', () => {
it('should return true if the given ticket does not exist', async() => {
let result = await app.models.Ticket.isLocked(99999);
expect(result).toEqual(true);
});
it('should return true if the given ticket is invoiced', async() => {
let invoicedTicket = await app.models.Ticket.findOne({
where: {invoiceOut: {neq: null}},
fields: ['id']
});
let result = await app.models.Ticket.isLocked(invoicedTicket.id);
expect(result).toEqual(true);
});
it(`should return true if the given ticket isn't invoiced but deleted`, async() => {
let deletedTicket = await app.models.Ticket.findOne({
where: {
invoiceOut: null,
isDeleted: true
},
fields: ['id']
});
let result = await app.models.Ticket.isLocked(deletedTicket.id);
expect(result).toEqual(true);
});
});

View File

@ -35,6 +35,7 @@ module.exports = Self => {
});
Self.updateDiscount = async(ctx, id, salesIds, newDiscount) => {
const userId = ctx.req.accessToken.userId;
const models = Self.app.models;
const tx = await Self.beginTransaction({});
@ -68,8 +69,14 @@ module.exports = Self => {
if (!allFromSameTicket)
throw new UserError('All sales must belong to the same ticket');
const isEditable = await models.Ticket.isEditable(ctx, id);
if (!isEditable)
const isLocked = await models.Ticket.isLocked(id);
const isSalesPerson = await models.Account.hasRole(userId, 'salesPerson');
const state = await Self.app.models.TicketState.findOne({
where: {ticketFk: id}
});
const alertLevel = state ? state.alertLevel : null;
if (isLocked || (!isSalesPerson && alertLevel > 0 ))
throw new UserError(`The sales of this ticket can't be modified`);
const ticket = await models.Ticket.findById(id, {

View File

@ -29,6 +29,7 @@ module.exports = Self => {
require('../methods/ticket/recalculateComponents')(Self);
require('../methods/ticket/deleteStowaway')(Self);
require('../methods/ticket/sendSms')(Self);
require('../methods/ticket/isLocked')(Self);
Self.observe('before save', async function(ctx) {
if (ctx.isNewInstance) return;

View File

@ -165,8 +165,8 @@
</span>
</vn-td>
<vn-td number>
<span ng-class="{'link': $ctrl.isEditable}"
title="{{$ctrl.isEditable ? 'Edit discount' : ''}}"
<span ng-class="{'link': !$ctrl.isLocked}"
title="{{!$ctrl.isLocked ? 'Edit discount' : ''}}"
ng-click="$ctrl.showEditDiscountPopover($event, sale)">
{{(sale.discount / 100) | percentage}}
</span>

View File

@ -46,6 +46,7 @@ class Controller {
set ticket(value) {
this._ticket = value;
this.isTicketEditable();
this.isTicketLocked();
}
get sales() {
@ -354,7 +355,7 @@ class Controller {
}
showEditDiscountPopover(event, sale) {
if (!this.isEditable) return;
if (this.isLocked) return;
this.sale = sale;
this.edit = [{
@ -540,6 +541,12 @@ class Controller {
});
}
isTicketLocked() {
this.$http.get(`Tickets/${this.$state.params.id}/isLocked`).then(res => {
this.isLocked = res.data;
});
}
hasOneSaleSelected() {
if (this.totalCheckedLines() === 1)
return true;

View File

@ -69,6 +69,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
$httpBackend.when('POST', `Claims/createFromSales`, {claim: claim, sales: sales}).respond(claim);
$httpBackend.expect('POST', `Claims/createFromSales`).respond(claim);
controller.createClaim();
@ -98,6 +99,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
let result = controller.checkedLines();
$httpBackend.flush();
@ -116,6 +118,7 @@ describe('Ticket', () => {
$httpBackend.expectGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.expectGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onStateOkClick();
$httpBackend.flush();
@ -129,6 +132,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onStateChange(3);
$httpBackend.flush();
});
@ -142,6 +146,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.onRemoveLinesClick('accept');
$httpBackend.flush();
@ -183,6 +188,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.unmarkAsReserved(false);
$httpBackend.flush();
});
@ -213,6 +219,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.updateQuantity(sale);
$httpBackend.flush();
@ -232,6 +239,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.updateConcept(sale);
$httpBackend.flush();
@ -262,6 +270,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.addSale(newSale);
$httpBackend.flush();
@ -287,6 +296,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.transferSales(13);
$httpBackend.flush();
@ -305,6 +315,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.setTransferParams();
$httpBackend.flush();
@ -330,6 +341,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.newOrderFromTicket();
$httpBackend.flush();
@ -353,6 +365,7 @@ describe('Ticket', () => {
$httpBackend.whenGET(`Tickets/1/subtotal`).respond(200, 227.5);
$httpBackend.whenGET(`Tickets/1/getVAT`).respond(200, 10.5);
$httpBackend.whenGET(`Tickets/1/isEditable`).respond();
$httpBackend.whenGET(`Tickets/1/isLocked`).respond();
controller.calculateSalePrice();
$httpBackend.flush();