<?php
/*
 *   This file is part of NOALYSS.
 *
 *   NOALYSS is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   NOALYSS is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with NOALYSS; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
// Copyright Author Dany De Bontridder danydb@aevalys.eu
/*! \file
 * \brief Manage the account
 */
/*!
 * \brief Manage the account from the table jrn, jrnx or tmp_pcmn
 */

class Acc_Account_Ledger
{
    var $db;          /*!< $db database connection */
    var $id;          /*!< $id poste_id (pcm_val)*/
    var $label;       /*!< $label label of the poste */
    var $parent;      /*!< $parent parent account */
    var $row;         /*!< $row double array see get_row */
    var $tot_deb;    /*!< value set by  get_row */
    var $tot_cred;    /*!< value by  get_row */
    var $name;

    function __construct ($p_cn,$p_id)
    {
        $this->db=$p_cn;
        $this->id=$p_id;
    }
    /**
     *@brief get the row thanks the resource
     *@return double array (j_date,deb_montant,cred_montant,description,jrn_name,j_debit,jr_internal)
     *         (tot_deb,tot_credit)
     * @deprecated since version 6920
     */
    private function get_row_sql_deprecated($Res)
    {
        $array=array();
        $tot_cred=0.0;
        $tot_deb=0.0;
        $Max=Database::num_row($Res);
        if ( $Max == 0 ) return null;
        for ($i=0;$i<$Max;$i++)
        {
            $array[]=Database::fetch_array($Res,$i);
            if ($array[$i]['j_debit']=='t')
            {
                $tot_deb+=$array[$i]['deb_montant'] ;
            }
            else
            {
                $tot_cred+=$array[$i]['cred_montant'] ;
            }
        }
        $this->row=$array;
        $this->tot_deb=$tot_deb;
        $this->tot_cred=$tot_cred;
        return array($array,$tot_deb,$tot_cred);

    }
    /*!
     * \brief  Get data for accounting entry between 2 periode
     *
     * \param  $p_from periode from
     * \param  $p_to   end periode
     * \return double array (j_date,deb_montant,cred_montant,description,jrn_name,j_debit,jr_internal)
     *         (tot_deb,tot_credit
     *
     */
    function get_row($p_from,$p_to)
    {
        $periode=sql_filter_per($this->db,$p_from,$p_to,'p_id','jr_tech_per');

        $this->row=$this->db->get_array("select distinct j_id,jr_id,to_char(j_date,'DD.MM.YYYY') as j_date_fmt,j_date,".
                                 "case when j_debit='t' then j_montant else 0 end as deb_montant,".
                                 "case when j_debit='f' then j_montant else 0 end as cred_montant,".
                                 " jr_comment as description,jrn_def_name as jrn_name,".
                                 "j_debit, jr_internal,jr_pj_number ".
                                  ",oc_amount,oc_vat_amount".
                                 " from jrnx left join jrn_def on jrn_def_id=j_jrn_def ".
                                 "  left join operation_currency using (j_id) ".
                                 " left join jrn on jr_grpt_id=j_grpt".
                                 " where j_poste=$1 and $periode ".
                                 " order by j_date",array($this->id));
         $res_saldo = $this->db->exec_sql(
                 "select  sum(deb_montant),sum(cred_montant) from 
                    (select case when j_debit='t' then j_montant else 0 end as deb_montant,
                    case when j_debit='f' then j_montant else 0 end as cred_montant
                    from jrnx 
                    left join jrn_def 
                    on jrn_def_id=j_jrn_def 
                    left join jrn on jr_grpt_id=j_grpt
                  where j_poste=$1 and $periode ) as m
                  ",array($this->id));
        $this->tot_deb=$this->tot_cred=0;
        
        if ( Database::num_row($res_saldo) > 0 ) {
            $this->tot_deb=Database::fetch_result($res_saldo, 0, 0);
            $this->tot_cred=Database::fetch_result($res_saldo, 0, 1);
        }
        return array($this->row,$this->tot_deb,$this->tot_cred);
    }
    /**
     * @brief build the SQL for get_row_data
     * @param $p_from date d.m.Y start date
     * @param $p_to  date d.m.Y until date
     * @param $sql_let  sql string for getting lettering info
     * @param $filter_sql string SQL for filtering the ledgers , to respect security on ledgers
     * @return  sql SELECT
     */
    function make_sql_accounting_detail($p_from,$p_to,$sql_let,$filter_sql)
    {

     $sql =  "
 with sqlletter as (select j_id,jl_id from letter_cred union all select j_id , jl_id from   letter_deb )
         select j1.j_id,jr_id,to_char(j_date,'DD.MM.YYYY') as j_date_fmt,j_date,
                                j_qcode
                                 ,case when j_debit='t' then j_montant else 0 end as deb_montant,
                                 case when j_debit='f' then j_montant else 0 end as cred_montant,
                                  case when j_text is null or j_text = '' then jr_comment 
                                   else jr_comment||' '||j_text  end
                                 as description,jrn_def_name as jrn_name,
                                 j_debit, jr_internal,jr_pj_number
                                 ,(select distinct jl_id from sqlletter  where sqlletter.j_id=j1.j_id ) as letter 
                                 ,pcm_lib
                                 ,jr_optype
				 				 ,jr_tech_per
                                 ,p_exercice
                                 ,jrn_def_name
                                 ,jrn_def_code
                                 ,(with cred as (select jl_id, sum(j_montant) as amount_cred from letter_cred left join jrnx using (j_id)  group by jl_id )
                                , deb as (select jl_id, sum(j_montant) as amount_deb from letter_deb left join jrnx using (j_id)   group by jl_id )
        select amount_deb-amount_cred
        from 
        cred 
        full  join deb using (jl_id) where jl_id=(select distinct jl_id from sqlletter  where sqlletter.j_id=j1.j_id  )) as delta_letter
            ,jrn.currency_rate
            ,jrn.currency_rate_ref
            ,jrn.currency_id
            ,(select cr_code_iso from currency where id=jrn.currency_id) as cr_code_iso
            ,j_montant
            ,oc_amount
            ,oc_vat_amount ,
	case when exists(select 1 from operation_analytique oa where j1.j_id=oa.j_id) then 1 else 0 end as op_analytic
  from jrnx as j1
    left join operation_currency as va on (j1.j_id = va.j_id )
          join jrn_def on (jrn_def_id=j_jrn_def )
           join jrn on (jr_grpt_id=j_grpt)
           join tmp_pcmn on (j1.j_poste=pcm_val)
           join parm_periode on (p_id=jr_tech_per)              
          where j1.j_poste=$1 and 
          ( to_date($2,'DD.MM.YYYY') <= j_date and 
            to_date($3,'DD.MM.YYYY') >= j_date )
                                  and $filter_sql  $sql_let 
                                  order by j_date,substring(jr_pj_number,'[0-9]+$') asc";
        return $sql;
    }

    /**
     * @brief make the SQL for the balanced accounting
     * @param $filter filter to respect the security on ledger
     * @return sql SELECT
     */
    public function make_sql_not_balanced_account($filter)
    {
        $bal_sql="select sum(amount_deb) as s_deb,sum(amount_cred) as s_cred, j_poste
                        from 						
                        (select case when j_debit='t' then j_montant else 0 end as amount_deb,
                                case when j_debit='f' then j_montant else 0 end as amount_cred,
                                j_poste
                                from jrnx join jrn on (j_grpt = jr_grpt_id)
                                where
                                j_poste=$1 and
                                $filter and
                                ( to_date($2,'DD.MM.YYYY') <= j_date and
                                  to_date($3,'DD.MM.YYYY') >= j_date  )) as signed_amount
						group by j_poste
						";
        return $bal_sql;
    }

    /**
     * @brief make the SQL for the balance of an accounting
     * @param $filter_sql filter to respect the security on ledger
     * @param $sql_let string for getting lettering info
     * @return sql SELECT
     *
     */
    public function make_sql_saldo_account($filter_sql,$sql_let)
    {
        $sql_saldo="select  sum(deb_montant) as deb,sum(cred_montant) as cred
                    from 
                    (select case when j_debit='t' then j_montant else 0 end as deb_montant,
                    case when j_debit='f' then j_montant else 0 end as cred_montant
                                  from jrnx j1
                                  join jrn_def on (jrn_def_id=j_jrn_def )
                                   join jrn on (jr_grpt_id=j_grpt)
                                   join tmp_pcmn on (j_poste=pcm_val)
				   join parm_periode on (p_id=jr_tech_per) 
                                  where j_poste=$1 and 
                                  ( to_date($2,'DD.MM.YYYY') <= j_date and 
                                    to_date($3,'DD.MM.YYYY') >= j_date ) 
                                  and $filter_sql  $sql_let ) as m";
        return $sql_saldo;
    }
    /*!
     * \brief  Get data for accounting entry between 2 date
     *
     *\param  $p_from date from DD.MM.YYYY
     *\param  $p_to   end date DD.MM.YYYY
     *\param $let 0 means all rows, 1 only lettered, 2 only unlettered
     *\param $solded 0 means all account, 1 means only accounts with a saldo <> 0
     *\note the data are filtered by the access of the current user
     * \return double array (j_date,deb_montant,cred_montant,description,jrn_name,j_debit,jr_internal)
     *         (tot_deb,tot_credit
     *
     */
    function get_row_date($p_from, $p_to, $let = 0, $solded = 0)
    {
        global $g_user;
        $filter_sql = $g_user->get_ledger_sql('ALL', 3);
        $sql_let = '';
        switch ($let) {
            case 0:
                break;
            case 1:
                $sql_let = ' and j1.j_id in (select j_id from letter_cred union all select j_id from letter_deb)';
                break;
            case '2':
                $sql_let = ' and j1.j_id not in (select j_id from letter_cred union all select j_id from letter_deb) ';
                break;
        }
        // if accounting is balanced , D = C then returns an empty array
        if ($solded == 1) {
            if ($this->db->is_prepare("not_balanced_account") == false) {
                $filter=noalyss_str_replace('jrn_def_id','jr_def_id',$filter_sql);
                $sql_balanced = $this->make_sql_not_balanced_account($filter);
                $this->db->prepare("not_balanced_account", $sql_balanced);
            }

            $ret_balanced = $this->db->execute("not_balanced_account", array($this->id, $p_from, $p_to));

            $r = Database::fetch_all($ret_balanced);
            if (empty($r)) return array();
            if ($r[0]['s_deb'] == $r[0]['s_cred']) return array();
        }

        // get the detail of accouting
        if (!$this->db->is_prepare("sql_accounting_detail")) {
            $sql = $this->make_sql_accounting_detail($p_from, $p_to, $sql_let, $filter_sql);
            $this->db->prepare("sql_accounting_detail", $sql);

        }
        $ret = $this->db->execute("sql_accounting_detail", array($this->id, $p_from, $p_to));
        $this->row = Database::fetch_all($ret);

        // $this->row=$this->db->get_array(,array($this->id,$p_from,$p_to));
        if ($this->db->is_prepare("saldo_account") == false) {
            $sql_saldo = $this->make_sql_saldo_account($filter_sql, $sql_let);
            $this->db->prepare("saldo_account", $sql_saldo);
        }
        $res_saldo = $this->db->execute("saldo_account", array($this->id, $p_from, $p_to));
        $result=Database::fetch_all($res_saldo);
        $this->tot_deb = $this->tot_cred = 0;

        if (! empty($result) > 0) {
            $this->tot_deb = $result[0]['deb'];
            $this->tot_cred = $result[0]['cred'];
        }
        return array($this->row, $this->tot_deb, $this->tot_cred);
    }


    /*!\brief Return the name of a account
     *        it doesn't change any data member
     * \return string with the pcm_lib
     */
    function get_name()
    {
        $ret=$this->db->exec_sql(
                 "select pcm_lib from tmp_pcmn where
                 pcm_val=$1",array($this->id));
        if ( Database::num_row($ret) != 0)
        {
            $r=Database::fetch_array($ret);
            $this->name=$r['pcm_lib'];
        }
        else
        {
            $this->name=_("Poste inconnu");
        }
        return $this->name;
    }
    /*!
    * \brief Return the type  of a account
     * \returns string ACT,ACTINV,CHA,CHAINV,CON,PAS,PRO
     */
    function get_type()
    {
        $type=$this->db->get_value(
            "select pcm_type from tmp_pcmn where
                 pcm_val=$1",array($this->id));
        return $type;
    }

    /*!\brief check if the poste exist in the tmp_pcmn
     *\return the number of line (normally 1 or 0)
     */
    function do_exist()
    {
        $sql="select pcm_val from tmp_pcmn where pcm_val= $1";
        $ret=$this->db->exec_sql($sql,array($this->id));
        return Database::num_row($ret) ;
    }
    /*!\brief Get all the value for this object from the database
     *        the data member are set
     * \return false if this account doesn't exist otherwise true
     */
    function load():bool
    {
        $ret=$this->db->exec_sql("select pcm_lib,pcm_val_parent from
                                 tmp_pcmn where pcm_val=$1",array($this->id));
        $r=Database::fetch_all($ret);

        if ( ! $r ) return false;
        $this->label=$r[0]['pcm_lib'];
        $this->parent=$r[0]['pcm_val_parent'];
        return true;

    }


    /*!
     * \brief  give the balance of an account
     * \param $p_cond (text) a SQL Condition, 
     * \return
     *      balance of the account
     *
     */
    function get_solde($p_cond=" true ")
    {
        if (DEBUGNOALYSS  > 1 ) { echo __CLASS__.".".__FUNCTION__."p_cond {$p_cond}"; }

        $Res=$this->db->exec_sql("select sum(deb) as sum_deb, sum(cred) as sum_cred from
                                 ( select j_poste,
                                 case when j_debit='t' then j_montant else 0 end as deb,
                                 case when j_debit='f' then j_montant else 0 end as cred
                                 from jrnx join tmp_pcmn on j_poste=pcm_val
                                 where
                                 j_poste::text like ('$this->id'::text) and
                                 $p_cond
                                 ) as m  ");
        if (DEBUGNOALYSS  > 1 ) { echo $this->db->get_sql(); }
        $Max=Database::num_row($Res);
        if ($Max==0) return 0;
        $r=Database::fetch_array($Res,0);

        return abs($r['sum_deb']-$r['sum_cred']);
    }
    /*!
     * \brief   give the balance of an account
     * \return
     *      balance of the account
     *
     */
    function get_solde_detail($p_cond="")
    {
        if ( $p_cond != "") $p_cond=" and ".$p_cond;

        $sql="select sum(deb) as sum_deb, sum(cred) as sum_cred from
             ( select j_poste,
             case when j_debit='t' then j_montant else 0 end as deb,
             case when j_debit='f' then j_montant else 0 end as cred
             from jrnx
             where
             j_poste::text like ('$this->id'::text)
             $p_cond
             ) as m  ";
        if (DEBUGNOALYSS  > 1 ) {  tracedebug("impress.debug.log", "$sql", 'acc_account_ledger:get_solde_detail'); }
        $Res=$this->db->exec_sql($sql);
        $Max=Database::num_row($Res);

        if ($Max==0)
        {
            return array('debit'=>0,
                         'credit'=>0,
                         'solde'=>0)     ;
        }
        $r=Database::fetch_array($Res,0);
// if p_start is < p_end the query returns null to avoid any problem
// we set it to 0
        if ($r['sum_deb']=='')
            $r['sum_deb']=0.0;
        if ($r['sum_cred']=='')
            $r['sum_cred']=0.0;

        return array('debit'=>$r['sum_deb'],
                     'credit'=>$r['sum_cred'],
                     'solde'=>abs(bcsub($r['sum_deb'],$r['sum_cred'],2)));
    }
    /*!
     * \brief isTva tell is a poste is used for VAT
     * \param none
     *
     *
     * \return 1 is Yes otherwise 0
     */
    function isTVA()
    {
        // Load TVA array
        $a_TVA=$this->db->get_array('select tva_poste
                                    from tva_rate');
        foreach ( $a_TVA as $line_tva)
        {
            if ( $line_tva['tva_poste']  == '' )
                continue;
            list($tva_deb,$tva_cred)=explode(',',$line_tva['tva_poste']);
            if ( $this->id == $tva_deb ||
                    $this->id == $tva_cred )
            {
                return 1;
            }
        }
        return 0;

    }
   
    /*!
     * \brief HtmlTable, display a HTML of a poste for the asked period
     * \param $p_array array for filter
     * \param $let lettering of operation 0
     * \return -1 if nothing is found otherwise 0
     */
    function HtmlTable($p_array=null,$let=0 , $from_div=0)
    {
        
        if ( $p_array==null)$p_array=$_REQUEST;
        global $g_parameter;
        $this->get_name();
        list($array,$tot_deb,$tot_cred)=$this->get_row_date( $p_array['from_periode'],
							     $p_array['to_periode'],$let
                                                           );

        if ( count($this->row ) == 0 )
            return -1;

        $rep="";

        $type =$this->get_type();
        // label  warning if the saldo is incorrect
        $label="";
        if (in_array($type,array('CHA','ACT','PASINV','PROINV')) && $tot_deb<$tot_cred)
        {

            $label.=_("Solde créditeur au lieu de débiteur").'<span class="icon">&#xe80e;</span>';
        }
        if (in_array($type,array('PRO','PAS','ACTINV','CHAINV')) && $tot_deb>$tot_cred)
        {

            $label.=_("Solde débiteur au lieu de créditeur")." ".'<span class="icon">&#xe80e;</span>';
        }
        if ( $label !="" ) 
                echo '<span class="notice" >'.$label.'</span>';
        
        if ( $from_div == 1)
			echo "<TABLE id=\"tbpopup\" class=\"resultfooter\" style=\"border-collapse:separate;margin:1%;width:98%;\">";
		else
			echo "<TABLE id=\"tb".$from_div."\" class=\"resultfooter\" style=\"border-collapse:separate;margin:1%;width:98%;\">";
        echo '<tbody>';
        echo "<TR>".
        "<TH style=\"text-align:left\">"._('Date')." </TH>".
        "<TH style=\"text-align:left\">"._('Pièce')." </TH>".
        "<TH style=\"text-align:left\">"._('Code')."</TH>".
        "<TH style=\"text-align:left\">"._('Interne')." </TH>".
        "<TH class=\"visible_gt800\"  style=\"text-align:left\">"._('Tiers')." </TH>".
        "<TH class=\"visible_gt800\"  style=\"text-align:left\">"._('Description')."</TH>".
        "<TH class=\"visible_gt800\"  style=\"text-align:left\">"._('Type')."</TH>".
        "<TH class=\"visible_gt800\"  style=\"text-align:left\">"._('ISO')."</TH>".
        "<TH class=\"visible_gt800\"  style=\"text-align:right\">"._('Dev.')."</TH>".
        "<TH style=\"text-align:right\">"._('Débit')."</TH>".
        "<TH style=\"text-align:right\">"._("Crédit")."</TH>".
        th('Prog.','style="text-align:right"').
        th('Let.',' class="visible_gt800" '.'style="text-align:right"');
        "</TR>"
        ;
        $progress=0;$sum_deb=0;$sum_cred=0;
	bcscale(2);
	$old_exercice="";
	$idx=0;
        $operation=new Acc_Operation($this->db);
        foreach ( $this->row as $op )
        {
           
            $tiers=$operation->find_tiers($op['jr_id'],$op['j_id'],$op['j_qcode']);
           
            
            $vw_operation = sprintf('<A class="detail" style="text-decoration:underline;color:red" HREF="javascript:modifyOperation(\'%s\',\'%s\')" >%s</A>', $op['jr_id'], dossier::id(), $op['jr_internal']);
            $let = '';
			$html_let = "";
			if ($op['letter'] != 0)
			{
				$let = strtoupper(base_convert($op['letter'], 10, 36));
				$html_let = HtmlInput::show_reconcile($from_div, $let);
                                if ( $op['delta_letter'] != 0) $html_let='<img src="image/warning.png" onmouseover="displayBulle(\'delta = '.$op['delta_letter'].'\')" onmouseleave="hideBulle()" style="height:12px"/>'.$html_let;
			}
			$tmp_diff=bcsub($op['deb_montant'],$op['cred_montant']);

	    /*
	     * reset prog. balance to zero if we change of exercice
	     */
	    if ($old_exercice != $op['p_exercice']) {
                if ($old_exercice != '') {
                    $progress = bcsub($sum_deb, $sum_cred);
                    $side = "&nbsp;" . $this->get_amount_side($progress);
                    echo "<TR class=\"highlight\">" .
                    td($op['p_exercice']) .
                    td("", ' class="visible_gt800" ') .
                    td("", ' class="visible_gt800" ') .
                    td("", ' class="visible_gt800" ') .
                    td("", ' class="visible_gt800" ') .
                    td("", ' class="visible_gt800" ') .
                    td() .
                    "<TD >Totaux</TD>" . td("") .
                    "<TD  style=\"text-align:right\">" . nbm($sum_deb) . "</TD>" .
                    "<TD  style=\"text-align:right\">" . nbm($sum_cred) . "</TD>" .
                    td(nbm(abs($progress)).$side,'style="text-align:right;padding-left:10px;"').
                    td("", ' class="visible_gt800" ') .
                    "</TR>";
		 
                   
                    $sum_cred = 0;
                    $sum_deb = 0;
                    $progress = 0;
                }
            }
            $progress=bcadd($progress,$tmp_diff);
		$side="&nbsp;".$this->get_amount_side($progress);
	    $sum_cred=bcadd($sum_cred,$op['cred_montant']);
	    $sum_deb=bcadd($sum_deb,$op['deb_montant']);
            $class=($idx%2 == 0)?'class="odd"':$class=' class="even"';
            $idx++;
 $op_analytic=($op['op_analytic']==1)?'<span style="float:right;background:black;color:white;">&ni;</span>':'';
	    echo "<TR $class name=\"tr_" . $let . "_" . $from_div . "\">" .
			"<TD>".smaller_date(format_date($op['j_date']))."</TD>".
	      td(h($op['jr_pj_number'])).
	      "<TD>".\HtmlInput::card_detail($op['j_qcode'])."</TD>".
	      "<TD>".$vw_operation."</TD>".
                "<TD class=\"visible_gt800\" >".$tiers."</TD>".
	      "<TD class=\"visible_gt800\" >".h($op['description']).$op_analytic."</TD>".
                    td($op['jr_optype'],' class="visible_gt800" ');
                     /// If the currency is not the default one , then show the amount
            if ( $op['currency_id'] > 0  )
            {
                // some amount are not directly recorded into operation_currency, like VAT
                $currency_val=($op['oc_amount'] == 0)?round(bcmul ($op['j_montant'],$op['currency_rate']),2):$op['oc_amount'] ;
               
               echo   td($op['cr_code_iso']).
                    td(nbm($currency_val,2),'style="text-align:right;padding-left:10px;"');
            } else {
                echo td('', 'class="visible_gt800" ').td('',' class="visible_gt800"' );
            }
            
            echo 
	      "<TD style=\"text-align:right;padding-left:10px;\">".nbm($op['deb_montant'])."</TD>".
	      "<TD style=\"text-align:right;padding-left:10px;\">".nbm($op['cred_montant'])."</TD>".
	      td(nbm(abs($progress)).$side,'style="text-align:right"').

	      td($html_let, ' class="visible_gt800" '.' style="color:red;text-align:right"') .
			"</TR>";
	    $old_exercice=$op['p_exercice'];
        }
        echo '<tfoot>';
        $solde_type=($sum_deb>$sum_cred)?_("solde débiteur"):_("solde créditeur");
        $diff=bcsub($sum_deb,$sum_cred);
		$side="&nbsp;".$this->get_amount_side($diff);
       echo "<TR class=\"highlight\">".
                td($op['p_exercice']).
                 td("",' class="visible_gt800" ').
                td("",' class="visible_gt800" ').
                td("",' class="visible_gt800" ').
                td("",' class="visible_gt800" ').
                td("",' class="visible_gt800" ').
                td().
        "<TD >Totaux</TD>".td("").
	  "<TD  style=\"text-align:right\">".nbm($sum_deb)."</TD>".
	  "<TD  style=\"text-align:right\">".nbm($sum_cred)."</TD>".
	  "<TD style=\"text-align:right\">".nbm(abs($diff)).$side."</TD>".
                td("",' class="visible_gt800" ').
        "</TR>";
	echo   "<tr style=\"font-weight:bold\"><TD>$solde_type</TD><td></td>".
	  "<TD style=\"text-align:right\">".nbm(abs($diff))."</TD>".
        "</TR>";
        // take saldo from 1st day until last
        if ($g_parameter->MY_REPORT=='N') {
            $solde_until_now=$this->get_solde_detail("  j_date <= to_date('{$p_array['to_periode']}','DD.MM.YYYY')  ");
            echo '<tr style="font-weight:bold;color:orangered">';
            echo td(_("Solde global"));
            echo td("D : ".nbm($solde_until_now['debit']),'class="num"');
            echo td("C : ".nbm($solde_until_now['credit']),'class="num"');
            echo td("Delta : ".nbm($solde_until_now['solde'])." ".$this->get_amount_side($solde_until_now['debit']-$solde_until_now['credit']),'class="num"');
            echo '</tr>';

        }
        echo '</tfoot>';
        echo '</tbody>';

        echo "</table>";
        if ( DEBUGNOALYSS>1) echo \Noalyss\Dbg::hidden_info("variable", get_defined_vars());
        if ( DEBUGNOALYSS>1) echo \Noalyss\Dbg::hidden_info("this", $this);

        return;
    }
	/**
	 * return the letter C if amount is > 0, D if < 0 or =
	 * @param type $p_amount
	 * @return string
	 */
	function get_amount_side($p_amount)
		{
			if ($p_amount == 0)
				return "=";
			if ($p_amount < 0)
				return "C";
			if ($p_amount > 0)
				return "D";
		}
    /*!
     * \brief Display HTML Table Header (button)
     *
     * \return none
     */
    static function HtmlTableHeader($actiontarget="poste")
    {
        $http=new \HttpInput();
      switch($actiontarget)
	{
	case 'poste':
	  $action_csv='CSV:postedetail';
	  $action_pdf='PDF:postedetail';
	  break;
	case 'gl_comptes':
	  $action_csv='CSV:glcompte';
	  $action_pdf='PDF:glcompte';
	  break;
	default:
	  throw new Exception(" Fonction HtmlTableHeader argument actiontarget invalid");
	}
        $hid=new IHidden();

        echo "<table  >";
        echo '<TR>';
        $str_ople=(isset($_REQUEST['ople']))?HtmlInput::hidden('ople',$http->request('ople')):'';
	if ($actiontarget=='poste')
	  {
	    echo '<TD><form method="GET" ACTION="export.php">'.
	      dossier::hidden().
	      HtmlInput::submit('bt_other',"Autre poste").
	      $hid->input("type","poste").$hid->input('ac',$http->request('ac'))."</form></TD>";
	  }

        $id=uniqid("pdf_");
        echo '<TD><form method="GET" ACTION="export.php" '.
             'id="'.$id.'"  onsubmit="return download_document_form(\''.$id.'\')">'.
        dossier::hidden().
        HtmlInput::submit('bt_pdf',"Export PDF").
        HtmlInput::hidden('act',$action_pdf).
        $hid->input("type","poste").$str_ople.
        $hid->input('p_action','impress').
        $hid->input("from_periode",$http->request('from_periode')).
        $hid->input("to_periode",$http->request('to_periode'))
	  ;

	if ( isset($_REQUEST['letter'] )) echo HtmlInput::hidden('letter','2');
	if ( isset($_REQUEST['solded'] )) echo HtmlInput::hidden('solded','1');

	if (isset($_REQUEST['from_poste']))
	  echo HtmlInput::hidden('from_poste',$http->request('from_poste'));

	if (isset($_REQUEST['to_poste']))
	  echo HtmlInput::hidden('to_poste',$http->request('to_poste'));

        if (isset($_REQUEST['poste_id']))
	  echo HtmlInput::hidden("poste_id",$http->request('poste_id'));

        if (isset($_REQUEST['poste_fille']))
            echo $hid->input('poste_fille','on');
        if (isset($_REQUEST['oper_detail']))
            echo $hid->input('oper_detail','on');

        echo "</form></TD>";
        $id=uniqid("csv_");
        echo '<TD><form method="GET" ACTION="export.php" id="'.$id.'"  onsubmit="download_document_form(\''.$id.'\')">'.
        dossier::hidden().
        HtmlInput::submit('bt_csv',"Export CSV").
	HtmlInput::hidden('act',$action_csv).
        $hid->input("type","poste").$str_ople.
        $hid->input('p_action','impress').
        $hid->input("from_periode",$http->request('from_periode')).
	  $hid->input("to_periode",$http->request('to_periode'));

	if (isset($_REQUEST['from_poste']))
	  echo HtmlInput::hidden('from_poste',$http->request('from_poste'));

	if (isset($_REQUEST['to_poste']))
	  echo HtmlInput::hidden('to_poste',$http->request('to_poste'));

        if (isset($_REQUEST['poste_id']))
	  echo HtmlInput::hidden("poste_id",$http->request('poste_id'));

	if ( isset($_REQUEST['letter'] )) echo HtmlInput::hidden('letter','2');
	if ( isset($_REQUEST['solded'] )) echo HtmlInput::hidden('solded','1');

        if (isset($_REQUEST['poste_fille']))
            echo $hid->input('poste_fille','on');
        if (isset($_REQUEST['oper_detail']))
            echo $hid->input('oper_detail','on');
        if (isset($_REQUEST['poste_id'])) echo $hid->input("poste_id",$http->request('poste_id'));

        echo "</form></TD>";
	echo '<td style="vertical-align:top">';
	echo HtmlInput::print_window();
	echo '</td>';
	echo '</tr>';
        echo "</table>";


    }
    /*!
     * \brief verify that the accounting belong to a ledger
     *
     * \return 0 ok,  -1 no
     */
    function belong_ledger($p_jrn)
    {
        $filter=$this->db->get_value("select jrn_def_class_cred from jrn_def where jrn_def_id=$1", array($p_jrn));
        if ( noalyss_trim ($filter) == '')
            return 0;

        $valid_cred=explode(" ",$filter);
        $sql="select count(*) as poste from tmp_pcmn where ";
        // Creation query
        $or="";
       $SqlFilter="";
        $SqlArray = array();
        $SqlArrayN = 1;
        foreach ( $valid_cred as $item_cred)
        {
            if ( strlen (trim($item_cred)))
            {
                if ( strstr($item_cred,"*") == true )
                {
                    $SqlItem=$or . 'pcm_val::text like $' . $SqlArrayN++;
                    array_push($SqlArray, strtr($item_cred,"*","%"));
                    $or="  or ";
                }
                else
                {
                    $SqlItem=$or . 'pcm_val::text = $' . $SqlArrayN++;
                    array_push($SqlArray, $item_cred);
                    $or="  or ";
                }
                $SqlFilter=$SqlFilter.$SqlItem;
            }
        }//foreach
        $sql.=$SqlFilter . ' and pcm_val::text=$' . $SqlArrayN++;
        array_push($SqlArray, $this->id);
        $max=$this->db->get_value($sql, $SqlArray);
        if ($max > 0 )
            return 0;
        else
            return -1;
    }
    /*!\brief With the id of the ledger, get the col jrn_def_class_deb
     *\param $p_jrn jrn_id
     *\return array of value, or an empty array if nothing is found
     *\note
     *\see
     */
    function get_account_ledger($p_jrn)
    {
        $l=new Acc_Ledger($this->db,$p_jrn);
        $row=$l->get_propertie();
        if ($l->get_type() != 'ODS') { return [];}
        if ( $row == null || noalyss_strlentrim($row['jrn_def_class_deb']) == 0 ) return array();
        $valid_account=explode(" ",$row['jrn_def_class_deb']);
        return $valid_account;
    }
    /*!\brief build a sql statement thanks a array found with get_account_ledger
     *
     *\param $p_jrn jrn_id
     *\return an emty string if nothing is found or a valid SQL statement like
    \code
    pcm_val like ... or pcm_val like ...
    \endcode
     *\note
     *\see get_account_ledger
     */
    function build_sql_account($p_jrn)
    {
        $array=$this->get_account_ledger($p_jrn);
        if ( empty($array) ) return "";
        $sql="";
        foreach ( $array as $item_cred)
        {
            if ( strlen (trim($item_cred))>0 )
            {
                if ( strstr($item_cred,"*") == true )
                {
                    $item_cred=strtr($item_cred,"*","%");
                    $sql_tmp=" pcm_val::text like '$item_cred' or";
                }
                else
                {
                    $sql_tmp=" pcm_val::text = '$item_cred' or";
                }
                $sql.=$sql_tmp;
            }
        }//foreach
        /* remove the last or */
        $sql=substr($sql,0,strlen($sql)-2);
        return $sql;
    }
    /**
     * Find the id of the cards which are using the current account
     * 
     * @return an array of f_id
     */
    function find_card()
    {
            $sql="select f_id from fiche_detail where ad_id=$1 and ad_value=$2";
            $account=$this->db->get_array($sql,array(ATTR_DEF_ACCOUNT,$this->id));
            return $account;
    }
    /**
     * @brief Return a string with the HTML code to display a button to export the 
     * history in CSV
     * @param type $p_from from date (DD.MM.YYYY)
     * @param type $p_to to date (DD.MM.YYYY)
     * @return HTML string
     */
    function button_csv($p_from,$p_to) {
        $href="export.php?".http_build_query(
                array(
                    "gDossier"=>Dossier::id(),
                    "poste_id"=>$this->id,
                    "ople"=>0,
                    "type"=>"poste",
                    "from_periode"=>$p_from,
                    "to_periode"=>$p_to,
                    "act"=>"CSV:postedetail"
                    )
                );
        return '<a class="smallbutton" style="display:inline-block" href="'.$href.'">'._("Export CSV").'</a>';

    }
    /**
     * @brief Return a string with the HTML code to display a button to export the 
     * history in PDF
     * @param type $p_from from date (DD.MM.YYYY)
     * @param type $p_to to date (DD.MM.YYYY)
     * @return HTML string
     */
    function button_pdf($p_from,$p_to) {
        $href="export.php?".http_build_query(
                array(
                    "gDossier"=>Dossier::id(),
                    "poste_id"=>$this->id,
                    "ople"=>0,
                    "type"=>"poste",
                    "from_periode"=>$p_from,
                    "to_periode"=>$p_to,
                    "act"=>"PDF:postedetail"
                    )
                );
        return '<a class="smallbutton" style="display:inline-block" href="'.$href.'">'._("Export PDF").'</a>';
        
    }
    /**
     * @brief Filter in javascript the table with the history
     * @param type $p_table_id id of the table containting the data to filter
     * @return html string
     */
    function filter_history($p_table_id) {
        return _('Filtre rapide').' '.HtmlInput::filter_table($p_table_id, '0,1,2,3,4,5,6,7,8,9,10', 1);
    }

    public static function get_used_accounting($from_date, $to_date, $from_accounting, $to_accounting)
    {
        // check date
        if (isDate($from_date) != $from_date || isDate($to_date) != $to_date) {
            return array();
        }
        // build query
        $sql = "select pcm_val,pcm_lib from tmp_pcmn  
                       where pcm_val in 
                             (select j_poste from jrnx where j_date >= to_date('$from_date','DD.MM.YYYY')
    and j_date <= to_date('$to_date','DD.MM.YYYY') ) ";
        $cond_poste="";
        if ($from_accounting != '') {
            $cond_poste .= "and pcm_val >= upper ('" . Database::escape_string($from_accounting) . "')";
        }

        if ($to_accounting != '') {
            $cond_poste .= " and pcm_val <= upper ('" . Database::escape_string($to_accounting) . "')";
        }

        $sql = $sql . $cond_poste . '  order by pcm_val::text';

        // get array
        $cn=Dossier::connect();
        $a_poste = $cn->get_array($sql);
        // return array
        return $a_poste;

    }
}
