<?php

/**
 * Classe permettant de gérer les actions sur les articles
 *
 */
class Article
{

    /**
     * Attributs de la classe
     */
    protected $COD_ART;
 // Code article HAPLUS
    protected $COD_FAB;
 // Code fabricant de l'article
    protected $RS_FAB;
 // Raison sociale du fabricant de l'article
    protected $COD_GAM;
 // Code de la gamme de l'article
    protected $LIB_GAM;
 // Libéllé de la gamma de l'article
    protected $REF_FAB;
 // Référence chez le fabricant de l'article
    protected $COD_SFAM;
 // Code de la sous-famille de l'article
    protected $LIB_SFAM;
 // Libéllé de la sous-famille de l'article
    protected $DES_ART;
 // Désignation de l'article
    protected $DES_COMP;
 // Désignation complémentaire de l'article
    protected $COD_UNIT;
 // Code de l'unité de l'articleent
    protected $PX_ART;
 // Prix de l'article trouvé dans Intuition
    protected $QTE;
 // Quantité de l'article
    protected $IS_ART_CDE_CHANTIER;
 // Flag indiquant si l'article est autorisé à commande chantier
    protected $IS_ART_MULTI_FRS;
 // Flag indiquant si l'article est multifournisseur
                                 // Attributs pour les articles stockés
    protected $IS_ART_STK_LOCAL;
 // Flag indiquant si l'article est stocké ou pas
    protected $QTE_DISPO_STK_LOCAL;
 // Pour les articles stocké, quantité disponible.
    protected $IS_QTE_DISPO_STK_LOCAL;
 // Flag indiquant si la quantité disponible est strictement supérieure à 0
    const HAP = 'HAP';
 // Constante représentant un article de type Haplus
    const CAT = 'CAT';
 // Constante représentant un article de type catalogue
    const ARTFAN = 'ARTFAN';
 // Constante représentant un article de type frais annexe
    const GEN = 'GEN';
 // Constante représentant un article de type générique
    const PO = 'PO';
 // Constante représentant un article de type PunchOut
    const AO = 'AO';
 // Constante représentant un article de type Generation via AO
    const SFAM = 'SFAM';

    // Type de provenance
    const HISTOCDE = 'HISTOCDE';

    /**
     * Constructeur de la classe
     */
    public function __construct()
    {}

    /**
     * Méthodes GET ans SET
     */
    public function &getQTE()
    {
        return $this->QTE;
    }

    public function &getUNITE()
    {
        return $this->COD_UNIT;
    }

    public function &getPX_ART()
    {
        return $this->PX_ART;
    }

    public function &getDES_ART()
    {
        return $this->DES_ART;
    }

    public function &getIS_ART_STK_LOCAL()
    {
        return $this->IS_ART_STK_LOCAL;
    }

    public function &getQTE_DISPO_STK_LOCAL()
    {
        return $this->QTE_DISPO_STK_LOCAL;
    }

    public function &getIS_QTE_DISPO_STK_LOCAL()
    {
        return $this->IS_QTE_DISPO_STK_LOCAL;
    }

    public function &getIS_ART_CDE_CHANTIER()
    {
        return $this->IS_ART_CDE_CHANTIER;
    }

    public function &getIS_ART_MULTI_FRS()
    {
        return $this->IS_ART_MULTI_FRS;
    }

    public function setPX_ART($prix_art)
    {
        $this->PX_ART = & $prix_art;
    }

    public function setQTE_DISPO_STK_LOCAL($qte)
    {
        $this->QTE_DISPO_STK_LOCAL = & $qte;
    }

    /**
     * Fonction testant l'existence d'un code article dans HA+
     *
     * @param string $code_art
     *            : code article recherché dans HA+
     * @return array ou null
     */
    public static function &isArticleHAPLUS(& $code_art, $NVIBOXAP = null, $clauseSsFam = false)
    {
        return SqlArticle::rqIsArticleHaplus($code_art, $NVIBOXAP, $clauseSsFam)->Trouve1();
    }

    public static function &afficheValeurUnite($valeurStr, & $unite)
    {
        if (strlen($valeurStr) == 0 || substr($valeurStr, 0, 1) == '.')
            $valeurStr = '0' . $valeurStr;
        
        if (strstr($valeurStr, '.') !== false) // test de l'existance
            while (substr($valeurStr, - 1) == '0')
                $valeurStr = substr($valeurStr, 0, strlen($valeurStr) - 1);
        
        if (substr($valeurStr, - 1) == '.')
            $valeurStr = substr($valeurStr, 0, strlen($valeurStr) - 1);
        
        if ($element = & SqlArticle::rqIsUniteHaplus($unite)->Trouve1())
            if ($element['NB_DECIM'] != 0) {
                // Si le nombre de decimal est inferieur au nombre de decimal du chiffre alors on formatte sinon on laisse la valeur comme elle est
                if (strstr($valeurStr, '.') === false || strlen($valeurStr) - strstr($valeurStr, '.') < $element['NB_DECIM'])
                    $valeurStr = sprintf('%1.' . $element['NB_DECIM'] . 'f', $valeurStr);
            }
        
        return $valeurStr;
    }

    public static function affichePrixUnitaire($px)
    {
        return sprintf(Param::getFormatNombreDeciamlePU(), round($px, Param::getNombreDeciamlePU()));
    }

