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 $t = ctx.req.__; // $translate
const models = Self.app.models; const models = Self.app.models;
let tx;
const myOptions = {};
const isEditable = await models.Ticket.isEditable(ctx, id); if (typeof options == 'object')
if (!isEditable) Object.assign(myOptions, options);
throw new UserError(`The sales of this ticket can't be modified`);
const item = await models.Item.findById(itemId); if (!myOptions.transaction) {
const ticket = await models.Ticket.findById(id, { tx = await Self.beginTransaction({});
include: { myOptions.transaction = tx;
relation: 'client', }
scope: {
include: { try {
relation: 'salesPersonUser', const isEditable = await models.Ticket.isEditable(ctx, id, myOptions);
scope: { if (!isEditable)
fields: ['id', 'name'] 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'; return sale;
if (!isPackaging && res.available < quantity) } catch (e) {
throw new UserError(`This item is not available`); if (tx) await tx.rollback();
throw e;
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;
}; };
}; };

View File

@ -2,69 +2,87 @@ const app = require('vn-loopback/server/server');
describe('ticket addSale()', () => { describe('ticket addSale()', () => {
const ticketId = 13; 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() => { it('should create a new sale for the ticket with id 13', async() => {
const ctx = { const tx = await app.models.Ticket.beginTransaction({});
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 4;
const quantity = 10;
newSale = await app.models.Ticket.addSale(ctx, ticketId, itemId, quantity);
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() => { it('should not be able to add a sale if the item quantity is not available', async() => {
const ctx = { const tx = await app.models.Ticket.beginTransaction({});
req: {
accessToken: {userId: 9},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
const itemId = 11;
const quantity = 10;
let error; 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() => { it('should not be able to add a sale if the ticket is not editable', async() => {
const ctx = { const tx = await app.models.Ticket.beginTransaction({});
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`);
});
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 options = {transaction: tx};
const ticket = await models.Ticket.findById(ticketId, null, options); 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); const canBeInvoiced = await models.Ticket.canBeInvoiced([ticketId], options);
@ -33,6 +33,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e;
} }
}); });
@ -52,6 +53,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e;
} }
}); });
@ -75,6 +77,7 @@ describe('ticket canBeInvoiced()', () => {
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
await tx.rollback(); await tx.rollback();
throw e;
} }
}); });