text:
/* Fecha de ultima actualizacion 22/06/2016 */

/* se setea variable global log_bin_trust_function_creators				*/
/* sino tira el error:													*/
/*																		*/
/* This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA	*/
/* in its declaration and binary logging is enabled 					*/
/* (you *might* want to use the less safe 								*/
/* log_bin_trust_function_creators variable) 							*/

/* SET GLOBAL log_bin_trust_function_creators=1; */

/* censos_diarios_calcular */

DROP FUNCTION IF EXISTS censos_diarios_calcular_sala;

/*
*	Funcion que calcula y genera tabla temporal con los
*	datos del censo diario global de la sala
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			 0 = OK
*															-1 = si id_sala no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_calcular_sala (id_sala INTEGER, fecha_censo DATE)
    RETURNS INTEGER
    MODIFIES SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-2=id_sala no existe;-4=fecha no valida'

BEGIN

	DECLARE existencia0 SMALLINT;
	DECLARE existencia24 SMALLINT;
	DECLARE ingresos SMALLINT;
	DECLARE pases_de_salas SMALLINT;
	DECLARE pases_de_servicios SMALLINT;
	DECLARE altas SMALLINT;
	DECLARE defunciones_menos_48 SMALLINT;
	DECLARE defunciones_mas_48 SMALLINT;
	DECLARE pases_a_salas SMALLINT;
	DECLARE pases_a_servicios SMALLINT;
	DECLARE entradas_salidas_dia SMALLINT;
	DECLARE pacientes_dia SMALLINT;
	DECLARE dias_estada SMALLINT;
	DECLARE total_camas_sala SMALLINT;
	DECLARE camas_disponibles_sala SMALLINT;
	DECLARE entradas_salidas_pases_de_sala SMALLINT;
	DECLARE entradas_salidas_egresos_sala SMALLINT;
	DECLARE aux_id INTEGER;

	/* check si id_sala existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			salas s
		WHERE
			s.id_sala = id_sala);

	IF aux_id=0 THEN

		RETURN -2;

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		RETURN -4;

	END IF;

	/* existencia0 */
	SET existencia0 = (
		SELECT
			COUNT(DISTINCT p.id_internacion) AS cant
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala AND ss.id_sala = id_sala)
		WHERE
			DATE(p.fecha_entrada)<fecha_censo
		AND(p.fecha_salida IS NULL OR
			(p.fecha_salida IS NOT NULL AND DATE(p.fecha_salida)>=fecha_censo) )
		);

	/* existencia 24 */
	SET	existencia24=(

		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala)
		WHERE
			DATE(p.fecha_entrada) = fecha_censo) -

		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala)
		WHERE
			DATE(p.fecha_salida) = fecha_censo)
		);

	SET existencia24 = existencia0 + existencia24;

	/* ingresos */
	SET ingresos=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'I'
	);

	/* pases de salas */
	SET pases_de_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON
			p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase
			)
		);

	/* pases de servicios */
	SET pases_de_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON
			p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase
			)
		);

	/* altas */
	SET altas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE ss1.id_sala = id_sala
		AND DATE(p1.fecha_salida) = fecha_censo
		AND (p1.tipo_salida = 'A' OR p1.tipo_salida='T')
		);

	/* obitos - defunciones menos 48 hs */
	SET defunciones_menos_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND DATEDIFF(
				DATE(i.egr_fecha_hora),
				DATE(i.ing_fecha_hora)
				)<=1
		);

	/* obitos - defunciones mas 48 hs */
	SET defunciones_mas_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND DATEDIFF(
				DATE(i.egr_fecha_hora),
				DATE(i.ing_fecha_hora)
				)>1
		);

	/* pases a salas */
	SET pases_a_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase
			)
		);

	/* pases a servicios */
	SET pases_a_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase
			)
		);

	/* ---------------------------- */
	/* calcula entradas salidas dia */

		/* entradas/salidas dia pases de sala */
		SET entradas_salidas_pases_de_sala=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			INNER JOIN
				pases p2
			ON p1.id_pase_siguiente = p2.id_pase
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				ss1.id_sala = id_sala
			AND ss2.id_sala <> id_sala
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p2.fecha_entrada) = fecha_censo
			);

		/* e/s dia de altas-obitos-salidas transitorias */
		SET entradas_salidas_egresos_sala=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			WHERE
				ss1.id_sala = id_sala
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p1.fecha_salida) = fecha_censo
			AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'O' OR p1.tipo_salida = 'T')
			);

		/* entradas salidas dia (sala) */
		SET entradas_salidas_dia =
				entradas_salidas_pases_de_sala +
				entradas_salidas_egresos_sala;

	/* fin calcula entradas salidas dia */
	/* -------------------------------- */

	/* pacientes dia */
	SET pacientes_dia = existencia24 + entradas_salidas_dia;

	/* dias de estada sala */
	SET dias_estada = (
		SELECT

			IFNULL(
				SUM(
					IF(
						DATEDIFF(p2.fecha_salida,p2.fecha_entrada)=0,
						1,
						DATEDIFF(p2.fecha_salida,p2.fecha_entrada)
						)
					),
				0) AS dias_estada

		FROM
			pases p1
		INNER JOIN
			pases p2
		ON p1.id_internacion = p2.id_internacion
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			salas s1
		ON ss1.id_sala = s1.id_sala
		INNER JOIN
			servicios_salas ss2
		ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
		INNER JOIN
			salas s2
		ON ss2.id_sala = s2.id_sala
		WHERE
			DATE(p1.fecha_salida)=fecha_censo
		AND s1.id_sala = id_sala
		AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'T' OR p1.tipo_salida = 'O')

		);

	/* total camas sala */
	SET total_camas_sala=(

        SELECT
			COUNT(*) AS cant
		FROM
			camas c
		INNER JOIN
			habitaciones h
		ON (c.id_habitacion = h.id_habitacion AND c.baja = 0 )
		INNER JOIN
			salas s
		ON
			(h.id_sala = s.id_sala AND s.id_sala = id_sala AND h.baja = 0)
        );

	/* camas disponibles sala */
	SET camas_disponibles_sala=(
		SELECT
			COUNT(*) AS cant
		FROM
			camas c
		INNER JOIN
			habitaciones h
		ON (c.id_habitacion = h.id_habitacion
			AND (c.estado = 'L' OR c.estado = 'O' OR c.estado = 'V')
			AND c.baja = 0
			)
		INNER JOIN
			salas s
		ON (h.id_sala = s.id_sala AND s.id_sala = id_sala AND h.baja = 0)
		);

	/* crea tabla temporal de censos diarios */
	CREATE TEMPORARY TABLE IF NOT EXISTS censos_diarios_tmp(

		id_efector_servicio INT UNSIGNED NULL DEFAULT NULL COMMENT 'Cuando id_efector_servicio IS NULL entonces es el total de la sala',
		id_sala INT UNSIGNED NULL COMMENT 'Id de la sala censada. Cuando es NULL entonces es registro global del servicio en el efector',
		fecha_censo DATE NOT NULL COMMENT 'Dia del censo',
		existencia_0 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que estan en la sala a las 0hs',
		ingresos SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que ingresaron, sin contar los pases_de',
		pases_de SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de ingresos de pacientes que provienen de otras salas (independiente del servicio)',
		pases_de_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que entran al servicio de la sala, pero que provengan de un servicio distinto al del registro (id_efector_servicio)',
		altas SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de egresos por alta',
		defunciones_menos_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala menos de 48 hs',
		defunciones_mas_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala mas de 48 hs',
		pases_a SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son los pacientes que pasaron a otra sala',
		pases_a_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que salen del servicio de la sala, con destino a un servicio distinto al del registro (id_efector_servicio)',
		existencia_24 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'existencia_0 + los ingresos + pases_de - egresos - pases_a',
		entradas_salidas_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son solo los pacientes que entraron y egresaron (por alta u obito) ese dia, sin tener en cuenta los pases',
		pacientes_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la suma de la existencia 24hs mas la cantidad de pacientes que entraron ese dia, sin importar que se hallan ido',
		dias_estada SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la sumatoria de los dias que estuvieron internados los pacientes egresados ese dia',
		total_camas_sala SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son la cantidad de camas que existen en esa sala, sin tener en cuenta el estado de la cama',
		camas_disponibles SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es el total de camas que esten en condiciones de uso y/o en uso de esa sala para ese dia. Editable por programa',

		INDEX idx_id_efector_servicio (id_efector_servicio ASC),
		INDEX idx_id_sala (id_sala ASC),
		INDEX idx_fecha_censo (fecha_censo ASC) )
		ENGINE = InnoDB
		CHARACTER SET = utf8
		COLLATE utf8_unicode_ci
		COMMENT = 'registra los censos diarios';

    /* elimina censo fecha y sala */
    DELETE FROM

		censos_diarios_tmp

	WHERE

		censos_diarios_tmp.id_sala = id_sala
	AND censos_diarios_tmp.fecha_censo = fecha_censo
	AND censos_diarios_tmp.id_efector_servicio IS NULL;

	/* ingresa censo global de sala */
    INSERT INTO
		censos_diarios_tmp

	VALUES

		(
	    /* id_efector_servicio */
	    NULL,

	    /* id_sala */
	    id_sala,

	    /* fecha_censo */
	    fecha_censo,

	    /* existencia_0 */
	    existencia0,

	    /* ingresos */
	    ingresos,

	    /* pases_de */
	    pases_de_salas,

	    /* pases_de_servicios */
	    pases_de_servicios,

	    /* altas */
	    altas,

	    /* defunciones_menos_48 */
	    defunciones_menos_48,

	    /* defunciones_mas_48 */
	    defunciones_mas_48,

	    /* pases_a */
	    pases_a_salas,

	    /* pases_a_servicios */
	    pases_a_servicios,

	    /* existencia_24 */
	    existencia24,

	    /* entradas_salidas_dia */
	    entradas_salidas_dia,

	    /* pacientes_dia */
	    pacientes_dia,

	    /* dias_estada */
	    dias_estada,

	    /* total_camas_sala */
	    total_camas_sala,

	    /* camas_disponibles */
	    camas_disponibles_sala
	);

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_calcular */

DROP FUNCTION IF EXISTS censos_diarios_calcular_servicio;

