<?php

/**
 *  Classe permettant de gérer le panier
 */
class Panier
{

    /** 
     * Attributs de la classe
     */
    protected $liste_DA;
 // Array : tableau contenant la liste des DA générées à la soumission du panier
    protected $liste_CDE;
 // Array : tableau contenant la liste des CDE générées à la soumission du panier
    protected $liste_cs;
    protected $liste_cc;

    protected $typeChargement; 

    public $libPanier;

    protected $tmp_typeChargement;
    
 // Array : tableau contenant la liste des CS de l'entête du panier
    public function __construct()
    {
        $this->liste_CDE = array();
        $this->liste_DA = array();
    }
    /**
     * Méthodes GET and SET
     */
    public function &getListeDA()
    {
        return $this->liste_DA;
    }

    public function &getListeCDE()
    {
        return $this->liste_CDE;
    }

    public function &getListe_cs()
    {
        return $this->liste_cs;
    }

    public function &getListe_cc()
    {
        return $this->liste_cc;
    }

    
    public function setTypeChargement($typeChargement)
    {
        $this->typeChargement = $typeChargement; 

    }
    public function setLibellePanier($libPanier)
    {
        $this->libPanier = $libPanier; 

    }



    /**
     * Fonction permettant d'intialiser le tableau de la liste des DA créées suite à la soumission du panier
     *
     * @param array $v
     *            : tableau de DA
     */
    public function setListeDA(& $v)
    {

        // Attention : Le format de la réponse récupéré suite à l'appel du WSDL n'est pas le même selon le nombre de résultat retourné
        // Lorsque 1 seul résultat alors le tableau n'est pas indicé, on crée donc un indice 0 afin de garder dans tous les cas au
        // final une structure indicée.
        if (is_array($v))
            // Si une seul DA créée
            if (! is_array($v['DA']))
                $this->liste_DA['DA'][0] = & $v['DA'];
            // Si plusieurs DA créées
            else
                $this->liste_DA = $v;
    }

    /**
     * Fonction permettant d'intialiser le tableau de la liste des CDE créées suite à la soumission du panier
     *
     * @param array $v
     *            : tableau de CDE
     */
    public function setListeCDE(& $v)
    {
        
        // Attention : Le format de la réponse récupéré suite à l'appel du WSDL n'est pas le même selon le nombre de résultat retourné
        // Lorsque 1 seul résultat alors le tableau n'est pas indicé, on crée donc un indice 0 afin de garder dans tous les cas au
        // final une structure indicée.
        if (is_array($v))
            if (! is_array($v['Cde']))
                $this->liste_CDE['Cde'][0] = & $v['Cde'];
            else
                $this->liste_CDE = $v;
    }

    /**
     * Fonction permettant de supprimer une commande dans la liste des commandes générées
     *
     * @param int $no_cde
     *            : numéro de la commande à supprimer
     */
    public function SupprCdeInListeCde($no_cde)
    {
        
        // On supprime de la liste la commande qui vient d'être imprimée
        for ($i = 0; $i < count($this->listeCde); $i ++)
            if ($this->listeCde[$i] == $no_cde) {
                unset($this->listeCde[$i]);
                // On réinitialise les indice du tableau suite au unset
                array_values($this->listeCde);
                break;
            }
    }

    /**
     * Fonction controlant le montant d'un budget, retourne vrai si le format du budget est ok
     *
     * @param int $budget
     *            : budget dont on contrôle la saisie
     * @param string $id
     *            : id du champ budget contrôlé
     * @return boolean : false si le budget est incorrect sinon true
     */
    public static function CtrlBudgetPanier($budget, $id = null)
    {
        
        // On contrôle le champ à partir d'une expression régulière
        if (! ControleSaisie::CtrlBudgetSaisi($budget)) {
            // On affiche le message à l'utilisateur
            Affichage::messageJS(trad('Le budget saisi est invalide, il doit comporter au maximun 9 chiffres et 2 décimales, séparés par un point (.)'));
            // On réinitialise la valeur du champ à 0.00
            if ($id != null)
                Affichage::setValue($id, '0.00');
            return false;
        } else
            return true;
    }

    /**
     * Fonction retournant le total du panier
     *
     * @param int $id_user
     *            : id de l'utilisateur
     * @param int $id_panier
     *            : id du panier
     *            @patam array $critere // COD_FOURN CRITERE_REGROUP
     * @return float : montant du panier
     */
    public static function getTotalPanier(& $id_panier, $critere = null, $type_de_ligne = null, $typeChargement = null, $EntetePanier = null, $force = false)
    {
        /*if(isset($_SESSION['trashV1']) && isset($_SESSION['trashV1']['getTotalPanier']) && $force == false)
        {
            $_SESSION['montant_Total_Panier'] = $_SESSION['trashV1']['getTotalPanier'];
            return $_SESSION['trashV1']['getTotalPanier'];
        } */
        
        // $typeChargement = $typeChargement;
        if(!$EntetePanier)
        {
            $EntetePanier = new PanierEntete();
            $EntetePanier->setTypeChargement($typeChargement);
            $EntetePanier->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
        }
        $devise = $EntetePanier->getCOD_DEV();
        
        if (is_null($critere)) {
            $lignes_panier = SqlPanier::rqGetAllLignePanier($id_panier, NULL, $type_de_ligne)->TrouveTous();
            $modeGlobal = true;
        } else {
            $lignes_panier = SqlPanier::rqGetFrsPanier_1($id_panier, $critere, $type_de_ligne)->TrouveTous();
            $modeGlobal = false;
        }
        
        $montant_total = 0;
        
        if (is_array($lignes_panier))
        foreach ($lignes_panier as & $ligne) {
            
            // Si on calcule le montant total du panier et que la devise de la ligne est différente de la devise de l'entête du panier alos on réalise la
            // conversion depuis la devise de la ligne vers la devise de l'entête
            if ($modeGlobal && $devise != $ligne['COD_DEV'])
                $ligne['PX_ART'] = $ligne['PX_ART'] * Param::getTauxConvDevSrcToDevDest($ligne['COD_DEV'], $devise);
            
            if ($ligne['TXTCOND'] != '' && $ligne['CONDITNT'] > 0)
                $conditionnement = $ligne['CONDITNT'];
            else
                $conditionnement = 1;
                
            // if($ligne['COD_ACD'] != '')
            // {
            //     $prixBase = Article::getInfoPuLigneLibre($ligne['COD_ART'], $ligne['COD_ACD'], $ligne['COD_FOURN'], $ligne['qte']);
            // }
            // else 
            // {
                $prixBase = $ligne['PX_ART'];
            // }

            if (Param::isAfficheTtc()) { // SPEC 3502
                $tauxTva = Article::getTauxTva($ligne['type_de_ligne'], $ligne['COD_ART'], $ligne['COD_SFAM'], $ligne['COD_FOURN'], $ligne['TAUX_TVA'], $ligne['CodeCtrLivraison']);
                $prixBase = Article::getPrixTtc($prixBase, $tauxTva);
            }

            $montant_total += round($prixBase * $ligne['qte'] * $conditionnement, 2);
        }

        $_SESSION['montant_Total_Panier'] = $montant_total;
        return $montant_total;

        return (isset($_SESSION['trashV1']) && !isset($_SESSION['trashV1']['getTotalPanier']))?$_SESSION['trashV1']['getTotalPanier'] = $montant_total:$montant_total;
    }

    /**
     * Fonction retournant le total du panier
     *
     * @param int $id_user
     *            : id de l'utilisateur
     * @param int $id_panier
     *            : id du panier
     * @param int $id_panier
     *            : id de la ligne
     * @param string $code_frs
     *            : code du fournisseur
     * @return float : montant du panier
     */
    public static function getTotalLigne(& $id_user, & $id_panier, & $id_ligne)
    {
        
        if ($r = & SqlPanier::rqGetTotalLignePanier($id_user, $id_panier, $id_ligne)->Trouve1()) {
            // qte,PX_ART,CONDITNT,COD_FOURN,TAUX_TVA
            $prixBase = $r['PX_ART'];
            if (Param::isAfficheTtc()) // SPEC 3502
                $prixBase = $prixBase * (1 + $r['TAUX_TVA'] / 100);
            
            if ($r['TXTCOND'] != '' && $r['CONDITNT'] != 0)
                $prixBase = $prixBase * $r['CONDITNT'];
            
            return $prixBase * $r['qte'];
        } else
            return 0;
    }

