|
|
@ -0,0 +1,253 @@ |
|
|
|
|
|
package jumapacelaya.gob.mx.vv.servicio; |
|
|
|
|
|
|
|
|
|
|
|
import java.sql.Connection; |
|
|
|
|
|
import java.sql.PreparedStatement; |
|
|
|
|
|
import java.sql.ResultSet; |
|
|
|
|
|
import java.sql.ResultSetMetaData; |
|
|
|
|
|
import java.sql.SQLException; |
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
|
import java.util.HashMap; |
|
|
|
|
|
import java.util.List; |
|
|
|
|
|
import java.util.Map; |
|
|
|
|
|
import java.util.Random; |
|
|
|
|
|
|
|
|
|
|
|
import javax.sql.DataSource; |
|
|
|
|
|
|
|
|
|
|
|
import jakarta.inject.Singleton; |
|
|
|
|
|
import io.micronaut.transaction.annotation.ReadOnly; |
|
|
|
|
|
import io.micronaut.transaction.annotation.Transactional; |
|
|
|
|
|
import jumapacelaya.gob.mx.vv.dto.citaDTO; |
|
|
|
|
|
import jumapacelaya.gob.mx.vv.dto.horarioDisponibleDTO; |
|
|
|
|
|
import jumapacelaya.gob.mx.vv.dto.tramiteDTO; |
|
|
|
|
|
import jumapacelaya.gob.mx.vv.repositorio.VvRepositorio; |
|
|
|
|
|
|
|
|
|
|
|
@Singleton |
|
|
|
|
|
public class VvServicio { |
|
|
|
|
|
|
|
|
|
|
|
private final DataSource dataSource; |
|
|
|
|
|
|
|
|
|
|
|
public VvServicio(DataSource dataSource) { |
|
|
|
|
|
this.dataSource = dataSource; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Transactional |
|
|
|
|
|
public List<Map<String, Object>> obtenerDiasDisponibles(Integer punto, Integer dias) { |
|
|
|
|
|
List<Map<String, Object>> resultado = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
String query = |
|
|
|
|
|
"with dias as ( " + |
|
|
|
|
|
" select sysdate as hoy, level as diasfaltantes, trunc(sysdate + level) as fechacita " + |
|
|
|
|
|
" from dual connect by level <= ? " + |
|
|
|
|
|
") " + |
|
|
|
|
|
"select count(c.citaid) as citas, " + |
|
|
|
|
|
" to_char(d.fechacita, 'dd/mm/yyyy', 'NLS_DATE_LANGUAGE = SPANISH') as fechacita, " + |
|
|
|
|
|
" to_char(d.fechacita, 'fmDY', 'NLS_DATE_LANGUAGE = SPANISH') || ' ' || " + |
|
|
|
|
|
" to_char(d.fechacita, 'dd/mm/yyyy', 'NLS_DATE_LANGUAGE = SPANISH') as sfechacita " + |
|
|
|
|
|
"from dias d " + |
|
|
|
|
|
"left join appmovcom.citas c on (trunc(c.fechora) = d.fechacita and c.estado in ('S', 'P') and c.puntoid = ?) " + |
|
|
|
|
|
"where d.fechacita not in (select fecha from diasfestivos) " + |
|
|
|
|
|
" and to_char(d.fechacita, 'fmDY', 'NLS_DATE_LANGUAGE = SPANISH') not in ('SÁB', 'DOM') " + |
|
|
|
|
|
"group by d.fechacita " + |
|
|
|
|
|
"order by d.fechacita"; |
|
|
|
|
|
|
|
|
|
|
|
try (Connection connection = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement stmt = connection.prepareStatement(query)) { |
|
|
|
|
|
|
|
|
|
|
|
stmt.setInt(1, dias); |
|
|
|
|
|
stmt.setInt(2, punto); |
|
|
|
|
|
|
|
|
|
|
|
try (ResultSet rs = stmt.executeQuery()) { |
|
|
|
|
|
ResultSetMetaData meta = rs.getMetaData(); |
|
|
|
|
|
int cols = meta.getColumnCount(); |
|
|
|
|
|
|
|
|
|
|
|
while (rs.next()) { |
|
|
|
|
|
Map<String, Object> fila = new HashMap<>(); |
|
|
|
|
|
for (int i = 1; i <= cols; i++) { |
|
|
|
|
|
fila.put(meta.getColumnLabel(i).toLowerCase(), rs.getObject(i)); |
|
|
|
|
|
} |
|
|
|
|
|
resultado.add(fila); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
|
throw new RuntimeException("Error al obtener días disponibles", e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return resultado; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@ReadOnly |
|
|
|
|
|
public List<horarioDisponibleDTO> obtenerHorariosDisponibles(Integer punto, String dia) { |
|
|
|
|
|
List<horarioDisponibleDTO> lista = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
String horarios = "09:30,10:00,10:30,11:00,11:30,12:00,12:30,13:00,13:30,14:00,14:30"; |
|
|
|
|
|
|
|
|
|
|
|
String query = """ |
|
|
|
|
|
with horarios as ( |
|
|
|
|
|
select to_char(fechora, 'hh24:mi', 'NLS_DATE_LANGUAGE = SPANISH') hora |
|
|
|
|
|
from appmovcom.citas |
|
|
|
|
|
where trunc(fechora) = trunc(to_date(?, 'ddmmyyyy')) |
|
|
|
|
|
and puntoid = ? |
|
|
|
|
|
) |
|
|
|
|
|
select column_value horariosdisponibles |
|
|
|
|
|
from table(cobranza.splitvlt(?, ',')) |
|
|
|
|
|
where column_value not in (select * from horarios) |
|
|
|
|
|
order by column_value |
|
|
|
|
|
"""; |
|
|
|
|
|
|
|
|
|
|
|
try (Connection conn = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement ps = conn.prepareStatement(query)) { |
|
|
|
|
|
|
|
|
|
|
|
ps.setString(1, dia); |
|
|
|
|
|
ps.setInt(2, punto); |
|
|
|
|
|
ps.setString(3, horarios); |
|
|
|
|
|
|
|
|
|
|
|
ResultSet rs = ps.executeQuery(); |
|
|
|
|
|
while (rs.next()) { |
|
|
|
|
|
horarioDisponibleDTO dto = new horarioDisponibleDTO(); |
|
|
|
|
|
dto.setHorariosdisponibles(rs.getString("horariosdisponibles")); |
|
|
|
|
|
lista.add(dto); |
|
|
|
|
|
} |
|
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
|
throw new RuntimeException("Error al obtener horarios disponibles", e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return lista; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Transactional |
|
|
|
|
|
public String guardarCita(int puntoId, int tipoTramite, String dia, String horario, String telefono, String email) { |
|
|
|
|
|
String fechaCita = dia + " " + horario; |
|
|
|
|
|
String citaIdExistente = obtenerCitaExistente(puntoId, dia, horario); |
|
|
|
|
|
|
|
|
|
|
|
if (citaIdExistente != null) { |
|
|
|
|
|
return "Ya existe una cita en ese horario. Revisa disponibilidad nuevamente."; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String folioGenerado = generarFolio(); |
|
|
|
|
|
|
|
|
|
|
|
String insertQuery = "INSERT INTO appmovcom.citas (citaid, puntoid, fechora, tipotramid, email, telefono) " + |
|
|
|
|
|
"VALUES (?, ?, TO_DATE(?, 'dd/mm/yyyy hh24:mi'), ?, ?, ?)"; |
|
|
|
|
|
|
|
|
|
|
|
try (Connection connection = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement ps = connection.prepareStatement(insertQuery)) { |
|
|
|
|
|
|
|
|
|
|
|
ps.setString(1, folioGenerado); |
|
|
|
|
|
ps.setInt(2, puntoId); |
|
|
|
|
|
ps.setString(3, fechaCita); |
|
|
|
|
|
ps.setInt(4, tipoTramite); |
|
|
|
|
|
ps.setString(5, email); |
|
|
|
|
|
ps.setString(6, telefono); |
|
|
|
|
|
|
|
|
|
|
|
ps.executeUpdate(); |
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
throw new RuntimeException("Error al guardar cita: " + e.getMessage(), e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return "Se generó la cita con folio " + folioGenerado + " para la oficina " + nombrePunto(puntoId) + |
|
|
|
|
|
" el día " + dia + " a las " + horario + " hrs."; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String obtenerCitaExistente(int puntoId, String dia, String horario) { |
|
|
|
|
|
String query = "SELECT citaid FROM appmovcom.citas WHERE puntoid = ? AND trunc(fechora) = TO_DATE(?, 'dd/mm/yyyy') AND TO_CHAR(fechora, 'hh24:mi') = ?"; |
|
|
|
|
|
try (Connection conn = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement ps = conn.prepareStatement(query)) { |
|
|
|
|
|
|
|
|
|
|
|
ps.setInt(1, puntoId); |
|
|
|
|
|
ps.setString(2, dia); |
|
|
|
|
|
ps.setString(3, horario); |
|
|
|
|
|
|
|
|
|
|
|
try (ResultSet rs = ps.executeQuery()) { |
|
|
|
|
|
if (rs.next()) { |
|
|
|
|
|
return rs.getString("citaid"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
|
|
throw new RuntimeException("Error al verificar cita existente: " + e.getMessage(), e); |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String generarFolio() { |
|
|
|
|
|
String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; |
|
|
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
|
|
Random random = new Random(); |
|
|
|
|
|
while (sb.length() < 7) { |
|
|
|
|
|
sb.append(chars.charAt(random.nextInt(chars.length()))); |
|
|
|
|
|
} |
|
|
|
|
|
return sb.toString(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String nombrePunto(int puntoId) { |
|
|
|
|
|
return switch (puntoId) { |
|
|
|
|
|
case 1 -> "División del Norte"; |
|
|
|
|
|
case 2 -> "Parque Morelos"; |
|
|
|
|
|
case 3 -> "Cañitos"; |
|
|
|
|
|
case 5 -> "Parque Celaya"; |
|
|
|
|
|
default -> "Desconocida"; |
|
|
|
|
|
}; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Transactional |
|
|
|
|
|
public String guardarTramite(tramiteDTO tramite) { |
|
|
|
|
|
String tramiteExistente = obtenerTramite(tramite.getUsuarioId(), tramite.getTipoTramite()); |
|
|
|
|
|
|
|
|
|
|
|
if (tramiteExistente != null) { |
|
|
|
|
|
return "Ya hay un trámite registrado para este usuario y tipo. Revisa tu email para dar seguimiento."; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
String folio = generarFolio(); |
|
|
|
|
|
|
|
|
|
|
|
String insertQuery = """ |
|
|
|
|
|
INSERT INTO appmovcom.tramites ( |
|
|
|
|
|
tramiteid, tipotramid, usuarioid, email, telefono, estatus, predioid |
|
|
|
|
|
) VALUES ( |
|
|
|
|
|
?, ?, ?, (SELECT email FROM appmovcom.usuarios WHERE usuarioid = ?), ?, 'NUEVO', ? |
|
|
|
|
|
) |
|
|
|
|
|
"""; |
|
|
|
|
|
|
|
|
|
|
|
try (Connection conn = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement ps = conn.prepareStatement(insertQuery)) { |
|
|
|
|
|
|
|
|
|
|
|
ps.setString(1, folio); |
|
|
|
|
|
ps.setInt(2, tramite.getTipoTramite()); |
|
|
|
|
|
ps.setInt(3, tramite.getUsuarioId()); |
|
|
|
|
|
ps.setInt(4, tramite.getUsuarioId()); |
|
|
|
|
|
ps.setString(5, tramite.getTelefono()); |
|
|
|
|
|
ps.setLong(6, tramite.getPredioId()); |
|
|
|
|
|
|
|
|
|
|
|
ps.executeUpdate(); |
|
|
|
|
|
|
|
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
|
throw new RuntimeException("Error al guardar trámite: " + e.getMessage(), e); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Envío de correo (si lo deseas activar más adelante) |
|
|
|
|
|
// enviaCorreo(folio, "G"); |
|
|
|
|
|
|
|
|
|
|
|
return "Se generó el Trámite con folio " + folio + ". Se te enviará un correo con la información necesaria."; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private String obtenerTramite(int usuarioId, int tipoTramite) { |
|
|
|
|
|
String query = "SELECT tramiteid FROM appmovcom.tramites WHERE usuarioid = ? AND tipotramid = ?"; |
|
|
|
|
|
try (Connection conn = dataSource.getConnection(); |
|
|
|
|
|
PreparedStatement ps = conn.prepareStatement(query)) { |
|
|
|
|
|
|
|
|
|
|
|
ps.setInt(1, usuarioId); |
|
|
|
|
|
ps.setInt(2, tipoTramite); |
|
|
|
|
|
|
|
|
|
|
|
try (ResultSet rs = ps.executeQuery()) { |
|
|
|
|
|
if (rs.next()) { |
|
|
|
|
|
return rs.getString("tramiteid"); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} catch (SQLException e) { |
|
|
|
|
|
throw new RuntimeException("Error al verificar trámite existente: " + e.getMessage(), e); |
|
|
|
|
|
} |
|
|
|
|
|
return null; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |