Commit 05d1b2f7 authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

WIP debug arrondisseur

Possibilité d'avoir plusieurs erreurs sur un même nombre
Calcul des tests en deux passes
Possibilité de limiter le taux d'erreur pour le mode minimal
parent 90b26fb6
Loading
Loading
Loading
Loading
Loading
+1 −1
Changes for code/formules/testArrondisseurFromService.php: 1 added line, 1 removed line.
Original line number Diff line number Diff line
@@ -69,5 +69,5 @@ $fi->setArrondisseur((int)$params['arrondir']);
if (isset($fi)) {
    $ts->getServiceFormule()->calculer($fi);
    $aff = new \Formule\Model\Arrondisseur\Afficheur();
    $aff->afficher($fi->getArrondisseurTrace());
    $aff->afficher($fi);
}
 No newline at end of file
+5 −9
Changes for code/formules/testArrondisseurMassif.php: 5 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ if (!$bdd->table()->exists($testTablename)) {
      0 err_full, 
      0 err_custom_min, 
      0 err_custom_full 
    from formule_resultat_intervenant fri JOIN intervenant i ON i.id = fri.intervenant_id";
    from formule_resultat_intervenant fri JOIN intervenant i ON i.id = fri.intervenant_id AND fri.etat_volume_horaire_id = 1";
    $bdd->exec($sql);
}

@@ -67,23 +67,19 @@ foreach ($data as $d) {

    $fi->setArrondisseur(FormuleIntervenant::ARRONDISSEUR_NO);
    $ts->getServiceFormule()->calculer($fi);
    $trace               = $fi->getArrondisseurTrace();
    $resData['ERR_NONE'] = $testeur->tester($trace);
    $resData['ERR_NONE'] = $testeur->tester($fi);

    $fi->setArrondisseur(FormuleIntervenant::ARRONDISSEUR_MINIMAL);
    $ts->getServiceFormule()->calculer($fi);
    $trace                  = $fi->getArrondisseurTrace();
    $resData['ERR_MINIMAL'] = $testeur->tester($trace);
    $resData['ERR_MINIMAL'] = $testeur->tester($fi);

    $fi->setArrondisseur(FormuleIntervenant::ARRONDISSEUR_FULL);
    $ts->getServiceFormule()->calculer($fi);
    $trace               = $fi->getArrondisseurTrace();
    $resData['ERR_FULL'] = $testeur->tester($trace);
    $resData['ERR_FULL'] = $testeur->tester($fi);

    $fi->setArrondisseur(FormuleIntervenant::ARRONDISSEUR_CUSTOM);
    $ts->getServiceFormule()->calculer($fi);
    $trace                      = $fi->getArrondisseurTrace();
    $resData['ERR_CUSTOM_FULL'] = $testeur->tester($trace);
    $resData['ERR_CUSTOM_FULL'] = $testeur->tester($fi);

    $bdd->getTable($testTablename)->update($resData, $resKey);
}
+17 −7
Changes for module/Formule/src/Model/Arrondisseur/Afficheur.php: 17 added lines, 7 removed lines.
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@

namespace Formule\Model\Arrondisseur;

use Formule\Entity\FormuleIntervenant;

class Afficheur
{
    private Testeur $testeur;
@@ -15,9 +17,11 @@ class Afficheur



    public function afficher(Ligne $ligne)
    public function afficher(FormuleIntervenant $fi)
    {
        $errors = $this->testeur->tester($ligne);
        $ligne = $fi->getArrondisseurTrace();

        $errors = $this->testeur->tester($fi);
        echo $errors . ' Erreurs';
        $main = $ligne;
        echo '<table class="table table-bordered table-xs">';
@@ -100,12 +104,18 @@ class Afficheur
        ];
        $color = 'transparent';