    /**
     * Fonction permettant de déterminer si un article peut être modifié ou pas (Modification autorisée ou non de "Désignation sommaire, Unité, Prix Unitaire, Référence article")
     * La règle de gestion est la suivante :
     * Si l'article n'est pas une ligne libre
     * et si son prix est différent de 0
     * et qu'il appartient soit à un ACD valide
     * soit à un lien art/frs valide
     * soit à un lien fabricant/gamme valide
     * Alors son prix n'est pas modifiable.
     *
     * @param int $type_ligne
     *            : Le type de ligne indique s'il s'agit d'une ligne libre (1) ou d'une ligne issue d'une recherche (0)
     * @param string $provenance
     *            : Provenance de l'article Catalogue, Haplus, Art de type Frais annexe
     * @param string $cod_art
     * @param string $cod_fab
     * @param string $cod_gam
     * @param string $code_acd
     * @param string $frs
     * @param string $ref_frs
     *
     * @return boolean : retourne 1 si l'article est modifiable sinon false
     */
    public static function IsModifiable($type_ligne, $provenance, $code_art, $cod_fab, $cod_gam, $code_acd, $frs, $ref_frs, $catalogue = null)
    {
        // Si la ligne est une ligne libre alors celle-ci est modifiable
        if (1 == $type_ligne) {
            if (Article::AO == $provenance)
                return 0;
            else if (Article::PO == $provenance)
                return 0;
            else
                return 1;
        }
        
        // Si l'article est un article catalogue (CAT) => L'article n'est pas modifiable
        if (Article::CAT == $provenance || Article::PO == $provenance)
            return 0;
            
        // Si l'article est un article provenant d'Haplus (HAP)
        if (Article::HAP == $provenance) {
            // Si l'article est un article générique (GEN) => L'article est modifiable
            if (Article::GEN == $cod_fab || Article::GEN == $cod_gam)
                return 1;
            
            // Si un accord-cadre est présent sur article
            if ('' != $code_acd) {
                // On détermine si l'ACD est valide ou pas en tenant compte du paramétrage HAPLUS ( prise en compte ou non de la validité des ACD)
                $result = & SqlArticle::rqIsAcdValide($code_acd)->Trouve1();
                if (is_array($result) && array_key_exists('CODE_ACD', $result))
                    return 0; // L'accord-cadre lié à l'article est valide, l'article n'est donc pas modifiable
            }
            
            // Si un lien article/fournisseur existe
            if ('' != $ref_frs) {
                $result = & SqlArticle::rqIsLienArtFrsValide($code_art, $ref_frs, $frs)->Trouve1();
                if (is_array($result) && array_key_exists('FOU', $result))
                    return 0; // Le lien article fournisseur est valide, l'article n'est donc pas modifiable
            }
            
            // Si l'article appartient à une gamme/fabriquant non générique et renseigné
            if (Article::GEN != $cod_fab && Article::GEN != $cod_gam && '' != trim($cod_fab) && '' != trim($cod_gam))
                return 0; // L'article est du type fabricant/gamme, il n'est donc pas modifiable
        }
        return 1; // Pour les autres cas, la ligne est modifiable
    }

    /**
     * Fonction initialisant le prix de l'article pour un fournisseur donné dans la devise pivot
     * 
     * @param string $code_fournisseur
     *            : Code du fournisseur
     * @param string $prix_article
     *            : Prix article à convertir dans la devise pivot
     */
    public function InitPrixArtInDevPivot(& $code_fournisseur, $prix_article)
    {
        $result = getPrixArtInDevisePivot($code_fournisseur, $prix_article)->Trouve1();
        // Formatage du prix de l'article dans la devise pivot
        $this->PX_ART = number_format((float) $result['PRIX_ART_IN_DEVISE_PIVOT'], 2, '.', '');
    }

    /**
     * Fonction initialisant le prix de l'article pour un fournisseur donné dans la devise pivot
     * 
     * @param string $code_fournisseur
     *            : Code du fournisseur
     * @param string $prix_article
     *            : Prix article à convertir dans la devise pivot
     */
    public function InitPrixArtInDevEntetePanier(& $code_fournisseur, $prix_article, $devise_entete)
    {
        $Fournisseur = new Fournisseur($code_fournisseur);
        $devise_source = $Fournisseur->getDEVISE();
        $prix_article = $prix_article * Param::getTauxConvDevSrcToDevDest($devise_source, $devise_entete);
        
        // Formatage du prix de l'article dans la devise de l'entête du panier
        $this->PX_ART = number_format((float) $prix_article, 2, '.', '');
    }

    /**
     * Fonction permettant d'initialiser le prix d'un article selon le conditionnement de référence de cet article dans HAPLUS
     * 
     * @param string $code_art
     *            : Code de l'article HAPLUS
     * @param string $unite
     *            : Unité de l'article dans intuition
     * @param int $prix_art
     *            : Prix de l'article retourné par intuition
     */
    public function InitPrixArtInCondHaplus(& $code_art, & $unite, & $prix_art)
    {
        $result = & SqlArticle::getPrixArtInCondHaplus($code_art, $unite, $prix_art)->Trouve1();
        // Mise à jour du prix seulement si une conversion existe entre les 2 unités alors calcul du prix de l'article avec conversion du conditionnement INTUITION vers celui d'HAPLUS
        if (is_array($result)) {
            $this->PX_ART = number_format((float) $result['PRIX_ART_IN_CDT_HAPLUS'], 2, '.', '');
        }
    }

    /**
     * Fonction calculant le prix d'un article issu de INTUITION
     * en le convertissant dans la devise pivot HAPLUS
     * et en le convertissant dans l'unité de conditionnement d'HAPLUS
     *
     * @param string $code_fournisseur
     *            : Code du fournisseur
     * @param string $prix_article
     *            : Prix article à convertir dans la devise pivot
     * @param string $code_art
     *            : Code de l'article HAPLUS
     * @param string $unite
     *            : Unité de l'article dans intuition
     * @return void
     */
    public function InitPrixArtInDevPivotAndInCondHaplus($code_fournisseur, $prix_article, $code_art, $unite)
    {
        
        // On réalise la conversion dans la devise pivot et dans l'unité Haplus que si
        // code fournisseur renseigné + prix article renseigné + code article renseigné
        if (is_string($code_fournisseur) && is_numeric($prix_article) && is_string($code_art)) {
            $this->InitPrixArtInDevPivot($code_fournisseur, $prix_article);
            $this->InitPrixArtInCondHaplus($code_art, $unite, $this->PX_ART);
        }        // Sinon on considère que le prix article vaut 0
        else
            $this->PX_ART = 0;
    }

    /**
     * Fonction convertissant la quantité d'un article depuis une unité vers un autre unité
     *
     * @param int $qte
     *            : quantité de l'article exprimé dans le 1er conditionnement
     * @param string $unite1
     *            : unité dans laquelle la quantité est exprimées initialement
     * @param string $unite2
     *            : unité dans laquelle on souhaite exprimer la quantité
     */
    public function getQteArtInCond($qte, $unite1, $unite2, $code_art)
    {
        // On commence par faire la recherche de convertion dans la table CONV_ART (spec 2263)
        // si il existe une convertion dans la table CONV_ART on calcule la quantité via le coefficient de cette table
        $result = & SqlArticle::rqGetQteArtInCondCONV_ART($qte, $code_art, $unite1)->Trouve1();
        
        if (! is_array($result)) { // requete de controle
                                  // On passe par la fonction de convertion de via la table de conversion CONVERS
            $result = & SqlArticle::rqGetQteArtInCond($qte, $unite1, $unite2)->Trouve1();
        }
        $this->QTE = $result['QUANTITE'];
        // Si la conversion entre les unités n'existe pas alors on retourne la quantité 0
        if (! is_numeric($this->QTE)) {
            $this->QTE = 0;
            return false;
        }
        return true;
    }

