DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `stock`.`log_sync`(vSync BOOL)
proc: BEGIN
	DECLARE vDone BOOL;
	DECLARE vLogId INT;
	DECLARE vHasPendingSync BOOL;
	DECLARE vOperation VARCHAR(255);
	DECLARE vTableName VARCHAR(255);
	DECLARE vTableId VARCHAR(255);
	DECLARE vInboundFk INT;
	DECLARE vOutboundFk INT;

	DECLARE cInbound CURSOR FOR
		SELECT id FROM inbound
			WHERE !isSync
			ORDER BY dated;

	DECLARE cOutbound CURSOR FOR
		SELECT id FROM outbound
			WHERE !isSync
			ORDER BY dated;

	DECLARE CONTINUE HANDLER FOR NOT FOUND
		SET vDone = TRUE;

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

	-- Applies changes

	opsLoop: LOOP
		START TRANSACTION;

		SET vDone = FALSE;
		SELECT id, operation, tableName, tableId
			INTO vLogId, vOperation, vTableName, vTableId
			FROM `log`
			ORDER BY id LIMIT 1
			FOR UPDATE;

		IF vDone THEN
			COMMIT;
			LEAVE opsLoop;
		END IF;

		CALL log_delete(vTableName, vTableId);

		IF vOperation = 'insert' THEN
			IF vTableName IN ('travel', 'entry', 'buy') THEN
				CALL log_refreshBuy(vTableName, vTableId);
			ELSEIF vTableName IN ('ticket', 'sale') THEN
				CALL log_refreshSale(vTableName, vTableId);
			ELSEIF vTableName IN ('order', 'orderRow') THEN
				CALL log_refreshOrder(vTableName, vTableId);
			END IF;
		END IF;

		DELETE FROM `log` WHERE id = vLogId;
		SET vSync = TRUE;

		COMMIT;
	END LOOP;

	IF !vSync THEN
		LEAVE proc;
	END IF;

	-- Deletes expired outbounds

	DELETE FROM outbound WHERE expired <= util.VN_NOW();

	-- Attaches desync inbounds

	REPEAT
		OPEN cInbound;
		SET vHasPendingSync = FALSE;

		inboundLoop: LOOP
			SET vDone = FALSE;
			FETCH cInbound INTO vInboundFk;

			IF vDone THEN
				LEAVE inboundLoop;
			END IF;

			START TRANSACTION;
			CALL inbound_sync(vInboundFk);
			COMMIT;

			SET vHasPendingSync = TRUE;
		END LOOP;

		CLOSE cInbound;
	UNTIL !vHasPendingSync END REPEAT;

	-- Attaches desync outbounds

	REPEAT
		OPEN cOutbound;
		SET vHasPendingSync = FALSE;

		outboundLoop: LOOP
			SET vDone = FALSE;
			FETCH cOutbound INTO vOutboundFk;

			IF vDone THEN
				LEAVE outboundLoop;
			END IF;

			START TRANSACTION;
			CALL outbound_sync(vOutboundFk);
			COMMIT;

			SET vHasPendingSync = TRUE;
		END LOOP;

		CLOSE cOutbound;
	UNTIL !vHasPendingSync END REPEAT;
END$$
DELIMITER ;