        if ($valeur->hasControle()) {
            $title[] = 'Valeur de contrôle : ' . $valeur->getControle();
            if ($valeur->isControleOk()) {
                $color = '#C4FFC5';
            } else {
        $errors = $valeur->getErrors();

        if ($valeur->hasError()) {
            $color = '#FFC4C4';
        } else {
            $color = '#C4FFC5';
        }

        if (!empty($errors)) {
            $title[] = 'Erreurs :';
            foreach ($errors as $error) {
                $title[] = ' - '.$error;
            }
        }

+2 −1
Changes for module/Formule/src/Model/Arrondisseur/Arrondisseur.php: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -88,7 +88,8 @@ class Arrondisseur
        foreach ($services as $service) {
            $vhs = $service->getSubs();
            foreach ($vhs as $vh) {
                $this->preparationHorizontaleMontante($vh);
                //$this->preparationHorizontaleMontante($vh);
                $this->preparationHorizontaleDescendante($vh);
            }
        }
    }
+182 −73
Changes for module/Formule/src/Model/Arrondisseur/Testeur.php: 182 added lines, 73 removed lines.
Original line number Diff line number Diff line
@@ -2,134 +2,211 @@

namespace Formule\Model\Arrondisseur;

use Formule\Entity\FormuleIntervenant;

class Testeur
{
    public function tester(Ligne $data): int
    {
        $errors = 0;
    public bool $depassementServiceDuSansHC = false;
    public int  $arrondisseurMode           = 0;

        $this->remonteeTotaux($data);

        $services = $data->getSubs();
        foreach ($services as $service) {
            $this->calcSommesLigne($service);
            $vhs = $service->getSubs();
            foreach ($vhs as $vh) {
                $this->calcSommesLigne($vh);
                $this->controleColonnes($vh);
                $errors += $this->countErrorsLigne($vh);
            }
            $errors += $this->countErrorsLigne($service);
        }

        $errors += $this->countErrorsLigne($data);
    public function tester(FormuleIntervenant $fi): int
    {
        $this->depassementServiceDuSansHC = $fi->isDepassementServiceDuSansHC();
        $this->arrondisseurMode           = $fi->getArrondisseur();

        return $errors;
    }
        $data = $fi->getArrondisseurTrace();

        // première passe
        $this->controleColonnes($data);

        // on recalcule les totaux
        $this->recalculTotaux($data);

    protected function countErrorsLigne(Ligne $data): int
    {
        $errors = 0;
        foreach ($data->getValeurs() as $valeur) {
            if (!$valeur->isControleOk()) $errors++;
        // comptage d'erreurs en seconde passe
        $errors = $this->controleColonnes($data);

        $serviceDuCalcule = $data->getValeur(Ligne::CAT_SERVICE)->getValueFinale();

        if ($serviceDuCalcule != $fi->getServiceDu() && $this->arrondisseurMode == FormuleIntervenant::ARRONDISSEUR_FULL) {
            $errors++;
            $data->getValeur(Ligne::CAT_SERVICE)->addError(
                'Le service calculé (' . $serviceDuCalcule . ') ne correspond pas au service dû (' . $fi->getServiceDu() . ')'
            );
        }

        return $errors;
    }



    protected function controleColonnes(Ligne $ligne): void
    protected function controleColonnes(Ligne $ligne): int
    {
        if ($ligne->getVolumeHoraire()){
            $vh = $ligne->getVolumeHoraire();
            $pService = $vh->getTauxServiceDu() * $vh->getPonderationServiceDu();
            $pCompl = $vh->getTauxServiceCompl() * $vh->getPonderationServiceCompl();
        $errors = 0;

            if ($ligne->getValeur(Ligne::CAT_SERVICE)->getValue() != 0 && $ligne->getValeur(Ligne::CAT_COMPL)->getValue() == 0 && $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValue() == 0){
                $ligne->getValeur(Ligne::TOTAL)->setControle($vh->getHeures() * $pService);
            }
            if ($ligne->getValeur(Ligne::CAT_SERVICE)->getValue() == 0 && $ligne->getValeur(Ligne::CAT_COMPL)->getValue() != 0 && $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValue() == 0){
                $ligne->getValeur(Ligne::TOTAL)->setControle($vh->getHeures() * $pCompl);
        $valeurs = $ligne->getValeurs();
        $subs    = $ligne->getSubs();

        $totaux  = [];
        $calculs = [];
        foreach ($valeurs as $valeur) {
            $vn           = $valeur->getName();
            $totaux[$vn]  = $valeur->getValueFinale();
            $calculs[$vn] = 0.0;
        }
            if ($ligne->getValeur(Ligne::CAT_SERVICE)->getValue() == 0 && $ligne->getValeur(Ligne::CAT_COMPL)->getValue() == 0 && $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValue() != 0){
                $ligne->getValeur(Ligne::TOTAL)->setControle($vh->getHeuresPrimes() * $pCompl);

        if ($ligne->getSup()) {
            $errors += $this->controleLigne($ligne);
        } else {
            if ($this->arrondisseurMode == FormuleIntervenant::ARRONDISSEUR_FULL) {
                $errors += $this->controleLigne($ligne);
            }
            if (abs($pService-$pCompl) < 0.001){ // taux service = taux compl
                $ligne->getValeur(Ligne::TOTAL)->setControle($vh->getHeures() * $pCompl);
        }

        if (empty($subs)) {
            return $errors;
        }
        foreach( $ligne->getValeurs() as $valeur ){
            $value = $valeur->getValueFinale();

            $sValeur = $ligne->getSup()->getValeur($valeur->getName());
            $sValeur->setControle(round($sValeur->getControle() + $value,2));
        foreach ($subs as $sub) {
            foreach ($valeurs as $valeur) {
                $vn           = $valeur->getName();
                $calculs[$vn] += $sub->getValeur($vn)->getValueFinale();
            }
            $errors += $this->controleColonnes($sub);
        }

            $tValeur = $sValeur->getLigne()->getSup()->getValeur($valeur->getName());
            $tValeur->setControle(round($tValeur->getControle() + $value,2));
        foreach ($valeurs as $valeur) {
            $vn = $valeur->getName();
            if (round($calculs[$vn], 2) != $totaux[$vn]) {
                if ($this->arrondisseurMode == FormuleIntervenant::ARRONDISSEUR_FULL || $ligne->getSup()) {
                    $errors++;
                    $valeur->addError('Somme des sous-valeurs de colonne = ' . $calculs[$vn] . " contre " . $totaux[$vn] . " attendu");
                }
            }
        }

        return $errors;
    }


    protected function controleSommesLigne(Ligne $ligne): void

    protected function controleLigne(Ligne $ligne): int
    {
        $sommeTotale = $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValueFinale();
        $errors = 0;

        $total  = $ligne->getValeur(Ligne::TOTAL)->getValueFinale();
        $sTotal = $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValueFinale();

        foreach (Ligne::CATEGORIES as $categorie) {
            $somme =
                $ligne->getValeur($categorie . Ligne::TYPE_FI)->getValueFinale()
                + $ligne->getValeur($categorie . Ligne::TYPE_FA)->getValueFinale()
                + $ligne->getValeur($categorie . Ligne::TYPE_FC)->getValueFinale();
            $sTotal += $ligne->getValeur($categorie)->getValueFinale();

            $catTotal  = $ligne->getValeur($categorie)->getValueFinale();
            $catSTotal = 0.0;

            $catSTotal += $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->getValueFinale();
            $catSTotal += $ligne->getValeur($categorie . Ligne::TYPE_REFERENTIEL)->getValueFinale();
            $catSTotal = round($catSTotal, 2);

            if ($catTotal != $catSTotal) {
                $errors++;
                $ligne->getValeur($categorie)->addError('Total Enseignement + référentiel = ' . $catSTotal . " contre " . $catTotal . " attendu");
            }

            $somme = round($somme, 2);

            $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->setControle($somme);
            $catEnsTotal  = $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->getValueFinale();
            $casEnsFi     = $ligne->getValeur($categorie . Ligne::TYPE_FI)->getValueFinale();
            $casEnsFa     = $ligne->getValeur($categorie . Ligne::TYPE_FA)->getValueFinale();
            $casEnsFc     = $ligne->getValeur($categorie . Ligne::TYPE_FC)->getValueFinale();
            $catEnsSTotal = round($casEnsFi + $casEnsFa + $casEnsFc, 2);

            $somme += $ligne->getValeur($categorie . Ligne::TYPE_REFERENTIEL)->getValueFinale();
            $somme = round($somme, 2);
            if ($catEnsTotal != $catEnsSTotal) {
                $errors++;
                $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->addError('Total FI + FA + FC = ' . $catEnsSTotal . " contre " . $catEnsTotal . " attendu");
            }

            $ligne->getValeur($categorie)->setControle($somme);
        }
        $sTotal = round($sTotal, 2);
        // ajouter les primes au sous-total ???

            $sommeTotale += $somme;
        if ($total != $sTotal) {
            $errors++;
            $ligne->getValeur(Ligne::TOTAL)->addError('Total Service + HC + Non payable = ' . $sTotal . " contre " . $total . " attendu");
        }

        $sommeTotale = round($sommeTotale, 2);
        $ligne->getValeur(Ligne::TOTAL)->setControle($sommeTotale);
        $errors += $this->controleTotauxVh($ligne);

        return $errors;
    }



    protected function calcSommesLigne(Ligne $ligne): void
    protected function controleTotauxVh(Ligne $ligne): int
    {
        $sommeTotale = $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValueFinale();
        if (!$ligne->getVolumeHoraire()) {
            return 0;
        }

        foreach (Ligne::CATEGORIES as $categorie) {
            $somme =
                $ligne->getValeur($categorie . Ligne::TYPE_FI)->getValueFinale()
                + $ligne->getValeur($categorie . Ligne::TYPE_FA)->getValueFinale()
                + $ligne->getValeur($categorie . Ligne::TYPE_FC)->getValueFinale();
        $erreurs = 0;

            $somme = round($somme, 2);
        $total    = $ligne->getValeur(Ligne::TOTAL);
        $vh       = $ligne->getVolumeHoraire();
        $pService = $vh->getTauxServiceDu() * $vh->getPonderationServiceDu();
        $pCompl   = $vh->getTauxServiceCompl() * $vh->getPonderationServiceCompl();

            $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->setValue($somme);
        $ponderation = null;

            $somme += $ligne->getValeur($categorie . Ligne::TYPE_REFERENTIEL)->getValueFinale();
            $somme = round($somme, 2);
        if (null === $ponderation && $pService == $pCompl){
            $ponderation = $pCompl;
        }

            $ligne->getValeur($categorie)->setValue($somme);
        if (null === $ponderation && $total->getValueFinale() == $ligne->getValeur(Ligne::CAT_SERVICE)->getValueFinale()) {
            $ponderation = $pService;
        }

            $sommeTotale += $somme;
        if (null === $ponderation && $ligne->getValeur(Ligne::CAT_SERVICE)->getValueFinale() == 0) {
            $ponderation = $pCompl;
        }

        $sommeTotale = round($sommeTotale, 2);
        $ligne->getValeur(Ligne::TOTAL)->setValue($sommeTotale);
        if ($ponderation === null) {
            return 0; // Calcul HETD impossible à refaire en ponderations multiples
        }

        $hetd   = round($vh->getHeures() * $ponderation, 2);
        $sTotal = $total->getValueFinale();


        if ($this->depassementServiceDuSansHC && $sTotal > $hetd && $ponderation == 0.67) {
            // Hack pour contourner pb tableur ?
            $hetd = round($vh->getHeures() * 1, 2);
        }

        if ($sTotal != $hetd) {
            $totalService = $ligne->getSup()->getValeur(Ligne::TOTAL)->getValueFinale();
            if ($sTotal == 0 && $totalService == 0) {
                $hetd = 0; // on passe le HETD à 0, car on est sur une compensation au niveau service (+128 - 128) => 0 HETD dans les 2 cas
            }
        }

    protected function remonteeTotaux(Ligne $ligne)

        if ($this->depassementServiceDuSansHC) {
            if ($sTotal > $hetd) {
                $erreurs++;
                $total->addError('Le total HETD est trop important par rapport au nombre d\'heures saisies (' . $hetd . ')');
            }
        } else {
            if ($sTotal != $hetd) {
                $erreurs++;
                $total->addError('Le total HETD ne correspond pas au nombre d\'hetd calculées (' . $hetd . ')');
            }
        }

        return $erreurs;
    }



    protected function recalculTotaux(Ligne $ligne)
    {
        $vns = [
            Ligne::CAT_TYPE_PRIME,
@@ -143,13 +220,18 @@ class Testeur
            $vns[] = $categorie . Ligne::TYPE_REFERENTIEL;
        }

        $this->recalculTotauxHorizontaux($ligne);
        foreach ($vns as $vn) {
            $iVal = $ligne->getValeur($vn);
            $iVal->setValue(0);
            $iVal->resetErrors();
            foreach ($ligne->getSubs() as $service) {
                $this->recalculTotauxHorizontaux($service);
                $sVal = $service->getValeur($vn);
                $sVal->setValue(0);
                $sVal->resetErrors();
                foreach ($service->getSubs() as $vh) {
                    $this->recalculTotauxHorizontaux($vh);
                    $vhValue = $vh->getValeur($vn)->getValueFinale();
                    $iVal->setValue($iVal->getValue() + $vhValue);
                    $sVal->setValue($sVal->getValue() + $vhValue);
@@ -157,4 +239,31 @@ class Testeur
            }
        }
    }



    protected function recalculTotauxHorizontaux(Ligne $ligne)
    {
        $total = $ligne->getValeur(Ligne::CAT_TYPE_PRIME)->getValueFinale();
        foreach (Ligne::CATEGORIES as $categorie) {
            // ens = fi + fa + fc
            $ens = $ligne->getValeur($categorie . Ligne::TYPE_FI)->getValueFinale();
            $ens += $ligne->getValeur($categorie . Ligne::TYPE_FA)->getValueFinale();
            $ens += $ligne->getValeur($categorie . Ligne::TYPE_FC)->getValueFinale();
            $ens = round($ens, 2);
            $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->setValue($ens);
            $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->resetErrors();


            //total categorie = ens + referentiel
            $cat = $ligne->getValeur($categorie . Ligne::TYPE_ENSEIGNEMENT)->getValueFinale();
            $cat += $ligne->getValeur($categorie . Ligne::TYPE_REFERENTIEL)->getValueFinale();
            $ligne->getValeur($categorie)->setValue($cat);
            $ligne->getValeur($categorie)->resetErrors();

            $total += $cat;
        }
        $ligne->getValeur(Ligne::TOTAL)->setValue($total);
        $ligne->getValeur(Ligne::TOTAL)->resetErrors();
    }
}
 No newline at end of file
Loading