    /**
     * Fonction retournant un booleen indiquant si un article pour un fournisseur, un fabricant et un accord-cadre donné est autorisé à commande oxaproc
     *
     * @param string $code_fourn
     *            : Code fournisseur
     * @param string $code_fab
     *            : Code fabricant
     * @param string $code_acd
     *            : Code accord-cadre
     * @param string $code_article
     *            : Code article
     * @return string $sql
     */
    public static function isArtMultiFrsAutCdeOxaproc(& $code_fourn, & $code_fab, & $code_acd, & $code_article)
    {
        if ($code_fab != '' || $code_acd != '' || $code_article != '') {
            $result = & SqlArticle::rqIsArtAuthCdeOxaproc($code_fourn, $code_fab, $code_acd, $code_article)->Trouve1();
            return $result['AUTOCC'];
        } else
            return '0';
    }

    /**
     * Fonction retournant un prix unitaire en fonction du prix de base de l'article sur l'accord-cadre 
     * ou 
     * si pas d'accord-cadre ou si article pas présent sur l'acd : tarif "article pr fournisseur
     *
     * @param string $code_fourn
     *            : Code fournisseur
     * @param string $code_fab
     *            : Code fabricant
     * @param string $code_acd
     *            : Code accord-cadre
     * @param string $code_article
     *            : Code article
     * @return string $sql
     */
    public static function getInfoPuLigneLibre($code_art = null, $code_acd = null, $code_fou = null, $qte = null)
    {
  
        $dataAcd = SqlArticle::rqGetAccadreData($code_acd, $code_art)->Trouve1();
        $trouveTous = SqlArticle::getPuTx($code_acd, $qte, $code_art)->Trouve1();
        if (($dataAcd['PU'] != '') || ($code_art != '' && $code_fou != ''))
        {
            if($dataAcd['PU'] == '')
            {
                
                $result = SqlArticle::rqGetPuByFourn('noAcd', $code_acd, $code_fou, $qte)->Trouve1();
            }
            else
            {            
                $finalArray = SqlArticle::getPuTx($code_acd, $qte, $code_art, false)->Trouve1(); 
                
                $result = $finalArray['PU_TX']; 
                
            }
            
            if($trouveTous == null)
            {
                $result = $dataAcd['PU'];
            }

            return $result;
        }
       
        if(SqlArticle::rqGetAccadreData($code_acd, $code_art)->Trouve1()['QTEMAX'] > $qte && SqlArticle::rqGetAccadreData($code_acd, $code_art)->Trouve1()['CODE_ART'] != '')
        {
            $result = SqlArticle::rqGetPuByFourn('acdArt', $code_acd, '', $qte, $code_art)->Trouve1();
            return $result['PU'] ? '' : $result = 0;
        }
    }

    public static function recursivData($array)
    {
        foreach($array  as $r)
        {

        }
    }
    /**
     * Fonction retournant les informations relatives a un article HAPLUS identifié par son code + les sections d'imputations associées
     *
     * @param string $code_art
     *            : code de l'article recherché
     * @return array : tableau de données
     */
    public static function &getInfoOnArticle(& $code_art)
    {
        return SqlArticle::rqGetInfoOnArticleHaplus($code_art)->Trouve1();
    }

    /**
     * Fonction retournant les informations d'un article HAPLUS.
     * Cette requête est utilisée notamment dans le cadre des popup article appelée sur les article issus de formulaire métier.
     *
     * @param string $code_art
     *            : Code de l'article recherché
     * @return string sql
     */
    public static function &getInfoArtFrmForPopup(& $code_art)
    {
        return SqlArticle::rqSelectInfoArtFrmForPopup($code_art)->Trouve1();
    }

    /**
     * Fonction retournant vrai si l'article est stocké sur le centre de stokage rattaché au centre de livraison donné
     *
     * @param string $centre_liv
     * @param string $code_art
     * @return boolean : 1 si l'article est stocké, 0 sinon.
     */
    public static function isArtStkForCtrLiv(& $centre_liv, & $code_art)
    {
        $CentreLivraison = new Centre();
        $CentreLivraison->getSiteStkFromCtrLiv($centre_liv);
        $codeSiteStock = $CentreLivraison->getSITE_STK();
        if ($codeSiteStock == '')
            return 0;
        $result = SqlArticle::rqIsArtStkForCtrLiv($centre_liv, $code_art)->Trouve1();
        if ($result['TROUVE'] > 0)
            return 1;
        else
            return 0;
    }

    /**
     * Fonction permettant de contrôler que le prix saisi pour un article autorisé à commande chantier lié à un formulaire métier
     * est inférieur au prix proposé par le fournisseur associé
     *
     * @param int $ID_PANIER
     * @param int $ID_LIGNE
     * @param int $PRIX
     * @return boolean : retourne 1 si le prix est bien inférieur ou égal sinon 0
     */
    public static function ctrlPrixArtFMonFrs($ID_PANIER, $ID_LIGNE, $PRIX)
    {
        $controleOK = true;
        
        $info_ligne = TrouveLignePanier($ID_PANIER, $ID_LIGNE);
        
        if ('' != $info_ligne['CODE_FM'] && ((0 == $info_ligne['REFLMAN'] && 0 == $info_ligne['type_de_ligne']) || '' != $info_ligne['COD_ACD'])) {
            
            $info_art = FormulaireMetier::getInfoArtFMForFRS($info_ligne['CODE_FM'], $info_ligne['CODE_MET'], $info_ligne['CODE_SPE'], $info_ligne['COD_ART'], $info_ligne['COD_FOURN'], $info_ligne['COD_ACD']);
            
            // On contrôle pour les lignes mono-fournisseur
            if (('F' == $info_art['TYPECATA'] && BoolSql($info_art['flg_cde'])) || '' != $info_ligne['COD_ACD'])
                $controleOK = ($PRIX <= $info_art['PX_ART']);
            // On contrôle pour les lignes multi-fournisseur
            elseif (('M' == $info_art['TYPECATA'] && Article::isArtMultiFrsAutCdeOxaproc($info_art['COD_FOURN'], $info_art['COD_FAB'], $info_art['COD_ACD'], $info_art['COD_ART']) > 0) || '' != $info_ligne['COD_ACD'])
                $controleOK = ($PRIX <= $info_art['PX_ART']);
        }
        
        return $controleOK;
    }

    public static function &getDocAttInfoFromIdLigne(& $idLigne)
    {
        $result = SqlArticle::rqDocAttInfoFromIdLigne($idLigne)->TrouveTous();
        if ($result)
            foreach ($result as & $info){
                $i=0;
                if ($info['TYP_CAR'] == 'U') {
                    $info['NOM_FIC'] = str_ireplace("\\", '/', $info['VAL_CAR']);
                    
                    if (strpos($info['NOM_FIC'], 'http:') === 0 || strpos($info['NOM_FIC'], 'https:') === 0 || strpos($info['NOM_FIC'], 'www.') === 0) {
                        $i=1;
                        // si commence par % alors replace
                        if (strpos($info['NOM_FIC'], '%') === 0)
                            $info['NOM_FIC'] = Param::getOxadataWeb($info['NOM_FIC']);
                        
                        if (strpos($info['NOM_FIC'], 'www.') === 0)
                            $info['LINK'] = Param::getProtocolWeb() . '://' . $info['NOM_FIC'];
                        
                        if (strpos($info['NOM_FIC'], 'http') === 0)
                            $info['LINK'] = $info['NOM_FIC'];
                        else
                            $info['LINK'] =  $_SESSION['oxadataweb'].$info['NOM_FIC'];
                    } else
                    {
                        $i=1;
                        $info['LINK'] =  $_SESSION['oxadataweb'].$info['NOM_FIC'];
                    }
                    
                    if ($info['NOM_FIC'] > '')
                        $info['LINKDOWN'] = "window.open('" . Fichier::GetUrl('chr', $info['NOM_FIC'], $info['NOM_ORI']) . '\');';
                    if($i==1)
                    {
                        $info['VAL_CAR'] =  $info['LINK'];
                    }
                }
            }
        
        return $result;
    }

    public static function &getDocAttInfoFromCodArt(& $codeArticle, $typeFt = null)
    {
        if ($result = SqlArticle::rqDocAttInfoFromCodArt($codeArticle, $typeFt)->TrouveTous())
            foreach ($result as & $info) {
                $info['COPIE'] = BoolSql($info['COPIE']);
                $info['DT_PARUT'] = convertDateSqlToFr($info['DT_PARUT']);
                $info['DT_VALID'] = convertDateSqlToFr($info['DT_VALID']);
                if ($info['TYPE_FT'] == 'U' || $info['COPIE'] == 1) {
                    $info['NOM_FIC'] = str_ireplace("\\", "/", $info['NOM_FIC']);
                    
                    if (strpos($info['NOM_FIC'], 'http:') === 0 || strpos($info['NOM_FIC'], 'https:') === 0 || strpos($info['NOM_FIC'], 'www.') === 0) {
                        if (strpos($info['NOM_FIC'], 'www.') === 0)
                            $info['LINK'] = Param::getProtocolWeb() . '://' . $info['NOM_FIC'];
                        else
                            $info['LINK'] = $info['NOM_FIC'];
                    } elseif ($info['NOM_FIC'] > '') {
                        $info['LINKDOWN'] = "window.open('" . Fichier::GetURL('chr', $info['NOM_FIC'], $info['NOM_ORI']) . '\');';
                    }
                }
            }
        
        return $result;
    }

    public static function getCaractInfoFromIdLigne(& $result, $idligne)
    {
        global $gloablStk;
        
        if ($result['caractinfo'] = $gloablStk->getInfo('rqCaractInfoFromIdLigne', $idligne)) {} else if (! $gloablStk->isExiste('rqCaractInfoFromIdLigne', $idligne)) {
            $result['caractinfo'] = SqlArticle::rqCaractInfoFromIdLigne($idligne)->TrouveTous();
            $gloablStk->setInfo('rqCaractInfoFromIdLigne', $idligne, $result['caractinfo']);
        }
    }

    /**
     * Fonction retournant pour un id catalogue et un couple code fabricant / code gamme donné
     * le fournisseur et le taux de remise associé et enregistrant les résultats en question dans le
     * tableau passé en référence
     *
     * @param int $id_cat
     *            : Identifiant du catalogue
     * @param string $cod_fab
     *            : Code fabricant de l'article
     * @param string $cod_gam
     *            : Code gamme de l'article
     * @param array $array
     *            : Tableau passé par référence dans lequel sont enregistrés les résultats
     */
    public static function getFrsAndTxForArtCatRemise(& $id_cat, & $cod_fab, & $cod_gam, &$array, $limit = '')
    {
        global $connecteur;
        
        $result = & $connecteur->CanFind(SqlSynequa::rqGetFrsAndTxRemise($id_cat, $cod_fab, $cod_gam, $limit), DB_OXACATDB, true, false);
        
        // Si un fournisseur a été trouvé par la procédure stockée ainsi que le taux de remise associée
        if (is_array($result) && array_key_exists('CODEFOUR', $result) && array_key_exists('REMGAM', $result))
            Article::updateArticleFromCatRemise($array, $result, $array['PX_ART']);
    }

    /**
     * Fonction retournant pour un id catalogue et un couple code fabricant / code gamme donné
     * TOUS LES fournisseurs et le taux de remise associé et enregistrant les résultats en question dans le
     * tableau passé en référence
     *
     * @param int $id_cat
     *            : Identifiant du catalogue
     * @param string $cod_fab
     *            : Code fabricant de l'article
     * @param string $cod_gam
     *            : Code gamme de l'article
     * @param array $array
     *            : Tableau passé par référence dans lequel sont enregistrés les résultats
     */
    public static function getAllFrsAndTxForArtCatRemise(& $id_cat, & $cod_fab, & $cod_gam, &$array, $limit = '')
    {
        global $connecteur;
        
        $result = & $connecteur->AllFind(SqlSynequa::rqGetFrsAndTxRemise($id_cat, $cod_fab, $cod_gam, $limit), DB_OXACATDB, true, false);
        
        // Si un fournisseur a été trouvé par la procédure stockée ainsi que le taux de remise associée
        if($result)
        {
            $nbRes = count($result);
            for ($i = 0; $i < $nbRes; $i ++)
                if (is_array($result[$i]) && array_key_exists('CODEFOUR', $result[$i]) && array_key_exists('REMGAM', $result[$i]))
                    Article::updateArticleFromCatRemise($array[$i], $result[$i], $array[$i]['PX_ART']);
        }
    }

    /**
     * Fonction permettant de mettre à jour les nouvelles valeurs d'une ligne de panier à partir d'un tableau de résultat
     *
     * @param array $array
     *            : tableau cible
     * @param array $result
     *            : tableau source provenant de la procédure stockée
     * @param int $result
     *            : Prix de base sur lequel la remise sera appliquée
     */
    public static function updateArticleFromCatRemise(&$array, & $result, $prix_art)
    {
        $array['COD_FOURN'] = & $result['CODEFOUR']; // On met le code fournisseur à jour
        $array['RS_FOURN'] = (is_null($result['ENSCOMM']) || $result['ENSCOMM'] == '') ? $result['RS'] : $result['ENSCOMM']; // On met la raison sociale à jour
        $array['CPOSTAL'] = & $result['CPOSTAL']; // On met le code postal à jour
        $array['VILLE1'] = & $result['VILLE1']; // On met la ville à jour
        $array['REMGAM'] = & $result['REMGAM']; // On met le taux de Remise à jour
        $array['PX_ART'] = FormatageData::formatMontant($prix_art * (1 - ($result['REMGAM'] / 100)), Param::getNombreDeciamlePU()); // On calcule le nouveau prix en prenant en compte le taux de remise
        
        $array['PX_ART_INIT'] = $array['PX_ART']; // Dossier 24926 Imperatif le px initial qte 1 doit etre reinitialiser avec les remise gammes fabricants SANS TENIR compte des degressif
        
        $array['TYPECATA'] = 'M';
        $array['is_multi_frs'] = 1;
    }

    /**
     * Fonction initialisant la quantité disponible pour un site de stock donné et un code article donné
     *
     * @param string $site_stock
     * @param string $code_art
     * @return Float : Quantité disponible de l'article
     */
    public function setQteArtStkDispo($site_stock, $code_art)
    {
        // On récupère les informations liés à l'article stocké
        $result = & SqlSiteStock::rqGetArticlesStk($site_stock, $code_art)->Trouve1();
        
        // Si l'article stocké est trouvé alors on calcule la quantité disponible
        if (is_array($result) && array_key_exists('CODE_ART', $result)) {
            $qte_dispo = $result['QTE_PHYS'] - $result['QTE_RES'] - $result['QTE_INDIS'] - $result['QTE_TRF'] - $result['QTE_PREV'];
            
            // Si l'article est un article dit 'Stratégique'
            if (1 == $result['STRATEG'])
                // Alors la quantité disponible est amputée dans la quantité de suretée
                $qte_dispo = $qte_dispo - $result['QTE_STSUR'];
            
            // On indique que l'article est stocké et on enregistre la qté disponible
            $this->IS_ART_STK_LOCAL = 1;
            $this->QTE_DISPO_STK_LOCAL = $qte_dispo;
            
            if ($this->QTE_DISPO_STK_LOCAL > 0)
                $this->IS_QTE_DISPO_STK_LOCAL = 1;
            else
                $this->IS_QTE_DISPO_STK_LOCAL = 0;
        }        // Sinon, on indique que l'article n'est pas stocké
        else {
            
            $this->IS_ART_STK_LOCAL = 0;
            $this->QTE_DISPO_STK_LOCAL = null;
            $this->IS_QTE_DISPO_STK_LOCAL = 0;
        }
    }

    /**
     * Fonction permettant de contrôler la quantité saisie par un utilisateur sur un article stocké.
     * Le contrôle est OK si la quantité saisie est inférieure à la quantité disponible
     *
     * @param string $ctr_liv
     *            : centre de livraison
     * @param string $code_art
     * @param int $qte
     * @return boolean : Vrai si le contrôle est OK faux sinon.
     */
    public function ctrlQteDispoForArtStk($ctr_liv, $code_art, $qte)
    {
        
        // On recherche le site de stock lié au centre de livraison donné
        $centre = new Centre();
        $site_stock = $centre->getSiteStkFromCtrLiv($ctr_liv);
        
        if (! is_null($site_stock)) {
            $this->setQteArtStkDispo($site_stock, $code_art);
            
            // Si l'article est stocké alors on contrôle les quantités
            if (1 == $this->IS_ART_STK_LOCAL)
                return ($this->QTE_DISPO_STK_LOCAL >= $qte);
            else
                return true;
        } else
            return true;
    }

    /**
     * Fonction déterminant les caractéristiques d'un article.
     * Les caractéristiques déterminées sont : article autorisé à commande chantier ?, article stocké ?, article multifournisseur ?
     * 
     * @param array $array_info_art
     *            : tableau contenant les données de l'article dont on va déterminer les caractéristiques
     */
    public static function initAllCaractArt($isCertifieIntuition, & $array_info_art, $is_autorise_cde_chantier = 0, $is_multi_frs = 0, $is_art_stk = 0, $rech_remfour = true, $calc_type = true)
    {
        
        // Si ce n'est pas un article en saisie libre
        if (is_array($array_info_art) && 'SYS' == $_SESSION['sys_panier'] && (! array_key_exists('PANIER_TYPE_SPEC', $_SESSION) || 'REGUL' != $_SESSION['PANIER_TYPE_SPEC'])) {
            
            // On détermine si l'article est un article stocké ou non
            if (0 == $is_art_stk && '' != trim($array_info_art['COD_ART'])) {
                $PanierEntete = new PanierEntete();
                $PanierEntete->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
                
                $is_art_stk = Article::isArtStkForCtrLiv($PanierEntete->getLIV_CTR(), $array_info_art['COD_ART']);
            }
            
            // On recherche les lignes correspondantes à l'article dans le moteur de recherche ayant :
            // le même code article ou le même couple cod_fab/ref_fab ou le même couple cod_grp/ref_fourn
            
            $elements_recherche_art['COD_FAB'] = & $array_info_art['COD_FAB'];
            $elements_recherche_art['REF_FAB'] = & $array_info_art['REF_FAB'];
            $elements_recherche_art['COD_ART'] = & $array_info_art['COD_ART'];
            $elements_recherche_art['COD_GRP'] = & $array_info_art['COD_GRP'];
            $elements_recherche_art['REF_FOURN'] = & $array_info_art['REF_FOURN'];
            
            $Synequa_rech_arti = new CtrlArticle();
            $recherche_synequa = & $Synequa_rech_arti->RechercheArtFrs(true, $isCertifieIntuition, $elements_recherche_art, '', '', null, $rech_remfour, $calc_type);
            
            // Si au moins une ligne est trouvée
            if (is_array($recherche_synequa)) 
            {
                
                if (0 == $is_multi_frs)
                {
                    // On plusieurs lignes ont été trouvées alors l'article est multifournisseur
                    if (count($recherche_synequa) > 1 || 'M' == $recherche_synequa[0]['TYPECATA'])
                    {
                        $is_multi_frs = 1;
                    }
                    elseif ('M' == $recherche_synequa[0]['TYPECATA']) 
                    {
                        if ($recherche_synequa[0]['is_multi_frs'] == 1)
                        {
                            $is_multi_frs = 1;
                        }
                    }
                }
                // On détermine si l'article est autorisé à commande Oxaproc pour au moins un des fournisseurs
                $nb_frs_intuition = count($recherche_synequa);
                $ind_frs_intuition = 0;
                
                // Pour chacune des lignes trouvées dans Inuition
                while ($ind_frs_intuition < $nb_frs_intuition && 0 == $is_autorise_cde_chantier) {
                    // Si la ligne est du type multi fournisseur
                    $is_autorise_cde_chantier = $recherche_synequa[$ind_frs_intuition]['IS_AUTH_CDE_OXAPROC'];
                    
                    $ind_frs_intuition ++;
                }
            }
            
            // Pour le client 28 ETDE, des règles spécifiques s'appliquent si l'article est lié à un formulaire métier
            if (28 == $_SESSION['Session_NumClient'] && // Identifié spec N°2431
'' != $array_info_art['COD_ART']) {
                
                // Pour le client ETDE N°28, Si l'article n'est pas autorisé é la commande chantier dans Sinequa et qu'un extension de panel existe
                // Alors on teste dans Haplus si l'article ou le fabricant de l'article est autorisé é commande chantier
                if (0 == $is_autorise_cde_chantier && $_SESSION['IS_EXTENSION_PANEL'])
                    $is_autorise_cde_chantier = BoolSql(Article::isExtentionPanel($array_info_art['COD_ART']));
                
                // Pour le client ETDE N°28 et si l'article n'est pas encore détecté comme multifournisseur et que l'extension de panel fournisseur peut être associé à l'article
                if (0 == $is_multi_frs && Article::isExtentionPanel($array_info_art['COD_ART'])) {
                    // Alors on détermine la liste des fournisseurs de l'extension de panel
                    $listeExclue = '';
                    
                    // On détemrine la liste des fournisseur de l'extension de panel
                    $listeFrsExtPanel = FormulaireMetier::getListFrsForArtFMExtPanel($listeExclue);
                    
                    // Si au moins un fournisseur a été trouvé alors le choix multifournisseur est activé
                    if (is_array($listeFrsExtPanel) && count($listeFrsExtPanel) > 0)
                        $is_multi_frs = 1;
                }
            }
            
            return 'is_autorise_cde_chantier=' . $is_autorise_cde_chantier . '|is_multi_frs=' . $is_multi_frs . '|is_art_stk=' . $is_art_stk;
        }
    }