/*
*	Funcion que calcula y genera tabla temporal con los
*	datos del censo diario global del servicio
*
*	@param		id_efector_servicio			INTEGER			id del servicio
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			 0 = OK
*															-3 = si id_efector_servicio no existe
*															-4 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_calcular_servicio (id_efector_servicio INTEGER, fecha_censo DATE)
    RETURNS INTEGER
    MODIFIES SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-3=id_efector_servicio no existe;-4=fecha no valida'

BEGIN

	DECLARE existencia0 SMALLINT;
	DECLARE existencia24 SMALLINT;
	DECLARE ingresos SMALLINT;
	DECLARE pases_de_salas SMALLINT;
	DECLARE pases_de_servicios SMALLINT;
	DECLARE altas SMALLINT;
	DECLARE defunciones_menos_48 SMALLINT;
	DECLARE defunciones_mas_48 SMALLINT;
	DECLARE pases_a_salas SMALLINT;
	DECLARE pases_a_servicios SMALLINT;
	DECLARE entradas_salidas_dia SMALLINT;
	DECLARE pacientes_dia SMALLINT;
	DECLARE dias_estada SMALLINT;
	DECLARE total_camas_sala SMALLINT;
	DECLARE camas_disponibles_sala SMALLINT;
	DECLARE entradas_salidas_pases_de_servicio SMALLINT;
	DECLARE entradas_salidas_egresos_servicio SMALLINT;
	DECLARE aux_id INTEGER;

	/* check si id_efector_servicio existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores_servicios es
		WHERE
			es.id_efector_servicio = id_efector_servicio);

	IF aux_id=0 THEN

		RETURN -3;

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		RETURN -4;

	END IF;

	/* existencia0 */
	SET existencia0 =(
		SELECT
			COUNT(DISTINCT p.id_internacion) AS cant
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_efector_servicio = id_efector_servicio)
		WHERE
			DATE(p.fecha_entrada)<fecha_censo
		AND (p.fecha_salida IS NULL
			OR (p.fecha_salida IS NOT NULL
			AND DATE(p.fecha_salida)>=fecha_censo)
			)
		);

	/* existencia 24 */
	SET	existencia24=(

		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_efector_servicio = id_efector_servicio)
		WHERE
			DATE(p.fecha_entrada) = fecha_censo) -

		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_efector_servicio = id_efector_servicio)
		WHERE
			DATE(p.fecha_salida) = fecha_censo)

		);

	SET existencia24 = existencia0 + existencia24;

	/* ingresos */
	SET ingresos=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'I'
		);

	/* pases de salas */
	SET pases_de_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase
			)
		);

	/* pases de servicios */
	SET pases_de_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase)
		);

	/* altas */
	SET altas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'T')
		);

	/* obitos - defunciones menos 48 hs */
	SET defunciones_menos_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND	DATEDIFF(
				DATE(i.egr_fecha_hora),
				DATE(i.ing_fecha_hora)
			)<=1
		);

	/* obitos - defunciones mas 48 hs */
	SET defunciones_mas_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND	DATEDIFF(
				DATE(i.egr_fecha_hora),
				DATE(i.ing_fecha_hora)
			)>1
		);

	/* pases a salas */
	SET pases_a_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase
			)
		);

	/* pases a servicios */
	SET pases_a_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase)
		);

	/* ---------------------------- */
	/* calcula entradas salidas dia */

		/* entradas/salidas dia pases de servicio */
		SET entradas_salidas_pases_de_servicio=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			INNER JOIN
				pases p2
			ON p1.id_pase_siguiente = p2.id_pase
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				ss1.id_efector_servicio = id_efector_servicio
			AND ss2.id_efector_servicio <> id_efector_servicio
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p2.fecha_entrada) = fecha_censo
			);

		/* e/s dia de altas-obitos-salidas transitorias */
		SET entradas_salidas_egresos_servicio=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			WHERE
				ss1.id_efector_servicio = id_efector_servicio
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p1.fecha_salida) = fecha_censo
			AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'O' OR p1.tipo_salida = 'T')
			);

		/* entradas salidas dia (sala) */
		SET entradas_salidas_dia =
				entradas_salidas_pases_de_servicio +
				entradas_salidas_egresos_servicio;

	/* fin calcula entradas salidas dia */
	/* -------------------------------- */

	/* pacientes dia */
	SET pacientes_dia = existencia24 + entradas_salidas_dia;

	/* dias de estada sala */
	SET dias_estada =(
		SELECT
			IFNULL(
				SUM(
					IF(
						DATEDIFF(p2.fecha_salida,p2.fecha_entrada)=0,
						1,
						DATEDIFF(p2.fecha_salida,p2.fecha_entrada)
					)
				),
			0) AS dias_estada
		FROM
			pases p1
		INNER JOIN
			pases p2
		ON p1.id_internacion = p2.id_internacion
		INNER JOIN
			servicios_salas ss1
		ON (p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			AND ss1.id_efector_servicio = id_efector_servicio)
		INNER JOIN
			efectores_servicios es1
		ON ss1.id_efector_servicio = es1.id_efector_servicio
		INNER JOIN
			servicios_salas ss2
		ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
		INNER JOIN
			efectores_servicios es2
		ON ss2.id_efector_servicio = es2.id_efector_servicio
		WHERE
			DATE(p1.fecha_salida) = fecha_censo
		AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'O' OR p1.tipo_salida = 'T')
		);

	/* total camas sala */
	SET total_camas_sala=0;

	/* camas disponibles sala */
	SET camas_disponibles_sala=0;

	/* crea tabla temporal de censos diarios */
	CREATE TEMPORARY TABLE IF NOT EXISTS censos_diarios_tmp(

		id_efector_servicio INT UNSIGNED NULL DEFAULT NULL COMMENT 'Cuando id_efector_servicio IS NULL entonces es el total de la sala',
		id_sala INT UNSIGNED NULL COMMENT 'Id de la sala censada. Cuando es NULL entonces es registro global del servicio en el efector',
		fecha_censo DATE NOT NULL COMMENT 'Dia del censo',
		existencia_0 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que estan en la sala a las 0hs',
		ingresos SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que ingresaron, sin contar los pases_de',
		pases_de SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de ingresos de pacientes que provienen de otras salas (independiente del servicio)',
		pases_de_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que entran al servicio de la sala, pero que provengan de un servicio distinto al del registro (id_efector_servicio)',
		altas SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de egresos por alta',
		defunciones_menos_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala menos de 48 hs',
		defunciones_mas_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala mas de 48 hs',
		pases_a SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son los pacientes que pasaron a otra sala',
		pases_a_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que salen del servicio de la sala, con destino a un servicio distinto al del registro (id_efector_servicio)',
		existencia_24 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'existencia_0 + los ingresos + pases_de - egresos - pases_a',
		entradas_salidas_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son solo los pacientes que entraron y egresaron (por alta u obito) ese dia, sin tener en cuenta los pases',
		pacientes_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la suma de la existencia 24hs mas la cantidad de pacientes que entraron ese dia, sin importar que se hallan ido',
		dias_estada SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la sumatoria de los dias que estuvieron internados los pacientes egresados ese dia',
		total_camas_sala SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son la cantidad de camas que existen en esa sala, sin tener en cuenta el estado de la cama',
		camas_disponibles SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es el total de camas que esten en condiciones de uso y/o en uso de esa sala para ese dia. Editable por programa',

		INDEX idx_id_efector_servicio (id_efector_servicio ASC),
		INDEX idx_id_sala (id_sala ASC),
		INDEX idx_fecha_censo (fecha_censo ASC) )
		ENGINE = InnoDB
		CHARACTER SET = utf8
		COLLATE utf8_unicode_ci
		COMMENT = 'registra los censos diarios';

    /* elimina censo fecha y sala */
    DELETE FROM

		censos_diarios_tmp

	WHERE

		censos_diarios_tmp.id_sala IS NULL
	AND censos_diarios_tmp.fecha_censo = fecha_censo
	AND censos_diarios_tmp.id_efector_servicio = id_efector_servicio;

	/* ingresa censo global del servicio */
    INSERT INTO
		censos_diarios_tmp

	VALUES

		(
	    /* id_efector_servicio */
	    id_efector_servicio,

	    /* id_sala */
	    NULL,

	    /* fecha_censo */
	    fecha_censo,

	    /* existencia_0 */
	    existencia0,

	    /* ingresos */
	    ingresos,

	    /* pases_de */
	    pases_de_salas,

	    /* pases_de_servicios */
	    pases_de_servicios,

	    /* altas */
	    altas,

	    /* defunciones_menos_48 */
	    defunciones_menos_48,

	    /* defunciones_mas_48 */
	    defunciones_mas_48,

	    /* pases_a */
	    pases_a_salas,

	    /* pases_a_servicios */
	    pases_a_servicios,

	    /* existencia_24 */
	    existencia24,

	    /* entradas_salidas_dia */
	    entradas_salidas_dia,

	    /* pacientes_dia */
	    pacientes_dia,

	    /* dias_estada */
	    dias_estada,

	    /* total_camas_sala */
	    total_camas_sala,

	    /* camas_disponibles */
	    camas_disponibles_sala
	);

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_calcular */

DROP FUNCTION IF EXISTS censos_diarios_calcular_servicio_sala;

/*
*	Funcion que calcula y genera tabla temporal con los
*	datos del censo diario del servicio-sala
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		id_efector_servicio			INTEGER			id del servicio
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			 0 = OK
*															-1 = si id_efector_servicio no existe
*															-2 = si id_sala no existe
*															-3 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_calcular_servicio_sala (
		id_sala INTEGER,
		id_efector_servicio INTEGER,
		fecha_censo DATE)
    RETURNS INTEGER
    MODIFIES SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-2=err id_sala;-3=err id_efector_servicio;-4=err fecha'

BEGIN

	DECLARE existencia0 SMALLINT;
	DECLARE existencia24 SMALLINT;
	DECLARE ingresos SMALLINT;
	DECLARE pases_de_salas SMALLINT;
	DECLARE pases_de_servicios SMALLINT;
	DECLARE altas SMALLINT;
	DECLARE defunciones_menos_48 SMALLINT;
	DECLARE defunciones_mas_48 SMALLINT;
	DECLARE pases_a_salas SMALLINT;
	DECLARE pases_a_servicios SMALLINT;
	DECLARE entradas_salidas_dia SMALLINT;
	DECLARE pacientes_dia SMALLINT;
	DECLARE dias_estada SMALLINT;
	DECLARE total_camas_sala SMALLINT;
	DECLARE camas_disponibles_sala SMALLINT;
	DECLARE entradas_salidas_pases_de_servicio SMALLINT;
	DECLARE entradas_salidas_egresos_servicio SMALLINT;
	DECLARE aux_id INTEGER;

	/* check si id_efector_servicio existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores_servicios es
		WHERE
			es.id_efector_servicio = id_efector_servicio);

	IF aux_id=0 THEN

		RETURN -3;

	END IF;

	/* check si id_sala existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			salas s
		WHERE
			s.id_sala = id_sala);

	IF aux_id=0 THEN

		RETURN -2;

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		RETURN -4;

	END IF;

	/* existencia0 */
	SET existencia0 =(
		SELECT
			COUNT(DISTINCT p.id_internacion) AS cant
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala
			AND ss.id_efector_servicio = id_efector_servicio
			)
		WHERE
			DATE(p.fecha_entrada)<fecha_censo
		AND (p.fecha_salida IS NULL
			OR (p.fecha_salida IS NOT NULL AND DATE(p.fecha_salida)>=fecha_censo)
			)
		);

	/* existencia 24 */
	SET	existencia24=(
		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala
			AND ss.id_efector_servicio = id_efector_servicio
			)
		WHERE
			DATE(p.fecha_entrada) = fecha_censo) -

		(SELECT
			COUNT(p.id_pase)
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala
			AND ss.id_efector_servicio = id_efector_servicio
			)
		WHERE
			DATE(p.fecha_salida) = fecha_censo)
		);

	SET existencia24 = existencia0 + existencia24;

	/* ingresos */
	SET ingresos=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'I'
		);

	/* pases de salas */
	SET pases_de_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase
			)
		);

	/* pases de servicios */
	SET pases_de_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_entrada) = fecha_censo
		AND p1.tipo_entrada = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p2.id_pase_siguiente = p1.id_pase
			)
		);

	/* altas */
	SET altas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND (p1.tipo_salida = 'A' OR p1.tipo_salida = 'T')
		);

	/* obitos - defunciones menos 48 hs */
	SET defunciones_menos_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND	DATEDIFF(
			DATE(i.egr_fecha_hora),
			DATE(i.ing_fecha_hora)
			)<=1
		);

	/* obitos - defunciones mas 48 hs */
	SET defunciones_mas_48=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		INNER JOIN
			internaciones i
		ON p1.id_internacion = i.id_internacion
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'O'
		AND	DATEDIFF(
			DATE(i.egr_fecha_hora),
			DATE(i.ing_fecha_hora)
			)>1
		);

	/* pases a salas */
	SET pases_a_salas=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_sala <>
			(SELECT
				ss2.id_sala
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase
			)
		);

	/* pases a servicios */
	SET pases_a_servicios=(
		SELECT
			COUNT(*) AS cant
		FROM
			pases p1
		INNER JOIN
			servicios_salas ss1
		ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
		WHERE
			ss1.id_sala = id_sala
		AND ss1.id_efector_servicio = id_efector_servicio
		AND DATE(p1.fecha_salida) = fecha_censo
		AND p1.tipo_salida = 'P'
		AND ss1.id_efector_servicio <>
			(SELECT
				ss2.id_efector_servicio
			FROM
				pases p2
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				p1.id_pase_siguiente = p2.id_pase
			)
		);

	/* -------------------------------------------- */
	/* calcula entradas salidas dia (servicio-sala) */

		/* entradas/salidas dia pases de servicio-sala */
		SET entradas_salidas_pases_de_servicio=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			INNER JOIN
				pases p2
			ON p1.id_pase_siguiente = p2.id_pase
			INNER JOIN
				servicios_salas ss2
			ON p2.id_servicio_sala_entrada = ss2.id_servicio_sala
			WHERE
				ss1.id_sala = id_sala
			AND ss1.id_efector_servicio = id_efector_servicio
			AND (ss2.id_sala <> id_sala
				OR  ss2.id_efector_servicio <> id_efector_servicio
				)
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p2.fecha_entrada) = fecha_censo

			);

		/* e/s dia de altas-obitos-salidas transitorias */
		SET entradas_salidas_egresos_servicio=(
			SELECT
				COUNT(*) AS cant
			FROM
				pases p1
			INNER JOIN
				servicios_salas ss1
			ON p1.id_servicio_sala_entrada = ss1.id_servicio_sala
			WHERE
				ss1.id_sala = id_sala
			AND ss1.id_efector_servicio = id_efector_servicio
			AND DATE(p1.fecha_entrada) = fecha_censo
			AND DATE(p1.fecha_salida) = fecha_censo
			AND (p1.tipo_salida = 'A'
				OR p1.tipo_salida = 'O'
				OR p1.tipo_salida = 'T'
				)
			);

		/* entradas salidas dia (servicio-sala) */
		SET entradas_salidas_dia =
				entradas_salidas_pases_de_servicio +
				entradas_salidas_egresos_servicio;

	/* fin calcula entradas salidas dia (servicio-sala) */
	/* ------------------------------------------------ */

	/* pacientes dia */
	SET pacientes_dia = existencia24 + entradas_salidas_dia;

	/* dias de estada servicio-sala */
	SET dias_estada =(
		SELECT
			IFNULL(
				SUM(
					IF(
						DATEDIFF(p.fecha_salida,p.fecha_entrada)=0,
						1,
						DATEDIFF(p.fecha_salida,p.fecha_entrada)
					)
				),
			0) AS dias_estada
		FROM
			pases p
		INNER JOIN
			servicios_salas ss
		ON (p.id_servicio_sala_entrada = ss.id_servicio_sala
			AND ss.id_sala = id_sala
			AND ss.id_efector_servicio = id_efector_servicio
			)
		WHERE
			DATE(p.fecha_salida) = fecha_censo
		AND p.estado_pase = 'E'
		);

	/* total camas sala */
	SET total_camas_sala=0;

	/* camas disponibles sala */
	SET camas_disponibles_sala=0;

	/* crea tabla temporal de censos diarios */
	CREATE TEMPORARY TABLE IF NOT EXISTS censos_diarios_tmp(

		id_efector_servicio INT UNSIGNED NULL DEFAULT NULL COMMENT 'Cuando id_efector_servicio IS NULL entonces es el total de la sala',
		id_sala INT UNSIGNED NULL COMMENT 'Id de la sala censada. Cuando es NULL entonces es registro global del servicio en el efector',
		fecha_censo DATE NOT NULL COMMENT 'Dia del censo',
		existencia_0 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que estan en la sala a las 0hs',
		ingresos SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que ingresaron, sin contar los pases_de',
		pases_de SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de ingresos de pacientes que provienen de otras salas (independiente del servicio)',
		pases_de_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que entran al servicio de la sala, pero que provengan de un servicio distinto al del registro (id_efector_servicio)',
		altas SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de egresos por alta',
		defunciones_menos_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala menos de 48 hs',
		defunciones_mas_48 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la cantidad de pacientes que fallecieron ese dia y estuvieron internados en esa sala mas de 48 hs',
		pases_a SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son los pacientes que pasaron a otra sala',
		pases_a_servicios SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Cantidad de pacientes que salen del servicio de la sala, con destino a un servicio distinto al del registro (id_efector_servicio)',
		existencia_24 SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'existencia_0 + los ingresos + pases_de - egresos - pases_a',
		entradas_salidas_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son solo los pacientes que entraron y egresaron (por alta u obito) ese dia, sin tener en cuenta los pases',
		pacientes_dia SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la suma de la existencia 24hs mas la cantidad de pacientes que entraron ese dia, sin importar que se hallan ido',
		dias_estada SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es la sumatoria de los dias que estuvieron internados los pacientes egresados ese dia',
		total_camas_sala SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Son la cantidad de camas que existen en esa sala, sin tener en cuenta el estado de la cama',
		camas_disponibles SMALLINT UNSIGNED NOT NULL DEFAULT '0' COMMENT 'Es el total de camas que esten en condiciones de uso y/o en uso de esa sala para ese dia. Editable por programa',

		INDEX idx_id_efector_servicio (id_efector_servicio ASC),
		INDEX idx_id_sala (id_sala ASC),
		INDEX idx_fecha_censo (fecha_censo ASC) )
		ENGINE = InnoDB
		CHARACTER SET = utf8
		COLLATE utf8_unicode_ci
		COMMENT = 'registra los censos diarios';

    /* elimina censo fecha y sala */
    DELETE FROM

		censos_diarios_tmp

	WHERE

		censos_diarios_tmp.id_sala = id_sala
	AND censos_diarios_tmp.fecha_censo = fecha_censo
	AND censos_diarios_tmp.id_efector_servicio = id_efector_servicio;

	/* ingresa censo global del servicio-sala */
    INSERT INTO
		censos_diarios_tmp

	VALUES

		(
	    /* id_efector_servicio */
	    id_efector_servicio,

	    /* id_sala */
	    id_sala,

	    /* fecha_censo */
	    fecha_censo,

	    /* existencia_0 */
	    existencia0,

	    /* ingresos */
	    ingresos,

	    /* pases_de */
	    pases_de_salas,

	    /* pases_de_servicios */
	    pases_de_servicios,

	    /* altas */
	    altas,

	    /* defunciones_menos_48 */
	    defunciones_menos_48,

	    /* defunciones_mas_48 */
	    defunciones_mas_48,

	    /* pases_a */
	    pases_a_salas,

	    /* pases_a_servicios */
	    pases_a_servicios,

	    /* existencia_24 */
	    existencia24,

	    /* entradas_salidas_dia */
	    entradas_salidas_dia,

	    /* pacientes_dia */
	    pacientes_dia,

	    /* dias_estada */
	    dias_estada,

	    /* total_camas_sala */
	    total_camas_sala,

	    /* camas_disponibles */
	    camas_disponibles_sala
	);

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_generar_sala*/

DROP FUNCTION IF EXISTS censos_diarios_generar_sala;

/*
*	Funcion que calcula y genera el censo de sala en la tabla temporal
*	Puede devolver id_efector_servicio no existe porque dentro de la
*	funcion se realizan los censos de los servicios-salas
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			 0 = OK
*															-1 = si id_efector_servicio no existe
*															-2 = si id_sala no existe
*															-3 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_generar_sala (
		id_sala INTEGER,
		fecha_censo DATE)

    RETURNS INTEGER
    MODIFIES SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-2=err id_sala;-3=err id_efector_servicio;-4=err fecha'

BEGIN

	DECLARE exit_loop INT;
	DECLARE aux_id INTEGER;
	DECLARE id_efector_servicio_aux INTEGER;

	/* id_efector_servicio vigentes de la sala */
	/* en la fecha del censo */
	DECLARE
		efectores_servicios_sala
	CURSOR FOR
		(SELECT
			es.id_efector_servicio
		FROM
			servicios_salas ss
		INNER JOIN
			efectores_servicios es
		ON
			es.id_efector_servicio = ss.id_efector_servicio
		INNER JOIN
			servicios_salas_hist ssh
		ON
			ssh.id_servicio_sala = ss.id_servicio_sala
		WHERE
			ss.id_sala = id_sala
		AND ssh.fecha_apertura<=fecha_censo
		AND (ssh.fecha_cierre IS NULL OR ssh.fecha_cierre>=fecha_censo)
		);

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = 1;

	/* check si id_sala existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			salas s
		WHERE
			s.id_sala = id_sala);

	IF aux_id=0 THEN

		RETURN -2;

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		RETURN -4;

	END IF;

	/* bucle de id_efector_servicio de sala */
	SET exit_loop = 0;

	OPEN efectores_servicios_sala;

	bucle:
	LOOP

		FETCH
			efectores_servicios_sala
		INTO
			id_efector_servicio_aux;

		IF exit_loop=1 THEN

			LEAVE bucle;

		END IF;

		/* realiza el censo del servicio-sala */
		SET aux_id =
			(SELECT
				censos_diarios_calcular_servicio_sala(
					id_sala,
					id_efector_servicio_aux,
					fecha_censo
				)
			);

		IF aux_id<0 THEN

			RETURN aux_id;

		END IF;

	END LOOP;

	CLOSE efectores_servicios_sala;

	/* realiza el censo global de la sala */
	SET aux_id =
		(SELECT
			censos_diarios_calcular_sala(
				id_sala,
				fecha_censo
			)
		);

	IF aux_id<0 THEN

		RETURN aux_id;

	END IF;

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_generar_servicios */

DROP FUNCTION IF EXISTS censos_diarios_generar_servicios;

/*
*	Funcion que calcula y genera el censo de todos los servicios
*	globales vigentes en el efector en la tabla temporal y la fecha
*
*	@param		id_efector					INTEGER			id_efector
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			 0 = OK
*															-1 = si id_efector no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_generar_servicios (
		id_efector INTEGER,
		fecha_censo DATE)

    RETURNS INTEGER
    MODIFIES SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-1=err id_efector;-4=err fecha'

BEGIN

	DECLARE exit_loop INTEGER;
	DECLARE aux_id INTEGER;
	DECLARE id_efector_servicio_aux INTEGER;

	/* id_efector_servicio vigentes del efector */
	/* en la fecha del censo */
	DECLARE

		efectores_servicios_efector
	CURSOR FOR
		(SELECT
			es.id_efector_servicio
		FROM
			efectores_servicios es
		INNER JOIN
			efectores_servicios_hist esh
		ON
			esh.id_efector_servicio = es.id_efector_servicio
		WHERE
			es.id_efector = id_efector
		AND es.subsector = '4'
		AND esh.fecha_apertura<=fecha_censo
		AND (esh.fecha_cierre IS NULL OR esh.fecha_cierre>=fecha_censo)
		);

	DECLARE CONTINUE HANDLER FOR NOT FOUND SET exit_loop = 1;

	/* check si id_efector existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector);

	IF aux_id=0 THEN

		RETURN -1;

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		RETURN -4;

	END IF;

	/* bucle de id_efector_servicio de sala */
	SET exit_loop = 0;

	OPEN efectores_servicios_efector;

	bucle:
	LOOP

		FETCH
			efectores_servicios_efector
		INTO
			id_efector_servicio_aux;

		IF exit_loop=1 THEN

			LEAVE bucle;

		END IF;

		/* realiza el censo global del servicio*/
		SET aux_id =
			(SELECT
				censos_diarios_calcular_servicio(
					id_efector_servicio_aux,
					fecha_censo
				)
			);

		IF aux_id<0 THEN

			RETURN aux_id;

		END IF;

	END LOOP;

	CLOSE efectores_servicios_efector;

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_eliminar_censo de sala */

DROP PROCEDURE IF EXISTS censos_diarios_eliminar_sala;

/*
*	Funcion que calcula y guarda el censo diario de la sala
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			id_censo_diario
*															-1 = si id_sala no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    PROCEDURE censos_diarios_eliminar_sala (
		IN id_sala INTEGER,
		IN fecha_censo DATE,
		OUT estado INTEGER,
		OUT msg VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci)
    MODIFIES SQL DATA
	COMMENT '0=OK; -2=err id_sala;-4=err fecha;-5=err update/insert'

BEGIN

	DECLARE nombre_sala VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE nom_efector VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE aux_id INTEGER;
	DECLARE id_censo_diario_aux INTEGER;
	DECLARE autocommit_old INTEGER;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		ROLLBACK;
		SET estado = -5;
		SET autocommit=autocommit_old;

	END;

	/* deshabilita el autocommit para iniciar una transaccion */
	SET autocommit_old=(SELECT @@autocommit);

	/* setea a OK */
	SET estado = 0;

	/* check si id_sala existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			salas s
		WHERE
			s.id_sala = id_sala);

	IF aux_id=0 THEN

		SET estado = -2;
		SET msg =
			CONCAT(
				"Sala con id_sala: ",
				id_sala,
				" no existe"
			);

	END IF;

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		SET estado = -4;
		SET msg =
			CONCAT(
				"Fecha de censo: ",
				fecha_censo,
				" superior a la fecha actual: ",
				DATE(NOW())
				);

	END IF;

	IF estado=0 THEN

		/* nombre de sala */
		SET nombre_sala =
			(SELECT
				s.nombre
			FROM
				salas s
			WHERE
				s.id_sala = id_sala
			);

		/* nombre del efector */
		SET nom_efector =
			(SELECT
				e.nom_efector
			FROM
				efectores e
			INNER JOIN
				salas s
			ON s.id_efector = e.id_efector
			WHERE
				s.id_sala = id_sala
			);

		/* deshabilita el autocommit antes de iniciar la transaccion */
		SET autocommit=0;

		/* transaccion */
		START TRANSACTION;

		/* mensaje */
		SET msg = CONCAT(
			'Poner NULL a los pases que apuntan al censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' existente'
			);

		/* pone NULL los pases que apuntan al censo existe */
		UPDATE
			pases p,
			censos_diarios cd
		SET
			p.id_censo_diario = NULL
		WHERE
			p.id_censo_diario = cd.id_censo_diario
		AND cd.id_sala = id_sala
		AND cd.fecha_censo = fecha_censo
		AND cd.id_efector_servicio IS NULL;

		/* mensaje */
		SET msg = CONCAT(
			'Eliminar censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo
			);

		/* elimina censo del dia si existe */
		DELETE FROM
			censos_diarios
		WHERE
			censos_diarios.id_sala = id_sala
		AND censos_diarios.fecha_censo = fecha_censo;

		/* mensaje */
		SET msg = CONCAT(
			'Censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' eliminado'
			);

		/* commit */
		COMMIT;

		/* devuelve valor de autocommit al iniciar el procedure */
		SET autocommit=autocommit_old;

	END IF;

END$$

DELIMITER ;

/* censos_diarios_guardar_censo de sala */

DROP PROCEDURE IF EXISTS censos_diarios_guardar_sala;

/*
*	Funcion que calcula y guarda el censo diario de la sala
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			id_censo_diario
*															-1 = si id_sala no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    PROCEDURE censos_diarios_guardar_sala (
		IN id_sala INTEGER,
		IN fecha_censo DATE,
		IN usuario CHAR(80) CHARSET utf8 COLLATE utf8_unicode_ci,
		OUT estado INTEGER,
		OUT msg VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci)
    MODIFIES SQL DATA
	COMMENT '0=OK; -2=err id_sala;-4=err fecha;-5=err update/insert'

BEGIN

	DECLARE nombre_sala VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE nom_efector VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE aux INTEGER;
	DECLARE id_censo_diario_aux INTEGER;
	DECLARE autocommit_old INTEGER;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		ROLLBACK;
		SET estado = -5;
		SET autocommit=autocommit_old;

	END;

	/* deshabilita el autocommit para iniciar una transaccion */
	SET autocommit_old=(SELECT @@autocommit);

	/* setea a OK */
	SET estado = 0;

	/* nombre de sala */
	SET nombre_sala =
		(SELECT
			s.nombre
		FROM
			salas s
		WHERE
			s.id_sala = id_sala
		);

	/* nombre del efector */
	SET nom_efector =
		(SELECT
			e.nom_efector
		FROM
			efectores e
		INNER JOIN
			salas s
		ON s.id_efector = e.id_efector
		WHERE
			s.id_sala = id_sala
		);

	/* genera censo en tabla temporal */
	SET aux = (
		SELECT censos_diarios_generar_sala(
			id_sala,
			fecha_censo
			)
		);

	IF aux<0 THEN

		/* error al generar el censo en las tablas temporales */
		SET estado = aux;
		SET msg = CONCAT(
			'Calcular el censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo
			);

	ELSE

		/* deshabilita el autocommit antes de iniciar la transaccion */
		SET autocommit=0;

		/* transaccion */
		START TRANSACTION;

		/* mensaje */
		SET msg = CONCAT(
			'Poner NULL a los pases que apuntan al censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' existente'
			);

		/* pone NULL los pases que apuntan al censo existe */
		UPDATE
			pases p,
			censos_diarios cd
		SET
			p.id_censo_diario = NULL
		WHERE
			p.id_censo_diario = cd.id_censo_diario
		AND cd.id_sala = id_sala
		AND cd.fecha_censo = fecha_censo
		AND cd.id_efector_servicio IS NULL;

		/* mensaje */
		SET msg = CONCAT(
			'Eliminar censo de sala: ',
			nombre_sala,
			' Efector ',
			nom_efector,
			' Fecha: ',
			fecha_censo
			);

		/* elimina censo del dia si existe */
		DELETE FROM
			censos_diarios
		WHERE
			censos_diarios.id_sala = id_sala
		AND censos_diarios.fecha_censo = fecha_censo;

		/* mensaje */
		SET msg = CONCAT(
			'Ingresar el nuevo censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo
			);

		/* ingresa el nuevo censo de sala */
		INSERT INTO

			censos_diarios

		SELECT

			/* id_censo_diario */
			NULL,

			/* id_efector_servicio */
			cdt.id_efector_servicio,

			/* id_sala */
			id_sala,

			/* fecha_censo */
			fecha_censo,

			/* existencia_0 */
			cdt.existencia_0,

			/* ingresos */
			cdt.ingresos,

			/* pases_de */
			cdt.pases_de,

			/* pases_de_servicios */
			cdt.pases_de_servicios,

			/* altas */
			cdt.altas,

			/* defunciones_menos_48 */
			cdt.defunciones_menos_48,

			/* defunciones_mas_48 */
			cdt.defunciones_mas_48,

			/* pases_a */
			cdt.pases_a,

			/* pases_a_servicios */
			cdt.pases_a_servicios,

			/* existencia_24 */
			cdt.existencia_24,

			/* entradas_salidas_dia */
			cdt.entradas_salidas_dia,

			/* pacientes_dia */
			cdt.pacientes_dia,

			/* dias_estada */
			cdt.dias_estada,

			/* total_camas_sala */
			cdt.total_camas_sala,

			/* camas_disponibles */
			cdt.camas_disponibles,

			/* usuario */
			usuario,

			/* fecha_modificacion */
			NULL

		FROM

			censos_diarios_tmp cdt
		WHERE
			cdt.id_sala = id_sala
		AND cdt.fecha_censo = fecha_censo;

		/* mensaje */
		SET msg = CONCAT(
			'Capturar el id_censo_diario global de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' para setearlo en los pases'
			);

		/* captura el id_censo_diario global de sala para setearlo */
		/* en los pases */
		SET id_censo_diario_aux = (
			SELECT
				id_censo_diario
			FROM
				censos_diarios cd
			WHERE
				cd.id_sala=id_sala
			AND cd.fecha_censo = fecha_censo
			AND cd.id_efector_servicio IS NULL
			);

		/* mensaje */
		SET msg = CONCAT(
			'Actualizar id_censo_diario de los pases de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' involucrados'
			);

		/* actualiza id_censo_diario de los pases involucrados */
		UPDATE
			pases p,
			servicios_salas ss
		SET
			p.id_censo_diario = id_censo_diario_aux
		WHERE
			DATE(p.fecha_entrada) = fecha_censo
		AND p.id_servicio_sala_entrada = ss.id_servicio_sala
		AND ss.id_sala = id_sala;

		/* mensaje */
		SET msg = CONCAT(
			'Censo de sala: ',
			nombre_sala,
			' Efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' realizado'
			);

		/* commit */
		COMMIT;

		/* devuelve valor de autocommit al iniciar el procedure */
		SET autocommit=autocommit_old;

	END IF;

END$$

DELIMITER ;

/* censos_diarios_eliminar_censo de servicios de internacion del efector */

DROP PROCEDURE IF EXISTS censos_diarios_eliminar_servicios;

/*
*	Funcion que elimina los censos diarios globales de servicios del efector
*
*	@param		id_efector					INTEGER			id del efector
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			id_censo_diario
*															-1 = si id_efector no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    PROCEDURE censos_diarios_eliminar_servicios (
		IN id_efector INTEGER,
		IN fecha_censo DATE,
		OUT estado INTEGER,
		OUT msg VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci)
    MODIFIES SQL DATA
	COMMENT '0=OK; -1=err id_efector;-4=err fecha;-5=err update/insert'

BEGIN

	DECLARE exit_loop INTEGER;
	DECLARE nom_efector VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE aux_id INTEGER;

	DECLARE id_efector_servicio_aux INTEGER;
	DECLARE nom_servicio_estadistica_aux VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;

	/* variable para guardar el estado de la variable global de autocommit */
	DECLARE autocommit_old INTEGER;

	/* id_efector_servicio vigentes del efector */
	/* en la fecha del censo */
	DECLARE

		efectores_servicios_efector
	CURSOR FOR
		(SELECT
			es.id_efector_servicio,
			es.nom_servicio_estadistica
		FROM
			efectores_servicios es
		INNER JOIN
			efectores_servicios_hist esh
		ON
			esh.id_efector_servicio = es.id_efector_servicio
		WHERE
			es.id_efector = id_efector
		AND es.subsector = '4'
		AND esh.fecha_apertura<=fecha_censo
		AND (esh.fecha_cierre IS NULL OR esh.fecha_cierre>=fecha_censo)
		);

	/* handler de bucle */
	DECLARE CONTINUE HANDLER FOR NOT FOUND

		SET exit_loop = 1;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		ROLLBACK;
		SET estado = -5;
		SET autocommit=autocommit_old;

	END;

	/* guarda el valor de autocommit antes de iniciar una transaccion */
	SET autocommit_old=(SELECT @@autocommit);

	/* setea a OK */
	SET estado = 0;

	/* check si id_efector existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector);

	IF aux_id=0 THEN

		SET estado = -1;
		SET msg =
			CONCAT(
				"Efector con id_efector: ",
				id_efector,
				" no existe"
			);

	END IF;

	/* nombre del efector */
	SET nom_efector =
		(SELECT
			e.nom_efector
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector
		);

	/* check fecha censo menor o igual a la fecha de hoy */
	IF fecha_censo>DATE(NOW()) THEN

		SET estado = -4;
		SET msg =
			CONCAT(
				"Fecha de censo: ",
				fecha_censo,
				" superior a la fecha actual: ",
				DATE(NOW())
				);

	END IF;

	/* check si OK */
	IF estado=0 THEN

		/* deshabilita el autocommit antes de iniciar la transaccion */
		SET autocommit=0;

		/* transaccion */
		START TRANSACTION;

		/* bucle de id_efector_servicio de sala */
		SET exit_loop = 0;

		OPEN efectores_servicios_efector;

		bucle:
		LOOP

			FETCH
				efectores_servicios_efector
			INTO
				id_efector_servicio_aux,
				nom_servicio_estadistica_aux;

			IF exit_loop=1 THEN

				LEAVE bucle;

			END IF;

			/* mensaje */
			SET msg = CONCAT(
				'Eliminar el censo global de servicio del efector: ',
				nom_efector,
				' Servicio: ',
				nom_servicio_estadistica_aux,
				' Fecha: ',
				fecha_censo
				);

			/* elimina censo del dia si existe */
			DELETE FROM
				censos_diarios
			WHERE
				censos_diarios.id_efector_servicio = id_efector_servicio_aux
			AND censos_diarios.fecha_censo = fecha_censo
			AND	censos_diarios.id_sala IS NULL;

		END LOOP;

		CLOSE efectores_servicios_efector;

		/* mensaje */
		SET msg = CONCAT(
			'Censo global de servicios del efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' eliminados'
			);

		/* commit */
		COMMIT;

		/* devuelve valor de autocommit al iniciar el procedure */
		SET autocommit=autocommit_old;

	END IF;

END$$

DELIMITER ;

/* censos_diarios_guardar_censo de servicios de internacion del efector */

DROP PROCEDURE IF EXISTS censos_diarios_guardar_servicios;

/*
*	Funcion que calcula y guarda el censo diario de los servicios de
*	internacion del efector
*
*	@param		id_efector					INTEGER			id del efector
*	@param		fecha_censo					DATE			fecha_censo
*	@return									INTEGER			id_censo_diario
*															-1 = si id_efector no existe
*															-2 = fecha no valida
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    PROCEDURE censos_diarios_guardar_servicios (
		IN id_efector INTEGER,
		IN fecha_censo DATE,
		IN usuario CHAR(80) CHARSET utf8 COLLATE utf8_unicode_ci,
		OUT estado INTEGER,
		OUT msg VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci)
    MODIFIES SQL DATA
	COMMENT '0=OK; -1=err id_efector;-4=err fecha;-5=err update/insert'

BEGIN

	DECLARE nom_efector VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;
	DECLARE aux INTEGER;
	DECLARE exit_loop INTEGER;

	DECLARE id_efector_servicio_aux INTEGER;
	DECLARE nom_servicio_estadistica_aux VARCHAR(255) CHARSET utf8 COLLATE utf8_unicode_ci;

	/* variable para guardar el estado de la variable global de autocommit */
	DECLARE autocommit_old INTEGER;

	/* id_efector_servicio vigentes del efector */
	/* en la fecha del censo */
	DECLARE

		efectores_servicios_efector
	CURSOR FOR
		(SELECT
			es.id_efector_servicio,
			es.nom_servicio_estadistica
		FROM
			efectores_servicios es
		INNER JOIN
			efectores_servicios_hist esh
		ON
			esh.id_efector_servicio = es.id_efector_servicio
		WHERE
			es.id_efector = id_efector
		AND es.subsector = '4'
		AND esh.fecha_apertura<=fecha_censo
		AND (esh.fecha_cierre IS NULL OR esh.fecha_cierre>=fecha_censo)
		);

	/* handler de bucle */
	DECLARE CONTINUE HANDLER FOR NOT FOUND

		SET exit_loop = 1;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		ROLLBACK;
		SET estado = -5;
		SET autocommit=autocommit_old;

	END;

	/* guarda el valor de autocommit antes de iniciar una transaccion */
	SET autocommit_old=(SELECT @@autocommit);

	/* setea a OK */
	SET estado = 0;

	/* nombre del efector */
	SET nom_efector =
		(SELECT
			e.nom_efector
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector
		);

	/* genera censo en tabla temporal */
	SET aux = (
		SELECT censos_diarios_generar_servicios(
			id_efector,
			fecha_censo
			)
		);

	IF aux<0 THEN

		/* error al generar el censo en las tablas temporales */
		SET estado = aux;

		IF aux=-1 THEN

			SET msg =
				CONCAT(
					"Efector con id_efector: ",
					id_efector,
					" no existe"
				);

		END IF;

		IF aux=-4 THEN

			SET msg =
				CONCAT(
					"Fecha de censo: ",
					fecha_censo,
					" superior a la fecha actual: ",
					DATE(NOW())
					);

		END IF;

	ELSE

		/* deshabilita el autocommit antes de iniciar la transaccion */
		SET autocommit=0;

		/* transaccion */
		START TRANSACTION;

		/* bucle de id_efector_servicio de sala */
		SET exit_loop = 0;

		OPEN efectores_servicios_efector;

		bucle:
		LOOP

			FETCH
				efectores_servicios_efector
			INTO
				id_efector_servicio_aux,
				nom_servicio_estadistica_aux;

			IF exit_loop=1 THEN

				LEAVE bucle;

			END IF;

			/* mensaje */
			SET msg = CONCAT(
				'Eliminar el censo global de servicio del efector: ',
				nom_efector,
				' Servicio: ',
				nom_servicio_estadistica_aux,
				' Fecha: ',
				fecha_censo
				);

			/* elimina censo del dia si existe */
			DELETE FROM
				censos_diarios
			WHERE
				censos_diarios.id_efector_servicio = id_efector_servicio_aux
			AND censos_diarios.fecha_censo = fecha_censo
			AND	censos_diarios.id_sala IS NULL;

		END LOOP;

		CLOSE efectores_servicios_efector;

		/* mensaje */
		SET msg = CONCAT(
			'Ingresar el nuevo censo global de servicios del efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo
			);

		/* ingresa el nuevo censo de sala */
		INSERT INTO

			censos_diarios

		SELECT

			/* id_censo_diario */
			NULL,

			/* id_efector_servicio */
			cdt.id_efector_servicio,

			/* id_sala */
			cdt.id_sala,

			/* fecha_censo */
			fecha_censo,

			/* existencia_0 */
			cdt.existencia_0,

			/* ingresos */
			cdt.ingresos,

			/* pases_de */
			cdt.pases_de,

			/* pases_de_servicios */
			cdt.pases_de_servicios,

			/* altas */
			cdt.altas,

			/* defunciones_menos_48 */
			cdt.defunciones_menos_48,

			/* defunciones_mas_48 */
			cdt.defunciones_mas_48,

			/* pases_a */
			cdt.pases_a,

			/* pases_a_servicios */
			cdt.pases_a_servicios,

			/* existencia_24 */
			cdt.existencia_24,

			/* entradas_salidas_dia */
			cdt.entradas_salidas_dia,

			/* pacientes_dia */
			cdt.pacientes_dia,

			/* dias_estada */
			cdt.dias_estada,

			/* total_camas_sala */
			cdt.total_camas_sala,

			/* camas_disponibles */
			cdt.camas_disponibles,

			/* usuario */
			usuario,

			/* fecha_modificacion */
			NULL

		FROM

			censos_diarios_tmp cdt

		INNER JOIN

			efectores_servicios es

		ON cdt.id_efector_servicio = es.id_efector_servicio

		INNER JOIN

			efectores_servicios_hist esh

		ON es.id_efector_servicio = esh.id_efector_servicio

		WHERE

			es.id_efector = id_efector
		AND es.subsector = '4'
		AND esh.fecha_apertura<=fecha_censo
		AND (esh.fecha_cierre IS NULL OR esh.fecha_cierre>=fecha_censo)
		AND cdt.id_sala IS NULL
		AND cdt.fecha_censo = fecha_censo;

		/* mensaje */
		SET msg = CONCAT(
			'Censos globales de servicios del efector: ',
			nom_efector,
			' Fecha: ',
			fecha_censo,
			' realizado'
			);

		/* commit */
		COMMIT;

		/* devuelve valor de autocommit al iniciar el procedure */
		SET autocommit=autocommit_old;

	END IF;

END$$

DELIMITER ;

/* censos_diarios_check_periodo_salas */

DROP FUNCTION IF EXISTS censos_diarios_check_periodo_salas;

/*
*	Funcion que controla en un periodo si estan todos los censos de salas
*	cerrados en el efector
*
*	@param		id_efector					INTEGER			id efector
*	@param		fecha_desde					DATE			fecha_censo desde
*	@param		fecha_hasta					DATE			fecha_censo hasta
*	@return									INTEGER			 0 = OK
*
*															-6 = err fecha desde
*															-7 = err fecha hasta
*															-8 = err fechas
*															-9 = warning censos
*															-10= sala no habilitada
*
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_check_periodo_salas (
		id_efector INTEGER,
		fecha_censo_desde DATE,
		fecha_censo_hasta DATE)

    RETURNS INTEGER
    READS SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-1=Er efec;-6=Er des;-7=Er has;-8=Er fec;-9=Er cens;-10'

BEGIN

	DECLARE dias_periodo INTEGER;
	DECLARE cant_salas_habilitadas_periodo INTEGER;
	DECLARE cant_censos_estimados INTEGER;
	DECLARE cant_censos_cerrados INTEGER;

	DECLARE aux_id INTEGER;
	DECLARE sId_sala INTEGER;

	DECLARE exit_loop INTEGER;
	DECLARE estado INTEGER;

	/* cursor salas habilitadas en el periodo en el efector */
	DECLARE

		salas_efector

	CURSOR FOR

		(SELECT
			s.id_sala
		FROM
			salas s
		INNER JOIN
			salas_hist sh
		ON s.id_sala = sh.id_sala

		WHERE
			sh.fecha_apertura<=fecha_censo_desde
		AND sh.fecha_apertura<=fecha_censo_hasta
		AND (sh.fecha_cierre IS NULL OR (
				sh.fecha_cierre >= fecha_censo_desde
			AND sh.fecha_cierre >= fecha_censo_hasta))
		AND s.id_efector = id_efector);

	/* handler de bucle */
	DECLARE CONTINUE HANDLER FOR NOT FOUND

		SET exit_loop = 1;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		RETURN -5;
	END;

	/* check si id_efector existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector);

	IF aux_id=0 THEN

		RETURN -1;

	END IF;

	/* check fecha desde */
	IF fecha_censo_desde>DATE(NOW()) THEN

		RETURN -6;

	END IF;

	/* check fecha hasta */
	IF fecha_censo_hasta>DATE(NOW()) THEN

		RETURN -7;

	END IF;

	/* check fecha desde <= hasta */
	IF fecha_censo_desde>fecha_censo_hasta THEN

		RETURN -8;

	END IF;

	/* checks censos cerrados en el periodo - solo warning */
	SET dias_periodo = (
		SELECT
			DATEDIFF(fecha_censo_hasta,fecha_censo_desde)+1
			);

	SET cant_salas_habilitadas_periodo =
		(SELECT
			COUNT(*)
		FROM
			salas_hist sh
		INNER JOIN
			salas s
		ON sh.id_sala = s.id_sala

		WHERE
			sh.fecha_apertura<=fecha_censo_desde
		AND sh.fecha_apertura<=fecha_censo_hasta
		AND (sh.fecha_cierre IS NULL OR (
				sh.fecha_cierre >= fecha_censo_desde
			AND sh.fecha_cierre >= fecha_censo_hasta))
		AND s.id_efector = id_efector);

	SET cant_censos_estimados = dias_periodo*cant_salas_habilitadas_periodo;
	SET cant_censos_cerrados =
		(SELECT
			COUNT(*)
		FROM
			censos_diarios cd
		INNER JOIN
			salas s
		ON cd.id_sala = s.id_sala
		WHERE
			s.id_efector = id_efector
		AND cd.fecha_censo >= fecha_censo_desde
		AND cd.fecha_censo <= fecha_censo_hasta
		AND cd.id_efector_servicio IS NULL);

	IF cant_censos_estimados<>cant_censos_cerrados THEN

		/* genera tabla temporal con los censos que faltan */

		/* bucle de salas habilitadas en el periodo */
		OPEN salas_efector;

		bucle:
		LOOP

			FETCH
				salas_efector
			INTO
				sId_sala;

			IF exit_loop=1 THEN

				LEAVE bucle;

			END IF;

			/* check censo sala individual en el periodo */
			SET estado =
				(SELECT
					censos_diarios_check_periodo_sala(
						sId_sala,
						fecha_censo_desde,
						fecha_censo_hasta)
				);

			/* check sala no habilitada */
			IF estado=-10 THEN

				RETURN estado;

			END IF;

		END LOOP;

		CLOSE salas_efector;

		/* devuelve flag de censos sin cerrar */
		RETURN -9;

	END IF;

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_check_periodo_sala */

DROP FUNCTION IF EXISTS censos_diarios_check_periodo_sala;

/*
*	Funcion que controla en un periodo si estan todos los censos
*	cerrados de la sala
*
*	@param		id_sala						INTEGER			id de la sala
*	@param		fecha_desde					DATE			fecha_censo desde
*	@param		fecha_hasta					DATE			fecha_censo hasta
*	@return									INTEGER			 0 = OK
*
*															-6 = err fecha desde
*															-7 = err fecha hasta
*															-8 = err fechas
*															-9 = warning censos
*															-10= sala no habilitada
*
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_check_periodo_sala (
		id_sala INTEGER,
		fecha_censo_desde DATE,
		fecha_censo_hasta DATE)

    RETURNS INTEGER
    NOT DETERMINISTIC
	COMMENT '0=OK;-2=E s;-6=E FD;-7=E FH;-8=E F;-9=E C;-10=NoHab'

BEGIN

	DECLARE dias_periodo INTEGER;
	DECLARE flag_sala_periodo INTEGER;
	DECLARE cant_censos_cerrados INTEGER;

	DECLARE id_efector INTEGER;

	/* borra y crea tabla temporal de censos sin cerrar */
	CREATE TEMPORARY TABLE IF NOT EXISTS censos_sin_cerrar_tmp(

		id_efector INT(10) UNSIGNED NULL
			COMMENT 'id_efector del censo sin cerrar',
		id_sala INT(10) UNSIGNED NULL
			COMMENT 'concatenacion del id_efector y nro_sala',
		id_efector_servicio INT(10) UNSIGNED NULL
			COMMENT 'concatenacion del id_efector con el id_servicio_estadistica. los nuevos valores pueden obtenerse con la funcion get_id_efector_servicio',
		nombre_sala VARCHAR(255) NULL
			COMMENT 'nombre de la sala dentro del efector',
		nom_servicio_estadistica VARCHAR(255) NULL
			COMMENT 'Nombre del servicio de estadistica',
		cod_servicio CHAR(3) NULL
			COMMENT 'codigo nuclear de servicios de nacion vigente desde 2008',
		sector CHAR(1) NULL
			COMMENT '1=varones; 2=mujeres; 3=mixto',
		subsector CHAR(1) NULL
			COMMENT '4=internacion; 5=CE; 6=atencion domiciliaria',
		fecha_censo	DATE NOT NULL
			COMMENT 'Fecha de censo sin cerrar')

		ENGINE = InnoDB
		CHARACTER SET = utf8
		COLLATE utf8_unicode_ci

		COMMENT = 'Censos sin cerrar en el periodo';

	/* limpia consulta anterior */
	DELETE FROM
		censos_sin_cerrar_tmp
	WHERE
		censos_sin_cerrar_tmp.id_sala = id_sala;

	/* check si id_sala existe */
	SET id_efector =
		(SELECT
			s.id_efector
		FROM
			salas s
		WHERE
			s.id_sala = id_sala);

	IF id_efector IS NULL THEN

		RETURN -2;

	END IF;

	/* check fecha desde */
	IF fecha_censo_desde>DATE(NOW()) THEN

		RETURN -6;

	END IF;

	/* check fecha hasta */
	IF fecha_censo_hasta>DATE(NOW()) THEN

		RETURN -7;

	END IF;

	/* check fecha desde <= hasta */
	IF fecha_censo_desde>fecha_censo_hasta THEN

		RETURN -8;

	END IF;

	/* cantidad dias del periodo */
	SET dias_periodo = (
		SELECT
			DATEDIFF(fecha_censo_hasta,fecha_censo_desde)+1
			);

	/* check sala habilitada en el periodo */
	SET flag_sala_periodo =
		(SELECT
			COUNT(*)
		FROM
			salas_hist sh

		WHERE
			sh.fecha_apertura<=fecha_censo_desde
		AND sh.fecha_apertura<=fecha_censo_hasta
		AND (sh.fecha_cierre IS NULL OR (
				sh.fecha_cierre >= fecha_censo_desde
			AND sh.fecha_cierre >= fecha_censo_hasta))
		AND sh.id_sala = id_sala);

	IF flag_sala_periodo = 0 THEN

		RETURN -10;

	END IF;

	/* cantidad de censo cerrados */
	SET cant_censos_cerrados =
		(SELECT
			COUNT(*)
		FROM
			censos_diarios cd
		WHERE
			cd.id_sala = id_sala
		AND cd.fecha_censo >= fecha_censo_desde
		AND cd.fecha_censo <= fecha_censo_hasta
		AND cd.id_efector_servicio IS NULL);

	IF dias_periodo=cant_censos_cerrados THEN

		RETURN 0;

	END IF;

	/* crea listado de fechas del periodo */
	CALL ri_generar_listado_fechas(
		fecha_censo_desde,
		fecha_censo_hasta);

	/* inserta los censos sin cerrar */
	INSERT INTO

		censos_sin_cerrar_tmp

	SELECT

		/* id_efector */
		id_efector,

		/* id_sala */
		id_sala,

		/* id_efector_servicio */
		NULL,

		/* nombre_sala */
		s.nombre,

		/* nom_servicio_estadistica */
		NULL,

		/* cod_servicio */
		NULL,

		/* sector */
		NULL,

		/* subsector */
		NULL,

		/* fecha_censo */
		lft.fecha

	FROM

		salas s,
		listado_fechas_tmp lft

	WHERE
		s.id_sala = id_sala
	AND lft.fecha NOT IN (
		SELECT
			cd.fecha_censo
		FROM
			censos_diarios cd
		WHERE
			cd.id_sala = id_sala
		AND cd.id_efector_servicio IS NULL
		AND cd.fecha_censo>=fecha_censo_desde
		AND cd.fecha_censo<=fecha_censo_hasta);

	RETURN -9;

END$$

DELIMITER ;

/* censos_diarios_check_periodo_servicios */

DROP FUNCTION IF EXISTS censos_diarios_check_periodo_servicios;

