add sale and canbeInvoice refactor + tests
This commit is contained in:
parent
4628c8ab6f
commit
870314277f
|
@ -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;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -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`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue