diff --git a/db/changes/240601/01-updateProcedureGetItemLack copy.sql b/db/changes/240601/01-updateProcedureGetItemLack copy.sql new file mode 100644 index 000000000..7372ad699 --- /dev/null +++ b/db/changes/240601/01-updateProcedureGetItemLack copy.sql @@ -0,0 +1,68 @@ +DROP PROCEDURE IF EXISTS vn.item_getLack; + +DELIMITER $$ +$$ +CREATE DEFINER=`root`@`localhost` PROCEDURE `vn`.`item_getLack`( + 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 ; diff --git a/db/changes/240601/01-updateProcedureGetItemLack.sql b/db/changes/240601/01-updateProcedureGetItemLack.sql index 8c36a762d..0a59ecb2b 100644 --- a/db/changes/240601/01-updateProcedureGetItemLack.sql +++ b/db/changes/240601/01-updateProcedureGetItemLack.sql @@ -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; diff --git a/modules/ticket/back/methods/ticket/itemLack.js b/modules/ticket/back/methods/ticket/itemLack.js index 35f299e6c..fa4b500fb 100644 --- a/modules/ticket/back/methods/ticket/itemLack.js +++ b/modules/ticket/back/methods/ticket/itemLack.js @@ -1,14 +1,52 @@ +/* eslint-disable no-console */ module.exports = Self => { Self.remoteMethod('itemLack', { description: 'Download a ticket delivery note document', accessType: 'READ', accepts: [ + { + 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}; + // 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 [ { diff --git a/modules/ticket/back/methods/ticket/specs/itemLack.spec.js b/modules/ticket/back/methods/ticket/specs/itemLack.spec.js new file mode 100644 index 000000000..49651abb8 --- /dev/null +++ b/modules/ticket/back/methods/ticket/specs/itemLack.spec.js @@ -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; + } + }); +});