Commit d3f42790 authored by Laurent Lecluse's avatar Laurent Lecluse
Browse files

Plein d'améliorations du système de génération de formules, WIP

parent 762c2ef9
Loading
Loading
Loading
Loading
+3 −2
Changes for admin/src/DataGen.php: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -591,11 +591,12 @@ class DataGen

    public function FORMULE()
    {
        $data     = $this->nomenclature['FORMULE'];
        $data = require $this->oseAdmin->getOseDir() . 'data/formules.php';;
        $formules = [];
        foreach ($data as $id => $formule) {
            $formule['ID'] = $id;
            $formule['PROCEDURE_NAME'] = 'CALCUL_RESULTAT';
            if (!isset($formule['INTERVENANT_QUERY'])) $formule['INTERVENANT_QUERY'] = null;
            if (!isset($formule['VOLUME_HORAIRE_QUERY'])) $formule['VOLUME_HORAIRE_QUERY'] = null;
            for ($i = 1; $i < 6; $i++) {
                if (!isset($formule['I_PARAM_' . $i . '_LIBELLE'])) $formule['I_PARAM_' . $i . '_LIBELLE'] = null;
                if (!isset($formule['VH_PARAM_' . $i . '_LIBELLE'])) $formule['VH_PARAM_' . $i . '_LIBELLE'] = null;
+43 −0
Changes for code/Créateur de formule.php: 43 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

use UnicaenCode\Util;

$name = strtoupper($_POST['name'] ?? '');

?>
    <form method="post" enctype="multipart/form-data">
        <div class="form-group">
            <label for="formule-name">Nom de la formule (pour nommer le package)</label>
            <input class="form-control" id="formule-name" type="text" name="name" value="<?= $name ?>"/>
        </div>

        <div class="form-group">
            <label for="formule-name">Feuille de calcul de la formule (format Excell ou OpenDocument Calc)</label>
            <input class="form-control" id="formule-fichier" type="file" name="fichier"/>
        </div>

        <div class="form-group">
            <button type="submit" name="action" value="generer" class="btn btn-primary">Générer le package</button>
            <button type="submit" name="action" value="voir" class="btn btn-default">Voir la feuille de calcul</button>
        </div>
    </form>
<?php
$action  = $_POST['action'] ?? 'generer';
$fichier = $_FILES['fichier'] ?? null;

if (!$fichier) {
    return;
}

$fc = new \Application\Model\FormuleCalcul($fichier['tmp_name'], $name);


switch ($action) {
    case 'voir':
        echo $fc->getSheet(1)->html();
    break;
    case 'generer':
        Util::highlight($fc->makePackageDef(), 'plsql', true, ['show-line-numbers' => true]);
        Util::highlight($fc->makePackageBody(), 'plsql', true, ['show-line-numbers' => true]);
    break;
}

code/FormuleTestColleur.php

deleted100644 → 0
+0 −214
Changes for code/FormuleTestColleur.php: 0 added lines, 214 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @var $this       \Application\View\Renderer\PhpRenderer
 * @var $controller \Laminas\Mvc\Controller\AbstractController
 * @var $container  \Psr\Container\ContainerInterface
 * @var $viewName   string
 * @var $viewFile   string
 */

$formuleTestIntervenantId = 3;

$save = false;
$save = true;

$structureUniversité = 'INSA';

$vhdata = "Dept1	Oui	Non	Oui	100,00 %	0,00 %	0,00 %	CM	1,50	1,50	1,00	1,00	25,00							24,78	0,00	0,00	0,00	12,72	0,00	0,00	0,00	0,00
Dept1	Oui	Non	Oui	100,00 %	0,00 %	0,00 %	TD	1,00	1,00	1,00	1,00	43,00							28,42	0,00	0,00	0,00	14,58	0,00	0,00	0,00	0,00
Dept1	Oui	Non	Oui	100,00 %	0,00 %	0,00 %	TP	1,00	0,67	1,00	1,00	172,00							113,68	0,00	0,00	0,00	38,88	0,00	0,00	0,00	0,00
Dept1	Oui	Non	Oui	100,00 %	0,00 %	0,00 %	Référentiel	1,00	1,00	1,00	1,00	0,00							0,00	0,00	0,00	0,00	0,00	0,00	0,00	0,00	0,00
Dept4	Non	Non	Oui	80,00 %	10,00 %	10,00 %	CM	1,50	1,50	1,00	1,00	8,00							6,34	0,79	0,79	0,00	3,26	0,41	0,41	0,00	0,00
Dept4	Non	Non	Oui	85,00 %	0,00 %	15,00 %	TD	1,00	1,00	1,00	1,00	22,00							12,36	0,00	2,18	0,00	6,34	0,00	1,12	0,00	0,00
Dept1	Oui	Non	Oui	50,00 %	0,00 %	50,00 %	TD	1,00	1,00	1,00	1,00	2,00							0,66	0,00	0,66	0,00	0,34	0,00	0,34	0,00	0,00
INSA	Non	Non	Oui	100,00 %	0,00 %	0,00 %	TD	1,00	1,00	1,00	1,00	2,00							1,32	0,00	0,00	0,00	0,68	0,00	0,00	0,00	0,00
INSA	Non	Non	Oui	100,00 %	0,00 %	0,00 %	Référentiel	1,00	1,00	1,00	1,00	0,00							0,00	0,00	0,00	0,00	0,00	0,00	0,00	0,00	0,00
";


/** @var \Doctrine\ORM\EntityManager $bdd */
$bdd = $container->get(\Application\Constants::BDD);
/** @var \Application\Service\FormuleTestIntervenantService $ftiService */
$ftiService = $container->get(\Application\Service\FormuleTestIntervenantService::class);
$fti        = $ftiService->get($formuleTestIntervenantId);
if (!$fti) {
    echo 'Mauvais ID de formule';

    return;
}

$lines = explode("\n", $vhdata);
$vhs   = [];
foreach ($lines as $l) {
    if (!empty($l)) {
        $l = explode("\t", $l);

        $structureCode = trim($l[0]);
        $rcode         = \UnicaenApp\Util::reduce($structureCode);
        $isUniv        = ($structureCode == $structureUniversité) || (false !== strpos($rcode, 'univ'));
        if ($isUniv) $structureCode = '__UNIV__';

        $tiCode      = trim($l[7]);
        $referentiel = \UnicaenApp\Util::reduce($tiCode) == 'referentiel';

        $vh = new \Application\Entity\Db\FormuleTestVolumeHoraire();
        $vh->setFormuleTestIntervenant($fti);
        $vh->setStructureCode($structureCode);
        $vh->setServiceStatutaire(cBool($l[3]));
        $vh->setTauxFi(cPourc($l[4]));
        $vh->setTauxFa(cPourc($l[5]));
        $vh->setTauxFc(cPourc($l[6]));
        $vh->setTypeInterventionCode($tiCode);
        $vh->setReferentiel($referentiel);
        $vh->setPonderationServiceDu(cFloat($l[10]));
        $vh->setPonderationServiceCompl(cFloat($l[11]));
        $vh->setHeures(cFloat($l[12]));
        $vh->setParam1(trim($l[13]) ?: null);
        $vh->setParam2(trim($l[14]) ?: null);
        $vh->setParam3(trim($l[15]) ?: null);
        $vh->setParam4(trim($l[16]) ?: null);
        $vh->setParam5(trim($l[17]) ?: null);
        $vh->setAServiceFi(cFloat($l[19]));
        $vh->setAServiceFa(cFloat($l[20]));
        $vh->setAServiceFc(cFloat($l[21]));
        $vh->setAServiceReferentiel(cFloat($l[22]));
        $vh->setAHeuresComplFi(cFloat($l[23]));
        $vh->setAHeuresComplFa(cFloat($l[24]));
        $vh->setAHeuresComplFc(cFloat($l[25]));
        $vh->setAHeuresComplFcMajorees(cFloat($l[26]));
        $vh->setAHeuresComplReferentiel(cFloat($l[27]));
        $vhs[] = $vh;
    }
}


?>

    <style>
        table {
            font-size: 8pt;
        }
    </style>
    <table class="table table-bordered table-condensed table-extra-condensed table-hover">
        <tr>
            <th colspan="18">Entrée</th>
            <th colspan="9">Résultats attendus</th>
        </tr>
        <tr>
            <th>Structure code</th>
            <th>Structure is affectation</th>
            <th>Structure is univ</th>
            <th>Service statutaire</th>
            <th>Taux fi</th>
            <th>Taux fa</th>
            <th>Taux fc</th>
            <th>Type intervention code</th>
            <th>Taux service du</th>
            <th>Taux service compl</th>
            <th>Ponderation service du</th>
            <th>Ponderation service compl</th>
            <th>Heures</th>
            <th>Param 1</th>
            <th>Param 2</th>
            <th>Param 3</th>
            <th>Param 4</th>
            <th>Param 5</th>
            <th>SFi</th>
            <th>SFa</th>
            <th>SFc</th>
            <th>SRef</th>
            <th>HCFi</th>
            <th>HCFa</th>
            <th>HCFc</th>
            <th>HCFcM</th>
            <th>HCRef</th>
        </tr>
        <?php foreach ($vhs as $vh):
            if ($vh->getReferentiel()) {
                $tauxServiceDu    = 1;
                $tauxServiceCompl = 1;
            } else {
                switch ($vh->getTypeInterventionCode()) {
                    case 'CM':
                        $tauxServiceDu    = $fti->getTauxCmServiceDu();
                        $tauxServiceCompl = $fti->getTauxCmServiceCompl();
                    break;
                    case 'TD':
                        $tauxServiceDu    = 1;
                        $tauxServiceCompl = 1;
                    break;
                    case 'TP':
                        $tauxServiceDu    = $fti->getTauxTpServiceDu();
                        $tauxServiceCompl = $fti->getTauxTpServiceCompl();
                    break;
                    default:
                        $tauxServiceDu    = $fti->getTauxAutreServiceDu();
                        $tauxServiceCompl = $fti->getTauxAutreServiceCompl();
                }
            }

            ?>
            <tr>
                <td><?= $vh->getStructureCode(); ?></td>
                <td><?= ($vh->getStructureCode() == $fti->getStructureCode()) ? 'Oui' : 'Non'; ?></td>
                <td><?= ($vh->getStructureCode() == '__UNIV__') ? 'Oui' : 'Non' ?></td>
                <td><?= $vh->getServiceStatutaire() ? 'Oui' : 'Non'; ?></td>
                <td><?= floatToString($vh->getTauxFi() * 100); ?>%</td>
                <td><?= floatToString($vh->getTauxFa() * 100); ?>%</td>
                <td><?= floatToString($vh->getTauxFc() * 100); ?>%</td>
                <td><?= $vh->getReferentiel() ? 'Référentiel' : $vh->getTypeInterventionCode(); ?></td>
                <td><?= floatToString($tauxServiceDu); ?></td>
                <td><?= floatToString($tauxServiceCompl); ?></td>
                <td><?= floatToString($vh->getPonderationServiceDu()); ?></td>
                <td><?= floatToString($vh->getPonderationServiceCompl()); ?></td>
                <td><?= floatToString($vh->getHeures()); ?></td>
                <td><?= $vh->getParam1(); ?></td>
                <td><?= $vh->getParam2(); ?></td>
                <td><?= $vh->getParam3(); ?></td>
                <td><?= $vh->getParam4(); ?></td>
                <td><?= $vh->getParam5(); ?></td>
                <td><?= floatToString($vh->getAServiceFi()); ?></td>
                <td><?= floatToString($vh->getAServiceFa()); ?></td>
                <td><?= floatToString($vh->getAServiceFc()); ?></td>
                <td><?= floatToString($vh->getAServiceReferentiel()); ?></td>
                <td><?= floatToString($vh->getAHeuresComplFi()); ?></td>
                <td><?= floatToString($vh->getAHeuresComplFa()); ?></td>
                <td><?= floatToString($vh->getAHeuresComplFc()); ?></td>
                <td><?= floatToString($vh->getAHeuresComplFcMajorees()); ?></td>
                <td><?= floatToString($vh->getAHeuresComplReferentiel()); ?></td>
            </tr>
        <?php endforeach; ?>
    </table>
<?php


function cBool($value): bool
{
    return trim(strtolower($value)) == 'oui';
}


function cPourc($value): float
{
    $value = trim(str_replace('%', '', $value));

    return cFloat($value) / 100;
}


function cFloat($value): float
{
    $value = trim($value);
    $value = str_replace(',', '.', $value);

    return (float)$value;
}

if ($save) {
    $bdd->getConnection()->executeStatement('DELETE FROM formule_test_volume_horaire WHERE intervenant_test_id = ' . $formuleTestIntervenantId);
    foreach ($vhs as $vh) {
        $bdd->persist($vh);
        $bdd->flush($vh);
    }
}
 No newline at end of file
+13 −23
Changes for code/test1.php: 13 added lines, 23 removed lines.
Original line number Diff line number Diff line
@@ -8,27 +8,17 @@
 * @var $viewFile   string
 */

/** @var $em \Doctrine\ORM\EntityManager */
$em = $container->get(\Application\Constants::BDD);


/** @var \Intervenant\Entity\Db\Statut $s */
$s = $em->find(\Intervenant\Entity\Db\Statut::class, 2799);
//$s->setServiceStatutaire($s->getServiceStatutaire() + 1);
//$em->persist($s);
//$em->flush($s);

/*
$ps = new \Plafond\Entity\Db\PlafondStatut();
$ps->setPlafond($em->find(\Plafond\Entity\Db\Plafond::class, 2));
$ps->setStatut($s);
$ps->setEtatRealise($em->find(\Plafond\Entity\Db\PlafondEtat::class, 1));
$ps->setEtatPrevu($em->find(\Plafond\Entity\Db\PlafondEtat::class, 2));
$ps->setHeures(1);
*/
use UnicaenCode\Util;

$fc = new \Application\Model\FormuleCalcul(getcwd() . '/cache/guyane.xlsx', 'GUYANE');


$f = 'IF(ISERROR([.J20]);1;[.J20])*IF(AND([.$A20]="ES3";i_structure_code<>"ES3";[.$AE$15]>=12);4/3;1)';

$f = 'SUM([.AD$1:.AD$1048576])';

return $fc->testFormule($f);

//echo $fc->getSheet(1)->html();

/** @var \Plafond\Entity\Db\PlafondStatut $ps */
$ps = $em->find(\Plafond\Entity\Db\PlafondStatut::class, 952);
$ps->setHeures($ps->getHeures() + 1);
$em->persist($ps);
$em->flush($ps);
Util::highlight($fc->makePackageBody(), 'plsql', true, ['show-line-numbers' => true]);

data/formule.sql

0 → 100644
+205 −0
Changes for data/formule.sql: 205 added lines, 0 removed lines.
Original line number Diff line number Diff line
CREATE OR REPLACE PACKAGE BODY FORMULE_<--NAME--> AS
  decalageLigne NUMERIC DEFAULT <--DECALAGE-->;

  /* Stockage des valeurs intermédiaires */
  TYPE t_cell IS RECORD (
    valeur FLOAT,
    enCalcul BOOLEAN DEFAULT FALSE
  );
  TYPE t_cells IS TABLE OF t_cell INDEX BY PLS_INTEGER;
  TYPE t_coll IS RECORD (
    cells t_cells
  );
  TYPE t_colls IS TABLE OF t_coll INDEX BY VARCHAR2(50);
  feuille t_colls;

  debugLine NUMERIC;


  PROCEDURE dbg( val CLOB ) IS
  BEGIN
    ose_formule.volumes_horaires.items(debugLine).debug_info :=
    ose_formule.volumes_horaires.items(debugLine).debug_info || val;
  END;


  PROCEDURE dbgi( val CLOB ) IS
  BEGIN
    ose_formule.intervenant.debug_info := ose_formule.intervenant.debug_info || val;
  END;

  PROCEDURE dbgDump( val CLOB ) IS
  BEGIN
    dbg('<div class="dbg-dump">' || val || '</div>');
  END;

  PROCEDURE dbgCell( c VARCHAR2, l NUMERIC, val FLOAT ) IS
    ligne NUMERIC;
  BEGIN
    ligne := l;
    IF l <> 0 THEN
      ligne := ligne + decalageLigne;
    END IF;

    dbgi( '[cell|' || c || '|' || ligne || '|' || val );
  END;

  PROCEDURE dbgCalc( fncName VARCHAR2, c VARCHAR2, res FLOAT ) IS
  BEGIN
    dbgi( '[calc|' || fncName || '|' || c || '|' || res );
  END;

  FUNCTION cell( c VARCHAR2, l NUMERIC DEFAULT 0 ) RETURN FLOAT IS
    val FLOAT;
  BEGIN
    IF feuille.exists(c) THEN
      IF feuille(c).cells.exists(l) THEN
        IF feuille(c).cells(l).enCalcul THEN
          raise_application_error( -20001, 'Dépendance cyclique : la cellule [' || c || ';' || l || '] est déjà en cours de calcul');
        END IF;
        RETURN feuille(c).cells(l).valeur;
      END IF;
    END IF;

    feuille(c).cells(l).enCalcul := true;
    val := calcCell( c, l );
    IF ose_formule.debug_actif THEN
      dbgCell( c, l, val );
    END IF;
    feuille(c).cells(l).valeur := val;
    feuille(c).cells(l).enCalcul := false;

    RETURN val;
  END;

  FUNCTION mainCell( libelle VARCHAR2, c VARCHAR2, l NUMERIC ) RETURN FLOAT IS
    val FLOAT;
  BEGIN
    debugLine := l;
    val := cell(c,l);

    RETURN val;
  END;

  FUNCTION calcFnc( fncName VARCHAR2, c VARCHAR2 ) RETURN FLOAT IS
    val FLOAT;
    cellRes FLOAT;
  BEGIN
    IF feuille.exists('__' || fncName || '__' || c || '__') THEN
      IF feuille('__' || fncName || '__' || c || '__').cells.exists(1) THEN
        RETURN feuille('__' || fncName || '__' || c || '__').cells(1).valeur;
      END IF;
    END IF;
    CASE
    -- Liste des fonctions supportées

    WHEN fncName = 'somme' THEN
      val := 0;
      FOR l IN 1 .. ose_formule.volumes_horaires.length LOOP
        val := val + COALESCE(cell(c, l),0);
      END LOOP;

    WHEN fncName = 'max' THEN
      val := NULL;
      FOR l IN 1 .. ose_formule.volumes_horaires.length LOOP
        cellRes := cell(c,l);
        IF val IS NULL OR val < cellRes THEN
          val := cellRes;
        END IF;
      END LOOP;

    -- fin de la liste des fonctions supportées
    ELSE
      raise_application_error( -20001, 'La formule "' || fncName || '" n''existe pas!');
    END CASE;
    IF ose_formule.debug_actif THEN
      dbgCalc(fncName, c, val );
    END IF;
    feuille('__' || fncName || '__' || c || '__').cells(1).valeur := val;

    RETURN val;
  END;



  FUNCTION calcCell( c VARCHAR2, l NUMERIC ) RETURN FLOAT IS
    vh ose_formule.t_volume_horaire;
    i  ose_formule.t_intervenant;
    val FLOAT;
  BEGIN
    i := ose_formule.intervenant;
    IF l > 0 THEN
      vh := ose_formule.volumes_horaires.items(l);
    END IF;
    CASE c



<--CELLS-->
    ELSE
      raise_application_error( -20001, 'La colonne c=' || c || ', l=' || l || ' n''existe pas!');
  END CASE;
  raise_application_error( -20001, 'La colonne c=' || c || ', l=' || l || ' n''existe pas!');

  END;



  PROCEDURE CALCUL_RESULTAT IS
  BEGIN
    feuille.delete;

    IF ose_formule.intervenant.depassement_service_du_sans_hc THEN -- HC traitées comme du service
      ose_formule.intervenant.service_du := ose_formule.intervenant.heures_service_statutaire + ose_formule.intervenant.heures_service_modifie;
    END IF;

    -- transmission des résultats aux volumes horaires et volumes horaires référentiel
    FOR l IN 1 .. ose_formule.volumes_horaires.length LOOP
      ose_formule.volumes_horaires.items(l).service_fi               := mainCell('Service FI', <--vh.service_fi-->,l);
      ose_formule.volumes_horaires.items(l).service_fa               := mainCell('Service FA', <--vh.service_fa-->,l);
      ose_formule.volumes_horaires.items(l).service_fc               := mainCell('Service FC', <--vh.service_fc-->,l);
      ose_formule.volumes_horaires.items(l).service_referentiel      := mainCell('Service référentiel', <--vh.service_referentiel-->,l);
      ose_formule.volumes_horaires.items(l).heures_compl_fi          := mainCell('Heures compl. FI', <--vh.heures_compl_fi-->,l);
      ose_formule.volumes_horaires.items(l).heures_compl_fa          := mainCell('Heures compl. FA', <--vh.heures_compl_fa-->,l);
      ose_formule.volumes_horaires.items(l).heures_compl_fc          := mainCell('Heures compl. FC', <--vh.heures_compl_fc-->,l);
      ose_formule.volumes_horaires.items(l).heures_compl_fc_majorees := mainCell('Heures compl. FC Maj.', <--vh.heures_compl_fc_majorees-->,l);
      ose_formule.volumes_horaires.items(l).heures_compl_referentiel := mainCell('Heures compl. référentiel', <--vh.heures_compl_referentiel-->,l);
    END LOOP;
  END;



  FUNCTION INTERVENANT_QUERY RETURN CLOB IS
  BEGIN
    RETURN '
    SELECT
      fi.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_INTERVENANT fi
    ';
  END;



  FUNCTION VOLUME_HORAIRE_QUERY RETURN CLOB IS
  BEGIN
    RETURN '
    SELECT
      fvh.*,
      NULL param_1,
      NULL param_2,
      NULL param_3,
      NULL param_4,
      NULL param_5
    FROM
      V_FORMULE_VOLUME_HORAIRE fvh
    ORDER BY
      ordre';
  END;

END FORMULE_<--NAME-->;
 No newline at end of file
Loading