    /**
     * Fonction permettant de récupérer la liste des CS présent sur l'entête des DA et pour chaque
     * de récupérer leurs attributs et les valeurs associées aux attributs.
     * Les résultats sont enresgitrés dans un tableau qui peut être transmis à une XSL.
     */
    public function initListeCS($properties, $code_table, $tag_xsl, $id_ligne, $popup_ctrl = 'gestion_cs_panier.php', $num_cs = null, $form, $ligne_exists = true, $contexte = null, $num_bloc = null, $no_doc = null, $typeChargement = null, $numDA = null, $apiMobility = false)
    {
        // On reinitialise la liste des cs
        $this->liste_cs = null;
        
        $liste_numfix = '';

        if ($r = SqlPanier::rqGetAllDevise()->TrouveTous()){
            foreach ($r as & $devise)
            $listeDevises[] = array(
                '!code' => $devise['CODE_DEVI'],
                '!texte' => $devise['LIBELLE']
            );
        }
        
        $panierEntete = new PanierEntete();
        $panierEntete->setTypeChargement($typeChargement);
        $panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
        if ($_SESSION['id_panier'] == 0 && $contexte != 'signerModifDocument')
            if (CountLigne($_SESSION['id_panier']) == 0) {
                SqlCs::rqSupCsPanier($_SESSION['id_panier'])->ExecuteSql();
                
                Panier::CreateLigneCSLeft($_SESSION['id_panier'], false, null);
            }
        
        // Pour le client N°56, si les CS à insérer sont issus DA_LIGNE dans le contexte 'imputation' (onglet imputation du bloc fournisseur du récap panier)
        if (CLT_CHAMPC == $_SESSION['Session_NumClient'] && 'DA_LIGNE' == $code_table && 'imputation' == $contexte) 
        {
            // Les axes d'imputations utilisé par le client N°56 sont tous stockés dans des CS sauf 2 qui reste stockés dans des champs d'imputation.
            // Afin de traiter l'ensemble des champs comme des CS on simule le fait que les 2 champs SI et SCA sont également 2 CS.
            // Pour cela on leur attribue un ensemble de propriétés telles que celles que l'on trouve au niveau des CS.
            // Parmis ces informations associés au CS on trouve une information particulièrement importante qui est le numéro du CS qui permet de l'identifier parmis les autres.
            // Ainsi pour l'axe d'imputation SI on lui attribue un numéro de CS fictif qui est 1000, de même pour l'axe d'imputation SCA pour lequel on attribue un numéro de CS fictif qui est 2000.
            // cela permettra notamment de distinguer ces 2 champs afin de les enregistrer au niveau des lignes dans les champs SI_CODE et SCA_CODE au lieu de les enregistrer dans la table des CS.
            
            $listeCS[0]['COD_TAB'] = 'DA_LIGNE';
            $listeCS[0]['NUM_FIX'] = 1000;
            $listeCS[0]['NUM_VAR'] = 'SI_CODE';
            $listeCS[0]['TYPE'] = 'SECTIMPU';
            $listeCS[0]['NOM'] = trad('Lieu analytique');
            $listeCS[0]['OBLIG'] = true;
            $listeCS[0]['NONDISPO'] = false;
            $listeCS[0]['MODAPVAL'] = false;
            $listeCS[0]['NONMODIF'] = false;
            $listeCS[0]['NONDUPLI'] = false;
            $listeCS[0]['LIBELLE'] = trad('Lieu analytique');
            $listeCS[0]['FORMAT'] = 'A';
            $listeCS[0]['ALP_LONG'] = 14;
            $listeCS[0]['PE_LONG'] = 0;
            $listeCS[0]['PD_LONG'] = 0;
            $listeCS[0]['CONTROLE'] = true;
            $listeCS[0]['CTRL_STD'] = true;
            $listeCS[0]['NOM_CODE'] = '';
            $listeCS[0]['TAB_DESTI'] = 'DA_LIGNE';
            $listeCS[0]['CHP_DESTI'] = 'SI_CODE';
            $listeCS[0]['TAB_SOUR'] = 'CODECOMP';
            $listeCS[0]['CHP_SOUR'] = Param::getNumCSLieuDALigne();
            $listeCS[0]['CODEDICO'] = 'NCS_DA_LIGNE_LIEUANA_VAL';
            
            $listeCS[1]['COD_TAB'] = 'DA_LIGNE';
            $listeCS[1]['NUM_FIX'] = 2000;
            $listeCS[1]['NUM_VAR'] = 'SCA_CODE';
            $listeCS[1]['TYPE'] = 'SSCPTANA';
            $listeCS[1]['NOM'] = trad('Projet');
            $listeCS[1]['MODAPVAL'] = false;
            $listeCS[1]['NONDUPLI'] = false;
            $listeCS[1]['LIBELLE'] = trad('Projet');
            $listeCS[1]['FORMAT'] = 'A';
            $listeCS[1]['ALP_LONG'] = 14;
            $listeCS[1]['PE_LONG'] = 0;
            $listeCS[1]['PD_LONG'] = 0;
            $listeCS[1]['CONTROLE'] = true;
            $listeCS[1]['CTRL_STD'] = true;
            $listeCS[1]['NOM_CODE'] = '';
            $listeCS[1]['TAB_DESTI'] = 'DA_LIGNE';
            $listeCS[1]['CHP_DESTI'] = 'SCA_CODE';
            $listeCS[1]['TAB_SOUR'] = 'CODECOMP';
            $listeCS[1]['CHP_SOUR'] = Param::getNumCSProjetDALigne();
            $listeCS[1]['CODEDICO'] = 'NCS_DA_LIGNE_PROJET_VAL';
            
            $listeCStmp = & SqlCs::rqGetInfoCSDALigneForImputCdc($code_table, $num_cs)->TrouveTous(); // Pour la table $code_table on récupère tous les CS et leur propriété
            
            $listeCS = array_merge($listeCS, $listeCStmp);
            
            // On récupère les informations de la ligne article
            if (! is_null($id_ligne) && ! is_array($id_ligne)) {
                $info_ligne = & SqlPanier::rqGetAllLignePanier($_SESSION['id_panier'], $id_ligne)->Trouve1();
                
                // On initialise 3 tableaux qui vont permettre d'ordonnéer la liste des CS
                $debut = array(); // Contient la liste des CS visibles et modifiables
                $milieu = array(); // Contient la liste des CS visibles
                $fin = array(); // Tous les autres
                                // POur chaque CS de la ligne
                $indCstmp = 0;
                foreach ($listeCS as & $cs)
                    
                    // Si le code du champ contient 'VAL'
                    if (false !== stripos($cs['CODEDICO'], '_VAL')) {
                        $nom_cs = explode('_', $cs['CODEDICO']);
                        
                        $listeCStmp[$indCstmp] = $cs;
                        
                        // Si le champ fait partie des 5 nommé ci-dessous
                        if (false !== stripos($cs['CODEDICO'], 'TXRECUPTVA_VAL') || false !== stripos($cs['CODEDICO'], 'TYPEFRAIS_VAL') || false !== stripos($cs['CODEDICO'], 'MODERECUPTVA_VAL') || false !== stripos($cs['CODEDICO'], 'ACTFACT_VAL') || false !== stripos($cs['CODEDICO'], 'ACTFAR_VAL')) {
                            // Alors on force les caractèristiques suivantes
                            $listeCStmp[$indCstmp]['OBLIG'] = false;
                            $listeCStmp[$indCstmp]['NONMODIF'] = true;
                            $listeCStmp[$indCstmp]['NONDISPO'] = true;
                        }                        // Pour les autres champs on récupère les 3 caractèristiques : obligatoire, non modifiable et non visible dans la base Haplus
                        else {
                            // ATTENTION AU VALEUR DES BOOLEAN
                            $info_propriete_cs_obl = & SqlCs::rqGetParamCSForCDCImput($info_ligne['CDC_CODE'], 'NCS_CODECOMP_' . $nom_cs[3] . '_OBLIG')->Trouve1();
                            $listeCStmp[$indCstmp]['OBLIG'] = BoolSql($info_propriete_cs_obl['VALEUR']);
                            
                            $info_propriete_cs_mod = & SqlCs::rqGetParamCSForCDCImput($info_ligne['CDC_CODE'], 'NCS_CODECOMP_' . $nom_cs[3] . '_MODIF')->Trouve1();
                            $listeCStmp[$indCstmp]['NONMODIF'] = ! BoolSql($info_propriete_cs_mod['VALEUR']);
                            
                            $info_propriete_cs_aff = & SqlCs::rqGetParamCSForCDCImput($info_ligne['CDC_CODE'], 'NCS_CODECOMP_' . $nom_cs[3] . '_AFF')->Trouve1();
                            $listeCStmp[$indCstmp]['NONDISPO'] = ! BoolSql($info_propriete_cs_aff['VALEUR']);
                        }
                        
                        // On ajoute dans $debut les CS visibles et modifiables
                        if (! BoolSql($listeCStmp[$indCstmp]['NONDISPO']) && ! BoolSql($listeCStmp[$indCstmp]['NONMODIF']))
                            $debut[] = $listeCStmp[$indCstmp];
                        // On ajoute dans $milieu les CS visibles
                        elseif (! BoolSql($listeCStmp[$indCstmp]['NONDISPO']) && BoolSql($listeCStmp[$indCstmp]['NONMODIF']))
                            $milieu[] = $listeCStmp[$indCstmp];
                        // On ajoute dans $fin les autres CS
                        else
                            $fin[] = $listeCStmp[$indCstmp];
                        
                        $indCstmp ++;
                    }
                
                // On fusionne les 3 tableaux obtenus
                $listeCS = array_merge($debut, $milieu, $fin);
            }
        } 
        else if (is_null($num_cs)) 
        {
            if (! is_null($id_ligne) && ! is_array($id_ligne)) 
            {
                $panier_temp = $typeChargement; 
                $cl_panier = new PanierEntete(); 
                $panierObject = new Panier(); 
               
                $panierObject->setTypeChargement($typeChargement);
                $info_ligne = & SqlPanier::rqGetAllLignePanier($_SESSION['id_panier'], $id_ligne)->Trouve1();
           
                
                $listeCS = $panierObject->getListeCsArray($code_table, $_SESSION['id_panier'], $info_ligne, false);
            }
            else
            {
                $panierObject = new Panier(); 
                $panierObject->setTypeChargement($typeChargement);
                $listeCS = $panierObject->getListeCsArray($code_table, $_SESSION['id_panier'], $id_ligne, false);
            }
        } else
            $listeCS = & SqlCs::rqGetInfoCS($code_table, $num_cs)->TrouveTous(); // Pour la table $code_table on récupère tous les CS et leur propriété

        if (is_array($listeCS)) 
        {
            foreach ($listeCS as & $cs_attributs) 
            {
                $cs_attributs['OBLIG'] = BoolSql($cs_attributs['OBLIG']);
                $cs_attributs['NONDISPO'] = BoolSql($cs_attributs['NONDISPO']);
                $cs_attributs['MODAPVAL'] = BoolSql($cs_attributs['MODAPVAL']);
                $cs_attributs['NONMODIF'] = BoolSql($cs_attributs['NONMODIF']);
                $cs_attributs['NONDUPLI'] = BoolSql($cs_attributs['NONDUPLI']);
                $cs_attributs['CONTROLE'] = BoolSql($cs_attributs['CONTROLE']);
                $cs_attributs['CTRL_STD'] = BoolSql($cs_attributs['CTRL_STD']);
                $cs_attributs['NEG_AUTO'] = BoolSql($cs_attributs['NEG_AUTO']);
                $cs_attributs['MODIFSIGN'] = BoolSql($cs_attributs['MODIFSIGN']);
            }
        
        /**
         * NE JAMAIS PURGER La liste des champs meme si NONMODIF vaut 1 en effet
         * dans les ecrans cela est affiché en TR HIDDEN servant ensuite lors de la validation à stocker les valeurs
         * contenu depuis le poste client vers le serveur
         */
        }
        
        $i = 0;
        if (is_array($listeCS)) {
            foreach ($listeCS as & $ligne) { // Pour chaque CS
                                             // Dans le contexte de modification de document depuis le module signature on prend on compte
                                             // la propriété des CS : 'Modifiable en signature ?'
                if (('signature' == $contexte || 'signerModifDocument' == $contexte) && !BoolSql($ligne['MODIFSIGN']))
                    $ligne['NONMODIF'] = true;
                else if (('signature' == $contexte || 'signerModifDocument' == $contexte) && BoolSql($ligne['MODIFSIGN']))
                    $ligne['NONMODIF'] = false;

                if ($ligne_exists) {
                    // Pour le client N°56 et pour les CS de type Lieu et Projet alors on récupère la valeur depuis le SI_CODE et le SCA_CODE de la ligne
                    if (CLT_CHAMPC == $_SESSION['Session_NumClient'] && ($ligne['NUM_FIX'] == 1000 || $ligne['NUM_FIX'] == 2000) && 0 != $id_ligne) {
                        $info_ligne = PanierLigne::getOneLigneByPanierUser($_SESSION['id_panier'], $id_ligne);
                        
                        if ($ligne['NUM_FIX'] == 1000)
                            $ligne['VALEUR'] = $info_ligne['SI_CODE'];
                        elseif ($ligne['NUM_FIX'] == 2000)
                            $ligne['VALEUR'] = $info_ligne['SCA_CODE'];
                    } else if ('signature' == $contexte) { // NE RIEN TOUCHER A REVOIR PROCESS COMPLET
                        $no_poste = str_pad($id_ligne, 3, 0, STR_PAD_LEFT) . $id_ligne;
                        $no_document = str_pad($no_doc, 9, 0, STR_PAD_LEFT) . $no_doc;
                        
                        $code_enreg = $no_document . $no_poste;
                        $result = SqlCs::rqGetListeCSbyListNumCs($code_enreg, $code_table, $ligne['NUM_FIX'])->Trouve1();
                        $ligne['VALEUR'] = $result['VALEUR'];
                    } else { // Dossier 23621
                             // Initialisation de la valeur présente dans le CS à partir de la base OXAPROCDB
                        $result = SqlCs::rqRechCsFixe($_SESSION['id_panier'], $id_ligne, $ligne['NUM_FIX'])->Trouve1();
                        $ligne['VALEUR'] = $result['VALEUR'];
                    }
                } else if (! array_key_exists('VALEUR', $ligne))
                    $ligne['VALEUR'] = '';
                
                if ('D' == $ligne['FORMAT'] && $apiMobility == false){ // Reformattage de la date pour affichage selon format session
                    if(strstr($ligne['VALEUR'], '/') == false){
                        $ligne['VALEUR'] = convertDateSqlToFr($ligne['VALEUR']);
                    }
                }
                if($ligne['FORMAT'] == 'U' || $ligne['FORMAT'] == 'E'){
                    $ligne['ALP_LONG'] = '3000';
                }                
                if($ligne['FORMAT'] == 'M'){
                    //$ligne['VALEUR'] = $ligne['CONTMEMO'] ?? '';
                    //32809
                    $ligne['VALEUR'] = $ligne['VALEUR'] ?? '';
                }                

                if ($ligne['VALEUR'] != '' && BoolSql($ligne['CONTROLE']) && ! BoolSql($ligne['CTRL_STD'])) {
                    if ($lib = & SqlCs::rqGetLibCS($ligne['VALEUR'], $ligne['TYPE'], (BoolSql($ligne['TBLSECTO']) ? $panierEntete->getCODE_STE() : ''))->Trouve1())
                        $ligne['libelle_valeur'] = $lib['LIB01DICO'];
                } else if ($ligne['VALEUR'] != '' && BoolSql($ligne['CTRL_STD'])) {
                    $cs_type_list                   = SqlCs::getListeTableStd();
                    $cs_type_check                  = `{`.$cs_type_list[$ligne['TYPE']][0].`}`;
                         
                    if ($cs_type_check === $ligne['TYPE']) {
                        $cs_libelle_req             = SqlCs::getRqForCS($ligne['TYPE'], 'recherche', '', $ligne['VALEUR'])->Trouve1();
                        // print_r($cs_libelle_req); 
                        $ligne['libelle_valeur']    = $cs_libelle_req['Libelle'];
                    } elseif(count(SqlCs::getRqForCS($cs_type_check, 'recherche', '', $ligne['VALEUR'])->Trouve1()) >= 1) {
                        $cs_libelle_req             = SqlCs::getRqForCS($cs_type_check, 'recherche', '', $ligne['VALEUR'])->Trouve1();
                        $ligne['libelle_valeur']    = $cs_libelle_req['Libelle'];
                    }
                    else
                    {
                        $ligne['libelle_valeur']    = "";
                    }
                   
                } else {
                    $ligne['libelle_valeur']    = "";
                }

                $j = 0;
                
                // Pour le client N°56, dans le cas de l'affichage des CS depuis l'onglet imputation
                if ('imputation' == $contexte && CLT_CHAMPC == $_SESSION['Session_NumClient']) {
                    $popup_ctrl_onblur = 'panier_ong_3_input_client_56.php'; // Page cible lorsque l'utilisateur quitte la zone de saisie
                    $popup_ctrl = 'panier_ong_3_input_client_56.php'; // Page cible lorsque l'utilisateur appelle un zoom sur un CS
                    $bloc_name = '_BLOC_' . $num_bloc; // Définition de l'identifiant des blocs fournisseurs
                } else {
                    $popup_ctrl_onblur = $popup_ctrl;
                    $bloc_name = '';
                }
                
                $pointeur = & $this->liste_cs['ListeCS']['CS'][$i];

                foreach ($ligne as $key => & $value) { // Pour chaque attribut du CS
                                                       // On enregistre chaque attribut et sa valeur associée
                                                       
                    if($key=='NOM')
                    {
                        $value = trad($value);
                    }
                    
                    $inputValuetest =  'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR' . $bloc_name;
                    $pointeur['attributs'][$j] = array(
                        '!name' => $key, // Nom du CS
                        '!value' => $value, // Valeur du CS
                        '!cle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_' . $key, // Identifiant du CS
                        '!popup_ctrl' => $popup_ctrl, // Page cible lorsque l'utilisateur appelle un zoom sur un CS
                        '!name_champ_input' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR' . $bloc_name, // Nom du champ imput pour le CS
                        '!name_champ_libelle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_LIBELLE_VALUE', // Libellé de la valeur du CS
                        '!UserAuthModCSNonMod' => $_SESSION['AuthModCSNonMod'], // Droit indiquant si l'utilisateur peut modifier le CS même si celui-ci n'est pas modifiable
                    );

                    if($ligne['FORMAT']=='1' && $key == 'FORMAT'){  
                        $pointeur['attributs'][$j]['id_info_sup'] = 'devise_CS_' . $tag_xsl . '_' .$ligne['NUM_FIX'];
                        $pointeur['attributs'][$j]['value_info_sup'] = array(
                            '!id' => 'select_'.$pointeur['attributs'][$j]['id_info_sup'],
                            '!value' => $panierEntete->getCOD_DEV() ?? $_SESSION['DEVISE_BASE'],
                            '!name' => $pointeur['attributs'][$j]['id_info_sup'],
                            'options' => $listeDevises
                        );
                    }  
                    
                    if($ligne['FORMAT']=='D')
                    {
                        $pointeur['attributs'][$j]['!onclick'] = "CL.show(null,document.{$form}.{$inputValuetest},null,-80);";
                    }

                    if($ligne['FORMAT']=='U')
                    {
                        $pointeur['attributs'][$j]['!onclick'] = 'openUrl(\'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR\')';
                       
                    }   
                    
                    if($ligne['FORMAT']=='E')
                    {
                         $pointeur['attributs'][$j]['!onclick'] = 'openMail(\'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR\')';
                    }
                    
                    if (0 == $j) // Construction de la liste globale de référence des identifiant des CS présents
                        $liste_numfix .= $ligne['NUM_FIX'] . '|';
                    
                    $j ++;
                }
                
                // On ajoute les actions associées aux champs
                // $popup_ctrl_onblur = gestion_cs_panier.php
                if (BoolSql($ligne['CONTROLE'])) {
                    // Ajout de l'action contrôlant la saisie d'un champ soumis à un contrôle
                    $zoom = (BoolSql($ligne['CTRL_STD']) ? 'zoom_CS_TABLE_STD' : 'zoom_TS_DON');
                    $type = htmlentities(urlencode($ligne['TYPE']));
                    $onblur = "if(this.value!=''){Traite('{$popup_ctrl_onblur}?action=SelectValueCS&champ=CS_{$tag_xsl}_{$ligne['NUM_FIX']}_VALEUR$bloc_name&controle=$zoom&type=$type',this.form['CS_{$tag_xsl}_{$ligne['NUM_FIX']}_VALEUR$bloc_name']);}";
                    $onblur .= " else{SetInnerHTML('CS_{$tag_xsl}_{$ligne['NUM_FIX']}_LIBELLE_VALUE','');} ";
                    
                    // Ajout de l'action de zoom sur la liste des valeurs possible d'un CS
                    $champ = "CS_{$tag_xsl}_{$ligne['NUM_FIX']}_VALEUR$bloc_name";
                    $onclick = "Traite(\"{$popup_ctrl}?action={$zoom}&TYPE={$type}&champ={$champ}&LIBELLE=" . htmlentities(urlencode($ligne['NOM'])) . "&form={$form}&controle={$zoom}&type={$type}'\",document.{$form}.{$champ});";
                    
                    $pointeur['actions'] = array(
                        '!onblur' => $onblur,
                        '!onclick' => $onclick
                    );
                }
                
                $i ++;
            }
        }
        
        $liste_numfixTmp = mb_substr($liste_numfix, 0, mb_strlen($liste_numfix) - 1);
        $this->liste_cs['ListeCS']['Listing'] = array(
            '!value' => $liste_numfixTmp
        );
        
        // Action spécifique aux CS de l'entête
        if ('DA_ENTET' == $code_table)
        {
     
            // Action d'enregistrement des CS de l'entête
            $this->liste_cs['ListeCS']['action']['enregistrerCS'] = array(
                '!value' => "TraiteAsync('gestion_cs_panier.php?action=enregistrerCSEntete',document.forms.$form.elements[0],'',\"" . cnv_to_javascript(trad("Enregistrement des champs supplémentaire en cours...")) . '");'
            );

            $panierEntete = new PanierEntete();        
            $panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
            // print_r($_SESSION['Session_NumClient']); exit; 
            
            if($_SESSION['Session_NumClient'] == 71)
            {

                $ok = 0; 
                $valueInit = SqlCs::rqGetNumDA()->Trouve1()['CHP_SOUR'];

                foreach($this->liste_cs['ListeCS']['CS'] as $csKey => $csValue)
                {
                    foreach($csValue['attributs'] as $attributsKey => $attributs)
                    {   
                        if($csValue['attributs'][$attributsKey]['!name'] == 'NUM_FIX' && $csValue['attributs'][$attributsKey]['!value'] == $valueInit)
                        {
                            $ok = 1;
                        }
                        if($csValue['attributs'][$attributsKey]['!name'] == 'VALEUR' && $ok == 1 && $csValue['attributs'][$attributsKey]['!value']=='' && $csValue['attributs'][$attributsKey]['!cle'] == 'CS_0_1_VALEUR')
                        { 
                            $this->liste_cs['ListeCS']['CS'][$csKey]['attributs'][$attributsKey]['!value']  = $numDA; 
                        }
                    } 

                }

            }

        }
        elseif ('DA_LIGNE' == $code_table && 'imputation' == $contexte && CLT_CHAMPC == $_SESSION['Session_NumClient'])
        {
            // Action d'enregistrement des CS des lignes d'un bloc fournisseur donné
            $this->liste_cs['ListeCS']['action']['enregistrerCS'] = array(
                '!value' => "TraiteAsync('" . $properties['popup_ctrl_onblur'] . "?action=enregistrer&bloc_name={$bloc_name}',document.forms.$form.elements[0],'',\"" . cnv_to_javascript(trad("Enregistrement des imputations en cours...")) . '");'
            );
        }


    }

    public function &getListeCsArray(& $code_table, & $id_panier, & $resultLigne, $stkClass = true)
    {
        // YANIS
        // On récupère la liste des CS de l'entete du panier à insérer
        $listeCS = SqlCs::rqGetInfoCS($code_table)->TrouveTous();

        $valueInit = SqlCs::rqGetNumDA()->Trouve1()['CHP_SOUR'];

        if ($listeCS) 
        {
            $PanierEntete = new PanierEntete();
            $tpch = $PanierEntete->setTypeChargement($this->typeChargement); 

            $PanierEntete->getEntetePanier($id_panier, $_SESSION['id_user']);

            foreach ($listeCS as & $cs_attributs) 
            {
                // On vérifie si ces lignes de CS existent déjà ou pas, si elles n'existent pas alors on les créé
                // On créé un objet CS
                $cs_attributs['OBLIG'] = BoolSql($cs_attributs['OBLIG']);
                $cs_attributs['NONDISPO'] = BoolSql($cs_attributs['NONDISPO']);
                $cs_attributs['MODAPVAL'] = BoolSql($cs_attributs['MODAPVAL']);
                $cs_attributs['NONMODIF'] = BoolSql($cs_attributs['NONMODIF']);
                $cs_attributs['NONDUPLI'] = BoolSql($cs_attributs['NONDUPLI']);
                $cs_attributs['CONTROLE'] = BoolSql($cs_attributs['CONTROLE']);
                $cs_attributs['CTRL_STD'] = BoolSql($cs_attributs['CTRL_STD']);
                $cs_attributs['NEG_AUTO'] = BoolSql($cs_attributs['NEG_AUTO']);

                if(($this->typeChargement ?? false) == 'modification' && $_SESSION['Session_NumClient'] == 0 && $cs_attributs['NUM_FIX'] == 1)
                {
                    $cs_attributs['VALEUR'] = 2512;
                }
               
                $CS = new CS($cs_attributs);
 
                // On recherche les valeurs des CS initialisé à partir des CS d'une table tiers
                switch ($CS->getTAB_SOUR()) {
                    
                    case 'CENTRE':
                        $CS->initValueForCSpanier($PanierEntete->getLIV_CTR());
                        break;
                    
                    case 'ARTFOURN':
                        if (! is_null($resultLigne)){
                            $codEnr = str_pad($resultLigne['COD_ART'], 13, ' ', STR_PAD_RIGHT).str_pad($resultLigne['COD_FOURN'], 12, ' ', STR_PAD_RIGHT);
                            $CS->initValueForCSpanier($codEnr);
                        }
                        break;
                    
                    case 'SSFAMILL':
                        if (is_array($resultLigne) && array_key_exists('COD_SFAM', $resultLigne)) {
                            $result = SqlCs::rqGetListeCSbyListNumCs($resultLigne['COD_SFAM'], 'SSFAMILL', '\'' . $CS->getCHP_SOUR() . '\'')->Trouve1();
                            $CS->setVALEUR($result['VALEUR']);
                        }
                        break;
                    
                    case 'ARTICLE': // ????? Soit disant que cela a marcher mais dans TBINI c'est articles avec
                    case 'ARTICLES':
                        if (is_array($resultLigne) && array_key_exists('COD_ART', $resultLigne))
                            $CS->initValueForCSpanier($resultLigne['COD_ART']);
                        break;
                    
                    case 'DA_ENTET':

                        if ($result = & SqlCs::rqRechCsFixe($id_panier, 0, $CS->getCHP_SOUR())->Trouve1())
                        {
                            $CS->setVALEUR($result['VALEUR']);
                        }
                        else
                        {
                            if(($this->typeChargement ?? null) != 'modification' && $_SESSION['Session_NumClient'] != 0)
                            {
                                $CS->setVALEUR('');
                            }
                        }

                        break;
                    
                    /*case 'FOURNISS':
                        $codeFournisse = sqlPanier::rqGetAllFrsByUserPanier()->Trouve1()['COD_FOURN'];
                        $CS->initValueForCSpanier($codeFournisse);
                        break;*/
                    case 'HASTUTIL':
                        $CS->initValueForCSpanier($_SESSION['Session_Login']);
                        break;
                    
                    case 'CODECOMP':
                        if (! is_null($resultLigne)) {
                            $result = & SqlCs::rqGetListeCSbyListNumCs($resultLigne['CDC_CODE'], 'CODECOMP', '\'' . $CS->getCHP_SOUR() . '\'')->Trouve1();
                            $CS->setVALEUR($result['VALEUR']);
                        }
                        break;
                    
                    // SPEC 4331 : ajout de l'initialisation par les CS SECTIMPU et SSCPTANA
                    case 'SECTIMPU':
                        if (! is_null($resultLigne)) {
                            $result = & SqlCs::rqGetListeCSbyListNumCs($resultLigne['SI_CODE'], 'SECTIMPU', '\'' . $CS->getCHP_SOUR() . '\'')->Trouve1();
                            $CS->setVALEUR($result['VALEUR']);
                        }
                        break;
                    
                    case 'SSCPTANA':
                        if (! is_null($resultLigne)) {
                            $result = & SqlCs::rqGetListeCSbyListNumCs($resultLigne['SCA_CODE'], 'SSCPTANA', '\'' . $CS->getCHP_SOUR() . '\'')->Trouve1();
                            $CS->setVALEUR($result['VALEUR']);
                        }
                        break;
                    
                    case 'TYPDOC': // Spécification 2709 : Les CS de DA_ENTET peuvent être initialisés par le CS contenu au niveau du type de document
                                   // On récupère le type de document défini pour l'Oxaproc
                        $type_doc = Param::getTypeDocForOxaproc();
                        
                        // On initialise le CS de l'entête du panier avec la valeur du CS associé au type de document défini pour l'Oxaproc
                        $CS->initValueForCSpanier($type_doc);
                        break;
                    case '': // Dossier 23621 DEP Ajout 
                        if ($code_table == 'DA_ENTET' && $result = & SqlCs::rqRechCsFixe($id_panier, 0, $cs_attributs['NUM_FIX'])->Trouve1())
                        {
                            $CS->setVALEUR($result['VALEUR']);
                        }

                        break;
                }
               
                if ($stkClass)
                    $cs_attributs['class'] = $CS;
                else
                    // VALEUR']/@value
                    $cs_attributs['VALEUR'] = $CS->getVALEUR();
            
            /**
             * A JAMAIS PU MARCHER CELA CAR $ligne NON DEFFINI : EDP JE METS EN COMMENTAIRE CAR BIZARRE CE CODE
             * if (BoolSql($ligne['CONTROLE']) && !BoolSql($ligne['CTRL_STD']))
             * if ( $lib = SqlCs::rqGetLibCS($value['VALEUR'], $ligne['TYPE'],(BoolSql($ligne['TBLSECTO']) ? $panierEntete->getCODE_STE() : ''))->Trouve1() )
             * $value['LIBELLE'] = $lib['LIB01DICO'];
             */
            }
        }
        
        return $listeCS;
    }

    // Fonction pour récupérer les CS Panier entete avec les valeurs sans réinitialisation
    public function &getListeCsArraySansInit(& $code_table, & $id_panier)
    {
        // On récupère la liste des CS de l'entete du panier à insérer
        $listeCS = SqlCs::rqGetInfoCS($code_table)->TrouveTous();

        if ($listeCS) 
        {
            $PanierEntete = new PanierEntete();
            $PanierEntete->getEntetePanier($id_panier, $_SESSION['id_user']);

            foreach ($listeCS as & $cs_attributs) 
            {
                // On vérifie si ces lignes de CS existent déjà ou pas, si elles n'existent pas alors on les créé
                // On créé un objet CS
                $cs_attributs['OBLIG'] = BoolSql($cs_attributs['OBLIG']);
                $cs_attributs['NONDISPO'] = BoolSql($cs_attributs['NONDISPO']);
                $cs_attributs['MODAPVAL'] = BoolSql($cs_attributs['MODAPVAL']);
                $cs_attributs['NONMODIF'] = BoolSql($cs_attributs['NONMODIF']);
                $cs_attributs['NONDUPLI'] = BoolSql($cs_attributs['NONDUPLI']);
                $cs_attributs['CONTROLE'] = BoolSql($cs_attributs['CONTROLE']);
                $cs_attributs['CTRL_STD'] = BoolSql($cs_attributs['CTRL_STD']);
                $cs_attributs['NEG_AUTO'] = BoolSql($cs_attributs['NEG_AUTO']);

                if(($this->typeChargement ?? false) == 'modification' && $_SESSION['Session_NumClient'] == 0 && $cs_attributs['NUM_FIX'] == 1)
                {
                    $cs_attributs['VALEUR'] = 2512;
                }
               
                $CS = new CS($cs_attributs);
                $result = SqlCs::rqRechCsFixe($_SESSION['id_panier'], 0, $cs_attributs['NUM_FIX'])->Trouve1();
                $CS->setVALEUR($result['VALEUR']);
                $cs_attributs['VALEUR'] = $CS->getVALEUR();
            }
        }
        
        return $listeCS;
    }

                
                            



    /**
     * Fonction réalisant l'insertion de tous les CS(entête ou ligne) pour un panier donné, si les ligne de CS existent déjà alors
     * l'insertion n'a pas lieu.
     *
     * @param string $code_table
     *            : Code de la table 'DA_ENTETE' pour l'entete du panier sinon 'DA_LIGNE' pour les lignes du panier
     * @param int $id_panier
     *            : Id du panier concerné
     * @param int $id_ligne
     *            : Type de ligne 0 pour l'entête sinon le numéro de la ligne
     * @param booleen $initProjetAndLieu
     *            : Booleen indiquant si le code projet et le code lieu associé au client CC N°56 doivent être initialisés
     * @param boolean $duplicationOk
     *            : Boolean indiquant autorise à l'utilisation des champs NONDISP à 1 // Dossier 25860
     * @return boolean
     */
    public static function InsertListeCsIntoPanier(& $PileCreationCS, $code_table, & $id_panier, $id_ligne, $initProjetAndLieu = true, $duplicationOk = true, $typeCharg = null)
    { // Dossier 25860
                      
         // On insère chacun des CS
        if ($id_ligne != 0)
            $resultLigne = & SqlPanier::rqGetAllLignePanier($id_panier, $id_ligne)->Trouve1();
        else
            $resultLigne = null;
        $panierObject = new Panier(); 
        // $panierObject->setTypeChargement($typeCharg);
        
        if ($listeCS = $panierObject->getListeCsArray($code_table, $id_panier, $resultLigne))
            foreach ($listeCS as & $cs_attributs) {
                // On vérifie si ces lignes de CS existent déjà ou pas, si elles n'existent pas alors on les créé
                
                if ($duplicationOk || ! BoolSql($cs_attributs['NONDUPLI'])) { // Dossier 25860 Si autorise pour mode duplication ou pas interdit en duplication
                    $listeCSdejaCrees = & SqlCs::rqRechCsFixe($id_panier, $id_ligne, $cs_attributs['NUM_FIX'])->Trouve1();
                    
                    if (is_array($listeCSdejaCrees) && count($listeCSdejaCrees) > 0)
                        continue;
                    
                    // On créé un objet CS
                    $CS = $cs_attributs['class'];
                    $num_fix = $CS->getNUM_FIX();
                    $cs_valeur = $CS->getVALEUR();
                    $PileCreationCS->AddRequeteSql(SqlCs::rqCreCsFixe($id_panier, $num_fix, $code_table, $id_ligne, $cs_valeur));
                }
            }
        
        // Pour le client N°56, on met à jour les 2 champs SI (LIEU) et SCA (PROJET) intialisés à partir des CS du CODECOMP
        if (CLT_CHAMPC == $_SESSION['Session_NumClient'] && $initProjetAndLieu) {
            
            $info_ligne = & SqlPanier::rqGetAllLignePanier($id_panier, $id_ligne)->Trouve1();
            
            // La donnée sera enregistrée dans un champ classique SI_CODE au niveau de la ligne de DA
            $result = & SqlCs::rqSelectValueCSforInit('CODECOMP', Param::getNumCSLieuCODECOMP(), $info_ligne['CDC_CODE'])->Trouve1();
            
            if (array_key_exists('REGLES_INIT_IMPUT', $_SESSION))
                $reglesInitImput = unserializeSecure($_SESSION['REGLES_INIT_IMPUT']);
            else
                $reglesInitImput = null;
            
            if (! is_object($reglesInitImput)) {
                // Alors on le crée
                $reglesInitImput = new Imputation();
                // $reglesInitImput->getReglesInitImput();
                // Et on le serialise afin de pouvoir l'appeller par la suite
                $_SESSION['REGLES_INIT_IMPUT'] = serializeSecure($reglesInitImput);
            }
            
            // Si la valeur du SI est vide alors on l'intialise selon les règles de priorités définies dans Haplus
            if ('' == trim($result['VALEUR']))
                $result['VALEUR'] = $reglesInitImput->getInitImput('SI', $info_ligne['COD_ART'], $info_ligne['COD_SFAM'], $id_panier);
            
            $PileCreationCS->AddRequeteSql(SqlPanier::MajPanierImput($_SESSION['id_user'], $id_panier, $id_ligne, 'SI_CODE', $result['VALEUR']));
            
            // Alors la donnée sera enregistrée dans un champ classique SCA_CODE au niveau de la ligne de DA
            // Bug decouverte le 28/09/15 EDP ajout du paramètre manquant SCA_CODE
            // Et en plus confirme par le client via dossier 24475
            $result2 = & SqlCs::rqSelectValueCSforInit('CODECOMP', Param::getNumCSProjetCODECOMP(), $info_ligne['CDC_CODE'])->Trouve1();
            
            // On réalise la mise à jour seulement si la valeur n'est pas vide
            if ('' == trim($result2['VALEUR']))
                $result2['VALEUR'] = $reglesInitImput->getInitImput('SCA', $info_ligne['COD_ART'], $info_ligne['COD_SFAM'], $id_panier);
            
            $PileCreationCS->AddRequeteSql(SqlPanier::MajPanierImput($_SESSION['id_user'], $id_panier, $id_ligne, 'SCA_CODE', $result2['VALEUR']));
        }
        
        if($_SESSION['Session_NumClient'] == '130')
        {
            if($CDC_CODE_NEW = cs::getValueCSSectimp($_SESSION['Session_SocUsr'], $info_ligne['SI_CODE']))
            {
                $PileCreationCS->AddRequeteSql(SqlPanier::MajPanierImput($_SESSION['id_user'], $id_panier, $id_ligne, 'CDC_CODE', $CDC_CODE_NEW));
            }
        }
    }

    /**
     * Foction permettant de contrôle un ensemble de champ supplémentaire associé à une table : $cod_tab.
     * Les champs ainsi que leur valeur associées sont dans le tableau $post (généralement issu d'un formulaire).
     * Les champs supplémentaires d'une ligne sont identifiés dans le tableau $post grâce aux clés de la forme : CS_{$id_post}_
     * Les champs supplémentaires sont enregistrés dans la base Oxaproc avec $id_ligne comme numéro de ligne panier.
     *
     * @param string $cod_tab
     *            : Code de la table de référence dont sont issus les champs supplémentaires
     * @param array $post
     *            : Tableau contenant les champs supplémentaires issus d'un formulaire. Chaque champ supplémentaire porte un nom du type CS_{$id_post}_
     * @param int $id_post
     *            : Identifiant permettant de récupérer dans $post les champs de la ligne panier concernée
     * @param int $id_ligne
     *            : Numéro identifiant de la ligne panier dans la base de données Oxaproc
     * @param boolean $update_cs
     *            : Booleen indiquant si le CS sera mis à jour
     * @param boolean $controle_obligatoire
     *            : Booleen indiquant si le contrôle obligatoire du CS sera effectué
     * @param boolean $controle_validite
     *            : Booleen indiquant si le contrôle d'existence de la valeur du CS sera effectuée
     * @param boolean $controle_imput_cc
     *            : Booleen indiquant si le contrôle des CS utilisé comme axe d'imputation pour le client N°56 (CC) sera effectué
     * @return boolean : retourne vrai si la mise à jour des valeurs des champs supplémentaires a réussi. Sinon false
     */
    public static function &getInfoCSCtrlCsUpdateCS($cod_tab, & $post, $id_post, $id_ligne, $update_cs = true, $controle_obligatoire = true, $controle_validite = true, $controle_imput_cc = false)
    {
        global $connecteur;
        
        $chaine_liste_numfix_cs = $post['Liste_num_fix_cs'];
        $tableau_numfix_cs = explode('|', $chaine_liste_numfix_cs);
        $result = true;
        $array_sql = array();
        
        // Pour le client N°56 (CC) on exclut du contrôle les CS qui servent à stocker des axes d'imputations
        if (CLT_CHAMPC == $_SESSION['Session_NumClient']) {
            $liste_cs_imput_ccTmp = Param::getListeNumCSDALigneForImputCC(); // On constitue la liste des numéros de CS déddiés aux imputations des lignes
            $liste_cs_imput_cc = explode(',', $liste_cs_imput_ccTmp);
        }
        
        // Si des CS sont présents
        if (is_array($tableau_numfix_cs)) {
            // Pour chaque champ supplémentaire présent on effectue un contrôle en fonction de ses attributs
            foreach ($tableau_numfix_cs as & $num_fix) {
                // Pour le client N°56 (CC) Si le $controle_imput_cc n'est pas à vrai on exclut du contrôle les CS qui servent à stocker des axes d'imputations sur les lignes de DA
                if ($controle_imput_cc || CLT_CHAMPC != $_SESSION['Session_NumClient'] || 'DA_LIGNE' != $cod_tab || ('DA_LIGNE' == $cod_tab && ! in_array($num_fix, $liste_cs_imput_cc))) {
                    if (is_numeric($num_fix)) { // Pour chaque Numéro de champ supplémentaire
                        $prefix_liste_attributs = "CS_{$id_post}_{$num_fix}_";
                        $data_cs = & SqlCs::rqGetInfoCS($cod_tab, $num_fix)->Trouve1();
                        $data_cs['VALEUR'] = getValueCS($prefix_liste_attributs . 'VALEUR');
                        
                        if ('L' == $data_cs['FORMAT'])
                            $data_cs['VALEUR'] = BoolSql($data_cs['VALEUR']);
                        
                        $CS = new CS($data_cs); // On crée un objet CS
                        $CS->setCOD_TAB($cod_tab); // On définit le COD_TAB des CS : Ici il s'agit de l'entête du panier
                        $societe = sqlCs::getSocPanierByLigne($id_ligne)->Trouve1()['CODE_STE']??'';
                        
                        $result_ctrl = $CS->ControlValueCS($controle_obligatoire, $controle_validite, $societe); // On appelle la fonction de contrôle sur le champ
                                                       // Si la valeur du champ n'est pas conforme Ex : valeur inexistante ou valeur non renseignée alors que champ obligatoire etc....
                        if (0 == $result_ctrl[0]) {
                            //$nom_champ = getValue($prefix_liste_attributs . 'NOM');
                            
                            Affichage::messageJS(CS::alertUser($result_ctrl[1], $CS->getNOM())); // Message d'avertissement pour l'utilisateur
                            Affichage::innerHTML($prefix_liste_attributs . 'LIBELLE_VALUE', '');
                            $connecteur->disconnect();
                            exit(); // On arrete l'execution du script
                        }
                        
                        // Construction du tableau utilisé pour l'enregistrement des données dans la base
                        $array_sql[] = array(
                            'NUM_FIX' => $CS->getNUM_FIX(),
                            'VALEUR' => $CS->getVALEUR(),
                            'ID_LIGNE' => $id_ligne,
                            'COD_TAB' => $CS->getCOD_TAB()
                        );
                    }
                }
            } // fin foreach
              // Tous les contrôles sont OK donc on enregistre les valeur des CS de l'entête du panier
            if ($update_cs) {
                $result = CS::UpdateCS($array_sql);
            }
        }
        
        return $result;
    }

    /**
     * Fonction permettant de créer les lignes de CS de l'entete et des lignes manquantes pour un panier donné de l'utilisateur connecté
     *
     * @param int $id_panier
     *            : Id du panier à traiter
     * @param booleen $initProjetAndLieu
     *            : Booleen indiquant si le code projet et le code lieu associé au client CC N°56 doivent être initialisés
     */
    public static function CreateLigneCSLeft(& $id_panier, $initProjetAndLieu = true, $SqlListe)
    { // NE PAS METTRE de reference sur SQLLISTE SINON erreur commit
        $localSqlListe = false;
        
        if (is_null($SqlListe)) {
            $SqlListe = new PileSql(DB_OXAPROCDB);
            $localSqlListe = true;
        }
        Panier::InsertListeCsIntoPanier($SqlListe, 'DA_ENTET', $id_panier, 0, $initProjetAndLieu);
        if ($listeLignePanier = SqlPanier::rqGetAllLignePanier($id_panier)->TrouveTous())
            // Insertion des lignes de CS de lignes manquantes
            foreach ($listeLignePanier as & $lignePanier)
                Panier::InsertListeCsIntoPanier($SqlListe, 'DA_LIGNE', $id_panier, $lignePanier['id_lig'], $initProjetAndLieu);
        
        if ($localSqlListe) {
            $SqlListe->Commit();
            $SqlListe = null;
        }
    }

    

    /**
     * SPEC 4241 Caractéristiques complémentaires : Fonction permettant de récupérer la liste des CC 
     * Les résultats sont enresgitrés dans un tableau qui peut être transmis à une XSL.
     */
    public function initListeCC($code_ssfam, $code_fam, $code_art, $code_doc, $tag_xsl, $popup_ctrl = 'gestion_cs_panier.php', $form)
    {
        $this->liste_cc = null;        
        $liste_numfix = '';

        $listeCC = CaracteristiquesCompl::getListeCCInit($code_ssfam, $code_fam, $code_art);
        
        $panierEntete = new PanierEntete();        
        $panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);

        if ($r = SqlPanier::rqGetAllDevise()->TrouveTous()){
            foreach ($r as & $devise)
            $listeDevises[] = array(
                '!code' => $devise['CODE_DEVI'],
                '!texte' => $devise['LIBELLE']
            );
        }

        $i = 0;
        if (is_array($listeCC)) {
            foreach ($listeCC as & $ligne)
            {
                $ligne['NUM_FIX'] = $ligne['CC_ID'];
                $ligne['TYPE'] = $ligne['CC_TYPE'];
                $ligne['CC_IS_TITLE'] = BoolSql($ligne['CC_IS_TITLE']);
                $ligne['OBLIG'] = BoolSql($ligne['CC_REQUIRED']) && ($code_doc == 'BR' || ($code_doc != 'BR' && !BoolSql($ligne['CC_UPD_ONLY_RECEIPT'])));                
                $ligne['NONDISPO'] = $code_doc == 'BR' ? BoolSql($ligne['CC_INVIS_RECEIPT']) : 0; // Si on est sur un BR et que le CC_INVIS_RECEIPT = true, alors le champs n'est pas visible pour l'utilisateur
                $ligne['MODAPVAL'] = BoolSql($ligne['MODAPVAL']);                
                $ligne['NONMODIF'] = ($code_doc != 'BR' && BoolSql($ligne['CC_UPD_ONLY_RECEIPT']) || BoolSql($ligne['CC_CALC'])) ? 1 : 0; // Si on est pas sur un BR et que le CC_UPD_ONLY_RECEIPT = true OU si le CC est calculé (CC_CALC = true), alors le champs n'est pas modifiable

                $ligne['CONTROLE'] = BoolSql($ligne['CONTROLE']);
                $ligne['CTRL_STD'] = BoolSql($ligne['CTRL_STD']);
                $ligne['NEG_AUTO'] = BoolSql($ligne['NEG_AUTO']);

                if ('D' == $ligne['FORMAT']){ // Reformattage de la date pour affichage selon format session
                    if(strstr($ligne['VALEUR'], '/') == false){
                        $ligne['VALEUR'] = convertDateSqlToFr($ligne['VALEUR']);
                    }
                }
                if($ligne['FORMAT'] == 'U' || $ligne['FORMAT'] == 'E'){
                    $ligne['ALP_LONG'] = '3000';
                }
                
                if ($ligne['VALEUR'] != '' && BoolSql($ligne['CONTROLE']) && ! BoolSql($ligne['CTRL_STD']))
                    if ($lib = & SqlCs::rqGetLibCS($ligne['VALEUR'], $ligne['TYPE'], (BoolSql($ligne['TBLSECTO']) ? $panierEntete->getCODE_STE() : ''))->Trouve1())
                        $ligne['libelle_valeur'] = $lib['LIB01DICO'];
                    else
                        $ligne['libelle_valeur'] = '';

                $liste_CC_calc[$ligne['CC_ID']] = [
                    'CC_ID' => $ligne['CC_ID'],
                    'NOM' => $ligne['NOM'],
                    'PD_LONG' => $ligne['PD_LONG'],
                    'CC_UPD_ONLY_RECEIPT' => $ligne['CC_UPD_ONLY_RECEIPT'],
                    'CC_CALC_EXP' => $ligne['CC_CALC_EXP'],
                    'tab_CC_CALC_EXP' => []
                ];
                
                if($ligne['CC_CALC']){
                    $liste_CC_calc[$ligne['CC_ID']]['tab_CC_CALC_EXP'] = preg_split('/(<[^>]*[^\/]>)/i', $ligne['CC_CALC_EXP'], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
                    foreach($liste_CC_calc[$ligne['CC_ID']]['tab_CC_CALC_EXP'] as &$tag){
                        $tag = str_replace(['<', '>'], '', $tag);
                    }
                }       
                
                $j = 0;
                
                $popup_ctrl_onblur = $popup_ctrl;
                
                $pointeur = & $this->liste_cc['ListeCS']['CS'][$i];

                foreach ($ligne as $key => & $value) { // Pour chaque attribut de la CC
                                                       // On enregistre chaque attribut et sa valeur associée
                    // on garde la même nomenclature que pour les CS, afin d'utiliser les mêmes fonctions de validation des zooms
                    $inputValuetest =  'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR';
                    $pointeur['attributs'][$j] = array(
                        '!name' => $key, // Nom du CC
                        '!value' => $value, // Valeur du CC
                        '!cle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_' . $key, // Identifiant du CC
                        '!popup_ctrl' => $popup_ctrl, // Page cible lorsque l'utilisateur appelle un zoom sur un CC
                        '!name_champ_input' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR', // Nom du champ imput pour le CC
                        '!name_champ_libelle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_LIBELLE_VALUE', // Libellé de la valeur du CC
                        '!UserAuthModCSNonMod' => 0,
                    );

                    if($ligne['FORMAT']=='1' && $key == 'FORMAT'){  
                        $pointeur['attributs'][$j]['id_info_sup'] = 'devise_CS_' . $tag_xsl . '_'.$ligne['NUM_FIX'];
                        $pointeur['attributs'][$j]['value_info_sup'] = array(
                            '!id' => 'select_'.$pointeur['attributs'][$j]['id_info_sup'],
                            '!value' => $panierEntete->getCOD_DEV() ?? $_SESSION['DEVISE_BASE'],
                            '!name' => $pointeur['attributs'][$j]['id_info_sup'],
                            'options' => $listeDevises
                        );
                    }     
                    
                    if($ligne['FORMAT']=='D')
                    {
                        $pointeur['attributs'][$j]['!onclick'] = "CL.show(null,document.{$form}.{$inputValuetest},null,-80);";
                    }   
                    
                    if($ligne['FORMAT']=='U')
                    {
                        // $pointeur['attributs'][$j]['!onclick'] = "openUrl($key)";
                        $pointeur['attributs'][$j]['!onclick'] = 'openUrl("CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR")';
                    }   
                    
                    if($ligne['FORMAT']=='E')
                    {
                        // $pointeur['attributs'][$j]['!onclick'] = "openMail($key)";
                        $pointeur['attributs'][$j]['!onclick'] = 'openMail("CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR")';
                    }
                    
                    if (0 == $j) // Construction de la liste globale de référence des identifiant des CC présents
                        $liste_numfix .= $ligne['CC_TABLE_ID'].'__'.$ligne['CC_RECORD_ID'].'__'.$ligne['NUM_FIX'].'|';
                    
                    $j ++;
                }
                
                // On ajoute les actions associées aux champs
                if (BoolSql($ligne['CONTROLE'])) {
                    // Ajout de l'action contrôlant la saisie d'un champ soumis à un contrôle
                    $zoom = (BoolSql($ligne['CTRL_STD']) ? 'zoom_CS_TABLE_STD' : 'zoom_TS_DON');
                    $type = htmlentities(urlencode($ligne['TYPE']));
                    $onblur = "if(this.value!=''){Traite('{$popup_ctrl_onblur}?action=SelectValueCS&champ={$inputValuetest}&controle=$zoom&type=$type',this.form['CS_{$tag_xsl}_{$ligne['NUM_FIX']}_VALEUR']);}";
                    $onblur .= " else{SetInnerHTML('CS_{$tag_xsl}_{$ligne['NUM_FIX']}_LIBELLE_VALUE','');} ";
                    
                    // Ajout de l'action de zoom sur la liste des valeurs possible d'un CC
                    $onclick = "Traite(\"{$popup_ctrl}?action={$zoom}&TYPE={$type}&champ={$inputValuetest}&LIBELLE=" . htmlentities(urlencode($ligne['NOM'])) . "&form={$form}&controle={$zoom}&type={$type}'\",document.{$form}.{$inputValuetest});";
                    
                    $pointeur['actions'] = array(
                        '!onblur' => $onblur,
                        '!onclick' => $onclick
                    );
                }
                
                $i ++;
            }
        }
        
        // TODO SPEC 4241 : onclick pour le bouton ajouter une CC libre (onclickCClibre)
        $liste_numfixTmp = mb_substr($liste_numfix, 0, mb_strlen($liste_numfix) - 1);
        $this->liste_cc['ListeCS']['Listing'] = array(
            '!value' => $liste_numfixTmp,
            '!type_liste' => 'CC',
            // '!onclickCClibre' => 'console.log("test");'
        );
        $this->liste_cc['liste_CC_calc'] = $liste_CC_calc;
    }

    

    /**
     * SPEC 4241 Caractéristiques complémentaires : Fonction permettant de récupérer la liste des CC 
     * Les résultats sont enregistrés dans un tableau qui peut être transmis à une XSL.
     */
    public function getListeCCDoc($code_doc, $doc_num, $id_line_doc = '', $id_user_panier=0,  $doc_amd=null, $tag_xsl, $popup_ctrl = 'gestion_cs_panier.php', $form)
    {
        $this->liste_cc = null;        
        $liste_numfix = '';

        $listeCC = CaracteristiquesCompl::getListeCCDoc($code_doc, $doc_num, $id_line_doc, $id_user_panier, $doc_amd);
        
        $panierEntete = new PanierEntete();        
        $panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);

        if ($r = SqlPanier::rqGetAllDevise()->TrouveTous()){
            foreach ($r as & $devise)
            $listeDevises[] = array(
                '!code' => $devise['CODE_DEVI'],
                '!texte' => $devise['LIBELLE']
            );
        }

        $i = 0;
        if (is_array($listeCC)) {
            foreach ($listeCC as $key => & $ligne)
            {
                $ligne['NUM_FIX'] = $ligne['CC_ID'];
                $ligne['TYPE'] = $ligne['CC_TYPE'];
                $ligne['CC_IS_TITLE'] = BoolSql($ligne['CC_IS_TITLE']);
                $ligne['OBLIG'] = BoolSql($ligne['CC_REQUIRED']) && ($code_doc == 'BRT' || ($code_doc != 'BRT' && !BoolSql($ligne['CC_UPD_ONLY_RECEIPT'])));               
                $ligne['NONDISPO'] = $code_doc == 'BR' || $code_doc == 'BRT' ? BoolSql($ligne['CC_INVIS_RECEIPT']) : 0; // Si on est sur un BR et que le CC_INVIS_RECEIPT = true, alors le champs n'est pas visible pour l'utilisateur
                $ligne['MODAPVAL'] = BoolSql($ligne['MODAPVAL']);  
                $ligne['NONMODIF'] = ($code_doc != 'BR' && $code_doc != 'BRT' && BoolSql($ligne['CC_UPD_ONLY_RECEIPT']) || BoolSql($ligne['CC_CALC'])) ? 1 : 0; // Si on est pas sur un BR et que le CC_UPD_ONLY_RECEIPT = true OU si le CC est calculé (CC_CALC = true), alors le champs n'est pas modifiable

                $ligne['CONTROLE'] = BoolSql($ligne['CONTROLE']);
                $ligne['CTRL_STD'] = BoolSql($ligne['CTRL_STD']);
                $ligne['NEG_AUTO'] = BoolSql($ligne['NEG_AUTO']);

                if ($ligne['FORMAT'] == 'D'){ // Reformattage de la date pour affichage selon format session
                    if(strstr($ligne['VALEUR'], '/') == false){
                        $ligne['VALEUR'] = convertDateSqlToFr($ligne['VALEUR']);
                    }
                }if ($ligne['FORMAT'] == 'H'){ // Reformattage de l'heure en HH:MM:SS
                    if(strstr($ligne['VALEUR'], ':') == false && $ligne['VALEUR'] != ''){
                        $ligne['VALEUR'] = convertHeureSqlToCC($ligne['VALEUR']);
                    }
                }
                if($ligne['FORMAT'] == 'U' || $ligne['FORMAT'] == 'E'){
                    $ligne['ALP_LONG'] = '3000';
                }
                
                if ($ligne['VALEUR'] != '' && BoolSql($ligne['CONTROLE']) && ! BoolSql($ligne['CTRL_STD']))
                    if ($lib = & SqlCs::rqGetLibCS($ligne['VALEUR'], $ligne['TYPE'], (BoolSql($ligne['TBLSECTO']) ? $panierEntete->getCODE_STE() : ''))->Trouve1())
                        $ligne['libelle_valeur'] = $lib['LIB01DICO'];
                    else
                        $ligne['libelle_valeur'] = '';

                $liste_CC_calc[$ligne['CC_ID']] = [
                    'index' => $key,
                    'CC_ID' => $ligne['CC_ID'],
                    'NOM' => $ligne['NOM'],
                    'PE_LONG' => $ligne['PE_LONG'],
                    'PD_LONG' => $ligne['PD_LONG'],
                    'CC_CALC_EXP' => $ligne['CC_CALC_EXP'],
                    'tab_CC_CALC_EXP' => [],
                ];
                
                if($ligne['CC_CALC']){
                    $liste_CC_calc[$ligne['CC_ID']]['tab_CC_CALC_EXP'] = preg_split('/(<[^>]*[^\/]>)/i', $ligne['CC_CALC_EXP'], -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
                    foreach($liste_CC_calc[$ligne['CC_ID']]['tab_CC_CALC_EXP'] as &$tag){
                        $tag = str_replace(['<', '>'], '', $tag);
                    }
                }       
                
                $j = 0;
                
                
                $popup_ctrl_onblur = $popup_ctrl;
                
                $pointeur = & $this->liste_cc['ListeCS']['CS'][$i];

                foreach ($ligne as $key => & $value) { // Pour chaque attribut de la CC
                                                       // On enregistre chaque attribut et sa valeur associée
                    // on garde la même nomenclature que pour les CS, afin d'utiliser les mêmes fonctions de validation des zooms
                    $inputValuetest =  'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR';
                    $pointeur['attributs'][$j] = array(
                        '!name' => $key, // Nom du CC
                        '!value' => $value, // Valeur du CC
                        '!cle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_' . $key, // Identifiant du CC
                        '!popup_ctrl' => $popup_ctrl, // Page cible lorsque l'utilisateur appelle un zoom sur un CC
                        '!name_champ_input' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_VALEUR', // Nom du champ imput pour le CC
                        '!name_champ_libelle' => 'CS_' . $tag_xsl . '_' . $ligne['NUM_FIX'] . '_LIBELLE_VALUE', // Libellé de la valeur du CC
                        '!UserAuthModCSNonMod' => 0,
                    );

                    if($ligne['FORMAT']=='1' && $key == 'FORMAT'){  
                        $pointeur['attributs'][$j]['id_info_sup'] = 'devise_CS_' . $tag_xsl . '_'.$ligne['NUM_FIX'];
                        $pointeur['attributs'][$j]['value_info_sup'] = array(
                            '!id' => 'select_'.$pointeur['attributs'][$j]['id_info_sup'],
                            '!value' => $panierEntete->getCOD_DEV() ?? $_SESSION['DEVISE_BASE'],
                            '!name' => $pointeur['attributs'][$j]['id_info_sup'],
                            'options' => $listeDevises
                        );
                    }     
                    
                    if($ligne['FORMAT']=='D')
                    {
                        $pointeur['attributs'][$j]['!onclick'] = "CL.show(null,document.{$form}.{$inputValuetest},null,-80);";
                    }
                    
                    if (0 == $j) // Construction de la liste globale de référence des identifiant des CC présents
                        $liste_numfix .= $ligne['CC_TABLE_ID'].'__'.$ligne['CC_RECORD_ID'].'__'.$ligne['NUM_FIX'].'|';
                    
                    $j ++;
                }
                
                // On ajoute les actions associées aux champs
                if (BoolSql($ligne['CONTROLE'])) {
                    // Ajout de l'action contrôlant la saisie d'un champ soumis à un contrôle
                    $zoom = (BoolSql($ligne['CTRL_STD']) ? 'zoom_CS_TABLE_STD' : 'zoom_TS_DON');
                    $type = htmlentities(urlencode($ligne['TYPE']));
                    $onblur = "if(this.value!=''){Traite('{$popup_ctrl_onblur}?action=SelectValueCS&champ={$inputValuetest}&controle=$zoom&type=$type',this.form['CS_{$tag_xsl}_{$ligne['NUM_FIX']}_VALEUR']);}";
                    $onblur .= " else{SetInnerHTML('CS_{$tag_xsl}_{$ligne['NUM_FIX']}_LIBELLE_VALUE','');} ";
                    
                    // Ajout de l'action de zoom sur la liste des valeurs possible d'un CC
                    $onclick = "Traite(\"{$popup_ctrl}?action={$zoom}&TYPE={$type}&champ={$inputValuetest}&LIBELLE=" . htmlentities(urlencode($ligne['NOM'])) . "&form={$form}&controle={$zoom}&type={$type}'\",document.{$form}.{$inputValuetest});";
                    
                    $pointeur['actions'] = array(
                        '!onblur' => $onblur,
                        '!onclick' => $onclick
                    );
                }
                
                $i ++;
            }
        }
        
        $liste_numfixTmp = mb_substr($liste_numfix, 0, mb_strlen($liste_numfix) - 1);
        $this->liste_cc['ListeCS']['Listing'] = array(
            '!value' => $liste_numfixTmp,
            '!type_liste' => 'CC'
        );
        $this->liste_cc['liste_CC_calc'] = $liste_CC_calc;
    }

    /**
     * Fonction analysant le retour de soumission du panier.
     * La fonction retourne vrai si la soumission finale est possible et faux si au moins une erreur est détectée
     *
     * @param array $flux_result
     *            : Résultat de la soumission retourné par le wsdl
     * @return boolean
     */
    public static function ControleResultSoumissionPanier(& $flux_result)
    {
        // Par défaut la soumission finale est déclarée possible
        $soumission_finale_possible = true;
        
        if (is_array($flux_result)) {
            
            // Détection de la présence de problème bloquant sur les DA
            if (array_key_exists('DA', $flux_result) && array_key_exists('StatutDocument', $flux_result['DA']))
                // Si présence d'une erreur pour la DA alors on bloque la soumission
                if (0 == $flux_result['DA']['StatutDocument'])
                    return false;
            
            // Détection de la présence de problème bloquant sur les DS
            if (array_key_exists('Stock', $flux_result) && array_key_exists('StatutDocument', $flux_result['Stock']))
                // Si présence d'une erreur pour la DA alors on bloque la soumission
                if (0 == $flux_result['Stock']['StatutDocument'])
                    return false;
            
            // Détection de la présence de problème bloquant sur les CDE
            if (array_key_exists('ListCdes', $flux_result))
                if (array_key_exists('Cde', $flux_result['ListCdes']))
                    // Dans le cas ou plusieurs CDE vont être générées
                    if (array_key_exists(0, $flux_result['ListCdes']['Cde']))
                        foreach ($flux_result['ListCdes']['Cde'] as $key => & $value) {
                            if (array_key_exists('StatutDocument', $value))
                                // Si présence d'une erreur pour la DA alors on bloque la soumission
                                if (0 == $flux_result['ListCdes']['Cde'][$key]['StatutDocument'])
                                    return false;
                        }
                    // Dans le cas où une seule CDE va être générée
                    else if (array_key_exists('StatutDocument', $flux_result['ListCdes']['Cde']))
                        if (0 == $flux_result['ListCdes']['Cde']['StatutDocument'])
                            return false;
        }
        
        return $soumission_finale_possible;
    }

    /**
     * Fonction retournant lenombre de ligne dans le panier dont la quantité saisie est supérieur à 0
     * 
     * @param int $id_user
     * @param int $id_panier
     * @return boolean
     */
    public static function NbLigneQtePositivePanier(& $id_user, & $id_panier)
    {
        $result = SqlPanier::rqNbligneRecapPanier($id_user, $id_panier)->Trouve1();
        return $result['result'];
    }

    /**
     * Fonction permettant de déterminer si lors d'une duplication ou d'une modification
     * on doit afficher la popup d'association des clauses et pièces jointes aux fournisseurs
     *
     * @param string $type_doc
     *            : Type de document concerné DA ou CDE
     * @param int $no_doc
     *            : Numéro du document concerné DA ou CDE
     */
    public static function IsSelectClauseAndPjToFRS(& $type_doc, & $no_doc)
    {
        // En fonction du type de document
        switch ($type_doc) {
            case TypeSuivi::DA: // Pour les DA
                $liste_pj = SqlDa::rqGetListePJDA($no_doc)->TrouveTous();
                $liste_clause = SqlDa::rqGetListeClauseDA($no_doc)->TrouveTous();
                break;
            case TypeSuivi::CDE: // Pour les CDE
                $liste_pj = SqlCde::rqGetListePJCDE($no_doc)->TrouveTous();
                $liste_clause = SqlCde::rqGetListeClauseCDE($no_doc)->TrouveTous();
                break;
        }
        
        if (is_array($liste_pj))
            $nb_pj = count($liste_pj);
        else
            $nb_pj = 0;
        
        if (is_array($liste_clause))
            $nb_clause = count($liste_clause);
        else
            $nb_clause = 0;
        
        // On affiche la popup seulement si le nombre de fournisseur est supérieur à 1 et qu'il existe au moins une PJ et/ou une clause
        return (($nb_pj > 0 || $nb_clause > 0));
    }

    /**
     * Fonction permettant de déterminer si lors d'une duplication ou d'une modification
     * on doit afficher la popup d'association des clauses et pièces jointes aux fournisseurs
     *
     * @param string $type_doc
     *            : Type de document concerné DA ou CDE
     * @param int $no_doc
     *            : Numéro du document concerné DA ou CDE
     *            
     *            
     *            /!\ ATTENTION : Le premier paramètre NE DOIT PAS être passé par référence
     *            
     */
    public static function IsClauseAndPjByDoc($type_doc, & $no_doc)
    {
        // En fonction du type de document
        switch ($type_doc) {
            case TypeSuivi::DA: // Pour les DA
                $liste_pj =  SqlDa::rqGetListePJDA($no_doc)->TrouveTous();
                $liste_clause =  SqlDa::rqGetListeClauseDA($no_doc)->TrouveTous();
                break;
            case TypeSuivi::CDE: // Pour les CDE
                $liste_pj =  SqlCde::rqGetListePJCDE($no_doc)->TrouveTous();
                $liste_clause =  SqlCde::rqGetListeClauseCDE($no_doc)->TrouveTous();
                break;
        }
        
        if (is_array($liste_pj))
            $nb_pj = count($liste_pj);
        else
            $nb_pj = 0;
        
        if (is_array($liste_clause))
            $nb_clause = count($liste_clause);
        else
            $nb_clause = 0;
        
        // On affiche la popup seulement s'l existe au moins une PJ et/ou une clause
        return ($nb_pj > 0 || $nb_clause > 0);
    }

    /**
     * Fonction réalisant l'insertion dans le panier donné des PJ et clauses présentes sélectionnée par l'utilisateur et référencées dans $array
     * ou bien de toutes les PJ et Clauses présentes dans le $no_doc donné
     *
     * @param string $typ_doc
     *            : Type de document DA ou CDE en cours de duplication/modification
     * @param int $no_doc
     *            : Numéro du document en question
     * @param int $id_panier
     *            : Identifiant du panier cible
     * @param int $id_user
     *            : Identifiant de l'utilisateur
     * @param array $array
     *            : Tableau contenant les fournisseurs retenus pour chaque PJ/CLAUSES
     */
    public static function InsertPJandClauseSelected($PileSql, & $critere, $mode, $typ_doc, $no_doc, $id_panier, $id_user, $array = array())
    {
        if (is_null($PileSql)) {
            $PileSql = new PileSql(DB_OXAPROCDB);
            $commitInterne = true;
        } else
            $commitInterne = false;
        
        $ajout_pj = false;
        $ajout_clause = false;
        
        $listeFrs_pj = array();
        $listeFrs_clause = array();
        
        // Dans le cas de l'insertion des PJ et clauses dans le panier suite à la sélection de l'utilisateur
        if (is_array($array) and count($array) > 0) {
            // Pour chaque PJ ou clause sélectionnée
            foreach ($array as $selection => & $value) {
                if (0 === strpos($selection, 'PJ_FRS_')) { // Dans le cas des PJ
                    $no_pj = str_replace('PJ_FRS_', '', $selection); // On extrait le numéro de la pièce jointe
                    $cod_frs = $value;
                    
                    if ($critere['COD_FOURN'] == $cod_frs) {
                        // On récupère le type d'achat du fournisseur
                        $info_frs = SqlPanier::GetTypeAchatFrs($critere['COD_FOURN']);
                        $type_achat_frs = $info_frs[0]['TYP_ACH'];
                        
                        // On ajoute le fournisseur dans le tableau de référence
                        if (! in_array($cod_frs, $listeFrs_pj))
                            array_push($listeFrs_pj, $cod_frs);
                        
                        switch ($typ_doc) { // Récupération des informations relatives à la PJ selon le type de document et le numéro de PJ
                            case TypeSuivi::DA:
                                $info_pj = & SqlDa::rqGetListePJDA($no_doc, $no_pj)->Trouve1();
                                break;
                            
                            case TypeSuivi::CDE:
                                $info_pj = & SqlCde::rqGetListePJCDE($no_doc, $no_pj)->Trouve1();
                                break;
                        }
                        
                        if (is_array($info_pj)) {
                            // On initialise le type d'achat avec la valeur du type d'achat du fournisseur
                            // seulement si le type d'achat du fournisseur est le même que le type d'achat de la PJ et qu'il s'agit d'une commande
                            // pour les DA le type d'achat est toujours à blanc.
                            if ($type_achat_frs == $info_pj['TYP_ACH'] && TypeSuivi::CDE == $typ_doc)
                                $type_achat = $type_achat_frs;
                            else
                                $type_achat = '';
                            
                            if(!BoolSql($info_pj['ISSU_TAC']))
                            {
                                $type_achat = '';
                            }
                            
                            // La il faut recopier la piece jointe depuis $_SESSION['chemin_pj']
                            // Insertion des informations relative à la PJ
                            
                            if(BoolSql($info_pj['LIEN_FICHIER'])) {
                                $file_dir = $info_pj['NOM_FIC'];
                                $file_dir_pdf = $info_pj['FIC_PDF'];
                            } else {
                                $cheminSource = $_SESSION['chemin_pj'] . $info_pj['NOM_FIC'];
                                $extchemin = $id_user . '/' . $id_panier . '/' . date('Ymd', time());
                                
                                $file_dir = $_SESSION['chemin_pj'] . $extchemin;
                                $tmp_dir = '';
                                foreach (explode('/', $file_dir) as $element) {
                                    $tmp_dir .= $element;
                                    if (! is_dir($tmp_dir))
                                        @mkdir($tmp_dir);
                                    
                                    $tmp_dir .= '/';
                                }
                                
                                $tmp_dir = str_replace('/','\\',$tmp_dir);
                                
                                $info_pj['NOM_ORI'] = str_ireplace("\\", '/', $info_pj['NOM_ORI']);
                                $liste = explode('/', $info_pj['NOM_ORI']);
                                
                                $info_pj['NOM_ORI'] = $liste[count($liste) - 1];
                                
                                $pos = strrpos($info_pj['NOM_ORI'], '.');
                                if ($pos === false)
                                    $extFile = '.';
                                else
                                    $extFile = substr($info_pj['NOM_ORI'], $pos);
                                
                                $nomCalculer = date('Ymd', time()) . substr((string) microtime(), 1, 6) . $extFile;
                                if (copy($cheminSource, $tmp_dir . $nomCalculer)) {
                                    $file_dir = $extchemin . '/' . $nomCalculer;
                                    $file_dir_pdf = Wsdl::wsdlConvertPdf('fic_pj', $file_dir); // Spec 3614
                                }
                            }

                            if($file_dir || $file_dir_pdf) {
                                $PileSql->AddRequeteSql(SqlPanier::rqAddPj($id_user, $id_panier, $critere, $info_pj['TITRE'], $info_pj['TYPE_PJ'], $info_pj['NOM_ORI'], $file_dir, $file_dir_pdf, $info_pj['LECTURE'], $info_pj['IMP_PJ'], $info_pj['IMP_TITRE'], ($mode != 'modifDocPourSignature' ? $type_achat : '____'), $info_pj['VERR_MOD'], $info_pj['USE_CGA'], $info_pj['ISSU_RATT'], $info_pj['TABLE_RATT']), BoolSql($info_pj['LIEN_FICHIER']));
                                $ajout_pj = true;
                            }

                        }
                    }
                } elseif (0 === strpos($selection, 'CLAUSE_FRS_')) { // Dans le cas de clauses
                    $no_clause = str_replace('CLAUSE_FRS_', '', $selection); // On extrait le numéro de la clause
                    $cod_frs = $value;
                    
                    if ($cod_frs == $critere['COD_FOURN']) {
                        $info_frs = SqlPanier::GetTypeAchatFrs($critere['COD_FOURN']);
                        $type_achat = $info_frs[0]['TYP_ACH'];
                        
                        if (! in_array($cod_frs, $listeFrs_clause))
                            array_push($listeFrs_clause, $cod_frs);
                        
                        switch ($typ_doc) { // Récupération des informations relatives à la clause selon le type de document et le numéro de clause
                            case TypeSuivi::DA:
                                $info_clause = & SqlDa::rqGetListeClauseDA($no_doc, $no_clause)->Trouve1();
                                break;
                            
                            case TypeSuivi::CDE:
                                $info_clause = & SqlCde::rqGetListeClauseCDE($no_doc, $no_clause)->Trouve1();
                                break;
                        }
                        
                        if (is_array($info_clause)) {
                            if ($type_achat_frs == $info_clause['TYP_ACH'] && TypeSuivi::CDE == $typ_doc)
                                $type_achat = $type_achat_frs;
                            else
                                $type_achat = '';
                            
                            // Insertion des informations relative à la Clause
                            $PileSql->AddRequeteSql(SqlPanier::rqAddClausePanier($id_user, $id_panier, $critere, $info_clause['CONTMEMO'], $type_achat, $info_clause['VERR_MOD'], $info_clause['CLAU_FIX']));
                            $ajout_clause = true;
                        }
                    }
                }
            } // Fin du foreach
        }        // Dans le cas où un seul fournisseur existe et que l'utilisateur n'a pas à faire de choix
        else {
            switch ($typ_doc) { // Récupération des informations relatives au fournisseur unique de la DA ou de la CDE
                case TypeSuivi::DA:
                    $frs = SqlDa::rqListFrsDA($no_doc)->Trouve1();
                    $cod_frs = $frs['CODE'];
                    break;
                
                case TypeSuivi::CDE:
                    $frs = SqlCde::getInfoOnEnteteCDE($no_doc)->Trouve1();
                    $cod_frs = $frs['CODE'];
                    break;
            }
            
            if ($cod_frs == $critere['COD_FOURN']) {
                if (! in_array($cod_frs, $listeFrs_pj))
                    array_push($listeFrs_pj, $cod_frs);
                
                if (! in_array($cod_frs, $listeFrs_clause))
                    array_push($listeFrs_clause, $cod_frs);
                
                // Initialisation du type d'achat issu du fournisseur
                if ('' != trim($cod_frs)) {
                    $info_frs = SqlPanier::GetTypeAchatFrs($critere['COD_FOURN']);
                    $type_achat = $info_frs[0]['TYP_ACH'];
                } else
                    $type_achat = '';
                
                switch ($typ_doc) { // Récupération des PJ et clauses du document
                    case TypeSuivi::DA:
                        $liste_pj = SqlDa::rqGetListePJDA($no_doc)->TrouveTous();
                        $liste_clause = SqlDa::rqGetListeClauseDA($no_doc)->TrouveTous();
                        break;
                    
                    case TypeSuivi::CDE:
                        $liste_pj = SqlCde::rqGetListePJCDE($no_doc)->TrouveTous();
                        $liste_clause = SqlCde::rqGetListeClauseCDE($no_doc)->TrouveTous();
                        break;
                }
                
                // Enregistrement des PJ pour le fournisseur donné
                if (is_array($liste_pj)) {
                    foreach ($liste_pj as & $info_pj) {
                        // On enregistre les pièces jointes :
                        // Pour les CDE uniquement les pièces jointes non hérités
                        // Pour les DA toutes les pièces jointes
                        
                        if ((TypeSuivi::CDE == $typ_doc && ! BoolSql($info_pj['ISSU_TAC'])) || TypeSuivi::DA == $typ_doc) {
                            if(!BoolSql($info_pj['ISSU_TAC']))
                            {
                                $type_achat = '';
                            }
                            
                            $cheminSource = $_SESSION['chemin_pj'] . $info_pj['NOM_FIC'];
                            $extchemin = $id_user . '/' . $id_panier . '/' . date('Ymd', time());
                            
                            $file_dir = $_SESSION['chemin_pj'] . $extchemin;
                            $tmp_dir = '';
                            foreach (explode('/', $file_dir) as $element) {
                                $tmp_dir .= $element;
                                if (! is_dir($tmp_dir))
                                    @mkdir($tmp_dir);
                                
                                $tmp_dir .= '/';
                            }
                            
                            $pos = strrpos($info_pj['NOM_ORI'], '.');
                            if ($pos === false)
                                $extFile = '.';
                            else
                                $extFile = substr($info_pj['NOM_ORI'], $pos);
                            
                            $nomCalculer = date('Ymd', time()) . substr((string) microtime(), 1, 6) . $extFile;
                            
                            if (copy($cheminSource, $tmp_dir . $nomCalculer)) {
                                $file_dir = $extchemin . '/' . $nomCalculer;
                                $file_dir_pdf = Wsdl::wsdlConvertPdf('fic_pj', $file_dir); // Spec 3614
                                
                                $PileSql->AddRequeteSql(SqlPanier::rqAddPj($id_user, $id_panier, $critere, $info_pj['TITRE'], $info_pj['TYPE_PJ'], 
                                $info_pj['NOM_ORI'], $file_dir, $file_dir_pdf, $info_pj['LECTURE'], $info_pj['IMP_PJ'], $info_pj['IMP_TITRE'], 
                                ($mode != 'modifDocPourSignature' ? $type_achat : '____'), $info_pj['VERR_MOD'], $info_pj['USE_CGA'], false, ''));
                                $ajout_pj = true;
                            }
                        }
                    }
                }
                
                if (! $commitInterne)
                    if ($listeDocRatt = DocRattache::getListDocRattByItem($typ_doc, $no_doc)) {
                        // Si le repertoire d'enregistrement n'existe pas alors on le créé
                        if (! is_dir($_SESSION['chemin_pj'] . '/docAttaches'))
                            mkdir($_SESSION['chemin_pj'] . '/docAttaches');
                        
                        foreach ($listeDocRatt as & $docRatt) {
                            $cheminSource = $_SESSION['chemin_pj'] . $docRatt['NOM_FIC'];
                            if(getValue('mode')=='actualiser'){
                                $extchemin = '';
                                $file_dir =$docRatt['NOM_ORI'];
                            }
                            else{
                                $extchemin = 'docAttaches';
                                $file_dir = $extchemin . '/' . $docRatt['NOM_ORI'];
                            }
                            
                            $file_dir = $_SESSION['chemin_pj'] . $extchemin;
                            $tmp_dir = '';
                            foreach (explode('/', $file_dir) as $element) {
                                $tmp_dir .= $element;
                                if (! is_dir($tmp_dir))
                                    @mkdir($tmp_dir);
                                
                                $tmp_dir .= '/';
                            }

                            $pos = strrpos($docRatt['NOM_ORI'], '.');
                            if ($pos === false)
                                $extFile = '.';
                            else
                                $extFile = substr($docRatt['NOM_ORI'], $pos);

                            
                            $nomCalculer = date('Ymd', time()) . substr((string) microtime(), 1, 6) . ($extFile??'');
                            
                            if (copy($cheminSource, $tmp_dir . $docRatt['NOM_ORI'])) {
                                // $file_dir = $extchemin . '/' . $docRatt['NOM_ORI'];
                                $PileSql->AddRequeteSql(SqlDocRattaches::rqInsertDocRattache($id_user, $id_panier, $critere, $docRatt['TITRE'], $docRatt['TYPE_PJ'], $file_dir, "docAttaches\\{$docRatt['NOM_ORI']}", $docRatt['DT_PARUT'], $docRatt['DT_VALID'], $docRatt['AUTEUR'], $docRatt['CENTRE'], $docRatt['COMMENT']), DB_OXAPROCDB);
                            }
                        }
                    }
                
                // Enregistrement des Clauses pour le fournisseur donné
                if (is_array($liste_clause))
                    foreach ($liste_clause as & $info_clause) {
                        // On enregistre les clauses :
                        // Pour les CDE uniquement les clauses non hérités
                        // Pour les DA toutes les clauses
                        if ((TypeSuivi::CDE == $typ_doc && ! BoolSql($info_clause['ISSU_TAC'])) || TypeSuivi::DA == $typ_doc) {
                            // Insertion des informations relatives à la Clause
                            $type_achat = '';
                            $PileSql->AddRequeteSql(SqlPanier::rqAddClausePanier($id_user, $id_panier, $critere, $info_clause['CONTMEMO'], $type_achat, $info_clause['VERR_MOD'], $info_clause['CLAU_FIX']));
                            $ajout_clause = true;
                        }
                    }
            }
        }
        
        // Selon le type de document, on initialise la valeur des flags indiquant si les pj et clauses ont été initialisées ou non
        switch ($typ_doc) {
            case TypeSuivi::DA:
                $flg_add_pj = false;
                $flg_add_clause = false;
                break;
            case TypeSuivi::CDE:
                $flg_add_pj = false;
                $flg_add_clause = false;
                break;
        }
        
        // Si des PJ ou des clauses ont été ajoutées alors on commit les transactions SQL
        if ($ajout_pj || $ajout_clause) {
            if (! $commitInterne || $PileSql->Commit()) { // Si les clause et PJ ont été enregistrées
                echo '';
                if ($ajout_pj)
                    foreach ($listeFrs_pj as & $frs) // Pour chaque fournisseur associé à une PJ on flag les pj comme initialisées pour ce frs
                        if ($frs[0] == $critere['COD_FOURN'])
                            SaveInfoFourPanier($critere, 'flg_add_pj', $flg_add_pj, false);
                
                if ($ajout_clause)
                    foreach ($listeFrs_clause as & $frs) // Pour chaque fournisseur associé à une clause on flag les clauses comme initialisées pour ce frs
                        if ($frs[0] == $critere['COD_FOURN'])
                            SaveInfoFourPanier($critere, 'flg_add_clause', $flg_add_clause, false);
                
                return true;
            } else
                return false;
        } else if ($typ_doc == TypeSuivi::CDE) {
            $info_entete_cde = SqlCde::getInfoOnEnteteCDE($no_doc)->Trouve1();
            $code_frs = $info_entete_cde['CODE'];
            if ($code_frs == $critere['COD_FOURN']) {
                $info_frs = SqlPanier::GetTypeAchatFrs($code_frs);
                $type_achat_frs = $info_frs[0]['TYP_ACH'];
                // DEVISE A FINIR
                $PileSql->AddRequeteSql(SqlPanier::rqInsertTypeAchatFrs($critere, $type_achat_frs), DB_OXASQLDB);
            }
        }
        
        if ($commitInterne)
            return $PileSql->Commit();
        else
            return true;
    }

    /**
     * Fonction construisant un tableau de données nécessaires à la construction de la popup
     * de d'association PJ/Clause aux fournisseurs
     *
     * @param sring $type_doc
     *            : type de document DA ou CDE
     * @param int $no_doc
     *            : Numéro du document
     */
    public static function &buildXmlForSelectClauseAndPjToFRS(& $type_doc, & $no_doc, & $action)
    {
        $array = array(
            'popup_title' => Trad('Associations Fournisseurs')
        );
        
        $array['ListeFrs']['FRS'][] = array(
            '!code' => 'NON_DEFINI',
            '!rs' => trad('Non reprise'),
            '!type' => 'defaut'
        );
        
        switch ($type_doc) {
            case TypeSuivi::DA:
                $listeFrs = SqlDa::rqListFrsDA($no_doc)->TrouveTous();
                $liste_pj = SqlDa::rqGetListePJDA($no_doc)->TrouveTous();
                $liste_clause = SqlDa::rqGetListeClauseDA($no_doc)->TrouveTous();
                break;
            
            case TypeSuivi::CDE:
                $listeFrs = SqlCde::getInfoOnEnteteCDE($no_doc)->Trouve1();
                $liste_pj = SqlCde::rqGetListePJCDE($no_doc)->TrouveTous();
                $liste_clause = SqlCde::rqGetListeClauseCDE($no_doc)->TrouveTous();

                $array['ListeFrs']['FRS'][] = array(
                    '!code' => $listeFrs['CODE'],
                    '!rs' => $listeFrs['RS']
                );
                
                break;
        }

        
        
        if (is_array($liste_pj))
        {
            foreach ($liste_pj as & $pj)
            {
                // TODO VOIR AVEC YVES
                if (! BoolSql($pj['ISSU_TAC']) && ! BoolSql($pj['ISSU_RATT']))
                {
                    $array['ListePJ']['PJ'][] = array(
                        '!code' => $pj['NO_ORDRE'],
                        '!type' => $pj['TYPE_PJ'],
                        '!titre' => $pj['TITRE']
                    );
                }
            }
        } 
        
        if (is_array($listeFrs) && $type_doc == TypeSuivi::DA)
        {
            foreach ($listeFrs as & $frs) 
            {
                if ('' == trim($frs['CODE']))
                {
                    $frs['RS'] = trad('Ligne sans fournisseur');
                }
                $array['ListeFrs']['FRS'][] = array(
                    '!code' => $frs['CODE'],
                    '!rs' => $frs['RS']
                );
            }

        }
         

        if (is_array($liste_clause))
        {
            foreach ($liste_clause as & $clause)
            {
                if (! BoolSql($clause['ISSU_TAC']))
                {
                    $array['ListeCLAUSES']['CLAUSES'][] = array(
                        '!code' => $clause['NM_PARAG'],
                        '!texte' => $clause['CONTMEMO']
                    );
                }
            }
        }



        
        // On encode en UTF8 les caractères provenants de la base de données
        // On définit l'action d'enregistrement des associations réalisées
        // todo correction traitement asynchrone
        $java_script = "if(searchValueInSelect(document.selection_pj_clause,'NON_DEFINI'))";
        $java_script .= "{	if(window.confirm('" . cnv_to_javascript(trad("Une ou plusieurs pièces-jointes / clauses n'ont pas été reprises, celles-ci seront perdues, voulez-vous continuer ?")) . "'))";
        $java_script .= "{ TraiteUrl('suivi_doc.php?action={$action}&etape=enregistrement&typ_doc={$type_doc}&no_doc={$no_doc}' ,document.selection_pj_clause.champ);window.closePopup();  }";
        $java_script .= "} else { TraiteUrl('suivi_doc.php?action={$action}&etape=enregistrement&typ_doc={$type_doc}&no_doc={$no_doc}' ,document.selection_pj_clause.champ);  window.closePopup();}";
        
        $array['actions']['enregistrer']['!onclick'] = $java_script;


        return $array;
    }

    /**
     * Fonction permettant de supprimer une panier donné
     *
     * @param int $id_panier
     * @return boolean : true si la suppression s'est correctement effectuée
     */
    public static function SupprimePanier($id_panier)
    {
        $SqlListe = new PileSql(DB_OXAPROCDB);
        
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelLigne($id_panier));
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelLigneFrs($id_panier));
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelFrs($id_panier));
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelClause($id_panier));
        
        if ($result = SqlPanier::rqGetQueryClausePj($_SESSION['id_user'], $id_panier)->TrouveTous())
            foreach ($result as & $pj)
                if (! BoolSql($pj['ISSU_DOCATT']) && $pj['TYP_ACH'] == '' && !BoolSql($pj['LIEN_FICHIER']))
                    Fichier::Supprimer(Fichier::getExtensionCheminPJ() . $pj['nom_piece_sys']);
        
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelPj($id_panier));
        $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDel($id_panier));

        /*** SPEC 4241 Caractéristiques complémentaires : suppression des CC de la ligne ***/
        $SqlListe->AddRequeteSql(SqlCaracteristiquesCompl::rqSupCCDoc('PAN', $id_panier, null, $_SESSION['id_user']));
        
        $SqlListe->AddRequeteSql(SqlCs::rqSupCsPanier($id_panier));
        $SqlListe->AddRequeteSql(SqlPanier::rqDeleteContactOnBlocFrs($id_panier));
        $SqlListe->AddRequeteSql(SqlDocRattaches::rqDeleteDocsRattaches($_SESSION['id_user'], $id_panier));
        //4328
        $SqlListe->AddRequeteSql(SqlPanier::deleteImputation($id_panier));

        return $SqlListe->Commit();
    }

    public static function revaluationFraisDePort(& $id_user, & $id_panier, $blocFournisseur = null)
    {
        // CHIF_EXEC ou $_SESSION['PANIER_MODE_AVENANT'] == 1
        // FOURNISS.AUTOCC FOURNISS.MTMAXCC
        // ARTFOUR.PXDERCDE
        if (PanierEntete::isPanierModifDocPourSignature())
            /**
             * Mis en compentaire suite Dossier 22155 Sauf pour la version 10.32af cette ligne a été rajouté suite à un skype
             * donc si quelque veut remettre cette ligne opérationnelle VOIR YA car le dossier 22155 va re planter
             * || PanierEntete::isAvenant()
             */
            return null;
        $retour = null;
        
        // Obtenir la liste de tous les fournisseurs potentiel du panier
        $entete = GetPanier($id_panier, $id_user);
        if ($blocFourPanier = GetLigneInfoFournisseur($id_user, $id_panier, 3)) {
            if ($info_frs = SqlFrs::rqGetRecordFournisListe($blocFourPanier)->TrouveTous())
                foreach ($blocFourPanier as & $recFrs) {
                    $codeFour = $recFrs['CODE_FOU'];
                    // Recherche des informations dans le detail fournisseur
                    foreach ($info_frs as & $elementFour) {
                        if ($elementFour['CODE'] == $codeFour) {
                            if (BoolSql($elementFour['RFRACT']))
                                $recFrs['FRAIS_FRANCO'] = 1;
                            else
                                $recFrs['FRAIS_FRANCO'] = 0;
                            
                            if (BoolSql($elementFour['AUTOCC']))
                                $recFrs['CDE_EPROC'] = 1;
                            else
                                $recFrs['CDE_EPROC'] = 0;
                            
                            if (BoolSql($elementFour['FRPOBLIG']))
                                $recFrs['FRAIS_OBL'] = 1;
                            else
                                $recFrs['FRAIS_OBL'] = 0;
                            
                            $recFrs['MNTMINFRA'] = $elementFour['MNTMINFRA'];
                            $recFrs['ARTFRPORT'] = $elementFour['ARTFRPORT'];
                            
                            if ($recFrs['TOTAL'] >= $elementFour['MNTMINFRA'])
                                $recFrs['FRANCOATTEINT'] = '1';
                            else
                                $recFrs['FRANCOATTEINT'] = 'O';
                            
                            $recFrs['_suite'] = $elementFour;
                            break;
                        }
                    }
                }

            // si le panier est de type execution
            // ou s'il s'agit d'un avenant à la commande
            $modeAvenant = PanierEntete::isAvenant();
            
            if ($entete['CHIF_EXEC'] == 'E' || $modeAvenant) {
                
                $panierEntete = new PanierEntete();
                $panierEntete->getEntetePanier($id_panier, $id_user);
                
                $paramSynequa['clause'] = 0;
                
                $requeteIntuition = new RechercheArticleMetier($paramSynequa, '', '', '');
                foreach ($blocFourPanier as & $recFrs) {
                    if (is_null($blocFournisseur) || ($blocFournisseur['COD_FOURN'] == $recFrs['CODE_FOU'] && $blocFournisseur['CRITERE_REGROUP'] == $recFrs['CRITERE_REGROUP'])) {
                        // Le fournisseur est autorise à la commande
                        if (isset($recFrs['CDE_EPROC']) && $recFrs['CDE_EPROC'] == 1) 
                        // et le montant total des lignes du bloc est inferieur au seuil de commande
                        // && $recFrs['TOTAL'] < $recFrs['_suite']['MTMAXCC'] // Suppression vu Avec YA pour la spec 3599 car devient illogique avec les doubles montants
                        {
                            // Si le fournisseur dispose d'un article de frais de port
                            if ($recFrs['_suite']['ARTFRPORT'] > '') {
                                // Si pas assujeti au franco ou franco pas atteint
                                if ($recFrs['FRAIS_FRANCO'] == 0 || $recFrs['FRANCOATTEINT'] == 'O') {
                                    
                                    $retour[]['AJOUT_ARTFRPORT'] = true;
                                    // Ajout de la ligne de frais si pas deja existante pour ce fournisseur
                                    $parametre_rq_intuition['COD_ART'] = $recFrs['_suite']['ARTFRPORT'];

                                    $result_rech_intuition = $requeteIntuition->InfoArt($parametre_rq_intuition, $recFrs['CODE_FOU']);
                                    
                                    if ($result_rech_intuition) 
                                    {
                                        if ($article_trouve = $result_rech_intuition[$requeteIntuition->getIndex_m()]) 
                                        {
                                            // Article de type 3 au sens des articles de frais de port
                                            // On insere la ligne dans le panier que si cet article n'est pas deja present
                                            $CRITERE = array(
                                                'COD_FOURN' => $recFrs['CODE_FOU'],
                                                'CRITERE_REGROUP' => $recFrs['CRITERE_REGROUP']
                                            );
                                            if ($article = SqlPanierLigne::rqGetLigneCodeArticleExiste($id_user, $id_panier, $recFrs['_suite']['ARTFRPORT'], $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->Trouve1()) 
                                            {
                                                $retour[]['CODE_FOU'] = array(
                                                    '!value' => $recFrs['CODE_FOU'],
                                                    '!obl' => $recFrs['FRAIS_OBL'],
                                                    '!regen' => 0,
                                                    '!ok' => 1
                                                );
                                                // Modification du type de ligne, notamment relatif à la duplication de DA qui ne positionne pas le type de ligne
                                                if ($article['type_de_ligne'] != 3) {
                                                    SqlPanierLigne::rqUpdateLigPanierTypeLigne($id_user, $id_panier, 3, $article['id_lig'])->ExecuteSql();
                                                }
                                                if ($article['qte'] == 0) {
                                                    SqlPanierLigne::rqUpdateLigPanierChamp($id_user, $id_panier, $article['id_lig'], 'qte', '1')->ExecuteSql();
                                                }
                                            } else if ($ligneBloc = SqlPanier::rqGetLignePanierBlocFournisseur($_SESSION['id_panier'], $CRITERE)->Trouve1()) {
                                                // ATTENTION IL FAUT INSERER L'ARTICLE SYNEQUA DANS LA DEVISE DU BLOC
                                                
                                                if ($article_trouve['COD_DEV'] != $ligneBloc['COD_DEV']) {
                                                    $article_trouve['PX_ART'] = $article_trouve['PX_ART'] * Param::getTauxConvDevSrcToDevDest($article_trouve['COD_DEV'], $ligneBloc['COD_DEV']);
                                                    $article_trouve['PX_ART_INIT'] = $article_trouve['PX_ART_INIT'] * Param::getTauxConvDevSrcToDevDest($article_trouve['COD_DEV'], $ligneBloc['COD_DEV']);
                                                    
                                                    $article_trouve['COD_DEV'] = $ligneBloc['COD_DEV'];
                                                }
                                                $TmpSqlListe = NULL;
                                                // DOSSIER 35094, l'init des axes d'imputation se fait selon les règles de priorité
                                                insertQteArticlePanier($id_panier, 3, $article_trouve, 1, '', '', '', '', '', '', '', $ligneBloc['CodeCtrLivraison'], $ligneBloc['MODE_TRS'], '', 1, $ligneBloc['DATELIVR'], true, false, $TmpSqlListe);
                                                $retour[]['CODE_FOU'] = array(
                                                    '!value' => $recFrs['CODE_FOU'],
                                                    '!regen' >= 1,
                                                    '!obl' => $recFrs['FRAIS_OBL'],
                                                    '!ok' => 1
                                                );
                                            }
                                        }
                                    } else {
                                        $retour[]['CODE_FOU'] = array(
                                            '!value' => $recFrs['CODE_FOU'],
                                            '!ok' => 0,
                                            '!regen' >= 1,
                                            '!mes' => Trad('Article de frais de port indisponible.') . " ({$recFrs['_suite']['ARTFRPORT']})"
                                        );
                                    }
                                } else {
                                    // Suppression de la ligne de frais de port
                                    if ($modeAvenant)
                                        SqlPanierLigne::rqSupQteLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                                    else
                                        SqlPanierLigne::rqSupLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                                    $retour[]['CODE_FOU'] = array(
                                        '!value' => $recFrs['CODE_FOU'],
                                        '!regen' >= 1,
                                        '!ok' => 1
                                    );
                                }
                            } else {
                                // Suppression de la ligne de frais de port
                                if ($modeAvenant)
                                    SqlPanierLigne::rqSupQteLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                                else
                                    SqlPanierLigne::rqSupLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                                $retour[]['CODE_FOU'] = array(
                                    '!value' => $recFrs['CODE_FOU'],
                                    '!regen' >= 1,
                                    '!ok' => 1
                                );
                            }
                        } else if (array_key_exists('_suite', $recFrs)) {
                            if ($article = SqlPanierLigne::rqGetLigneCodeArticleExiste($id_user, $id_panier, $recFrs['_suite']['ARTFRPORT'], $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->Trouve1()) {
                                // Suppression de la ligne de frais de port
                                if ($modeAvenant)
                                    SqlPanierLigne::rqSupQteLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                                else
                                    SqlPanierLigne::rqSupLigneFrais($id_user, $id_panier, $recFrs['CODE_FOU'], $recFrs['CRITERE_REGROUP'])->ExecuteSql();
                            }
                        }
                    }
                }
            } else {
                // Pas de ligne de frais de port suppression automatique des lignes de types 3
                SqlPanierLigne::rqSupLigneFrais($id_user, $id_panier)->ExecuteSql();
                $retour[]['CODE_FOU'] = array(
                    '!value' => $recFrs['CODE_FOU'] ?? '',
                    '!regen' >= 1,
                    '!ok' => 1
                );
            }
        }
        
        return $retour;
    }

    /**
     * Fonction permettant de supprimer les données associées à un bloc fournisseur
     *
     * @param int $id_panier
     * @return boolean : true si la suppression s'est correctement effectuée
     */
    public static function supprimerBlocFournisseurSansLigne(& $id_user, & $id_panier)
    {
        
        // On initialise la liste des blocs fournisseurs associés à aucune ligne
        if ($liste_frs_sans_ligne = SqlPanier::rqGetListeFrsSansLigne($id_user, $id_panier)->TrouveTous())
            foreach ($liste_frs_sans_ligne as & $liste) {
                $SqlListe = new PileSql(DB_OXAPROCDB);
                $SqlListe->AddRequeteSql(SqlPanier::rqSupprimeLigneRegroupement($id_panier, $liste['CRITERE_REGROUP']));
                $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelLigneFrs($id_panier, $liste));
                $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelFrs($id_panier, $liste));
                $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelClause($id_panier, $liste));
                
                if ($result = SqlPanier::rqGetQueryClausePj($_SESSION['id_user'], $id_panier, $liste)->TrouveTous())
                    foreach ($result as & $pj)
                        if (! BoolSql($pj['ISSU_DOCATT']) && $pj['TYP_ACH'] == '' && !BoolSql($pj['LIEN_FICHIER']))
                            Fichier::Supprimer(Fichier::getExtensionCheminPJ() . $pj['nom_piece_sys']);
                
                $SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelPj($id_panier, $liste));
                $SqlListe->AddRequeteSql(SqlPanier::rqDeleteContactOnBlocFrs($id_panier, $liste));
                $SqlListe->AddRequeteSql(SqlDocRattaches::rqDeleteDocsRattaches($_SESSION['id_user'], $id_panier, $liste));
                $SqlListe->Commit();
            }
    }

    /**
     * Fonction retournant le nombre de ligne présentes dans un panier donné d'un utilisateur donné
     *
     * @param string $id_user
     * @param int $id_panier
     * @return int : Nombre de ligne présente dans le panier
     */
    public static function &getNbLignePanier(& $id_user, & $id_panier, $sup_zero = false)
    {
        $result = & SqlPanier::rqGetNbLignePanier($id_user, $id_panier, $sup_zero)->Trouve1();

        return $result['TOTAL'];
        if(isset($_SESSION['trashV1']) && isset($_SESSION['trashV1']['getNbLignePanier']))
        {
            return $_SESSION['trashV1']['getNbLignePanier'];
        } 


        return  isset($_SESSION['trashV1']) && !isset($_SESSION['trashV1']['getNbLignePanier']) ? $_SESSION['trashV1']['getNbLignePanier'] = $result['TOTAL']:$result['TOTAL'];
    }

    /**
     * Fonction enregistrant le contact fournisseur pour un utilisateur, un panier et un fournisseur donné
     *
     * @param string $code_frs
     *            : Code du fournisseur
     * @param string $ind_ctc
     *            : Indice du contact
     * @param array $info_contact
     *            : Tableau contenant les informations du contact fournisseur
     * @return booelan : vrai si l'exécution de la requête à fonctionné, faux sinon.
     */
    public static function saveContactFournisseur(& $critere, & $post)
    {
        // On met à jour les informations liées au contact fournisseur
        return SqlPanier::rqUpdateContactFrs($critere, 0, $post)->ExecuteSql();
    }

    public static function savePanierFournisseur(& $critere, & $post)
    {
        // On met à jour les informations liées au contact fournisseur
        return SqlPanier::rqUpdatePanierFrs($critere, $post)->ExecuteSql();
    }

    /**
     * Fonction enregistrant le contact livraison pour un utilisateur, un panier et un fournisseur donné
     *
     * @param string $code_frs
     *            : Code du fournisseur / et ou tableau avec code du fournisseur et critere de regouprment
     * @param string $ind_ctc
     *            : Indice du contact
     * @param array $info_contact_liv
     *            : Tableau contenant les informations du contact de livraison
     * @return booelan : vrai si l'exécution de la requête à fonctionné, faux sinon.
     */
    public static function saveContact($information_four, $type, $ind_ctc, & $info_contact_liv)
    {
        // On met à jour les informations liées au contact livraison du bloc fournisseur
        return SqlPanier::rqUpdateContactByBlocFrs($information_four, $type, $ind_ctc, $info_contact_liv)->ExecuteSql();
    }

    /**
     * Fonction permettant de mettre à jour le contact de livraison renseigné au niveau des blocs entête à partir des informations du contact livraison de l'entête du panier
     */
    public static function updateContactLivBlocFrsByContactLivEntetePanier($type, $pile = null)
    {
        // On récupère les nouvelles données liées au contact de livraison de l'entête du panier en cours
        $info_contact_livr = & SqlPanier::rqGetPanier($_SESSION['id_panier'], $_SESSION['id_user'])->Trouve1();
        
        // On récupère la liste des fournisseurs présents dans le panier en cours de l'utilisateur
        if ($liste_frs_panier = SqlPanier::rqGetAllFrsByUserPanier()->TrouveTous())
        {    // Pour chacun des fournisseurs du panier, on met à jour les informations liées au contact de livraison issues de l'entête du panier en cours
            foreach ($liste_frs_panier as & $fournisseur)
            {
                if (Param::InitialiseMailFaxFour()) 
                {
                    $adr_frs = sqlPanier::rqGetListeAdresseCdeFrs($fournisseur['COD_FOURN'], $fournisseur)->Trouve1();
                    
                    if($adr_frs && $type == 'fournisseur')
                    {
                        $info_contact_livr = [
                            'CTC_NOM'   => $adr_frs[''],
                            'CTC_FCT'   => $adr_frs[''],
                            'CTC_TEL'   => $adr_frs['TEL'],
                            'CTC_FAX'   => $adr_frs['FAX'],
                            'CTC_MAIL'  => $adr_frs['EMAIL'],
                            'CTC_GSM'   => $adr_frs['TELEX'],
                        ];
                    }
                }
                
                if (is_null($pile))
                {
                    SqlPanier::rqUpdateContactByBlocFrs($fournisseur, $type, 0, $info_contact_livr)->ExecuteSql();
                }
                else
                {
                    $pile->AddRequeteSql(SqlPanier::rqUpdateContactByBlocFrs($fournisseur, $type, 0, $info_contact_livr));
                }
            }
        }
    }

    /**
     * Fonction permettant de mettre a jour les pj issues de documents attaches pour tous les blocs fournisseurs
     */
    public static function updatepjDocAttAllBlock($pile = NULL)
    {
        $frsLignes = GetFrsLigne($_SESSION['id_panier']);
        foreach ($frsLignes as & $bloc) {
            $flagpj = SqlPanier::rqGetFlagAddPj($bloc)->Trouve1();
            if ($flagpj && BoolSql($flagpj['flg_add_pj'])) {
                if (NULL != $pile) {
                    $pile->AddSql(SqlPanier::rqDeletePjDocAtt($bloc, 'CENTRE')->TexteSqlTraduit());
                } else
                    SqlPanier::rqDeletePjDocAtt($bloc, 'CENTRE')->ExecuteSql();
            }
        }
    }

    /**
     * Fonction retournant un boolean indiquant si un fournisseur de type prospect est présent dans le panier de l'utilisateur
     *
     * @return boolean : true si un prospect est present, false sinon
     */
    public static function isFrsPropectInBasket()
    {
        $is_prospect = false;
        if ($liste_frs_panier = SqlPanier::rqGetFrsLigne($_SESSION['id_panier'])->TrouveTous())
            foreach ($liste_frs_panier as & $frs) {
                $info_frs = SqlFrs::rqGetRecordFournis($frs['COD_FOURN'])->Trouve1();
                
                if (BoolSql($info_frs['PROSPECT'])) {
                    $is_prospect = true;
                    break;
                }
            }
        
        return $is_prospect;
    }

    /**
     * Fonction retournant un boolean indiquant 1 : si le panier est du type punch out sinon 0
     *
     * @param int $id_user
     * @param int $id_panier
     * @return string sql
     */
    public static function isPanierPunchOut()
    {
        $liste_ligne_punch_out = SqlPanierLigne::rqGetLignePunchOutByUserPanier($_SESSION['id_user'], $_SESSION['id_panier'])->TrouveTous();
        return BoolSql(is_array($liste_ligne_punch_out) && count($liste_ligne_punch_out) > 0);
    }

    /**
     * Fonction retournant un boolean indiquant si au moins une ligne de type punch out cXML est présente dans un bloc fournisseur
     * du panier et de l'utilisateur en cours
     *
     * @param string $code_frs
     * @return boolean
     */
    public static function &isPunchOutCXMLinBlocFrs($code_frs)
    {

        $isLignePunchOutCXML = false;
        $liste_ligne_punch_out = SqlPanierLigne::rqGetLignePunchOutByUserPanier($_SESSION['id_user'], $_SESSION['id_panier'], $code_frs)->TrouveTous();
        
        if (is_array($liste_ligne_punch_out) && count($liste_ligne_punch_out) > 0) {
            $nb_ligne_fournisseur = count($liste_ligne_punch_out);
            $i = 0;
            
            while ($i < $nb_ligne_fournisseur && ! $isLignePunchOutCXML) {
                if ($liste_ligne_punch_out[$i]['ID_CAT'] != '') {
                    $catalogue = new Catalogue($liste_ligne_punch_out[$i]['ID_CAT']);
                    $info_catalogue = $catalogue->getInfoOnCatPunchOut();
                    
                    if ('PC' == $info_catalogue['SRCDATA'])
                        $isLignePunchOutCXML = true;
                }
                
                $i ++;
            }
        }
        
        return $isLignePunchOutCXML;
    }

    /**
     * Fonction retournant l'identifiant du catalogue associé aux lignes de type punch out cXML d'un bloc fournisseur donné
     * du panier et de l'utilisateur en cours
     *
     * @param string $code_frs
     * @return int : identifiant du catalogue privé
     */
    public static function getIDCATPunchOutCXMLFromBlocFrs($code_frs)
    {
        $id_cat = '';
        $liste_ligne_punch_out = & SqlPanierLigne::rqGetLignePunchOutByUserPanier($_SESSION['id_user'], $_SESSION['id_panier'], $code_frs)->TrouveTous();
        if (is_array($liste_ligne_punch_out) && count($liste_ligne_punch_out) > 0) {
            $nb_ligne_fournisseur = count($liste_ligne_punch_out);
            $i = 0;
            
            while ($i < $nb_ligne_fournisseur && '' == $id_cat) {
                $catalogue = new Catalogue($liste_ligne_punch_out[$i]['ID_CAT']);
                $info_catalogue = $catalogue->getInfoOnCatPunchOut();
                
                if ('PC' == $info_catalogue['SRCDATA'])
                    $id_cat = $liste_ligne_punch_out[$i]['ID_CAT'];
                
                $i ++;
            }
        }
        
        return $id_cat;
    }

    /**
     * Fonction permettant d'initialiser un ensemble de paramètre qui vont conditionner l'affichage des éléments dans le récapitulatif panier
     *
     * @param array $array
     *            : tableau de donnée qui sera fusionné avec la xsl auquel on ajoute les paramètres d'affichage
     */
    public static function getParamAffichageItemRecapPanier(&$array)
    {
        
        $array['viewer']['!isPageRechercheArt'] = 1; // l'onglet recherche article est il affiché ?
        $array['viewer']['!isPagePanierEnCours'] = 1; // l'onglet panier en cours est il affiché ?
        $array['viewer']['!isPageRecappanier'] = 1; // l'onglet récapitulatif panier est il affiché ?
        $array['viewer']['!isChiffrageExecution'] = 1; // la sélection du type chiffrage/exécution est il affiché ?
        
        $array['viewer']['!libPagePanierEnCours'] = trad('Récapitulatif panier');
        
        $array['viewer']['!isBudget'] = 1; // le budget de l'entete est il affiché ?
        $array['viewer']['!isModBudget'] = 1; // le budget de l'entete est il modifiable ?
        
        $array['viewer']['!isEnteteCentreLiv'] = 1; // Le centre de livraison de l'entête est il affiché ?
        $array['viewer']['!isModEnteteCentreLiv'] = 1; // Le centre de livraison de l'entête est il modifiable ?
        
        $array['viewer']['!isEnteteCS'] = 1; // Les CS de l'entête sont ils affichés ?
        
        $array['viewer']['!isBlocContactLiv'] = 1; // Le contact livraison des blocs fournisseurs est il affiché ?
        
        $array['viewer']['!isBlocDateLiv'] = 1; // La date de livraison des blocs fournisseurs est elle affichée ?
        $array['viewer']['!isModBlocDateLiv'] = 1; // La date de livraison des blocs fournisseurs est elle modifiable ?
        
        $array['viewer']['!isOngletInsFrs'] = Param::isOngletRecapInstructionsFrs(); // L'onglet instruction fournisseur des blocs fournisseursest il affiché ?
        $array['viewer']['!isOngletClause'] = Param::isOngletRecapClauses(); // L'onglet clause du bloc fournisseur des blocs fournisseurs est il affiché ?
        $array['viewer']['!isOngletLiv'] = Param::isOngletRecapLivraison(); // L'onglet livraison des blocs fournisseurs est il affiché ?
        
        $array['viewer']['!isOngletImput'] = Param::isOngletRecapImputation(); // L'onglet imputation des blocs fournisseurs est il affiché ?
        $array['viewer']['!isOngletDetail'] = 1; // L'onglet détail des blocs fournisseurs est il affiché ?
        
        $array['viewer']['!isOngletPJ'] = Param::isOngletRecapPJ(); // L'onglet PJ des blocs fournisseurs est il affiché ?
        $array['viewer']['!isOngletDocRattaches'] = Param::isOngletDocRattaches(); // L'onglet des documents rattaches est il affiché ?
        
        $array['viewer']['!isModQte'] = true; // La modification des quantités est elle possible ?
        $array['viewer']['!isSuprLigne'] = true; // La suppression de ligne est elle possible ?
        
        $panierEntete = new PanierEntete();        
        $panierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);


        // Si le panier provient d'une modification de document en signature
        if (false !== stripos($panierEntete->getORIGINE(), 'modifDocPourSignature')) {
            $array['viewer']['!isPageRechercheArt'] = 0;
            $array['viewer']['!isPagePanierEnCours'] = 0;
            $array['viewer']['!libPagePanierEnCours'] = $panierEntete->getlib_panier(); // libellé de l'onglet correspondant au récapitulatif panier
            $array['viewer']['!isModBudget'] = false;
            $array['viewer']['!isModQte'] = false;
            $array['viewer']['!isSuprLigne'] = false;
            $array['viewer']['!isPanierModifDocPourSignature'] = true;
            $array['viewer']['!signerDocument'] = "TraiteUrl('SIGN_manage.php?action=signerModifDocument&delegateur=" . getValue('delegateur') . "', document.forms.frm_saisie_panier.password_signature);";
            $array['viewer']['!isOngletClause'] = false;
        }
        
        // le type chiffrage/exécution est il modifiable ?
        $array['viewer']['!isModChiffrageExecution'] = $panierEntete->getCHIF_EXEC_LOCK() == 1 ? 0 : 1;
    }

    /**
     * Fonction permettant de mettre à jour l'ensemble des prix des articles contenus dans
     * le panier d'un utilisateur donné
     *
     * @param int $id_user
     *            : Identifiant de l'utilisateur
     * @param int $id_panier
     *            : Identifiant du panier
     */
    public static function updatePrixLignePanier($id_panier)
    {
        // On récupère toutes les lignes du panier
        $listeLignesPanier = & SqlPanier::rqGetAllLignePanier($id_panier)->TrouveTous();
        
        // Pour chacune des lignes on recherche le prix actualisé
        foreach ($listeLignesPanier as & $ligne) {
            $info_frs = PanierLigne::isFrsValideByLigne($ligne['COD_FOURN']);
            
            // Si le fournisseur est trouvé pour la ligne en question
            if (! empty($info_frs)) {
                
                $new_ligne_article = $ligne;
                
                // Alors les données suivantes sont mises à jour au niveau de la ligne panier :
                $new_ligne_article['COD_FOURN'] = $info_frs['COD_FOURN']; // le code fournisseur
                $new_ligne_article['REF_FOURN'] = $info_frs['REF_FOURN']; // la référence fournisseur
                $new_ligne_article['RS_FOURN'] = $info_frs['RS_FOURN']; // la raison sociale du fournisseur
                $new_ligne_article['PX_ART'] = $info_frs['PX_ART']; // le prix article
                $new_ligne_article['COD_ACD'] = $info_frs['COD_ACD']; // le code accord-cadre
                                                                      // On enregistre la mise à jour de la ligne
                MajPanierLigneFrs($new_ligne_article['id_lig'], $new_ligne_article);
            }
        }
    }

    /**
     * Fonciton mettant à jour au niveau du menu, le montant du panier et le nombre d'articles contenu
     */
    public static function updateMontantAndNbArticlePanier(& $id_panier, $mode_ajax = true, $mode_parent = false, $openDiv = TRUE)
    {
        // if(! $mode_ajax) echo "<script type='text/javascript'>";
        // On met à jour le montant total du panier en cours (code panier =0) s'il est affiché dans le menu du gauche
        // si on est sur un autre panier que le panier en cours
        $panierEntete = new PanierEntete();
        $panierEntete->getEntetePanier($id_panier, $_SESSION['id_user']);
        
        if (!isset($_SESSION['MODE_V2'])) {
            if (! $mode_ajax)
                echo '<script language=\'javascript\'>';
            if ($id_panier > 0) {
                require_once 'application/class/class_panier.php';
                
                echo 'CallUrl(\'barre_menu.php?action=' . Barre_menu::$act_Barre_eProcAlt . '&init_page=false\');' . 'openPanierAlt(', $id_panier, ', "', cnv_to_javascript($panierEntete->getlib_panier()), '",
                function() { SupPanier(', $id_panier, ',"', cnv_to_javascript(Trad('Confirmez-vous la suppression du panier')), ' ?"); },
                function() { InitSocSession();ChargePanier(', $id_panier, ',"SYS","', cnv_to_javascript(Trad('Le panier en cours n\'est pas vide et son contenu sera perdu, voulez-vous poursuivre')), ' ?"); },
                function() { LanceEcr("recherche.php","men_gene","id_panier=', $id_panier, '&type=SYS"); });';
            } else
                echo 'openPanierAlt(0,"");';
            
            if (! $mode_ajax)
                echo '</script>';
        }
        
        $idPanierEncours = $id_panier;
        $panierEnteteEncours = new PanierEntete();
        $panierEnteteEncours->getEntetePanier($idPanierEncours, $_SESSION['id_user']);
        
        $montantDuPanier = Panier::getTotalPanier($idPanierEncours);
        $total = FormatageData::formatMontant((float) $montantDuPanier, 2, ' ');
        
        if (!isset($_SESSION['MODE_V2'])) {
            Affichage::innerHTMLPointeur(Menu::id_panier_mnt . $idPanierEncours, $total, $mode_ajax, $mode_parent, $openDiv);
            Affichage::innerHTMLPointeur(Menu::id_panier_dev . $idPanierEncours, $panierEnteteEncours->getCOD_DEV(), $mode_ajax, $mode_parent, $openDiv);
            
            if ($panierEnteteEncours->getCOD_DEV() != Param::GetDeviseApplication()) {
                Affichage::setAttribut('id_sp_panier_mnt_' . $idPanierEncours, 'title', Trad('Valeur en').' ' . Param::GetDeviseApplication() . ' : ' . FormatageData::formatMontant($montantDuPanier * Param::getTauxConvDevSrcToDevDest($panierEnteteEncours->getCOD_DEV(), Param::GetDeviseApplication()), 2, ' '));
            }
            //id_sp_panier_mnt_1
            $nbLigne = Panier::getNbLignePanier($_SESSION['id_user'], $idPanierEncours, true);
            Affichage::innerHTMLPointeur('montant_total_panier', $total, $mode_ajax, $mode_parent, $openDiv);
            // On met à jour le compteur affiché du nombre d'articles présent dans le panier
            Affichage::innerHTMLPointeur('panier_txt_' . $idPanierEncours, $nbLigne, $mode_ajax, $mode_parent, $openDiv);
            if (! $mode_ajax)
                echo '<script language=\'javascript\'>';
            
            if ($panierEnteteEncours->getCOD_DEV() != Param::GetDeviseApplication())
                Affichage::setAttribut('montant_total_panier', 'title', Trad('Valeur en'). ' ' . Param::GetDeviseApplication() . ' : ' . FormatageData::formatMontant($montantDuPanier * Param::getTauxConvDevSrcToDevDest($panierEnteteEncours->getCOD_DEV(), Param::GetDeviseApplication()), 2, ' '));
            if (! $mode_ajax)
                echo '</script>';


            if ($id_panier == 0) {
                $obj_xml = new GenXslt(true);
    
                $array_menu['societeUtilisateur'] = $_SESSION['societeUtilisateur'];
                $array_menu['pageMenu'] = '1';
                $array_menu['modules'][]['entete'] = Menu::getMenuUtilisateur();
          
    
                $obj_xml->XslHtml(Menu::fichier_xsl_menu, $array_menu);
                
                echo $obj_xml->AffHtml('nomSocieteHeader');
                echo $obj_xml->AffHtml(Menu::id_select_societe);
            }
        }

    }

    public static function deletePanier($id_panier, $noUpdate = false) {

        $refreshPanier = false;
    
        $SqlListe = new PileSql(DB_OXAPROCDB);
                        
        if ($result = SqlPanier::rqGetQueryClausePj($_SESSION['id_user'], $id_panier)->TrouveTous())
            foreach ($result as & $pj) // Correction EDP sur le delete des PJ
                if (! BoolSql($pj['ISSU_DOCATT']) && $pj['TYP_ACH'] == '' && !BoolSql($pj['LIEN_FICHIER']))
                    Fichier::Supprimer(Fichier::getExtensionCheminPJ() . $pj['nom_piece_sys']);
        /*** SPEC 4241 Caractéristiques complémentaires : ajout de la suppression des CC du panier ***/
        if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelPj($id_panier)))
            if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelFourClause($id_panier)))
                if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelFour($id_panier)))
                    if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelLigneFrs($id_panier)))
                        if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelLigne($id_panier)))
                            if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelEntete($id_panier)))
                                if ($SqlListe->AddRequeteSql(SqlCaracteristiquesCompl::rqSupCCDoc('PAN', $id_panier, null, $_SESSION['id_user'])))
                                if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelCS_DON($id_panier)))
                                    if ($SqlListe->AddRequeteSql(SqlPanier::rqCopiePanierDelPanier($id_panier)))
                                        if ($SqlListe->AddRequeteSql(SqlPanier::rqDeleteContactOnBlocFrs($id_panier)))
                                            if ($SqlListe->AddRequeteSql(SqlDocRattaches::rqDeleteDocsRattaches($_SESSION['id_user'], $id_panier)))
                                                //4328 suppresion panier (delete eclatement)
                                                if($SqlListe->AddRequeteSql(SqlPanier::deleteImputation($id_panier)))
                                                    if ($SqlListe->Commit()) {
                                                        // Si le panier supprimé correspond au panier qui était chargé
                                                        if ($id_panier == $_SESSION['id_panier']) {
                                                            // Alors on ré-initialise le panier chargé en indiquant qu'il s'agit du panier en cours : 0
                                                            $_SESSION['id_panier'] = 0;
                                                            $refreshPanier = true;
                                                        }
                                                        
                                                        if (is_numeric($id_panier) && $id_panier == 0) {
                                                            /*
                                                             * Si l'entête du panier en cours ne contient pas de ligne alors on la résinitialise avec les variables de session nouvellement renseignées
                                                             */
                                                            $PanierEntete = new PanierEntete();
                                                            
                                                            // Si le panier en cours ne contient pas de ligne
                                                            // Ajout cde de Regul : Dans le cas ou on vient de créer une commande de régul sans ligne, on ne réinitialise pas l'entête du panier
                                                            // le champs CHPSPECCLT est alors du type "REGUL|codfrs={$codfrs}"
                                                            $PanierEntete->getEntetePanier($id_panier, $_SESSION['id_user']);
                                                            
                                                            // Si le panier en cours ne contient pas de ligne
                                                            $_SESSION['initConnexion'] = 1;
                                                            if (Panier::getNbLignePanier($_SESSION['id_user'], $id_panier) == 0 && false === stripos($PanierEntete->getCHPSPECCLT(), 'REGUL')) {
                                                                // On résinitialise l'entête du panier en faisant appel au mode forçage
                                                                $PanierEntete->initEntetePanier($id_panier, true);
                                                            } else {
                                                                // Initialisation de l'entête du panier
                                                                $PanierEntete->initEntetePanier($id_panier);
                                                            }
                                                            
                                                            /*
                                                             *
                                                             */
                                                        }
                                                        
                                                        $panierEncours = 0;
                                                        if ($noUpdate != true) {
                                                            Panier::updateMontantAndNbArticlePanier($panierEncours);
                                                        }
                                                        PanierRupture::NettoyerSession();
                                                    }
    
        return $refreshPanier;
    }
}
