/** * * Vérifie que l'ensemble de la table d'agrégation est à jours, pour tous les élèves. * Corrige automatiquement la table pour un certain nombres d'élèves (précisé par $reparation_nbr), * si plus d'élève que ce nombre sont en échec on renvoie faux * * @param DateTime $dateDebut date de début pour la prise en compte du test * @param DateTime $dateFin date de fin pour la prise en compte du test * @param int $reparation_nbr nomble d'elve qu'on va mettre à jour avant de renvoyer faux * @return Boolean * */ public static function checkSynchroAbsenceAgregationTable(DateTime $dateDebut = null, DateTime $dateFin = null, $reparation_nbr = 50) { global $mysqli; $debug = false; if ($debug) { print_r('AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable() called<br/>'); } //on initialise les date clone qui seront manipulés dans l'algoritme, c'est nécessaire pour ne pas modifier les dates passées en paramêtre. $dateDebutClone = null; $dateFinClone = null; if ($dateDebut != null) { if ($debug) { print_r('Date début '.$dateDebut->format('Y-m-d').'<br/>'); } $dateDebutClone = clone $dateDebut; $dateDebutClone->setTime(0,0); } if ($dateFin != null) { if ($debug) { print_r('Date fin '.$dateFin->format('Y-m-d').'<br/>'); } $dateFinClone = clone $dateFin; $dateFinClone->setTime(23,59); } //on va vérifier que tout les marqueurs de fin des calculs de mise à jour sont bien présents pour tout les élèves $query = ' SELECT distinct eleves.ID_ELEVE FROM `eleves` LEFT JOIN ( SELECT distinct ELEVE_ID FROM `a_agregation_decompte` WHERE date_demi_jounee = \'0001-01-01 00:00:00\') as a_agregation_decompte_selection ON (eleves.ID_ELEVE=a_agregation_decompte_selection.ELEVE_ID) WHERE a_agregation_decompte_selection.ELEVE_ID IS NULL'; $result = mysqli_query($mysqli, $query); $num_rows = mysqli_num_rows($result); if ($num_rows>0 && $num_rows < $reparation_nbr) { if ($debug) { print_r('Il manque des marqueurs de fin de calcul<br/>'); } //on va corriger la table pour ces élèves là while ($row = mysqli_fetch_array($result, MYSQL_NUM)) { $eleve = EleveQuery::create()->findOneById($row[0]); if ($debug) { print_r('recalcul pour l eleve '.$eleve->getId().'<br/>'); } $eleve->checkAndUpdateSynchroAbsenceAgregationTable($dateDebutClone,$dateFinClone); } //après avoir corrigé on relance le test return(AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable($dateDebutClone, $dateFinClone)); } elseif ($num_rows>0) { if ($debug) { print_r('retourne faux : Il manque trop de marqueurs de fin de calcul<br/>'); } return false; } //conditions sql sur les dates $date_saisies_selection = ' 1=1 '; $date_saisies_version_selection = ' 1=1 '; $date_agregation_selection = ' 1=1 '; if ($dateDebutClone != null) { $date_saisies_selection .= ' and a_saisies.fin_abs >= "'.$dateDebutClone->format('Y-m-d H:i:s').'" '; $date_saisies_version_selection .= ' and a_saisies_version.fin_abs >= "'.$dateDebutClone->format('Y-m-d H:i:s').'" '; $date_agregation_selection .= ' and a_agregation_decompte.DATE_DEMI_JOUNEE >= "'.$dateDebutClone->format('Y-m-d H:i:s').'" '; } if ($dateFinClone != null) { $date_saisies_selection .= ' and a_saisies.debut_abs <= "'.$dateFinClone->format('Y-m-d H:i:s').'" '; $date_saisies_version_selection .= ' and a_saisies_version.debut_abs <= "'.$dateFinClone->format('Y-m-d H:i:s').'" '; $date_agregation_selection .= ' and a_agregation_decompte.DATE_DEMI_JOUNEE <= "'.$dateFinClone->format('Y-m-d H:i:s').'" '; } //on va vérifier que tout les élèves ont bien le bon nombres entrées dans la table d'agrégation pour cette période if ($dateFinClone != null && $dateDebutClone != null) { $query = ' SELECT eleves.ID_ELEVE, count(eleves.ID_ELEVE) as count_entrees FROM `eleves` LEFT JOIN ( SELECT ELEVE_ID FROM `a_agregation_decompte` WHERE '.$date_agregation_selection.') as a_agregation_decompte_selection ON (eleves.ID_ELEVE=a_agregation_decompte_selection.ELEVE_ID) group by eleves.ID_ELEVE'; $result = mysqli_query($mysqli, $query); $wrong_eleve = array(); $nbre_demi_journees=(int)(($dateFinClone->format('U')+3700-$dateDebutClone->format('U'))/(3600*12)); while($row = mysqli_fetch_array($result)){ if ($row[1]!=$nbre_demi_journees) { if ($debug) { print_r('Il manque des entrees pour l eleve '.$row[0].'<br/>'); } $wrong_eleve[]=$row[0]; } } if (count($wrong_eleve) > 0 && count($wrong_eleve) < $reparation_nbr) { //on va corriger la table pour ces élèves là foreach($wrong_eleve as $idEleve) { $eleve = EleveQuery::create()->findOneById($idEleve); if ($debug) { print_r('recalcul pour l eleve '.$eleve->getId().'<br/>'); } $eleve->checkAndUpdateSynchroAbsenceAgregationTable($dateDebutClone,$dateFinClone); } //après avoir corrigé on relance le test return(AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable($dateDebutClone, $dateFinClone)); } elseif (!empty($wrong_eleve) > 0) { if ($debug) { print_r('retourne faux : Il manque des saisies sur '.count($wrong_eleve).' eleves<br/>'); } return false; } } // est-ce que la date updated_at de mise à jour de la table est bien postérieure aux date de modification des saisies et autres entrées $query = 'select union_date, updated_at, now() as now FROM (SELECT max(updated_at) as updated_at FROM a_agregation_decompte WHERE '.$date_agregation_selection.' ) as updated_at_select LEFT JOIN ( (SELECT union_date from ( SELECT GREATEST(IFNULL(max(updated_at),CAST(0 as DATETIME)),IFNULL(max(deleted_at),CAST(0 as DATETIME))) as union_date FROM a_saisies WHERE eleve_id is not null and '.$date_saisies_selection.' UNION ALL SELECT GREATEST(IFNULL(max(a_saisies_version.updated_at),CAST(0 as DATETIME)),IFNULL(max(a_saisies_version.deleted_at),CAST(0 as DATETIME))) as union_date FROM a_saisies_version WHERE a_saisies_version.eleve_id is not null and '.$date_saisies_version_selection.' UNION ALL SELECT GREATEST(IFNULL(max(a_traitements.updated_at),CAST(0 as DATETIME)),IFNULL(max(a_traitements.deleted_at),CAST(0 as DATETIME))) as union_date FROM a_traitements join j_traitements_saisies on a_traitements.id = j_traitements_saisies.a_traitement_id join a_saisies on a_saisies.id = j_traitements_saisies.a_saisie_id WHERE a_saisies.eleve_id is not null and '.$date_saisies_selection.' ORDER BY union_date DESC LIMIT 1 ) AS union_date_union_all_select ) AS union_date_select ) ON 1=1;'; $result_query = mysqli_query($mysqli, $query); if ($result_query === false) { if ($debug) { echo $query; } echo 'Erreur sur la requete : '.mysqli_error($mysqli).'<br/>'; return false; } $row = mysqli_fetch_array($result_query); mysqli_free_result($result_query); if ($debug) { print_r($row); } if ($row['updated_at'] && $row['updated_at'] > $row['now']) { if ($debug) { print_r('faux : Date de mise a jour des agregation ne peut pas etre dans le futur<br/>'); } return false; } else if ($row['union_date'] && $row['union_date'] > $row['now']) { if ($debug) { print_r('faux : Date de mise a jour des saisie ou traitements ne peut pas etre dans le futur<br/>'); } return false; } else if ($row['union_date'] && (!$row['updated_at'] || $row['union_date'] > $row['updated_at'])){//si on a pas de updated_at dans la table d'agrégation, ou si la date de mise à jour des saisies est postérieure à updated_at ou if ($debug) { print_r('retourne faux : Les date de mise a jour de la table sont trop anciennes<br/>'); } return false; } else { if ($debug) { print_r('retourne vrai<br/>'); } return true;//on ne vérifie pas le nombre d'entrée car les dates ne sont pas précisée } }
} else { $eleve_query->filterByUtilisateurProfessionnel($utilisateur); } if ($id_classe !== null && $id_classe != -1) { $eleve_query->useJEleveClasseQuery()->filterByIdClasse($id_classe)->endUse(); } if ($nom_eleve !== null && $nom_eleve != '') { $eleve_query->filterByNomOrPrenomLike($nom_eleve); } $eleve_query->where('Eleve.DateSortie<?','0') ->orWhere('Eleve.DateSortie is NULL') ->orWhere('Eleve.DateSortie>?', $dt_date_absence_eleve_debut->format('U')); $eleve_col = $eleve_query->find(); $table_synchro_ok = AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable($dt_date_absence_eleve_debut,$dt_date_absence_eleve_fin); if (!$table_synchro_ok) {//la table n'est pas synchronisée. On va vérifier individuellement les élèves qui se sont pas synchronisés if ($eleve_col->count()>150) { echo 'Il semble que vous demandez des statistiques sur trop d\'élèves et votre table de statistiques n\'est pas synchronisée.<br />Veuillez faire une demande pour moins d\'élèves ou'; if(getSettingAOui('AccesCpeAgregationAbs2')) { echo ' <a href="./admin/admin_table_agregation.php" title="ATTENTION : Cette opération est lourde. Elle peut enliser le serveur, perturber les saisies le temps qu\'elle s\'achève.">remplir la table d\'agrégation</a>.'; } else { echo ' demander à votre administrateur de remplir la table d\'agrégation.'; } if (ob_get_contents()) { ob_flush(); } flush();
public function testPeerUpdateAgregationTable() { //on va modifier à la main une saisie AbsenceAgregationDecompteQuery::create()->deleteAll(); foreach (EleveQuery::create()->find() as $eleve) { $eleve->updateAbsenceAgregationTable(new DateTime(VENDREDI_s40j5.' 00:00:00'),new DateTime(DIMANCHE_s41j7.' 23:59:59')); } sleep(1); $florence_eleve = EleveQuery::create()->findOneByLogin('Florence Michu'); $saisie = $florence_eleve->getAbsenceEleveSaisiesDuJour(SAMEDI_s40j6)->getFirst(); $saisie_id = $saisie->getId(); mysqli_query($GLOBALS["mysqli"], "update a_saisies set updated_at = now() where id = ".$saisie_id); $this->assertFalse(AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable(null, null, 0)); $col = new PropelCollection(); $col->append($saisie); AbsenceAgregationDecomptePeer::updateAgregationTable($col); $this->assertTrue(AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable(new DateTime(VENDREDI_s40j5.' 00:00:00'),new DateTime(DIMANCHE_s41j7.' 23:59:59'),0)); $this->assertTrue(AbsenceAgregationDecomptePeer::checkSynchroAbsenceAgregationTable(null, null, 0)); AbsenceAgregationDecompteQuery::create()->deleteAll(); foreach (EleveQuery::create()->find() as $eleve) { $eleve->updateAbsenceAgregationTable(new DateTime(VENDREDI_s40j5.' 00:00:00'),new DateTime(DIMANCHE_s41j7.' 23:59:59')); } sleep(1); $florence_eleve = EleveQuery::create()->findOneByLogin('Florence Michu'); $saisie = $florence_eleve->getAbsenceEleveSaisiesDuJour(VENDREDI_s40j5)->getFirst(); $saisie_id = $saisie->getId(); mysqli_query($GLOBALS["mysqli"], "update a_saisies set fin_abs = '".VENDREDI_s40j5." 08:10:00' where id = ".$saisie_id);//ça devient un retard $decompte = AbsenceAgregationDecompteQuery::create()->filterByEleve($florence_eleve)->filterByDateDemiJounee(VENDREDI_s40j5)->findOne(); $this->assertTrue($decompte->getManquementObligationPresence()); $this->assertEquals(0,$decompte->getRetards()); $saisie->getEleve()->clearAllReferences(); $saisie->clearAllReferences(); $saisie->reload(); $col = new PropelCollection(); $col->append($saisie); AbsenceAgregationDecomptePeer::updateAgregationTable($col); $decompte = AbsenceAgregationDecompteQuery::create()->filterByEleve($florence_eleve)->filterByDateDemiJounee(VENDREDI_s40j5)->findOne(); $this->assertFalse($decompte->getManquementObligationPresence()); $this->assertEquals(1,$decompte->getRetards()); $saisie->setFinAbs(VENDREDI_s40j5.' 09:00:00'); $saisie->save(); AbsenceAgregationDecompteQuery::create()->deleteAll(); AbsenceAgregationDecomptePeer::updateAgregationTable(AbsenceEleveSaisieQuery::create()->filterByPlageTemps(new DateTime(VENDREDI_s40j5), new DateTime(DIMANCHE_s41j7))->find()); $eleve_col = EleveQuery::create()->useAbsenceEleveSaisieQuery()->filterByPlageTemps(new DateTime(VENDREDI_s40j5), new DateTime(DIMANCHE_s41j7))->endUse()->find(); foreach($eleve_col as $eleve) { $this->assertTrue($eleve->checkSynchroAbsenceAgregationTable(new DateTime(SAMEDI_s40j6.' 00:00:00'),new DateTime(MARDI_s41j2))); } }