diff --git a/curriculumsearch/pom.xml b/curriculumsearch/pom.xml index 7d27c1a..bd97b04 100644 --- a/curriculumsearch/pom.xml +++ b/curriculumsearch/pom.xml @@ -92,24 +92,7 @@ compile - - com.itextpdf - kernel - 7.1.12 - - - com.itextpdf - html2pdf - 3.0.1 - - - - - - - - org.apache.poi @@ -117,6 +100,12 @@ 4.1.0 + + com.itextpdf + itextpdf + 5.5.13 + + diff --git a/curriculumsearch/src/main/java/com/roshka/CurriculumsearchApplication.java b/curriculumsearch/src/main/java/com/roshka/CurriculumsearchApplication.java index 173a835..ef85ce3 100644 --- a/curriculumsearch/src/main/java/com/roshka/CurriculumsearchApplication.java +++ b/curriculumsearch/src/main/java/com/roshka/CurriculumsearchApplication.java @@ -42,6 +42,7 @@ public class CurriculumsearchApplication { guardarJson(convR,"/json/convocatoria.json",ConvocatoriaCargo.class); guardarJson(depR,"/json/Departamento.json",Departamento.class); guardarJson(ciudR,"/json/Ciudad.json",Ciudad.class); + guardarJson(tecRepo,"/json/tecnologia.json",Tecnologia.class); guardarJson(postRepo,"/json/postulante.json",Postulante.class); String password = new BCryptPasswordEncoder().encode("test"); diff --git a/curriculumsearch/src/main/java/com/roshka/controller/PostulanteController.java b/curriculumsearch/src/main/java/com/roshka/controller/PostulanteController.java index 2e15e7e..5ef4d2b 100644 --- a/curriculumsearch/src/main/java/com/roshka/controller/PostulanteController.java +++ b/curriculumsearch/src/main/java/com/roshka/controller/PostulanteController.java @@ -114,10 +114,7 @@ public class PostulanteController { DBFile cv = Helper.createFile(file); if(cv!=null) cv.setPostulante(postulante); postulante.setCvFile(cv); - } - postulante.getTecnologias().stream().filter(tec -> tec.getTecnologia().getId() != 0) - .forEach(tec -> tec.setTecnologia(tecRepo.getById(tec.getTecnologia().getId()))); - + } for(Estudio estudio: postulante.getEstudios()){ String nombreIns = ""; nombreIns = estudio.getInstitucion().getNombre().toLowerCase(); diff --git a/curriculumsearch/src/main/java/com/roshka/controller/PostulanteRRHHController.java b/curriculumsearch/src/main/java/com/roshka/controller/PostulanteRRHHController.java index 34693cb..20b20ba 100644 --- a/curriculumsearch/src/main/java/com/roshka/controller/PostulanteRRHHController.java +++ b/curriculumsearch/src/main/java/com/roshka/controller/PostulanteRRHHController.java @@ -26,6 +26,7 @@ import com.roshka.repositorio.ExperienciaRepository; import com.roshka.repositorio.InstitucionRepository; import com.roshka.repositorio.PostulanteRepository; import com.roshka.repositorio.TecnologiaRepository; +import com.roshka.service.PdfGenerator; import com.roshka.utils.Helper; @@ -247,5 +248,26 @@ public class PostulanteRRHHController { } } + + @GetMapping("/postulantes/{id}/pdf") + public ResponseEntity downloadPDF(@PathVariable Long id) { + // Load file from database + PdfGenerator pdf = new PdfGenerator(); + + + try { + Postulante postulante = post.findById(id) + .orElseThrow(() -> new Exception("Postulante no encontrado")); + return ResponseEntity.ok() + .contentType(MediaType.parseMediaType("application/pdf")) + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + postulante.getNroDocument() + ".pdf" + "\"") + .body(new ByteArrayResource(pdf.generatePdfReport(postulante))); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return ResponseEntity.notFound().build(); + } + + } } \ No newline at end of file diff --git a/curriculumsearch/src/main/java/com/roshka/modelo/Postulante.java b/curriculumsearch/src/main/java/com/roshka/modelo/Postulante.java index 7c27b6a..6d037a2 100644 --- a/curriculumsearch/src/main/java/com/roshka/modelo/Postulante.java +++ b/curriculumsearch/src/main/java/com/roshka/modelo/Postulante.java @@ -96,6 +96,9 @@ public class Postulante { @Column(name = "disponibilidad", length = 2) private Disponibilidad disponibilidad; + @Column(name = "tecnologia_otros") + private String tecnologiaOtros; + @JsonManagedReference(value = "postulantetecnologia-postulante") @OneToMany(mappedBy = "postulante",cascade = CascadeType.ALL) private List tecnologias; diff --git a/curriculumsearch/src/main/java/com/roshka/modelo/PostulanteTecnologia.java b/curriculumsearch/src/main/java/com/roshka/modelo/PostulanteTecnologia.java index 4224e07..771a35c 100644 --- a/curriculumsearch/src/main/java/com/roshka/modelo/PostulanteTecnologia.java +++ b/curriculumsearch/src/main/java/com/roshka/modelo/PostulanteTecnologia.java @@ -31,7 +31,7 @@ public class PostulanteTecnologia { @Min(value = 1) @Max(value = 5) private Long nivel; - @ManyToOne(cascade = {CascadeType.PERSIST},optional = false) + @ManyToOne() @JoinColumn private Tecnologia tecnologia; diff --git a/curriculumsearch/src/main/java/com/roshka/service/PdfGenerator.java b/curriculumsearch/src/main/java/com/roshka/service/PdfGenerator.java new file mode 100644 index 0000000..0d75e82 --- /dev/null +++ b/curriculumsearch/src/main/java/com/roshka/service/PdfGenerator.java @@ -0,0 +1,169 @@ +package com.roshka.service; + +import java.io.ByteArrayOutputStream; +import java.util.Date; +import java.util.stream.Collectors; + +import com.itextpdf.text.List; +import com.itextpdf.text.ListItem; + + +import org.springframework.stereotype.Component; + + +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Element; +import com.itextpdf.text.Font; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.pdf.PdfWriter; +import com.roshka.modelo.Estudio; +import com.roshka.modelo.Experiencia; +import com.roshka.modelo.Postulante; +import com.roshka.utils.Helper; + +@Component("pdfGenerator") +public class PdfGenerator { + + private static Font COURIER = new Font(Font.FontFamily.COURIER, 20, Font.BOLD); + private static Font COURIER_MEDIUM = new Font(Font.FontFamily.COURIER, 16, Font.BOLD); + private static Font COURIER_SMALL = new Font(Font.FontFamily.COURIER, 14, Font.UNDERLINE); + + public byte[] generatePdfReport(Postulante postulante) { + + Document document = new Document(); + + try { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + PdfWriter.getInstance(document, byteArrayOutputStream); + document.open(); + + addDocTitle(document, postulante); + createTable(document,postulante); + + + document.close(); + System.out.println("------------------Your PDF Report is ready!-------------------------"); + return byteArrayOutputStream.toByteArray(); + + } catch ( DocumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + return null; + } + + } + + private void addDocTitle(Document document, Postulante postulante) throws DocumentException { + Paragraph p1 = new Paragraph(); + leaveEmptyLine(p1, 1); + p1.add(new Paragraph("Detalles del postulante", COURIER)); + p1.setAlignment(Element.ALIGN_CENTER); + document.add(p1); + + } + private void agregarEncabezado(Document document, String titulo) throws DocumentException { + + Paragraph p1 = new Paragraph(); + p1.setAlignment(Element.ALIGN_CENTER); + p1.add(new Paragraph(titulo, COURIER_MEDIUM)); + document.add(p1); + + } + private void agregarSubEncabezado(Document document, String titulo) throws DocumentException { + + Paragraph p1 = new Paragraph(); + p1.setAlignment(Element.ALIGN_CENTER); + p1.add(new Paragraph(titulo, COURIER_SMALL)); + document.add(p1); + + } + + private void agregarLabelTexto(Document document, String label, Object texto) throws DocumentException{ + if(texto == null) return; + if(texto instanceof Date) texto = Helper.formatDate((Date)texto, "dd-MM-yyyy"); + Paragraph paragraph = new Paragraph(); + paragraph.add(label + ": "); + paragraph.add(texto.toString()); + document.add(paragraph); + } + + private void createTable(Document document, Postulante postulante) throws DocumentException { + + Paragraph paragraph = new Paragraph(); + leaveEmptyLine(paragraph, 3); + //paragraph.add(); + agregarEncabezado(document, "Datos personales"); + agregarLabelTexto(document, "Nombre", postulante.getNombre() + " " + postulante.getApellido()); + agregarLabelTexto(document, "Nro de Documento", postulante.getNroDocument()); + agregarLabelTexto(document, "Correo", postulante.getCorreo()); + agregarLabelTexto(document, "Direccion", postulante.getDireccion()); + agregarLabelTexto(document, "Ciudad", postulante.getCiudad().getNombre()); + agregarLabelTexto(document, "Telefono", postulante.getTelefono()); + agregarLabelTexto(document, "Edad", Helper.calculateAge(postulante.getFechaNacimiento()) ); + agregarLabelTexto(document, "Nivel de Ingles", postulante.getNivelIngles()); + agregarLabelTexto(document, "Nacionalidad", postulante.getNacionalidad().getDescripcion()); + + agregarEncabezado(document, "Experiencias"); + + for(Experiencia ex : postulante.getExperiencias()){ + agregarSubEncabezado(document, ex.getInstitucion()); + agregarLabelTexto(document, "Fecha Inicio", ex.getFechaDesde()); + agregarLabelTexto(document, "Fecha Fin", ex.getFechaHasta()); + agregarLabelTexto(document, "Cargo", ex.getCargo()); + agregarLabelTexto(document, "Tipo Experiencia", ex.getTipoExperiencia()); + agregarLabelTexto(document, "Descripcion", ex.getDescripcion()); + agregarLabelTexto(document, "Nombre Referencia", ex.getNombreReferencia()); + agregarLabelTexto(document, "Telefono Referencia", ex.getTelefonoReferencia()); + agregarLabelTexto(document, "Motivo Salida", ex.getMotivoSalida()); + } + agregarEncabezado(document, "Estudios"); + + for(Estudio ex : postulante.getEstudios()){ + agregarSubEncabezado(document, ex.getInstitucion().getNombre()); + agregarLabelTexto(document, "Fecha Inicio", ex.getFechaDesde()); + agregarLabelTexto(document, "Fecha Fin", ex.getFechaHasta()); + agregarLabelTexto(document, "Tema de Estudio", ex.getTemaDeEstudio()); + agregarLabelTexto(document, "Tipo de Estudio", ex.getTipoDeEstudio()); + agregarLabelTexto(document, "Descripcion", ex.getEstado().toString()); + } + + agregarEncabezado(document, "Cargo al cual postula"); + + agregarList(postulante.getPostulaciones().stream() + .map(cc -> cc.getCargo().getNombre()) + .collect(Collectors.toList()), document); + + agregarEncabezado(document, "Tecnologias"); + + agregarList(postulante.getTecnologias().stream() + .map(cc -> cc.getTecnologia().getNombre()) + .collect(Collectors.toList()), + document); + + agregarEncabezado(document, "Referencias Personales"); + + agregarList(postulante.getReferencias().stream() + .map(cc -> "Nombre: " + cc.getNombre() + ". Relacion: " + cc.getRelacion() + ". Telefono: " + cc.getTelefono() ) + .collect(Collectors.toList()), + document); + + + } + + private void agregarList(java.util.List items, Document document) throws DocumentException{ + List list = new List(false); + for(String item : items){ + list.add(new ListItem(item)); + } + document.add(list); + + + } + private static void leaveEmptyLine(Paragraph paragraph, int number) { + for (int i = 0; i < number; i++) { + paragraph.add(new Paragraph(" ")); + } + } + +} diff --git a/curriculumsearch/src/main/java/com/roshka/utils/Helper.java b/curriculumsearch/src/main/java/com/roshka/utils/Helper.java index 189aa82..426686e 100644 --- a/curriculumsearch/src/main/java/com/roshka/utils/Helper.java +++ b/curriculumsearch/src/main/java/com/roshka/utils/Helper.java @@ -3,9 +3,9 @@ package com.roshka.utils; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.time.YearMonth; -import java.time.ZoneOffset; -import java.time.temporal.ChronoUnit; +import java.time.LocalDate; +import java.time.Period; +import java.time.format.DateTimeFormatter; import java.util.Date; import java.util.concurrent.TimeUnit; @@ -46,6 +46,31 @@ public class Helper { return Math.round(diff/30.d) ; } + public static LocalDate convertToLocalDateViaSqlDate(Date dateToConvert) { + return new java.sql.Date(dateToConvert.getTime()).toLocalDate(); + } + + public static int calculateAge(LocalDate birthDate, LocalDate currentDate) { + if ((birthDate != null) && (currentDate != null)) { + return Period.between(birthDate, currentDate).getYears(); + } else { + return 0; + } + } + + public static int calculateAge(Date birthDate) { + LocalDate currentDate = LocalDate.now(); + return calculateAge(convertToLocalDateViaSqlDate(birthDate),currentDate); + } + + public static String formatDate(LocalDate fecha, String format){ + if(fecha == null || format == null) return null; + return fecha.format(DateTimeFormatter.ofPattern(format)); + } + public static String formatDate(Date fecha, String format){ + return formatDate(convertToLocalDateViaSqlDate(fecha), format); + } + public static DBFile createFile(MultipartFile file) { // Normalize file name String fileName = StringUtils.cleanPath(file.getOriginalFilename()); diff --git a/curriculumsearch/src/main/resources/json/postulante.json b/curriculumsearch/src/main/resources/json/postulante.json index e3f9e2a..34e0467 100644 --- a/curriculumsearch/src/main/resources/json/postulante.json +++ b/curriculumsearch/src/main/resources/json/postulante.json @@ -40,19 +40,19 @@ "tecnologias": [ { "tecnologia": { - "nombre": "JAVA" + "id": 1 }, "nivel": 5 }, { "tecnologia": { - "nombre": "Python" + "id": 2 }, "nivel": 4 }, { "tecnologia": { - "nombre": "C" + "id": 3 }, "nivel": 5 } @@ -99,7 +99,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "Spring" + "id": 4 }, "nivel": 2 } @@ -146,7 +146,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "Django" + "id": 5 }, "nivel": 3 } @@ -193,7 +193,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "Flutter" + "id": 6 }, "nivel": 2 } @@ -240,7 +240,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "Switf" + "id": 3 }, "nivel": 5 } @@ -287,7 +287,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "SL" + "id": 2 }, "nivel": 4 } @@ -334,7 +334,7 @@ "tecnologias": [ { "tecnologia": { - "nombre": "Scala" + "id": 5 }, "nivel": 5 } diff --git a/curriculumsearch/src/main/resources/json/tecnologia.json b/curriculumsearch/src/main/resources/json/tecnologia.json index fb148bf..70e424e 100644 --- a/curriculumsearch/src/main/resources/json/tecnologia.json +++ b/curriculumsearch/src/main/resources/json/tecnologia.json @@ -18,5 +18,17 @@ { "id": 5, "nombre": "spring" + }, + { + "id": 6, + "nombre": "php" + }, + { + "id": 7, + "nombre": "laravel" + }, + { + "id": 8, + "nombre": "sqlserver" } ] \ No newline at end of file diff --git a/curriculumsearch/src/main/webapp/css/formPostulanteStyle.css b/curriculumsearch/src/main/webapp/css/formPostulanteStyle.css index 105dde9..32b1605 100644 --- a/curriculumsearch/src/main/webapp/css/formPostulanteStyle.css +++ b/curriculumsearch/src/main/webapp/css/formPostulanteStyle.css @@ -213,4 +213,9 @@ h4{ } form[name="postulante"]{ color: #ffffff; +} + +.form-check-input:checked { + background-color: #198754; + border-color: #0d6efd; } \ No newline at end of file diff --git a/curriculumsearch/src/main/webapp/jsp/cargos.jsp b/curriculumsearch/src/main/webapp/jsp/cargos.jsp index dad22a0..cfa6c05 100644 --- a/curriculumsearch/src/main/webapp/jsp/cargos.jsp +++ b/curriculumsearch/src/main/webapp/jsp/cargos.jsp @@ -20,40 +20,45 @@ contentType="text/html;charset=UTF-8" language="java" %> Agregar Nuevo Cargo -
- - - - - - - - - +
+ +
+
+
#Cargo
+ - - - - + + - - -
${sta.index+1}${cargo.getNombre()} - Ver Convocatorias - Editar cargo#Cargo
+ + + + + ${sta.index+1} + ${cargo.getNombre()} + + Ver Convocatorias + + Editar cargo + + + + +
+ - - diff --git a/curriculumsearch/src/main/webapp/jsp/convocatorias.jsp b/curriculumsearch/src/main/webapp/jsp/convocatorias.jsp index 120f336..f4a8463 100644 --- a/curriculumsearch/src/main/webapp/jsp/convocatorias.jsp +++ b/curriculumsearch/src/main/webapp/jsp/convocatorias.jsp @@ -2,6 +2,8 @@ <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + @@ -25,12 +27,15 @@ -
- Agregar Nueva Convocatoria - + Agregar Nueva Convocatoria +
${SUCCESS_MESSAGE}
-
- + +
+ +
+
+
@@ -47,9 +52,9 @@ - - - + + + @@ -57,8 +62,9 @@ -
#${sta.index+1} ${convocatoria.getCargo().getNombre()} ${convocatoria.getEstado().getDescripcion()}${convocatoria.getFechaInicio().toString().split(" ")[0]}${convocatoria.getFechaFin().toString().split(" ")[0]}Ver PostulantesVer postulantes
- + +
+
diff --git a/curriculumsearch/src/main/webapp/jsp/detallepostulante.jsp b/curriculumsearch/src/main/webapp/jsp/detallepostulante.jsp index e51cfdc..25a745b 100644 --- a/curriculumsearch/src/main/webapp/jsp/detallepostulante.jsp +++ b/curriculumsearch/src/main/webapp/jsp/detallepostulante.jsp @@ -145,6 +145,9 @@ + diff --git a/curriculumsearch/src/main/webapp/jsp/dp.jsp b/curriculumsearch/src/main/webapp/jsp/dp.jsp new file mode 100644 index 0000000..5d0a8fd --- /dev/null +++ b/curriculumsearch/src/main/webapp/jsp/dp.jsp @@ -0,0 +1,16 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> +<%@ taglib uri="http://kwonnam.pe.kr/jsp/template-inheritance" prefix="layout"%> +<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> + + + + +

+ DETALLE POSTULANTE +

+ ${postulante.nombre} ${postulante.apellido} +
+
+ diff --git a/curriculumsearch/src/main/webapp/jsp/postulante-form.jsp b/curriculumsearch/src/main/webapp/jsp/postulante-form.jsp index 38c588e..55798c9 100644 --- a/curriculumsearch/src/main/webapp/jsp/postulante-form.jsp +++ b/curriculumsearch/src/main/webapp/jsp/postulante-form.jsp @@ -217,6 +217,27 @@ + +
+
+ +
+
+ +

Otras Tecnologias

+
+
+ +
+ +
+ +
+ + + +
+

@@ -238,7 +259,7 @@
-

Referencia Personal

+

Referencias Personales

@@ -371,7 +392,7 @@