main
elmer-20 1 month ago
parent 1bfa6a6ade
commit e6343ce179

@ -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


@ -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


@ -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());
}
}
}

@ -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());
}
}
}

@ -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<String> 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());
}
}
}

@ -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<ResultadoExamen> 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<List<ResultadoExamen>> ranking(
@PathVariable Long procesoId) {
List<ResultadoExamen> ranking =
resultadoService.obtenerRanking(procesoId);
return ResponseEntity.ok(ranking);
}
}

@ -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;
}

@ -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;

@ -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<CarpetaExamen, Long> {
List<CarpetaExamen> findByProcesoIdAndAreaId(Long procesoId, Long areaId);
Optional<CarpetaExamen> findByProcesoIdAndAreaIdAndTipo(
Long procesoId,
Long areaId,
String tipo
);
}

@ -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<ClaveExamen, Long> {
// Busca una clave por proceso, área e idExamen
Optional<ClaveExamen> findByProcesoIdAndAreaIdAndIdExamen(Long procesoId, Long areaId, String idExamen);
}

@ -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<Inscripcion, Long> {
// 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<Inscripcion> findByPostulanteAndProceso(Postulante postulante, Proceso proceso);
// Buscar inscripción directamente por DNI y proceso
Optional<Inscripcion> findByPostulanteDniAndProcesoId(String dni, Long procesoId);
}

@ -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<ResultadoExamen, Long> {
Optional<ResultadoExamen> 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<ResultadoExamen> 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<ResultadoExamen> findRankingByProceso(Long procesoId);
}

@ -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);
}
}

@ -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<String, String> tipoMap = new HashMap<>();
List<String> 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<String> lineasClaves = Files.readAllLines(Paths.get(archivoClaves.getRuta()));
List<ClaveExamen> 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();
}
}

@ -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<String, String> tipoMap = new HashMap<>();
List<String> 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<String> lineasClaves = Files.readAllLines(Paths.get(archivoClaves.getRuta()));
List<ClaveExamen> 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();
}
}

@ -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<Inscripcion> 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();
}
}

@ -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<ResultadoExamen> obtenerResultado(String dni, Long procesoId) {
return resultadoRepo.findByDniAndProceso(dni, procesoId);
}
// Ranking por proceso
public List<ResultadoExamen> obtenerRanking(Long procesoId) {
return resultadoRepo.findRankingByProceso(procesoId);
}
}
Loading…
Cancel
Save