DELIMITER $$
CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`ticket_setState`(
	vSelf INT,
	vStateCode VARCHAR(255) COLLATE utf8_general_ci
)
proc:BEGIN
/**
 * Modifica el estado de un ticket si se cumplen las condiciones necesarias.
 *
 * @param vSelf el id del ticket
 * @param vStateCode estado a modificar del ticket
 */
	DECLARE vTicketAlertLevel INT;
	DECLARE vTicketStateCode VARCHAR(255) COLLATE utf8_general_ci;
	DECLARE vCanChangeState BOOL;
	DECLARE vPackedAlertLevel INT;
	DECLARE vZoneFk INT;
	DECLARE vOldWorkerFk INT;
	DECLARE vNewWorkerFk INT;

	SET vNewWorkerFk = account.myUser_getId();

	SELECT s.alertLevel, s.`code`, t.zoneFk, tt.userFk
		INTO vTicketAlertLevel, vTicketStateCode, vZoneFk, vOldWorkerFk
		FROM state s
			JOIN ticketTracking tt ON tt.stateFk = s.id
			JOIN ticket t ON t.id = tt.ticketFk
		WHERE tt.ticketFk = vSelf
		ORDER BY tt.created DESC
		LIMIT 1;

	SELECT id INTO vPackedAlertLevel FROM alertLevel WHERE code = 'PACKED'; 

	IF vStateCode = 'OK' AND vZoneFk IS NULL THEN
		CALL util.throw('ASSIGN_ZONE_FIRST');
	END IF;

	SET vCanChangeState = ((
			vStateCode <> 'ON_CHECKING' AND vStateCode <> 'CHECKED') OR 
			vTicketAlertLevel < vPackedAlertLevel
		) AND NOT (
			vTicketStateCode IN ('CHECKED', 'CHECKING')
			AND vStateCode IN ('PREPARED', 'ON_PREPARATION')
		);

	IF vCanChangeState THEN
		IF vStateCode = 'PACKED' THEN
			CALL ticket_doCmr(vSelf);
		END IF;

		IF vStateCode = vTicketStateCode AND vOldWorkerFk = vNewWorkerFk THEN
			LEAVE proc;
		END IF;

		INSERT INTO ticketTracking (stateFk, ticketFk, userFk)
			SELECT id, vSelf, vNewWorkerFk
				FROM state
				WHERE `code` = vStateCode COLLATE utf8_unicode_ci;
	ELSE
		CALL util.throw('INCORRECT_TICKET_STATE');
	END IF;
END$$
DELIMITER ;