/*
*	Funcion que controla en un periodo si estan todos los censos de servicios
*	cerrados en el efector
*
*	@param		id_efector					INTEGER			id efector
*	@param		fecha_desde					DATE			fecha_censo desde
*	@param		fecha_hasta					DATE			fecha_censo hasta
*	@return									INTEGER			 0 = OK
*
*															-6 = err fecha desde
*															-7 = err fecha hasta
*															-8 = err fechas
*															-9 = warning censos
*															-10= servicio no habilitado
*
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_check_periodo_servicios (
		id_efector INTEGER,
		fecha_censo_desde DATE,
		fecha_censo_hasta DATE)

    RETURNS INTEGER
    READS SQL DATA
    NOT DETERMINISTIC
	COMMENT '0=OK;-1=Er efec;-6=Er des;-7=Er has;-8=Er fec;-9=Er cens;-10'

BEGIN

	DECLARE dias_periodo INTEGER;
	DECLARE cant_servicios_habilitados_periodo INTEGER;
	DECLARE cant_censos_estimados INTEGER;
	DECLARE cant_censos_cerrados INTEGER;

	DECLARE aux_id INTEGER;
	DECLARE sId_efector_servicio INTEGER;

	DECLARE exit_loop INTEGER;
	DECLARE estado INTEGER;

	/* cursor servicios habilitados en el periodo en el efector */
	DECLARE

		servicios_efector

	CURSOR FOR

		(SELECT
			es.id_efector_servicio
		FROM
			efectores_servicios es
		INNER JOIN
			efectores_servicios_hist esh
		ON es.id_efector_servicio = esh.id_efector_servicio

		WHERE
			esh.fecha_apertura <= fecha_censo_desde
		AND esh.fecha_apertura <= fecha_censo_hasta
		AND (esh.fecha_cierre IS NULL OR (
				esh.fecha_cierre >= fecha_censo_desde
			AND esh.fecha_cierre >= fecha_censo_hasta))
		AND es.id_efector = id_efector
		AND es.sector = '4');

	/* handler de bucle */
	DECLARE CONTINUE HANDLER FOR NOT FOUND

		SET exit_loop = 1;

	/* exit handler para falla de sql */
	DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING
	BEGIN
		RETURN -5;
	END;

	/* check si id_efector existe */
	SET aux_id =
		(SELECT
			COUNT(*)
		FROM
			efectores e
		WHERE
			e.id_efector = id_efector);

	IF aux_id=0 THEN

		RETURN -1;

	END IF;

	/* check fecha desde */
	IF fecha_censo_desde>DATE(NOW()) THEN

		RETURN -6;

	END IF;

	/* check fecha hasta */
	IF fecha_censo_hasta>DATE(NOW()) THEN

		RETURN -7;

	END IF;

	/* check fecha desde <= hasta */
	IF fecha_censo_desde>fecha_censo_hasta THEN

		RETURN -8;

	END IF;

	/* checks censos cerrados en el periodo - solo warning */
	SET dias_periodo = (
		SELECT
			DATEDIFF(fecha_censo_hasta,fecha_censo_desde)+1
			);

	SET cant_servicios_habilitados_periodo =
		(SELECT
			COUNT(*)
		FROM
			efectores_servicios_hist esh
		INNER JOIN
			efectores_servicios es
		ON esh.id_efector_servicio = es.id_efector_servicio

		WHERE
			esh.fecha_apertura <= fecha_censo_desde
		AND esh.fecha_apertura <= fecha_censo_hasta
		AND (esh.fecha_cierre IS NULL OR (
				esh.fecha_cierre >= fecha_censo_desde
			AND esh.fecha_cierre >= fecha_censo_hasta))
		AND es.id_efector = id_efector
		AND es.subsector = '4');

	SET cant_censos_estimados = dias_periodo*cant_servicios_habilitados_periodo;
	SET cant_censos_cerrados =
		(SELECT
			COUNT(*)
		FROM
			censos_diarios cd
		INNER JOIN
			efectores_servicios es
		ON cd.id_efector_servicio = es.id_efector_servicio
		WHERE
			es.id_efector = id_efector
		AND cd.fecha_censo >= fecha_censo_desde
		AND cd.fecha_censo <= fecha_censo_hasta
		AND cd.id_sala IS NULL);

	IF cant_censos_estimados<>cant_censos_cerrados THEN

		/* genera tabla temporal con los censos que faltan */

		/* bucle de servicios habilitadas en el periodo */
		OPEN servicios_efector;

		bucle:
		LOOP

			FETCH
				servicios_efector
			INTO
				sId_efector_servicio;

			IF exit_loop=1 THEN

				LEAVE bucle;

			END IF;

			/* check censo servicio individual en el periodo */
			SET estado =
				(SELECT
					censos_diarios_check_periodo_servicio(
						sId_efector_servicio,
						fecha_censo_desde,
						fecha_censo_hasta)
				);

			/* check servicio no habilitado */
			IF estado=-10 THEN

				RETURN estado;

			END IF;

		END LOOP;

		CLOSE servicios_efector;

		/* devuelve flag de censos sin cerrar */
		RETURN -9;

	END IF;

	RETURN 0;

END$$

DELIMITER ;

/* censos_diarios_check_periodo_servicio */

DROP FUNCTION IF EXISTS censos_diarios_check_periodo_servicio;

/*
*	Funcion que controla en un periodo si estan todos los censos
*	cerrados del servicio
*
*	@param		id_efector_servicio			INTEGER			id efector servicio
*	@param		fecha_desde					DATE			fecha_censo desde
*	@param		fecha_hasta					DATE			fecha_censo hasta
*	@return									INTEGER			 0 = OK
*
*															-6 = err fecha desde
*															-7 = err fecha hasta
*															-8 = err fechas
*															-9 = warning censos
*															-10= servicio no habilitado
*
*/

/* A procedure or function is considered deterministic if it always produces the same result for the
	same input parameters, and not deterministic otherwise. If neither DETERMINISTIC nor NOT DETERMINISTIC
	is given in the routine definition, the default is NOT DETERMINISTIC. */

DELIMITER $$

CREATE
    DEFINER = CURRENT_USER
    FUNCTION censos_diarios_check_periodo_servicio (
		id_efector_servicio INTEGER,
		fecha_censo_desde DATE,
		fecha_censo_hasta DATE)

    RETURNS INTEGER
    NOT DETERMINISTIC
	COMMENT '0=OK;-2=E s;-6=E FD;-7=E FH;-8=E F;-9=E C;-10=NoHab'

BEGIN

	DECLARE dias_periodo INTEGER;
	DECLARE flag_servicio_periodo INTEGER;
	DECLARE cant_censos_cerrados INTEGER;

	DECLARE id_efector INTEGER;

	/* borra y crea tabla temporal de censos sin cerrar */
	CREATE TEMPORARY TABLE IF NOT EXISTS censos_sin_cerrar_tmp(

		id_efector INT(10) UNSIGNED NULL
			COMMENT 'id_efector del censo sin cerrar',
		id_sala INT(10) UNSIGNED NULL
			COMMENT 'concatenacion del id_efector y nro_sala',
		id_efector_servicio INT(10) UNSIGNED NULL
			COMMENT 'concatenacion del id_efector con el id_servicio_estadistica. los nuevos valores pueden obtenerse con la funcion get_id_efector_servicio',
		nombre_sala VARCHAR(255) NULL
			COMMENT 'nombre de la sala dentro del efector',
		nom_servicio_estadistica VARCHAR(255) NULL
			COMMENT 'Nombre del servicio de estadistica',
		cod_servicio CHAR(3) NULL
			COMMENT 'codigo nuclear de servicios de nacion vigente desde 2008',
		sector CHAR(1) NULL
			COMMENT '1=varones; 2=mujeres; 3=mixto',
		subsector CHAR(1) NULL
			COMMENT '4=internacion; 5=CE; 6=atencion domiciliaria',
		fecha_censo	DATE NOT NULL
			COMMENT 'Fecha de censo sin cerrar')
		ENGINE = InnoDB
		CHARACTER SET = utf8
		COLLATE utf8_unicode_ci

		COMMENT = 'Censos sin cerrar en el periodo';

	/* limpia consulta anterior */
	DELETE FROM
		censos_sin_cerrar_tmp
	WHERE
		censos_sin_cerrar_tmp.id_efector_servicio = id_efector_servicio;

	/* check si id_efector_servicio existe */
	SET id_efector =
		(SELECT
			es.id_efector
		FROM
			efectores_servicios es
		WHERE
			es.id_efector_servicio = id_efector_servicio);

	IF id_efector IS NULL THEN

		RETURN -2;

	END IF;

	/* check fecha desde */
	IF fecha_censo_desde>DATE(NOW()) THEN

		RETURN -6;

	END IF;

	/* check fecha hasta */
	IF fecha_censo_hasta>DATE(NOW()) THEN

		RETURN -7;

	END IF;

	/* check fecha desde <= hasta */
	IF fecha_censo_desde>fecha_censo_hasta THEN

		RETURN -8;

	END IF;

	/* cantidad dias del periodo */
	SET dias_periodo = (
		SELECT
			DATEDIFF(fecha_censo_hasta,fecha_censo_desde)+1
			);

	/* check servicio habilitado en el periodo */
	SET flag_servicio_periodo =
		(SELECT
			COUNT(*)
		FROM
			efectores_servicios_hist esh

		WHERE
			esh.fecha_apertura <= fecha_censo_desde
		AND esh.fecha_apertura <= fecha_censo_hasta
		AND (esh.fecha_cierre IS NULL OR (
				esh.fecha_cierre >= fecha_censo_desde
			AND esh.fecha_cierre >= fecha_censo_hasta))
		AND esh.id_efector_servicio = id_efector_servicio);

	IF flag_servicio_periodo = 0 THEN

		RETURN -10;

	END IF;

	/* cantidad de censo cerrados */
	SET cant_censos_cerrados =
		(SELECT
			COUNT(*)
		FROM
			censos_diarios cd
		WHERE
			cd.id_efector_servicio = id_efector_servicio
		AND cd.fecha_censo >= fecha_censo_desde
		AND cd.fecha_censo <= fecha_censo_hasta
		AND cd.id_sala IS NULL);

	IF dias_periodo = cant_censos_cerrados THEN

		RETURN 0;

	END IF;

	/* crea listado de fechas del periodo */
	CALL ri_generar_listado_fechas(
		fecha_censo_desde,
		fecha_censo_hasta);

	/* inserta los censos sin cerrar */
	INSERT INTO

		censos_sin_cerrar_tmp

	SELECT

		/* id_efector */
		id_efector,

		/* id_sala */
		NULL,

		/* id_efector_servicio */
		id_efector_servicio,

		/* nombre_sala */
		NULL,

		/* nom_servicio_estadistica */
		es.nom_servicio_estadistica,

		/* cod_servicio */
		es.cod_servicio,

		/* sector */
		es.sector,

		/* subsector */
		es.subsector,

		/* fecha_censo */
		lft.fecha

	FROM

		efectores_servicios es,
		listado_fechas_tmp lft

	WHERE
		es.id_efector_servicio = id_efector_servicio
	AND lft.fecha NOT IN (
		SELECT
			cd.fecha_censo
		FROM
			censos_diarios cd
		WHERE
			cd.id_efector_servicio = id_efector_servicio
		AND cd.id_sala IS NULL
		AND cd.fecha_censo >= fecha_censo_desde
		AND cd.fecha_censo <= fecha_censo_hasta);

	RETURN -9;

END$$

DELIMITER ;


text:
title: Meeting Tonight
author: Andrew Mike
date: 2015-11-03
layout: post
---

Hello everyone!

