fixes: refs #7760 collection problems #2888

Merged
carlosap merged 7 commits from 7760-Refactor-collection_assign into dev 2024-08-28 15:27:16 +00:00
7 changed files with 354 additions and 426 deletions

View File

@ -13,39 +13,42 @@ BEGIN
* @param vCollectionFk Id de colección
*/
DECLARE vHasTooMuchCollections BOOL;
DECLARE vItemPackingTypeFk VARCHAR(1);
DECLARE vWarehouseFk INT;
DECLARE vLockName VARCHAR(215);
DECLARE vLockTime INT DEFAULT 30;
DECLARE vErrorNumber INT;
DECLARE vErrorMsg TEXT;
DECLARE vDone BOOL DEFAULT FALSE;
DECLARE vCollectionWorker INT;
DECLARE vMaxNotAssignedCollectionLifeTime TIME;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
vErrorNumber = MYSQL_ERRNO,
vErrorMsg = MESSAGE_TEXT;
CALL util.debugAdd('collection_assign', JSON_OBJECT(
'errorNumber', vErrorNumber,
'errorMsg', vErrorMsg,
'lockName', vLockName,
'userFk', vUserFk
)); -- Tmp
IF vLockName IS NOT NULL THEN
DO RELEASE_LOCK(vLockName);
END IF;
RESIGNAL;
END;
DECLARE vCollections CURSOR FOR
WITH collections AS (
SELECT tc.collectionFk,
SUM(sv.volume) volume,
c.saleTotalCount,
c.itemPackingTypeFk,
c.trainFk,
c.warehouseFk,
c.wagons
FROM vn.ticketCollection tc
JOIN vn.collection c ON c.id = tc.collectionFk
JOIN vn.saleVolume sv ON sv.ticketFk = tc.ticketFk
WHERE c.workerFk IS NULL
AND sv.shipped >= util.VN_CURDATE()
GROUP BY tc.collectionFk
) SELECT c.collectionFk
FROM collections c
JOIN vn.operator o
WHERE o.workerFk = vUserFk
AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL)
AND (c.itemPackingTypeFk = o.itemPackingTypeFk OR o.itemPackingTypeFk IS NULL)
AND o.numberOfWagons = c.wagons
AND o.trainFk = c.trainFk
AND o.warehouseFk = c.warehouseFk;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
-- Si hay colecciones sin terminar, sale del proceso
CALL collection_get(vUserFk);
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0,
collection_assign_lockname
INTO vHasTooMuchCollections,
vLockName
SELECT (pc.maxNotReadyCollections - COUNT(*)) <= 0, pc.maxNotAssignedCollectionLifeTime
INTO vHasTooMuchCollections, vMaxNotAssignedCollectionLifeTime
FROM productionConfig pc
LEFT JOIN tmp.collection ON TRUE;
@ -55,69 +58,69 @@ BEGIN
CALL util.throw('Hay colecciones pendientes');
END IF;
SELECT warehouseFk, itemPackingTypeFk
INTO vWarehouseFk, vItemPackingTypeFk
FROM operator
WHERE 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 eliminan las colecciones sin asignar que estan obsoletas
INSERT INTO ticketTracking(stateFk, ticketFk)
SELECT s.id, tc.ticketFk
FROM `collection` c
JOIN ticketCollection tc ON tc.collectionFk = c.id
JOIN `state` s ON s.code = 'PRINTED_AUTO'
JOIN productionConfig pc
WHERE c.workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
DELETE c.*
FROM `collection` c
JOIN productionConfig pc
WHERE c.workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), c.created) > pc.maxNotAssignedCollectionLifeTime;
INSERT INTO ticketTracking(stateFk, ticketFk)
SELECT s.id, tc.ticketFk
FROM `collection` c
JOIN ticketCollection tc ON tc.collectionFk = c.id
JOIN `state` s ON s.code = 'PRINTED_AUTO'
WHERE c.workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), c.created) > vMaxNotAssignedCollectionLifeTime;
DELETE FROM `collection`
WHERE workerFk IS NULL
AND TIMEDIFF(util.VN_NOW(), created) > vMaxNotAssignedCollectionLifeTime;
-- Se añade registro al semillero
INSERT INTO collectionHotbed(userFk)
VALUES(vUserFk);
INSERT INTO collectionHotbed(userFk) VALUES(vUserFk);
-- Comprueba si hay colecciones disponibles que se ajustan a su configuracion
SELECT MIN(c.id) INTO vCollectionFk
FROM `collection` c
JOIN operator o
ON (o.itemPackingTypeFk = c.itemPackingTypeFk OR c.itemPackingTypeFk IS NULL)
AND o.numberOfWagons = c.wagons
AND o.trainFk = c.trainFk
AND o.warehouseFk = c.warehouseFk
AND c.workerFk IS NULL
AND (c.saleTotalCount <= o.linesLimit OR o.linesLimit IS NULL)
JOIN (
SELECT tc.collectionFk, SUM(sv.volume) volume
FROM ticketCollection tc
JOIN saleVolume sv ON sv.ticketFk = tc.ticketFk
WHERE sv.shipped >= util.VN_CURDATE()
GROUP BY tc.collectionFk
) sub ON sub.collectionFk = c.id
AND (volume <= o.volumeLimit OR o.volumeLimit IS NULL)
WHERE o.workerFk = vUserFk;
OPEN vCollections;
l: LOOP
SET vDone = FALSE;
FETCH vCollections INTO vCollectionFk;
IF vDone THEN
LEAVE l;
END IF;
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
SET vCollectionFk = NULL;
RESIGNAL;
END;
START TRANSACTION;
SELECT workerFk INTO vCollectionWorker
FROM `collection`
WHERE id = vCollectionFk FOR UPDATE;
IF vCollectionWorker IS NULL THEN
UPDATE `collection`
SET workerFk = vUserFk
WHERE id = vCollectionFk;
COMMIT;
LEAVE l;
END IF;
ROLLBACK;
END;
END LOOP;
CLOSE vCollections;
IF vCollectionFk IS NULL THEN
CALL collection_new(vUserFk, vCollectionFk);
UPDATE `collection`
SET workerFk = vUserFk
WHERE id = vCollectionFk;
END IF;
UPDATE `collection`
SET workerFk = vUserFk
WHERE id = vCollectionFk;
DO RELEASE_LOCK(vLockName);
END$$
DELIMITER ;

