Commit 4f49934a authored by Stephane Bouvry's avatar Stephane Bouvry
Browse files

- Fix : Dans l'administration des comptes utilisés, les comptes qualifés par...

 - Fix : Dans l'administration des comptes utilisés, les comptes qualifés par une masse héritées n'apparaissent plus en rouge et la masse héritée est affichées
 - Fix : Dans la fiche activité (synthèse des dépenses), les données ignorées apparaissent correctement
 - Fix : Dans le détail des dépenses, les données ignorées apparaissent correctement
 - Note : la qualification des dépenses Hors-Masse n'est disponible que depuis l'écran de détails des dépenses
parent ff362b46
Loading
Loading
Loading
Loading
+11 −17
Changes for module/Oscar/src/Oscar/Service/ProjectGrantApiService.php: 11 added lines, 17 removed lines.
Original line number Diff line number Diff line
@@ -53,7 +53,8 @@ use UnicaenSignature\Provider\SignaturePrivileges;
use UnicaenSignature\Service\SignatureService;
use UnicaenSignature\Utils\SignatureConstants;

class ProjectGrantApiService implements UseEntityManager,
class ProjectGrantApiService implements
    UseEntityManager,
    UseLoggerService,
    UseOscarConfigurationService,
    UsePersonService,
@@ -127,8 +128,7 @@ class ProjectGrantApiService implements UseEntityManager,
        ?Url              $urlPlugin = null,
        ?OscarUserContext $oscarUserContext = null,
        ?string           $perimeters = null
    ): array
    {
    ): array {
        try {
            $activity = $this->getActivityRepository()->find($activityId);
        } catch (\Exception $exception) {
@@ -206,8 +206,7 @@ class ProjectGrantApiService implements UseEntityManager,
        Activity         $activity,
        OscarUserContext $oscarUserContext,
        array            $perimeters
    ): array
    {
    ): array {
        $locked = $activity->isLocked();
        $editable = $oscarUserContext->hasPrivileges(Privileges::ACTIVITY_EDIT, $activity);
        $lockEditable = $oscarUserContext->hasPrivileges(Privileges::ACTIVITY_EDIT_LOCKED, $activity);
@@ -375,6 +374,7 @@ class ProjectGrantApiService implements UseEntityManager,
                        'read' => $oscarUserContext->hasPrivileges(Privileges::DEPENSE_SHOW, $activity),
                        'sync' => $oscarUserContext->hasPrivileges(Privileges::DEPENSE_SYNC, $activity),
                        'details' => $oscarUserContext->hasPrivileges(Privileges::DEPENSE_DETAILS, $activity),
                        'manageIgnored' => $oscarUserContext->hasPrivileges(Privileges::DEPENSE_IGNORED, $activity),
                    ];
                    break;

@@ -417,8 +417,7 @@ class ProjectGrantApiService implements UseEntityManager,
        Activity $activity,
        ?Url     $urlPlugin = null,
        ?array   $perimeters = null
    ): array
    {
    ): array {
        $datas = [
            "api" => "Oscar Activity API"
        ];
@@ -841,8 +840,7 @@ class ProjectGrantApiService implements UseEntityManager,
    public function getNotesActivity(
        Activity $activity,
        ?Url     $urlPlugin = null
    ): array
    {
    ): array {
        /** @var ActivityNoteRepository $notesActivityRepository */
        $notesActivityRepository = $this->getEntityManager()->getRepository(ActivityNote::class);

@@ -893,8 +891,7 @@ class ProjectGrantApiService implements UseEntityManager,

        $roles = [];
        /** @var OrganizationRole $role */
        foreach (
            $this->getEntityManager()->getRepository(OrganizationRole::class)->findBy([], ['label' => 'ASC']) as $role
        foreach ($this->getEntityManager()->getRepository(OrganizationRole::class)->findBy([], ['label' => 'ASC']) as $role
        ) {
            $roles[] = [
                'id' => $role->getId(),
@@ -995,8 +992,7 @@ class ProjectGrantApiService implements UseEntityManager,
        $output = [];
        $roles = [];

        foreach (
            $this->getEntityManager()->getRepository(Role::class)->getRolesAvailableForPersonInActivity() as $role
        foreach ($this->getEntityManager()->getRepository(Role::class)->getRolesAvailableForPersonInActivity() as $role
        ) {
            $roles[] = [
                'id' => $role->getId(),
@@ -1101,8 +1097,7 @@ class ProjectGrantApiService implements UseEntityManager,
    public function getTimesheetsActivity(
        Activity $activity,
        ?Url     $urlPlugin = null
    ): array
    {
    ): array {
        $out = [
            'enabled' => false,
            'informations' => ""
@@ -1253,8 +1248,7 @@ class ProjectGrantApiService implements UseEntityManager,
    private function formatDateTime(
        ?\DateTime $datetime,
        string     $format = 'Y-m-d H:i:s'
    ): ?string
    {
    ): ?string {
        if ($datetime === null) {
            return null;
        } else {
+58 −43
Changes for module/Oscar/src/Oscar/Service/SpentService.php: 58 added lines, 43 removed lines.
Original line number Diff line number Diff line
@@ -29,7 +29,6 @@ use Oscar\Utils\AccountInfoUtil;
use Oscar\Utils\StringUtils;
use Laminas\Log\Logger;


class SpentService implements UseLoggerService, UseOscarConfigurationService, UseEntityManager
{
    use UseEntityManagerTrait, UseOscarConfigurationServiceTrait, UseLoggerServiceTrait;
@@ -81,8 +80,9 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                $compteLabel = $compteInfos['label'];
                $compteInherit = $compteInfos['compte_inherit'];
                $masseInherit = $compteInfos['masse_inherit'];
                if( !$compteMasse )
                if (!$compteMasse) {
                    $compteMasse = $masseInherit;
                }

                if (!array_key_exists($compteMasse, $out)) {
                    $out[$compteMasse] = [
@@ -130,12 +130,10 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                        break;
                    }
                    $lastOpen = $open[$openIndex];

                }
            }
            $spent->setLft($bound++);
            $open[] = $spent;

        }

        while (count($open) > 0) {
@@ -198,24 +196,30 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
            return $type;
        } else {
            $insiderId = intval($inside);
            if ($insiderId < 1) throw new OscarException(_("DATA ERROR : Type de destination incohérent"));
            if ($insiderId < 1) {
                throw new OscarException(_("DATA ERROR : Type de destination incohérent"));
            }

            // Récupération du noeud racine
            /** @var SpentTypeGroup $insider */
            $insider = $this->getSpentTypeRepository()->find($insiderId);

            if (!$insider) throw new OscarException(_("Impossible de localiser l'emplacement pour le nouveau type"));
            if (!$insider) {
                throw new OscarException(_("Impossible de localiser l'emplacement pour le nouveau type"));
            }

            $lgt = $insider->getRgt();
            $rgt = $lgt + 1;

            // Mise à jour des bornes
            $this->getEntityManager()->createNativeQuery(
                'UPDATE spenttypegroup SET lft = lft+2 WHERE lft > :lft', new ResultSetMapping()
                'UPDATE spenttypegroup SET lft = lft+2 WHERE lft > :lft',
                new ResultSetMapping()
            )->execute(['lft' => $lgt]);

            $this->getEntityManager()->createNativeQuery(
                'UPDATE spenttypegroup SET rgt = rgt+2 WHERE rgt >= :rgt', new ResultSetMapping()
                'UPDATE spenttypegroup SET rgt = rgt+2 WHERE rgt >= :rgt',
                new ResultSetMapping()
            )->execute(['rgt' => $lgt]);

            $type->setLft($lgt)->setRgt($rgt);
@@ -279,11 +283,13 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us

        // Mise à jour des bornes
        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET rgt = rgt - :decalage WHERE rgt > :rgt', new ResultSetMapping()
            'UPDATE spenttypegroup SET rgt = rgt - :decalage WHERE rgt > :rgt',
            new ResultSetMapping()
        )->execute(['decalage' => $decalage, 'rgt' => $rgt, 'lft' => $lft]);

        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET lft = lft - :decalage WHERE lft >= :lft', new ResultSetMapping()
            'UPDATE spenttypegroup SET lft = lft - :decalage WHERE lft >= :lft',
            new ResultSetMapping()
        )->execute(['decalage' => $decalage, 'rgt' => $rgt, 'lft' => $lft]);
    }

@@ -301,12 +307,14 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        $borneMovedRight = $move->getRgt();

        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET lft = lft - :rgt, rgt = rgt - :rgt WHERE lft >= :lft AND rgt <= :rgt', new ResultSetMapping()
            'UPDATE spenttypegroup SET lft = lft - :rgt, rgt = rgt - :rgt WHERE lft >= :lft AND rgt <= :rgt',
            new ResultSetMapping()
        )->execute(['lft' => $borneMovedLeft, 'rgt' => $borneMovedRight]);


        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET lft = lft - :size, rgt = rgt - :size WHERE lft >= :lft', new ResultSetMapping()
            'UPDATE spenttypegroup SET lft = lft - :size, rgt = rgt - :size WHERE lft >= :lft',
            new ResultSetMapping()
        )->execute(['lft' => $borneMovedRight, 'size' => $sizeBranch]);


@@ -318,17 +326,20 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us

        // TROU
        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET lft = lft + :size WHERE lft >= :lft', new ResultSetMapping()
            'UPDATE spenttypegroup SET lft = lft + :size WHERE lft >= :lft',
            new ResultSetMapping()
        )->execute(['lft' => $destPoint, 'size' => $sizeBranch]);

        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET rgt = rgt + :size WHERE rgt >= :rgt', new ResultSetMapping()
            'UPDATE spenttypegroup SET rgt = rgt + :size WHERE rgt >= :rgt',
            new ResultSetMapping()
        )->execute(['rgt' => $destPoint, 'size' => $sizeBranch]);

        // ON replace la branche
        $deplacement = $sizeBranch + $destPoint - 1;
        $this->getEntityManager()->createNativeQuery(
            'UPDATE spenttypegroup SET lft = lft + :size, rgt = rgt + :size WHERE rgt <= :pos', new ResultSetMapping()
            'UPDATE spenttypegroup SET lft = lft + :size, rgt = rgt + :size WHERE rgt <= :pos',
            new ResultSetMapping()
        )->execute(['size' => $deplacement, 'pos' => 0]);
    }

@@ -336,11 +347,13 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
    public function getYearsListActivity(Activity $activity)
    {

        if (!$activity->getDateStart())
        if (!$activity->getDateStart()) {
            throw new OscarException(sprintf(_("L'activité %s n'a pas de date de début"), $activity));
        }

        if (!$activity->getDateEnd())
        if (!$activity->getDateEnd()) {
            throw new OscarException(sprintf(_("L'activité %s n'a pas de date de fin"), $activity));
        }

        if ($activity->getDateEnd() < $activity->getDateStart()) {
            throw new OscarException(sprintf(_("L'activité %s a une date de fin antérieur à sa date de début"), $activity));
@@ -428,7 +441,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                        $p['empty'] = false;
                    }
                }

            }
        }

@@ -452,9 +464,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us

        $re = '/(\d+)\.?/';

        if (($handle = fopen($filepath, "r")) !== FALSE) {
            while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {

        if (($handle = fopen($filepath, "r")) !== false) {
            while (($data = fgetcsv($handle, 1000, ",")) !== false) {
                if (preg_match($re, $data[0], $matches)) {
                    $code = $matches[1];
                    $label = $data[1];
@@ -472,7 +483,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                }

                if (array_key_exists($code, $spentTypes)) {

                } else {
                    $spentType = new SpentTypeGroup();
                    $this->getEntityManager()->persist($spentType);
@@ -484,7 +494,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        }

        $this->orderSpentsByCode();

    }


@@ -497,7 +506,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
            $node->setLft(++$i)->setRgt(++$i);
        }
        $this->getEntityManager()->flush();

    }

    public function updateSpentTypeGroup($datas)
@@ -593,7 +601,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
     * @param $codeEnfant
     * @return array
     */
    protected function getParentWithAnnexe($plan, $codeEnfant){
    protected function getParentWithAnnexe($plan, $codeEnfant)
    {
        $indexInPlan = '00'.StringUtils::feedString($codeEnfant);
        $parentCode = '';
        $parentlabel = '';
@@ -673,7 +682,9 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
            $reduce = strval($code);
            $out = [];
            for ($i = strlen($reduce) - 1; $find == null && $i > 0; $i--) {
                if( $reduce[$i] == '0' ) continue;
                if ($reduce[$i] == '0') {
                    continue;
                }
                if (array_key_exists($reduce, $plan)) {
                    $parent = $this->getParentWithAnnexe($plan, $plan[$reduce]->getCode());
                    $out['id'] = $plan[$reduce]->getId();
@@ -713,7 +724,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
     * @return array
     * @throws \Doctrine\DBAL\Exception
     */
    public function getSpentsByPFIs(array $pfis, $spentType = self::SPENT_EFFECTIVE){
    public function getSpentsByPFIs(array $pfis, $spentType = self::SPENT_EFFECTIVE)
    {
        $out = [];
        foreach ($pfis as $pfi) {
            $spents = $this->getSpentsByPFI($pfi, $spentType);
@@ -795,16 +807,13 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                // Recette / Ignorer
                $spentType->setBlind(false);
                $spentType->setAnnexe($compteAffectation);
            }
            elseif ( $compteAffectation == '0' ){
            } elseif ($compteAffectation == '0') {
                $spentType->setAnnexe('0');
                $spentType->setBlind(true);
            }
            elseif ( $compteAffectation == '' ){
            } elseif ($compteAffectation == '') {
                $this->getLoggerService()->error("Erreur d'affectation pour $codeCompteFull (valeur nulle).");
                throw new OscarException("Erreur d'affectation (valeur nulle)");
            }
            else {
            } else {
                $spentType->setBlind(false);
                $spentType->setAnnexe($compteAffectation);
            }
@@ -824,6 +833,9 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        $accountInfos = [];
        foreach ($usedAccounts as $compte) {
            $infos = $this->getCompte($compte);
            if ($infos['annexe'] === null && $infos['masse_inherit'] !== null) {
                $infos['annexe'] = $infos['masse_inherit'];
            }
            $accountInfos[] = $infos;
        }
        return $accountInfos;
@@ -901,7 +913,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        ]);

        if (count($activities) > 0) {

            // synchro
            try {
                $this->getConnector()->sync($eotp);
@@ -942,10 +953,13 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        static $assoc;

        // Fix : Pas de type chargé en base de donnée
        if ($code === false) return "0";
        if ($code === false) {
            return "0";
        }

        if ($types === null)
        if ($types === null) {
            $types = $this->getSpentsTypes();
        }

        if ($assoc === null) {
            $assoc = [];
@@ -1031,7 +1045,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
     * @param $pfi
     * @return array
     */
    public function getSpentsDatas($pfi, $spentType = self::SPENT_EFFECTIVE){
    public function getSpentsDatas($pfi, $spentType = self::SPENT_EFFECTIVE)
    {

        $array = [];
        $spents = $this->getSpentsByPFI($pfi, $spentType);
@@ -1065,7 +1080,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
     * @param $spents
     * @return array[]
     */
    public function getSpentDatasSynthesisBySpents($spents){
    public function getSpentDatasSynthesisBySpents($spents)
    {
        $pfis = [];
        $synthesis = [
            'lines' => count($spents),
@@ -1160,7 +1176,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
                $synthesis['totaux']['engage'] += $totalEngage;
            }
            $synthesis[$masse]['nbr']++;

        }
        $synthesis['pfis'] = $pfis;

@@ -1168,7 +1183,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
        return $synthesis;
    }

    public function getSpentDatasSynthesisByPfi($pfi){
    public function getSpentDatasSynthesisByPfi($pfi)
    {
        $spents = $this->getSpentsByPFI($pfi);
        return $this->getSpentDatasSynthesisBySpents($spents);
    }
@@ -1214,7 +1230,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us

        /** @var SpentLine $spent */
        foreach ($spents as $spent) {

            $numPiece = $spent->getNumPiece();
            $compteBudg = $spent->getCompteBudgetaire();
            $compte = $this->getCompte($spent->getCompteGeneral());
@@ -1227,7 +1242,8 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
            if (!is_array($byMasses[$masseGroup])) {
                echo "<h1>$masseGroup</h1>";
                var_dump($compte);
                var_dump($byMasses); die();
                var_dump($byMasses);
                die();
            }
            if (!array_key_exists($numPiece, $byMasses[$masseGroup]['spents'])) {
                $byMasses[$masseGroup]['spents'][] = [
@@ -1361,7 +1377,6 @@ class SpentService implements UseLoggerService, UseOscarConfigurationService, Us
            $this->getLoggerService()->critical("Erreur : Plusieurs connector configuré pour les dépenses");
            throw new OscarException("Oscar ne prends en charge qu'une source de synchronisation pour les dépenses.");
        } else {

            $conf = $connectorConfig[$keysConfig[0]];
            $class = $conf['class'];
            $factory = new \ReflectionClass($class);
+1 −0
Changes for ui/src/views/Activity.vue: 1 added line, 0 removed lines.
Original line number Diff line number Diff line
@@ -608,6 +608,7 @@
            <ActivitySpentSynthesis
                :standalone="false"
                :datas="spents"
                :manage-ignored="credentials.spents.manageIgnored"
            />
            <nav class="buttons xs">
              <a :href="spents.url_details" class="btn btn-primary btn" v-if="credentials.spents.details">
+4 −8
Changes for ui/src/views/ActivitySpentSynthesis.vue: 4 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -105,14 +105,9 @@
        </table>
      </div>
    </div>

    <div v-if="manageIgnored && synthesis && synthesis.synthesis['0'].total != 0">
      <a href="#" @click.prevent="displayIgnored = !displayIgnored">
        <span v-if="displayIgnored"><i class="icon-eye-off"></i> Cacher</span>
        <span v-else><i class="icon-eye"></i> Montrer</span>
        les données ignorées
      </a>
      <table class="table table-condensed card synthesis" v-if="spentlines && displayIgnored">
      <h3><i class="icon-eye-off"></i>Ignorées</h3>
      <table class="table table-condensed card synthesis">
        <tbody>
        <tr>
          <th>
@@ -133,7 +128,8 @@ export default {
  props: {
    url: { default: "" },
    standalone: { default: true },
    datas: { default: {} }
    datas: { default: {} },
    manageIgnored: { default: false }
  },

  computed:{
+22 −14
Changes for ui/src/views/SpentLinePFI.vue: 22 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -187,7 +187,7 @@
          </table>

          <div v-if="manageRecettes">
            <h3><i class="icon-calculator"></i>Recettes</h3>
            <h3><i class="icon-down-outline"></i>Recettes</h3>
            <table class="table table-condensed card synthesis" v-if="spentlines">
              <tbody>
              <tr>
@@ -200,13 +200,9 @@

          </div>

          <div v-if="manageIgnored && spentlines.synthesis['0'].total != 0">
            <a href="#" @click.prevent="displayIgnored = !displayIgnored">
              <span v-if="displayIgnored"><i class="icon-eye-off"></i> Cacher</span>
              <span v-else><i class="icon-eye"></i> Montrer</span>
              les données ignorées
            </a>
            <table class="table table-condensed card synthesis" v-if="spentlines && displayIgnored">
          <div v-if="manageIgnored && spentlines && spentlines.synthesis['0'] && spentlines.synthesis['0'].total != 0">
            <h3><i class="icon-eye-off"></i>Ignorées</h3>
            <table class="table table-condensed card synthesis">
              <tbody>
              <tr>
                <th>
@@ -223,7 +219,10 @@

          <div v-if="spentlines != null">
            <div v-for="m, k in masses">
              <h3 :id="'repport-' + k">{{ m }}</h3>
              <h3 :id="'repport-' + k">
                <i class="icon-calculator"></i>
                Dépenses ({{ m }})
              </h3>
              <spent-line-p-f-i-grouped
                  :lines="byMasse.datas[k]" :total="spentlines.synthesis[k].total"
                  @editcompte="handlerEditCompte"
@@ -232,9 +231,11 @@
            </div>

            <div v-if="Object.keys(byMasse.datas['N.B']).length > 0">
              <h3 :id="'repport-nb'">Hors-masse</h3>
              <h3 :id="'repport-nb'">
                <i class="icon-attention"></i> Hors-masse
              </h3>
              <div class="alert alert-warning">
                <i class="icon-attention"></i> Les comptes des entrées suivantes ne sont pas qualifié.
                <i class="icon-attention"></i> Les comptes des entrées suivantes ne sont pas qualifiés.
              </div>
              <spent-line-p-f-i-grouped
                  :lines="byMasse.datas['N.B']" :total="spentlines.synthesis['N.B'].total"
@@ -244,16 +245,21 @@
            </div>

            <div v-if="manageRecettes && Object.keys(byMasse.datas['recettes']).length > 0">
              <h3 :id="'repport-1'">Recettes</h3>
              <h3 :id="'repport-1'">
                <i class="icon-down-outline"></i>
                  Recettes
              </h3>
              <spent-line-p-f-i-grouped
                  :lines="byMasse.datas['recettes']" :total="spentlines.synthesis['1'].total_effectue"
                  @editcompte="handlerEditCompte"
                  @detailsline="handlerDetailsLine"
              />
              {{ spentlines.synthesis }}
            </div>
            <div v-if="manageIgnored && Object.keys(byMasse.datas['ignorés']).length > 0">
              <h3 :id="'repport-0'">Ignorés</h3>
              <h3 :id="'repport-0'">
                <i class="icon-eye-off"></i>
                Ignorés
              </h3>
              <spent-line-p-f-i-grouped
                  :lines="byMasse.datas['ignorés']" :total="spentlines.synthesis['0'].total"
                  @editcompte="handlerEditCompte"
@@ -293,8 +299,10 @@ export default {
      editCompte: null,
      informations: null,


      //
      manageRecettes: true,
      manageIgnored: true,

      // URL
      url_activity: null,