Tonight, we'll have our general meeting at 7:30 PM at the space. The agenda is [here](http://wiki.hacksburg.org/meetings:meeting_agenda_and_minutes_for_2015-11-03).

We'll be talking about the annual meeting this Saturday, projects we're working on, and the vacuum former project. Also, don't forget about Kurt's high altitude balloon meeting at 6:30. Hope you can join us!

redpajama_set_name: RedPajamaGithub


text:
package avrora.sim.energy;

import avrora.sim.FiniteStateMachine;
import avrora.sim.clock.Clock;

/**
 * Class for energy modeling. All consumers create an instance of this class and keep it updated with all
 * state changes concerning power consumption. This class keeps track of all these state changes and cycles
 * spend in each state. The state changes are propagated to monitors based on a subscription system. This
 * enables logging of power consumption.
 *
 * @author Olaf Landsiedel
 */
public class Energy implements FiniteStateMachine.Probe {

    //name of the device, which energy consumption is traced by
    //this class instance
    private String deviceName;
    //current draw for each state
    private double[] ampere;
    //cycles spent in each state
    private long[] cycles;
    // current state, e.g. mode
    private int currentMode;
    // the mode (e.g. state) the system was in before
    private int oldMode;
    // cycle the state was changed last
    private long lastChange;
    // voltage, needed for computation of energy consumption
    private static final double voltage = 3.0d;
    // time one mcu cycle takes
    private double cycleTime;
    //the state machine handles the sate of the device
    private FiniteStateMachine stateMachine;
    //the clock -> it knwos the time ;-)
    private Clock clock;

    private EnergyControl.Instance instance;

    /**
     * create new energy class, to enable energy modelling
     *
     * @param deviceName  name of the device to model
     * @param modeAmpere  array of current draw for each device state (in Ampere)
     * @param fsm         finite state machine of this device
     */
    public Energy(String deviceName, double[] modeAmpere, FiniteStateMachine fsm ) {
        // remember all params
        this.deviceName = deviceName;
        this.clock = fsm.getClock();
        this.ampere = modeAmpere;
        this.stateMachine = fsm;
        this.currentMode = fsm.getStartState();
        int freq=(int)clock.getHZ();
        this.cycleTime = 1.0d / freq;
        this.instance = EnergyControl.getCurrentInstance();

        // subscribe this consumer to the energy control
        EnergyControl.addConsumer(this);
    }

    /**
     * The fireBeforeTransition() method allows the probe to gain control
     * before the state machine transitions between two states. The before state and the
     * after state are passed as parameters.
     * @param beforeState the before state represented as an integer
     * @param afterState the after state represented as an integer
     */
    public void fireBeforeTransition(int beforeState, int afterState){
        //we use fireAfterTransition
    }

    /**
     * The fireAfterTransition() method allows the probe to gain control
     * after the state machine transitions between two states. The before state and the
     * after state are passed as parameters.
     * @param beforeState the before state represented as an integer
     * @param afterState the after state represented as an integer
     */
    public void fireAfterTransition(int beforeState, int afterState){
        if (afterState != currentMode) {
            cycles[currentMode] += clock.getCount() - lastChange;
            oldMode = currentMode;
            currentMode = afterState;
            lastChange = clock.getCount();
            //notify the energy control that I am now in a new state
            instance.stateChange(this);
        }
    }

    /**
     * get the power consumption of this device
     *
     * @return power consumption in Joule
     */
    public double getTotalConsumedEnergy() {
        double total = 0.0d;
        for (int i = 0; i < ampere.length; i++)
            total += getConsumedEnergy(i);
        return total;
    }

    /**
     * get the power consumption of a state
     *
     * @param mode the mode or state
     * @return power consumption in Joule
     */
    public double getConsumedEnergy(int mode) {
        return voltage * getCycles(mode) * ampere[mode] * cycleTime;
    }

    /**
     * get the number of modes of this device
     *
     * @return mode number
     */
    public int getModeNumber() {
        return ampere.length;
    }

    /**
     * get the current state or mode of the device
     *
     * @return current mode
     */
    public int getCurrentMode() {
        return currentMode;
    }

    /**
     * get the name of a mode
     *
     * @param mode mode number
     * @return mode name
     */
    public String getModeName(int mode) {
        return stateMachine.getStateName(mode);
    }

    /**
     * get the current draw of a mode
     *
     * @param mode mode number
     * @return current draw in Ampere
     */
    public double getModeAmpere(int mode) {
        return ampere[mode];
    }

    /**
     * get the cycles spend in a device state
     *
     * @param mode mode number
     * @return cycles
     */
    public long getCycles(int mode) {
        if ( cycles == null ) return 0;
        long ret = cycles[mode];
        if (mode == currentMode)
            ret += clock.getCount() - lastChange;
        return ret;
    }

    /**
     * get the device name
     *
     * @return device name
     */
    public String getName() {
        return deviceName;
    }

    /**
     * get old mode
     *
     * @return old mode
     */
    public int getOldMode() {
        return oldMode;
    }

    /**
     * get the current draw
     *
     * @return current draw in Ampere
     */
    public double getCurrentAmpere() {
        return ampere[currentMode];
    }

    /**
     * get the current draw of the old mode
     *
     * @return current draw
     */
    public double getOldAmpere() {
        return ampere[oldMode];
    }

    /**
     * active energy modeling, e.g. insert the probe into to
     * component state machine
     */
    public void activate() {
        //insert probe into finite state machine
        stateMachine.insertProbe(this);
        // setup cycle array to store the cycles of each state
        cycles = new long[ampere.length];
        for (int i = 0; i < cycles.length; i++)
            cycles[i] = 0;
    }

}


text:
Examples
========

Retry decorator
---------------

TODO: Make a more configurable retry decorator and add it in ``aspectlib.contrib``.

.. code-block:: python

    class Client(object):
        def __init__(self, address):
            self.address = address
            self.connect()
        def connect(self):
            # establish connection
        def action(self, data):
            # do some stuff

    def retry(retries=(1, 5, 15, 30, 60), retry_on=(IOError, OSError), prepare=None):
        assert len(retries)

        @aspectlib.Aspect
        def retry_aspect(*args, **kwargs):
            durations = retries
            while True:
                try:
                    yield aspectlib.Proceed
                    break
                except retry_on as exc:
                    if durations:
                        logging.warn(exc)
                        time.sleep(durations[0])
                        durations = durations[1:]
                        if prepare:
                            prepare(*args, **kwargs)
                    else:
                        raise

        return retry_aspect

Now patch the ``Client`` class to have the retry functionality on all its methods:

.. code-block:: python

    aspectlib.weave(Client, retry())

or with different retry options (reconnect before retry):

.. code-block:: python

    aspectlib.weave(Client, retry(prepare=lambda self, *_: self.connect())

or just for one method:

.. code-block:: python

    aspectlib.weave(Client.action, retry())

You can see here the advantage of having reusable retry functionality. Also, the retry handling is
decoupled from the ``Client`` class.

Debugging
---------

... those damn sockets:

.. code-block:: pycon

    >>> import aspectlib, socket, sys
    >>> with aspectlib.weave(
    ...     socket.socket,
    ...     aspectlib.debug.log(
    ...         print_to=sys.stdout,
    ...         stacktrace=None,
    ...     ),
    ...     lazy=True,
    ... ):
    ...     s = socket.socket()
    ...     s.connect(('example.com', 80))
    ...     s.send(b'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
    ...     s.recv(8)
    ...     s.close()
    ...
    {socket...}.connect(('example.com', 80))
    {socket...}.connect => None
    {socket...}.send(...'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n')
    {socket...}.send => 37
    37
    {socket...}.recv(8)
    {socket...}.recv => ...HTTP/1.1...
    ...'HTTP/1.1'
    ...

The output looks a bit funky because it is written to be run by `doctest
<https://docs.python.org/2/library/doctest.html>`_ - so you don't use broken examples :)

Testing
-------

Mock behavior for tests:

.. code-block:: python

    class MyTestCase(unittest.TestCase):

        def test_stuff(self):

            @aspectlib.Aspect
            def mock_stuff(self, value):
                if value == 'special':
                    yield aspectlib.Return('mocked-result')
                else:
                    yield aspectlib.Proceed

            with aspectlib.weave(foo.Bar.stuff, mock_stuff):
                obj = foo.Bar()
                self.assertEqual(obj.stuff('special'), 'mocked-result')


text:
mod scalar;
mod px;
mod image;

pub use scalar::{Scalar, ScalarVal};

pub use px::{Pixel, PixelArithmetic, PixelVal};
pub use px::{Gray, Gray8U, Gray16U, Gray32U, Gray32F, Gray64F};
pub use px::{GrayVal, GrayVal8U, GrayVal16U, GrayVal32U, GrayVal32F, GrayVal64F};

pub use image::{Image, ImageVal, ImageBuffer, ImageBufferVal};


text:
package org.apache.commons.jexl2.internal;

import java.util.Iterator;
import java.util.Enumeration;

/**
 * An Iterator wrapper for an Enumeration.
 * @param <T> the type of object this iterator returns
 * @since 1.0
 */
public class EnumerationIterator<T> implements Iterator<T> {
    /**
     * The enumeration to iterate over.
     */
    private final Enumeration<T> enumeration;

    /**
     * Creates a new iteratorwrapper instance for the specified
     * Enumeration.
     *
     * @param enumer  The Enumeration to wrap.
     */
    public EnumerationIterator(Enumeration<T> enumer) {
        enumeration = enumer;
    }

    /**
     * Move to next element in the array.
     *
     * @return The next object in the array.
     */
    public T next() {
        return enumeration.nextElement();
    }

    /**
     * Check to see if there is another element in the array.
     *
     * @return Whether there is another element.
     */
    public boolean hasNext() {
        return enumeration.hasMoreElements();
    }

    /**
     *  Unimplemented.  No analogy in Enumeration
     */
    public void remove() {
        // not implemented
    }
}


text:
Browser wars have given amazing performance to JavaScript, and Node.js has brought that power to the server
side.  But let's be honest... JavaScript, HTML and CSS aren't the most beautiful and maintainable technologies,
so some of us adopt compile-to languages like CoffeeScript, Jade and Stylus.  We use tools like Grunt and Gulp
to build and minify for client-side performance, and we end up waiting a bit longer to see each of our changes.

In this talk, I will explore the trade-offs we make when we choose one technology or another.  I will discuss
how our choices affect development and production environments and how we can position ourselves to work around
those trade-offs, developing beautiful code without sacrificing speed.  After all, what good is an amazing
JavaScript engine if we don't run amazing code on it?

## About Sam Eubank

![Sam Eubank](https://avatars.githubusercontent.com/u/6846442?s=256)

Sam Eubank ([GitHub](https://github.com/zerious), [Twitter](https://twitter.com/sameubank),
[LinkedIn](https://www.linkedin.com/in/sameubank)) is a full-stack developer who has been writing JavaScript
code since 1997. He was a core contributor on Amazon's JavaScript Excellence Team and spoke about Node.js at
Amazon's WebDevCon 2013. Since leaving Amazon, Sam has been building JavaScript tools for the rest of us.