#6321 - Negative tickets #1945
|
@ -0,0 +1,68 @@
|
|||
DROP PROCEDURE IF EXISTS vn.item_getLack;
|
||||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getLack`(
|
||||
jsegarra marked this conversation as resolved
Outdated
|
||||
IN vForce BOOLEAN DEFAULT TRUE,
|
||||
IN vDays INT DEFAULT 2,
|
||||
IN vCustomWhere TEXT,
|
||||
)
|
||||
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula una tabla con el máximo negativo visible para cada producto y almacen
|
||||
*
|
||||
* @param vForce Fuerza el recalculo del stock
|
||||
* @param vDays Numero de dias a considerar
|
||||
* @param vSearch Filtro items
|
||||
**/
|
||||
|
||||
CALL `cache`.stock_refresh(vForce);
|
||||
CALL item_getMinacum(NULL, util.VN_CURDATE(), vDays, NULL);
|
||||
CALL item_getMinETD();
|
||||
CALL item_zoneClosure();
|
||||
|
||||
|
||||
SET @sqlQuery = CONCAT(`SELECT i.id itemFk,
|
||||
i.longName,
|
||||
w.id warehouseFk,
|
||||
p.`name` producer,
|
||||
i.`size`,
|
||||
i.category,
|
||||
w.name warehouse,
|
||||
SUM(IFNULL(sub.amount,0)) lack,
|
||||
i.inkFk,
|
||||
IFNULL(im.timed, util.midnight()) timed,
|
||||
IFNULL(izc.timed, util.midnight()) minTimed
|
||||
FROM (SELECT item_id,
|
||||
warehouse_id,
|
||||
amount
|
||||
FROM cache.stock
|
||||
WHERE amount > 0
|
||||
UNION ALL
|
||||
SELECT itemFk,
|
||||
warehouseFk,
|
||||
amount
|
||||
FROM tmp.itemMinacum
|
||||
) sub
|
||||
JOIN warehouse w ON w.id = sub.warehouse_id
|
||||
JOIN item i ON i.id = sub.item_id
|
||||
LEFT JOIN producer p ON p.id = i.producerFk
|
||||
JOIN itemType it ON it.id = i.typeFk
|
||||
JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
LEFT JOIN tmp.itemMinETD im ON im.itemFk = i.id
|
||||
LEFT JOIN tmp.itemZoneClosure izc ON izc.itemFk = i.id
|
||||
WHERE w.isForTicket
|
||||
AND ic.display
|
||||
AND it.code != 'GEN'
|
||||
AND `,vCustomWhere,`
|
||||
GROUP BY i.id, w.id
|
||||
HAVING lack < 0;`);
|
||||
CALL `exec`(@sqlQuery);
|
||||
|
||||
DROP TEMPORARY TABLE tmp.itemMinacum;
|
||||
DROP TEMPORARY TABLE tmp.itemMinETD;
|
||||
DROP TEMPORARY TABLE tmp.itemZoneClosure;
|
||||
END
|
||||
$$
|
||||
DELIMITER ;
|
|
@ -2,7 +2,18 @@ DROP PROCEDURE IF EXISTS vn.item_getLack;
|
|||
|
||||
DELIMITER $$
|
||||
$$
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getLack`(IN vForce BOOLEAN, IN vDays INT, IN vCustomWhere VARCHAR(500))
|
||||
CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getLack`(
|
||||
IN vForce BOOLEAN DEFAULT TRUE,
|
||||
IN vDays INT DEFAULT 2,
|
||||
IN vId INT DEFAULT NULL,
|
||||
IN vLongname INT DEFAULT NULL,
|
||||
IN vSupplier VARCHAR DEFAULT NULL,
|
||||
IN vColor VARCHAR DEFAULT NULL,
|
||||
IN vSize INT DEFAULT NULL,
|
||||
IN vOrigen VARCHAR DEFAULT NULL,
|
||||
IN vLack INT DEFAULT NULL
|
||||
)
|
||||
|
||||
BEGIN
|
||||
/**
|
||||
* Calcula una tabla con el máximo negativo visible para cada producto y almacen
|
||||
|
@ -50,7 +61,14 @@ BEGIN
|
|||
WHERE w.isForTicket
|
||||
AND ic.display
|
||||
AND it.code != 'GEN'
|
||||
AND (vCustomWhere IS NULL OR vCustomWhere = '' OR vCustomWhere)
|
||||
AND (vId IS NULL OR i.id = vId)
|
||||
AND (vLongname IS NULL OR i.longName = vLongname)
|
||||
AND (vSupplier IS NULL OR p.`name` LIKE CONCAT('%', vSupplier, '%'))
|
||||
AND (vColor IS NULL OR vColor = i.inkFk)
|
||||
AND (vSize IS NULL OR vSize = i.`size`)
|
||||
AND (vOrigen IS NULL OR vOrigen = w.name)
|
||||
AND (vLack IS NULL OR vLack = lack)
|
||||
|
||||
GROUP BY i.id, w.id
|
||||
HAVING lack < 0;
|
||||
|
||||
|
|
|
@ -1,14 +1,52 @@
|
|||
/* eslint-disable no-console */
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('itemLack', {
|
||||
description: 'Download a ticket delivery note document',
|
||||
accessType: 'READ',
|
||||
accepts: [
|
||||
{
|
||||
alexm
commented
Cambiar descripccion Cambiar descripccion
|
||||
arg: 'ctx',
|
||||
type: 'object',
|
||||
http: {source: 'context'}
|
||||
},
|
||||
{
|
||||
arg: 'filter',
|
||||
type: 'object',
|
||||
description: 'Filter defining where, order, offset, and limit - must be a JSON-encoded string',
|
||||
http: {source: 'query'}
|
||||
},
|
||||
{
|
||||
arg: 'id',
|
||||
type: 'number',
|
||||
description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'longname',
|
||||
type: 'string',
|
||||
description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'supplier',
|
||||
type: 'string',
|
||||
description: 'The client fiscal id',
|
||||
},
|
||||
{
|
||||
arg: 'color',
|
||||
type: 'string',
|
||||
description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'size',
|
||||
type: 'string', description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'origen',
|
||||
type: 'string', description: 'The item id',
|
||||
},
|
||||
{
|
||||
arg: 'lack',
|
||||
type: 'number', description: 'The item id',
|
||||
}
|
||||
],
|
||||
returns: [
|
||||
{
|
||||
|
@ -25,15 +63,107 @@ module.exports = Self => {
|
|||
|
||||
Self.itemLack = async(ctx, filter, options) => {
|
||||
const myOptions = {};
|
||||
|
||||
// const versionSQL = false;
|
||||
if (typeof options == 'object')
|
||||
Object.assign(myOptions, options);
|
||||
// if (versionSQL) {
|
||||
// const filterKeyOrder = ['id', 'longname', 'supplier', 'colour', 'size', 'origen', 'lack'];
|
||||
|
||||
// let query = 'CALL vn.item_getLack(?, ?)';
|
||||
// const {body} = ctx;
|
||||
|
||||
// const result = await Self.rawSql(query, [true, 2]);
|
||||
// let procedureParams = [true, 2];
|
||||
// procedureParams.push(...filterKeyOrder.map(clave => body || null));
|
||||
// const procedureArgs = Array(procedureParams.length).fill('?').join(', ');
|
||||
// let query = `CALL vn.item_getLack(${procedureArgs})`;
|
||||
|
||||
// if (tx) await tx.commit();
|
||||
// const result = await Self.rawSql(query, procedureParams, myOptions);
|
||||
// console.log('qUERY:', query);
|
||||
// console.log('Argumentos procedimiento:', procedureArgs);
|
||||
// console.log('PArametros del procedimiento:', procedureParams);
|
||||
// // const result = await Self.rawSql(query, [true, 2, ...procedureParams]);
|
||||
// // console.log('Resultado', result);
|
||||
// return result;
|
||||
// } else {
|
||||
// const where = buildFilter(ctx.args, (param, value) => {
|
||||
// switch (param) {
|
||||
// case 'id':
|
||||
// return {'i.id': value};
|
||||
// case 'longname':
|
||||
// return {'i.longName': value};
|
||||
// case 'name':
|
||||
// return {'p.name': {like: `%${value}%`}};
|
||||
// case 'color':
|
||||
// return {'i.inkFk': value};
|
||||
jsegarra marked this conversation as resolved
Outdated
jgallego
commented
si se va a migrar el proc tal cual confirmar con Juan pero yo no lo moveria que se llame a item_getLack de la BBDD directamente si se va a migrar el proc tal cual confirmar con Juan pero yo no lo moveria que se llame a item_getLack de la BBDD directamente
jsegarra
commented
Lo anoto para hablar con el Lo anoto para hablar con el
jsegarra
commented
La idea de hacer este movimiento, es poder aplicar filtros a la consulta. Esto justo se esta haciendo en "Monitor de ventas". Hay mucho código SQL definido en el método para poder aplicar los filtros que vienen por parámetros La idea de hacer este movimiento, es poder aplicar filtros a la consulta. Esto justo se esta haciendo en "Monitor de ventas". Hay mucho código SQL definido en el método para poder aplicar los filtros que vienen por parámetros
jsegarra
commented
Tras hablar con Juan, consideramos mejor enfoque modificar el procedimiento añadiendo tantos argumentos como filtros tengamos Tras hablar con Juan, consideramos mejor enfoque modificar el procedimiento añadiendo tantos argumentos como filtros tengamos
|
||||
// case 'size':
|
||||
// return {'i.size': value};
|
||||
// case 'origen':
|
||||
// return {'w.name': value};
|
||||
// case 'lack':
|
||||
// return {'lack': value};
|
||||
// }
|
||||
// }) ?? {};
|
||||
|
||||
// const stmts = [
|
||||
// 'CALL cache.stock_refresh(vForce);',
|
||||
// 'CALL item_getMinacum(NULL, util.VN_CURDATE(), vDays, NULL);',
|
||||
// 'CALL item_getMinETD();',
|
||||
// 'CALL item_zoneClosure();'
|
||||
// ];
|
||||
|
||||
// const stmt = new ParameterizedSQL(`
|
||||
// SELECT i.id itemFk,
|
||||
// i.longName,
|
||||
// w.id warehouseFk,
|
||||
// p.name producer,
|
||||
// i.size,
|
||||
// i.category,
|
||||
// w.name warehouse,
|
||||
// SUM(IFNULL(sub.amount,0)) lack,
|
||||
// i.inkFk,
|
||||
// IFNULL(im.timed, util.midnight()) timed,
|
||||
// IFNULL(izc.timed, util.midnight()) minTimed
|
||||
// FROM (SELECT item_id,
|
||||
// warehouse_id,
|
||||
// amount
|
||||
// FROM cache.stock
|
||||
// WHERE amount > 0
|
||||
// UNION ALL
|
||||
// SELECT itemFk,
|
||||
// warehouseFk,
|
||||
// amount
|
||||
// FROM tmp.itemMinacum
|
||||
// ) sub
|
||||
// JOIN warehouse w ON w.id = sub.warehouse_id
|
||||
// JOIN item i ON i.id = sub.item_id
|
||||
// LEFT JOIN producer p ON p.id = i.producerFk
|
||||
// JOIN itemType it ON it.id = i.typeFk
|
||||
// JOIN itemCategory ic ON ic.id = it.categoryFk
|
||||
// LEFT JOIN tmp.itemMinETD im ON im.itemFk = i.id
|
||||
// LEFT JOIN tmp.itemZoneClosure izc ON izc.itemFk = i.id
|
||||
// WHERE w.isForTicket
|
||||
// AND ic.display
|
||||
// AND it.code != 'GEN'
|
||||
// `);
|
||||
|
||||
// const sqlWhere = conn.makeWhere(where);
|
||||
|
||||
// stmt.merge(sqlWhere);
|
||||
// stmt.merge(`
|
||||
// GROUP BY i.id, w.id
|
||||
// HAVING lack < 0;`
|
||||
// );
|
||||
// stmts.push(`
|
||||
// DROP TEMPORARY TABLE tmp.itemMinacum;
|
||||
// DROP TEMPORARY TABLE tmp.itemMinETD;
|
||||
// DROP TEMPORARY TABLE tmp.itemZoneClosure;
|
||||
// `);
|
||||
// stmt.merge(conn.makeSuffix(filter));
|
||||
// const itemsIndex = stmts.push(stmt) - 1;
|
||||
|
||||
// const sql = ParameterizedSQL.join(stmts, ';');
|
||||
// const result = await conn.executeStmt(sql, myOptions);
|
||||
// return itemsIndex === 0 ? result : result[itemsIndex];
|
||||
// }
|
||||
|
||||
return [
|
||||
{
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
const models = require('vn-loopback/server/server').models;
|
||||
|
||||
describe('Item Lack', () => {
|
||||
it('should return data with NO filters', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const result = await models.Ticket.itemLack(3, options);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
|
||||
it('should return data with filters', async() => {
|
||||
const tx = await models.Ticket.beginTransaction({});
|
||||
|
||||
try {
|
||||
const options = {transaction: tx};
|
||||
|
||||
const result = await models.Ticket.isEmpty(8, options);
|
||||
|
||||
expect(result).toBeFalsy();
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
hay que usar el propio archivo del procedimiento db/routines/vn/procedures/item_getLack.sql
Se han colado las diferentes pruebas que hice antes de decirme que me base en "Monitor de ventas"