<?php

namespace Modules\Facture\Controller;

use Entity\Model\Articles;
use Entity\Model\Paravrac;
use GuzzleHttp\Psr7\Response;
use Helpers\Outil\Date;
use Modules\GlobalApplication\Repository\LicenceOxalys;
use Skeleton\Controller\Controller;
use Helpers\ChampsSupplementaire\ChampSupp;
use Helpers\Outil\Sql;
use Helpers\Pagination\Paginator;
use Helpers\Trad\Trad;
use Helpers\Outil\Roles;
use Helpers\Validator\Validator;
use Helpers\Parametres\Constante;
use Entity\Model\FacLigTravail;
use Helpers\Additional\Specifique\Specifique;
use Modules\Facture\Repository\CreationFacture;
use Entity\Model\Codgest;
use Modules\Facture\MenuContextuel\AffectationMenuContextuel;
use Modules\Facture\MenuContextuel\SuiviEventMenuContextuel;

class AjaxFactureController extends Controller
{


    /***************************************************** CREATION/MODIFICATION ENTETE FACTURE *****************************************************/
    // CALCUL DE LA DATE DE PERIODE ENTETE FACTURE
    public function calculDatePeriodeAction()
    {
        $post      = $this->request->getParsedBody();
        $validator = $this->createValidator();
        $date      = $post['DATE_FAFO'];
        $validator->isDate($date);
        $validator->isDate($post['DATE_ENR']);

        // Calcul DTAE_ECH
        $dateReturn['DTAE_ECH'] = $this->calculDateEch($post, $date, $this->pdo);

        $dateConverte = new \Helpers\Outil\Date();
        // Calcul DATE_PER
        // SPEC 4284 : modification de l'initialisation de la date de période en prenant compte des dates prévisionnelles globales ou par société pour les sous-périodes
        if (\Helpers\Outil\Roles::droit($this->pdo, 'SPER_AVEC_OUV_FERM') && \Helpers\Outil\Roles::droit($this->pdo, 'CTRL_SSPERIODE_FAC')) {
            $CreationFacture    = new \Modules\Facture\Repository\CreationFacture($this->pdo);
            $resultSousPer      = $CreationFacture->ouvertureSousPeriode($date, $post['societe'], 1);
            $sousPeriodeOuverte = 0;
            if (isset($resultSousPer['ETAT'])
                && (
                    $resultSousPer['ETAT'] == 'O' ||
                    ($resultSousPer['ETAT'] == '' && $resultSousPer['DATE_DEB'] <= $date && ($resultSousPer['DATE_FIN'] >= $date || $resultSousPer['PREV_CLOSING_DATE'] >= $date || $resultSousPer['PREV_CLOSING_DATE_STE'] >= $date))
                )
            ) {
                $sousPeriodeOuverte = 1;
            }

            if ($sousPeriodeOuverte) {
                $dateReturn['DATE_PER'] = $post['DATE_FAFO'];
            } else {
                $resultPremSousPeriode = $CreationFacture->DatepremiereSousPeriode($date, $post['societe']);
                if ($resultPremSousPeriode['DATE_DEB'] ?? false) {
                    $dateReturn['DATE_PER'] = $dateConverte->dateConverte($resultPremSousPeriode['DATE_DEB']);
                } else {
                    $resultDerniereSousPeriode = $CreationFacture->DateDernièreSousPeriode($date, $post['societe']);
                    if ($resultDerniereSousPeriode['DATE_FIN']) {
                        $dateReturn['DATE_PER'] = $dateConverte->dateConverte($resultDerniereSousPeriode['DATE_FIN']);
                    } else {
                        $dateReturn['DATE_PER'] = $dateConverte->dateConverte(date("Ymd"));
                    }
                }
            }
        } else {
            $dateReturn['DATE_PER'] = $dateConverte->dateConverte(date("Ymd"));
        }

        $dateReturn['DTAE_ECH'] = $dateConverte->dateConverte($dateReturn['DTAE_ECH']);
        return new Response(200, [], (string) \json_encode($dateReturn));
    }

    // CALCUL DE LA DATE D'ECHEANCE ENTETE FACTURE
    public static function calculDateEch($post, $date, $pdo)
    {
        $paravrac = new Paravrac($pdo);
        // Date pour la base de calcul
        if (!$paravrac->getFlag('PARAMGEN', 'DECHFACT') && (($post['DATE_FAFO'] ?? '00000000') != '00000000' && ($post['DATE_FAFO'] ?? '') != '')) {
            $baseCalcul = $date;
        } else {
            $baseCalcul = $post['DATE_ENR'];
        }
        $baseCalcul = substr($baseCalcul, 0, 4) . '-' . substr($baseCalcul, 4, 2) . '-' . substr($baseCalcul, 6);

        // Calcul DTAE_ECH
        if ($post['COND_PAIE'] != '') {
            $condpaie = (new \Entity\Model\CondPaie($pdo))->find($post['COND_PAIE']);

            if ($condpaie) {
                // Si Paiement Fin De Mois
                if (\Helpers\Outil\Sql::boolSql($condpaie['FIN_D_MOI'])) {
                    // + DELAI_PAI jour; fin de moi; le QUANT_PAI du moi suivant
                    $DTAE_ECH =
                        (new \DateTime("$baseCalcul + " . $condpaie['DELAI_PAI'] . " day"))
                            ->modify('last day of this month') // Beware 'next month' alone will do +30 day 2025-03-31 -> 2025-05-01
                            ->modify('+' . intval($condpaie['QUANT_PAI']) . ' day')
                            ->format('Ymd');
                } else {
                    // Si Paiement Calendaire
                    $DTAE_ECH = Date::convert("$baseCalcul + " . $condpaie['DELAI_PAI'] . " days", null, "Ymd");
                }

                if ($DTAE_ECH == '') {
                    return '00000000';
                }
                return $DTAE_ECH;
            }
        }

        return date("Ymd");
    }

    // RECUPERATION DE LA LONGEUR DU CODE POSTAL SELON LE PAYS
    public function getLONGCPAction()
    {
        $post = $this->request->getParsedBody();

        $country = new \Entity\Model\Country($this->pdo);
        $country = $country->find($post['PAYS']);

        return new Response(200, [], (string) \json_encode($country));
    }

    /***************************************************** SAISIE DES AFFECTATIONS *****************************************************/
    // VERIFICATION DE LA QUANTITE PAR LIGNE
    public function verifQteLigneAction()
    {
        $trad   = $this->getTranslationService();
        $post   = $this->request->getParsedBody();
        $erreur = '';

        // $qte = str_replace(' ', '', $post['qte']);
        // $qte_init = str_replace(' ', '', $post['qte_init']);
        $qte_eclatementLigneInitiale = str_replace(' ', '', $post['qte_eclatementLigneInitiale'] ?? 0);

        // vérification de la quantité pour eclatement ligne
        if ($post['typeAction'] == 'eclatementLigne' && (float) $qte_eclatementLigneInitiale <= 0) {
            $erreur .= '<br /> ' . $trad->t('La quantité de la ligne initiale ne peut pas être inférieure ou égale à 0.');
        }

        // DOSSIER 30072 : suppression du controle
        // vérification de la quantité par rapport à la quantité facturable (sauf pour eclatement ligne et ligne manuelle)
        // if($post['typeAction']=='' && $qte>$qte_init)
        //     $erreur .= '<br /> '.$trad->t('La quantité de la ligne ne peut pas être supérieure à la quantité facturable.');

        return new Response(200, [], (string) \json_encode(['erreur' => $erreur]));
    }

    // VERIFICATION DU PRIX UNITAIRE REMISE PAR LIGNE
    public function verifPuRemiseLigneAction()
    {
        $trad   = $this->getTranslationService();
        $post   = $this->request->getParsedBody();
        $erreur = '';

        $pu_remise = str_replace(' ', '', $post['pu_remise']);
        $type      = $post['type'];

        // DOSSIER 30892 : SUPPRESSION DE CONTROLE SI FACTURE
        // si avoir, pu_remise doivent être négatif
        if ($type == 'A') {
            if ((int) $pu_remise > 0) {
                $erreur .= '<br /> ' . $trad->t('Le pu remisé de la ligne ne peut pas être positif.');
            }
        }

        return new Response(200, [], (string) \json_encode(['erreur' => $erreur]));
    }

