Merge branch '2092-ticket_isEditable_refactor' of verdnatura/salix into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
33158b05f6
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
|
@ -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, {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue