DELIMITER $$ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_new`( vUserFk INT, OUT vCollectionFk INT ) BEGIN /** * Genera colecciones de tickets sin asignar trabajador. * * @param vUserFk Identificador de account.user */ DECLARE vWarehouseFk INT; DECLARE vWagons INT; DECLARE vTrainFk INT; DECLARE vLinesLimit INT; DECLARE vTicketLines INT; DECLARE vVolumeLimit DECIMAL; DECLARE vSizeLimit INT; DECLARE vTicketVolume DECIMAL; DECLARE vMaxTickets INT; DECLARE vStateCode VARCHAR(45); DECLARE vFirstTicketFk INT; DECLARE vWorkerCode VARCHAR(3); DECLARE vWagonCounter INT DEFAULT 1; DECLARE vTicketFk INT; DECLARE vItemPackingTypeFk VARCHAR(1); DECLARE vHasAssignedTickets BOOL; DECLARE vHasUniqueCollectionTime BOOL; DECLARE vHeight INT; DECLARE vVolume INT; DECLARE vLiters INT; DECLARE vLines INT; DECLARE vTotalLines INT DEFAULT 0; DECLARE vTotalVolume INT DEFAULT 0; DECLARE vFreeWagonFk INT; DECLARE vDone INT DEFAULT FALSE; DECLARE vTickets CURSOR FOR SELECT ticketFk, `lines`, m3 FROM tmp.productionBuffer ORDER BY HH, mm, productionOrder DESC, m3 DESC, agency, zona, routeFk, ticketFk LIMIT vMaxTickets; DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE; SELECT pc.ticketTrolleyMax * o.numberOfWagons, pc.hasUniqueCollectionTime, w.code, o.warehouseFk, o.itemPackingTypeFk, st.code, o.numberOfWagons, o.trainFk, o.linesLimit, o.volumeLimit, o.sizeLimit INTO vMaxTickets, vHasUniqueCollectionTime, vWorkerCode, vWarehouseFk, vItemPackingTypeFk, vStateCode, vWagons, vTrainFk, vLinesLimit, vVolumeLimit, vSizeLimit FROM worker w JOIN operator o ON o.workerFk = w.id JOIN state st ON st.`code` = 'ON_PREPARATION' JOIN productionConfig pc WHERE w.id = vUserFk; -- Se prepara el tren, con tantos vagones como sea necesario. CREATE OR REPLACE TEMPORARY TABLE tTrain (wagon INT, shelve INT, liters INT, `lines`INT, height INT, ticketFk INT, PRIMARY KEY(wagon, shelve)) ENGINE = MEMORY; INSERT INTO tTrain (wagon, shelve, liters, `lines`, height) WITH RECURSIVE wagonSequence AS ( SELECT vWagonCounter wagon UNION ALL SELECT wagon + 1 wagon FROM wagonSequence WHERE wagon < vWagonCounter + vWagons -1 ) SELECT ws.wagon, cv.`level`, cv.liters, cv.`lines`, cv.height FROM wagonSequence ws JOIN vn.collectionVolumetry cv ON cv.trainFk = vTrainFk AND cv.itemPackingTypeFk = vItemPackingTypeFk; -- Esto desaparecerá cuando tengamos la table cache.ticket CALL productionControl(vWarehouseFk, 0); ALTER TABLE tmp.productionBuffer ADD COLUMN liters INT, ADD COLUMN height INT; -- Los tickets de recogida en Algemesí sólo se sacan si están asignados. -- Los pedidos con riesgo no se sacan aunque se asignen. DELETE pb FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE (pb.agency = 'REC_ALGEMESI' AND s.code <> 'PICKER_DESIGNED') OR pb.problem LIKE '%RIESGO%'; -- Si hay tickets asignados, nos centramos exclusivamente en esos tickets -- y los sacamos independientemente de problemas o tamaños SELECT EXISTS ( SELECT TRUE FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE (s.code = 'PICKER_DESIGNED' AND pb.workerCode = vWorkerCode) OR s.code = 'LAST_CALL' ) INTO vHasAssignedTickets; -- Se dejan en la tabla tmp.productionBuffer sólo aquellos tickets adecuados IF vHasAssignedTickets THEN DELETE pb FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE (s.code <> 'PICKER_DESIGNED' OR pb.workerCode <> vWorkerCode) AND s.code <> 'LAST_CALL'; ELSE DELETE pb FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state LEFT JOIN ( SELECT pb.ticketFk, MAX(i.`size`) maxSize FROM tmp.productionBuffer pb JOIN ticket t ON t.id = pb.ticketfk JOIN sale s ON s.ticketFk = t.id JOIN item i ON i.id = s.itemFk GROUP BY pb.ticketFk ) sub ON sub.ticketFk = pb.ticketFk JOIN productionConfig pc WHERE pb.shipped <> util.VN_CURDATE() OR pb.ubicacion IS NULL OR (NOT s.isPreparable AND NOT s.isPrintable) OR pb.collectionH IS NOT NULL OR pb.collectionV IS NOT NULL OR pb.collectionN IS NOT NULL OR (NOT pb.H AND pb.V > 0 AND vItemPackingTypeFk = 'H') OR (NOT pb.V AND vItemPackingTypeFk = 'V') OR (pc.isPreviousPreparationRequired AND pb.previousWithoutParking) OR LENGTH(pb.problem) OR pb.lines > vLinesLimit OR pb.m3 > vVolumeLimit OR sub.maxSize > vSizeLimit OR pb.hasPlantTray; END IF; -- Hay que excluir aquellos que no tengan la misma hora de preparacion, si procede IF vHasUniqueCollectionTime THEN DELETE pb FROM tmp.productionBuffer pb JOIN tmp.productionBuffer pb2 ON pb2.ticketFk = vFirstTicketFk AND (pb.HH <> pb2.HH OR pb.mm <> pb2.mm); END IF; SELECT ticketFk INTO vFirstTicketFk FROM tmp.productionBuffer ORDER BY HH, mm, productionOrder DESC, m3 DESC, agency, zona, routeFk, ticketFk LIMIT 1; OPEN vTickets; l: LOOP SET vDone = FALSE; FETCH vTickets INTO vTicketFk, vTicketLines, vTicketVolume; IF vDone THEN LEAVE l; END IF; -- Buscamos un ticket que cumpla con los requisitos en el listado IF (vLinesLimit IS NULL OR (vTotalLines + vTicketLines) <= vLinesLimit) AND (vVolumeLimit IS NULL OR (vTotalVolume + vTicketVolume) <= vVolumeLimit) THEN CALL ticket_splitItemPackingType(vTicketFk, vItemPackingTypeFk); DROP TEMPORARY TABLE tmp.ticketIPT; SELECT COUNT(*), SUM(litros), MAX(i.`size`), SUM(sv.volume) INTO vLines, vLiters, vHeight, vVolume FROM saleVolume sv JOIN sale s ON s.id = sv.saleFk JOIN item i ON i.id = s.itemFk WHERE sv.ticketFk = vTicketFk; SET vTotalVolume = vTotalVolume + vVolume, vTotalLines = vTotalLines + vLines; UPDATE tmp.productionBuffer pb SET pb.liters = vLiters, pb.`lines` = vLines, pb.height = vHeight WHERE pb.ticketFk = vTicketFk; UPDATE tTrain tt JOIN tmp.productionBuffer pb ON pb.ticketFk = vTicketFk SET tt.ticketFk = pb.ticketFk WHERE tt.liters >= pb.liters AND tt.`lines` >= pb.`lines` AND (tt.height >= pb.height OR vItemPackingTypeFk <> 'V') AND tt.ticketFk IS NULL ORDER BY wagon, shelve, tt.liters, tt.`lines`, tt.height LIMIT 1; -- Si no le encuentra una balda, intentamos darle un carro entero libre IF NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN SELECT wagon INTO vFreeWagonFk FROM tTrain GROUP BY wagon HAVING COUNT(ticketFk) = 0 ORDER BY wagon LIMIT 1; IF vFreeWagonFk THEN UPDATE tTrain SET ticketFk = vFirstTicketFk WHERE wagon = vFreeWagonFk; -- Se anulan el resto de carros libres, -- máximo un carro con pedido excesivo DELETE tt FROM tTrain tt JOIN (SELECT wagon FROM tTrain GROUP BY wagon HAVING COUNT(ticketFk) = 0 ) sub ON sub.wagon = tt.wagon; END IF; END IF; END IF; END LOOP; CLOSE vTickets; IF (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN -- Se obtiene nº de colección INSERT INTO collection SET itemPackingTypeFk = vItemPackingTypeFk, trainFk = vTrainFk, wagons = vWagons, warehouseFk = vWarehouseFk; SELECT LAST_INSERT_ID() INTO vCollectionFk; -- Asigna las bandejas INSERT IGNORE INTO ticketCollection(ticketFk, collectionFk, `level`, wagon, liters) SELECT tt.ticketFk, vCollectionFk, tt.shelve, tt.wagon, tt.liters FROM tTrain tt WHERE tt.ticketFk IS NOT NULL ORDER BY tt.wagon, tt.shelve; -- Actualiza el estado de los tickets CALL collection_setState(vCollectionFk, vStateCode); -- Aviso para la preparacion previa INSERT INTO ticketDown(ticketFk, collectionFk) SELECT tc.ticketFk, tc.collectionFk FROM ticketCollection tc WHERE tc.collectionFk = vCollectionFk; CALL collection_mergeSales(vCollectionFk); UPDATE `collection` c JOIN( SELECT COUNT(*) saleTotalCount, SUM(s.isPicked <> 0) salePickedCount FROM ticketCollection tc JOIN sale s ON s.ticketFk = tc.ticketFk WHERE tc.collectionFk = vCollectionFk AND s.quantity > 0 )sub SET c.saleTotalCount = sub.saleTotalCount, c.salePickedCount = sub.salePickedCount WHERE c.id = vCollectionFk; ELSE SET vCollectionFk = NULL; END IF; DROP TEMPORARY TABLE tTrain, tmp.productionBuffer; END$$ DELIMITER ;