    // VERIFICATION DU MONTANT HT PAR LIGNE
    public function verifHTLigneAction()
    {
        $post   = $this->request->getParsedBody();
        $erreur = '';

        $trad = $this->getTranslationService();

        $qte                              = floatval(str_replace(' ', '', $post['qte']));
        $pu_remise                        = floatval(str_replace(' ', '', $post['pu_remise']));
        $montant                          = str_replace(' ', '', $post['montant']);
        $type                             = $post['type'];
        $mtt_init_eclatementLigneInitiale = str_replace(' ', '', $post['mtt_init_eclatementLigneInitiale'] ?? 0);
        $mtt_eclatementLigneInitiale      = str_replace(' ', '', $post['mtt_eclatementLigneInitiale'] ?? 0);

        $fourchetteMontantMin = round($qte * $pu_remise - 0.005, 2);
        $fourchetteMontantMax = round($qte * $pu_remise + 0.005, 2);


        // si avoir, montant doivent être négatif // si facture, different de 0
        if ($type == 'F') {
            // @phpstan-ignore-next-line
            if ($post['typeAction'] == 'eclatementLigne' && $mtt_init_eclatementLigneInitiale > 0 && $mtt_eclatementLigneInitiale <= 0) {
                $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être inférieur ou égal à 0.');
                // @phpstan-ignore-next-line
            } elseif ($post['typeAction'] == 'eclatementLigne' && $mtt_init_eclatementLigneInitiale < 0 && $mtt_eclatementLigneInitiale >= 0) {
                $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être supérieur ou égal à 0.');
            }
            // elseif($montant==0) $erreur .= '<br /> '.$trad->t('Le montant HT de la ligne ne peut pas être égal à zéro.');
        } else {
            // @phpstan-ignore-next-line
            if ($post['typeAction'] == 'eclatementLigne' && $mtt_eclatementLigneInitiale >= 0) {
                $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être supérieur ou égal à 0.');
            }
            // @phpstan-ignore-next-line
            if ($montant > 0) {
                $erreur .= '<br /> ' . $trad->t('Le montant HT de la ligne ne peut pas être positif.');
            }
        }

        // tolérance du montant HT
        // @phpstan-ignore-next-line
        if ($post['verificationMontantQte'] && ($montant < $fourchetteMontantMin || $montant > $fourchetteMontantMax)) {
            $erreur = '<br /> ' . Trad::strBuild($trad->t('Le montant facturé de la ligne doit être compris entre @1@ et @2@ ; cet écart nécessite la variation du prix unitaire et de la quantité (passer par le calcul pourcentage).'), $fourchetteMontantMin, $fourchetteMontantMax);
        }

        return new Response(200, [], (string) \json_encode(['erreur' => $erreur]));
    }

    // VERIFICATION DU MONTANT TVA PAR LIGNE
    public function verifTVALigneAction()
    {
        $post   = $this->request->getParsedBody();
        $erreur = '';

        $trad = $this->getTranslationService();

        $montant    = floatval(str_replace(' ', '', $post['montant']));
        $tauxTva    = floatval(str_replace(' ', '', $post['tauxTva']));
        $montantTva = floatval(str_replace(' ', '', $post['montantTva']));
        $type       = $post['type'];

        // DOSSIER 30892 : SUPPRESSION DE CONTROLE SI FACTURE
        // si avoir, pu_remise et montant doivent être négatif
        if ($type == 'A') {
            if ($montantTva > 0 && $tauxTva != 0) {
                $erreur .= '<br /> ' . $trad->t('Le montant de TVA de la ligne ne peut pas être positif.');
            }
        }

        // si le montant HT != 0 et taux de tva != 0, TVA ne peut pas être égal à 0
        if ($montant != 0 && $montantTva == 0 && $tauxTva != 0) {
            $erreur .= '<br /> ' . $trad->t('Le montant de TVA de la ligne ne peut pas être égal à 0.');
        }

        if ($tauxTva == 0 && $montantTva != 0) {
            $erreur .= '<br /> ' . $trad->t('Le montant de TVA de la ligne doit être égal à 0.');
        } else {
            // DOSSIER 33156 : augmentation de l'écart -> passage de 0.005 à 0.05
            // DOSSIER 35088: augmentation de l'écart -> passage à 1
            $fourchetteMontantTVAMin = round($montant * $tauxTva / 100) - 1;
            $fourchetteMontantTVAMax = round($montant * $tauxTva / 100) + 1;

            if ($montantTva < $fourchetteMontantTVAMin || $montantTva > $fourchetteMontantTVAMax) {
                $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le montant de TVA de la ligne doit être compris entre @1@ et @2@.'), $fourchetteMontantTVAMin, $fourchetteMontantTVAMax);
            }
        }

        return new Response(200, [], (string) \json_encode(['erreur' => $erreur]));
    }

    // INITIALISATION SELON ARTICLE
    public function changeArticleAction()
    {
        $post = $this->request->getParsedBody();

        $articles = new \Entity\Model\Articles($this->pdo);
        $siSteArt = new \Entity\Model\SiSteArt($this->pdo);
        $cdcSteAr = new \Entity\Model\CdcSteAr($this->pdo);
        $scaSteAr = new \Entity\Model\ScaSteAr($this->pdo);

        $articles = $articles->find($post['CODE_ART']);
        $result   = ['DESIGN' => ($articles['DESIGN'] ?? ''), 'SSFAM' => ($articles['SSFAM'] ?? '')];

        $steSi  = \Helpers\Outil\Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE') ? $post['CODE_STE'] : '';
        $steCdc = \Helpers\Outil\Roles::droit($this->pdo, 'CDCSECTO', 'PARAMSTE') ? $post['CODE_STE'] : '';
        $steSca = \Helpers\Outil\Roles::droit($this->pdo, 'SCASECTO', 'PARAMSTE') ? $post['CODE_STE'] : '';

        $si                               = $siSteArt->find(['CODE_ART' => $post['CODE_ART'], 'CODE_STE' => $steSi]);
        $result['CODE_SI']                = $si['SI'] ?? '';
        $result['codeGestionSaisie']      = Sql::boolSql($si['SICODG'] ?? 0);
        $result['codeGestionObligatoire'] = Sql::boolSql($si['IMPCODG'] ?? 0) == 1 ? 'false' : 'true';
        $result['CODE_CDC']               = $cdcSteAr->find(['CODE_ART' => $post['CODE_ART'], 'CODE_STE' => $steCdc])['CDC'] ?? '';
        $result['CODE_SCA']               = $scaSteAr->find(['CODE_ART' => $post['CODE_ART'], 'CODE_STE' => $steSca])['SCA'] ?? '';

        return new Response(200, [], (string) \json_encode($result));
    }

    // INITIALISATION SELON ARTICLE
    public function changeArticleSiCdcScaAction(): Response
    {
        $post = $this->request->getParsedBody();

        $repository = new CreationFacture($this->pdo);
        $result     = $repository->articleSiCdcSca($post);

        if (\is_array($result) and $result[0] !== []) {
            return new Response(200, [], (string) \json_encode($result[0]));
        } else {
            return new Response(200, [], (string) \json_encode($result));
        }
    }

    // INITIALISATION SELON SOUS FAMILLE
    public function changeSousFamilleAction()
    {
        $post = $this->request->getParsedBody();


        $result        = [];
        $result['si']  = '';
        $result['cdc'] = '';
        $result['sca'] = '';

        $creationFacture = new CreationFacture($this->pdo);
        $result['si']    = $creationFacture->getSiSousFamille($post) ?? '';
        $result['cdc']   = $creationFacture->getCdcSousFamille($post) ?? '';
        $result['sca']   = $creationFacture->getScaSousFamille($post) ?? '';

        if ($result['si'] != '') {
            $sectimpu                            = new \Entity\Model\Sectimpu($this->pdo);
            $sectimpu                            = $sectimpu->find($result['si']);
            $result['codeGestionSaisie']         = $codeGestionSaisie = Sql::boolSql($sectimpu['SICODG']);
            $result['codeGestionNonObligatoire'] = $codeGestionNonObligatoire = Sql::boolSql($sectimpu['IMPCODG']) == 1 ? 'false' : 'true';
        }

        if ($post['CODE_SI'] != '' || $post['CODE_CDC'] != '' || $post['CODE_SCA'] != '') {
            $listeImputation = [];

            if ($result['si'] != '' && $result['si'] != $post['CODE_SI']) {
                $listeImputation['SI'] = [
                    'Titre'                     => 'SI',
                    'OldValeur'                 => $post['CODE_SI'],
                    'NewValeur'                 => $result['si'],
                    'codeGestionSaisie'         => $codeGestionSaisie,
                    'codeGestionNonObligatoire' => $codeGestionNonObligatoire,
                ];
            }
            if ($result['cdc'] != '' && $result['cdc'] != $post['CODE_CDC']) {
                $listeImputation['CDC'] = [
                    'Titre'     => 'CDC',
                    'OldValeur' => $post['CODE_CDC'],
                    'NewValeur' => $result['cdc'],
                ];
            }
            if ($result['sca'] != '' && $result['sca'] != $post['CODE_SCA']) {
                $listeImputation['SCA'] = [
                    'Titre'     => 'SCA',
                    'OldValeur' => $post['CODE_SCA'],
                    'NewValeur' => $result['sca'],
                ];
            }

            if (count($listeImputation) > 0) {
                $params = [
                    'listeImputation'  => $listeImputation,
                    'encodeImputation' => json_encode($listeImputation),
                    'idLigne'          => $post['ID_LIGNE'],
                    'titrePopup'       => '',

                ];
                return new Response(443, [], $this->renderer->render('@ajax-facture/ajaxSousFamille', ['params' => $params]));
            }
        }

        return new Response(200, [], (string) \json_encode($result));
    }

    // VALIDATION DE L'ECLATEMENT DE LIGNE
    public function validerEclatementAction()
    {
        $post = $this->request->getParsedBody();

        $trad = $this->getTranslationService();

        $erreur                = '';
        $idLigneInitEclatement = $post['idLigneInitEclatement'];

        $facture = new \Entity\Model\FactEnt($this->pdo);
        $facture = $facture->find($post['facture']);
        $data    = array();
        foreach ($post['tblIdLigne'] as $idLigne) {
            $data[$idLigne]               = array();
            $data[$idLigne]['typeAction'] = '';

            foreach ($post['data'] as $key => $value) {
                $tblKey = explode('-', $key);
                if (isset($tblKey[1]) && $tblKey[1] == $idLigne) {
                    $data[$idLigne][$tblKey[0]] = $value;
                }
                $tblKey = explode('debut-----fin', $key);
                if (count($tblKey) > 1) {
                    $data[$idLigne][$key] = $value;
                }
            }
        }

        $testQte = 1;

        foreach ($data as $key => $ligne) {
            $qte          = $data[$key]['QUANTITE'] = $ligne['QUANTITE'] = floatval(str_replace(' ', '', $ligne['QUANTITE']));
            $pu_remise    = $data[$key]['PU_REMISE'] = $ligne['PU_REMISE'] = floatval(str_replace(' ', '', $ligne['PU_REMISE']));
            $taux_tva     = $data[$key]['TAUX_TVA'];
            $montant_init = $data[$key]['MONTANT_INIT'] = $ligne['MONTANT_INIT'] = floatval(str_replace(' ', '', $ligne['MONTANT_INIT']));
            $montant = $data[$key]['MONTANT'] = $ligne['MONTANT'] = floatval(str_replace(' ', '', $ligne['MONTANT']));
            $mt_tva = $data[$key]['MT_TVA'] = $ligne['MT_TVA'] = floatval(str_replace(' ', '', $ligne['MT_TVA']));

            // si la réception n'est pas en montant
            if ($ligne['ligneEnMontant'] == 0) {
                // vérification de la quantité pour eclatement ligne
                if ($ligne['NO_LIGNE'] == $idLigneInitEclatement && $qte <= 0) {
                    $erreur  .= '<br /> ' . $trad->t('La quantité de la ligne initiale ne peut pas être inférieure ou égale à 0.');
                    $testQte  = 0;
                }

                // DOSSIER 30892 : SUPPRESSION DE CONTROLE SI FACTURE
                // si avoir, pu_remise doivent être négatif
                if ($facture['TYPE'] == 'A') {
                    if ($pu_remise > 0) {
                        $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le pu remisé de la ligne @1@ de la commande @2@ ne peut pas être positif.'), $ligne['NUM_LICDE'], $ligne['NUM_CDE']);
                    }
                }

                // tolérance du montant HT par ligne : (QUANTITE * PU) - 0.005 < Montant HT > (QUANTITE * PU) + 0.005
                $fourchetteMontantMin = round(($qte * $pu_remise - 0.005), 2);
                $fourchetteMontantMax = round(($qte * $pu_remise + 0.005), 2);

                if ($montant < $fourchetteMontantMin || $montant > $fourchetteMontantMax) {
                    $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le montant HT de la ligne @1@ de la commande @2@ n\'est pas compris dans une fourchette acceptable.'), $ligne['NUM_LICDE'], $ligne['NUM_CDE']);
                }
            }

            // DOSSIER 30892 : SUPPRESSION DE CONTROLE SI FACTURE
            // si avoir, pu_remise, montant et TVA doivent être négatif
            if ($facture['TYPE'] == 'F') {
                if ($ligne['NO_LIGNE'] == $idLigneInitEclatement && $montant_init > 0 && $montant <= 0) {
                    $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être inférieur ou égal à 0.');
                } elseif ($ligne['NO_LIGNE'] == $idLigneInitEclatement && $montant_init < 0 && $montant >= 0) {
                    $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être supérieur ou égal à 0.');
                }
            } else {
                if ($ligne['NO_LIGNE'] == $idLigneInitEclatement && $montant >= 0) {
                    $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être supérieur ou égal à 0.');
                } elseif ($montant > 0) {
                    $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le montant HT de la ligne @1@ de la commande @2@ ne peut pas être positif.'), $ligne['NUM_LICDE'], $ligne['NUM_CDE']);
                }

                if ($mt_tva > 0) {
                    $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le montant de TVA  de la ligne @1@ de la commande @2@ ne peut pas être positif.'), $ligne['NUM_LICDE'], $ligne['NUM_CDE']);
                }

                if ($ligne['NO_LIGNE'] == $idLigneInitEclatement && $montant >= 0) {
                    $erreur .= '<br /> ' . $trad->t('Le montant de la ligne initiale ne peut pas être supérieur ou égal à 0.');
                }
            }

            // tolérance du montant TVA par ligne : (MONTANT HT * TAUX_TVA / 100) - 1  <= Montant TVA => (MONTANT HT * TAUX_TVA / 100) + 1
            // DOSSIER 33156 : augmentation de l'écart -> passage de 0.005 à 0.05
            // DOSSIER 35088: augmentation de l'écart -> passage à 1
            $fourchetteMontantTVAMin = round($montant * $taux_tva / 100) - 1;
            $fourchetteMontantTVAMax = round($montant * $taux_tva / 100) + 1;

            if ($mt_tva < $fourchetteMontantTVAMin || $mt_tva > $fourchetteMontantTVAMax) {
                $erreur .= '<br /> ' . Trad::strBuild($trad->t('Le montant de TVA  de la ligne @1@ de la commande @2@ n\'est pas compris dans une fourchette acceptable.'), $ligne['NUM_LICDE'], $ligne['NUM_CDE']);
            }