View File

@ -0,0 +1,29 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_mergeSales`(vCollectionFk INT)
BEGIN
DECLARE vDone BOOL;
DECLARE vTicketFk INT;
carlosap marked this conversation as resolved
Review

??

??
DECLARE vTickets CURSOR FOR
SELECT ticketFk
carlosap marked this conversation as resolved
Review
El nombre del cursor no es correcto: https://wiki.verdnatura.es/index.php/Convenciones_SQL#Cursores
FROM ticketCollection
WHERE collectionFk = vCollectionFk;
carlosap marked this conversation as resolved
Review

Aquí sobre el vn.

Aquí sobre el `vn.`
DECLARE CONTINUE HANDLER FOR NOT FOUND
SET vDone = TRUE;
OPEN vTickets;
l: LOOP
SET vDone = FALSE;
FETCH vTickets INTO vTicketFk;
IF vDone THEN
LEAVE l;
END IF;
CALL ticket_mergeSales(vTicketFk);
END LOOP;
carlosap marked this conversation as resolved
Review

Aquí sobre el vn.

Aquí sobre el `vn.`
CLOSE vTickets;
END$$
DELIMITER ;

View File

@ -1,5 +1,8 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_new`(vUserFk INT, OUT vCollectionFk INT)
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`collection_new`(
vUserFk INT,
OUT vCollectionFk INT
)
BEGIN
/**
* Genera colecciones de tickets sin asignar trabajador.
@ -12,30 +15,29 @@ BEGIN
DECLARE vLinesLimit INT;
carlosap marked this conversation as resolved Outdated

Por defecto ya es NULL

Por defecto ya es NULL
DECLARE vTicketLines INT;
DECLARE vVolumeLimit DECIMAL;
carlosap marked this conversation as resolved Outdated

Por defecto ya es NULL

Por defecto ya es NULL
DECLARE vTicketVolume DECIMAL;
DECLARE vSizeLimit INT;
DECLARE vTicketVolume DECIMAL;
DECLARE vMaxTickets INT;
carlosap marked this conversation as resolved
Review

ja que estem renombra a vStateCode perque no es el id lo que es guarda sino el code, es confus

ja que estem renombra a vStateCode perque no es el id lo que es guarda sino el code, es confus
DECLARE vStateFk VARCHAR(45);
DECLARE vStateCode VARCHAR(45);
DECLARE vFirstTicketFk INT;
DECLARE vHour INT;
DECLARE vMinute INT;
DECLARE vWorkerCode VARCHAR(3);
DECLARE vWagonCounter INT DEFAULT 0;
DECLARE vWagonCounter INT DEFAULT 1;
DECLARE vTicketFk INT;
DECLARE vItemPackingTypeFk VARCHAR(1);
DECLARE vHasAssignedTickets BOOLEAN;
DECLARE vHasAssignedTickets BOOL;
DECLARE vHasUniqueCollectionTime BOOL;
DECLARE vDone INT DEFAULT FALSE;
DECLARE vLockName VARCHAR(215);
DECLARE vLockTime INT DEFAULT 30;
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 vErrorNumber INT;
DECLARE vErrorMsg TEXT;
DECLARE vDone INT DEFAULT FALSE;
DECLARE c1 CURSOR FOR
DECLARE vTickets CURSOR FOR
SELECT ticketFk, `lines`, m3
FROM tmp.productionBuffer
WHERE ticketFk <> vFirstTicketFk
ORDER BY HH,
mm,
productionOrder DESC,
@ -48,26 +50,6 @@ BEGIN
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
vErrorNumber = MYSQL_ERRNO,
vErrorMsg = MESSAGE_TEXT;
CALL util.debugAdd('collection_new', JSON_OBJECT(
'errorNumber', vErrorNumber,
'errorMsg', vErrorMsg,
'lockName', vLockName,
'userFk', vUserFk,
'ticketFk', vTicketFk
)); -- Tmp
IF vLockName IS NOT NULL THEN
DO RELEASE_LOCK(vLockName);
END IF;
RESIGNAL;
END;
SELECT pc.ticketTrolleyMax * o.numberOfWagons,
pc.hasUniqueCollectionTime,
w.code,
@ -78,36 +60,26 @@ BEGIN
o.trainFk,
o.linesLimit,
o.volumeLimit,
o.sizeLimit,
pc.collection_new_lockname
o.sizeLimit
INTO vMaxTickets,
vHasUniqueCollectionTime,
vWorkerCode,
vWarehouseFk,
vItemPackingTypeFk,
vStateFk,
vWagons,
vTrainFk,
vLinesLimit,
vVolumeLimit,
vSizeLimit,
vLockName
FROM productionConfig pc
JOIN worker w ON w.id = vUserFk
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 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;
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,
@ -118,59 +90,58 @@ BEGIN
PRIMARY KEY(wagon, shelve))
ENGINE = MEMORY;
WHILE vWagons > vWagonCounter DO
SET vWagonCounter = vWagonCounter + 1;
INSERT INTO tTrain(wagon, shelve, liters, `lines`, height)
SELECT vWagonCounter, cv.`level` , cv.liters , cv.`lines` , cv.height
FROM collectionVolumetry cv
WHERE cv.trainFk = vTrainFk
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;
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%';
-- 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;
-- Si hay tickets asignados, nos centramos exclusivamente en esos tickets
-- y los sacamos independientemente de problemas o tamaños
SELECT EXISTS (
carlosap marked this conversation as resolved
Review

Ací per que no fas aço?

	SELECT TRUE INTO vHasAssignedTickets
			FROM tmp.productionBuffer pb
				JOIN state s ON s.id = pb.state
			WHERE s.code = 'PICKER_DESIGNED'
				AND pb.workerCode = vWorkerCode;
				AND pb.workerCode = vWorkerCode
			LIMIT 1
Ací per que no fas aço? ``` SELECT TRUE INTO vHasAssignedTickets FROM tmp.productionBuffer pb JOIN state s ON s.id = pb.state WHERE s.code = 'PICKER_DESIGNED' AND pb.workerCode = vWorkerCode; AND pb.workerCode = vWorkerCode LIMIT 1 ```
Review
Per optimitzar: https://wiki.verdnatura.es/index.php/Convenciones_SQL#:~:text=SELECT%20EXISTS%20(SELECT%20TRUE%20FROM%20vn.ticket%20WHERE%20false%20LIMIT%201)%3B
Review

Pues en el cas de gastar EXISTS el LIMIT te sobra, ja que nomes trova un registre per a la execució, hi ha que canviar-ho en la wiki tame.

https://stackoverflow.com/questions/34759173/any-point-in-using-limit-in-exists-query

Pues en el cas de gastar EXISTS el LIMIT te sobra, ja que nomes trova un registre per a la execució, hi ha que canviar-ho en la wiki tame. https://stackoverflow.com/questions/34759173/any-point-in-using-limit-in-exists-query
Review

El LIMIT és per a que quan trove la primera coincidencia no continue, crec que optimitza el resultat, quan més registres tinga la taula més li costarà

El LIMIT és per a que quan trove la primera coincidencia no continue, crec que optimitza el resultat, quan més registres tinga la taula més li costarà
SELECT TRUE
FROM tmp.productionBuffer pb
JOIN state s ON s.id = pb.state
WHERE s.code = 'PICKER_DESIGNED'
AND pb.workerCode = vWorkerCode
) INTO vHasAssignedTickets;
-- 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
@ -193,72 +164,65 @@ 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) > 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);
carlosap marked this conversation as resolved
Review

Has quitado mis cambios

Has quitado mis cambios
OR LENGTH(pb.problem)
OR pb.lines > vLinesLimit
carlosap marked this conversation as resolved Outdated

LENGTH(pb.problem)

`LENGTH(pb.problem)`
OR pb.m3 > vVolumeLimit
OR sub.maxSize > vSizeLimit;
END IF;
-- 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,
productionOrder DESC,
m3 DESC,
agency,
zona,
routeFk,
ticketFk
LIMIT 1;
-- 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;
SELECT ticketFk INTO vFirstTicketFk
FROM tmp.productionBuffer
ORDER BY HH,
mm,
productionOrder DESC,
m3 DESC,
agency,
zona,
routeFk,
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);
END IF;
SET vTicketFk = vFirstTicketFk;
SET @lines = 0;
SET @volume = 0;
OPEN c1;
read_loop: LOOP
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 ((vTicketLines + @lines) <= vLinesLimit OR vLinesLimit IS NULL)
AND ((vTicketVolume + @volume) <= vVolumeLimit OR vVolumeLimit IS NULL) THEN
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
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
) sub
SET pb.liters = sub.liters,
pb.`lines` = sub.`lines`,
pb.height = sub.height
SET pb.liters = vLiters,
pb.`lines` = vLines,
pb.height = vHeight
WHERE pb.ticketFk = vTicketFk;
UPDATE tTrain tt
@ -275,17 +239,13 @@ BEGIN
tt.height
LIMIT 1;
-- Si no le encuentra una balda adecuada, intentamos darle un carro entero si queda alguno libre
-- Si no le encuentra una balda, intentamos darle un carro entero libre
IF NOT (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN
SELECT tt.wagon
INTO vFreeWagonFk
FROM tTrain tt
LEFT JOIN (
SELECT DISTINCT wagon
FROM tTrain
WHERE ticketFk IS NOT NULL
) nn ON nn.wagon = tt.wagon
WHERE nn.wagon IS NULL
SELECT wagon INTO vFreeWagonFk
FROM tTrain
GROUP BY wagon
HAVING SUM(IFNULL(ticketFk, 0)) = 0
ORDER BY wagon
guillermo marked this conversation as resolved Outdated

Me podries explicar esta part? Per que sumes els ticketFk??
Ho he vist tame baix

Me podries explicar esta part? Per que sumes els ticketFk?? Ho he vist tame baix

El que es vol és agafar el primer vagó lliure (sense tickets asignats) del tren

El que es vol és agafar el primer vagó lliure (sense tickets asignats) del tren
LIMIT 1;
@ -294,38 +254,35 @@ BEGIN
SET ticketFk = vFirstTicketFk
WHERE wagon = vFreeWagonFk;
-- Se anulan el resto de carros libres para que sólo uno lleve un pedido excesivo
DELETE tt.*
FROM tTrain tt
LEFT JOIN (
SELECT DISTINCT wagon
FROM tTrain
WHERE ticketFk IS NOT NULL
) nn ON nn.wagon = tt.wagon
WHERE nn.wagon IS NULL;
END IF;
END IF;
-- Se anulan el resto de carros libres,
-- máximo un carro con pedido excesivo
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;
DELETE tt
FROM tTrain tt
JOIN (SELECT wagon
FROM tTrain
GROUP BY wagon
HAVING SUM(IFNULL(ticketFk, 0)) = 0
) sub ON sub.wagon = tt.wagon;
END IF;
END IF;
END IF;
END LOOP;
CLOSE c1;
CLOSE vTickets;
IF (SELECT COUNT(*) FROM tTrain WHERE ticketFk) THEN
UPDATE collection c
JOIN state st ON st.code = 'ON_PREPARATION'
SET c.stateFk = st.id
WHERE c.id = vCollectionFk;
-- 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
@ -333,37 +290,34 @@ BEGIN
ORDER BY tt.wagon, tt.shelve;
-- Actualiza el estado de los tickets
CALL collection_setState(vCollectionFk, vStateFk);
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 sales_mergeByCollection(vCollectionFk);
CALL collection_mergeSales(vCollectionFk);
UPDATE `collection` c
JOIN (
JOIN(
SELECT COUNT(*) saleTotalCount,
SUM(s.isPicked <> 0) salePickedCount
FROM ticketCollection tc
carlosap marked this conversation as resolved
Review

SUM(s.isPicked)

`SUM(s.isPicked)`
Review

Crec que està fet per el 1 -1 com a valors de TRUE, és posible que algún formulari en access modifiquen el dato, el SUM el faría mal.

Crec que està fet per el 1 -1 com a valors de TRUE, és posible que algún formulari en access modifiquen el dato, el SUM el faría mal.
Review

Es que ho he comprovat, i si es -1 es TRUE, per lo tant fa el que volem

Es que ho he comprovat, i si es -1 es TRUE, per lo tant fa el que volem
Review

No és el mateix, estic segur, quan pugues heu mirem

No és el mateix, estic segur, quan pugues heu mirem
JOIN sale s ON s.ticketFk = tc.ticketFk
WHERE tc.collectionFk = vCollectionFk
AND s.quantity > 0
) sub
WHERE tc.collectionFk = vCollectionFk
AND s.quantity > 0
)sub
SET c.saleTotalCount = sub.saleTotalCount,
c.salePickedCount = sub.salePickedCount
WHERE c.id = vCollectionFk;
ELSE
DELETE FROM `collection`
WHERE id = vCollectionFk;
SET vCollectionFk = NULL;
SET vCollectionFk = NULL;
END IF;
DO RELEASE_LOCK(vLockName);
DROP TEMPORARY TABLE
tTrain,
tmp.productionBuffer;

View File

@ -1,41 +0,0 @@
DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`sales_merge`(vTicketFk INT)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;
CREATE OR REPLACE TEMPORARY TABLE tSalesToPreserve
(PRIMARY KEY (id))
ENGINE = MEMORY
SELECT s.id, s.itemFk, SUM(s.quantity) newQuantity
FROM sale s
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
WHERE s.ticketFk = vTicketFk
AND it.isMergeable
GROUP BY s.itemFk, s.price, s.discount;
START TRANSACTION;
UPDATE sale s
JOIN tSalesToPreserve stp ON stp.id = s.id
SET s.quantity = newQuantity
WHERE s.ticketFk = vTicketFk;
DELETE s.*
FROM sale s
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 ;

View File

@ -26,7 +26,7 @@ BEGIN
LEAVE myLoop;
END IF;
CALL vn.sales_merge(vTicketFk);
CALL ticket_mergeSales(vTicketFk);
carlosap marked this conversation as resolved Outdated

No poner vn.

No poner `vn.`
END LOOP;

View File

@ -0,0 +1,49 @@
DELIMITER $$
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
SELECT s.id, s.itemFk, SUM(s.quantity) newQuantity
FROM sale s
JOIN item i ON i.id = s.itemFk
JOIN itemType it ON it.id = i.typeFk
WHERE s.ticketFk = vSelf
AND it.isMergeable
GROUP BY s.itemFk, s.price, s.discount
HAVING COUNT(*) > 1;
guillermo marked this conversation as resolved
Review

HAVING COUNT(*);

`HAVING COUNT(*);`
Review

Se vol que siga més de 1 registre, si no te més d'un registre agrupat, el procès no farà merge de res.
Si el canviarem es crearía la taula per al registres en COUNT(*) = 1 i ixos hi ha que descartar-los

Se vol que siga més de 1 registre, si no te més d'un registre agrupat, el procès no farà merge de res. Si el canviarem es crearía la taula per al registres en COUNT(*) = 1 i ixos hi ha que descartar-los
Review

Val sí, tens tota la raó

Val sí, tens tota la raó
SELECT COUNT(*) INTO vHasSalesToMerge
FROM tSalesToPreserve;
IF vHasSalesToMerge THEN
UPDATE sale s
JOIN tSalesToPreserve stp ON stp.id = s.id
SET s.quantity = newQuantity;
DELETE s
FROM sale s
JOIN tSalesToPreserve stp ON stp.itemFk = s.itemFk
WHERE s.ticketFk = vSelf
AND s.id <> stp.id;
END IF;
COMMIT;
DROP TEMPORARY TABLE tSalesToPreserve;
END$$
DELIMITER ;

View File

@ -5,139 +5,73 @@ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`ticket_splitItemPac
)
BEGIN
/**
* Clona y reparte las ventas de un ticket en funcion del tipo de empaquetado.
* Respeta el id inicial para el tipo propuesto.
* Clona y reparte las líneas de ventas de un ticket en funcion del tipo de empaquetado.
* Respeta el id de ticket inicial para el tipo de empaquetado propuesto.
*
* @param vSelf Id ticket
* @param vOriginalItemPackingTypeFk Tipo para el que se reserva el número de ticket original
* @return table tmp.ticketIPT(ticketFk, itemPackingTypeFk)
* @param vOriginalItemPackingTypeFk Tipo empaquetado al que se mantiene el ticket original
*/
DECLARE vItemPackingTypeFk VARCHAR(1) DEFAULT 'H';
DECLARE vNewTicketFk INT;
DECLARE vPackingTypesToSplit INT;
DECLARE vDone INT DEFAULT FALSE;
DECLARE vErrorNumber INT;
DECLARE vErrorMsg TEXT;
DECLARE vHasItemPackingType BOOL;
DECLARE vItemPackingTypeFk INT;
DECLARE vNewTicketFk INT;
DECLARE vSaleGroup CURSOR FOR
SELECT itemPackingTypeFk
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL
ORDER BY (itemPackingTypeFk = vOriginalItemPackingTypeFk) DESC;
DECLARE vItemPackingTypes CURSOR FOR
SELECT DISTINCT itemPackingTypeFk
FROM tSalesToMove;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1
vErrorNumber = MYSQL_ERRNO,
vErrorMsg = MESSAGE_TEXT;
CALL util.debugAdd('ticket_splitItemPackingType', JSON_OBJECT(
'errorNumber', vErrorNumber,
'errorMsg', vErrorMsg,
'ticketFk', vSelf
)); -- Tmp
ROLLBACK;
RESIGNAL;
END;
START TRANSACTION;
SELECT id
FROM sale
WHERE ticketFk = vSelf
AND NOT quantity
FOR UPDATE;
DELETE FROM sale
WHERE NOT quantity
AND ticketFk = vSelf;
CREATE OR REPLACE TEMPORARY TABLE tSale
(PRIMARY KEY (id))
ENGINE = MEMORY
SELECT s.id, i.itemPackingTypeFk, IFNULL(sv.litros, 0) litros
FROM sale s
SELECT COUNT(*) INTO vHasItemPackingType
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
LEFT JOIN saleVolume sv ON sv.saleFk = s.id
WHERE s.ticketFk = vSelf;
WHERE t.id = vSelf
AND i.itemPackingTypeFk = vOriginalItemPackingTypeFk;
CREATE OR REPLACE TEMPORARY TABLE tSaleGroup
ENGINE = MEMORY
SELECT itemPackingTypeFk, SUM(litros) totalLitros
FROM tSale
GROUP BY itemPackingTypeFk;
IF NOT vHasItemPackingType THEN
CALL util.throw('The ticket has not sales with the itemPackingType');
END IF;
SELECT COUNT(*) INTO vPackingTypesToSplit
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
CREATE OR REPLACE TEMPORARY TABLE tmp.ticketIPT(
CREATE OR REPLACE TEMPORARY TABLE tSalesToMove (
carlosap marked this conversation as resolved Outdated

Como es una tabla que no sale del procedimiento, reenombrar a tSalesToMove

Como es una tabla que no sale del procedimiento, reenombrar a `tSalesToMove`
ticketFk INT,
itemPackingTypeFk VARCHAR(1)
) ENGINE = MEMORY;
saleFk INT,
itemPackingTypeFk INT
) ENGINE=MEMORY;
CASE vPackingTypesToSplit
WHEN 0 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
WHEN 1 THEN
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
SELECT vSelf, itemPackingTypeFk
FROM tSaleGroup
WHERE itemPackingTypeFk IS NOT NULL;
ELSE
OPEN vSaleGroup;
FETCH vSaleGroup INTO vItemPackingTypeFk;
INSERT INTO tSalesToMove (saleFk, itemPackingTypeFk)
SELECT s.id, i.itemPackingTypeFk
FROM ticket t
JOIN sale s ON s.ticketFk = t.id
JOIN item i ON i.id = s.itemFk
WHERE t.id = vSelf
AND i.itemPackingTypeFk <> vOriginalItemPackingTypeFk;
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vSelf, vItemPackingTypeFk);
OPEN vItemPackingTypes;
l: LOOP
SET vDone = FALSE;
FETCH vSaleGroup INTO vItemPackingTypeFk;
l: LOOP
SET vDone = FALSE;
FETCH vItemPackingTypes INTO vItemPackingTypeFk;
carlosap marked this conversation as resolved Outdated

