DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`itemShelvingSale_setQuantity`(
	vItemShelvingSaleFk INT(10),
	vQuantity DECIMAL(10,0),
	vIsItemShelvingSaleEmpty BOOLEAN,
	vSectorFk INT,
	vShelvingFk VARCHAR(10)
)
BEGIN
/**
 * Gestiona la reserva de un itemShelvingFk, actualizando isPicked y quantity
 * en itemShelvingSale y sale.isPicked en caso necesario. 
 * Si la reserva de la ubicación es fallida, se regulariza la situación 
 * 
 * @param vItemShelvingSaleFk Id itemShelvingSaleFK 
 * @param vQuantity Cantidad real que se ha cogido de la ubicación
 * @param vIsItemShelvingSaleEmpty determina si la ubicación itemShelvingSale se ha 
 * quedado vacio tras el movimiento
 * @param vSectorFk Id del sector
 */
	DECLARE vSaleFk INT;
	DECLARE vItemShelvingFk INT;
	DECLARE vReservedQuantity INT;
	DECLARE vRemainingQuantity INT;
	DECLARE vItemFk INT;
	DECLARE vTotalQuantity INT;
	DECLARE vStateCode VARCHAR(45);
	DECLARE vCurrentShelvingFk VARCHAR(10);

	DECLARE EXIT HANDLER FOR SQLEXCEPTION
		BEGIN
			ROLLBACK;
			RESIGNAL;
		END;

	IF vQuantity > vReservedQuantity 
		OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty)
		OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN
		CALL util.throw('The quantity cannot be different from the reserved');
	END IF;

	IF (SELECT isPicked FROM itemShelvingSale WHERE id = vItemShelvingSaleFk) THEN
		CALL util.throw('Reservation completed');
	END IF;

	SELECT s.itemFk, 
			iss.saleFk, 
			iss.itemShelvingFk, 
			SUM(IFNULL(iss.quantity,0)), 
			IF(sgd.id, 'PREVIOUS_PREPARATION', 'PREPARED'),
			ish.shelvingFk
		INTO vItemFk, 
			vSaleFk, 
			vItemShelvingFk, 
			vReservedQuantity, 
			vStateCode,
			vCurrentShelvingFk
		FROM itemShelvingSale iss
			JOIN sale s ON s.id = iss.saleFk
			JOIN itemShelving ish ON ish.id = iss.itemShelvingFk
			LEFT JOIN vn.saleGroupDetail sgd ON sgd.saleFk = iss.saleFk
		WHERE iss.id = vItemShelvingSaleFk
			AND NOT iss.isPicked;

	IF NOT (vCurrentShelvingFk <=> vShelvingFk) THEN
		CALL util.throw('The shelving can not be different from the shelving reserved');
	END IF;

	IF vQuantity > vReservedQuantity 
		OR (vQuantity < vReservedQuantity AND NOT vIsItemShelvingSaleEmpty)
		OR (vQuantity = vReservedQuantity AND vIsItemShelvingSaleEmpty) THEN
		CALL util.throw('The quantity cannot be different from the reserved');
	END IF;

	START TRANSACTION;

	UPDATE itemShelvingSale 
		SET isPicked = TRUE,
			quantity = vQuantity
		WHERE id = vItemShelvingSaleFk;	
	
	SELECT id INTO vItemShelvingFk 
		FROM itemShelving 
		WHERE id = vItemShelvingFk
		FOR UPDATE;

	UPDATE itemShelving
		SET visible = GREATEST(0, visible - vQuantity)
		WHERE id = vItemShelvingFk;

	SELECT SUM(IF(isPicked OR id = vItemShelvingSaleFk, 0, quantity)), SUM(quantity) 
		INTO vRemainingQuantity, vTotalQuantity
		FROM itemShelvingSale 
			WHERE saleFk = vSaleFk;

	IF vRemainingQuantity = 0 AND NOT vIsItemShelvingSaleEmpty THEN
		CALL saleTracking_new(
			vSaleFk,
			TRUE, 
			vTotalQuantity, 
			`account`.`myUser_getId`(), 
			NULL,
			vStateCode,
			TRUE);

		UPDATE sale s
			SET s.quantity = vTotalQuantity,
				isPicked = TRUE
			WHERE s.id = vSaleFk;
	END IF;

	COMMIT;
	
	IF vIsItemShelvingSaleEmpty AND vQuantity <> vReservedQuantity THEN
		INSERT INTO itemShelvingSaleReserve (saleFk, sectorFk)
			SELECT vSaleFk, vSectorFk;
		CALL itemShelvingSale_reallocate(vItemShelvingFk, vItemFk, vSectorFk);
	END IF;
END$$
DELIMITER ;