{"id":14324,"date":"2023-03-10T15:21:32","date_gmt":"2023-03-10T21:21:32","guid":{"rendered":"http:\/\/201.237.206.56\/Sitios\/ugit.siua.ac.cr\/?p=14324"},"modified":"2023-03-22T16:34:20","modified_gmt":"2023-03-22T22:34:20","slug":"sigesa-crear-proceso-de-envio-de-correos","status":"publish","type":"post","link":"https:\/\/sada.services\/?p=14324","title":{"rendered":"SIGESA: Crear Proceso de Envio de Correos"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Tarea:<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>El correo debe ser remitido al rol digitador y aprobador<\/li>\n\n\n\n<li>El correo debe venir con copia a los analistas de PPO<\/li>\n\n\n\n<li>El correo debe indicar la fecha de inicio y la fecha de fin de la etapa de planificaci\u00f3n<\/li>\n\n\n\n<li>El correo debe indicar:\n<ul class=\"wp-block-list\">\n<li>Lista de c\u00f3digos presupuestarios vinculados a metas operativas en la etapa de formulaci\u00f3n sin presupuesto asignado.<\/li>\n\n\n\n<li>Lista de c\u00f3digos presupuestarios en ejecuci\u00f3n que tienen dinero y que no han sido incluidos en la formulaci\u00f3n operativa.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Paso01: Crear Proceso<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Lo primero que vamos hacer es crear el archivo que va manejar el proceso<\/li>\n\n\n\n<li>Para esto <\/li>\n\n\n\n<li>Debemos ubicarnos en la ruta\n<ul class=\"wp-block-list\">\n<li>Proyecto-&gt; Service-&gt;src-&gt;main-&gt;resources-&gt;META-INF-&gt;spring<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img fetchpriority=\"high\" decoding=\"async\" width=\"431\" height=\"404\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_001.png\" alt=\"\" class=\"wp-image-14327\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_001.png 431w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_001-300x281.png 300w\" sizes=\"(max-width: 431px) 100vw, 431px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Aqu\u00ed se encuentran todos los archivos que manejan procesos<\/li>\n\n\n\n<li>Podr\u00edamos crear uno nuevo o copiar uno y modificarlo<\/li>\n\n\n\n<li>Creamos el archivo<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>applicationContext-procesoPPIAvisoInicioFinalizacionEtapasPPOJob.xml<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>El contenido basico es:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\n       xmlns:batch=\"http:\/\/www.springframework.org\/schema\/batch\"\n       xmlns:aop=\"http:\/\/www.springframework.org\/schema\/aop\"\n       xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\n       xmlns:task=\"http:\/\/www.springframework.org\/schema\/task\"\n       xmlns:p=\"http:\/\/www.springframework.org\/schema\/p\"\n       xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n       xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/batch http:\/\/www.springframework.org\/schema\/batch\/spring-batch.xsd\n        http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd \n\thttp:\/\/www.springframework.org\/schema\/aop http:\/\/www.springframework.org\/schema\/aop\/spring-aop.xsd\n        http:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context.xsd \n        http:\/\/www.springframework.org\/schema\/task http:\/\/www.springframework.org\/schema\/task\/spring-task.xsd\n         http:&#47;&#47;www.springframework.org\/schema\/context\n         http:\/\/www.springframework.org\/schema\/context\/spring-context.xsd\n         http:\/\/www.springframework.org\/schema\/aop http:\/\/www.springframework.org\/schema\/aop\/spring-aop-2.5.xsd\"&gt;\n\n\n&lt;\/beans&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Paso1.1 Relaci\u00f3n SIGESA -&gt; Proceso<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora debemos agregarle el c\u00f3digo necesario para crear un listener que relaciona \n<ul class=\"wp-block-list\">\n<li>procesoPPIAvisoInicioFinalizacionEtapasPPOJob<\/li>\n\n\n\n<li>Con\n<ul class=\"wp-block-list\">\n<li>procesoPPIAvisoInicioFinalizacionEtapasPPO<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;batch:job id=\"procesoPPIAvisoInicioFinalizacionEtapasPPOJob\"&gt;\n        &lt;batch:step id=\"simpleTaskletStepProcesoPPIAvisoInicioFinalizacionEtapasPPOJob\"&gt;\n            &lt;batch:tasklet ref=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" \/&gt;\n            &lt;batch:listeners&gt;\n                &lt;batch:listener ref=\"batchJobStepListener\" \/&gt;\n            &lt;\/batch:listeners&gt;\n        &lt;\/batch:step&gt;\n    &lt;\/batch:job&gt;<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NOTA:<\/li>\n\n\n\n<li>Notar que los nombres son diferentes<\/li>\n\n\n\n<li>procesoPPIFinalizacionEtapasPPOJob: \n<ul class=\"wp-block-list\">\n<li>este referecia al nombre del proceso en la interfaz de SIGESA<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;batch:job id=\"procesoPPIAvisoInicioFinalizacionEtapasPPOJob\"&gt;<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>procesoPPIFinalizacionEtapasPPO:\n<ul class=\"wp-block-list\">\n<li>Y este se refiere al bean que contiene la informaci\u00f3n de servicio que debe ejecutar<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;batch:tasklet ref=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" \/&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Paso 1.2: relaci\u00f3n Proceso -&gt; Servicio<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora debemos agregarle el bean que contiene la informaci\u00f3n de cual servicio debe ejecutar al invocarse el proceso<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"838\" height=\"332\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_027.png\" alt=\"\" class=\"wp-image-14361\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_027.png 838w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_027-300x119.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_027-768x304.png 768w\" sizes=\"(max-width: 838px) 100vw, 838px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Y ademas va establecer donde esta el servicio y el m\u00e9todo que va a ejecutar<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" width=\"1024\" height=\"145\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_028-1024x145.png\" alt=\"\" class=\"wp-image-14362\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_028-1024x145.png 1024w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_028-300x43.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_028-768x109.png 768w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_028.png 1086w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Y tambien va establecer cuales parametros se van a pasar desde la interfaz de SIGESA \n<ul class=\"wp-block-list\">\n<li>#{stepExecution.id}: siempre se pasa es el id del proceso<\/li>\n\n\n\n<li>#{jobParameters[&#8216;etapaPlan&#8217;]} y este es uno adicional que se le debe pasar para el funcionamiento del proceso<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"850\" height=\"277\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_029.png\" alt=\"\" class=\"wp-image-14363\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_029.png 850w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_029-300x98.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_029-768x250.png 768w\" sizes=\"(max-width: 850px) 100vw, 850px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Codigo:<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;bean id=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" class=\"org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter\" scope=\"step\"&gt;\n        &lt;property name=\"targetObject\" ref=\"planOperativoServiceImpl\"  \/&gt;\n        &lt;property name=\"targetMethod\" value=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" \/&gt;\n        &lt;property name=\"arguments\"&gt;\n            &lt;list&gt;           \n                &lt;value&gt;#{stepExecution.id}&lt;\/value&gt;\n                &lt;value&gt;#{jobParameters&#91;'etapaPlan']}&lt;\/value&gt;\n            &lt;\/list&gt;\n        &lt;\/property&gt;\n    &lt;\/bean&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Paso 1.3: lanzador del proceso<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Adem\u00e1s es necesario crear el lanzador del proceso para esto agregamos<\/li>\n\n\n\n<li>NOTAR que es con JOB <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>procesoPPIAvisoInicioFinalizacionEtapasPPO<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Agregamos<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;bean id=\"procesoPPIAvisoInicioFinEtapasPPOJobLauncher\" class=\"cr.ac.una.cgi.sdkuna.service.BatchJobLauncherService\" scope=\"prototype\"&gt;\n        &lt;property name=\"jobLauncher\" ref=\"jobLauncher\"&gt;&lt;\/property&gt;\n        &lt;property name=\"job\" ref=\"procesoPPIAvisoInicioFinEtapasPPOJob\"&gt;&lt;\/property&gt;\n    &lt;\/bean&gt;<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Paso 1.4: Resultado Final<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Resultado<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?>\n&lt;beans xmlns=\"http:\/\/www.springframework.org\/schema\/beans\"\n       xmlns:batch=\"http:\/\/www.springframework.org\/schema\/batch\"\n       xmlns:aop=\"http:\/\/www.springframework.org\/schema\/aop\"\n       xmlns:context=\"http:\/\/www.springframework.org\/schema\/context\"\n       xmlns:task=\"http:\/\/www.springframework.org\/schema\/task\"\n       xmlns:p=\"http:\/\/www.springframework.org\/schema\/p\"\n       xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n       xsi:schemaLocation=\"http:\/\/www.springframework.org\/schema\/batch http:\/\/www.springframework.org\/schema\/batch\/spring-batch.xsd\n        http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans.xsd \n\thttp:\/\/www.springframework.org\/schema\/aop http:\/\/www.springframework.org\/schema\/aop\/spring-aop.xsd\n        http:\/\/www.springframework.org\/schema\/context http:\/\/www.springframework.org\/schema\/context\/spring-context.xsd \n        http:\/\/www.springframework.org\/schema\/task http:\/\/www.springframework.org\/schema\/task\/spring-task.xsd\n         http:&#47;&#47;www.springframework.org\/schema\/context\n         http:\/\/www.springframework.org\/schema\/context\/spring-context.xsd\n         http:\/\/www.springframework.org\/schema\/aop http:\/\/www.springframework.org\/schema\/aop\/spring-aop-2.5.xsd\">\n\n \n\n    &lt;batch:job id=\"procesoPPIAvisoInicioFinalizacionEtapasPPOJob\">\n        &lt;batch:step id=\"simpleTaskletStepProcesoPPIAvisoInicioFinalizacionEtapasPPOJob\">\n            &lt;batch:tasklet ref=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" \/>\n            &lt;batch:listeners>\n                &lt;batch:listener ref=\"batchJobStepListener\" \/>\n            &lt;\/batch:listeners>\n        &lt;\/batch:step>\n    &lt;\/batch:job>\n    \n    \n    \n    &lt;bean id=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" class=\"org.springframework.batch.core.step.tasklet.MethodInvokingTaskletAdapter\" scope=\"step\">\n        &lt;property name=\"targetObject\" ref=\"planOperativoServiceImpl\"  \/>\n        &lt;property name=\"targetMethod\" value=\"procesoPPIAvisoInicioFinalizacionEtapasPPO\" \/>\n        &lt;property name=\"arguments\">\n            &lt;list>           \n                &lt;value>#{stepExecution.id}&lt;\/value>\n                &lt;value>#{jobParameters&#91;'etapaPlan']}&lt;\/value>\n            &lt;\/list>\n        &lt;\/property>\n    &lt;\/bean>\n  \n  \n\n    &lt;bean id=\"procesoPPIAvisoInicioFinEtapasPPOJobLauncher\" class=\"cr.ac.una.cgi.sdkuna.service.BatchJobLauncherService\" scope=\"prototype\">\n        &lt;property name=\"jobLauncher\" ref=\"jobLauncher\">&lt;\/property>\n        &lt;property name=\"job\" ref=\"procesoPPIAvisoInicioFinEtapasPPOJob\">&lt;\/property>\n    &lt;\/bean>\n    \n&lt;\/beans><\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Paso2: reportar el proceso<\/h2>\n\n\n\n<p>Paso 2.1: Reportar proceso<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora debemos reportar el proceso dentro de SIGESA<\/li>\n\n\n\n<li>Para esto ingresamos a SIGESA -&gt; SAS  &#8211; Seguridad y administraci\u00f3n -&gt; SAS &#8211; Mantenimiento -&gt; Lista de Procesos<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"267\" height=\"186\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_006.png\" alt=\"\" class=\"wp-image-14337\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Le damos agregar <\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"264\" height=\"166\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_011.png\" alt=\"\" class=\"wp-image-14344\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Le agregamos los datos:\n<ul class=\"wp-block-list\">\n<li>Nombre del trabajo: procesoPPIAvisoInicioFinalizacionEtapasPPOJob<\/li>\n\n\n\n<li>Descripci\u00f3n: Proceso que envi\u00e1 un correo a los usuarios con rol PPO Analista, PPO Aprobador Unidad Ejecutora, Aprobador Unidad Integradora y PPO Digitador para avisarles el inicio o finalizaci\u00f3n de una etapa y errores en los c\u00f3digos presupuestarios.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"225\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_012-1024x225.png\" alt=\"\" class=\"wp-image-14345\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_012-1024x225.png 1024w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_012-300x66.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_012-768x169.png 768w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_012-1536x338.png 1536w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_012.png 1583w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora le agregamos los parametros<\/li>\n\n\n\n<li>EtapaPlan:<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"827\" height=\"605\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_013.png\" alt=\"\" class=\"wp-image-14346\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_013.png 827w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_013-300x219.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_013-768x562.png 768w\" sizes=\"(max-width: 827px) 100vw, 827px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>datos:\n<ul class=\"wp-block-list\">\n<li>Parametro: etapaPlan<\/li>\n\n\n\n<li>Descripci\u00f3n: Etapa de Planificaci\u00f3n<\/li>\n\n\n\n<li>Tipo parametro: objeto<\/li>\n\n\n\n<li>Requerido: true<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"545\" height=\"448\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_014.png\" alt=\"\" class=\"wp-image-14347\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_014.png 545w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_014-300x247.png 300w\" sizes=\"(max-width: 545px) 100vw, 545px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Le damos agregar<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"911\" height=\"507\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_015.png\" alt=\"\" class=\"wp-image-14348\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_015.png 911w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_015-300x167.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_015-768x427.png 768w\" sizes=\"(max-width: 911px) 100vw, 911px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Regresamos y le damos guardar y retornamos a configurar el parametro<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"486\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_016-1024x486.png\" alt=\"\" class=\"wp-image-14349\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_016-1024x486.png 1024w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_016-300x142.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_016-768x364.png 768w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_016-1536x729.png 1536w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_016.png 1602w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>le damos en propiedades<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"660\" height=\"439\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_017.png\" alt=\"\" class=\"wp-image-14350\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_017.png 660w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_017-300x200.png 300w\" sizes=\"(max-width: 660px) 100vw, 660px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Datos:\n<ul class=\"wp-block-list\">\n<li>Clase Mapeada: cr.ac.una.cgi.sigesa.ppi.ppo.domain.EtapaPlan<\/li>\n\n\n\n<li>Propiedad objeto: nombre<\/li>\n\n\n\n<li>T\u00edtulo del LOV Bean: etapa_list_form_title<\/li>\n\n\n\n<li>Nombre bean: EtapaPlanBean<\/li>\n\n\n\n<li>Servicio clase: EtapaPlanService\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"622\" height=\"729\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_018.png\" alt=\"\" class=\"wp-image-14351\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_018.png 622w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_018-256x300.png 256w\" sizes=\"(max-width: 622px) 100vw, 622px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>NOTA: Ahora como no seleccionamos el \u00abm\u00e9todo de filtrado\u00bb ni \u00abM\u00e9todo filtrado LOV\u00bb va mostrar todas las etapas<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Regresamos y guardamos todo<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">PASO2.2: Reportar el recurso<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora debemos reportar el proceso como un recurso<\/li>\n\n\n\n<li>Para esto ingresamos a SAS &#8211;  Seguridad y Administraci\u00f3n-&gt;SAS &#8211; Mantenimiento -&gt; \u00abLista de recursos\u00bb<\/li>\n\n\n\n<li>Datos:\n<ul class=\"wp-block-list\">\n<li>Nombre: \/pages\/batchJobLauncher.xhtml?proceso=procesoPPIAvisoInicioFinalizacionEtapasPPOJob   (NOTA: ES EL NOMBRE DEL ARCHIVO XML)<\/li>\n\n\n\n<li>Tipo de recurso: P\u00e1gina<\/li>\n\n\n\n<li>Visible: true<\/li>\n\n\n\n<li>Secuencia: 1<\/li>\n\n\n\n<li>Notas: Proceso que envi\u00e1 un correo a los usuarios con rol PPO Analista, PPO Aprobador Unidad Ejecutora, Aprobador Unidad Integradora y PPO Digitador para avisarles el inicio o finalizaci\u00f3n de una etapa y errores en los c\u00f3digos presupuestarios.<\/li>\n\n\n\n<li>Estado: Activo<\/li>\n\n\n\n<li>rol: UNA_PPI_PPO_ADMIN<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"879\" height=\"798\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_030.png\" alt=\"\" class=\"wp-image-14369\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_030.png 879w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_030-300x272.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_030-768x697.png 768w\" sizes=\"(max-width: 879px) 100vw, 879px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Paso3: crear men\u00fa<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora que ya definimos el proceso y definimos el recurso debemos crear la opci\u00f3n de men\u00fa<\/li>\n\n\n\n<li>Ingresamos a SAS &#8211; Seguridad y Administraci\u00f3n -&gt; SAS &#8211; Mantenimiento -&gt; \u00abLista de Men\u00fa\u00bb<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"221\" height=\"253\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_031.png\" alt=\"\" class=\"wp-image-14371\"\/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Le damos nuevo<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"304\" height=\"237\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_032.png\" alt=\"\" class=\"wp-image-14372\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_032.png 304w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_032-300x234.png 300w\" sizes=\"(max-width: 304px) 100vw, 304px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Datos:\n<ul class=\"wp-block-list\">\n<li>Crear men\u00fa de un men\u00fa padre:<\/li>\n\n\n\n<li>Men\u00fa: PPO &#8211; Procesos<\/li>\n\n\n\n<li>Recurso: \/pages\/batchJobLauncher.xhtml?proceso=procesoPPIAvisoInicioFinalizacionEtapasPPOJob<\/li>\n\n\n\n<li>Nombre: Proceso Aviso Inicio Finalizaci\u00f3n de Etapas PPO<\/li>\n\n\n\n<li>Notas: Proceso que envi\u00e1 un correo a los usuarios con rol PPO Analista, PPO Aprobador Unidad Ejecutora, Aprobador Unidad Integradora y PPO Digitador para avisarles el inicio o finalizaci\u00f3n de una etapa y errores en los c\u00f3digos presupuestarios.<\/li>\n\n\n\n<li>Estado: Activo<\/li>\n\n\n\n<li>Secuencia 2<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"837\" height=\"808\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_033.png\" alt=\"\" class=\"wp-image-14373\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_033.png 837w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_033-300x290.png 300w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_033-768x741.png 768w\" sizes=\"(max-width: 837px) 100vw, 837px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Paso 2.3: Volver a ingresar<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Ahora debemos salir del sistema y volver a ingresar <\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"419\" height=\"548\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_034.png\" alt=\"\" class=\"wp-image-14374\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_034.png 419w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_034-229x300.png 229w\" sizes=\"(max-width: 419px) 100vw, 419px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Y podemos ingresar a PPI -&gt; PPO-&gt; PPO &#8211; Procesos -&gt; \u00abProceso Aviso Inicio Finalizaci\u00f3n de Etapas PPO\u00bb<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"575\" height=\"394\" src=\"\/wp-content\/uploads\/2023\/03\/Seleccion_035.png\" alt=\"\" class=\"wp-image-14375\" srcset=\"https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_035.png 575w, https:\/\/sada.services\/wp-content\/uploads\/2023\/03\/Seleccion_035-300x206.png 300w\" sizes=\"(max-width: 575px) 100vw, 575px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Paso3: Creaci\u00f3n de funciones en PlanOperativoRepository<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Para la tarea espec\u00edfica se debio crear los siguientes metodos en el repository <\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n     * \n     * Defnici\u00f3n que retorna una lista de Planes Operativos seg\u00fan:\n     * \n     * @param periodoAnual\n     * @param unidadEjecutora\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @since 13\/03\/2023\n     * @issue: PPI-275\n     * @return List&lt;PlanOperativo>\n     *\/\n    public List&lt;PlanOperativo> findByPeriodoAnualAndUnidadEjecutora (PeriodoAnual periodoAnual, UnidadEjecutora unidadEjecutora);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Paso4: creaci\u00f3n de la definici\u00f3n del servicio (planOperativoService)<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n     * Definici\u00f3n del proceso que envia un correo de notificacion a usuarios con rol de digitador, aprobador y analista PPO sobre:\n     * * C\u00f3digos presupuestarios Sin presupuesto v\u00ednculados a metas\n     * * C\u00f3digos presupuestarios Con presupuesto No v\u00edculados a metas\n     *\n     * @param jobId : Id del proceso\n     * @param etapaPlan : etapaPlan a notificar\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 10\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public void procesoPPIAvisoInicioFinalizacionEtapasPPO(Long jobId, String idEtapaPlan);\n\n    \/**\n     * Definici\u00f3n de m\u00e9todo que obtiene los planes operativos por PeriodoAnual y Unidad Ejecutora:\n     *\n     * @param periodoAnual\n     * @param unidadEjecutora\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 10\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public List&lt;PlanOperativo> findByPeriodoAnualAndUnidadEjecutora(PeriodoAnual periodoAnual, UnidadEjecutora unidadEjecutora);\n\n    \/**\n     * Definici\u00f3n de m\u00e9todo que obtiene los c\u00f3digos presupuestarios sin presupuesto asignados a Metas de un plan operativo\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public List&lt;CodigoPresupuestario> obtenerCodigosPresupuestariosSinPresupuestoAsignadosAMetas(PlanOperativo planOperativo);\n\n    \/**\n     * Definici\u00f3n de m\u00e9todo que obtiene los c\u00f3digos presupuestarios con presupuesto sin asignar a Metas de un plan operativo\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public List&lt;CodigoPresupuestario> obtenerCodigosPresupuestariosConPresupuestoSinAsignarAMetas(PlanOperativo planOperativo);\n\n    \/**\n     * Definici\u00f3n que obtiene el plan operativo duplicado\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public PlanOperativo obtenerPlanOperativoDuplicadoPorPlanOperativo( PlanOperativo planOperativo);<\/code><\/pre>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Paso4: creaci\u00f3n de la definici\u00f3n del servicio (planOperativoServiceImpl)<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/**\n     * Proceso que envia un correo de notificacion a usuarios con rol de digitador, aprobador y Analista sobre:\n     * * C\u00f3digos presupuestarios Sin presupuesto v\u00ednculados a metas\n     * * C\u00f3digos presupuestarios Con presupuesto No v\u00edculados a metas\n     *\n     * @param jobId : Id del proceso\n     * @param etapaPlan : etapaPlan a notificar\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    @Override\n    public void procesoPPIAvisoInicioFinalizacionEtapasPPO(Long jobId, String idEtapaPlan) {\n\n\n        \/\/ *************************************************\n        \/\/ Variables Necesarias\n        \/\/ *************************************************\n        \/\/ Etapa plan pasada por parametro\n        EtapaPlan etapaPlan = etapaPlanService.find(Long.parseLong(idEtapaPlan));\n        \n        TipoEtapa tipoEtapaModificacion = tipoEtapaService.findTipoEtapaByParametro(\"param_ppi_ppo_tipoEtapa_modificacion\");\n        TipoPlanOperativo tipoPlanUnidad = tipoPlanOperativoService.findTipoPlanUnidad();\n        \n        \/\/ Creamos una lista de planes operativos por notificar\n        List&lt;PlanOperativo> planesOperativosPorNotificar = new ArrayList();\n        \n        \/\/ Cuerpo del correo\n        String bodyCorreo=\"\"; \n\n        \/\/ *************************************************\n        \/\/ Crear lista de planOperativos por notificar (Si existe duplicado o sino formulado)\n        \/\/ *************************************************\n\n        \/\/ Obtenemos los planes activos\n        List&lt;PlanOperativo> planesOperativosActivos = repository.findByActivo(Boolean.TRUE);\n\n        \/\/ Si existen planes activos\n        if (!planesOperativosActivos.isEmpty()) {\n\n            \/\/ Recorremos los planes activos\n            for (PlanOperativo planOperativoActivo : planesOperativosActivos) {\n                \/\/ Obtenemos el duplicado del plan\n                PlanOperativo planOperativoDuplicado = obtenerPlanOperativoDuplicadoPorPlanOperativo(planOperativoActivo);\n                \n                \/\/ Existe duplicado\n                if(planOperativoDuplicado != null){\n                    planesOperativosPorNotificar.add(planOperativoDuplicado);\n\n                    \/\/ Si no existe duplicado utilizamos el formulado\n                }else{\n                    planesOperativosPorNotificar.add(planOperativoActivo);\n                }\n            }\n\n            \/\/ *************************************************\n            \/\/ Si la lista no esta vacia\n            \/\/ *************************************************\n            if (!planesOperativosPorNotificar.isEmpty()) {\n\n                \/\/ *************************************************\n                \/\/ Obtener los roles necesarios\n                \/\/ *************************************************\n                \/\/ Obtenemos los usuarios con rol de Aprobador Unidad Ejecutora\n                Rol rolPPOAprobadorUnidadEjecutora = rolService.findOne(Long.parseLong(parametroService.findOneByLlave(\"param_ppi_ppo_rol_aprobador_unidad_ejecutora\").getValor()));\n                List&lt;Usuario> usuariosPPOUnidadEjecutora = rolUsuarioService.getByRolActivo(rolPPOAprobadorUnidadEjecutora);\n\n                \/\/ Obtenemos los usuarios con rol de Aprobador Unidad Integradora\n                Rol rolPPOAprobadorUnidadIntegradora = rolService.findOne(Long.parseLong(parametroService.findOneByLlave(\"param_ppi_ppo_rol_aprobador_unidad_integradora\").getValor()));\n                List&lt;Usuario> usuariosPPOUnidadIntegradora = rolUsuarioService.getByRolActivo(rolPPOAprobadorUnidadIntegradora);\n\n                \/\/ Obtenemos los usuarios con rol de Analista PPO\n                Rol rolPPOAnalista = rolService.findOne(Long.parseLong(parametroService.findOneByLlave(\"param_ppi_ppo_rol_analista\").getValor()));\n                List&lt;Usuario> usuariosPPOAnalista = rolUsuarioService.getByRolActivo(rolPPOAnalista);\n\n\n                \/\/ Obtenemos los usuarios con rol de Digitador PPO\n                Rol rolPPODigitador = rolService.findOne(Long.parseLong(parametroService.findOneByLlave(\"param_ppi_ppo_rol_digitador\").getValor()));\n                List&lt;Usuario> usuariosPPODigitador = rolUsuarioService.getByRolActivo(rolPPODigitador);\n\n                \/\/ *************************************************\n                \/\/ Crea asunto correo\n                \/\/ *************************************************\n                \/\/ A\u00f1o de la etapa\n                String etapaPlanAnno = Integer.toString(etapaPlan.getPeriodoAnual().getAno());\n                \n                \/\/ Variable para el asunto del correo\n                String subject=\"\";\n\n                \/\/ Obtenemos el parametro del subject\n                String titulo = i18nService.findOneByLlaveAndIdioma(\"param_ppi_ppo_AvisoInicioFinalizacionEtapasPPO_subject\", \"es\").getValor();\n                \n                \/\/ Subject\n                subject = titulo + \": \" + etapaPlan.getNombre() + \" \" + etapaPlanAnno;\n\n                \/\/ *************************************************\n                \/\/ Recorrer los planes operativos activos\n                \/\/ *************************************************\n                for (PlanOperativo planOperativo : planesOperativosPorNotificar) {\n\n                    \/\/ *************************************************\n                    \/\/ Parametros Correo\n                    \/\/ *************************************************\n                    Map&lt;String, String> parametros = new HashMap&lt;>();\n\n                    parametros.put(\"etapaPlanNombre\", etapaPlan.getNombre());\n                    parametros.put(\"etapaPlanFechaInicial\", etapaPlan.getFechaInicialStr());\n                    parametros.put(\"etapaPlanFechaFinal\", etapaPlan.getFechaFinalStr());\n                    parametros.put(\"etapaPlanAnno\", etapaPlanAnno);\n\n                    \/\/ Variable para almacenar los codigos presupuestarios Sin Presupuesto Asignados a Metas\n                    String mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta = \"\";\n\n                    \/\/ Variable para almacenar los codigos Presupuestarios Con Presupuesto Sin Asignar a Metas\n                    String mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta = \"\";\n\n                    \/\/ *************************************************\n                    \/\/ Obtener usuarios ACL por Unidad Ejecutora\n                    \/\/ *************************************************\n                    \/\/ Obtenemos los usuarios por Rol ACL\n                    List&lt;Usuario> usuariosUE = this.obtieneUsuariosPorRolAcl(planOperativo.getUnidadEjecutora().getCodigo());\n\n                    \/\/ Creamos una lista de usuarios para envi\u00f3 de correo\n                    List&lt;Usuario> usuariosEnviarCorreo = new ArrayList();\n\n                    \/\/ Le agregamos la lista de usuarios de analista a la lista de envi\u00f3 de correo\n                    usuariosEnviarCorreo.addAll(usuariosPPOAnalista);\n\n                    \/\/ Que corremos la lista de usuarios ACL\n                    for (Usuario usuarioACL : usuariosUE) {\n            \n                        \/\/ Si el el usuarioACL esta dentro de de la lista de unidadEjecutora o unidadIntegradora o digitador o no esta en la lista de envi\u00f3 de correo \n                        if (\n                            (\n                                usuariosPPOUnidadEjecutora.contains(usuarioACL) || \n                                usuariosPPOUnidadIntegradora.contains(usuarioACL)|| \n                                usuariosPPODigitador.contains(usuarioACL)\n                            ) \n                            &amp;&amp; \n                            (\n                                !usuariosEnviarCorreo.contains(usuarioACL)\n                            )) {\n                            \n                            \/\/ Agregue el usuario a la lista\n                            usuariosEnviarCorreo.add(usuarioACL);\n                        }\n                    }\n\n\n                    \/\/ *************************************************\n                    \/\/ PASO2.1 Si es tipo Modificaci\u00f3n y Plan de Unidad \n                    \/\/ *************************************************\n                    if(etapaPlan.getTipoEtapa().equals(tipoEtapaModificacion) &amp;&amp; (planOperativo.getTipoPlanOperativo().equals(tipoPlanUnidad) )){\n                        \n                        \n                        \/\/ ****************************************************************\n                        \/\/ Lista de Codigos Presupuestarios Sin Presupuesto Asignado a Meta\n                        \/\/ ****************************************************************\n                        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosSinPresupuestoAsignadosAMetas =  this.obtenerCodigosPresupuestariosSinPresupuestoAsignadosAMetas(planOperativo);\n\n                        \/\/ Si la lista no esta vacia\n                        if (!listaCodigosPresupuestariosSinPresupuestoAsignadosAMetas.isEmpty()) {\n                            for(CodigoPresupuestario codigoPresupuestario : listaCodigosPresupuestariosSinPresupuestoAsignadosAMetas) {\n\n                                if (codigoPresupuestario.equals(listaCodigosPresupuestariosSinPresupuestoAsignadosAMetas.get(0))) {\n                                    mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta += i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_titleWarnnig\", \"es\").getValor()+\"&lt;br\/>\";\n                                } \n                                if(codigoPresupuestario.getSubprogramaPresupuestario().getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAcademico()) &amp;&amp; (!mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta.contains(i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioAcademico_titleWarnnig\", \"es\").getValor() + \"&lt;br\/>\"))){\n                                    mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta += i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioAcademico_titleWarnnig\", \"es\").getValor() + \"&lt;br\/>\";\n                               \n                                } else if(codigoPresupuestario.getSubprogramaPresupuestario().getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioVidaEstudiantil()) &amp;&amp; (!mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta.contains(i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioVidaUniversitaria_titleWarnnig\", \"es\").getValor()+ \"&lt;br\/>\"))){\n                                    mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta += i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioVidaUniversitaria_titleWarnnig\", \"es\").getValor() + \"&lt;br\/>\";\n                                } else if(codigoPresupuestario.getSubprogramaPresupuestario().getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAdministrativo()) &amp;&amp; (!mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta.contains(i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioAdministrativo_titleWarnnig\", \"es\").getValor()+ \"&lt;br\/>\"))){\n                                    mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta += i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosSinPresupuesto_programaPresupuestarioAdministrativo_titleWarnnig\", \"es\").getValor()+ \"&lt;br\/>\";\n                                } \n                                mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta += codigoPresupuestario.getCodigo() + \" \" + codigoPresupuestario.getNombre() + \"&lt;br \/>\";\n                            }\n                            parametros.put(\"mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta\", mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta);\n\n                        } else {\n                            parametros.put(\"mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta\", \"\");\n                        }\n\n                        \/\/ ****************************************************************\n                        \/\/ Lista de Codigos Presupuestarios Con Presupuesto Sin Asignar a Meta\n                        \/\/ ****************************************************************\n                        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosConPresupuestoSinAsignarAMeta =  this.obtenerCodigosPresupuestariosConPresupuestoSinAsignarAMetas(planOperativo);\n\n                        \/\/ Si la lista no esta vacia\n                        if(!listaCodigosPresupuestariosConPresupuestoSinAsignarAMeta.isEmpty()){\n                            for(CodigoPresupuestario codigoPresupuestario : listaCodigosPresupuestariosConPresupuestoSinAsignarAMeta){\n                                if (codigoPresupuestario.equals(listaCodigosPresupuestariosConPresupuestoSinAsignarAMeta.get(0))) {\n                                    mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta += i18nService.findOneByLlaveAndIdioma(\"planOperativo_codigosConPresupuesto_titleWarnnig\", \"es\").getValor()+\"&lt;br\/>\";\n                                } \n                                mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta += codigoPresupuestario.getCodigo() + \" \" + codigoPresupuestario.getNombre() + \"&lt;br \/>\";\n                            }\n                            parametros.put(\"mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta\", mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta);\n\n                        }else{\n                            parametros.put(\"mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta\", \"\");\n                        }\n\n                        \/\/ Verificar si almenos una lista tiene datos\n                        if( (!mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta.equals(\"\")) || (!mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta.equals(\"\"))){\n                            parametros.put(\"mensajeListaCodigosPresupuestarios\", \"Se le informa que el plan operativo c\u00f3digo: '\"+ planOperativo.getCodigo()+\"' contiene lo siguiente:\");\n                        }else{\n                            parametros.put(\"mensajeListaCodigosPresupuestarios\", \"\");\n                        }\n\n\n                    \/\/ *************************************************\n                    \/\/ Si no es etapa modificacion\n                    \/\/ *************************************************\n                    }else{\n                        \/\/ Oculte las siguientes variables del mensaje\n                        parametros.put(\"mensajeListaCodigosPresupuestarios\", \"\");\n                        parametros.put(\"mensajeCodigosPresupuestariosSinPresupuestoAsignadoMeta\", \"\");\n                        parametros.put(\"mensajeCodigosPresupuestariosConPresupuestoSinAsignarAMeta\", \"\");\n                    }\n\n                    bodyCorreo = plantillaCorreoService.getHtmlContent(\"TPPIPPOAVISOINICIOFINALIZACIONETAPASPPO\", parametros);\n\n                    \/\/ Verificamos si existe un plan \n                    this.enviarCorreoAvisoInicioFinalizacionEtapasPPO(\n                                    usuariosEnviarCorreo, \n                                    bodyCorreo,\n                                    subject);\n\n                }\n            }\n        }\n       \n\n        \n    }\n\n    \/**\n     * Metodo que envia un correo de notificacion a usuarios con rol de digitador, aprobador y Analista sobre:\n     * * C\u00f3digos presupuestarios Sin presupuesto v\u00ednculados a metas\n     * * C\u00f3digos presupuestarios Con presupuesto No v\u00edculados a metas\n     *\n     * @param usuariosEnviarCorreo\n     * @param bodyCorreo\n     * @param subject\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    public void enviarCorreoAvisoInicioFinalizacionEtapasPPO(\n                List&lt;Usuario> usuariosEnviarCorreo, \n                String bodyCorreo,\n                String subject) {\n        try {\n\n            \/\/ Creamos una lista vacia de personas\n            List&lt;Persona> personas = new ArrayList();\n\n            \/\/ Agregamos personas por usuario\n            personas = agregarPersonasPorUsuarios(personas, usuariosEnviarCorreo);\n\n            \/\/ Si la lista no esta vacia\n            if (!personas.isEmpty()) {\n\n                \/\/ Recorremos la lista de personas a enviar correo\n                for (Persona persona : personas) {\n                    \n                    \/\/ Crear lista de correos\n                    List&lt;String> correos = new ArrayList();\n\n                    \/\/ *************************************************\n                    \/\/ PASO3: Enviar correo \n                    \/\/ *************************************************\n                    \/\/ Obtenemos los correos de las personas\n                    persona.getPersonaCorreos().stream()\n                            .filter(personaCorreo -> ((personaCorreo.getActivo() == 1) &amp;&amp; (personaCorreo.getPrioridad() == 1)))\n                            .map(personaCorreo -> personaCorreo.getCorreoElectronico())\n                            .forEachOrdered(destinatario -> {\n                                correos.add(destinatario);\n                            });\n\n                    \/\/ Enviamos el correo\n                    if (!correos.isEmpty()) {\n                        mailService.sendMail(MailMessageData.builder()\n                                .to(correos)\n                                .subject(subject)\n                                .body(bodyCorreo)\n                                .build());\n                    }\n                }\n            }\n\n        } catch (Exception ex) {\n\n        }\n    }\n\n    \n    \/**\n     * M\u00e9todo que obtiene los c\u00f3digos presupuestarios sin presupuesto asignados a metas de un plan operativo\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    @Override\n    public List&lt;CodigoPresupuestario> obtenerCodigosPresupuestariosSinPresupuestoAsignadosAMetas(PlanOperativo planOperativo) {\n\n        \/\/*************************************************************\n        \/\/ Declaraci\u00f3n de Variables\n        \/\/*************************************************************\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestarios = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosAC = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosVU = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosAD = new ArrayList();\n\n        \n        List&lt;CodigoPresupuestario> listaCodigosFormuladosSinPresupuesto = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosEnPlanOperativo = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoAcademico = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoAdministrativo = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoVidaUniversitaria = new ArrayList();\n        List&lt;ObjetivoPOA> listaObjetivosPoa = planOperativo.getListaObjetivosPOA();\n\n        TipoPlanOperativo tipoPlanUnidad = tipoPlanOperativoService.findTipoPlanUnidad();\n        VinculacionPoa vinculacionPoaActual = vinculacionPoaService.findByUnidadEjecutoraAndPeriodoAnualAndTipoPlanOperativo(planOperativo.getUnidadEjecutora(), planOperativo.getPeriodoAnual(), tipoPlanUnidad);\n        List&lt;VinPoaUnidadEjecutora> listaVinPoaUnidadEjecutora = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosConPresupuesto = new ArrayList();\n\n        \/\/*************************************************************\n        \/\/ Si Existe vinculaci\u00f3n POA: Obtenemos Los c\u00f3digos Presupuestarios Con Presupuesto\n        \/\/*************************************************************\n        if (vinculacionPoaActual != null) {\n\n            if (vinculacionPoaActual.getId() != null) {\n                listaVinPoaUnidadEjecutora.addAll(vinculacionPoaActual.getListaVinPoaUnidadEjecutora());\n            } else {\n                listaVinPoaUnidadEjecutora.clear();\n            }\n                for (ObjetivoPOA objetivoPoa : planOperativo.getListaObjetivosPOA()) {\n                    listaCodigosPresupuestariosConPresupuesto.addAll(codigoPresupuestarioService.findByUnidadEjecutoraAndProgramaPresupuestarioAndPeriodoAnual(planOperativo.getUnidadEjecutora(), objetivoPoa.getProgramaPresupuestario(), planOperativo.getPeriodoAnual()));\n\n                    if (!listaVinPoaUnidadEjecutora.isEmpty()) {\n                        for (VinPoaUnidadEjecutora uniVin : listaVinPoaUnidadEjecutora) {\n                            listaCodigosPresupuestariosConPresupuesto.addAll(codigoPresupuestarioService.findByUnidadEjecutoraAndProgramaPresupuestarioAndPeriodoAnual(uniVin.getUnidadEjecutora(), objetivoPoa.getProgramaPresupuestario(), planOperativo.getPeriodoAnual()));\n                        }\n                    }\n                }\n        }\n        \n        \/\/*************************************************************\n        \/\/ Se eliminan Repetidos\n        \/\/*************************************************************\n        Set setConPresupuesto = new HashSet&lt;>(listaCodigosPresupuestariosConPresupuesto);\n        listaCodigosPresupuestariosConPresupuesto.clear();\n        listaCodigosPresupuestariosConPresupuesto.addAll(setConPresupuesto);\n\n\n        \/\/*************************************************************\n        \/\/ Obtener las Metas por Programa Presupuestario Y C\u00f3digos Presupuestarios por Metas\n        \/\/*************************************************************\n        for (ObjetivoPOA objetivo : listaObjetivosPoa) {\n            for (MetaPoa meta : objetivo.getListaMetasPoa()) {\n                for (MetaPoaPresupuesto presupuesto : meta.getListaMetaPoaPresupuestos()) {                  \n                    listaCodigosEnPlanOperativo.add(presupuesto.getCodigoPresupuestario());\n                }\n                if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAcademico())) {\n                    listaMetasEnPlanOperativoAcademico.add(meta);\n                } else if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAdministrativo())) {\n                    listaMetasEnPlanOperativoAdministrativo.add(meta);\n                } else if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioVidaEstudiantil())) {\n                    listaMetasEnPlanOperativoVidaUniversitaria.add(meta);\n                }\n            }\n        }\n\n        \/\/*************************************************************\n        \/\/ Obtener las Excepciones Presupuestarias y removerlas\n        \/\/*************************************************************\n        EtapaPlan etapaPlan = planOperativo.getEtapaPlan();\n        UnidadEjecutora unidadEjecutora = planOperativo.getUnidadEjecutora();\n        List&lt;ExcepcionPresupuestaria> listaExcepcionPresupuestaria = excepcionPresupuestariaService.findAllExcepcionPresupuestariaByEtapaPlanAndUnidadEjecutora(etapaPlan, unidadEjecutora);\n\n        if (listaExcepcionPresupuestaria != null &amp;&amp; !listaExcepcionPresupuestaria.isEmpty()) {\n            List&lt;ExcepcionCodigo> listaCodigosPresupuestariosExcepcionUnidad = excepcionCodigoService.findAllExcepcionCodigoByExcepcionPresupuestaria(listaExcepcionPresupuestaria.get(0));\n            for (ExcepcionCodigo excepcionCodigo : listaCodigosPresupuestariosExcepcionUnidad) {\n                if (listaCodigosPresupuestariosConPresupuesto.contains(excepcionCodigo.getCodigoPresupuestario())) {\n                    listaCodigosPresupuestariosConPresupuesto.remove(excepcionCodigo.getCodigoPresupuestario());\n                }\n            }\n        }\n\n        \/\/*************************************************************\n        \/\/ Crear lista de listaCodigosFormuladosSinPresupuesto\n        \/\/*************************************************************\n        for (CodigoPresupuestario codigoFormulado : listaCodigosEnPlanOperativo) {\n            if (!listaCodigosPresupuestariosConPresupuesto.contains(codigoFormulado) &amp;&amp; !listaCodigosFormuladosSinPresupuesto.contains(codigoFormulado)) {\n                listaCodigosFormuladosSinPresupuesto.add(codigoFormulado);\n            }\n        }\n\n        \/\/ Si la lista no esta vacia\n        if (!listaCodigosFormuladosSinPresupuesto.isEmpty()) {\n            for (CodigoPresupuestario codigoPresupuestario : listaCodigosFormuladosSinPresupuesto) {\n                String mensajeMeta = \"\";\n                for (MetaPoa meta : listaMetasEnPlanOperativoAcademico) {\n                    for (MetaPoaPresupuesto presupuesto : meta.getListaMetaPoaPresupuestos()) {\n                        if (presupuesto.getCodigoPresupuestario().getId().equals(codigoPresupuestario.getId()) &amp;&amp; !listaCodigosPresupuestariosAC.contains(presupuesto.getCodigoPresupuestario())) {\n                            listaCodigosPresupuestariosAC.add(presupuesto.getCodigoPresupuestario());\n                        }\n                    }\n                }\n                for (MetaPoa meta : listaMetasEnPlanOperativoVidaUniversitaria) {\n                    for (MetaPoaPresupuesto presupuesto : meta.getListaMetaPoaPresupuestos()) {\n                        if (presupuesto.getCodigoPresupuestario().getId().equals(codigoPresupuestario.getId()) &amp;&amp; !listaCodigosPresupuestariosVU.contains(presupuesto.getCodigoPresupuestario())) {\n                           listaCodigosPresupuestariosVU.add(presupuesto.getCodigoPresupuestario());\n                        }\n                    }\n                }\n                for (MetaPoa meta : listaMetasEnPlanOperativoAdministrativo) {\n                    for (MetaPoaPresupuesto presupuesto : meta.getListaMetaPoaPresupuestos()) {\n                        if (presupuesto.getCodigoPresupuestario().getId().equals(codigoPresupuestario.getId()) &amp;&amp; !listaCodigosPresupuestariosAD.contains(presupuesto.getCodigoPresupuestario())) {\n                            listaCodigosPresupuestariosAD.add(presupuesto.getCodigoPresupuestario());\n                        }\n                    }\n                }\n            }\n        }\n\n        \/\/ Contatenar las listas\n        if(!listaCodigosPresupuestariosAC.isEmpty()){\n            listaCodigosPresupuestarios.addAll(listaCodigosPresupuestariosAC);\n        }else if(!listaCodigosPresupuestariosVU.isEmpty()){\n            listaCodigosPresupuestarios.addAll(listaCodigosPresupuestariosVU);\n        }else if(!listaCodigosPresupuestariosAD.isEmpty()){\n            listaCodigosPresupuestarios.addAll(listaCodigosPresupuestariosAD);\n        }\n        return listaCodigosPresupuestarios;\n    }\n\n    \/**\n     * Definici\u00f3n de m\u00e9todo que obtiene los c\u00f3digos presupuestarios con presupuesto sin asignar a metas de un plan operativo\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    @Override\n    public List&lt;CodigoPresupuestario> obtenerCodigosPresupuestariosConPresupuestoSinAsignarAMetas(PlanOperativo planOperativo) {\n\n        \/\/*************************************************************\n        \/\/ Declaraci\u00f3n de Variables\n        \/\/*************************************************************\n        List&lt;CodigoPresupuestario> listaCodigosFormuladosSinPresupuesto = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosEnPlanOperativo = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosConPresupuestoFaltantes = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoAcademico = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoAdministrativo = new ArrayList();\n        List&lt;MetaPoa> listaMetasEnPlanOperativoVidaUniversitaria = new ArrayList();\n        List&lt;ObjetivoPOA> listaObjetivosPoa = planOperativo.getListaObjetivosPOA();\n\n\n        TipoPlanOperativo tipoPlanUnidad = tipoPlanOperativoService.findTipoPlanUnidad();\n        VinculacionPoa vinculacionPoaActual = vinculacionPoaService.findByUnidadEjecutoraAndPeriodoAnualAndTipoPlanOperativo(planOperativo.getUnidadEjecutora(), planOperativo.getPeriodoAnual(), tipoPlanUnidad);\n        List&lt;VinPoaUnidadEjecutora> listaVinPoaUnidadEjecutora = new ArrayList();\n        List&lt;CodigoPresupuestario> listaCodigosPresupuestariosConPresupuesto = new ArrayList();\n\n        \/\/*************************************************************\n        \/\/ Si Existe vinculaci\u00f3n POA: Obtenemos Los c\u00f3digos Presupuestarios Con Presupuesto\n        \/\/*************************************************************\n        if (vinculacionPoaActual != null) {\n\n            if (vinculacionPoaActual.getId() != null) {\n                listaVinPoaUnidadEjecutora.addAll(vinculacionPoaActual.getListaVinPoaUnidadEjecutora());\n            } else {\n                listaVinPoaUnidadEjecutora.clear();\n            }\n                for (ObjetivoPOA objetivoPoa : planOperativo.getListaObjetivosPOA()) {\n                    listaCodigosPresupuestariosConPresupuesto.addAll(codigoPresupuestarioService.findByUnidadEjecutoraAndProgramaPresupuestarioAndPeriodoAnual(planOperativo.getUnidadEjecutora(), objetivoPoa.getProgramaPresupuestario(), planOperativo.getPeriodoAnual()));\n\n                    if (!listaVinPoaUnidadEjecutora.isEmpty()) {\n                        for (VinPoaUnidadEjecutora uniVin : listaVinPoaUnidadEjecutora) {\n                            listaCodigosPresupuestariosConPresupuesto.addAll(codigoPresupuestarioService.findByUnidadEjecutoraAndProgramaPresupuestarioAndPeriodoAnual(uniVin.getUnidadEjecutora(), objetivoPoa.getProgramaPresupuestario(), planOperativo.getPeriodoAnual()));\n                        }\n                    }\n                }\n        }\n        \n        \/\/*************************************************************\n        \/\/ Se eliminan Repetidos\n        \/\/*************************************************************\n        Set setConPresupuesto = new HashSet&lt;>(listaCodigosPresupuestariosConPresupuesto);\n        listaCodigosPresupuestariosConPresupuesto.clear();\n        listaCodigosPresupuestariosConPresupuesto.addAll(setConPresupuesto);\n\n        \/\/*************************************************************\n        \/\/ Obtener las Metas por Programa Presupuestario Y C\u00f3digos Presupuestarios por Metas\n        \/\/*************************************************************\n        for (ObjetivoPOA objetivo : listaObjetivosPoa) {\n            for (MetaPoa meta : objetivo.getListaMetasPoa()) {\n                for (MetaPoaPresupuesto presupuesto : meta.getListaMetaPoaPresupuestos()) {                  \n                    listaCodigosEnPlanOperativo.add(presupuesto.getCodigoPresupuestario());\n                }\n                if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAcademico())) {\n                    listaMetasEnPlanOperativoAcademico.add(meta);\n                } else if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioAdministrativo())) {\n                    listaMetasEnPlanOperativoAdministrativo.add(meta);\n                } else if (objetivo.getProgramaPresupuestario().equals(programaPresupuestarioService.getProgramaPresupuestarioVidaEstudiantil())) {\n                    listaMetasEnPlanOperativoVidaUniversitaria.add(meta);\n                }\n            }\n        }\n\n        \/\/*************************************************************\n        \/\/ Obtener las Excepciones Presupuestarias y removerlas\n        \/\/*************************************************************\n        EtapaPlan etapaPlan = planOperativo.getEtapaPlan();\n        UnidadEjecutora unidadEjecutora = planOperativo.getUnidadEjecutora();\n        List&lt;ExcepcionPresupuestaria> listaExcepcionPresupuestaria = excepcionPresupuestariaService.findAllExcepcionPresupuestariaByEtapaPlanAndUnidadEjecutora(etapaPlan, unidadEjecutora);\n\n        if (listaExcepcionPresupuestaria != null &amp;&amp; !listaExcepcionPresupuestaria.isEmpty()) {\n            List&lt;ExcepcionCodigo> listaCodigosPresupuestariosExcepcionUnidad = excepcionCodigoService.findAllExcepcionCodigoByExcepcionPresupuestaria(listaExcepcionPresupuestaria.get(0));\n            for (ExcepcionCodigo excepcionCodigo : listaCodigosPresupuestariosExcepcionUnidad) {\n                if (listaCodigosPresupuestariosConPresupuesto.contains(excepcionCodigo.getCodigoPresupuestario())) {\n                    listaCodigosPresupuestariosConPresupuesto.remove(excepcionCodigo.getCodigoPresupuestario());\n                }\n            }\n        }\n\n        \n\n        \/\/*************************************************************\n        \/\/ Crear lista de listaCodigosConPresupuestoFaltantes\n        \/\/*************************************************************\n        for (CodigoPresupuestario codigoConPresupuesto : listaCodigosPresupuestariosConPresupuesto) {\n            if (!listaCodigosEnPlanOperativo.contains(codigoConPresupuesto) &amp;&amp; !listaCodigosConPresupuestoFaltantes.contains(codigoConPresupuesto)) {\n                listaCodigosConPresupuestoFaltantes.add(codigoConPresupuesto);\n            }\n        }\n\n        \n        \n        if (!listaCodigosConPresupuestoFaltantes.isEmpty()) {\n            Set setCodigos = new HashSet&lt;>(listaCodigosConPresupuestoFaltantes);\n            listaCodigosConPresupuestoFaltantes.clear();\n            listaCodigosConPresupuestoFaltantes.addAll(setCodigos);\n        \n        }\n\n        return listaCodigosConPresupuestoFaltantes;\n    }\n\n    \/**\n     * M\u00e9todo que obtiene los planes operativos por PeriodoAnual y Unidad Ejecutora:\n     *\n     * @param periodoAnual\n     * @param unidadEjecutora\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 10\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    @Override\n    public List&lt;PlanOperativo> findByPeriodoAnualAndUnidadEjecutora(PeriodoAnual periodoAnual, UnidadEjecutora unidadEjecutora) {\n        return repository.findByPeriodoAnualAndUnidadEjecutora(periodoAnual, unidadEjecutora);\n    }\n\n    \/**\n     * M\u00e9todo que obtiene el plan operativo duplicado\n     *\n     * @param planOperativo\n     * @author Gustavo Matamoros Gonz\u00e1lez\n     * @fechaCreacion: 22\/03\/2023\n     * @Version: 1.0.0\n     * @modulo: PPI-PPO\n     * @issue: PPI-275\n     *\/\n    @Override\n    public PlanOperativo obtenerPlanOperativoDuplicadoPorPlanOperativo( PlanOperativo planOperativo) {\n        \n        \/\/ Obtenemos el estado de borrador\n        EstadoFormulacionOpe estadoAnulado = estadoFormulacionOpeService.obtenerEstadoAnulado();\n\n        \/\/ Obtenemos el tipo de Etapa Modificaci\u00f3n\n        TipoEtapa tipoEtapaModificacion = tipoEtapaService.findTipoEtapaByParametro(\"param_ppi_ppo_tipoEtapa_modificacion\");\n\n        \/\/ Creamos una lista de planes operativos por Unidad Ejecutora\n        List&lt;PlanOperativo> planesOperativosPorUnidadEjecutora = new ArrayList();\n\n        \/\/ Obtenemos los planes operativos por PeriodoAnual y Unidad Ejecutora\n        planesOperativosPorUnidadEjecutora = this.findByPeriodoAnualAndUnidadEjecutora(planOperativo.getPeriodoAnual(),planOperativo.getUnidadEjecutora());\n\n        \/\/ Crear variable de plan Operativo Duplicado\n        PlanOperativo planOperativoDuplicado = null;\n\n        \/\/ Si la lista de Planes Operativos x Unidad Ejecutora no esta vacia\n        if (!planesOperativosPorUnidadEjecutora.isEmpty()) {\n\n            \/\/ Recorremos la lista de planes operativos por Unidad ejecutora\n            for (PlanOperativo planOperativoPorUnidad : planesOperativosPorUnidadEjecutora) {\n\n                \/\/ Obtenemos el tipo de Etapa Modificaci\u00f3n\n                EtapaPlan etapaPlan = etapaPlanService.findByTipoEtapaAndTipoPlanAndTipoPlanOperativoAndPeriodoAnualAndFechaInicialLessThanEqualAndFechaFinalGreaterThanEqual(tipoEtapaModificacion, planOperativo.getTipoPlan(), planOperativo.getTipoPlanOperativo(), planOperativo.getPeriodoAnual());\n\n                \/\/ Si la etapa de Plan de Modificaci\u00f3n existe\n                if (etapaPlan != null) {\n\n                    \/\/ Si existe un duplicado para la etapaPlan modificacion\n                    if( (planOperativoPorUnidad.getEstadoFormulacionOpe() != estadoAnulado) &amp;&amp; (planOperativoPorUnidad.getEtapaPlan()==etapaPlan)){\n                        planOperativoDuplicado = planOperativoPorUnidad;\n                    } \n                }\n            }\n            \n        }\n        return planOperativoDuplicado;\n        \n    }<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Paso5: funciones adicionales en EtapaPlan.java<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>import java.text.SimpleDateFormat;\n\n\npublic String getFechaInicialStr() {\n        if (fechaInicial != null) {\n            SimpleDateFormat dt = new SimpleDateFormat(\"dd-MM-yyyy\");\n            return dt.format(fechaInicial);\n        } else {\n            return \"\";\n        }\n    }\n\n    public String getFechaFinalStr() {\n        if (fechaFinal != null) {\n            SimpleDateFormat dt = new SimpleDateFormat(\"dd-MM-yyyy\");\n            return dt.format(fechaFinal);\n        } else {\n            return \"\";\n        }\n    }<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Tarea: Paso01: Crear Proceso Paso1.1 Relaci\u00f3n SIGESA -&gt; Proceso Paso 1.2: relaci\u00f3n Proceso -&gt; Servicio Paso 1.3: lanzador del proceso Paso 1.4: Resultado Final Paso2: reportar el proceso Paso 2.1: Reportar proceso PASO2.2: Reportar el recurso Paso3: crear men\u00fa Paso 2.3: Volver a ingresar Paso3: Creaci\u00f3n de funciones en PlanOperativoRepository Paso4: creaci\u00f3n de la definici\u00f3n [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[443],"tags":[69,484,444],"class_list":["post-14324","post","type-post","status-publish","format-standard","hentry","category-sigesa","tag-correo","tag-proceso","tag-sigesa"],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"_links":{"self":[{"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/posts\/14324","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sada.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=14324"}],"version-history":[{"count":25,"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/posts\/14324\/revisions"}],"predecessor-version":[{"id":14497,"href":"https:\/\/sada.services\/index.php?rest_route=\/wp\/v2\/posts\/14324\/revisions\/14497"}],"wp:attachment":[{"href":"https:\/\/sada.services\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=14324"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sada.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=14324"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sada.services\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=14324"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}