/* GENERACION DEL PLAN ESTRATEGICO  */

create or replace PROCEDURE AB39A.PROC_GENERA_PLAN_ESTATEGICO (
-- Codigo del plan estrategico
codigo_pe IN PLS_INTEGER
) AS

	-- Resultado de la INSERT_SELECT de EJES
	blnEJES BOOLEAN;
	-- Resultado de la INSERT_SELECT de ELEMENTOS
	blnELEMENTOS BOOLEAN;
	
BEGIN
	
	blnEJES:=false;
	blnELEMENTOS:=false;
	
	-- Realizamos la copia del plan para la tabla de EJES_PE  
	BEGIN
		INSERT INTO EJES_PE (CODPLANE, ID_EJE, HELBURU, HELBURUCAS, CODVERSIONPE)
		SELECT 
		PLANES_ESTRATEGICOS.CODPLANE, EJE.ID_EJE, EJE.HELBURU, EJE.HELBURUCAS, 1
		FROM EJE, ENTIDADES, PLANES_ESTRATEGICOS
		WHERE
		PLANES_ESTRATEGICOS.CODPLANE = codigo_pe AND
		PLANES_ESTRATEGICOS.CODENTIDAD = ENTIDADES.CODENTIDAD AND
		ENTIDADES.TIPO_ENTIDAD = EJE.ID_TIPOORGANIZACION;
		blnEJES:=true;
    EXCEPTION
		WHEN OTHERS THEN
		blnEJES:=false;
		DBMS_OUTPUT.put_line ( 'Error generando EJES_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;
  
	-- Realizamos la copia del plan para la tabla de ELEMENTOS_PE  
	BEGIN
		INSERT INTO ELEMENTOS_PE 
		(CODELEMENTOPE,CODPLANE, CODVERSIONPE, ELEMBASE,
		ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO, 
		HELBURU, HELBURUCAS, CODELEMENTOPEPADRE, 
    TIENEVALOR, TIENEEUS, TIENEELEBI)
		SELECT 
		ELEMENTOS_PE_SEQ.NEXTVAL, PLANES_ESTRATEGICOS.CODPLANE, 1, 0, 
		ELEMENTO.ORDEN, ELEMENTO.NIVEL, ELEMENTO.NOMBRE, ELEMENTO.NOMBRECAS, ELEMENTO.ID_ELEMENTO, 
		ELEMENTO.HELBURU, ELEMENTO.HELBURUCAS, NULL CODELEMENTOPEPADRE, 
    TIENEVALOR, TIENEEUS, TIENEELEBI
		FROM ELEMENTO, EJE, ENTIDADES, PLANES_ESTRATEGICOS
		WHERE
		PLANES_ESTRATEGICOS.CODPLANE = codigo_pe AND
		PLANES_ESTRATEGICOS.CODENTIDAD = ENTIDADES.CODENTIDAD AND
		ENTIDADES.TIPO_ENTIDAD = EJE.ID_TIPOORGANIZACION AND
		ELEMENTO.NIVEL <= 3 AND
		ELEMENTO.ID_EJE = EJE.ID_EJE;
		blnELEMENTOS:=true;
    EXCEPTION
		WHEN OTHERS THEN
		blnELEMENTOS:=false;
		DBMS_OUTPUT.put_line ( 'Error generando ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;

	if (blnEJES=true and blnELEMENTOS=true) then
	
		BEGIN
			UPDATE ELEMENTOS_PE EPE SET EPE.CODELEMENTOPEPADRE = (SELECT ELE_DEST.CODELEMENTOPE
    FROM ELEMENTO ELE, ELEMENTOS_PE ELE_ORIG, ELEMENTOS_PE ELE_DEST
  WHERE 
   -- El codigo del elemento_pe origen es el que estamos recorriendo desde le exterior
   ELE_ORIG.CODELEMENTOPE = EPE.CODELEMENTOPE AND   
   ELE_ORIG.CODPLANE = EPE.CODPLANE AND 
   ELE_ORIG.CODVERSIONPE = EPE.CODVERSIONPE AND
   -- Los elementos de origen_pe y destino_pe pertenecen al mismo plan
   ELE_ORIG.CODPLANE = ELE_DEST.CODPLANE AND 
   ELE_ORIG.CODVERSIONPE = ELE_DEST.CODVERSIONPE AND
   -- Cruzamos el ID de elemento_pe de origen con el ID de elemento
   ELE_ORIG.IDELEMENTO = ELE.ID_ELEMENTO AND
   -- Cruzamos el ID de elemento padre de elemento 
   -- con el ID de elemento_pe destino para recuperar su nueva codificacion
   ELE.ID_ELEMENTOPADRE = ELE_DEST.IDELEMENTO)
   -- La UPDATE solo actua sobre los elementos del plan y version indicados
   WHERE CODPLANE = codigo_pe AND CODVERSIONPE = 1;				

		EXCEPTION
			WHEN OTHERS THEN
			DBMS_OUTPUT.put_line ( 'Error generaldo los codigos padre: '|| DBMS_UTILITY.format_error_stack ());
			RAISE;
		END;
	
	end if;	  

END PROC_GENERA_PLAN_ESTATEGICO;
/

/* VERSIONADO DEL PLAN ESTRATEGICO  */

create or replace PROCEDURE PROC_VERSIONA_PLAN_ESTATEGICO (
-- Codigo del plan estrategico
codigo_pe IN PLS_INTEGER
) AS

	-- Version a la que tendremos que hacer el versionado
	maxVersion INTEGER;	
	-- Posicion del recorrido de inserts
	counter INTEGER;		
	-- Valor recuperado del type table para recodificacion
	codElemFromType	INTEGER;
	-- Valor del elemento destino
	elemDest	INTEGER;  
	-- Cursor para recorrer los elementos
	CURSOR curELEMENTO IS SELECT CODELEMENTOPE, codigo_pe CODPLANE, 
		ELEMBASE, ORDEN, NIVEL, NOMBRE, 
		NOMBRECAS, HELBURU, HELBURUCAS,IDELEMENTO,  CODELEMENTOPEPADRE,
		HAS_EUS,HAS_ELEBI,AURRE_EUS,AURRE_ELEBI,AMAI_EUS,AMAI_ELEBI,OHARRAK,
    HAS_VALOR, AURRE_VALOR, AMAI_VALOR, TIENEELEBI, TIENEVALOR, TIENESINO,
    HAS_SINO, AURRE_SINO, AMAI_SINO, TIENEEUS
		FROM ELEMENTOS_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion ORDER BY CODELEMENTOPE;
    reg curELEMENTO%ROWTYPE;

	-- Cursor para actualizar los elementos padre
	CURSOR curELEMENTOPADRE IS SELECT CODPLANE, CODVERSIONPE, CODELEMENTOPE, CODELEMENTOPEPADRE
		FROM ELEMENTOS_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion+1 AND
		CODELEMENTOPEPADRE IS NOT NULL ORDER BY CODELEMENTOPEPADRE;
    regPadre curELEMENTOPADRE%ROWTYPE;
	
	TYPE RECORD_RECODIFICACION IS RECORD(
	  CODELEMENTO_ORIG NUMBER,
	  CODELEMENTO_DEST NUMBER);
	TYPE TBL_RECODIFICACION IS TABLE OF RECORD_RECODIFICACION INDEX BY BINARY_INTEGER;
	
	rec_recod RECORD_RECODIFICACION;
	tbl_recod TBL_RECODIFICACION;
	
BEGIN

	counter:=1;
	-- Recuperacion de la version maxima dado un plan estrategico
	SELECT DISTINCT MAX(CODVERSION) VERSION INTO maxVersion FROM PLANES_ESTRATEGICOS WHERE CODPLANE = codigo_pe ;

	-- Realizamos la copia del plan para la tabla de PLANES_ESTRATEGICOS
	BEGIN
		INSERT INTO PLANES_ESTRATEGICOS 
		(CODPLANE,CODVERSION,CODENTIDAD,CODPLANIFICACION,ANYOINICIO,ANYOFIN,
		 ACTIVO,INDICE_OBLIGAT,NIVEL_CUMPLIMIENTO_REQEUS,PORCENTAJE_BILIN,
		 FECHA_ALTA,FECHA_ACEPTACION_PLAN,NOMBRE,NOMBREEUS,SOLICITAR_TXOSTENA)
		SELECT 
		CODPLANE,(maxversion+1) CODVERSION,CODENTIDAD,CODPLANIFICACION,ANYOINICIO,ANYOFIN,
		 ACTIVO,INDICE_OBLIGAT,NIVEL_CUMPLIMIENTO_REQEUS,PORCENTAJE_BILIN,
		 SYSDATE,FECHA_ACEPTACION_PLAN,NOMBRE,NOMBREEUS,SOLICITAR_TXOSTENA
		FROM PLANES_ESTRATEGICOS
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSION = maxVersion;
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error versionando PLANES_ESTRATEGICOS: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;   

	-- Realizamos la copia del plan para la tabla de EJES_PE  
	BEGIN
		INSERT INTO EJES_PE (CODPLANE, ID_EJE, HELBURU, HELBURUCAS, CODVERSIONPE)
		SELECT 
		CODPLANE, ID_EJE, HELBURU, HELBURUCAS, (maxversion+1)
		FROM EJES_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion;
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error versionando EJES_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;
  
	-- Realizamos la copia del plan para la tabla de ELEMENTOS_PE  
	BEGIN									

	   OPEN curELEMENTO;
	   FETCH curELEMENTO INTO reg;
	   WHILE curELEMENTO%FOUND LOOP
     
      SELECT ELEMENTOS_PE_SEQ.NEXTVAL INTO ElemDest FROM DUAL;
     
			INSERT INTO ELEMENTOS_PE 
			(CODELEMENTOPE, CODPLANE, CODVERSIONPE, ELEMBASE, 
			ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
			HELBURU, HELBURUCAS,  CODELEMENTOPEPADRE,
			HAS_EUS,HAS_ELEBI,AURRE_EUS,AURRE_ELEBI,AMAI_EUS,AMAI_ELEBI,OHARRAK,
      HAS_VALOR, AURRE_VALOR, AMAI_VALOR, TIENEELEBI, TIENEVALOR, TIENESINO,
      HAS_SINO, AURRE_SINO, AMAI_SINO, TIENEEUS) VALUES
			(ElemDest,reg.CODPLANE,(maxVersion+1),reg.ELEMBASE,
			reg.ORDEN,reg.NIVEL,reg.NOMBRE,reg.NOMBRECAS,reg.IDELEMENTO,
			reg.HELBURU,reg.HELBURUCAS,reg.CODELEMENTOPEPADRE,
			reg.HAS_EUS,reg.HAS_ELEBI,reg.AURRE_EUS,reg.AURRE_ELEBI,reg.AMAI_EUS,reg.AMAI_ELEBI,reg.OHARRAK,
      reg.HAS_VALOR, reg.AURRE_VALOR, reg.AMAI_VALOR, reg.TIENEELEBI, reg.TIENEVALOR, reg.TIENESINO,
      reg.HAS_SINO, reg.AURRE_SINO, reg.AMAI_SINO, reg.TIENEEUS);
			
			-- Guardamos los datos para la posterior recodificacion
			rec_recod.CODELEMENTO_ORIG := reg.CODELEMENTOPE;
			rec_recod.CODELEMENTO_DEST := ElemDest;
			
			-- INSERT INTO AB39LGT00 (CODORIGEN, CODDESTINO) VALUES (rec_recod.CODELEMENTO_ORIG,rec_recod.CODELEMENTO_DEST );
      
			tbl_recod(counter) := rec_recod;
			
			counter:=counter+1;			
			
			FETCH curELEMENTO INTO reg;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error versionando ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

	-- Realizamos la recodificacion de ELEMENTOS_PE
	BEGIN									

	   OPEN curELEMENTOPADRE;
	   FETCH curELEMENTOPADRE INTO regPadre;
	   WHILE curELEMENTOPADRE%FOUND LOOP
			codElemFromType:=null;
			-- Recorremos el Array para recuperar el codigo actual del padre
		  FOR counter IN tbl_recod.FIRST .. tbl_recod.LAST LOOP
				-- INSERT INTO AB39LGT00 (CODORIGEN, CODDESTINO) VALUES (tbl_recod(counter).CODELEMENTO_ORIG,tbl_recod(counter).CODELEMENTO_DEST );
				if (regPadre.CODELEMENTOPEPADRE = tbl_recod(counter).CODELEMENTO_ORIG) then
					codElemFromType := tbl_recod(counter).CODELEMENTO_DEST;
				end if;
				exit when regPadre.CODELEMENTOPEPADRE = tbl_recod(counter).CODELEMENTO_ORIG;
		  END LOOP;						

			UPDATE ELEMENTOS_PE  SET 
			CODELEMENTOPEPADRE = codElemFromType
			WHERE
			CODPLANE = regPadre.CODPLANE AND
			CODVERSIONPE = regPadre.CODVERSIONPE AND
			CODELEMENTOPE = regPadre.CODELEMENTOPE AND
			CODELEMENTOPEPADRE IS NOT NULL;
		
			FETCH curELEMENTOPADRE INTO regPadre;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error recalculando elementosPadre en ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

END PROC_VERSIONA_PLAN_ESTATEGICO;
/

/* COPIA DEL PLAN ESTRATEGICO  */

create or replace PROCEDURE AB39A.PROC_COPIA_PLAN_ESTATEGICO (
-- Codigo del plan estrategico origen
codigo_pe IN PLS_INTEGER,
-- Codigo del plan estrategico destino
codSigPlanEstrategico IN PLS_INTEGER
) AS

	-- Version a la que tendremos que hacer el versionado
	maxVersion INTEGER;	
	-- Posicion del recorrido de inserts
	counter INTEGER;		
	-- Valor recuperado del type table para recodificacion
	codElemFromType	INTEGER;
	-- Valor del elemento destino
	elemDest	INTEGER;  
	-- Cursor para recorrer los elementos
	CURSOR curELEMENTO IS SELECT CODELEMENTOPE, codigo_pe CODPLANE, 
		ELEMBASE, ORDEN, NIVEL, NOMBRE, 
		NOMBRECAS, HELBURU, HELBURUCAS,IDELEMENTO,  CODELEMENTOPEPADRE,
		HAS_EUS,HAS_ELEBI,AURRE_EUS,AURRE_ELEBI,AMAI_EUS,AMAI_ELEBI,OHARRAK,
    HAS_VALOR,AURRE_VALOR,AMAI_VALOR,TIENEELEBI,TIENEVALOR,TIENESINO,
    HAS_SINO,AURRE_SINO,AMAI_SINO,TIENEEUS
		FROM ELEMENTOS_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion ORDER BY CODELEMENTOPE;
    reg curELEMENTO%ROWTYPE;

	-- Cursor para actualizar los elementos padre
	CURSOR curELEMENTOPADRE IS SELECT CODPLANE, CODVERSIONPE, CODELEMENTOPE, CODELEMENTOPEPADRE
		FROM ELEMENTOS_PE
		WHERE
		CODPLANE = codSigPlanEstrategico AND
		CODVERSIONPE = 1 AND CODELEMENTOPEPADRE IS NOT NULL
    ORDER BY CODELEMENTOPEPADRE;
    regPadre curELEMENTOPADRE%ROWTYPE;
	
	TYPE RECORD_RECODIFICACION IS RECORD(
	  CODELEMENTO_ORIG NUMBER,
	  CODELEMENTO_DEST NUMBER);
	TYPE TBL_RECODIFICACION IS TABLE OF RECORD_RECODIFICACION INDEX BY BINARY_INTEGER;
	
	rec_recod RECORD_RECODIFICACION;
	tbl_recod TBL_RECODIFICACION;
	
BEGIN

	counter:=1;
	-- Recuperacion de la version maxima dado un plan estrategico
	SELECT DISTINCT MAX(CODVERSION) VERSION INTO maxVersion FROM PLANES_ESTRATEGICOS WHERE CODPLANE = codigo_pe ; 

	-- Realizamos la copia del plan para la tabla de EJES_PE  
	BEGIN
		INSERT INTO EJES_PE (CODPLANE, ID_EJE, HELBURU, HELBURUCAS, CODVERSIONPE)
		SELECT 
		codSigPlanEstrategico, ID_EJE, HELBURU, HELBURUCAS, 1
		FROM EJES_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion;
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error copiando EJES_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;
  
	-- Realizamos la copia del plan para la tabla de ELEMENTOS_PE  
	BEGIN									

	   OPEN curELEMENTO;
	   FETCH curELEMENTO INTO reg;
	   WHILE curELEMENTO%FOUND LOOP
     
			SELECT ELEMENTOS_PE_SEQ.NEXTVAL INTO ElemDest FROM DUAL;
     
			INSERT INTO ELEMENTOS_PE 
			(CODELEMENTOPE, CODPLANE, CODVERSIONPE, ELEMBASE, 
			ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
			HELBURU, HELBURUCAS,  CODELEMENTOPEPADRE,
			HAS_EUS,HAS_ELEBI,AURRE_EUS,AURRE_ELEBI,AMAI_EUS,AMAI_ELEBI,OHARRAK,
      HAS_VALOR,AURRE_VALOR,AMAI_VALOR,TIENEELEBI,TIENEVALOR,TIENESINO,
      HAS_SINO,AURRE_SINO,AMAI_SINO,TIENEEUS
      ) VALUES
			(ElemDest,codSigPlanEstrategico,1,reg.ELEMBASE,
			reg.ORDEN,reg.NIVEL,reg.NOMBRE,reg.NOMBRECAS,reg.IDELEMENTO,
			reg.HELBURU,reg.HELBURUCAS,reg.CODELEMENTOPEPADRE,
			reg.HAS_EUS,reg.HAS_ELEBI,reg.AURRE_EUS,reg.AURRE_ELEBI,reg.AMAI_EUS,reg.AMAI_ELEBI,reg.OHARRAK,
      reg.HAS_VALOR,reg.AURRE_VALOR,reg.AMAI_VALOR,reg.TIENEELEBI,reg.TIENEVALOR,reg.TIENESINO,
      reg.HAS_SINO,reg.AURRE_SINO,reg.AMAI_SINO,reg.TIENEEUS      
      );
			
			-- Guardamos los datos para la posterior recodificacion
			rec_recod.CODELEMENTO_ORIG := reg.CODELEMENTOPE;
			rec_recod.CODELEMENTO_DEST := ElemDest;
			
			-- INSERT INTO AB39LGT00 (CODORIGEN, CODDESTINO) VALUES (rec_recod.CODELEMENTO_ORIG,rec_recod.CODELEMENTO_DEST );
      
			tbl_recod(counter) := rec_recod;
			
			counter:=counter+1;			
			
			FETCH curELEMENTO INTO reg;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error copiando ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

	-- Realizamos la recodificacion de ELEMENTOS_PE
	BEGIN									

	   OPEN curELEMENTOPADRE;
	   FETCH curELEMENTOPADRE INTO regPadre;
	   WHILE curELEMENTOPADRE%FOUND LOOP
			codElemFromType:=null;
			-- Recorremos el Array para recuperar el codigo actual del padre
		  FOR counter IN tbl_recod.FIRST .. tbl_recod.LAST LOOP
				if (regPadre.CODELEMENTOPEPADRE = tbl_recod(counter).CODELEMENTO_ORIG) then
					codElemFromType := tbl_recod(counter).CODELEMENTO_DEST;
				end if;
				exit when regPadre.CODELEMENTOPEPADRE = tbl_recod(counter).CODELEMENTO_ORIG or
                  regPadre.CODELEMENTOPEPADRE = NULL;
		  END LOOP;						

			UPDATE ELEMENTOS_PE  SET 
			CODELEMENTOPEPADRE = codElemFromType
			WHERE
			CODPLANE = codSigPlanEstrategico AND
			CODVERSIONPE = 1 AND
			CODELEMENTOPE = regPadre.CODELEMENTOPE;
		
			FETCH curELEMENTOPADRE INTO regPadre;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN

		DBMS_OUTPUT.put_line ( 'Error recalculando elementosPadre en ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

END PROC_COPIA_PLAN_ESTATEGICO;
/

/* GENERACION DEL PLAN DE GESTION  */

create or replace PROCEDURE AB39A.PROC_GENERA_PLAN_GESTION (
-- Codigo del plan de gestion
codigo_pg IN PLS_INTEGER
) AS

	-- Codigo del plan estrategico
	codigo_pe INTEGER;	
	-- Resultado de la UPDATE de los elementos padre de los ELEMENTOS_PE
	blnELEMENTOS_PG BOOLEAN;
	-- Version a la que tendremos que hacer el versionado
	maxVersion INTEGER;	

BEGIN

	blnELEMENTOS_PG:=false;

	-- Recuperacion de la version maxima dado un plan estrategico
	SELECT DISTINCT CODPLANE INTO codigo_pe FROM PLANES_GESTION WHERE CODPLANG = codigo_pg ;
  	-- Recuperacion de la version maxima dado un plan estrategico
	SELECT DISTINCT MAX(CODVERSION) VERSION INTO maxVersion FROM PLANES_ESTRATEGICOS WHERE CODPLANE = codigo_pe;
	
	-- Realizamos la copia del plan estrategico en el plan de gestion
	-- para la tabla de ELEMENTOS_PG
	BEGIN
		INSERT INTO ELEMENTOS_PG 
			(CODELEMPG, CODPLANG, ELEMBASE, 
			ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
			CODELEMENTOPE,CODELEMPGPADRE)
		SELECT 
		ELEMENTOS_PG_SEQ.NEXTVAL, codigo_pg, ELEMBASE,
		ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
		CODELEMENTOPE, NULL CODELEMENTOPEPADRE
		FROM ELEMENTOS_PE
		WHERE
		CODPLANE = codigo_pe AND
		CODVERSIONPE = maxVersion AND
		NIVEL <= 3;
		blnELEMENTOS_PG:=true;
    EXCEPTION
		WHEN OTHERS THEN
		blnELEMENTOS_PG:=false;
		DBMS_OUTPUT.put_line ( 'Error generando ELEMENTOS_PG: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;
	
	-- Si el volcado de elementos PE ha ido bien, recodificamos los padres
	if (blnELEMENTOS_PG=true) then
	
		BEGIN
			UPDATE ELEMENTOS_PG EPG SET EPG.CODELEMPGPADRE = (SELECT ELE_DEST.CODELEMPG
          FROM ELEMENTOS_PE ELE, ELEMENTOS_PG ELE_ORIG, ELEMENTOS_PG ELE_DEST
        WHERE 
         -- El codigo del elemento_pg origen es el que estamos recorriendo desde el exterior
         ELE_ORIG.CODELEMPG = EPG.CODELEMPG AND   
         ELE_ORIG.CODPLANG = EPG.CODPLANG AND 
         -- Los elementos de origen_pg y destino_pg pertenecen al mismo plan
         ELE_ORIG.CODPLANG = ELE_DEST.CODPLANG AND 
         -- Cruzamos el codigo de elementope en elemento_pg de origen con el codigo de elemento
         ELE_ORIG.CODELEMENTOPE = ELE.CODELEMENTOPE AND
         -- Cruzamos el ID de elemento padre de elemento 
         -- con el ID de elemento_pe destino para recuperar su nueva codificacion
         ELE.CODELEMENTOPEPADRE = ELE_DEST.CODELEMENTOPE)
			WHERE
			   EPG.CODPLANG = codigo_pg;				
		EXCEPTION
			WHEN OTHERS THEN
			DBMS_OUTPUT.put_line ( 'Error generaldo los codigos padre en ELEMENTOS_PG: '|| DBMS_UTILITY.format_error_stack ());
			RAISE;
		END;
	
	end if;		

	-- Volcado de los ELEMENTOS de nivel 4 desde la tabla de ELEMENTOS
	-- el padre se establece en la propia INSERT/SELECT recuperandolo
	-- desde la tabla ELEMENTOS_PG
	BEGIN
		INSERT INTO ELEMENTOS_PG 
			(CODELEMPG, CODPLANG, ELEMBASE, 
			ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
			CODELEMENTOPE,CODELEMPGPADRE)
			SELECT 
			ELEMENTOS_PG_SEQ.NEXTVAL, codigo_pg, 0,
			ELEMENTO.ORDEN, ELEMENTO.NIVEL, ELEMENTO.NOMBRE, ELEMENTO.NOMBRECAS, ELEMENTO.ID_ELEMENTO, 
			null, (
				-- Recuperacion del correspondiente padre desde ELEMENTOS_PG 
				-- con el IDELEMENTO original
				SELECT CODELEMPG FROM 
				ELEMENTOS_PG 
				WHERE ELEMENTOS_PG.CODPLANG = codigo_pg AND 
				ELEMENTOS_PG.IDELEMENTO = ELEMENTO.ID_ELEMENTOPADRE
			)
			FROM 
			(SELECT MAX(PE.CODVERSION) CODVERSION, PE.CODPLANE CODPLANE 
                FROM PLANES_ESTRATEGICOS PE WHERE CODPLANE=codigo_pe
                GROUP BY CODPLANE) PLANES,
			ELEMENTO, EJE, ENTIDADES, PLANES_ESTRATEGICOS
			WHERE
			--PLANES_ESTRATEGICOS.CODPLANE = codigo_pe AND
			PLANES_ESTRATEGICOS.CODPLANE=PLANES.CODPLANE 
			AND PLANES_ESTRATEGICOS.CODVERSION=PLANES.CODVERSION
			AND PLANES_ESTRATEGICOS.CODENTIDAD = ENTIDADES.CODENTIDAD
			AND ENTIDADES.TIPO_ENTIDAD = EJE.ID_TIPOORGANIZACION 
			AND	ELEMENTO.NIVEL = 4 
			AND	ELEMENTO.ID_EJE = EJE.ID_EJE;

    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error generando ELEMENTOS_PG: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END;	

END PROC_GENERA_PLAN_GESTION;
/

/* COPIA DEL PLAN DE GESTION  */

create or replace PROCEDURE AB39A.PROC_COPIA_PLAN_GESTION (
-- Codigo del plan de gestion origen
codigo_pg_orig IN PLS_INTEGER,
-- Codigo del plan de gestion destino
codigo_pg_dest IN PLS_INTEGER
) AS

	-- Posicion del recorrido de inserts
	counter INTEGER;		
	-- Valor recuperado del type table para recodificacion
	codElemFromType	INTEGER;
	-- Valor del elemento destino
	elemDest	INTEGER;
	-- id accion nueva
	codAccionNueva INTEGER;
	-- Cursor para recorrer los elementos
	CURSOR curELEMENTO IS SELECT CODELEMPG, CODPLANG, 
		ELEMBASE, ORDEN, NIVEL, NOMBRE, 
		NOMBRECAS, IDELEMENTO, CODELEMENTOPE, CODELEMPGPADRE		
		FROM ELEMENTOS_PG
		WHERE
		CODPLANG = codigo_pg_orig 
    ORDER BY CODELEMPG;
    reg curELEMENTO%ROWTYPE;

	-- Cursor para actualizar los elementos padre
	CURSOR curELEMENTOPADRE IS SELECT CODPLANG,  CODELEMPG, CODELEMPGPADRE
		FROM ELEMENTOS_PG
		WHERE
		CODPLANG = codigo_pg_dest AND
		CODELEMPGPADRE IS NOT NULL
    ORDER BY CODELEMPGPADRE;
    regPadre curELEMENTOPADRE%ROWTYPE;
	
	CURSOR curACCIONES (codElemento NUMBER) IS SELECT CODACCIONPG, CODELEMPG, NUMRECEPTORES, 
		NUMRECEPH, NUMRECEPM, CODSITUACIONFINAL, 
		ORDEN, ELEMBASE, NOMBRE, 
		NOMBRECAS, NUEVAFECHAPREV, IDACCION, 
		RESPONSABLE, FECHAPREV, CODTIPORECEPTOR, 
		RAZON_APLAZA, MOTIVO_CANCELA, DESCRIPCION, 
		RAZON_APLAZA_CAS, MOTIVO_CANCELA_CAS, DESCRIPCIONCAS, 
		OBSERVACIONES, OBSERVACIONESCAS
		FROM ACCIONES_PG WHERE CODELEMPG=codElemento;
	regAccion curACCIONES%ROWTYPE;
	
	TYPE RECORD_RECODIFICACION IS RECORD(
	  CODELEMENTO_ORIG NUMBER,
	  CODELEMENTO_DEST NUMBER);
	TYPE TBL_RECODIFICACION IS TABLE OF RECORD_RECODIFICACION INDEX BY BINARY_INTEGER;
	
	rec_recod RECORD_RECODIFICACION;
	tbl_recod TBL_RECODIFICACION;
	
BEGIN

	counter:=1;
  
	-- Realizamos la copia del plan para la tabla de ELEMENTOS_PG  
	BEGIN									

	   OPEN curELEMENTO;
	   FETCH curELEMENTO INTO reg;
	   WHILE curELEMENTO%FOUND LOOP
     
			SELECT ELEMENTOS_PG_SEQ.NEXTVAL INTO ElemDest FROM DUAL;
     
			INSERT INTO ELEMENTOS_PG 
			(CODELEMPG, CODPLANG, ELEMBASE, 
			ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
			CODELEMENTOPE, CODELEMPGPADRE)
			VALUES
				(ElemDest,codigo_pg_dest,reg.ELEMBASE,
				reg.ORDEN, reg.NIVEL, reg.NOMBRE,reg.NOMBRECAS,reg.IDELEMENTO,
				reg.CODELEMENTOPE, reg.CODELEMPGPADRE);
			
			-- Guardamos los datos para la posterior recodificacion
			rec_recod.CODELEMENTO_ORIG := reg.CODELEMPG;
			rec_recod.CODELEMENTO_DEST := ElemDest;
			
			tbl_recod(counter) := rec_recod;
			
			counter:=counter+1;
			
			OPEN curACCIONES(reg.CODELEMPG);
			FETCH curACCIONES INTO regAccion;
			WHILE curACCIONES%FOUND LOOP
				SELECT ACCIONES_PG_SEQ.NEXTVAL INTO codAccionNueva FROM DUAL;
				
				INSERT INTO ACCIONES_PG (CODACCIONPG, CODELEMPG, NUMRECEPTORES, 
				   NUMRECEPH, NUMRECEPM, CODSITUACIONFINAL, 
				   ORDEN, ELEMBASE, NOMBRE, 
				   NOMBRECAS, NUEVAFECHAPREV, IDACCION, 
				   RESPONSABLE, FECHAPREV, CODTIPORECEPTOR, 
				   RAZON_APLAZA, MOTIVO_CANCELA, DESCRIPCION, 
				   RAZON_APLAZA_CAS, MOTIVO_CANCELA_CAS, DESCRIPCIONCAS, 
				   OBSERVACIONES, OBSERVACIONESCAS)
				   VALUES (codAccionNueva,ElemDest,regAccion.NUMRECEPTORES, regAccion.NUMRECEPH, regAccion.NUMRECEPM, regAccion.CODSITUACIONFINAL, regAccion.ORDEN, 
						regAccion.ELEMBASE, regAccion.NOMBRE, regAccion.NOMBRECAS, regAccion.NUEVAFECHAPREV, regAccion.IDACCION, 
						regAccion.RESPONSABLE, regAccion.FECHAPREV, regAccion.CODTIPORECEPTOR, regAccion.RAZON_APLAZA, regAccion.MOTIVO_CANCELA, 
						regAccion.DESCRIPCION, regAccion.RAZON_APLAZA_CAS, regAccion.MOTIVO_CANCELA_CAS, regAccion.DESCRIPCIONCAS, 
						regAccion.OBSERVACIONES, regAccion.OBSERVACIONESCAS);
				
				FETCH curACCIONES INTO regAccion;
			END LOOP;
			CLOSE curACCIONES;
			
			FETCH curELEMENTO INTO reg;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN
		DBMS_OUTPUT.put_line ( 'Error copiando ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

	-- Realizamos la recodificacion de ELEMENTOS_PE
	BEGIN									

	   OPEN curELEMENTOPADRE;
	   FETCH curELEMENTOPADRE INTO regPadre;
	   WHILE curELEMENTOPADRE%FOUND LOOP
			codElemFromType:=null;
			-- Recorremos el Array para recuperar el codigo actual del padre
		  FOR counter IN tbl_recod.FIRST .. tbl_recod.LAST LOOP
				if (regPadre.CODELEMPGPADRE = tbl_recod(counter).CODELEMENTO_ORIG) then
					codElemFromType := tbl_recod(counter).CODELEMENTO_DEST;
				end if;
				exit when regPadre.CODELEMPGPADRE = tbl_recod(counter).CODELEMENTO_ORIG or
                  regPadre.CODELEMPGPADRE = NULL;
		  END LOOP;						

			UPDATE ELEMENTOS_PG  SET 
			CODELEMPGPADRE = codElemFromType
			WHERE
			CODPLANG = codigo_pg_dest AND
			CODELEMPG = regPadre.CODELEMPG;
		
			FETCH curELEMENTOPADRE INTO regPadre;
	   END LOOP;		
	   	
    EXCEPTION
		WHEN OTHERS THEN

		DBMS_OUTPUT.put_line ( 'Error recalculando elementosPadre en ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
		RAISE;
	END; 

END PROC_COPIA_PLAN_GESTION;
/

/* TRASLADO DE ACCIONES REALIZADAS EN ELEMENTOS_PE */

create or replace PROCEDURE AB39A.PROC_TRASACCIONPE_PLAN_GESTION (
-- Accion que se realiza sobre ELEMENTOS_PE
-- 0-Baja, 1-Alta, 2-Modificacion
accion IN PLS_INTEGER,
-- Codigo del elemento con origen en ELEMENTOS_PE
cod_elem_pe IN PLS_INTEGER

) AS

  -- Variables para el almacenamiento de los datos del ELEMENTO_PE
  elembase INTEGER;
  orden  INTEGER;
  nivel  INTEGER;
  nombre  VARCHAR2(250);
  nombrecas VARCHAR2(250);
  ideelemento INTEGER;
  
	-- Cursor para recuperar los codigos de los elementos_pg padres y 
  -- los codigos de los planes a los que se les realizara la insert
  -- del elemento procedente de ELEMENTOS_PE.
	CURSOR curELEMENTO IS SELECT DISTINCT 
    ELEMENTOS_PG.CODPLANG CODPLANG, ELEMENTOS_PG.CODELEMPG CODELEMPGPADRE, 
    ELEMENTOS_PG.CODELEMENTOPE CODELEMENTOPE
    FROM
      ELEMENTOS_PE HIJO_PE,  ELEMENTOS_PG
    WHERE 
    -- Elemento sobre el que cae la accion en origen
    HIJO_PE.CODELEMENTOPE = cod_elem_pe AND
    -- Cruce entre el padre de ELEMENTOS_PE y el elemento origen de ELEMENTOS_PG
    -- para recuperar su codificacion
    HIJO_PE.CODELEMENTOPEPADRE = ELEMENTOS_PG.CODELEMENTOPE;
    reg curELEMENTO%ROWTYPE;
	
BEGIN


  -- #################################
	-- BAJA de un registro (Accion = 0)
  IF accion = 0 THEN

    BEGIN									
    
      -- Borrar las acciones de ese elemento en los planes de gestión
      DELETE FROM ACCIONES_PG WHERE 
      CODELEMPG IN (SELECT CODELEMPG FROM ELEMENTOS_PG WHERE CODELEMENTOPE = cod_elem_pe);
      
      -- Borrar las acciones de sus hijos de ese elemento en los planes de gestión
      DELETE FROM ACCIONES_PG WHERE 
      CODELEMPG IN (
        SELECT CODELEMPG FROM ELEMENTOS_PG WHERE 
          CODELEMPGPADRE IN (
            SELECT CODELEMPG FROM ELEMENTOS_PG WHERE CODELEMENTOPE = cod_elem_pe
          )
        );
        
      -- Borrar hijos del plan de gestion
      DELETE FROM ELEMENTOS_PG WHERE 
      CODELEMPGPADRE IN (
        SELECT CODELEMPG FROM ELEMENTOS_PG WHERE CODELEMENTOPE = cod_elem_pe
        );
      
      -- Borrar elemento de plan de gestion
      DELETE FROM ELEMENTOS_PG WHERE CODELEMENTOPE = cod_elem_pe;
      
      -- Borrar elemento de plan estrategico	
      DELETE FROM ELEMENTOS_PE WHERE CODELEMENTOPE = cod_elem_pe;
              
      EXCEPTION
      WHEN OTHERS THEN
      DBMS_OUTPUT.put_line ( 'Error trasladando una baja desde ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
      RAISE;
    END; 
  -- Fin de funcionalidad de BAJA de un registro  
  -- #################################
  -- ALTA de un registro (Accion = 1)
  ELSIF accion = 1 THEN
	
    BEGIN									
    
     SELECT 
        ELEMBASE, ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO 
     into 
        elembase, orden, nivel, nombre, nombrecas, ideelemento 
     FROM 
     ELEMENTOS_PE WHERE CODELEMENTOPE = cod_elem_pe;
     
	   OPEN curELEMENTO;
	   FETCH curELEMENTO INTO reg;
	   WHILE curELEMENTO%FOUND LOOP     
       
        INSERT INTO ELEMENTOS_PG 
        (CODELEMPG, CODPLANG, ELEMBASE, 
        ORDEN, NIVEL, NOMBRE, NOMBRECAS, IDELEMENTO,
        CODELEMENTOPE, CODELEMPGPADRE)
        VALUES
        (ELEMENTOS_PG_SEQ.NEXTVAL, reg.CODPLANG ,elembase,
        orden, nivel, nombre,nombrecas,ideelemento,
        cod_elem_pe, reg.CODELEMPGPADRE);
        
        FETCH curELEMENTO INTO reg;
     END LOOP;            
        
      EXCEPTION
      WHEN OTHERS THEN
      DBMS_OUTPUT.put_line ( 'Error trasladando un alta desde ELEMENTOS_PE: '|| 
                            DBMS_UTILITY.format_error_stack ());
      RAISE;
    END; 
  -- Fin de funcionalidad de ALTA de un registro  
  -- #########################################
  -- Modificacion de un registro (Accion = 2)
  ELSIF accion = 2 THEN
    
    BEGIN									
      
      -- Actualizar los campos NOMBRE y NOMBRECAS en funcion del contenido del ELEMENTO_PE
      UPDATE ELEMENTOS_PG SET 
      NOMBRE = (SELECT NOMBRE FROM ELEMENTOS_PE WHERE CODELEMENTOPE = cod_elem_pe),
      NOMBRECAS = (SELECT NOMBREcas FROM ELEMENTOS_PE WHERE CODELEMENTOPE = cod_elem_pe)
      WHERE
      CODELEMENTOPE = cod_elem_pe;
        
      EXCEPTION
      WHEN OTHERS THEN
      DBMS_OUTPUT.put_line ( 'Error trasladando una modificacion desde ELEMENTOS_PE: '|| DBMS_UTILITY.format_error_stack ());
      RAISE;
    END; 
	END IF;

END PROC_TRASACCIONPE_PLAN_GESTION;
/

DROP SYNONYM AB39A.GENERA_PLAN_ESTATEGICO;
DROP SYNONYM AB39A.VERSIONA_PLAN_ESTATEGICO;
DROP SYNONYM AB39A.COPIA_PLAN_ESTATEGICO;
DROP SYNONYM AB39A.GENERA_PLAN_GESTION;
DROP SYNONYM AB39A.COPIA_PLAN_GESTION;
DROP SYNONYM AB39A.TRASLADA_ACCIONPE_PLAN_GESTION;

CREATE SYNONYM AB39A.GENERA_PLAN_ESTATEGICO FOR AB39A.PROC_GENERA_PLAN_ESTATEGICO;
CREATE SYNONYM AB39A.VERSIONA_PLAN_ESTATEGICO FOR AB39A.PROC_VERSIONA_PLAN_ESTATEGICO;
CREATE SYNONYM AB39A.COPIA_PLAN_ESTATEGICO FOR AB39A.PROC_COPIA_PLAN_ESTATEGICO;
CREATE SYNONYM AB39A.GENERA_PLAN_GESTION FOR AB39A.PROC_GENERA_PLAN_GESTION;
CREATE SYNONYM AB39A.COPIA_PLAN_GESTION FOR AB39A.PROC_COPIA_PLAN_GESTION;
CREATE SYNONYM AB39A.TRASLADA_ACCIONPE_PLAN_GESTION FOR AB39A.PROC_TRASACCIONPE_PLAN_GESTION;

COMMIT;
EXIT;



