DELIMITER $$
CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn`.`balance_create`(
	vStartingMonth INT,
	vEndingMonth INT,
	vCompany INT,
	vIsConsolidated BOOLEAN,
	vInterGroupSalesIncluded BOOLEAN
)
BEGIN
/**
 * Crea un balance financiero para una empresa durante 
 * un período de tiempo determinado.
 *
 * @param vStartingMonth Mes de inicio del período
 * @param vEndingMonth Mes de finalización del período
 * @param vCompany Identificador de la empresa
 * @param vIsConsolidated Indica si se trata de un balance consolidado
 * @param vInterGroupSalesIncluded Indica si se incluyen las ventas del grupo
 */
	DECLARE intGAP INT DEFAULT 7;
	DECLARE vYears INT DEFAULT 2;
	DECLARE vYear TEXT;
	DECLARE vOneYearAgo TEXT;
	DECLARE vTwoYearsAgo TEXT;
	DECLARE vQuery TEXT;
	DECLARE vConsolidatedGroup INT;
	DECLARE vStartingDate DATE DEFAULT '2020-01-01';
	DECLARE vCurYear INT DEFAULT YEAR(util.VN_CURDATE());
	DECLARE vStartingYear INT DEFAULT vCurYear - 2;
	DECLARE vTable TEXT;

	SET vTable = util.quoteIdentifier('balanceNestTree');
	SET vYear = util.quoteIdentifier(vCurYear);
	SET vOneYearAgo = util.quoteIdentifier(vCurYear-1);
	SET vTwoYearsAgo = util.quoteIdentifier(vCurYear-2);

	-- Solicitamos la tabla tmp.nest, como base para el balance.
	DROP TEMPORARY TABLE IF EXISTS tmp.nest;

	EXECUTE IMMEDIATE CONCAT(
		'CREATE TEMPORARY TABLE tmp.nest
			SELECT node.id
					,CONCAT( REPEAT(REPEAT(" ",?), COUNT(parent.id) - 1), 
					node.name) name,
					node.lft,
					node.rgt,
					COUNT(parent.id) - 1 depth,
					CAST((node.rgt - node.lft - 1) / 2 AS DECIMAL) sons
				FROM ', vTable, ' node,
					', vTable, ' parent
				WHERE node.lft BETWEEN parent.lft AND parent.rgt
				GROUP BY node.id
				ORDER BY node.lft')
		USING intGAP;

	CREATE OR REPLACE TEMPORARY TABLE tmp.balance
		SELECT * FROM tmp.nest;

		SELECT companyGroupFk INTO vConsolidatedGroup
			FROM company
			WHERE id = vCompany;

	CREATE OR REPLACE TEMPORARY TABLE tCompanyReceiving
		SELECT id companyFk
			FROM company
			WHERE id = vCompany
				OR companyGroupFk = IF(vIsConsolidated, vConsolidatedGroup, NULL);

	CREATE OR REPLACE TEMPORARY TABLE tCompanyIssuing
		SELECT id companyFk
			FROM supplier p;

		IF NOT vInterGroupSalesIncluded THEN

			DELETE ci
				FROM tCompanyIssuing ci
					JOIN company e on e.id = ci.companyFk
				WHERE e.companyGroupFk = vConsolidatedGroup;

		END IF;

	-- Se calculan las facturas que intervienen, 
	-- para luego poder servir el desglose desde aqui.
	CREATE OR REPLACE TEMPORARY TABLE tmp.balanceDetail
		SELECT cr.companyFk receivingId,
				ci.companyFk issuingId,
				YEAR(IFNULL(r.bookEntried,IFNULL(r.booked, r.issued))) `year`,
				MONTH(IFNULL(r.bookEntried,IFNULL(r.booked, r.issued))) `month`,
				expenseFk,
				SUM(taxableBase) amount
			FROM invoiceIn r
				JOIN invoiceInTax ri on ri.invoiceInFk = r.id
				JOIN tCompanyReceiving cr on cr.companyFk = r.companyFk
				JOIN tCompanyIssuing ci ON ci.companyFk = r.supplierFk
			WHERE COALESCE(r.bookEntried, r.booked, r.issued) >= vStartingDate
				AND r.isBooked
			GROUP BY expenseFk, `year`, `month`, ci.companyFk, cr.companyFk;

	INSERT INTO tmp.balanceDetail(
			receivingId,
			issuingId,
			`year`,
			`month`,
			expenseFk,
			amount)
		SELECT em.companyFk,
				em.companyFk,
				`year`,
				`month`,
				expenseFk,
				SUM(em.amount)
			FROM expenseManual em
				JOIN tCompanyReceiving er ON er.companyFk = em.companyFk
			WHERE `year` >= vStartingYear
				AND `month` BETWEEN vStartingMonth AND vEndingMonth
			GROUP BY expenseFk, `year`, `month`, em.companyFk;

	DELETE FROM tmp.balanceDetail
		WHERE `month` < vStartingMonth
			OR `month` > vEndingMonth;

	-- Ahora el balance
	EXECUTE IMMEDIATE CONCAT(
		'ALTER TABLE tmp.balance
			ADD COLUMN ', vTwoYearsAgo ,' INT(10) NULL ,
			ADD COLUMN ', vOneYearAgo ,' INT(10) NULL ,
			ADD COLUMN ', vYear,' INT(10) NULL ,
			ADD COLUMN expenseFk VARCHAR(10) NULL,
			ADD COLUMN expenseName VARCHAR(45) NULL');

	-- Añadimos los gastos, para facilitar el formulario
	UPDATE tmp.balance b
			JOIN balanceNestTree bnt on bnt.id = b.id
			JOIN expense e ON e.id = bnt.expenseFk COLLATE utf8_general_ci
		SET b.expenseFk = e.id COLLATE utf8_general_ci,
			b.expenseName = e.name COLLATE utf8_general_ci ;

	-- Rellenamos los valores de primer nivel, los que corresponden 
	-- a los gastos simples.
	WHILE vYears >= 0 DO
		SET vQuery = CONCAT(
			'UPDATE tmp.balance b
					JOIN (
						SELECT expenseFk, SUM(amount) amount
							FROM tmp.balanceDetail
							WHERE year = ?
							GROUP BY expenseFk
					) sub on sub.expenseFk = b.expenseFk COLLATE utf8_general_ci
				SET ', util.quoteIdentifier(vCurYear - vYears), ' = - amount');

		EXECUTE IMMEDIATE vQuery
			USING vCurYear - vYears;

		SET vYears = vYears - 1;
	END WHILE;

	-- Añadimos las ventas.
	EXECUTE IMMEDIATE CONCAT(
		'UPDATE tmp.balance b
				JOIN (
					SELECT SUM(IF(year = ?, venta, 0)) y2,
							SUM(IF(year = ?, venta, 0)) y1,
							SUM(IF(year = ?, venta, 0)) y0,
							c.Gasto
						FROM bs.ventas_contables c
							JOIN tCompanyReceiving cr ON cr.companyFk = c.empresa_id
						WHERE month BETWEEN ? AND ?
						GROUP BY c.Gasto
				) sub ON sub.gasto = b.expenseFk COLLATE utf8_general_ci
			SET b.', vTwoYearsAgo, '= IFNULL(b.', vTwoYearsAgo, ', 0) + sub.y2,
				b.', vOneYearAgo, '= IFNULL(b.', vOneYearAgo, ', 0) + sub.y1,
				b.', vYear, '= IFNULL(b.', vYear, ', 0) + sub.y0')
		USING vCurYear-2,
			vCurYear-1,
			vCurYear,
			vStartingMonth,
			vEndingMonth;

	-- Ventas intra grupo.
	IF NOT vInterGroupSalesIncluded THEN

		SELECT lft, rgt INTO @groupLft, @groupRgt
			FROM tmp.balance b
			WHERE TRIM(b.`name`) = 'Grupo';

		DELETE
			FROM tmp.balance
			WHERE lft BETWEEN @groupLft AND @groupRgt;

	END IF;

	-- Rellenamos el valor de los padres con la suma de los hijos.
	CREATE OR REPLACE TEMPORARY TABLE tmp.balance_aux
		SELECT * FROM tmp.balance;

	EXECUTE IMMEDIATE
		CONCAT('UPDATE tmp.balance b
			JOIN (
				SELECT b1.id,
						b1.name,
						SUM(b2.', vYear,') thisYear,
						SUM(b2.', vOneYearAgo,') oneYearAgo,
						SUM(b2.', vTwoYearsAgo,') twoYearsAgo
					FROM tmp.nest b1
						JOIN tmp.balance_aux b2 on b2.lft BETWEEN b1.lft and b1.rgt
					GROUP BY b1.id
				)sub ON sub.id = b.id
			SET b.', vYear, ' = thisYear,
				b.', vOneYearAgo, ' = oneYearAgo,
				b.', vTwoYearsAgo, ' = twoYearsAgo');

	SELECT *, CONCAT('',IFNULL(expenseFk,'')) newgasto
		FROM tmp.balance;

	DROP TEMPORARY TABLE IF EXISTS tCompanyReceiving, tCompanyIssuing;
	
END$$
DELIMITER ;