From e6343ce179057d479f69e886806f960f7bd113c5 Mon Sep 17 00:00:00 2001 From: elmer-20 <80175046+elmer-20@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:27:15 -0500 Subject: [PATCH] cddcdcd --- examenes/1/1/clavebioid.dat | 6 + examenes/1/1/clavebioresp.dat | 6 + .../controller/CarpetaExamenController.java | 44 +++++ .../controller/ClaveExamenController.java | 34 ++++ .../controller/ExcelResultadoController.java | 40 +++++ .../controller/ResultadoController.java | 51 ++++++ .../ingresantes/entity/ClaveExamen.java | 33 ++++ .../ingresantes/entity/ResultadoExamen.java | 15 +- .../repository/CarpetaExamenRepository.java | 8 + .../repository/ClaveExamenRepository.java | 15 ++ .../repository/InscripcionRepository.java | 10 +- .../repository/ResultadoExamenRepository.java | 24 ++- .../service/CarpetaExamenService.java | 68 ++++++++ .../service/ClaveExamenService.java | 98 +++++++++++ .../service/ClaveExamenServiceBloque.java | 122 +++++++++++++ .../service/ExcelResultadoService.java | 162 ++++++++++++++++++ .../ingresantes/service/ResultadoService.java | 30 ++++ 17 files changed, 761 insertions(+), 5 deletions(-) create mode 100644 examenes/1/1/clavebioid.dat create mode 100644 examenes/1/1/clavebioresp.dat create mode 100644 src/main/java/com/service/ingresantes/controller/CarpetaExamenController.java create mode 100644 src/main/java/com/service/ingresantes/controller/ClaveExamenController.java create mode 100644 src/main/java/com/service/ingresantes/controller/ExcelResultadoController.java create mode 100644 src/main/java/com/service/ingresantes/controller/ResultadoController.java create mode 100644 src/main/java/com/service/ingresantes/entity/ClaveExamen.java create mode 100644 src/main/java/com/service/ingresantes/repository/ClaveExamenRepository.java create mode 100644 src/main/java/com/service/ingresantes/service/CarpetaExamenService.java create mode 100644 src/main/java/com/service/ingresantes/service/ClaveExamenService.java create mode 100644 src/main/java/com/service/ingresantes/service/ClaveExamenServiceBloque.java create mode 100644 src/main/java/com/service/ingresantes/service/ExcelResultadoService.java create mode 100644 src/main/java/com/service/ingresantes/service/ResultadoService.java diff --git a/examenes/1/1/clavebioid.dat b/examenes/1/1/clavebioid.dat new file mode 100644 index 0000000..7b892e3 --- /dev/null +++ b/examenes/1/1/clavebioid.dat @@ -0,0 +1,6 @@ +227000001001011026001 5310 #0001 N 074151P +227000002001011026001 5310 #0001 N 074153Q +227000003001011026001 5310 #0001 N 074148R +227000004001011026001 5310 #0001 N 074147S +227000005001011026001 5310 #0001 N 074154T + \ No newline at end of file diff --git a/examenes/1/1/clavebioresp.dat b/examenes/1/1/clavebioresp.dat new file mode 100644 index 0000000..d0a1ac5 --- /dev/null +++ b/examenes/1/1/clavebioresp.dat @@ -0,0 +1,6 @@ +228000001001011026001 5310 #0001 N 074151BDBDCEDACCCBDDAADCDEACEBBEDDDBEEAADCECAADBADBABCDDCAEEEEBCBA +228000002001011026001 5310 #0001 N 074153ACBADAEAABDECECACBEDEDBCADDCEDDDCADDDBCDBBAAADBADBEBCBDABACB +228000003001011026001 5310 #0001 N 074148AAADBBCACBDEEEBCCDEAADADADDABAAABDDCCAECCCCBCCEDADDACDCDACDE +228000004001011026001 5310 #0001 N 074147BBDCDBDDCBACDBAAEBBCBEABECACACECDCEBDBBBBDDECAABACEEDECDCEEA +228000005001011026001 5310 #0001 N 074154CEDBBAAAABECDDEBEDCABACBEECCEACCCCDAEABCAAAAEEDCDCCDEBECDDEE + \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/controller/CarpetaExamenController.java b/src/main/java/com/service/ingresantes/controller/CarpetaExamenController.java new file mode 100644 index 0000000..fc9157c --- /dev/null +++ b/src/main/java/com/service/ingresantes/controller/CarpetaExamenController.java @@ -0,0 +1,44 @@ +package com.service.ingresantes.controller; + +import com.service.ingresantes.service.CarpetaExamenService; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/api/examen") +@CrossOrigin("*") +public class CarpetaExamenController { + + private final CarpetaExamenService carpetaService; + + public CarpetaExamenController(CarpetaExamenService carpetaService) { + this.carpetaService = carpetaService; + } + + @PostMapping("/upload") + public ResponseEntity subirArchivo( + @RequestParam("file") MultipartFile file, + @RequestParam("tipo") String tipo, + @RequestParam("procesoId") Long procesoId, + @RequestParam("areaId") Long areaId) { + + try { + + if (file.isEmpty()) { + return ResponseEntity.badRequest().body("Archivo vacío"); + } + + carpetaService.subirArchivo(file, tipo, procesoId, areaId); + + return ResponseEntity.ok("Archivo .dat subido correctamente"); + + } catch (Exception e) { + + return ResponseEntity + .badRequest() + .body("Error al subir archivo: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/controller/ClaveExamenController.java b/src/main/java/com/service/ingresantes/controller/ClaveExamenController.java new file mode 100644 index 0000000..dd62313 --- /dev/null +++ b/src/main/java/com/service/ingresantes/controller/ClaveExamenController.java @@ -0,0 +1,34 @@ +package com.service.ingresantes.controller; + +import com.service.ingresantes.service.ClaveExamenService; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/claves") +@CrossOrigin("*") +public class ClaveExamenController { + + private final ClaveExamenService claveService; + + public ClaveExamenController(ClaveExamenService claveService) { + this.claveService = claveService; + } + + @PostMapping("/procesar") + public ResponseEntity procesarClaves( + @RequestParam("procesoId") Long procesoId, + @RequestParam("areaId") Long areaId) { + + try { + int guardadas = claveService.procesarClaves(procesoId, areaId); + return ResponseEntity.ok("Claves procesadas y guardadas correctamente: " + guardadas); + } catch (Exception e) { + return ResponseEntity + .badRequest() + .body("Error al procesar claves: " + e.getMessage()); + } + } + +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/controller/ExcelResultadoController.java b/src/main/java/com/service/ingresantes/controller/ExcelResultadoController.java new file mode 100644 index 0000000..89ccf2e --- /dev/null +++ b/src/main/java/com/service/ingresantes/controller/ExcelResultadoController.java @@ -0,0 +1,40 @@ +package com.service.ingresantes.controller; + +import com.service.ingresantes.service.ExcelResultadoService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +@RestController +@RequestMapping("/api/excel") +@CrossOrigin("*") +public class ExcelResultadoController { + + private final ExcelResultadoService excelResultadoService; + + public ExcelResultadoController(ExcelResultadoService excelResultadoService) { + this.excelResultadoService = excelResultadoService; + } + + @PostMapping("/upload-resultados") + public ResponseEntity uploadResultados( + @RequestParam("file") MultipartFile file) { + + if (file.isEmpty()) { + return ResponseEntity.badRequest().body("El archivo está vacío"); + } + + try { + + excelResultadoService.importarExcelResultados(file); + + return ResponseEntity.ok("Archivo de resultados procesado correctamente"); + + } catch (Exception e) { + + return ResponseEntity + .badRequest() + .body("Error al procesar el archivo: " + e.getMessage()); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/controller/ResultadoController.java b/src/main/java/com/service/ingresantes/controller/ResultadoController.java new file mode 100644 index 0000000..94d5a2c --- /dev/null +++ b/src/main/java/com/service/ingresantes/controller/ResultadoController.java @@ -0,0 +1,51 @@ +package com.service.ingresantes.controller; + +import com.service.ingresantes.entity.ResultadoExamen; +import com.service.ingresantes.service.ResultadoService; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Optional; + +@RestController +@RequestMapping("/api/resultados") +@CrossOrigin("*") +public class ResultadoController { + + private final ResultadoService resultadoService; + + public ResultadoController(ResultadoService resultadoService) { + this.resultadoService = resultadoService; + } + + // Buscar resultado por DNI y proceso + @GetMapping("/{dni}/{procesoId}") + public ResponseEntity obtenerResultado( + @PathVariable String dni, + @PathVariable Long procesoId) { + + Optional resultado = + resultadoService.obtenerResultado(dni, procesoId); + + if (resultado.isEmpty()) { + + return ResponseEntity + .badRequest() + .body("No se encontró resultado para ese DNI y proceso"); + } + + return ResponseEntity.ok(resultado.get()); + } + + // Ranking del proceso + @GetMapping("/ranking/{procesoId}") + public ResponseEntity> ranking( + @PathVariable Long procesoId) { + + List ranking = + resultadoService.obtenerRanking(procesoId); + + return ResponseEntity.ok(ranking); + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/entity/ClaveExamen.java b/src/main/java/com/service/ingresantes/entity/ClaveExamen.java new file mode 100644 index 0000000..1c9176b --- /dev/null +++ b/src/main/java/com/service/ingresantes/entity/ClaveExamen.java @@ -0,0 +1,33 @@ +package com.service.ingresantes.entity; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name = "clave_examen") +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ClaveExamen { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "id_examen") + private String idExamen; + + private String tipo; + + @Column(columnDefinition = "TEXT") + private String clave; + + @ManyToOne + @JoinColumn(name = "proceso_id") + private Proceso proceso; + + @ManyToOne + @JoinColumn(name = "area_id") + private Area area; +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/entity/ResultadoExamen.java b/src/main/java/com/service/ingresantes/entity/ResultadoExamen.java index b763ec2..b44477d 100644 --- a/src/main/java/com/service/ingresantes/entity/ResultadoExamen.java +++ b/src/main/java/com/service/ingresantes/entity/ResultadoExamen.java @@ -5,21 +5,30 @@ import lombok.Data; @Data @Entity -@Table(name = "resultado_examen") +@Table( + name = "resultado_examen", + uniqueConstraints = { + @UniqueConstraint(columnNames = {"inscripcion_id"}) + } +) public class ResultadoExamen { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - // RELACION CON INSCRIPCION @OneToOne @JoinColumn(name = "inscripcion_id", nullable = false) private Inscripcion inscripcion; + @ManyToOne + @JoinColumn(name = "proceso_id", nullable = false) + private Proceso proceso; + private Double puntaje; - private Boolean apto; + @Column(length = 2) + private String apto; // SI / NO / CL private String obs; diff --git a/src/main/java/com/service/ingresantes/repository/CarpetaExamenRepository.java b/src/main/java/com/service/ingresantes/repository/CarpetaExamenRepository.java index 3648c7b..a716411 100644 --- a/src/main/java/com/service/ingresantes/repository/CarpetaExamenRepository.java +++ b/src/main/java/com/service/ingresantes/repository/CarpetaExamenRepository.java @@ -2,10 +2,18 @@ package com.service.ingresantes.repository; import com.service.ingresantes.entity.CarpetaExamen; import org.springframework.data.jpa.repository.JpaRepository; + import java.util.List; +import java.util.Optional; public interface CarpetaExamenRepository extends JpaRepository { List findByProcesoIdAndAreaId(Long procesoId, Long areaId); + Optional findByProcesoIdAndAreaIdAndTipo( + Long procesoId, + Long areaId, + String tipo + ); + } \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/repository/ClaveExamenRepository.java b/src/main/java/com/service/ingresantes/repository/ClaveExamenRepository.java new file mode 100644 index 0000000..c4d5b6d --- /dev/null +++ b/src/main/java/com/service/ingresantes/repository/ClaveExamenRepository.java @@ -0,0 +1,15 @@ +package com.service.ingresantes.repository; + +import com.service.ingresantes.entity.ClaveExamen; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ClaveExamenRepository extends JpaRepository { + + // Busca una clave por proceso, área e idExamen + Optional findByProcesoIdAndAreaIdAndIdExamen(Long procesoId, Long areaId, String idExamen); + +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/repository/InscripcionRepository.java b/src/main/java/com/service/ingresantes/repository/InscripcionRepository.java index 1e5201b..8854560 100644 --- a/src/main/java/com/service/ingresantes/repository/InscripcionRepository.java +++ b/src/main/java/com/service/ingresantes/repository/InscripcionRepository.java @@ -5,9 +5,17 @@ import com.service.ingresantes.entity.Postulante; import com.service.ingresantes.entity.Proceso; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.Optional; + public interface InscripcionRepository extends JpaRepository { - // Método para verificar si existe una inscripción de un postulante a un proceso + // Verifica si ya existe inscripción de un postulante a un proceso boolean existsByPostulanteAndProceso(Postulante postulante, Proceso proceso); + // Buscar inscripción por postulante y proceso + Optional findByPostulanteAndProceso(Postulante postulante, Proceso proceso); + + // Buscar inscripción directamente por DNI y proceso + Optional findByPostulanteDniAndProcesoId(String dni, Long procesoId); + } \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/repository/ResultadoExamenRepository.java b/src/main/java/com/service/ingresantes/repository/ResultadoExamenRepository.java index b1b5419..e4c5d79 100644 --- a/src/main/java/com/service/ingresantes/repository/ResultadoExamenRepository.java +++ b/src/main/java/com/service/ingresantes/repository/ResultadoExamenRepository.java @@ -2,10 +2,32 @@ package com.service.ingresantes.repository; import com.service.ingresantes.entity.ResultadoExamen; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; import java.util.Optional; public interface ResultadoExamenRepository extends JpaRepository { - Optional findByInscripcionId(Long inscripcionId); + boolean existsByInscripcionId(Long inscripcionId); + + // Buscar resultado por DNI y proceso + @Query(""" + SELECT r FROM ResultadoExamen r + JOIN r.inscripcion i + JOIN i.postulante p + WHERE p.dni = :dni + AND i.proceso.id = :procesoId + """) + Optional findByDniAndProceso(String dni, Long procesoId); + + // Ranking por proceso + @Query(""" + SELECT r FROM ResultadoExamen r + JOIN r.inscripcion i + WHERE i.proceso.id = :procesoId + ORDER BY r.puntaje DESC + """) + List findRankingByProceso(Long procesoId); } \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/service/CarpetaExamenService.java b/src/main/java/com/service/ingresantes/service/CarpetaExamenService.java new file mode 100644 index 0000000..3f8f38e --- /dev/null +++ b/src/main/java/com/service/ingresantes/service/CarpetaExamenService.java @@ -0,0 +1,68 @@ +package com.service.ingresantes.service; + +import com.service.ingresantes.entity.Area; +import com.service.ingresantes.entity.CarpetaExamen; +import com.service.ingresantes.entity.Proceso; +import com.service.ingresantes.repository.AreaRepository; +import com.service.ingresantes.repository.CarpetaExamenRepository; +import com.service.ingresantes.repository.ProcesoRepository; + +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; + +@Service +public class CarpetaExamenService { + + private final CarpetaExamenRepository carpetaRepo; + private final ProcesoRepository procesoRepo; + private final AreaRepository areaRepo; + + public CarpetaExamenService( + CarpetaExamenRepository carpetaRepo, + ProcesoRepository procesoRepo, + AreaRepository areaRepo) { + + this.carpetaRepo = carpetaRepo; + this.procesoRepo = procesoRepo; + this.areaRepo = areaRepo; + } + + public void subirArchivo( + MultipartFile file, + String tipo, + Long procesoId, + Long areaId) throws Exception { + + Proceso proceso = procesoRepo.findById(procesoId) + .orElseThrow(() -> new RuntimeException("Proceso no existe")); + + Area area = areaRepo.findById(areaId) + .orElseThrow(() -> new RuntimeException("Area no existe")); + + String rutaBase = System.getProperty("user.dir") + + "/examenes/" + procesoId + "/" + areaId + "/"; + + File carpeta = new File(rutaBase); + + if (!carpeta.exists()) { + carpeta.mkdirs(); + } + + String nombreArchivo = file.getOriginalFilename(); + + File destino = new File(rutaBase + nombreArchivo); + + file.transferTo(destino); + + CarpetaExamen carpetaExamen = CarpetaExamen.builder() + .tipo(tipo) + .ruta(destino.getAbsolutePath()) + .proceso(proceso) + .area(area) + .build(); + + carpetaRepo.save(carpetaExamen); + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/service/ClaveExamenService.java b/src/main/java/com/service/ingresantes/service/ClaveExamenService.java new file mode 100644 index 0000000..642f1f8 --- /dev/null +++ b/src/main/java/com/service/ingresantes/service/ClaveExamenService.java @@ -0,0 +1,98 @@ +package com.service.ingresantes.service; + +import com.service.ingresantes.entity.CarpetaExamen; +import com.service.ingresantes.entity.ClaveExamen; +import com.service.ingresantes.entity.Proceso; +import com.service.ingresantes.entity.Area; +import com.service.ingresantes.repository.CarpetaExamenRepository; +import com.service.ingresantes.repository.ClaveExamenRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +@Service +public class ClaveExamenService { + + private final CarpetaExamenRepository carpetaRepo; + private final ClaveExamenRepository claveRepo; + + public ClaveExamenService( + CarpetaExamenRepository carpetaRepo, + ClaveExamenRepository claveRepo) { + this.carpetaRepo = carpetaRepo; + this.claveRepo = claveRepo; + } + + @Transactional + public int procesarClaves(Long procesoId, Long areaId) throws Exception { + + // 1️⃣ Buscar archivos + CarpetaExamen archivoClaveId = carpetaRepo + .findByProcesoIdAndAreaIdAndTipo(procesoId, areaId, "claves_id") + .orElseThrow(() -> new RuntimeException("No existe archivo clave_id")); + + CarpetaExamen archivoClaves = carpetaRepo + .findByProcesoIdAndAreaIdAndTipo(procesoId, areaId, "claves") + .orElseThrow(() -> new RuntimeException("No existe archivo claves")); + + // 2️⃣ Leer archivo claves_id → idExamen + tipo + Map tipoMap = new HashMap<>(); + List lineasId = Files.readAllLines(Paths.get(archivoClaveId.getRuta())); + for (String linea : lineasId) { + linea = linea.trim(); + if (linea.length() < 7) continue; + + String ultimos7 = linea.substring(linea.length() - 7); + String idExamen = ultimos7.substring(0, 6); + String tipo = ultimos7.substring(6, 7); + tipoMap.put(idExamen, tipo); + } + + // 3️⃣ Leer archivo claves + List lineasClaves = Files.readAllLines(Paths.get(archivoClaves.getRuta())); + List listaGuardar = new ArrayList<>(); + + Proceso proceso = new Proceso(); + proceso.setId(procesoId); + Area area = new Area(); + area.setId(areaId); + + for (String linea : lineasClaves) { + linea = linea.trim(); + if (linea.length() < 7) continue; + + int posId = linea.indexOf("074"); // buscar inicio del idExamen + if (posId == -1 || linea.length() < posId + 6) continue; + + String idExamen = linea.substring(posId, posId + 6); + String clave = linea.substring(posId + 6); // todo lo demás + + String tipo = tipoMap.get(idExamen); + if (tipo == null) continue; + + // ❌ Solo guardar si no existe en la base de datos + boolean existe = claveRepo.findByProcesoIdAndAreaIdAndIdExamen(procesoId, areaId, idExamen).isPresent(); + if (existe) continue; + + ClaveExamen c = ClaveExamen.builder() + .idExamen(idExamen) + .tipo(tipo) + .clave(clave) + .proceso(proceso) + .area(area) + .build(); + + listaGuardar.add(c); + } + + // 4️⃣ Guardar en DB + claveRepo.saveAll(listaGuardar); + + System.out.println("Claves procesadas y guardadas: " + listaGuardar.size()); + return listaGuardar.size(); + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/service/ClaveExamenServiceBloque.java b/src/main/java/com/service/ingresantes/service/ClaveExamenServiceBloque.java new file mode 100644 index 0000000..c0c91c6 --- /dev/null +++ b/src/main/java/com/service/ingresantes/service/ClaveExamenServiceBloque.java @@ -0,0 +1,122 @@ +package com.service.ingresantes.service; + +import com.service.ingresantes.entity.CarpetaExamen; +import com.service.ingresantes.entity.ClaveExamen; +import com.service.ingresantes.entity.Proceso; +import com.service.ingresantes.entity.Area; +import com.service.ingresantes.repository.CarpetaExamenRepository; +import com.service.ingresantes.repository.ClaveExamenRepository; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.*; + +@Service +public class ClaveExamenServiceBloque { + + private final CarpetaExamenRepository carpetaRepo; + private final ClaveExamenRepository claveRepo; + + public ClaveExamenServiceBloque( + CarpetaExamenRepository carpetaRepo, + ClaveExamenRepository claveRepo) { + this.carpetaRepo = carpetaRepo; + this.claveRepo = claveRepo; + } + + @Transactional + public int procesarClaves(Long procesoId, Long areaId) throws Exception { + + // 1️⃣ Buscar archivos en CarpetaExamen + CarpetaExamen archivoClaveId = carpetaRepo + .findByProcesoIdAndAreaIdAndTipo(procesoId, areaId, "claves_id") + .orElseThrow(() -> new RuntimeException("No existe archivo clave_id")); + + CarpetaExamen archivoClaves = carpetaRepo + .findByProcesoIdAndAreaIdAndTipo(procesoId, areaId, "claves") + .orElseThrow(() -> new RuntimeException("No existe archivo claves")); + + // 2️⃣ Map para idExamen -> tipo + Map tipoMap = new HashMap<>(); + List lineasId = Files.readAllLines(Paths.get(archivoClaveId.getRuta())); + + for (String linea : lineasId) { + linea = linea.trim(); + if (linea.length() < 7) continue; + + // Tomamos los últimos 7 caracteres de la línea + String ultimos7 = linea.substring(linea.length() - 7); + String idExamen = ultimos7.substring(0, 6); + String tipo = ultimos7.substring(6, 7); + tipoMap.put(idExamen, tipo); + } + + // 3️⃣ Leer archivo claves + List lineasClaves = Files.readAllLines(Paths.get(archivoClaves.getRuta())); + List listaGuardar = new ArrayList<>(); + + Proceso proceso = new Proceso(); + proceso.setId(procesoId); + Area area = new Area(); + area.setId(areaId); + + int descartadas = 0; + + for (String linea : lineasClaves) { + linea = linea.trim(); + if (linea.length() < 7) { + descartadas++; + continue; + } + + // Buscar idExamen dentro de la línea: 6 dígitos seguidos de letra + // Regex simple: 6 dígitos + 1 letra + String idExamen = null; + String clave = null; + + for (int i = 0; i < linea.length() - 6; i++) { + String candidato = linea.substring(i, i + 7); + if (candidato.matches("\\d{6}[A-Z]")) { // 6 números + 1 letra + idExamen = candidato.substring(0, 6); + // Clave = todo lo que sigue después de idExamen + tipo + clave = linea.substring(i + 7); + break; + } + } + + if (idExamen == null || clave == null) { + descartadas++; + continue; + } + + String tipo = tipoMap.get(idExamen); + if (tipo == null) { + descartadas++; + continue; + } + + ClaveExamen c = ClaveExamen.builder() + .idExamen(idExamen) + .tipo(tipo) + .clave(clave) + .proceso(proceso) + .area(area) + .build(); + + listaGuardar.add(c); + } + + // 4️⃣ Guardar en DB + claveRepo.saveAll(listaGuardar); + + // 5️⃣ Reporte + System.out.println("Total líneas leídas: " + lineasClaves.size()); + System.out.println("Claves procesadas y guardadas: " + listaGuardar.size()); + System.out.println("Claves descartadas: " + descartadas); + + return listaGuardar.size(); + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/service/ExcelResultadoService.java b/src/main/java/com/service/ingresantes/service/ExcelResultadoService.java new file mode 100644 index 0000000..d58548c --- /dev/null +++ b/src/main/java/com/service/ingresantes/service/ExcelResultadoService.java @@ -0,0 +1,162 @@ +package com.service.ingresantes.service; + +import com.service.ingresantes.entity.Inscripcion; +import com.service.ingresantes.entity.ResultadoExamen; +import com.service.ingresantes.repository.InscripcionRepository; +import com.service.ingresantes.repository.ResultadoExamenRepository; + +import org.apache.poi.ss.usermodel.*; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import jakarta.transaction.Transactional; +import java.io.InputStream; +import java.util.Optional; + +@Service +public class ExcelResultadoService { + + private final InscripcionRepository inscripcionRepo; + private final ResultadoExamenRepository resultadoRepo; + + public ExcelResultadoService( + InscripcionRepository inscripcionRepo, + ResultadoExamenRepository resultadoRepo) { + + this.inscripcionRepo = inscripcionRepo; + this.resultadoRepo = resultadoRepo; + } + + private String getCellString(Cell cell) { + + if (cell == null) return ""; + + switch (cell.getCellType()) { + + case STRING: + return cell.getStringCellValue().trim(); + + case NUMERIC: + return String.valueOf((long) cell.getNumericCellValue()); + + default: + return ""; + } + } + + private Double getCellDouble(Cell cell) { + + if (cell == null) return null; + + if (cell.getCellType() == CellType.NUMERIC) { + return cell.getNumericCellValue(); + } + + if (cell.getCellType() == CellType.STRING) { + return Double.parseDouble(cell.getStringCellValue()); + } + + return null; + } + + private Integer getCellInteger(Cell cell) { + + if (cell == null) return null; + + if (cell.getCellType() == CellType.NUMERIC) { + return (int) cell.getNumericCellValue(); + } + + if (cell.getCellType() == CellType.STRING) { + return Integer.parseInt(cell.getStringCellValue()); + } + + return null; + } + + @Transactional + public void importarExcelResultados(MultipartFile file) throws Exception { + + InputStream is = file.getInputStream(); + Workbook workbook = WorkbookFactory.create(is); + Sheet sheet = workbook.getSheetAt(0); + + for (Row row : sheet) { + + if (row.getRowNum() == 0) continue; + + try { + + String dni = getCellString(row.getCell(0)); + String procesoStr = getCellString(row.getCell(1)); + + if (dni.isEmpty() || procesoStr.isEmpty()) { + continue; + } + + Long procesoId = Long.parseLong(procesoStr); + + Optional inscripcionOpt = + inscripcionRepo.findByPostulanteDniAndProcesoId(dni, procesoId); + + if (inscripcionOpt.isEmpty()) { + + System.out.println("No existe inscripción -> DNI " + dni); + continue; + } + + Inscripcion inscripcion = inscripcionOpt.get(); + + if (resultadoRepo.existsByInscripcionId(inscripcion.getId())) { + + System.out.println("Resultado ya existe -> DNI " + dni); + continue; + } + + Double puntaje = getCellDouble(row.getCell(2)); + String apto = getCellString(row.getCell(3)); + String obs = getCellString(row.getCell(4)); + + String idExamen = getCellString(row.getCell(5)); + String litho = getCellString(row.getCell(6)); + String numLectura = getCellString(row.getCell(7)); + String tipo = getCellString(row.getCell(8)); + String calificar = getCellString(row.getCell(9)); + String aula = getCellString(row.getCell(10)); + String respuestas = getCellString(row.getCell(11)); + + Integer puesto = getCellInteger(row.getCell(12)); + + ResultadoExamen resultado = new ResultadoExamen(); + + resultado.setInscripcion(inscripcion); + resultado.setProceso(inscripcion.getProceso()); + + resultado.setPuntaje(puntaje); + resultado.setApto(apto); + resultado.setObs(obs); + + resultado.setIdExamen(idExamen); + resultado.setLitho(litho); + resultado.setNumLectura(numLectura); + resultado.setTipo(tipo); + resultado.setCalificar(calificar); + resultado.setAula(aula); + resultado.setRespuestas(respuestas); + + resultado.setPuesto(puesto); + + resultadoRepo.save(resultado); + + System.out.println("Resultado guardado -> DNI " + dni); + + } catch (Exception e) { + + System.out.println("Error fila " + row.getRowNum() + " -> " + e.getMessage()); + } + } + + workbook.close(); + is.close(); + } +} \ No newline at end of file diff --git a/src/main/java/com/service/ingresantes/service/ResultadoService.java b/src/main/java/com/service/ingresantes/service/ResultadoService.java new file mode 100644 index 0000000..d127b53 --- /dev/null +++ b/src/main/java/com/service/ingresantes/service/ResultadoService.java @@ -0,0 +1,30 @@ +package com.service.ingresantes.service; + +import com.service.ingresantes.entity.ResultadoExamen; +import com.service.ingresantes.repository.ResultadoExamenRepository; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +public class ResultadoService { + + private final ResultadoExamenRepository resultadoRepo; + + public ResultadoService(ResultadoExamenRepository resultadoRepo) { + this.resultadoRepo = resultadoRepo; + } + + // Buscar resultado por DNI y proceso + public Optional obtenerResultado(String dni, Long procesoId) { + + return resultadoRepo.findByDniAndProceso(dni, procesoId); + } + + // Ranking por proceso + public List obtenerRanking(Long procesoId) { + + return resultadoRepo.findRankingByProceso(procesoId); + } +} \ No newline at end of file