vItemPackingTypeFk

vItemPackingTypeFk
IF vDone THEN
LEAVE l;
END IF;
IF vDone THEN
LEAVE l;
END IF;
CALL ticket_Clone(vSelf, vNewTicketFk);
CALL ticket_Clone(vSelf, vNewTicketFk);
INSERT INTO tmp.ticketIPT(ticketFk, itemPackingTypeFk)
VALUES(vNewTicketFk, vItemPackingTypeFk);
END LOOP;
UPDATE tSalesToMove
SET ticketFk = vNewTicketFk
WHERE itemPackingTypeFk = vItemPackingTypeFk;
CLOSE vSaleGroup;
END LOOP;
SELECT s.id
FROM sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
FOR UPDATE;
CLOSE vItemPackingTypes;
UPDATE sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = ts.itemPackingTypeFk
SET s.ticketFk = t.ticketFk;
UPDATE sale s
JOIN tSalesToMove stm ON stm.saleFk = s.id
SET s.ticketFk = stm.ticketFk
WHERE stm.ticketFk;
SELECT itemPackingTypeFk INTO vItemPackingTypeFk
FROM tSaleGroup sg
WHERE sg.itemPackingTypeFk IS NOT NULL
ORDER BY sg.itemPackingTypeFk
LIMIT 1;
UPDATE sale s
JOIN tSale ts ON ts.id = s.id
JOIN tmp.ticketIPT t ON t.itemPackingTypeFk = vItemPackingTypeFk
SET s.ticketFk = t.ticketFk
WHERE ts.itemPackingTypeFk IS NULL;
END CASE;
COMMIT;
DROP TEMPORARY TABLE
tSale,
tSaleGroup;
DROP TEMPORARY TABLE tSalesToMove;
END$$
DELIMITER ;