Merge pull request 'refs #6199 fix(sale_hook): fix quantity case' (!1797) from 6119-better_sale_hook into test
gitea/salix/pipeline/head This commit looks good Details

Reviewed-on: #1797
Reviewed-by: Carlos Andrés <carlosap@verdnatura.es>
Reviewed-by: Javi Gallego <jgallego@verdnatura.es>
This commit is contained in:
Carlos Andrés 2023-10-17 13:34:26 +00:00
commit 92e76a6d44
4 changed files with 77 additions and 33 deletions

View File

@ -18,6 +18,7 @@ describe('setSaleQuantity()', () => {
it('should change quantity sale', async() => { it('should change quantity sale', async() => {
const tx = await models.Ticket.beginTransaction({}); const tx = await models.Ticket.beginTransaction({});
spyOn(models.Item, 'getVisibleAvailable').and.returnValue((new Promise(resolve => resolve({available: 100}))));
try { try {
const options = {transaction: tx}; const options = {transaction: tx};

View File

@ -1,3 +1,5 @@
/* eslint max-len: ["error", { "code": 150 }]*/
const models = require('vn-loopback/server/server').models; const models = require('vn-loopback/server/server').models;
const LoopBackContext = require('loopback-context'); const LoopBackContext = require('loopback-context');
@ -31,6 +33,7 @@ describe('sale updateQuantity()', () => {
} }
}; };
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1)); spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
spyOn(models.Item, 'getVisibleAvailable').and.returnValue((new Promise(resolve => resolve({available: 100}))));
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
@ -38,7 +41,7 @@ describe('sale updateQuantity()', () => {
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
await models.Sale.updateQuantity(ctx, 17, 99, options); await models.Sale.updateQuantity(ctx, 17, 31, options);
await tx.rollback(); await tx.rollback();
} catch (e) { } catch (e) {
@ -50,9 +53,6 @@ describe('sale updateQuantity()', () => {
}); });
it('should add quantity if the quantity is greater than it should be and is role advanced', async() => { it('should add quantity if the quantity is greater than it should be and is role advanced', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9));
const tx = await models.Sale.beginTransaction({});
const saleId = 17; const saleId = 17;
const buyerId = 35; const buyerId = 35;
const ctx = { const ctx = {
@ -62,6 +62,9 @@ describe('sale updateQuantity()', () => {
__: () => {} __: () => {}
} }
}; };
const tx = await models.Sale.beginTransaction({});
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(buyerId));
spyOn(models.Item, 'getVisibleAvailable').and.returnValue((new Promise(resolve => resolve({available: 100}))));
try { try {
const options = {transaction: tx}; const options = {transaction: tx};
@ -169,7 +172,14 @@ describe('sale updateQuantity()', () => {
}); });
it('should throw an error if the quantity is less than the minimum quantity of the item', async() => { it('should throw an error if the quantity is less than the minimum quantity of the item', async() => {
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(9)); const ctx = {
req: {
accessToken: {userId: 1},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
const tx = await models.Sale.beginTransaction({}); const tx = await models.Sale.beginTransaction({});
const itemId = 2; const itemId = 2;
@ -194,4 +204,36 @@ describe('sale updateQuantity()', () => {
expect(error).toEqual(new Error('The amount cannot be less than the minimum')); expect(error).toEqual(new Error('The amount cannot be less than the minimum'));
}); });
it('should change quantity if has minimum quantity and new quantity is equal than item available', async() => {
const ctx = {
req: {
accessToken: {userId: 1},
headers: {origin: 'localhost:5000'},
__: () => {}
}
};
spyOn(LoopBackContext, 'getCurrentContext').and.returnValue(getActiveCtx(1));
const tx = await models.Sale.beginTransaction({});
const itemId = 2;
const saleId = 17;
const minQuantity = 30;
const newQuantity = minQuantity - 1;
try {
const options = {transaction: tx};
const item = await models.Item.findById(itemId, null, options);
await item.updateAttribute('minQuantity', minQuantity, options);
spyOn(models.Item, 'getVisibleAvailable').and.returnValue((new Promise(resolve => resolve({available: newQuantity}))));
await models.Sale.updateQuantity(ctx, saleId, newQuantity, options);
await tx.rollback();
} catch (e) {
await tx.rollback();
throw e;
}
});
}); });

View File

@ -63,17 +63,6 @@ module.exports = Self => {
} }
}, myOptions); }, 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({ const newSale = await models.Sale.create({
ticketFk: id, ticketFk: id,
itemFk: item.id, itemFk: item.id,

View File

@ -27,8 +27,7 @@ module.exports = Self => {
const loopBackContext = LoopBackContext.getCurrentContext(); const loopBackContext = LoopBackContext.getCurrentContext();
ctx.req = loopBackContext.active; ctx.req = loopBackContext.active;
const canEditQuantity = await models.ACL.checkAccessAcl(ctx, 'Sale', 'canForceQuantity', 'WRITE'); if (await models.ACL.checkAccessAcl(ctx, 'Sale', 'canForceQuantity', 'WRITE')) return;
if (canEditQuantity) return;
const ticketId = changes?.ticketFk || instance?.ticketFk; const ticketId = changes?.ticketFk || instance?.ticketFk;
const itemId = changes?.itemFk || instance?.itemFk; const itemId = changes?.itemFk || instance?.itemFk;
@ -36,7 +35,7 @@ module.exports = Self => {
const ticket = await models.Ticket.findById( const ticket = await models.Ticket.findById(
ticketId, ticketId,
{ {
fields: ['id', 'clientFk'], fields: ['id', 'clientFk', 'warehouseFk', 'shipped'],
include: { include: {
relation: 'client', relation: 'client',
scope: { scope: {
@ -51,29 +50,42 @@ module.exports = Self => {
} }
}, },
ctx.options); ctx.options);
if (ticket.client().type().code === 'loses') return; if (ticket?.client()?.type()?.code === 'loses') return;
const ticketRefund = await models.TicketRefund.findOne({ const isRefund = await models.TicketRefund.findOne({
where: {refundTicketFk: ticketId}, fields: ['id'],
fields: ['id']} where: {refundTicketFk: ticketId}
, ctx.options); }, ctx.options);
if (isRefund) return;
if (newQuantity < 0 && !ticketRefund) if (newQuantity < 0)
throw new UserError('You can only add negative amounts in refund tickets'); throw new UserError('You can only add negative amounts in refund tickets');
const item = await models.Item.findOne({ const item = await models.Item.findOne({
fields: ['family', 'minQuantity'],
where: {id: itemId}, where: {id: itemId},
fields: ['minQuantity']} }, ctx.options);
, ctx.options);
if (newQuantity < item.minQuantity && !ticketRefund) if (item.family == 'EMB') return;
const itemInfo = await models.Item.getVisibleAvailable(
itemId,
ticket.warehouseFk,
ticket.shipped,
ctx.options
);
const oldQuantity = instance?.quantity ?? null;
const quantityAdded = newQuantity - oldQuantity;
if (itemInfo.available < quantityAdded)
throw new UserError(`This item is not available`);
if (await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*')) return;
if (newQuantity < item.minQuantity && itemInfo.available != newQuantity)
throw new UserError('The amount cannot be less than the minimum'); throw new UserError('The amount cannot be less than the minimum');
const oldQuantity = instance?.quantity; if (!ctx.isNewInstance && newQuantity > oldQuantity)
if (oldQuantity === null) return;
const isRoleAdvanced = await models.ACL.checkAccessAcl(ctx, 'Ticket', 'isRoleAdvanced', '*');
if (newQuantity > oldQuantity && !isRoleAdvanced)
throw new UserError('The new quantity should be smaller than the old one'); throw new UserError('The new quantity should be smaller than the old one');
}); });
}; };