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
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:
commit
92e76a6d44
|
@ -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};
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue