fix: refs #7760 collection_new
gitea/salix/pipeline/head This commit looks good Details

This commit is contained in:
Guillermo Bonet 2024-09-17 09:30:40 +02:00
parent 3fe1724e84
commit 267ce3167c
2 changed files with 189 additions and 164 deletions

View File

@ -1,8 +1,5 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_new`(
vUserFk INT,
OUT vCollectionFk INT
)
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`collection_new`(vUserFk INT, OUT vCollectionFk INT)
BEGIN
/**
* Genera colecciones de tickets sin asignar trabajador.
@ -15,29 +12,28 @@ BEGIN
DECLARE vLinesLimit INT;
DECLARE vTicketLines INT;
DECLARE vVolumeLimit DECIMAL;
DECLARE vSizeLimit INT;
DECLARE vTicketVolume DECIMAL;
DECLARE vSizeLimit INT;
DECLARE vMaxTickets INT;
DECLARE vStateCode VARCHAR(45);
DECLARE vStateFk VARCHAR(45);
DECLARE vFirstTicketFk INT;
DECLARE vHour INT;
DECLARE vMinute INT;
DECLARE vWorkerCode VARCHAR(3);
DECLARE vWagonCounter INT DEFAULT 1;
DECLARE vWagonCounter INT DEFAULT 0;
DECLARE vTicketFk INT;
DECLARE vItemPackingTypeFk VARCHAR(1);
DECLARE vHasAssignedTickets BOOL;
DECLARE vHasAssignedTickets BOOLEAN;
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 vLockName VARCHAR(215);
DECLARE vLockTime INT DEFAULT 30;
DECLARE vFreeWagonFk INT;
DECLARE vTickets CURSOR FOR
DECLARE c1 CURSOR FOR
SELECT ticketFk, `lines`, m3
FROM tmp.productionBuffer
WHERE ticketFk <> vFirstTicketFk
ORDER BY HH,
mm,
productionOrder DESC,
@ -50,6 +46,14 @@ BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
IF vLockName IS NOT NULL THEN
DO RELEASE_LOCK(vLockName);
END IF;
RESIGNAL;
END;
SELECT pc.ticketTrolleyMax * o.numberOfWagons,
pc.hasUniqueCollectionTime,
w.code,
@ -60,26 +64,36 @@ BEGIN
o.trainFk,
o.linesLimit,
o.volumeLimit,
o.sizeLimit
o.sizeLimit,
pc.collection_new_lockname
INTO vMaxTickets,
vHasUniqueCollectionTime,
vWorkerCode,
vWarehouseFk,
vItemPackingTypeFk,
vStateCode,
vStateFk,
vWagons,
vTrainFk,
vLinesLimit,
vVolumeLimit,
vSizeLimit
FROM worker w
JOIN operator o ON o.workerFk = w.id
vSizeLimit,
vLockName
FROM productionConfig pc
JOIN worker w ON w.id = vUserFk
JOIN state st ON st.`code` = 'ON_PREPARATION'
JOIN productionConfig pc
WHERE w.id = vUserFk;
JOIN operator o ON o.workerFk = vUserFk;
SET vLockName = CONCAT_WS('/',
vLockName,
vWarehouseFk,
vItemPackingTypeFk
);
IF NOT GET_LOCK(vLockName, vLockTime) THEN
CALL util.throw(CONCAT('Cannot get lock: ', vLockName));
END IF;
-- Se prepara el tren, con tantos vagones como sea necesario.
CREATE OR REPLACE TEMPORARY TABLE tTrain
(wagon INT,
shelve INT,
@ -90,58 +104,59 @@ BEGIN
PRIMARY KEY(wagon, shelve))
ENGINE = MEMORY;
WHILE vWagons > vWagonCounter DO
SET vWagonCounter = vWagonCounter + 1;
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
SELECT vWagonCounter, cv.`level` , cv.liters , cv.`lines` , cv.height
FROM collectionVolumetry cv
WHERE cv.trainFk = vTrainFk
AND cv.itemPackingTypeFk = vItemPackingTypeFk;
END WHILE;
-- Esto desaparecerá cuando tengamos la table cache.ticket
CALL productionControl(vWarehouseFk, 0);
ALTER TABLE tmp.productionBuffer
ADD COLUMN liters INT,
ADD COLUMN height INT;
-- Se obtiene nº de colección.
INSERT INTO collection
SET itemPackingTypeFk = vItemPackingTypeFk,
trainFk = vTrainFk,
wagons = vWagons,
warehouseFk = vWarehouseFk;
SELECT LAST_INSERT_ID() INTO vCollectionFk;
-- 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
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
-- Comprobamos si hay tickets asignados. En ese caso, nos centramos
-- exclusivamente en esos tickets y los sacamos independientemente
-- de problemas o tamaños
SELECT COUNT(*) INTO vHasAssignedTickets
FROM tmp.productionBuffer pb
JOIN state s ON s.id = pb.state
WHERE s.code = 'PICKER_DESIGNED'
AND pb.workerCode = vWorkerCode
) INTO vHasAssignedTickets;
AND pb.workerCode = vWorkerCode;
-- Se dejan en la tabla tmp.productionBuffer sólo aquellos tickets adecuados
IF vHasAssignedTickets THEN
DELETE pb
DELETE pb.*
FROM tmp.productionBuffer pb
JOIN state s ON s.id = pb.state
WHERE s.code <> 'PICKER_DESIGNED'
OR pb.workerCode <> vWorkerCode;
ELSE
DELETE pb
DELETE pb.*
FROM tmp.productionBuffer pb
JOIN state s ON s.id = pb.state
JOIN agencyMode am ON am.id = pb.agencyModeFk
@ -164,17 +179,23 @@ BEGIN
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;
OR LENGTH(pb.problem) > 0
OR (pb.lines > vLinesLimit AND vLinesLimit IS NOT NULL)
OR (pb.m3 > vVolumeLimit AND vVolumeLimit IS NOT NULL)
OR ((sub.maxSize > vSizeLimit OR sub.maxSize IS NOT NULL) AND vSizeLimit IS NOT NULL);
END IF;
-- Hay que excluir aquellos que no tengan la misma hora de preparacion, si procede
IF vHasUniqueCollectionTime THEN
SELECT ticketFk INTO vFirstTicketFk
-- Es importante que el primer ticket se coja en todos los casos
SELECT ticketFk,
HH,
mm,
`lines`,
m3
INTO vFirstTicketFk,
vHour,
vMinute,
vTicketLines,
vTicketVolume
FROM tmp.productionBuffer
ORDER BY HH,
mm,
@ -186,44 +207,44 @@ BEGIN
ticketFk
LIMIT 1;
DELETE pb
FROM tmp.productionBuffer pb
JOIN tmp.productionBuffer pb2 ON pb2.ticketFk = vFirstTicketFk
AND (pb.HH <> pb2.HH OR pb.mm <> pb2.mm);
-- Hay que excluir aquellos que no tengan la misma hora de preparacion, si procede
IF vHasUniqueCollectionTime THEN
DELETE FROM tmp.productionBuffer
WHERE HH <> vHour
OR mm <> vMinute;
END IF;
OPEN vTickets;
l: LOOP
SET vTicketFk = vFirstTicketFk;
SET @lines = 0;
SET @volume = 0;
OPEN c1;
read_loop: 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
IF ((vTicketLines + @lines) <= vLinesLimit OR vLinesLimit IS NULL)
AND ((vTicketVolume + @volume) <= vVolumeLimit OR vVolumeLimit IS NULL) 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
UPDATE tmp.productionBuffer pb
JOIN (
SELECT SUM(litros) liters,
@lines:= COUNT(*) + @lines,
COUNT(*) `lines`,
MAX(i.`size`) height,
@volume := SUM(sv.volume) + @volume,
SUM(sv.volume) volume
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 sv.ticketFk = vTicketFk
) sub
SET pb.liters = sub.liters,
pb.`lines` = sub.`lines`,
pb.height = sub.height
WHERE pb.ticketFk = vTicketFk;
UPDATE tTrain tt
@ -240,13 +261,17 @@ BEGIN
tt.height
LIMIT 1;
-- Si no le encuentra una balda, intentamos darle un carro entero libre
-- Si no le encuentra una balda adecuada, intentamos darle un carro entero si queda alguno libre
IF NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN
SELECT wagon INTO vFreeWagonFk
SELECT tt.wagon
INTO vFreeWagonFk
FROM tTrain tt
LEFT JOIN (
SELECT DISTINCT wagon
FROM tTrain
GROUP BY wagon
HAVING SUM(IFNULL(ticketFk, 0)) = 0
WHERE ticketFk IS NOT NULL
) nn ON nn.wagon = tt.wagon
WHERE nn.wagon IS NULL
ORDER BY wagon
LIMIT 1;
@ -255,35 +280,38 @@ BEGIN
SET ticketFk = vFirstTicketFk
WHERE wagon = vFreeWagonFk;
-- Se anulan el resto de carros libres,
-- máximo un carro con pedido excesivo
DELETE tt
-- Se anulan el resto de carros libres para que sólo uno lleve un pedido excesivo
DELETE tt.*
FROM tTrain tt
JOIN (SELECT wagon
LEFT JOIN (
SELECT DISTINCT wagon
FROM tTrain
GROUP BY wagon
HAVING SUM(IFNULL(ticketFk, 0)) = 0
) sub ON sub.wagon = tt.wagon;
WHERE ticketFk IS NOT NULL
) nn ON nn.wagon = tt.wagon
WHERE nn.wagon IS NULL;
END IF;
END IF;
FETCH c1 INTO vTicketFk, vTicketLines, vTicketVolume;
IF vDone OR NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk IS NULL) THEN
LEAVE read_loop;
END IF;
ELSE
FETCH c1 INTO vTicketFk, vTicketLines, vTicketVolume;
IF vDone THEN
LEAVE read_loop;
END IF;
END IF;
END LOOP;
CLOSE vTickets;
CLOSE c1;
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;
UPDATE collection c
JOIN state st ON st.code = 'ON_PREPARATION'
SET c.stateFk = st.id
WHERE c.id = 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
@ -291,17 +319,15 @@ BEGIN
ORDER BY tt.wagon, tt.shelve;
-- Actualiza el estado de los tickets
CALL collection_setState(vCollectionFk, vStateCode);
CALL collection_setState(vCollectionFk, vStateFk);
-- 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);
CALL sales_mergeByCollection(vCollectionFk);
UPDATE `collection` c
JOIN (
@ -315,10 +341,15 @@ BEGIN
SET c.saleTotalCount = sub.saleTotalCount,
c.salePickedCount = sub.salePickedCount
WHERE c.id = vCollectionFk;
ELSE
DELETE FROM `collection`
WHERE id = vCollectionFk;
SET vCollectionFk = NULL;
END IF;
DO RELEASE_LOCK(vLockName);
DROP TEMPORARY TABLE
tTrain,
tmp.productionBuffer;

View File

@ -3,19 +3,12 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_mergeSales`(
vSelf INT
)
BEGIN
DECLARE vHasSalesToMerge BOOL;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
SELECT id INTO vSelf
FROM ticket
WHERE id = vSelf FOR UPDATE;
CREATE OR REPLACE TEMPORARY TABLE tSalesToPreserve
(PRIMARY KEY (id))
ENGINE = MEMORY
@ -23,27 +16,28 @@ BEGIN
FROM sale s
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
WHERE s.ticketFk = vSelf
WHERE s.ticketFk = vTicketFk
AND it.isMergeable
GROUP BY s.itemFk, s.price, s.discount
HAVING COUNT(*) > 1;
GROUP BY s.itemFk, s.price, s.discount;
SELECT COUNT(*) INTO vHasSalesToMerge
FROM tSalesToPreserve;
START TRANSACTION;
IF vHasSalesToMerge THEN
UPDATE sale s
JOIN tSalesToPreserve stp ON stp.id = s.id
SET s.quantity = newQuantity;
SET s.quantity = newQuantity
WHERE s.ticketFk = vTicketFk;
DELETE s
DELETE s.*
FROM sale s
JOIN tSalesToPreserve stp ON stp.itemFk = s.itemFk
WHERE s.ticketFk = vSelf
AND s.id <> stp.id;
END IF;
LEFT JOIN tSalesToPreserve stp ON stp.id = s.id
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
WHERE s.ticketFk = vTicketFk
AND stp.id IS NULL
AND it.isMergeable;
COMMIT;
DROP TEMPORARY TABLE tSalesToPreserve;
END$$
DELIMITER ;