Loading front/Intervenant/Recherche.vue +2 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ export default { unicaenVue.axios.post( unicaenVue.url("intervenant/recherche-json"), { term: this.searchTerm term: this.searchTerm, types: this.checkedTypes, } ) .then(response => { Loading module/Formule/src/Model/FormuleDetailsExtractor.php +71 −3 Original line number Diff line number Diff line Loading @@ -172,10 +172,78 @@ class FormuleDetailsExtractor implements ExtractionInterface $valeur = $this->trace->getValeur($typeHetd); $this->intervenant['hetd'][$typeHetd] = $this->valeurToJson($valeur); } //Mécanique d'arrondis du total si écart entre service du et total heure est de 0.01 HETD if ($this->intervenant['hetd']['HeuresService']['valeur'] > 0 && $this->intervenant['serviceDu'] > 0 && abs($this->intervenant['hetd']['HeuresService']['valeur'] - $this->intervenant['serviceDu']) <= 0.01) { $this->intervenant['hetd']['HeuresService']['valeur'] = $this->intervenant['serviceDu']; $this->reconcileIntervenantService(); } /** * Répercute un écart d'un centième entre le service calculé et le service dû * sur les valeurs affichées, tout en conservant leurs valeurs originales. */ private function reconcileIntervenantService(): void { $serviceKey = Ligne::CAT_SERVICE; if (!isset($this->intervenant['hetd'][$serviceKey])) { return; } $serviceDu = round($this->intervenant['serviceDu'], 2); $calculatedService = round($this->intervenant['hetd'][$serviceKey]['valeur'], 2); $difference = round($serviceDu - $calculatedService, 2); if ($serviceDu <= 0.0 || abs($difference) !== 0.01) { return; } $componentKeys = array_map( static fn(string $type): string => Ligne::CAT_SERVICE . $type, Ligne::TYPES ); $componentKeys = array_values(array_filter( $componentKeys, fn(string $key): bool => isset($this->intervenant['hetd'][$key]) )); if ([] !== $componentKeys) { usort( $componentKeys, fn(string $left, string $right): int => abs($this->intervenant['hetd'][$right]['valeur']) <=> abs($this->intervenant['hetd'][$left]['valeur']) ); $componentKey = $componentKeys[0]; $this->intervenant['hetd'][$componentKey]['valeur'] = round( $this->intervenant['hetd'][$componentKey]['valeur'] + $difference, 2 ); $enseignementKeys = array_map( static fn(string $type): string => Ligne::CAT_SERVICE . $type, Ligne::TYPES_ENSEIGNEMENT ); $enseignementKey = Ligne::CAT_SERVICE . Ligne::TYPE_ENSEIGNEMENT; if (in_array($componentKey, $enseignementKeys, true) && isset($this->intervenant['hetd'][$enseignementKey])) { $this->intervenant['hetd'][$enseignementKey]['valeur'] = round( $this->intervenant['hetd'][$enseignementKey]['valeur'] + $difference, 2 ); } } $this->intervenant['hetd'][$serviceKey]['valeur'] = $serviceDu; if (isset($this->intervenant['hetd'][Ligne::TOTAL])) { $this->intervenant['hetd'][Ligne::TOTAL]['valeur'] = round( $this->intervenant['hetd'][Ligne::TOTAL]['valeur'] + $difference, 2 ); } } Loading module/Formule/src/Service/AfficheurService.php +31 −14 Original line number Diff line number Diff line Loading @@ -85,6 +85,10 @@ class AfficheurService } } if ($hasServiceStatutaire) { $this->reconcileServiceWithServiceDu($data['heures']['service'], $data['serviceDu']); } if (count($types) > 1) { $types[] = 'total'; foreach ($data['heures'] as $categorie => $values) { Loading @@ -109,28 +113,41 @@ class AfficheurService } } } } //Mécanique d'arrondis du total si écart entre service du et total heure est de 0.01 HETD $hasMultipleTypes = count($types) > 1; $serviceDu = $data['serviceDu']; return $data; } $total = $hasMultipleTypes ? $data['heures']['total']['total'] : current($data['heures']['total']); $hasRoundingDifference = abs($total - $serviceDu) <= 0.01; if ($total > 0 && $serviceDu > 0 && $hasRoundingDifference) { $key = $hasMultipleTypes ? 'total' : array_key_first($data['heures']['total']); /** * Répercute un écart d'arrondi d'un centième sur la plus grande composante * du service afin que la somme affichée corresponde au service dû. */ private function reconcileServiceWithServiceDu(array &$service, float $serviceDu): void { if ($serviceDu <= 0.0 || [] === $service) { return; } $data['heures']['total'][$key] = $serviceDu; $data['heures']['service'][$key] = $serviceDu; $roundedService = array_map(static fn(float $hours): float => round($hours, 2), $service); $difference = round(round($serviceDu, 2) - array_sum($roundedService), 2); if (abs($difference) !== 0.01) { return; } return $data; $keyToAdjust = array_keys( $roundedService, max($roundedService), true )[0]; $roundedService[$keyToAdjust] = round($roundedService[$keyToAdjust] + $difference, 2); $service = $roundedService; } } module/Intervenant/src/Controller/IntervenantController.php +15 −1 Original line number Diff line number Diff line Loading @@ -128,9 +128,23 @@ class IntervenantController extends AbstractController $recherche->setShowHisto($canShowHistorises); $intervenants = []; $term = $this->axios()->fromPost('term'); $requestedTypes = (array)$this->axios()->fromPost('types', []); $typeCodesByFilter = [ 'vacataire' => 'E', 'permanent' => 'P', 'etudiant' => 'S', ]; $typeCodes = []; foreach ($requestedTypes as $requestedType) { if (isset($typeCodesByFilter[$requestedType])) { $typeCodes[] = $typeCodesByFilter[$requestedType]; } } if (!empty($term)) { $intervenants = $recherche->rechercher($term, 40); $intervenants = array_values( $recherche->rechercher($term, 40, ':CODE', $typeCodes) ); } return new AxiosModel($intervenants); Loading module/Intervenant/src/Processus/RechercheProcessus.php +33 −9 Original line number Diff line number Diff line Loading @@ -25,18 +25,24 @@ class RechercheProcessus * * @return array */ public function rechercher ($critere, $limit = 50, string $key = ':CODE') public function rechercher ($critere, $limit = 50, string $key = ':CODE', array $typeIntervenantCodes = []) { try { return $this->rechercheGenerique($critere, $limit, $key, false); return $this->rechercheGenerique($critere, $limit, $key, false, $typeIntervenantCodes); } catch (\Exception $e) { return $this->rechercheGenerique($critere, $limit, $key, true); return $this->rechercheGenerique($critere, $limit, $key, true, $typeIntervenantCodes); } } private function rechercheGenerique ($critere, $limit = 50, string $key = ':CODE', $onlyLocale = false) private function rechercheGenerique ( $critere, $limit = 50, string $key = ':CODE', $onlyLocale = false, array $typeIntervenantCodes = [] ) { if (strlen($critere) < 2) return []; Loading @@ -49,8 +55,8 @@ class RechercheProcessus WITH vrec AS ( ' . $this->sqlLocale() . ' ) SELECT * FROM vrec WHERE rownum <= ' . (int)$limit . ' AND annee_id = ' . $anneeId; SELECT * FROM ( SELECT * FROM vrec WHERE annee_id = ' . $anneeId; $sqlCri = ''; $criCode = 0; Loading @@ -71,7 +77,20 @@ class RechercheProcessus $orc[] = 'code LIKE \'%' . $criCode . '%\''; } $orc = implode(' OR ', $orc); $sql .= ' AND (' . $orc . ') ORDER BY nom_usuel, prenom'; $validTypeCodes = array_values(array_intersect(['E', 'P', 'S'], $typeIntervenantCodes)); if ([] !== $validTypeCodes) { $quotedTypeCodes = array_map( static fn(string $code): string => "'" . $code . "'", $validTypeCodes ); $sql .= ' AND type_intervenant_code IN (' . implode(', ', $quotedTypeCodes) . ')'; } $sql .= ' AND (' . $orc . ') ORDER BY nom_usuel, prenom ) WHERE rownum <= ' . (int)$limit . ' ORDER BY nom_usuel, prenom'; $intervenants = []; Loading Loading @@ -225,9 +244,14 @@ class RechercheProcessus * * @return array */ public function rechercherLocalement ($critere, $limit = 50, string $key = ':CODE') public function rechercherLocalement ( $critere, $limit = 50, string $key = ':CODE', array $typeIntervenantCodes = [] ) { return $this->rechercheGenerique($critere, $limit, $key, true); return $this->rechercheGenerique($critere, $limit, $key, true, $typeIntervenantCodes); } /** Loading Loading
front/Intervenant/Recherche.vue +2 −1 Original line number Diff line number Diff line Loading @@ -122,7 +122,8 @@ export default { unicaenVue.axios.post( unicaenVue.url("intervenant/recherche-json"), { term: this.searchTerm term: this.searchTerm, types: this.checkedTypes, } ) .then(response => { Loading
module/Formule/src/Model/FormuleDetailsExtractor.php +71 −3 Original line number Diff line number Diff line Loading @@ -172,10 +172,78 @@ class FormuleDetailsExtractor implements ExtractionInterface $valeur = $this->trace->getValeur($typeHetd); $this->intervenant['hetd'][$typeHetd] = $this->valeurToJson($valeur); } //Mécanique d'arrondis du total si écart entre service du et total heure est de 0.01 HETD if ($this->intervenant['hetd']['HeuresService']['valeur'] > 0 && $this->intervenant['serviceDu'] > 0 && abs($this->intervenant['hetd']['HeuresService']['valeur'] - $this->intervenant['serviceDu']) <= 0.01) { $this->intervenant['hetd']['HeuresService']['valeur'] = $this->intervenant['serviceDu']; $this->reconcileIntervenantService(); } /** * Répercute un écart d'un centième entre le service calculé et le service dû * sur les valeurs affichées, tout en conservant leurs valeurs originales. */ private function reconcileIntervenantService(): void { $serviceKey = Ligne::CAT_SERVICE; if (!isset($this->intervenant['hetd'][$serviceKey])) { return; } $serviceDu = round($this->intervenant['serviceDu'], 2); $calculatedService = round($this->intervenant['hetd'][$serviceKey]['valeur'], 2); $difference = round($serviceDu - $calculatedService, 2); if ($serviceDu <= 0.0 || abs($difference) !== 0.01) { return; } $componentKeys = array_map( static fn(string $type): string => Ligne::CAT_SERVICE . $type, Ligne::TYPES ); $componentKeys = array_values(array_filter( $componentKeys, fn(string $key): bool => isset($this->intervenant['hetd'][$key]) )); if ([] !== $componentKeys) { usort( $componentKeys, fn(string $left, string $right): int => abs($this->intervenant['hetd'][$right]['valeur']) <=> abs($this->intervenant['hetd'][$left]['valeur']) ); $componentKey = $componentKeys[0]; $this->intervenant['hetd'][$componentKey]['valeur'] = round( $this->intervenant['hetd'][$componentKey]['valeur'] + $difference, 2 ); $enseignementKeys = array_map( static fn(string $type): string => Ligne::CAT_SERVICE . $type, Ligne::TYPES_ENSEIGNEMENT ); $enseignementKey = Ligne::CAT_SERVICE . Ligne::TYPE_ENSEIGNEMENT; if (in_array($componentKey, $enseignementKeys, true) && isset($this->intervenant['hetd'][$enseignementKey])) { $this->intervenant['hetd'][$enseignementKey]['valeur'] = round( $this->intervenant['hetd'][$enseignementKey]['valeur'] + $difference, 2 ); } } $this->intervenant['hetd'][$serviceKey]['valeur'] = $serviceDu; if (isset($this->intervenant['hetd'][Ligne::TOTAL])) { $this->intervenant['hetd'][Ligne::TOTAL]['valeur'] = round( $this->intervenant['hetd'][Ligne::TOTAL]['valeur'] + $difference, 2 ); } } Loading
module/Formule/src/Service/AfficheurService.php +31 −14 Original line number Diff line number Diff line Loading @@ -85,6 +85,10 @@ class AfficheurService } } if ($hasServiceStatutaire) { $this->reconcileServiceWithServiceDu($data['heures']['service'], $data['serviceDu']); } if (count($types) > 1) { $types[] = 'total'; foreach ($data['heures'] as $categorie => $values) { Loading @@ -109,28 +113,41 @@ class AfficheurService } } } } //Mécanique d'arrondis du total si écart entre service du et total heure est de 0.01 HETD $hasMultipleTypes = count($types) > 1; $serviceDu = $data['serviceDu']; return $data; } $total = $hasMultipleTypes ? $data['heures']['total']['total'] : current($data['heures']['total']); $hasRoundingDifference = abs($total - $serviceDu) <= 0.01; if ($total > 0 && $serviceDu > 0 && $hasRoundingDifference) { $key = $hasMultipleTypes ? 'total' : array_key_first($data['heures']['total']); /** * Répercute un écart d'arrondi d'un centième sur la plus grande composante * du service afin que la somme affichée corresponde au service dû. */ private function reconcileServiceWithServiceDu(array &$service, float $serviceDu): void { if ($serviceDu <= 0.0 || [] === $service) { return; } $data['heures']['total'][$key] = $serviceDu; $data['heures']['service'][$key] = $serviceDu; $roundedService = array_map(static fn(float $hours): float => round($hours, 2), $service); $difference = round(round($serviceDu, 2) - array_sum($roundedService), 2); if (abs($difference) !== 0.01) { return; } return $data; $keyToAdjust = array_keys( $roundedService, max($roundedService), true )[0]; $roundedService[$keyToAdjust] = round($roundedService[$keyToAdjust] + $difference, 2); $service = $roundedService; } }
module/Intervenant/src/Controller/IntervenantController.php +15 −1 Original line number Diff line number Diff line Loading @@ -128,9 +128,23 @@ class IntervenantController extends AbstractController $recherche->setShowHisto($canShowHistorises); $intervenants = []; $term = $this->axios()->fromPost('term'); $requestedTypes = (array)$this->axios()->fromPost('types', []); $typeCodesByFilter = [ 'vacataire' => 'E', 'permanent' => 'P', 'etudiant' => 'S', ]; $typeCodes = []; foreach ($requestedTypes as $requestedType) { if (isset($typeCodesByFilter[$requestedType])) { $typeCodes[] = $typeCodesByFilter[$requestedType]; } } if (!empty($term)) { $intervenants = $recherche->rechercher($term, 40); $intervenants = array_values( $recherche->rechercher($term, 40, ':CODE', $typeCodes) ); } return new AxiosModel($intervenants); Loading
module/Intervenant/src/Processus/RechercheProcessus.php +33 −9 Original line number Diff line number Diff line Loading @@ -25,18 +25,24 @@ class RechercheProcessus * * @return array */ public function rechercher ($critere, $limit = 50, string $key = ':CODE') public function rechercher ($critere, $limit = 50, string $key = ':CODE', array $typeIntervenantCodes = []) { try { return $this->rechercheGenerique($critere, $limit, $key, false); return $this->rechercheGenerique($critere, $limit, $key, false, $typeIntervenantCodes); } catch (\Exception $e) { return $this->rechercheGenerique($critere, $limit, $key, true); return $this->rechercheGenerique($critere, $limit, $key, true, $typeIntervenantCodes); } } private function rechercheGenerique ($critere, $limit = 50, string $key = ':CODE', $onlyLocale = false) private function rechercheGenerique ( $critere, $limit = 50, string $key = ':CODE', $onlyLocale = false, array $typeIntervenantCodes = [] ) { if (strlen($critere) < 2) return []; Loading @@ -49,8 +55,8 @@ class RechercheProcessus WITH vrec AS ( ' . $this->sqlLocale() . ' ) SELECT * FROM vrec WHERE rownum <= ' . (int)$limit . ' AND annee_id = ' . $anneeId; SELECT * FROM ( SELECT * FROM vrec WHERE annee_id = ' . $anneeId; $sqlCri = ''; $criCode = 0; Loading @@ -71,7 +77,20 @@ class RechercheProcessus $orc[] = 'code LIKE \'%' . $criCode . '%\''; } $orc = implode(' OR ', $orc); $sql .= ' AND (' . $orc . ') ORDER BY nom_usuel, prenom'; $validTypeCodes = array_values(array_intersect(['E', 'P', 'S'], $typeIntervenantCodes)); if ([] !== $validTypeCodes) { $quotedTypeCodes = array_map( static fn(string $code): string => "'" . $code . "'", $validTypeCodes ); $sql .= ' AND type_intervenant_code IN (' . implode(', ', $quotedTypeCodes) . ')'; } $sql .= ' AND (' . $orc . ') ORDER BY nom_usuel, prenom ) WHERE rownum <= ' . (int)$limit . ' ORDER BY nom_usuel, prenom'; $intervenants = []; Loading Loading @@ -225,9 +244,14 @@ class RechercheProcessus * * @return array */ public function rechercherLocalement ($critere, $limit = 50, string $key = ':CODE') public function rechercherLocalement ( $critere, $limit = 50, string $key = ':CODE', array $typeIntervenantCodes = [] ) { return $this->rechercheGenerique($critere, $limit, $key, true); return $this->rechercheGenerique($critere, $limit, $key, true, $typeIntervenantCodes); } /** Loading