add sale and canbeInvoice refactor + tests

This commit is contained in:
Carlos Jimenez Ruiz 2021-08-05 13:32:35 +02:00
parent 4628c8ab6f
commit 870314277f
3 changed files with 138 additions and 100 deletions

View File

@ -32,64 +32,81 @@ module.exports = Self => {
}
});
Self.addSale = async(ctx, id, itemId, quantity) => {
Self.addSale = async(ctx, id, itemId, quantity, options) => {
const $t = ctx.req.__; // $translate
const models = Self.app.models;
let tx;
const myOptions = {};
const isEditable = await models.Ticket.isEditable(ctx, id);
if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`);
if (typeof options == 'object')
Object.assign(myOptions, options);
const item = await models.Item.findById(itemId);
const ticket = await models.Ticket.findById(id, {
include: {
relation: 'client',
scope: {
include: {
relation: 'salesPersonUser',
scope: {
fields: ['id', 'name']
if (!myOptions.transaction) {
tx = await Self.beginTransaction({});
myOptions.transaction = tx;
}
try {
const isEditable = await models.Ticket.isEditable(ctx, id, myOptions);
if (!isEditable)
throw new UserError(`The sales of this ticket can't be modified`);
const item = await models.Item.findById(itemId, null, myOptions);
const ticket = await models.Ticket.findById(id, {
include: {
relation: 'client',
scope: {
include: {
relation: 'salesPersonUser',
scope: {
fields: ['id', 'name']
}
}
}
}
}, myOptions);
const itemInfo = await models.Item.getVisibleAvailable(itemId, ticket.warehouseFk, ticket.shipped, myOptions);
const isPackaging = item.family == 'EMB';
if (!isPackaging && itemInfo.available < quantity)
throw new UserError(`This item is not available`);
const newSale = await models.Sale.create({
ticketFk: id,
itemFk: item.id,
concept: item.name,
quantity: quantity
}, myOptions);
await Self.rawSql('CALL vn.sale_calculateComponent(?, NULL)', [newSale.id], myOptions);
const sale = await models.Sale.findById(newSale.id, {
include: {
relation: 'item'
}
}, myOptions);
const addition = `\r\n-${sale.itemFk}: ${sale.concept} (${sale.quantity})`;
const salesPerson = ticket.client().salesPersonUser();
if (salesPerson) {
const origin = ctx.req.headers.origin;
const message = $t('Added sale to ticket', {
ticketId: id,
ticketUrl: `${origin}/#!/ticket/${id}/sale`,
addition: addition
});
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
}
});
const res = await models.Item.getVisibleAvailable(itemId, ticket.warehouseFk, ticket.shipped);
if (tx) await tx.commit();
const isPackaging = item.family == 'EMB';
if (!isPackaging && res.available < quantity)
throw new UserError(`This item is not available`);
const newSale = await models.Sale.create({
ticketFk: id,
itemFk: item.id,
concept: item.name,
quantity: quantity
});
await Self.rawSql('CALL vn.sale_calculateComponent(?, NULL)', [newSale.id]);
const sale = await models.Sale.findById(newSale.id, {
include: {
relation: 'item'
}
});
const addition = `\r\n-${sale.itemFk}: ${sale.concept} (${sale.quantity})`;
const salesPerson = ticket.client().salesPersonUser();
if (salesPerson) {
const origin = ctx.req.headers.origin;
const message = $t('Added sale to ticket', {
ticketId: id,
ticketUrl: `${origin}/#!/ticket/${id}/sale`,
addition: addition
});
await models.Chat.sendCheckingPresence(ctx, salesPerson.id, message);
return sale;
} catch (e) {
if (tx) await tx.rollback();
throw e;
}
return sale;
};
};

View File

@ -2,69 +2,87 @@ const app = require('vn-loopback/server/server');
describe('ticket addSale()', () => {
const ticketId = 13;
let newSale;
afterAll(async done => {
const sale = await app.models.Sale.findById(newSale.id);
await sale.destroy();
done();
});
it('should create a new sale for the ticket with id 13', async() => {
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 4;
const quantity = 10;
newSale = await app.models.Ticket.addSale(ctx, ticketId, itemId, quantity);
const tx = await app.models.Ticket.beginTransaction({});
expect(newSale.itemFk).toEqual(4);
try {
const options = {transaction: tx};
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 4;
const quantity = 10;
const newSale = await app.models.Ticket.addSale(ctx, ticketId, itemId, quantity, options);
expect(newSale.itemFk).toEqual(4);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
it('should not be able to add a sale if the item quantity is not available', async() => {
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 11;
const quantity = 10;
const tx = await app.models.Ticket.beginTransaction({});
let error;
await app.models.Ticket.addSale(ctx, ticketId, itemId, quantity).catch(e => {
error = e;
}).finally(() => {
expect(error.message).toEqual(`This item is not available`);
});
expect(error).toBeDefined();
try {
const options = {transaction: tx};
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 11;
const quantity = 10;
await app.models.Ticket.addSale(ctx, ticketId, itemId, quantity, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`This item is not available`);
});
it('should not be able to add a sale if the ticket is not editable', async() => {
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const notEditableTicketId = 1;
const itemId = 4;
const quantity = 10;
let error;
await app.models.Ticket.addSale(ctx, notEditableTicketId, itemId, quantity).catch(e => {
error = e;
}).finally(() => {
expect(error.message).toEqual(`The sales of this ticket can't be modified`);
});
const tx = await app.models.Ticket.beginTransaction({});
expect(error).toBeDefined();
let error;
try {
const options = {transaction: tx};
const ctx = {
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const notEditableTicketId = 1;
const itemId = 4;
const quantity = 10;
await app.models.Ticket.addSale(ctx, notEditableTicketId, itemId, quantity, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
error = e;
}
expect(error.message).toEqual(`The sales of this ticket can't be modified`);
});
});

View File

@ -24,7 +24,7 @@ describe('ticket canBeInvoiced()', () => {
const options = {transaction: tx};
const ticket = await models.Ticket.findById(ticketId, null, options);
await ticket.updateAttribute('refFk', 'T1234567', options);
await ticket.updateAttribute('refFk', 'T1111111', options);
const canBeInvoiced = await models.Ticket.canBeInvoiced([ticketId], options);
@ -33,6 +33,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
@ -52,6 +53,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
@ -75,6 +77,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});