DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`inventoryMake`(vDate DATE, vWh INT)
proc: BEGIN
/**
* Recalcula los inventarios de todos los almacenes, si vWh = 0
*
* @param vDate Fecha de los nuevos inventarios
* @param vWh almacen al cual hacer el inventario
*/

	DECLARE vDone BOOL;
	DECLARE vEntryFk INT;
	DECLARE vTravelFk INT;
	DECLARE vDateLastInventory DATE;
	DECLARE vDateYesterday DATETIME DEFAULT vDate - INTERVAL 1 SECOND;
	DECLARE vWarehouseOutFkInventory INT;
	DECLARE vInventorySupplierFk INT;
	DECLARE vAgencyModeFkInventory INT;

	DECLARE cWarehouses CURSOR FOR
		SELECT id
			FROM warehouse
			WHERE isInventory
				AND vWh IN (0,id);

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET vDone = TRUE;

	OPEN cWarehouses;
	SET @isModeInventory := TRUE;
	l: LOOP

		SET vDone = FALSE;
		FETCH cWarehouses INTO vWh;

		IF vDone THEN
			LEAVE l;
		END IF;

		SELECT w.id INTO vWarehouseOutFkInventory
			FROM warehouse w
			WHERE w.code = 'inv';

		SELECT inventorySupplierFk	INTO vInventorySupplierFk
			FROM entryConfig;

		SELECT am.id INTO vAgencyModeFkInventory
				FROM agencyMode am
					where code = 'inv';

		SELECT MAX(landed) INTO vDateLastInventory
			FROM travel tr
				JOIN entry e ON e.travelFk = tr.id
				JOIN buy b ON b.entryFk = e.id
			WHERE warehouseOutFk = vWarehouseOutFkInventory
				AND landed < vDate
				AND e.supplierFk = vInventorySupplierFk
				AND warehouseInFk = vWh
				AND NOT isRaid;

		IF vDateLastInventory IS NULL THEN
			SELECT inventoried INTO vDateLastInventory FROM config;
		END IF;

		-- Generamos travel, si no existe.
		SET vTravelFK = 0;

		SELECT id INTO vTravelFk
			FROM travel
			WHERE warehouseOutFk = vWarehouseOutFkInventory
				AND warehouseInFk = vWh
				AND landed = vDate
				AND agencyModeFk = vAgencyModeFkInventory
				AND ref = 'inventario'
			LIMIT 1;

		IF NOT vTravelFK THEN

			INSERT INTO travel SET
				warehouseOutFk = vWarehouseOutFkInventory,
				warehouseInFk = vWh,
				shipped = vDate,
				landed = vDate,
				agencyModeFk = vAgencyModeFkInventory,
				ref = 'inventario',
				isDelivered = TRUE,
				isReceived = TRUE;

			SELECT LAST_INSERT_ID() INTO vTravelFk;

		END IF;

		-- Generamos entrada si no existe, o la vaciamos.
		SET vEntryFk = 0;

		SELECT id INTO vEntryFk
			FROM entry
			WHERE supplierFk = vInventorySupplierFk
			AND travelFk = vTravelFk;

		IF NOT vEntryFk THEN

			INSERT INTO entry SET
				supplierFk = vInventorySupplierFk,
				isConfirmed = TRUE,
				isOrdered = TRUE,
				travelFk = vTravelFk;

			SELECT LAST_INSERT_ID() INTO vEntryFk;

		ELSE

			DELETE FROM buy WHERE entryFk = vEntryFk;

		END IF;

		-- Preparamos tabla auxilar
		CREATE OR REPLACE TEMPORARY TABLE tmp.inventory (
				itemFk INT(11) NOT NULL PRIMARY KEY,
				quantity int(11) DEFAULT '0',
				buyingValue decimal(10,4) DEFAULT '0.0000',
				freightValue decimal(10,3) DEFAULT '0.000',
				packing int(11) DEFAULT '0',
				`grouping` smallint(5) unsigned NOT NULL DEFAULT '1',
				groupingMode tinyint(4) NOT NULL DEFAULT 0 ,
				comissionValue decimal(10,3) DEFAULT '0.000',
				packageValue decimal(10,3) DEFAULT '0.000',
				packageFk varchar(10) COLLATE utf8_unicode_ci DEFAULT '--',
				price1 decimal(10,2) DEFAULT '0.00',
				price2 decimal(10,2) DEFAULT '0.00',
				price3 decimal(10,2) DEFAULT '0.00',
				minPrice decimal(10,2) DEFAULT '0.00',
				producer varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
		INDEX (itemFK)) ENGINE = MEMORY;

		-- Compras
		INSERT INTO tmp.inventory(itemFk,quantity)
			SELECT b.itemFk, SUM(b.quantity)
				FROM buy b
					JOIN entry e ON e.id = b.entryFk
					JOIN travel tr ON tr.id = e.travelFk
				WHERE tr.warehouseInFk = vWh
					AND tr.landed BETWEEN vDateLastInventory
					AND vDateYesterday
					AND NOT isRaid
				GROUP BY b.itemFk;
	SELECT vDateLastInventory , vDateYesterday;

		-- Traslados
		INSERT INTO tmp.inventory(itemFk, quantity)
			SELECT itemFk, quantityOut
			FROM (
					SELECT b.itemFk,- SUM(b.quantity) quantityOut
						FROM buy b
							JOIN entry e ON e.id = b.entryFk
							JOIN travel tr ON tr.id = e.travelFk
						WHERE tr.warehouseOutFk = vWh
							AND tr.shipped BETWEEN vDateLastInventory
							AND vDateYesterday
							AND NOT isRaid
						GROUP BY b.itemFk
				) sub
			ON DUPLICATE KEY UPDATE quantity = IFNULL(quantity, 0) + sub.quantityOut;

		-- Ventas
		INSERT INTO tmp.inventory(itemFk,quantity)
			SELECT itemFk, saleOut
			FROM (
					SELECT s.itemFk, - SUM(s.quantity) saleOut
						FROM sale s
							JOIN ticket t ON t.id = s.ticketFk
						WHERE t.warehouseFk = vWh
							AND t.shipped BETWEEN vDateLastInventory AND vDateYesterday
						GROUP BY s.itemFk
				) sub
			ON DUPLICATE KEY UPDATE quantity = IFNULL(quantity,0) + sub.saleOut;

		-- Actualiza valores de la ultima compra
		UPDATE tmp.inventory inv
				JOIN cache.last_buy lb ON lb.item_id = inv.itemFk AND lb.warehouse_id = vWh
				JOIN buy b ON b.id = lb.buy_id
				JOIN item i ON i.id = b.itemFk
				LEFT JOIN producer p ON p.id = i.producerFk
			SET inv.buyingValue = b.buyingValue,
				inv.freightValue = b.freightValue,
				inv.packing = b.packing,
				inv.`grouping`= b.`grouping`,
				inv.groupingMode = b.groupingMode,
				inv.comissionValue = b.comissionValue,
				inv.packageValue = b.packageValue,
				inv.packageFk = b.packagingFk,
				inv.price1 = b.price1,
				inv.price2 = b.price2,
				inv.price3 = b.price3,
				inv.minPrice = b.minPrice,
				inv.producer = p.name;

		INSERT INTO buy( itemFk,
				quantity,
				buyingValue,
				freightValue,
				packing,
				`grouping`,
				groupingMode,
				comissionValue,
				packageValue,
				packagingFk,
				price1,
				price2,
				price3,
				minPrice,
				entryFk)
			SELECT itemFk,
					GREATEST(quantity, 0),
					buyingValue,
					freightValue,
					packing,
					`grouping`,
					groupingMode,
					comissionValue,
					packageValue,
					packageFk,
					price1,
					price2,
					price3,
					minPrice,
					vEntryFk
				FROM tmp.inventory;

		SELECT vWh, COUNT(*), util.VN_NOW() FROM tmp.inventory;

	-- Actualizamos el campo lastUsed de item
	UPDATE item i
			JOIN tmp.inventory i2 ON i2.itemFk = i.id
		SET i.lastUsed = NOW()
		WHERE i2.quantity;

	-- DROP TEMPORARY TABLE tmp.inventory;

	END LOOP;

	CLOSE cWarehouses;

	UPDATE config SET inventoried = vDate;
	SET @isModeInventory := FALSE;

	DROP TEMPORARY TABLE IF EXISTS tmp.entryToDelete;
	CREATE TEMPORARY TABLE tmp.entryToDelete
		(INDEX(entryId) USING BTREE) ENGINE = MEMORY
		SELECT e.id as entryId,
				t.id as travelId
			FROM travel t
				JOIN `entry` e ON e.travelFk = t.id
			WHERE e.supplierFk = vInventorySupplierFk
				AND t.shipped <= util.VN_CURDATE() - INTERVAL 12 DAY
				AND (DAY(t.shipped) <> 1 OR shipped < util.VN_CURDATE() - INTERVAL 12 DAY);

	DELETE e
		FROM `entry` e
			JOIN tmp.entryToDelete tmp ON tmp.entryId = e.id;

	DELETE IGNORE t
		FROM travel t
			JOIN tmp.entryToDelete tmp ON tmp.travelId = t.id;
END$$
DELIMITER ;