            if ($erreur == '' && $testQte) {
                $data[$key]['QUANTITE_INIT'] = $data[$key]['QUANTITE'];
            }
        }
        $creationFacture = new CreationFacture($this->pdo);

        if ($erreur == '') {
            foreach ($data as $key => $ligne) {
                if (is_array($ligne)) {
                    $idLigne = $ligne['NO_LIGNE'];
                    if ($ligne['NO_LIGNE'] == $idLigneInitEclatement) {
                        $creationFacture->updateLigneFacLigTravail($post['facture'], $idLigne, $ligne);
                    } else {
                        $creationFacture->insertLigneFacLigTravail($post['facture'], $idLigneInitEclatement, $idLigne, $ligne);

                        $listeCSFac = $creationFacture->infoCSLigTravail($post['facture'], $idLigneInitEclatement);
                        foreach ($listeCSFac as $cs) {
                            ChampSupp::insertChampSupp('FAC_LIG_TRAVAIL', ChampSupp::autoCompletCodeEnr($post['facture'], $idLigne, 'FAC_LIG'), $cs['NUM_FIX'], $cs['VALEUR'], $this->pdo);
                        }
                    }
                }
            }
        }
        return new Response(200, [], (string) \json_encode(['erreur' => $erreur, 'data' => $data]));
    }

    // AFFICHAGE D'UNE LIGNE D'AFFECTATION : LIGNE MANUELLE, ECLATEMENT DE LIGNE
    public function ligneAffectationAction(): string
    {
        $spliter              = Constante::spliter;
        $post                 = $this->request->getParsedBody();
        $droits['HA_FA_MOLI'] = Roles::droitsUtilisateur($this->pdo, 'HA_FA_MOLI');

        $repoChampSup = new ChampSupp($this->pdo);

        $validator = $this->createValidator();

        $fourniss = new \Entity\Model\Fourniss($this->pdo);
        $country  = new \Entity\Model\Country($this->pdo);
        $sectimpu = new \Entity\Model\Sectimpu($this->pdo);
        $Codgest  = new \Entity\Model\Codgest($this->pdo);
        $Codecomp = new \Entity\Model\Codecomp($this->pdo);
        $Sscptana = new \Entity\Model\Sscptana($this->pdo);

        $listeCS = ChampSupp::listeIdCS('FAC_LIG', $this->pdo);

        // DOSSIER 30276 + 31844
        $params['IS_CG_ACTIVE'] = (new LicenceOxalys($this->pdo))->codeGestionActive();
        $creationFacture        = new CreationFacture($this->pdo);
        $numLot                 = $creationFacture->numLot()['NUM_LOT'] ?? '1';

        $facture = new \Entity\Model\FactEnt($this->pdo);
        $facture = $facture->find($post['facture']);

        $societe = $facture['CODE_STE'];

        if (Roles::droit($this->pdo, 'IMP_BO_SI__FA_' . $societe, 'PARAMSOC', true) == 'O') {
            $saisieNonObligatoire['SI'] = true;
        } elseif (Roles::droit($this->pdo, 'IMP_BO_SI__FA_', 'PARAMGEN', true) == 'O') {
            $saisieNonObligatoire['SI'] = true;
        } else {
            $saisieNonObligatoire['SI'] = false;
        }

        if (Roles::droit($this->pdo, 'IMP_BO_CDC_FA_' . $societe, 'PARAMSOC', true) == 'O') {
            $saisieNonObligatoire['CDC'] = true;
        } elseif (Roles::droit($this->pdo, 'IMP_BO_CDC_FA_', 'PARAMGEN', true) == 'O') {
            $saisieNonObligatoire['CDC'] = true;
        } else {
            $saisieNonObligatoire['CDC'] = false;
        }

        if (Roles::droit($this->pdo, 'IMP_BO_SCA_FA_' . $societe, 'PARAMSOC', true) == 'O') {
            $saisieNonObligatoire['SCA'] = true;
        } elseif (Roles::droit($this->pdo, 'IMP_BO_SCA_FA_', 'PARAMGEN', true) == 'O') {
            $saisieNonObligatoire['SCA'] = true;
        } else {
            $saisieNonObligatoire['SCA'] = false;
        }

        $steSi  = \Helpers\Outil\Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE') ? $facture['CODE_STE'] : '';
        $steCDC = \Helpers\Outil\Roles::droit($this->pdo, 'CDCSECTO', 'PARAMSTE') ? $facture['CODE_STE'] : '';
        $steSCA = \Helpers\Outil\Roles::droit($this->pdo, 'SCASECTO', 'PARAMSTE') ? $facture['CODE_STE'] : '';

        $typeTva      = new \Entity\Model\TypeTVA($this->pdo);
        $typeTva      = $typeTva->fetchAll();
        $listeTypeTva = array();
        foreach ($typeTva as $key => $value) {
            $listeTypeTva[$value['CODE_TTV']] = $value['LIBELLE'];
        }
        if (!isset($listeTypeTva[''])) {
            $params['AddTypeTvaVide'] = 1;
        }

        $typeAction = '';
        $listeCde   = array();

        if (isset($post['data'][0]) && $post['data'][0]['typeAction'] == '') {
        } else {
            $listeCde = $post['data'];
        }

        $detailFac   = $creationFacture->detailFactTravail($post['facture']);
        $idLastLigne = ($detailFac['NUM_LIG'] ?? 0) + 1;

        if (isset($post['typeAction']) && $post['typeAction'] == 'duplicationLigne') {
            $typeAction = $post['typeAction'];
        }

        if ($typeAction != 'duplicationLigne') {
            foreach ($listeCde as $key => $value) {
                $listeCde[$key]['SELECT_LIGNE'] = $validator->isCheck($value['SELECT_LIGNE']);
                $idLigne                        = $idLastLigne;
                if ($value['typeAction'] == 'ligneManuelle') {
                    $listeCde[$key]['SELECT_LIGNE'] = 1;
                    $listeCde[$key]['CODE_STE']     = $facture['CODE_STE'];
                    $listeCde[$key]['NUM_FACT']     = $facture['NUM_FACT'];
                    $pays_fourniss                  = $fourniss->find($facture['CODE_FOUR'])['CODE_PAYS'];
                    $pays_fourniss_cee              = Sql::boolSql($country->find($pays_fourniss)['PAYSCEE']);

                    $pays_install     = '';
                    $pays_install_cee = 0;
                    if (\Helpers\Outil\Roles::droit($this->pdo, 'PAYSINSTAL', 'PARAMGEN', true) !== null && \Helpers\Outil\Roles::droit($this->pdo, 'PAYSINSTAL', 'PARAMGEN', true) != '') {
                        $pays_install     = \Helpers\Outil\Roles::droit($this->pdo, 'PAYSINSTAL', 'PARAMGEN', true);
                        $pays_install_cee = Sql::boolSql($country->find($pays_install)['PAYSCEE'] ?? true);
                    }

                    if ($pays_install != '' && ($pays_install == $pays_fourniss || ($pays_install_cee && $pays_fourniss_cee))) {
                        $parametr                   = (new \Entity\Model\Parametr($this->pdo))->get();
                        $listeCde[$key]['TAUX_TVA'] = number_format($parametr->TX_TVA, 2);
                    } else {
                        $listeCde[$key]['TAUX_TVA'] = number_format(0, 2);
                    }



                    $listeCde[$key]['TYPE_TVA'] = $fourniss->find($facture['CODE_FOUR'])['TYP_TVA'];

                    $typeTvaSpecifique = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Facture\\Service\\TypeTVASpecifique', 'getTypeTVA', $this->pdo, $facture['CODE_FOUR'], $facture['CODE_STE']);
                    if ($typeTvaSpecifique) {
                        $listeCde[$key]['TYPE_TVA'] = $typeTvaSpecifique;
                    }

                    //TODO SPEC 4961
                    $listeCde[$key]['RECEP_EN_MONTANT'] = 1;

                    // SPECIFIQUE : Initialisation SI par celui de l'entête
                    $listeCde[$key]['CODE_SI'] = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Facture\\Repository\\CsCreationFacture', 'initCsSI', 'FAC_ENT', str_pad($facture['NUM_FACT'], 9, 0, STR_PAD_LEFT), $this->pdo);

                    // SPECIFIQUE : Initialisation CDC spécifique
                    $specifique          = new \Helpers\Additional\Specifique\Specifique();
                    $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Outil\\CompteComptable');
                    if (class_exists($namespaceSpecifique)) {
                        $paramsCdcSpec  = ['societe' => $facture['CODE_STE'], 'fournisseur' => $facture['CODE_FOUR'], 'codeEnrLigne' => str_pad($post['facture'], 9, '0', STR_PAD_LEFT) . $idLigne];
                        $listeCde[$key] = array_merge($listeCde[$key], \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Outil\\CompteComptable', 'initCompteComptable', $this->pdo, $paramsCdcSpec));
                    }
                } elseif ($value['typeAction'] == 'eclatementLigneInit') {
                    $indexEclatementLigneInit = $key;
                    $typeAction               = 'eclatementLigneInit';

                    // SPECIFIQUE : Initialisation CDC spécifique
                    $specifique          = new \Helpers\Additional\Specifique\Specifique();
                    $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Outil\\SousFamille');
                    if (class_exists($namespaceSpecifique)) {
                        $paramsCdcSpec                         = ['societe' => $facture['CODE_STE'], 'CODE_CDC' => $listeCde[$key]['CODE_CDC']];
                        $resultSousFamille                     = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Outil\\SousFamille', 'initSousfamilleSelonCdc', $this->pdo, $paramsCdcSpec);
                        $listeCde[$key]['sousFamilleReadonly'] = $resultSousFamille['sousFamilleReadonly'];
                        $listeCde[$key]['listeSousFamille']    = $resultSousFamille['listeSousFamille'];
                    }
                } elseif ($value['typeAction'] == 'eclatementLigne') {
                    $listeCde[$key]['QUANTITE'] = 0;
                    $listeCde[$key]['MONTANT']  = 0;
                    $listeCde[$key]['MT_TVA']   = 0;

                    // SPECIFIQUE : Initialisation CDC spécifique
                    $specifique          = new \Helpers\Additional\Specifique\Specifique();
                    $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Outil\\SousFamille');
                    if (class_exists($namespaceSpecifique)) {
                        $paramsCdcSpec                         = ['societe' => $facture['CODE_STE'], 'CODE_CDC' => $listeCde[$key]['CODE_CDC']];
                        $resultSousFamille                     = \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Outil\\SousFamille', 'initSousfamilleSelonCdc', $this->pdo, $paramsCdcSpec);
                        $listeCde[$key]['sousFamilleReadonly'] = $resultSousFamille['sousFamilleReadonly'];
                        $listeCde[$key]['listeSousFamille']    = $resultSousFamille['listeSousFamille'];
                    }
                }

                // Ligne en montant : réception en montant ou terme de paiement en montant, manuelle et sans numéro de ligne de commande
                if ($listeCde[$key]['RECEP_EN_MONTANT'] == 1 || ($listeCde[$key]['NUM_TERME'] != 0 && $listeCde[$key]['TP_QUANT'] == 0) || ($listeCde[$key]['NUM_LICDE'] == 0 || ($listeCde[$key]['LIG_MAN'] ?? 0) == 1)) {
                    $listeCde[$key]['ligneEnMontant'] = 1;
                } else {
                    $listeCde[$key]['ligneEnMontant'] = 0;
                }

                if (isset($value['CODE_SI']) && $value['CODE_SI'] != '') {
                    $si                                       = $sectimpu->find(['CODE_SI' => $value['CODE_SI'], 'CODE_STE' => $steSi]);
                    $listeCde[$key]['codeGestionSaisie']      = Sql::boolSql($si['SICODG'] ?? false);
                    $listeCde[$key]['codeGestionObligatoire'] = Sql::boolSql($si['IMPCODG'] ?? false) == 1 ? 'false' : 'true';
                    $listeCde[$key]['LIBELLE_SI']             = $si['LIBELLE'] ?? '';

                    if ((new LicenceOxalys($this->pdo))->codeGestionActive()) {
                        $cg_ligne                      = $Codgest->find([
                            'CODE_GES' => $value['ID_CG'],
                            'CODE_STE' => $steSi,
                            'CODE_SI'  => $value['CODE_SI'],
                            'NUM_LOT'  => intval($numLot),
                        ]);
                        $listeCde[$key]['codeGestion'] = $cg_ligne['CODE_AFF'] ?? '';
                        $listeCde[$key]['LIBELLE_CDG'] = $cg_ligne['LIB_GES'] ?? '';
                    }
                } else {
                    $listeCde[$key]['codeGestionSaisie']      = 0;
                    $listeCde[$key]['codeGestionObligatoire'] = 0;
                }

                if ($value['typeAction'] == '') {
                    $last_NO_LIGNE = $idLastLigne;
                }
            }

            if ($typeAction == 'eclatementLigneInit') {
                $last_NO_LIGNE_tmp                             = $post['last_NO_LIGNE_tmp'] + 1;
                $listeCde[$last_NO_LIGNE_tmp]                  = $listeCde[$indexEclatementLigneInit];
                $listeCde[$last_NO_LIGNE_tmp]['NO_LIGNE_PERE'] = $listeCde[$indexEclatementLigneInit]['NO_LIGNE'];
                $listeCde[$last_NO_LIGNE_tmp]['NO_LIGNE']      = $idLastLigne;
                $listeCde[$last_NO_LIGNE_tmp]['QUANTITE']      = 0;
                $listeCde[$last_NO_LIGNE_tmp]['MONTANT']       = 0;
                $listeCde[$last_NO_LIGNE_tmp]['MT_TVA']        = 0;
                foreach ($listeCde[$last_NO_LIGNE_tmp] as $k => $val) {
                    $tbKeyCs = explode($spliter, $k);
                    if (count($tbKeyCs) > 1) {
                        $listeCde[$last_NO_LIGNE_tmp][implode($spliter, $tbKeyCs) . $spliter . $last_NO_LIGNE_tmp] = $listeCde[$indexEclatementLigneInit][implode($spliter, $tbKeyCs)] ?? $listeCde[$indexEclatementLigneInit][implode($spliter, $tbKeyCs) . $spliter . $listeCde[$indexEclatementLigneInit]['NO_LIGNE']];

                        $listeCde[$last_NO_LIGNE_tmp]['CS' . $tbKeyCs[3]] = $listeCde[$indexEclatementLigneInit][implode($spliter, $tbKeyCs)];

                        unset($listeCde[$last_NO_LIGNE_tmp][$k]);
                    }
                }
                $listeCde[$last_NO_LIGNE_tmp]['typeAction'] = 'eclatementLigne';
            }
        } else {
            $infoFacLig = $creationFacture->infoLigneTravail($post['facture'], $post['ligFact']);
            $listeCSFac = $creationFacture->infoCSLigTravail($post['facture'], $post['ligFact']);

            $calculFac = $creationFacture->detailSelectFactTravail($post['facture']);
            $montant   = floatval($facture['TOTAL_HT']) - floatval($calculFac['HT'] ?? 0);

            foreach ($listeCde as &$cde) {
                $cde = array_merge($cde, $infoFacLig);
                if (isset($cde['CODE_SI']) && $cde['CODE_SI'] != '') {
                    $si                            = $sectimpu->find(['CODE_SI' => $cde['CODE_SI'], 'CODE_STE' => $steSi]);
                    $cde['codeGestionSaisie']      = Sql::boolSql($si['SICODG']);
                    $cde['codeGestionObligatoire'] = Sql::boolSql($si['IMPCODG']) == 1 ? 'false' : 'true';
                    $cde['LIBELLE_SI']             = $si['LIBELLE'];

                    if ((new LicenceOxalys($this->pdo))->codeGestionActive()) {
                        $cg_ligne           = $Codgest->find([
                            'CODE_GES' => $cde['ID_CG'],
                            'CODE_STE' => $steSi,
                            'CODE_SI'  => $cde['CODE_SI'],
                            'NUM_LOT'  => intval($numLot),
                        ]);
                        $cde['codeGestion'] = $cg_ligne['CODE_AFF'] ?? '';
                        $cde['LIBELLE_CDG'] = $cg_ligne['LIB_GES'] ?? '';
                    }
                } else {
                    $cde['codeGestionSaisie']      = 0;
                    $cde['codeGestionObligatoire'] = 0;
                }

                // Ligne en montant : réception en montant ou terme de paiement en montant, manuelle et sans numéro de ligne de commande
                if ($cde['RECEP_EN_MONTANT'] == 1 || ($cde['NUM_TERME'] != 0 && $cde['TP_QUANT'] == 0) || ($cde['NUM_LICDE'] == 0 || $cde['LIG_MAN'] == 1)) {
                    $cde['ligneEnMontant'] = 1;
                } else {
                    $cde['ligneEnMontant'] = 0;
                }

                if (!$cde['ligneEnMontant']) {
                    $cde['PU_REMISE'] = $montant / floatval($cde['QUANTITE']);
                }
                $cde['MONTANT'] = $montant;
                $cde['MT_TVA']  = $montant * floatval($cde['TAUX_TVA']) / 100;

                $cde['SELECT_LIGNE'] = $cde['SELECTIONNEE'];

                $cde['REFARTFOURN'] = $infoFacLig['REFARTFOU'];

                // soit un duplique depuis les valeurs trouvées dans FAC_LIG_TRAVAIL, soit on va chercher ces valeurs dans les input dans le cas de la duplication d'une ligne créée manuellement (donc pas encore dans FAC_LIG_TRAVAIL)

                $creationFacture->insertLigneFacLigTravail($post['facture'], $post['ligFact'], $cde['NO_LIGNE'], $cde);

                foreach ($listeCSFac as $cs) {
                    $infoCS = $repoChampSup->getInfoCS('FAC_LIG', $cs['NUM_FIX']);

                    if (Sql::boolSql($infoCS['NONDUPLI'])) {
                        $cde['CS' . $cs['NUM_FIX']] = '';
                    } else {
                        $cde['CS' . $cs['NUM_FIX']] = $cs['VALEUR'];
                    }

                    ChampSupp::insertChampSupp('FAC_LIG_TRAVAIL', ChampSupp::autoCompletCodeEnr($post['facture'], $cde['NO_LIGNE'], 'FAC_LIG'), $cs['NUM_FIX'], $cde['CS' . $cs['NUM_FIX']], $this->pdo);
                }
            }
        }

        foreach ($listeCde as $cde) {
            if ($cde['typeAction'] == 'ligneManuelle') {
                $creationFacture->insertNewFacLigTravail($post['facture'], $cde['NO_LIGNE'], $cde);
            }
            if (isset($cde['CODE_CDC'])) {
                $cde['LIBELLE_CDC'] = $Codecomp->find(['CODE_CDC' => $cde['CODE_CDC'], 'CODE_STE' => $steCDC])['LIBELLE'] ?? '';
            }
            if (isset($cde['CODE_SCA'])) {
                $cde['LIBELLE_SCA'] = $Sscptana->find(['CODE_SCA' => $cde['CODE_SCA'], 'CODE_STE' => $steSCA])['LIBELLE'] ?? '';
            }
        }

        // Paramétrage spécifique
        $specifique          = new \Helpers\Additional\Specifique\Specifique();
        $namespaceSpecifique = $specifique->specifiqueFunction('\\Modules\\Outil\\Parametrage');
        if (class_exists($namespaceSpecifique)) {
            $params = array_merge($params, \Helpers\Additional\Specifique\Specifique::specifique('\\Modules\\Outil\\Parametrage', 'FactureAffectation', $this->pdo));
        }



        $menuContextuel = new AffectationMenuContextuel($this->pdo, $this->router, $this->getTranslationService());

        foreach ($listeCde as &$cde) {
            $cde['NUM_FACT']       = $post['facture'];
            $cde['menuContextuel'] = $menuContextuel->generate($cde, ($post['mode'] ?? ''));
        }

        return $this->renderer->render('@ajax-facture/ligne-affectation', [
            'listeCde'             => $listeCde,
            'facture'              => $facture ?? '',
            'saisieNonObligatoire' => $saisieNonObligatoire,
            'numLot'               => $numLot,
            'last_NO_LIGNE'        => $last_NO_LIGNE ?? '',
            'last_NO_LIGNE_tmp'    => $last_NO_LIGNE_tmp ?? 0,
            'listeCS'              => $listeCS,
            'action'               => $post['mode'] ?? '',
            'listeTypeTva'         => $listeTypeTva,

            'params'               => $params,
            'numFact'              => $post['facture'],
            'typeAction'           => $post['typeAction'] ?? '',
            'droits'               => $droits,
        ]);
    }

    /*****************************************************  *****************************************************/
    // VERIFICATION SI AFFICHAGE DU CODE GESTION SELON SECTION D'IMPUTATION
    public function setCGAction()
    {
        $post  = $this->request->getParsedBody();
        $stesi = \Helpers\Outil\Roles::droit($this->pdo, 'SISECTOR', 'PARAMSTE') ? $post['CODE_STE'] : '';

        $sectimpu = new \Entity\Model\Sectimpu($this->pdo);
        $sectimpu = $sectimpu->find(['CODE_SI' => $post['CODE_SI'], 'CODE_STE' => $stesi]);

        $codeGestion['saisie']         = Sql::boolSql($sectimpu['SICODG'] ?? 0);
        $codeGestion['nonObligatoire'] = Sql::boolSql($sectimpu['IMPCODG'] ?? 0) == 1 ? 'false' : 'true';

        $codeGestion['cG_label'] = $sectimpu[2] ?? $post['CODE_SI'];

        if (isset($post['NO_LIGNE'])) {
            $repository = new CreationFacture($this->pdo);
            $repository->updateFacLigTravail($post['NUM_FACT'], $post['NO_LIGNE'], '', 'ID_CG', '');
        }

        return new Response(200, [], (string) \json_encode($codeGestion));
    }

    // AFFICHAGE DU DETAIL DE LA LIGNE DANS CHOIX DES COMMANDES
    public function detailChoixDesCommandesAction(): string
    {
        // Au premier affichage, affichage des 5 premières lignes
        $post = $this->request->getParsedBody();

        $br       = new \Modules\Facture\Repository\CreationFacture($this->pdo);
        $brLignes = $br->getLignCDE($post['id']);

        $nombreEnregistrement = count($brLignes);

        if ($nombreEnregistrement > 5 && !isset($post['affichage'])) {
            $paginator         = new Paginator();
            $infoPagination    = $paginator->generate($brLignes, 5, $post);
            $post['affichage'] = 'notAll';
        }

        return $this->renderer->render('@ajax-facture/detail-choix-des-commandes', [
            'cas'                  => $brLignes,
            'nombreEnregistrement' => $nombreEnregistrement,
            'id'                   => $post['id'],
            'affichage'            => $post['affichage'] ?? '',

        ]);
    }

    // GESTION FACTURE - CHOIX AVOIR : DETAIL DE L'ENTETE FACTURE + LISTE DES LIGNES DE LA FACTURE
    public function ligneFactureAction(): string
    {
        // Au premier affichage, affichage des 5 premières lignes
        $post      = $this->request->getParsedBody();
        $factureId = $this->request->getAttribute('numFact');

        $factures = new \Modules\Facture\Repository\GestionFacture($this->pdo);
        $entete   = $factures->getEntetFact($factureId);

        $lignes               = $factures->listeLigneFacture($factureId);
        $nombreEnregistrement = count($lignes);

        if ($nombreEnregistrement > 5 && !isset($post['affichage'])) {
            $paginator = new Paginator();
            $paginator->generate($lignes, 5, $post);
            $post['affichage'] = 'notAll';
        }

        foreach ($lignes as &$facLigne) {
            $facLigne['codeCs'] = ChampSupp::autoCompletCodeEnr(
                $facLigne['NUM_FACT'],
                $facLigne['NUM_LIG'],
                'FAC_LIG',
            );
        }

        return $this->renderer->render('@ajax-facture/tableFactureDetail', [
            'lignes'               => $lignes,
            'entete'               => $entete,
            'nombreEnregistrement' => $nombreEnregistrement,
            'id'                   => $factureId,
            'affichage'            => $post['affichage'] ?? '',
            'params'               => [
                'IS_EXPE_ACTIVE' => (new LicenceOxalys($this->pdo))->expeditionActive(),
                'IS_TP_ACTIVE'   => (new LicenceOxalys($this->pdo))->termPaieActive(),
                'IS_CG_ACTIVE'   => (new LicenceOxalys($this->pdo))->codeGestionActive(),
            ],
            'codeEnrCs'            => ChampSupp::autoCompletCodeEnr($factureId),
        ]);
    }

    // VISUALISATION FACTURE : DETAILS DE LA LIGNE SELECTIONNEE
    public function ligneDetailAction(): string
    {
        $id       = $this->request->getAttribute('numFact');
        $numLigne = $this->request->getAttribute('ligne');

        $facture = new \Modules\Facture\Repository\GestionFacture($this->pdo);
        $ligne   = $facture->detail1LigneFacture($id, $numLigne);

        $TypeTVA                  = new \Entity\Model\TypeTVA($this->pdo);
        $ligne['TypeTVA_LIBELLE'] = $TypeTVA->find($ligne['TYPE_TVA'])['LIBELLE'] ?? '';

        return $this->renderer->render('@ajax-facture/ligne-detail', [
            'ligne'     => $ligne,
            'listeCS'   => ChampSupp::listeIdCS('FAC_LIG', $this->pdo),
            'codeEnrCs' => ChampSupp::autoCompletCodeEnr($id, $numLigne, 'FAC_LIG'),

        ]);
    }

    // LISTE FACTURE PAR ENTÊTE : DETAIL ENTETE FACTURE + LISTE DES LIGNES DE LA FACTURE
    public function ligneListeEnteteAction(): string
    {
        // Au premier affichage, affichage des 5 premières lignes
        $post = $this->request->getParsedBody();

        $factures = new \Modules\Facture\Repository\GestionFacture($this->pdo);
        $entete   = $factures->getEntetFact($post['id']);

        $listesFacture = new \Modules\Facture\Repository\ListesFacture($this->pdo);
        $lignes        = $listesFacture->ligneListeEntete($post['id']);

        $nombreEnregistrement = count($lignes);

        if ($nombreEnregistrement > 5 && !isset($post['affichage'])) {
            $paginator         = new Paginator();
            $infoPagination    = $paginator->generate($lignes, 5, $post);
            $post['affichage'] = 'notAll';
        }

        return $this->renderer->render('@ajax-facture/ligne-liste-entete', [
            'lignes'               => $lignes,
            'entete'               => $entete,
            'nombreEnregistrement' => $nombreEnregistrement,
            'id'                   => $post['id'],
            'affichage'            => $post['affichage'] ?? '',
            'IS_EXPE_ACTIVE'       => (new LicenceOxalys($this->pdo))->expeditionActive(),
        ]);
    }

    // LISTE FACTURE PAR LIGNES : DETAIL DE LA LIGNE SELECTIONNEE + DETAIL ENTETE FACTURE
    public function ligneListeLigneAction(): string
    {
        $post = $this->request->getParsedBody();

        $factures = new \Modules\Facture\Repository\GestionFacture($this->pdo);
        $entete   = $factures->getEntetFact($post['facture']);

        $listesFacture = new \Modules\Facture\Repository\ListesFacture($this->pdo);
        $ligne         = $listesFacture->ligneListeLigne($post['facture'], $post['ligne']);

        return $this->renderer->render('@ajax-facture/ligne-liste-ligne', [
            'ligne'     => $ligne,
            'entete'    => $entete,
            'id'        => $post['id'],
            'affichage' => $post['affichage'] ?? '',

        ]);
    }

    // LORS D'UN ENVOI DE MAIL À PARTIR DU MODULE FACTURE, LES ÉLÉMENTS DU MAIL SONT CONSERVÉS DANS LA TABLE DES ÉVÈNEMENTS
    public static function mailEvenementFactureAction($post)
    {
        $xmlResult = new \Modules\Facture\WebService\MailEvenementFacture();
        $xmlResult = $xmlResult->mailEvenement($post);
        $reponse   = new \SimpleXMLElement($xmlResult->responseData);

        return $reponse;
    }

    // MAJ d'une valeur sur une ligne dans FAC_LIG_TRAVAIL
    public function ajaxInsertValueAction()
    {
        $post    = $this->request->getParsedBody();
        $spliter = Constante::spliter;

        $numFact = $post['numFact'];
        $numLig  = $post['numLig'];
        $value   = $post['value'];
        $champs  = $post['CODE_CHAMPS'];

        $validator = $this->createValidator();
        $champSupp = new ChampSupp($this->pdo);

        if (substr($champs, 0, 16) == 'CS_' . $spliter) {
            $detailCS = $champSupp->generateChampSupp('FAC_LIG', '', substr($champs, 16));

            if ($detailCS['0']['FORMAT'] == 'D') {
                ChampSupp::convertDateToCS($value);
            } elseif ($detailCS['0']['FORMAT'] == 'N') {
                $value = str_replace(' ', '', $value);
            } elseif ($detailCS['0']['FORMAT'] == 'L') {
                if ($value == 'true') {
                    $value = '1';
                } else {
                    $value = '0';
                }
            }

            $numFixe = substr($champs, 16);
            $champSupp->updateChampSupp('FAC_LIG_TRAVAIL', $champSupp::autoCompletCodeEnr($numFact, $numLig, 'FAC_LIG'), $numFixe, $value, $this->pdo);
        } else {
            if ($champs == 'CODE_CDC') {
                // SPECIFIQUE : initialisation des CS FAC_LIG en fonction du CODE_CDC
                $facLigCs = Specifique::specifique('\\Modules\\Facture\\Service\\AjaxFactureService', 'updateCsValue', $this->pdo, $value, $numFact);
                if ($facLigCs) {
                    foreach ($facLigCs as $cs) {
                        $champSupp->updateChampSupp('FAC_LIG_TRAVAIL', $champSupp::autoCompletCodeEnr($numFact, $numLig, 'FAC_LIG'), $cs['NUM_FIX'], $cs['VALEUR'], $this->pdo);
                    }
                }
            }

            $entity       = new FacLigTravail($this->pdo);
            $architecture = $entity->getArchitecture($this->getTranslationService());
            $detailChamps = $architecture[$champs];

            if ($detailChamps['type'] == 'DATE') {
                $validator->isDate($value);
            } elseif ($detailChamps['type'] == 'float') {
                $validator->isFloat($value, $value, 13.5);
                // $value = str_replace(' ', '', $value);
            } elseif ($detailChamps['type'] == 'RADIO') {
                if ($value == 'true') {
                    $value = 1;
                } else {
                    $value = 0;
                }
            }

            if (!$validator->isValid()) {
                return new Response(200, [], $validator->getError());
            }

            $repository = new CreationFacture($this->pdo);
            $repository->updateFacLigTravail($numFact, $numLig, $value, $champs, $detailChamps['type']);
        }

        return new Response(200, []);
    }

    // CALCUL HT ET TVA TOTAL DEPUIS FAC_LIG_TRAVAIL
    public function calculTotalAction()
    {
        $post    = $this->request->getParsedBody();
        $numFact = $this->request->getAttribute('numFact');

        $creationFacture = new CreationFacture($this->pdo);
        $detailSelect    = $creationFacture->detailSelectFactTravail($numFact);

        return new Response(200, [], (string) \json_encode([
            'HT'  => $detailSelect['HT'] ?? 0,
            'TVA' => $detailSelect['TVA'] ?? 0,
        ]));
    }

    // MAJ groupée dans FAC_LIG_TRAVAIL
    public function ajaxModificationGroupeAction()
    {
        $post    = $this->request->getParsedBody();
        $numFact = $this->request->getAttribute('numFact');

        $creationFacture = new CreationFacture($this->pdo);
        $creationFacture->updateFacture($numFact, $post);

        return new Response(200, []);
    }

    /**
     * @return Response
     */
    public function factureEnteteFournisseurAction()
    {
        $post            = $this->request->getParsedBody();
        $id              = $post['value'];
        $CreationFacture = new \Modules\Facture\Repository\CreationFacture($this->pdo);
        $fournisseur     = $CreationFacture->getFournisseur($id);
        $dateConvertie   = new \Helpers\Outil\Date();

        if (is_array($fournisseur)) {
            // Récupération des libellés des conditions de paiement et mode de paiement
            $CondPaie = new \Entity\Model\CondPaie($this->pdo);

            $fournisseur['COND_PAIE_LIBELLE'] = $CondPaie->find($fournisseur['COND_PAIE'])['LIBELLE'];
            $Modepaie                         = new \Entity\Model\Modepaie($this->pdo);
            $fournisseur['modepaie_LIBELLE']  = $Modepaie->find($fournisseur['MODE_PAIE'])['LIBELLE'];

            $facture = new \Modules\Ajax\Repository\Facture($this->pdo);

            // Calcul de la date d'échéance
            \Helpers\Outil\Date::dateToSql($post['DATE_FAFO']);
            \Helpers\Outil\Date::dateToSql($post['DATE_ENR']);
            $post['COND_PAIE']      = $fournisseur['COND_PAIE'];
            $fournisseur['dateEch'] = \Modules\Facture\Controller\AjaxFactureController::calculDateEch($post, $post['DATE_FAFO'], $this->pdo);
            $fournisseur['dateEch'] = $dateConvertie->dateConverte($fournisseur['dateEch']);
            // TODO aller voir si la fonction calculDelaiPaiement() ci-dessous est utilisée ailleurs et probablement la remplacer par calculDateEch()
            // $fournisseur['dateEch']= \Helpers\Outil\Date::dateConverte($facture->calculDelaiDePaiement($dateBase, $fournisseur['COND_PAIE']));

            // Récupération de la valeur et le libellé de la devise
            $deviseEntity                 = new \Entity\Model\Devise($this->pdo);
            $fournisseur['libelleDevise'] = $deviseEntity->find($fournisseur['DEVISE'])['LIBELLE'] ?? '';

            // Taux devise BDD et Société
            $outilCreationFacture = new \Modules\Facture\Outil\CreationFacture();
            $fournisseur          = array_merge($fournisseur, $outilCreationFacture->getTxDevise($this->pdo, ['deviseBDD' => $post['deviseBDD'], 'deviseSociete' => $post['deviseSociete'], 'deviseFacture' => $fournisseur['DEVISE']]));

            // Récupération du taux de tva
            $country           = new \Entity\Model\Country($this->pdo);
            $pays_fourniss     = $fournisseur['CODE_PAYS'];
            $pays_fourniss_cee = Sql::boolSql($country->find($pays_fourniss)['PAYSCEE']);

            $paravrac         = new Paravrac($this->pdo);
            $pays_install     = $paravrac->getPaysInstall();
            $pays_install_cee = Sql::boolSql($country->find($pays_install)['PAYSCEE']);
            // On prend le taux de TVA paramétré si les deux conditions suivantes sont vraies :
            // Condition 1 :  il existe un pays d'installation paramétré
            // Condition 2 :  le pays du fournisseur = le pays d'installation OU les pays d'installation et fournisseur sont CEE
            // Sinon, il est défini à 0;
            if ($pays_install != '' && ($pays_install == $pays_fourniss || ($pays_install_cee && $pays_fourniss_cee))) {
                $fournisseur['taux_tva'] = (new \Entity\Model\Parametr($this->pdo))->get()->TX_TVA;
            } else {
                $fournisseur['taux_tva'] = 0;
            }
        }

        return new Response(200, [

        ], (string) \json_encode($fournisseur));
    }

    /**
     * @return Response
     */
    public function factureModeNumAction()
    {

        $post = $this->request->getParsedBody();
        $id   = $post['value'];

        $facture          = new \Modules\Facture\Repository\CreationFacture($this->pdo);
        $fact['MODE_NUM'] = $facture->getModeNumFact($id);

        $trad               = $this->getTranslationService();
        $fact['texteLabel'] = $trad->t('Numéro d\'enregistrement :');
        if ($fact['MODE_NUM'] == 'M') {
            $fact['texteLabel'] .= '<span class="obligatoire">*</span>';
        }

        $societe               = new \Entity\Model\Societe($this->pdo);
        $fact['deviseSociete'] = $societe->find($id)['DEVISE'];

        // Initialisation de la devise facture
        $fact['deviseFacture'] = $post['CODE_FOUR'] != '' ? $post['deviseFacture'] : $fact['deviseSociete'];
        $devise                = new \Entity\Model\Devise($this->pdo);
        $fact['libelleDevise'] = $devise->find($fact['deviseFacture'])['LIBELLE'];

        // Taux devise BDD et Société
        $outilCreationFacture = new \Modules\Facture\Outil\CreationFacture();
        $fact                 = array_merge($fact, $outilCreationFacture->getTxDevise($this->pdo, ['deviseBDD' => $post['deviseBDD'], 'deviseSociete' => $fact['deviseSociete'], 'deviseFacture' => $fact['deviseFacture']]));

        return new Response(200, [

        ], (string) \json_encode($fact));
    }

    /**
     * @return Response
     */
    public function factureEnteteNumCdeAction()
    {
        $post    = $this->request->getParsedBody();
        $id      = $post['value'];
        $CaEntet = new \Entity\Model\CaEntet($this->pdo);
        $CaEntet = $CaEntet->find($id, [], [], $this->pdo::FETCH_ASSOC);

        if ($CaEntet) {
            $CondPaie                     = new \Entity\Model\CondPaie($this->pdo);
            $CaEntet['COND_PAIE_LIBELLE'] = $CondPaie->find($CaEntet['COND_PAIE'])['LIBELLE'];
            $Modepaie                     = new \Entity\Model\Modepaie($this->pdo);
            $CaEntet['modepaie_LIBELLE']  = $Modepaie->find($CaEntet['MODE_PAIE'])['LIBELLE'];

            // Valeur de la devise
            $fournisseur              = new \Entity\Model\Fourniss($this->pdo);
            $fournisseur              = $fournisseur->find($CaEntet['CODE_FOU']);
            $CaEntet['RS_FOU']        = $fournisseur['RS'];
            $Devise                   = new \Entity\Model\Devise($this->pdo);
            $CaEntet['libelleDevise'] = $Devise->find($CaEntet['DEVISE'])['LIBELLE'];

            // Taux devise BDD et Société
            $outilCreationFacture = new \Modules\Facture\Outil\CreationFacture();
            $CaEntet              = array_merge($CaEntet, $outilCreationFacture->getTxDevise($this->pdo, ['deviseBDD' => $post['deviseBDD'], 'deviseSociete' => $post['deviseSociete'], 'deviseFacture' => $CaEntet['DEVISE']]));
        }

        return new Response(200, [

        ], (string) \json_encode($CaEntet));
    }

    /**
     * @return Response
     */
    public function deviseAction()
    {
        $post          = $this->request->getParsedBody();
        $deviseFacture = $post['value'];
        $deviseBDD     = $post['deviseBDD'];
        $deviseSociete = $post['deviseSociete'];

        // Taux devise BDD et Société
        $outilCreationFacture = new \Modules\Facture\Outil\CreationFacture();
        $taux                 = $outilCreationFacture->getTxDevise($this->pdo, ['deviseBDD' => $deviseBDD, 'deviseSociete' => $deviseSociete, 'deviseFacture' => $deviseFacture]);

        return new Response(200, [

        ], (string) \json_encode($taux));
    }
}