    /**
     * Fonction permettant de retourner un boolean indiquant si l'extension de panel doit être affiché pour un article donné
     *
     * @param string $code_art
     *            : Code de l'article sur lequel on souhaite tester l'existence de la panel
     * @return boolean : 1 si le panel peut être affiché 0 sinon
     */
    public static function isExtentionPanel(& $code_art)
    {
        // On récupère les informations liées à l'article
        $info_art = & SqlArticle::rqIsArticleHaplus($code_art)->Trouve1();
        
        // Si des fournisseurs sont présents dans le panel et si l'article ou le fabicant sont autorisés à commande e-proc alors le panel pourra être affiché
        // Note : $_SESSION['IS_EXTENSION_PANEL'] vaut 1 si au moins 1 fournisseur est présent dans le panel
        return (array_key_exists('IS_EXTENSION_PANEL', $_SERVER) && 1 == $_SESSION['IS_EXTENSION_PANEL'] && (BoolSql($info_art['CDIRFMT']) || BoolSql($info_art['AUTOCC'])));
    }

    /**
     * Fonction permettant d'extraire la liste des caractéristiques à partie d'une chaine
     * Exemple de chaine : is_autorise_cde_chantier=1|is_multi_frs=1|is_art_stk=0
     *
     * @param string $liste_caract_art
     *            : Chaine dans laquelle les caractéristiques articles sont contenus
     */
    public function getAllCaractArt(& $liste_caract_art)
    {
        $this->IS_ART_STK_LOCAL = 0;
        $this->IS_ART_CDE_CHANTIER = 0;
        $this->IS_ART_MULTI_FRS = 0;
        
        if (is_string($liste_caract_art)) {
            $liste = explode('|', $liste_caract_art);
            
            foreach ($liste as & $caract_and_value)
                if ($caract_and_value != '') {
                    $caract = explode('=', $caract_and_value);
                    $caract_nom = $caract[0];
                    $caract_value = $caract[1];
                    
                    switch ($caract_nom) {
                        case 'is_autorise_cde_chantier':
                            $this->IS_ART_CDE_CHANTIER = $caract_value;
                            break;
                        
                        case 'is_multi_frs':
                            $this->IS_ART_MULTI_FRS = $caract_value;
                            break;
                        
                        case 'is_art_stk':
                            $this->IS_ART_STK_LOCAL = $caract_value;
                            break;
                    }
                }
        }
    }

    /**
     * Fonction permettant de vérifier si un article dont le code est donné est déjà
     * pour un panier et un utilisateur donné
     *
     * @param int $id_user
     *            : Identifiant de l'utilisateur
     * @param int $id_panier
     *            : Identifiant du panier
     * @param string $code_art
     *            : Code de l'article recherché
     */
    public static function isArticleInPanier(& $id_user, & $id_panier, & $code_art, $code_four = '', $REF_FAB = '', $COD_FAB = '', $REF_FOURN = '', $type_de_ligne = null)
    {
        $article_panier = & SqlPanier::rqIsArticleInUserPanier($id_user, $id_panier, $code_art, $code_four, $REF_FAB, $COD_FAB, $REF_FOURN, $type_de_ligne)->Trouve1();
        return (is_array($article_panier) && array_key_exists('COD_ART', $article_panier) && $code_art == $article_panier['COD_ART']);
    }

    /**
     * Fonction retournant la traduction de la désignation d'un article donné
     *
     * @param string $code_art
     * @param string $langue
     * @return string : Libellé traduit de l'article
     */
    public static function &getDesignatTrad(& $code_art, & $langue)
    {
        $article = & SqlArticle::rqGetDesignatArt($code_art, $langue)->Trouve1();
        return $article['DES_ART'];
    }

    /**
     * Fonction recherchant pour un article donné, le prix degressif correspondant à la quantité saisie
     *
     * @param array $element_article
     *            : tableau contenant les informations de l'article permettant de rechercher les prix dégressifs associés à l'article
     * @param int $qte
     * @return int : Retourne le prix de l'article, si aucun prix degressif n'est présent alors on retourne le prix initial
     */
    public static function &getPrixDegressifByQte(& $article, $qte)
    {
        if (! BoolSql($article['PRIXDEGRESSIF']))
            return $article['PX_ART'];
        
        if ($article && $qte > 0 && is_array($article)) {
            $prix_initial = $article['PX_ART_INIT']; // ICI IL FAUT PRENDRE LE PRIX DE BASE SINEQUA incluant au cas ou, les remises fabriquant gammes 24926
                                                     // La quantité etant exprime dans l'oxaproc en boite, il faut la recalculer pour la faire comparer à une expression à l'unité
                                                     // Correction de l'unité de conditionnement Dossier 9664
            if (trim($article['TXTCOND']) != '')
                if ($article['CONDITNT'] != 0)
                    $qte *= $article['CONDITNT'];
            
            $prix_degressif = & SqlFavoriCatalogue::rqGetListePrixDegressifByArt($article['PROVENANCE'], $article['ID_CAT'], $article['IDLIGNE'], $article['COD_ART'], $qte)->Trouve1();
            if (is_array($prix_degressif) && count($prix_degressif) > 0 && $article['PROVENANCE'] == 'CAT')
                if ($prix_degressif['PRIXNET'] > 0)
                    $prix = $prix_degressif['PRIXNET'];
                else
                    $prix = FormatageData::formatMontant($prix_initial * (1 - ($prix_degressif['REMQTE'] / 100)), Param::getNombreDeciamlePU());
            else
                $prix = $article['PX_ART_INIT'];
            // $prix = $article['PX_ART'];
            // Attention le prix ramené par intuition est le prix à l'unite et dans le cas de conditionnement il faut le ramener à la boite
            // spec 2946 : prix catalogues nuls modifiables.
            // si la saisie des prix nuls est activée, si le prix retourné par intuition est 0 alors on laisse le prix initial
            // sinon le prix est remis à 0 même si on a déjà fait des modifications sur le prix.
            if ($article['PX_ART'] == 0) {
                $r = & SqlUsers::rqIsSaisiePrixNullOk()->Trouve1(true);
                if (is_array($r) && $r['LIB01PARV'] == 'O')
                    $prix = $prix_initial;
            }
        } else
            $prix = $article['PX_ART'];

        if(getValue('val'))
        {
            echo "if(document.getElementById('px_art_".getValue("num_ligne")."'))
                    document.getElementById('px_art_".getValue("num_ligne")."').textContent ='".number_format($prix,Param::getNombreDeciamlePU(),'.',' ')."';";
        }

        return $prix;
    }

