Exemple #1
0
 public static int getNumeroExpulsiones(Alumno alumno, GregorianCalendar fecha) {
   int ret = 0;
   PreparedStatement st = null;
   ResultSet res = null;
   try {
     // Tenemos que ver si hay expulsiones para ese alumno
     st =
         (PreparedStatement)
             MaimonidesApp.getApplication()
                 .getConector()
                 .getConexion()
                 .prepareStatement(
                     "SELECT count(*) FROM expulsiones WHERE alumno_id=? AND fecha<=?");
     st.setInt(1, alumno.getId());
     st.setDate(2, new java.sql.Date(fecha.getTimeInMillis()));
     res = st.executeQuery();
     if (res.next()) {
       ret = res.getInt(1);
     }
   } catch (SQLException ex) {
     Logger.getLogger(Expulsion.class.getName()).log(Level.SEVERE, null, ex);
   }
   Obj.cerrar(st, res);
   return ret;
 }
Exemple #2
0
 public void setAlumno(Alumno alumno) {
   this.alumno = null;
   lInfoAlumno.setText("");
   // De primeras ponemos todos los apoyos a false
   for (int hora = 0; hora < 6; hora++) {
     for (int dia = 0; dia < 5; dia++) {
       tabla.getModel().setValueAt(false, hora, dia + 1);
     }
   }
   // Sacamos todos sus apoyos
   if (alumno != null) {
     lInfoAlumno.setText(alumno.getNombreFormateado());
     try {
       String sql =
           "SELECT distinct h.dia,h.hora FROM horarios_ AS h JOIN apoyos_alumnos AS aa ON aa.horario_id=h.id WHERE aa.alumno_id=? ";
       PreparedStatement st =
           (PreparedStatement)
               MaimonidesApp.getApplication().getConector().getConexion().prepareStatement(sql);
       st.setInt(1, alumno.getId());
       ResultSet res = st.executeQuery();
       while (res.next()) {
         tabla.getModel().setValueAt(true, res.getInt("hora") - 1, res.getInt("dia"));
       }
       Obj.cerrar(st, res);
     } catch (SQLException ex) {
       Logger.getLogger(PanelApoyos.class.getName()).log(Level.SEVERE, null, ex);
     }
   }
   this.alumno = alumno;
 }
Exemple #3
0
 /**
  * Calcula si un alumno esta expulsado. Se sabe si un alumno está expulsado por el número de dias
  * escolares entre la fecha de expulsión y la de parte. Un día escolar es el numero de partes con
  * fecha distinta entre dos fechas.
  *
  * @param anoEscolar Año escola
  * @param alumno Alumno
  * @param fecha Fecha en la que se quiere saber si el alumno estça expulsado
  * @return true si está expulsado en la fecha del parte, false si no lo está
  */
 public static Boolean isAlumnoExpulsado(Alumno alumno, GregorianCalendar fecha) {
   boolean ret = false;
   try {
     // Tenemos que ver si hay expulsiones para ese alumno
     PreparedStatement st =
         (PreparedStatement)
             MaimonidesApp.getApplication()
                 .getConector()
                 .getConexion()
                 .prepareStatement("SELECT * FROM expulsiones WHERE alumno_id=? AND fecha<=?");
     st.setInt(1, alumno.getId());
     st.setDate(2, new java.sql.Date(fecha.getTimeInMillis()));
     ResultSet res = st.executeQuery();
     while (res.next() && !ret) {
       // Si hay expulsiones tenemos que ver si son válidas
       // Para eso tenemos que contar los partes desde la fecha de expulsión hasta ahora
       GregorianCalendar fechaExpulsion = Fechas.toGregorianCalendar(res.getDate("fecha"));
       if (fechaExpulsion != null) {
         // Como la fecha de expulsión esta incluida tenemos que quitarle un día
         fechaExpulsion.add(GregorianCalendar.DATE, -1);
         // Y vemos la diferencia en días
         int dias = res.getInt("dias");
         long diasTranscurridos =
             Fechas.getDiferenciaTiempoEn(fecha, fechaExpulsion, GregorianCalendar.DATE);
         ret = diasTranscurridos <= dias;
       }
     }
     Obj.cerrar(st, res);
   } catch (SQLException ex) {
     Logger.getLogger(Expulsion.class.getName()).log(Level.SEVERE, null, ex);
   }
   return ret;
 }
