DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `hedera`.`order_addItem`(
	vSelf INT,
	vWarehouse INT,
	vItem INT,
	vAmount INT)
BEGIN
/**
 * Adds an item to the order, checking availability and grouping.
 *
 * @param vSelf The order id
 * @param vWarehouse The warehouse id
 * @param vItem The item id
 * @param vAmount The amount to add
 */
	DECLARE vRow INT;
	DECLARE vAdd INT;
	DECLARE vAvailable INT;
	DECLARE vMinQuantity INT;
	DECLARE vDone BOOL;
	DECLARE vGrouping INT;
	DECLARE vRate INT;
	DECLARE vShipment DATE;
	DECLARE vPrice DECIMAL(10,2);
	DECLARE cur CURSOR FOR
		SELECT `grouping`, price, rate
			FROM tmp.ticketComponentPrice
			WHERE warehouseFk = vWarehouse
				AND itemFk = vItem
			ORDER BY `grouping` DESC;

	DECLARE CONTINUE HANDLER FOR NOT FOUND
		SET vDone = TRUE;

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

	CALL order_calcCatalogFromItem(vSelf, vItem);
	START TRANSACTION;

	CALL order_checkEditable(vSelf);

	SELECT shipped INTO vShipment
		FROM tmp.zoneGetShipped
		WHERE warehouseFk = vWarehouse;

	SELECT available INTO vAvailable
		FROM tmp.ticketLot
		WHERE warehouseFk = vWarehouse
			AND itemFk = vItem;

	IF vAvailable IS NULL THEN
		SET vAvailable = 0;
	END IF;

	IF vAmount > vAvailable THEN
		CALL util.throw ('ORDER_ROW_UNAVAILABLE');
	END IF;

	WITH itemMinQuantityPriority AS (
		SELECT quantity,
				ROW_NUMBER() OVER (
					PARTITION BY itemFk
					ORDER BY warehouseFk IS NULL
				) priority
		FROM vn.itemMinimumQuantity
		WHERE itemFk = vItem
			AND `started` <= vShipment
			AND (`ended` >= vShipment OR `ended` IS NULL)
			AND (warehouseFk = vWarehouse OR warehouseFk IS NULL)
	)
	SELECT quantity INTO vMinQuantity
		FROM itemMinQuantityPriority
		WHERE priority = 1;

	IF vAmount < LEAST(IFNULL(vMinQuantity, 0), vAvailable)  THEN
		CALL util.throw ('quantityLessThanMin');
	END IF;

	OPEN cur;

	l: LOOP
		SET vDone = FALSE;
		FETCH cur INTO vGrouping, vPrice, vRate;

		IF vDone THEN
			LEAVE l;
		END IF;

		SET vAdd = vAmount - MOD(vAmount, vGrouping);
		SET vAmount = vAmount - vAdd;

		IF vAdd = 0 THEN
			ITERATE l;
		END IF;

		INSERT INTO orderRow SET
			orderFk = vSelf,
			itemFk = vItem,
			warehouseFk = vWarehouse,
			shipment = vShipment,
			rate = vRate,
			amount = vAdd,
			price = vPrice;

		CALL cache.available_updateItem(vItem, vWarehouse, vShipment, vAdd);

		SET vRow = LAST_INSERT_ID();

		INSERT INTO orderRowComponent (rowFk, componentFk, price)
			SELECT vRow, c.componentFk, c.cost
				FROM tmp.ticketComponent c
					JOIN vn.component t
						ON t.id = c.componentFk
						AND (t.classRate IS NULL OR t.classRate = vRate)
				WHERE c.warehouseFk = vWarehouse
					AND c.itemFk = vItem;
	END LOOP;

	CLOSE cur;

	IF vAmount > 0 THEN
		CALL util.throw ('AMOUNT_NOT_MATCH_GROUPING');
	END IF;

	COMMIT;
	CALL vn.ticketCalculatePurge;
END$$
DELIMITER ;