    public static function &buildXmlForPrixDegressif($id_div, & $element_art)
    {
        $rechercheIntuition = new RechercheArticlesIntuition(true);
        if (array_key_exists('IDLIGNE', $element_art) && is_numeric($element_art['IDLIGNE'])) {
            if (array_key_exists('PUNCHOUT', $element_art) && array_key_exists('REGRFOUR', $element_art)) {
                // Comme IDLIGNE, REGRFOUR et PUNCHOUT sont dans l'array: cela veut dire que c'est déjà le résultat d'une recherche intuition donc pas besoin d'en refaire une
                $article_trouve = & $element_art;
            } else if ($article_trouveTmp = & $rechercheIntuition->rechercheArtCatalogue(FALSE, 1, 1, '', '', '', '', array(), array(), array(), array(), array(), array(), array(), array(), array(), array(), array(), '', $element_art)) {
                if (count($article_trouveTmp['lignes']) != 0) {
                    $article_trouve = $article_trouveTmp['lignes'][0];
                } else
                    $article_trouve = null;
            } else
                $article_trouve = null;
        } else {
            $clArticle = new CtrlArticle();
            $article_trouve = & $clArticle->RechercheArt($element_art);
        }
        
        $array_xml = null;
        if (is_array($article_trouve)) {
            $qte_cond = 1;
            if (trim($article_trouve['TXTCOND']) != '')
                if ($article_trouve['CONDITNT'] != 0) {
                    // Correction de l'unité de conditionnement Dossier 9664
                    $qte_cond = $article_trouve['CONDITNT'];
                }
            $listePrixDegressif = SqlFavoriCatalogue::rqGetListePrixDegressifByArt($article_trouve['PROVENANCE'], $article_trouve['ID_CAT'], $article_trouve['IDLIGNE'], $article_trouve['COD_ART'])->TrouveTous();
            $array_xml['prixDegressif']['fermer'] = "changeDisplay('$id_div', false);";
            if (mb_strlen($article_trouve['DES_ART']) > 25)
                $array_xml['prixDegressif']['des_art'] = mb_substr($article_trouve['DES_ART'], 0, 25) . '...';
            else
                $array_xml['prixDegressif']['des_art'] = $article_trouve['DES_ART'];
            
            if (is_array($listePrixDegressif))
                foreach ($listePrixDegressif as & $prix_degressif) {
                    if ($prix_degressif['PRIXNET'] > 0)
                        $prix = $prix_degressif['PRIXNET'];
                    else
                        $prix = $article_trouve['PX_ART'] * (1 - ($prix_degressif['REMQTE'] / 100));
                    
                    // Dossier 23961
                    if (Param::isAfficheTtc())
                        $prix = FormatageData::formatMontant(Article::getPrixTtc($prix * $qte_cond, $article_trouve['TAUX_TVA']), Param::getNombreDeciamlePU(), ' ');
                    else
                        // Suppresion de l'information de tva car déjà 1 pas de taux demandé et 2, la fonctionne prends 2 parametre et pas 3
                        $prix = FormatageData::formatMontant($prix * $qte_cond, Param::getNombreDeciamlePU(), ' ');
                    
                    $array_xml['prixDegressif']['liste'][] = array(
                        'qte' => $prix_degressif['QTETRANCHE'] / $qte_cond,
                        'prix' => $prix
                    );
                }
        }
        return $array_xml;
    }