Exemple #4
0
 @Override
 protected ArrayList<Usuario> doInBackground() {
   ArrayList<Usuario> ret = new ArrayList<Usuario>();
   if (!Beans.isDesignTime()) {
     try {
       PreparedStatement st =
           (PreparedStatement)
               MaimonidesApp.getApplication()
                   .getConector()
                   .getConexion()
                   .prepareStatement(
                       "SELECT * FROM usuarios WHERE fbaja IS NULL ORDER BY nombre");
       ResultSet res = st.executeQuery();
       while (res.next()) {
         Usuario p = new Usuario();
         try {
           p.cargarDesdeResultSet(res);
           ret.add(p);
         } catch (SQLException ex) {
           Logger.getLogger(PanelUsuarios.class.getName()).log(Level.SEVERE, null, ex);
         } catch (Exception ex) {
           Logger.getLogger(PanelUsuarios.class.getName()).log(Level.SEVERE, null, ex);
         }
       }
       Obj.cerrar(st, res);
     } catch (SQLException ex) {
       Logger.getLogger(PanelUsuarios.class.getName()).log(Level.SEVERE, null, ex);
     }
   }
   return ret; // return your result
 }
 private String docToString(Document doc) throws TransformerException {
   StringWriter sw = new StringWriter();
   StreamResult result = new StreamResult(sw);
   DOMSource source = new DOMSource(doc);
   getTransformer().transform(source, result);
   String contenido = sw.toString();
   Obj.cerrar(sw);
   source = null;
   result = null;
   return contenido;
 }
Exemple #6
0
 public Expulsion(int id) throws Exception {
   PreparedStatement st =
       (PreparedStatement)
           MaimonidesApp.getApplication()
               .getConector()
               .getConexion()
               .prepareStatement("SELECT * FROM expulsiones WHERE id=? ");
   st.setInt(1, id);
   ResultSet res = st.executeQuery();
   if (res.next()) {
     cargarDesdeResultSet(res);
   } else {
     throw new InvalidParameterException("No existe ninguna expulsion con ID " + id);
   }
   Obj.cerrar(st, res);
 }
Exemple #7
0
 public static Expulsion getUltimaExpulsionPorFechaDeRegreso(Alumno alumno) {
   Expulsion e = null;
   PreparedStatement st = null;
   ResultSet res = null;
   String sql =
       "SELECT ADDDATE(fecha,dias) AS fechaEntrada ,e.* FROM expulsiones AS e WHERE e.alumno_id=? ORDER BY fechaEntrada DESC LIMIT 0,1";
   try {
     st =
         (PreparedStatement)
             MaimonidesApp.getApplication().getConector().getConexion().prepareStatement(sql);
     st.setInt(1, alumno.getId());
     res = st.executeQuery();
     if (res.next()) {
       e = new Expulsion();
       e.cargarDesdeResultSet(res);
     }
   } catch (Exception ex) {
     Logger.getLogger(Expulsion.class.getName()).log(Level.SEVERE, null, ex);
     e = null;
   }
   Obj.cerrar(st, res);
   return e;
 }
 @Override
 protected Vector<Profesor> doInBackground() {
   Vector<Profesor> ret = new Vector<Profesor>();
   if (!Beans.isDesignTime()) {
     try {
       if (Permisos.isUsuarioSoloProfesor() && Permisos.getFiltroProfesor() != null) {
         ret.add(Permisos.getFiltroProfesor());
       } else {
         PreparedStatement st =
             (PreparedStatement)
                 MaimonidesApp.getApplication()
                     .getConector()
                     .getConexion()
                     .prepareStatement(
                         "SELECT * FROM profesores_ WHERE ano=? ORDER BY nombre,apellido1,apellido2");
         st.setInt(1, MaimonidesApp.getApplication().getAnoEscolar().getId());
         ResultSet res = st.executeQuery();
         while (res.next()) {
           Profesor p = new Profesor();
           try {
             p.cargarDesdeResultSet(res);
             ret.add(p);
           } catch (SQLException ex) {
             Logger.getLogger(PanelProfesores.class.getName()).log(Level.SEVERE, null, ex);
           } catch (Exception ex) {
             Logger.getLogger(PanelProfesores.class.getName()).log(Level.SEVERE, null, ex);
           }
         }
         Obj.cerrar(st, res);
       }
     } catch (SQLException ex) {
       Logger.getLogger(PanelProfesores.class.getName()).log(Level.SEVERE, null, ex);
     }
   }
   return ret; // return your result
 }
Exemple #9
0
 public ArrayList<ParteConvivencia> getPartes() {
   if (partes == null) {
     partes = new ArrayList<ParteConvivencia>();
     PreparedStatement st = null;
     ResultSet res = null;
     try {
       st =
           (PreparedStatement)
               MaimonidesApp.getConexion()
                   .prepareStatement("SELECT * FROM conv_partes WHERE expulsion_id=?");
       st.setInt(1, getId());
       res = st.executeQuery();
       while (res.next()) {
         ParteConvivencia parte = new ParteConvivencia();
         parte.cargarDesdeResultSet(res);
         partes.add(parte);
       }
     } catch (Exception ex) {
       Logger.getLogger(Expulsion.class.getName()).log(Level.SEVERE, null, ex);
     }
     Obj.cerrar(st, res);
   }
   return partes;
 }
 // TODO Implementar el envío directo a Séneca
 public File exportarHorariosXMLSeneca() throws IOException {
   File ficheroXml = null;
   // Primero precargamos los profesores, unidades, etc
   firePropertyChange("message", null, "Precargando datos de profesores...");
   Profesor.getProfesores();
   firePropertyChange("message", null, "Precargando datos de unidades...");
   Unidad.getUnidades();
   firePropertyChange("message", null, "Precargando datos de dependencias...");
   Dependencia.getDependencias();
   firePropertyChange("message", null, "Precargando datos de tramos horarios...");
   TramoHorario.getTramosHorarios();
   firePropertyChange("message", null, "Precargando datos de materias...");
   Materia.getMaterias();
   firePropertyChange("message", null, "Precargando datos de actividades...");
   Actividad.getActividades();
   firePropertyChange("message", null, "Precargando datos de unidades...");
   Unidad.getUnidades();
   firePropertyChange("message", null, "Precargando datos de cursos...");
   Curso.getCursos();
   int contadorProfesores = 1;
   int contadorActividad = 1;
   // Ahora cargamos todos los horarios del año escolar
   PreparedStatement st = null;
   ResultSet res = null;
   try {
     firePropertyChange("message", null, "Procesando horarios...");
     st =
         (PreparedStatement)
             MaimonidesApp.getConexion()
                 .prepareStatement("SELECT * FROM horarios_ WHERE ano=? ORDER BY profesor_id ");
     st.setInt(1, MaimonidesApp.getApplication().getAnoEscolar().getId());
     res = st.executeQuery();
     int ultimoProfesor = -1;
     ArrayList<String> bloquesProfesores = new ArrayList<String>();
     ArrayList<String> bloquesActividad = new ArrayList<String>();
     while (res.next()) {
       try {
         int idProfesor = res.getInt("profesor_id");
         int dia = res.getInt("dia");
         int idMateria = res.getInt("materia_id");
         int idActividad = res.getInt("actividad_id");
         int idUnidad = res.getInt("unidad_id");
         int idDependencia = res.getInt("aula_id");
         Dependencia dependencia = null;
         if (idDependencia > 0) {
           try {
             dependencia = Dependencia.getDependencia(idDependencia);
           } catch (Exception ex) {
             Logger.getLogger(ExportadorHorariosSeneca.class.getName())
                 .log(Level.SEVERE, "No existe la dependencia " + idDependencia + ".", ex);
           }
         }
         TramoHorario tramo = TramoHorario.getTramoHorario(res.getInt("tramo_id"));
         Materia materia = null;
         Actividad actividad = Actividad.getActividad(idActividad);
         Unidad unidad = Unidad.getUnidad(idUnidad);
         Curso curso = Curso.getCurso(unidad.getIdCurso());
         if (idMateria > 0) {
           materia = Materia.getMateria(idMateria);
         }
         if (idProfesor != ultimoProfesor) {
           // Si cambiamos de profesor tenemos que crear un nuevo registro
           // si el profesor anterior no era -1
           if (ultimoProfesor != -1) {
             String bloqueProfesor =
                 getBloqueProfesor(contadorProfesores, idProfesor, bloquesActividad);
             if (bloqueProfesor != null) {
               bloquesProfesores.add(bloqueProfesor);
               contadorProfesores++;
             }
             bloquesActividad.clear();
             contadorActividad = 1;
           }
         }
         ultimoProfesor = idProfesor;
         // Añadimos el bloque de actividades
         bloquesActividad.add(
             getXMLBloqueHorario(
                 MaimonidesApp.getApplication().getAnoEscolar(),
                 contadorActividad,
                 dia,
                 tramo,
                 dependencia,
                 curso,
                 unidad,
                 actividad,
                 materia));
         contadorActividad++;
       } catch (Exception e) {
         Logger.getLogger(ExportadorHorariosSeneca.class.getName())
             .log(Level.SEVERE, "Ha habido un error procesando el horario.", e);
       }
     }
     // Añadimos el último profesor
     if (ultimoProfesor != -1) {
       String bloqueProfesor =
           getBloqueProfesor(contadorProfesores, ultimoProfesor, bloquesActividad);
       if (bloqueProfesor != null) {
         bloquesProfesores.add(bloqueProfesor);
       }
     }
     // Ahora generamos el resto del documento
     GregorianCalendar fecha = new GregorianCalendar();
     StringBuilder xml = new StringBuilder();
     xml.append(
         String.format(
             "<SERVICIO modulo=\"HORARIOS\" tipo=\"I\" autor=\"Maimonides %s\" fecha=\"%2$tm/%2$td/%2$tY %tT\">\n",
             Mantenimiento.getAplicationVersion(), fecha, fecha));
     xml.append("<BLOQUE_DATOS>\n");
     xml.append(
         String.format(
             "\t<grupo_datos seq=\"ANNO_ACADEMICO\">\n\t\t<dato nombre_dato=\"C_ANNO\">%d</dato>\n\t</grupo_datos>\n",
             MaimonidesApp.getApplication().getAnoEscolar().getAno()));
     xml.append(
         String.format(
             "\t<grupo_datos seq=\"HORARIOS_REGULARES\" registros=\"%d\">\n",
             bloquesProfesores.size()));
     xml.append(Str.implode(bloquesProfesores, ""));
     xml.append("\t</grupo_datos>\n");
     xml.append("</BLOQUE_DATOS>\n");
     xml.append("</SERVICIO>\n");
     // Ahora guardamos el contenido en el fichero
     ficheroXml = File.createTempFile("horarios_seneca", ".xml");
     Archivo.setContenido(xml.toString(), "ISO-8859-1", ficheroXml, false);
   } catch (SQLException ex) {
     Logger.getLogger(ExportadorHorariosSeneca.class.getName())
         .log(Level.SEVERE, "Error recuperando listado de horarios.", ex);
   }
   Obj.cerrar(st, res);
   return ficheroXml;
 }
 public ArrayList<String> exportarFaltas(
     GregorianCalendar fechaDesde, GregorianCalendar fechaHasta, ArrayList<String> cursos) {
   ArrayList<String> err = new ArrayList<String>();
   setFaltasExportadas(false);
   String texto = "Procesando... ";
   if (Fechas.getDiferenciaTiempoEn(fechaDesde, fechaHasta, GregorianCalendar.DATE) == 0) {
     texto += Fechas.format(fechaHasta, "dd/MM");
   } else {
     texto += Fechas.format(fechaDesde, "dd/MM") + " a " + Fechas.format(fechaHasta, "dd/MM");
   }
   PreparedStatement st = null;
   try {
     firePropertyChange("message", null, "Recuperando datos...");
     StringBuilder sbCursos = new StringBuilder();
     boolean primero = true;
     for (String c : cursos) {
       if (primero) {
         primero = false;
       } else {
         sbCursos.append(",");
       }
       sbCursos.append("\"").append(c).append("\"");
     }
     String sql =
         "SELECT p.id as idParte,p.fecha,t.cod AS codTramo,pa.asistencia,a.id AS idAlumno FROM partes_alumnos AS pa "
             + " JOIN partes AS p ON p.id=pa.parte_id "
             + " JOIN alumnos AS a ON a.id=pa.alumno_id "
             + " LEFT JOIN alumnos_problemas_envio AS ap ON a.id=ap.alumno_id "
             + " JOIN horarios AS h ON h.id=pa.horario_id "
             + " LEFT JOIN calendario_escolar AS ce ON ce.ano=p.ano AND p.fecha=ce.dia AND ce.docentes "
             + // TODO Esta linea elimina a caso hecho a los alumnos "MIXTOS" ya que séneca da un
               // error con ellos.
             " JOIN unidades AS u ON a.unidad_id=u.id AND a.curso_id=u.curso_id "
             + " JOIN tramos AS t ON t.id=h.tramo_id "
             + // Sólo hay que recuperar las que sean de actividad doncencia de alumnos con código
               // de faltas y que no están borrados, y que no son festivos
             " WHERE ce.id IS NULL AND (ap.id IS NULL || ap.excluir=0 ) AND h.actividad_id="
             + Actividad.getIdActividadDocencia(MaimonidesApp.getApplication().getAnoEscolar())
             + " AND a.borrado=0 AND a.codFaltas!='' AND p.fecha BETWEEN ? AND ? AND p.curso IN ("
             + sbCursos.toString()
             + ") AND pa.asistencia > "
             + ParteFaltas.FALTA_ASISTENCIA
             + " AND p.ano=? ORDER BY a.curso_id,a.unidad_id,idAlumno,p.fecha,asistencia,t.hora";
     System.out.println(sql);
     PreparedStatement actuParte =
         (PreparedStatement)
             MaimonidesApp.getApplication()
                 .getConector()
                 .getConexion()
                 .prepareStatement(
                     "UPDATE partes SET enviado=1, justificado=1 WHERE fecha BETWEEN ? AND ? AND curso IN ("
                         + sbCursos.toString()
                         + ") AND ano=?  ");
     st =
         (PreparedStatement)
             MaimonidesApp.getApplication().getConector().getConexion().prepareStatement(sql);
     st.setDate(1, new java.sql.Date(fechaDesde.getTime().getTime()));
     st.setDate(2, new java.sql.Date(fechaHasta.getTime().getTime()));
     st.setInt(3, MaimonidesApp.getApplication().getAnoEscolar().getId());
     actuParte.setDate(1, new java.sql.Date(fechaDesde.getTime().getTime()));
     actuParte.setDate(2, new java.sql.Date(fechaHasta.getTime().getTime()));
     actuParte.setInt(3, MaimonidesApp.getApplication().getAnoEscolar().getId());
     ResultSet res = st.executeQuery();
     Curso ultimoCurso = null;
     Unidad ultimaUnidad = null;
     Alumno ultimoAlumno = null;
     Element nCursos = getDocumento().createElement("CURSOS");
     Element nCurso = null;
     Element nUnidades = null;
     Element nUnidad = null;
     Element nAlumnos = null;
     Element nAlumno = null;
     Element nFaltas = null;
     while (res.next() && !isCancelado()) {
       setFaltasExportadas(true);
       GregorianCalendar fecha = Fechas.toGregorianCalendar(res.getDate("fecha"));
       // firePropertyChange("message", null, "Procesando asistencia ...");
       // int idParte = res.getInt("idParte");
       int tramo = res.getInt("codTramo");
       int asistencia = res.getInt("asistencia");
       int idAlumno = res.getInt("idAlumno");
       Alumno a = Alumno.getAlumno(idAlumno);
       Curso c = Curso.getCurso(a.getIdCurso());
       Unidad u = a.getUnidad();
       firePropertyChange("message", null, texto + " " + u + " " + a + "...");
       if (ultimoCurso == null || !ultimoCurso.equals(c)) {
         nCurso = getDocumento().createElement("CURSO");
         nCursos.appendChild(nCurso);
         // Creamos la linea <X_OFERTAMATRIG>2063</X_OFERTAMATRIG>
         nCurso.appendChild(crearTag("X_OFERTAMATRIG", c.getCodigo()));
         // Creamos la linea <D_OFERTAMATRIG>1º de Bachillerato (Humanidades y Ciencias
         // Sociales)</D_OFERTAMATRIG>
         nCurso.appendChild(crearTag("D_OFERTAMATRIG", c.getDescripcion()));
         // Ahora creamos el comienzo de la unidad
         nUnidades = getDocumento().createElement("UNIDADES");
         nCurso.appendChild(nUnidades);
       }
       if (ultimaUnidad == null || !ultimaUnidad.equals(u)) {
         // Creamos una nueva unidad
         nUnidad = getDocumento().createElement("UNIDAD");
         nUnidades.appendChild(nUnidad);
         // Creamos la linea <X_UNIDAD>601648</X_UNIDAD>
         nUnidad.appendChild(crearTag("X_UNIDAD", u.getCodigo()));
         // Creamos la linea <T_NOMBRE>1BTO-A</T_NOMBRE>
         nUnidad.appendChild(crearTag("T_NOMBRE", u.getCursoGrupo()));
         // Ahora creamos el comienzo de la unidad
         nAlumnos = getDocumento().createElement("ALUMNOS");
         nUnidad.appendChild(nAlumnos);
       }
       if (ultimoAlumno == null || !ultimoAlumno.equals(a)) {
         nAlumno = getDocumento().createElement("ALUMNO");
         nAlumno.appendChild(crearTag("X_MATRICULA", a.getCodFaltas()));
         // Y Creamos el inicio para las faltas de asistencia de este alumno
         nFaltas = getDocumento().createElement("FALTAS_ASISTENCIA");
         nAlumno.appendChild(nFaltas);
         nAlumnos.appendChild(nAlumno);
       }
       addFalta(fecha, tramo, asistencia, nFaltas);
       ultimoCurso = c;
       ultimaUnidad = u;
       ultimoAlumno = a;
     }
     if (isFaltasExportadas() && !isCancelado()) {
       firePropertyChange("message", null, "Generando fichero...");
       generarCabeceraFaltas(fechaDesde, fechaHasta, nCursos);
       File f = generarFicheroFaltas(fechaDesde, fechaHasta, cursos);
       if (isEnviarASeneca()) {
         firePropertyChange("message", null, "Enviando fichero a Séneca...");
         String nombre = f.getName().substring(0, f.getName().length() - 4);
         String codigoOperacion = Cripto.md5(nombre + "" + Math.random());
         int ret = enviarFichero(f, codigoOperacion);
         if (ret == GestorEnvioFaltas.RET_OK) {
           firePropertyChange(
               "message", null, "Fichero enviado correctamente. Marcando faltas como enviadas...");
           actuParte.executeUpdate();
           File enviados = new File(f.getParent(), "enviados");
           enviados.mkdirs();
           f.renameTo(new File(enviados, f.getName()));
           firePropertyChange("message", null, "Envío de faltas terminado.");
         } else {
           if (ret == GestorEnvioFaltas.RET_ERROR_PROCESANDO) {
             firePropertyChange(
                 "message", null, "Séneca ha dado errores procesando el fichero enviado.");
             File nuevo =
                 new File(getCarpetaFallidos(), nombre + "-ID" + codigoOperacion + ".xml");
             f.renameTo(nuevo);
             // Creamos el fichero de propiedades del nuevo
             File info = new File(nuevo.getParentFile(), nuevo.getName() + ".info");
             Properties p = new Properties();
             p.setProperty("desde", fechaDesde.getTimeInMillis() + "");
             p.setProperty("hasta", fechaHasta.getTimeInMillis() + "");
             p.setProperty("cursos", Str.implode(cursos, ","));
             p.setProperty("archivo", nuevo.getAbsolutePath());
             p.setProperty("codigo", codigoOperacion);
             p.setProperty("error", getClienteSeneca().getUltimoError());
             FileOutputStream fos = new FileOutputStream(info);
             p.store(fos, "Error enviando fichero de faltas");
             Obj.cerrar(fos);
             err.add(
                 "<html>Séneca ha dado errores procesando el fichero enviado:<br/> "
                     + nombre
                     + ".<br/><br/>");
             if (!getClienteSeneca().getUltimoError().equals("")) {
               err.add(getClienteSeneca().getUltimoError());
             }
           } else {
             firePropertyChange("message", null, "No se ha podido enviar el fichero a Séneca.");
             f.delete();
             err.add("<html>No se ha podido enviar el fichero:<br/> " + nombre + ".<br/><br/>");
             if (!getClienteSeneca().getUltimoError().equals("")) {
               err.add(getClienteSeneca().getUltimoError());
             }
           }
           // Si no se está loggeado cancelamos el proceso
           if (!getClienteSeneca().isLoggeado()) {
             setCancelado(true);
           }
         }
       } else {
         firePropertyChange("message", null, "Marcando faltas como enviadas...");
         actuParte.executeUpdate();
       }
     }
     Obj.cerrar(actuParte, st, res);
   } catch (Exception ex) {
     Logger.getLogger(GeneradorFicherosSeneca.class.getName()).log(Level.SEVERE, null, ex);
   }
   return err;
 }
  public ArrayList<String> exportarFaltas(
      GregorianCalendar fechaDesde, GregorianCalendar fechaHasta) {
    setFicherosGenerados(false);
    getErrores().clear();
    if (MaimonidesApp.getApplication().getAnoEscolar() == null) {
      getErrores().add("No hay año escolar asignado.");
    } else {
      // Ponemos el tema de h.materia_id IS NOT NULL para que no introduzca la actvidaddes. Podría
      // ponerse directamente un tipo de actividad.
      // No queremos que meta actividades porque séneca no admite faltas en las actividades sólo en
      // las materias.
      // El envío de faltas hay que hacerlo siempre por cursos completos para una fecha por lo que
      // primero tenemos que sacar fechas y cursos
      String sql =
          "SELECT distinct p.fecha,p.curso FROM partes_alumnos AS pa "
              + " JOIN partes AS p ON p.id=pa.parte_id "
              + " JOIN alumnos AS a ON a.id=pa.alumno_id "
              + " LEFT JOIN alumnos_problemas_envio AS ap ON a.id=ap.alumno_id "
              + " JOIN horarios AS h ON h.id=pa.horario_id "
              + " JOIN tramos AS t ON t.id=h.tramo_id "
              + " LEFT JOIN calendario_escolar AS ce ON ce.ano=p.ano AND p.fecha=ce.dia AND ce.docentes "
              + // TODO Esta linea elimina a caso hecho a los alumnos "MIXTOS" ya que séneca da un
                // error con ellos.
              " JOIN unidades AS u ON a.unidad_id=u.id AND a.curso_id=u.curso_id "
              + // Sólo hay que recuperar las que sean de actividad doncencia de alumnos con código
                // de faltas y que no están borrados, y que no son festivos
              " WHERE ce.id IS NULL AND (ap.id IS NULL || ap.excluir=0 ) AND  h.actividad_id="
              + Actividad.getIdActividadDocencia(MaimonidesApp.getApplication().getAnoEscolar())
              + " AND a.borrado=0 AND a.codFaltas!='' AND pa.asistencia>"
              + ParteFaltas.FALTA_ASISTENCIA
              + " AND p.enviado=0 AND p.ano=? AND (p.justificado OR p.fecha<? )"
              + ((fechaDesde != null) ? " AND p.fecha>=? " : "")
              + ((fechaHasta != null) ? " AND p.fecha<=? " : "")
              + " ORDER BY p.fecha ASC,p.curso";
      PreparedStatement st = null;
      ResultSet res = null;
      try {
        st =
            (PreparedStatement)
                MaimonidesApp.getApplication().getConector().getConexion().prepareStatement(sql);
        int pos = 1;
        st.setInt(pos++, MaimonidesApp.getApplication().getAnoEscolar().getId());
        GregorianCalendar fechaFiltro = new GregorianCalendar();
        // Asignamos el principio de la semana siempre
        fechaFiltro.add(
            GregorianCalendar.DATE, fechaFiltro.get(GregorianCalendar.DAY_OF_WEEK) * -1);
        st.setDate(pos++, new java.sql.Date(fechaFiltro.getTime().getTime()));
        if (fechaDesde != null) {
          st.setDate(pos++, new java.sql.Date(fechaDesde.getTime().getTime()));
        }
        if (fechaHasta != null) {
          st.setDate(pos++, new java.sql.Date(fechaHasta.getTime().getTime()));
        }

        GregorianCalendar fechaMin = null;
        GregorianCalendar fechaMax = null;
        ArrayList<String> cursos = new ArrayList<String>();
        res = st.executeQuery();
        while (res.next() && !isCancelado()) {
          GregorianCalendar f = Fechas.toGregorianCalendar(res.getDate("fecha"));
          String c = res.getString("curso");
          if (fechaMin == null) {
            fechaMin = f;
            fechaMax = f;
          } else {
            // vemos la diferencia entre fechas
            boolean cambiarDeFichero = isCambiarDeFichero(f, fechaMax);
            if (cambiarDeFichero) {
              // Si es mayor de un dia hay que crear un fichero nuevo
              getErrores().addAll(procesarFaltas(fechaMin, fechaMax, cursos));
              fechaMin = f;
              fechaMax = f;
              cursos.clear();
            } else {
              // Si no asignamos ese dia simplemente
              fechaMax = f;
            }
          }
          if (!cursos.contains(c)) {
            firePropertyChange("message", null, "Procesando " + Fechas.format(f) + " " + c + "...");
            cursos.add(c);
          }
        }
        if (cursos.size() > 0) {
          // Y procesamos la última tanda
          getErrores().addAll(procesarFaltas(fechaMin, fechaMax, cursos));
        }
      } catch (SQLException ex) {
        Logger.getLogger(GeneradorFicherosSeneca.class.getName()).log(Level.SEVERE, null, ex);
      } finally {
        Obj.cerrar(st, res);
      }
    }
    return getErrores();
  }