    /**
     * SPEC 3502
     * Pour une ligne sans fournisseur
     *
     * Lecture de la règle "Taxe locale" :
     * Pays du panier avec taxe locale : flag COUNTRY.AV_TAXLOC
     * Si Article avec taxe locale ARTICLES.AV_TAX_LOC ou sous famille avec taxe locale SSFAMILL.AV_TAXLOC, alors taux de TVA est celui du centre de livraison : CENTRE.TX_TAXLOC
     * Sinon, taux de TVA par défaut :
     * Si pays du panier = pays d'install de la BDD ou (pays du panier CEE et Pays d'install CEE), Si Code article, taux de TVA de l'article ARTICLES.TXTVA, sinon Taux de TVA par défaut (paramétrage)
     *
     * Flag pays CEE : COUNTRY.PAYSCEE
     * Pays d'installation : select LIB01PARV from PARAVRAC where TYPEPARV='PARAMGEN' and CODEPARV='PAYSINSTAL'
     * Taux de TVA par défaut : select TX_TVA from PARAMETR where CLE='1'
     *
     * Pour une ligne libre avec fournisseur, le seul changement est dans le pays à utiliser qui n'est plus celui du panier, mais celui du fournisseur FOURNISS.CODE_PAYS
     *
     * @global type $connecteur
     * @param string $typeDeLigne
     * @param string $codeArticle
     * @param string $codeSousFamille
     * @param string $codFourn
     * @param string $tauxTva
     * @param string $CodeCtrLivraison
     * @return int
     */
    public static function getTauxTva($typeDeLigne, $codeArticle, $codeSousFamille = '', $codFourn = null, $tauxTva = null, $CodeCtrLivraison = null)
    {
        // 100063
        if (is_null($CodeCtrLivraison)) {
            $EntetePanier = new PanierEntete();
            $EntetePanier->getEntetePanier($_SESSION['id_panier'], $_SESSION['id_user']);
            $CodeCtrLivraison = $EntetePanier->getLIV_CTR();
        }
        
        // Sur
        $centreLiv = & SqlCentreGene::getInfoOnCentre($CodeCtrLivraison)->Trouve1();
        if ($recPaysCentre = & SqlFrs::rqGetRecordCountry($centreLiv['PAYS'])->Trouve1())
            $taxeLocalCentre = $recPaysCentre['AV_TAXLOC'];
        else
            $taxeLocalCentre = false;
        
        $sql =  "SELECT TX_TVA 
                FROM PARAMETR 
                WITH(NOLOCK) 
                WHERE CLE='1' ";
        if ($r = (new RequeteSQL($sql, DB_OXASQLDB))->Trouve1())
            $tauxTvaSysteme = $r['TX_TVA'];
        
        // Pays du panier avec taxe locale (pays du centre de livraison de la ligne de panier)
        $regle1 = false;
        if ($taxeLocalCentre) {
            $taxeLocalArticle = false;
            if ($codeArticle != '') // prise en compte fu flag tax locale article
                if ($result = & SqlArticle::rqIsArticleHaplus($codeArticle)->Trouve1())
                    $taxeLocalArticle = $result['AV_TAX_LOC'];
            
            $taxeLocalSfam = false;
            if ($codeSousFamille != '') // prise en compte fu flag tax locale sous famille
                if ($result = & SqlArticle::rqGetSousFamille($codeSousFamille)->Trouve1())
                    $taxeLocalSfam = $result['AV_TAXLOC'];
            
            if ($taxeLocalArticle || $taxeLocalSfam) {
                $tauxTva = $centreLiv['TX_TAXLOC'];
                $regle1 = true;
            }
        }
        
        if (! $regle1) {
            /**
             * Ajout fonctionnel du 29/10/2014
             * Si la valeur de LIB01PARV est "T", le taux de TVA à appliquer dans tous les cas est celui du pays de livraison, à savoir "COUNTRY.TVA"
             * Pour tous les types de ligne, on ignore les autres taux (que ce soit catalogue, article, etc...).
             * ATTENTION, la règle s'applique après celle de la taxe locale qui est prioritaire.
             */
            if (Param::isTvaPaysLivraison()) {
                $tauxTva = $recPaysCentre['TVA'];
            } else {
                if (is_null($codFourn) || $codFourn == '') // Pour une ligne sans fournisseur
                    $paysAControle = Param::getPaysInstall();
                else if ($r = & SqlFrs::rqGetRecordFournis($codFourn)->Trouve1())
                    $paysAControle = $r['CODE_PAYS'];
                else
                    $paysAControle = & Param::getPaysInstall();
                
                $recPaysAControle = & SqlFrs::rqGetRecordCountry($paysAControle)->Trouve1();
                
                // Trouve sur le client VIVESCIA, l'information peut etre a blanc dans ce cas on utilisera le pays d'install
                $paysDuCentreLivr = $centreLiv['PAYS'];
                if (trim($paysDuCentreLivr) == '')
                    $paysDuCentreLivr = Param::getPaysInstall();
                
                if ($paysAControle == $paysDuCentreLivr || $recPaysAControle['PAYSCEE'] == $recPaysCentre['PAYSCEE']) {
                    if (is_null($tauxTva) && $codeArticle != '')
                        if ($result = & SqlArticle::rqIsArticleHaplus($codeArticle)->Trouve1())
                            $tauxTva = $result['TXTVA'];
                } else
                    $tauxTva = 0;
            }
        }
        // Gestion des cas particuliers relatif au fournisseur
        
        if (is_null($tauxTva))
            $tauxTva = $tauxTvaSysteme;
        return FormatageData::formatMontant($tauxTva, 2);
    }

    /**
     *
     * @global type $connecteur
     * @param string $codeArticle
     * @param string $codeSfam
     * @param string $codeFournisseur
     * @param string $propriete
     *            Array contenant notamment le centre de livraison de la ligne
     *            'CTR_LIV' => (test)
     *            
     *            !!!! NE PAS METTRE DE PASSAGE DE REFERENCE SUR $prixHt
     *            
     * @return int
     */
    public static function getPrixTtc($prixHt, & $tauxTva)
    {
        return $prixHt * (1 + $tauxTva / 100);
    }

    /**
     * Fonction retournant la référence fournisseur d'un article donné
     *
     * @param string $code_art
     * @param string $codeFou
     * @return string : Référence fournisseur
     */
    public static function getRefFou($code_art, $codeFou = '')
    {
        $article = & SqlArticle::rqGetRefFou($code_art, $codeFou)->Trouve1();
        return $article['REF_FOUR'];
    }

    /**
     * Fonction retournant la référence fournisseur d'un article donné
     *
     * @param string $code_art
     * @param string $codeFou
     * @return string : Contrôle quanlité
     */
    public static function getCtrlQualite($code_art, $codeFou = '')
    {
        $article = & SqlArticle::rqGetCtrlQualite($code_art, $codeFou)->Trouve1();
        return $article['CTRL_QUA'];
    }

    /**
     * Fonction retournant la référence fournisseur d'un article donné
     *
     * @param string $code_art
     * @param string $codeFou
     * @return string : Contrôle quanlité
     */
    public static function getDateLivraisonDA($param)
    {
        $dateLivraison = '';
        
        /* VARIABLES DATES */
        // Date Livraison souhaitée actuelle
        $date1 = $param['DTELIVSOU'];
        // Date Livraison de l'entête 
        $date2 = $param['DTE_LIV'];

        /* VARIABLES DELAIS */
        // Délai de livraison en jours sur le lien article/Acccord cadre 
        $delai1 = SqlArticle::rqGetDelaiFromAcart($param['ACD'],$param['CODE_ART'])->Trouve1()['DELAI'] ?? 0;
        // Délai de livraison en jours sur du marché de l'Accord-cadre
        $result = SqlArticle::rqIsAcdValide($param['ACD'])->Trouve1();
        $delai2 = SqlArticle::rqGetDelaiFromMarches($result['MARCHE'])->Trouve1()['DELAILIV'] ?? 0;
        // Délai de traitement standard pour une DA
        $delai3 = SqlParam::rqGetParamParavrac('PARAMGEN', 'DUREETTDA')->Trouve1()['LIB01PARV'] ?? 0;
        
        if($delai1 != 0){
            $days2Add = $delai1 + $delai3;
            $dateLivraison = date("Ymd", strtotime("+$days2Add day"));
        }
        elseif($delai2 != 0){
            $days2Add = $delai2 + $delai3;
            $dateLivraison = date("Ymd", strtotime("+$days2Add day"));
        }
        elseif($date1!='' && $date1 != '00000000'){
            $dateLivraison = $date1;
        }
        elseif($date2!='' && $date2 != '00000000'){
            $dateLivraison = $date2;
        }
        elseif($delai3 != 0){
            $dateLivraison = date("Ymd", strtotime("+$delai3 day"));
        }
        else{
            $dateLivraison = '00000000';
        }
        
        return $dateLivraison;
    }
}
