id = $p_id; $this->name = &$this->jrn_def_name; $this->jrn_def_id = &$this->id; $this->db = $p_cn; $this->row = null; $this->nb = MAX_ARTICLE; } function get_last_pj() { if ($this->db->exist_sequence("s_jrn_pj" . $this->id)) { $ret = $this->db->get_array("select last_value,is_called from s_jrn_pj" . $this->id); $last = $ret[0]['last_value']; /** * \note With PSQL sequence , the last_value column is 1 when before AND after the first call, to make the difference between them * I have to check whether the sequence has been already called or not */ if ($ret[0]['is_called'] == 'f') $last--; return $last; } else $this->db->create_sequence("s_jrn_pj" . $this->id); return 0; } /** * @brief Return the type of a ledger (ACH,VEN,ODS or FIN) or GL * */ function get_type() { if ($this->id == 0) { $this->name = _(" Tous les journaux"); $this->type = "GL"; return "GL"; } $Res = $this->db->exec_sql("select jrn_def_type from " . " jrn_def where jrn_def_id=" . $this->id); $Max = Database::num_row($Res); if ($Max == 0) return null; $ret = Database::fetch_array($Res, 0); $this->type = $ret['jrn_def_type']; return $ret['jrn_def_type']; } /** * let you delete a operation * @note by cascade it will delete also in * - jrnx * - stock * - quant_purchase * - quant_fin * - quant_sold * - operation_analytique * - letter * - reconciliation * @bug the attached document is not deleted * @bug Normally it should be named delete_operation, cause the id is the ledger_id * (jrn_def_id) and not the operation id */ function delete() { if ($this->id == 0) return; $grpt_id = $this->db->get_value('select jr_grpt_id from jrn where jr_id=$1', array($this->jr_id)); if ($this->db->count() == 0) return; $this->db->exec_sql('delete from jrnx where j_grpt=$1', array($grpt_id)); $this->db->exec_sql('delete from jrn where jr_id=$1', array($this->jr_id)); } /** * Display warning contained in an array * @return string with error message */ function display_warning($pa_msg, $p_warning) { $str = '

' . $p_warning; $str.="

    "; for ($i = 0; $i < count($pa_msg); $i++) { $str.="
  1. " . $pa_msg[$i] . "
  2. "; } $str.='
'; $str.='

'; return $str; } /** * reverse the operation by creating the opposite one, * the result is to avoid it * it must be done in * - jrn * - jrnx * - quant_fin * - quant_sold * - quant_purchase * - stock * - ANC * @param $p_date is the date of the reversed op * @exception if date is invalid or other prob * @note automatically create a reconciliation between operation * You must set the ledger_id $this->jrn_def_id * This function should be in operation or call an acc_operation object * */ function reverse($p_date) { global $g_user; try { $this->db->start(); if (!isset($this->jr_id) || $this->jr_id == '') throw new Exception(_("this->jr_id is not set ou opération inconnue")); /* check if the date is valid */ if (isDate($p_date) == null) throw new Exception(_('Date invalide') . $p_date); // if the operation is in a closed or centralized period // the operation is voided thanks the opposite operation $grp_new = $this->db->get_next_seq('s_grpt'); $seq = $this->db->get_next_seq("s_jrn"); $p_internal = $this->compute_internal_code($seq); $this->jr_grpt_id = $this->db->get_value('select jr_grpt_id from jrn where jr_id=$1', array($this->jr_id)); if ($this->db->count() == 0) throw new Exception(_("Cette opération n'existe pas")); $this->jr_internal = $this->db->get_value('select jr_internal from jrn where jr_id=$1', array($this->jr_id)); if ($this->db->count() == 0 || trim($this->jr_internal) == '') throw new Exception(_("Cette opération n'existe pas")); /* find the periode thanks the date */ $per = new Periode($this->db); $per->jrn_def_id = $this->id; $per->find_periode($p_date); if ($per->is_open() == 0) throw new Exception(_('PERIODE FERMEE')); // Mark the operation invalid into the ledger // to avoid to nullify twice the same op. $sql = "update jrn set jr_comment='extourne : '||jr_comment where jr_id=$1"; $Res = $this->db->exec_sql($sql, array($this->jr_id)); // Check return code if ($Res == false) throw new Exception(__FILE__ . __LINE__ . "sql a echoue [ $sql ]"); ////////////////////////////////////////////////// // Reverse in jrnx* tables ////////////////////////////////////////////////// $a_jid = $this->db->get_array("select j_id,j_debit from jrnx where j_grpt=$1", array($this->jr_grpt_id)); for ($l = 0; $l < count($a_jid); $l++) { $row = $a_jid[$l]['j_id']; // Make also the change into jrnx $sql = "insert into jrnx ( j_date,j_montant,j_poste,j_grpt, j_jrn_def,j_debit,j_text,j_internal,j_tech_user,j_tech_per,j_qcode ) select to_date($1,'DD.MM.YYYY'),j_montant,j_poste,$2, j_jrn_def,not (j_debit),j_text,$3,$4,$5, j_qcode from jrnx where j_id=$6 returning j_id"; $Res = $this->db->exec_sql($sql, array($p_date, $grp_new, $p_internal, $g_user->id, $per->p_id, $row)); // Check return code if ($Res == false) throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]")); $aj_id = $this->db->fetch(0); $j_id = $aj_id['j_id']; /* automatic lettering */ $let = new Lettering($this->db); $let->insert_couple($j_id, $row); // reverse in QUANT_SOLD $Res = $this->db->exec_sql("INSERT INTO quant_sold( qs_internal, qs_fiche, qs_quantite, qs_price, qs_vat, qs_vat_code, qs_client, qs_valid, j_id) SELECT $1, qs_fiche, qs_quantite*(-1), qs_price*(-1), qs_vat*(-1), qs_vat_code, qs_client, qs_valid, $2 FROM quant_sold where j_id=$3", array($p_internal, $j_id, $row)); if ($Res == false) throw new Exception(__FILE__ . __LINE__ . "sql a echoue [ $sql ]"); $Res = $this->db->exec_sql("INSERT INTO quant_purchase( qp_internal, j_id, qp_fiche, qp_quantite, qp_price, qp_vat, qp_vat_code, qp_nd_amount, qp_nd_tva, qp_nd_tva_recup, qp_supplier, qp_valid, qp_dep_priv) SELECT $1, $2, qp_fiche, qp_quantite*(-1), qp_price*(-1), qp_vat*(-1), qp_vat_code, qp_nd_amount*(-1), qp_nd_tva*(-1), qp_nd_tva_recup*(-1), qp_supplier, qp_valid, qp_dep_priv*(-1) FROM quant_purchase where j_id=$3", array($p_internal, $j_id, $row)); if ($Res == false) throw new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]"); } $sql = "insert into jrn ( jr_id, jr_def_id, jr_montant, jr_comment, jr_date, jr_grpt_id, jr_internal ,jr_tech_per, jr_valid ) select $1,jr_def_id,jr_montant,jr_comment, to_date($2,'DD.MM.YYYY'),$3,$4, $5, true from jrn where jr_id=$6"; $Res = $this->db->exec_sql($sql, array($seq, $p_date, $grp_new, $p_internal, $per->p_id, $this->jr_id)); // Check return code if ($Res == false) throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]")); // reverse in QUANT_FIN table $Res = $this->db->exec_sql(" INSERT INTO quant_fin( qf_bank, qf_other, qf_amount,jr_id) SELECT qf_bank, qf_other, qf_amount*(-1),$1 FROM quant_fin where jr_id=$2", array($seq, $this->jr_id)); if ($Res == false) throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR[ $sql ]")); // Add a "concerned operation to bound these op.together // $rec = new Acc_Reconciliation($this->db); $rec->set_jr_id($seq); $rec->insert($this->jr_id); // Check return code if ($Res == false) { throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]")); } // the table stock must updated // also in the stock table $sql = "delete from stock_goods where sg_id = any ( select sg_id from stock_goods natural join jrnx where j_grpt=" . $this->jr_grpt_id . ")"; $Res = $this->db->exec_sql($sql); if ($Res == false) throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]")); $this->db->commit(); } catch (Exception $e) { $this->db->rollback(); throw $e; } } /** * @brief Return the name of a ledger * */ function get_name() { if ($this->id == 0) { $this->name = _("Grand Livre"); return $this->name; } $Res = $this->db->exec_sql("select jrn_def_name from " . " jrn_def where jrn_def_id=$1", array($this->id)); $Max = Database::num_row($Res); if ($Max == 0) return null; $ret = Database::fetch_array($Res, 0); $this->name = $ret['jrn_def_name']; return $ret['jrn_def_name']; } /** \function get_row * @brief Get The data * * * @paramp_from from periode * @paramp_to to periode * @paramp_limit starting line * @paramp_offset number of lines * \return Array with the asked data * */ function get_row($p_from, $p_to, $p_limit = -1, $p_offset = -1) { global $g_user; $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'jr_tech_per'); $cond_limite = ($p_limit != -1) ? " limit " . $p_limit . " offset " . $p_offset : ""; // retrieve the type $this->get_type(); // Grand livre == 0 if ($this->id != 0) { $Res = $this->db->exec_sql("select jr_id,j_id,j_id as int_j_id,to_char(j_date,'DD.MM.YYYY') as j_date, jr_internal, case j_debit when 't' then j_montant::text else ' ' end as deb_montant, case j_debit when 'f' then j_montant::text else ' ' end as cred_montant, j_debit as debit,j_poste as poste,jr_montant , " . "case when j_text='' or j_text is null then pcm_lib else j_text end as description,j_grpt as grp, jr_comment||' ('||jr_internal||')' as jr_comment, jr_pj_number, j_qcode, jr_rapt as oc, j_tech_per as periode from jrnx left join jrn on " . "jr_grpt_id=j_grpt " . " left join tmp_pcmn on pcm_val=j_poste " . " where j_jrn_def=" . $this->id . " and " . $periode . " order by j_date::date asc,substring(jr_pj_number,'[0-9]+$')::numeric asc,j_grpt,j_debit desc " . $cond_limite); } else { $Res = $this->db->exec_sql("select jr_id,j_id,j_id as int_j_id,to_char(j_date,'DD.MM.YYYY') as j_date, jr_internal, case j_debit when 't' then j_montant::text else ' ' end as deb_montant, case j_debit when 'f' then j_montant::text else ' ' end as cred_montant, j_debit as debit,j_poste as poste," . "case when j_text='' or j_text is null then pcm_lib else j_text end as description,j_grpt as grp, jr_comment||' ('||jr_internal||')' as jr_comment, jr_pj_number, jr_montant, j_qcode, jr_rapt as oc, j_tech_per as periode from jrnx left join jrn on " . "jr_grpt_id=j_grpt left join tmp_pcmn on pcm_val=j_poste join jrn_def on (jr_def_id=jrn_def_id) where " . $g_user->get_ledger_sql() . " and " . " " . $periode . " order by j_date::date,substring(jr_pj_number,'[0-9]+$') asc,j_grpt,j_debit desc " . $cond_limite); } $array = array(); $Max = Database::num_row($Res); if ($Max == 0) return null; $case = ""; $tot_deb = 0; $tot_cred = 0; $row = Database::fetch_all($Res); for ($i = 0; $i < $Max; $i++) { $fiche = new Fiche($this->db); $line = $row[$i]; $mont_deb = ($line['deb_montant'] != 0) ? sprintf("% 8.2f", $line['deb_montant']) : ""; $mont_cred = ($line['cred_montant'] != 0) ? sprintf("% 8.2f", $line['cred_montant']) : ""; $jr_montant = ($line['jr_montant'] != 0) ? sprintf("% 8.2f", $line['jr_montant']) : ""; $tot_deb+=$line['deb_montant']; $tot_cred+=$line['cred_montant']; $tot_op = $line['jr_montant']; /* Check first if there is a quickcode */ if (strlen(trim($line['description'])) == 0 && strlen(trim($line['j_qcode'])) != 0) { if ($fiche->get_by_qcode($line['j_qcode'], false) == 0) { $line['description'] = $fiche->strAttribut(ATTR_DEF_NAME); } } if ($case != $line['grp']) { $case = $line['grp']; // for financial, we show if the amount is or not in negative if ($this->type == 'FIN') { $amount = $this->db->get_value('select qf_amount from quant_fin where jr_id=$1', array($line['jr_id'])); /* if nothing is found */ if ($this->db->count() == 0) $tot_op = $jr_montant; else if ($amount < 0) { $tot_op = $amount; } } $array[] = array( 'jr_id' => $line['jr_id'], 'int_j_id' => $line['int_j_id'], 'j_id' => $line['j_id'], 'j_date' => $line['j_date'], 'internal' => $line['jr_internal'], 'deb_montant' => '', 'cred_montant' => ' ', 'description' => '' . h($line['jr_comment']) . ' [' . $tot_op . '] ', 'poste' => $line['oc'], 'qcode' => $line['j_qcode'], 'periode' => $line['periode'], 'jr_pj_number' => $line ['jr_pj_number']); $array[] = array( 'jr_id' => '', 'int_j_id' => $line['int_j_id'], 'j_id' => '', 'j_date' => '', 'internal' => '', 'deb_montant' => $mont_deb, 'cred_montant' => $mont_cred, 'description' => $line['description'], 'poste' => $line['poste'], 'qcode' => $line['j_qcode'], 'periode' => $line['periode'], 'jr_pj_number' => '' ); } else { $array[] = array( 'jr_id' => $line['jr_id'], 'int_j_id' => $line['int_j_id'], 'j_id' => '', 'j_date' => '', 'internal' => '', 'deb_montant' => $mont_deb, 'cred_montant' => $mont_cred, 'description' => $line['description'], 'poste' => $line['poste'], 'qcode' => $line['j_qcode'], 'periode' => $line['periode'], 'jr_pj_number' => ''); } } $this->row = $array; $a = array($array, $tot_deb, $tot_cred); return $a; } /** @brief Get simplified row from ledger * * @param p_from periode * @param p_to periode * @param p_limit starting line * @param p_offset number of lines * @param trunc if data must be truncated (pdf export) * * \return an Array with the asked data */ function get_rowSimple($p_from, $p_to, $trunc = 0, $p_limit = -1, $p_offset = -1) { global $g_user; // Grand-livre : id= 0 //--- $jrn = ($this->id == 0 ) ? "and " . $g_user->get_ledger_sql() : "and jrn_def_id = " . $this->id; $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'jr_tech_per'); $cond_limite = ($p_limit != -1) ? " limit " . $p_limit . " offset " . $p_offset : ""; //--- $sql = " SELECT jrn.jr_id as jr_id , jrn.jr_id as num , jrn.jr_def_id as jr_def_id, jrn.jr_montant as montant, substr(jrn.jr_comment,1,35) as comment, to_char(jrn.jr_date,'DD-MM-YYYY') as date, to_char(jrn.jr_date_paid,'DD-MM-YYYY') as date_paid, jr_pj_number, jr_internal, jrn.jr_grpt_id as grpt_id, jrn.jr_pj_name as pj, jrn_def_type, jrn.jr_tech_per FROM jrn join jrn_def on (jrn_def_id=jr_def_id) WHERE $periode $jrn order by jr_date,substring(jrn.jr_pj_number,'[0-9]+$')::numeric asc $cond_limite"; $Res = $this->db->exec_sql($sql); $Max = Database::num_row($Res); if ($Max == 0) { return null; } $type = $this->get_type(); // for type ACH and Ven we take more info if ($type == 'ACH' || $type == 'VEN') { $a_ParmCode = $this->db->get_array('select p_code,p_value from parm_code'); $a_TVA = $this->db->get_array('select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0 order by tva_rate,tva_label,tva_id '); for ($i = 0; $i < $Max; $i++) { $array[$i] = Database::fetch_array($Res, $i); $p = $this->get_detail($array[$i], $type, $trunc, $a_TVA, $a_ParmCode); if ($array[$i]['dep_priv'] != 0.0) { $array[$i]['comment'].="(priv. " . $array[$i]['dep_priv'] . ")"; } } } else { $array = Database::fetch_all($Res); } return $array; } // end function get_rowSimple /** * @brief guess what the next pj should be */ function guess_pj() { $prop = $this->get_propertie(); $pj_pref = $prop["jrn_def_pj_pref"]; $pj_seq = $this->get_last_pj() + 1; return $pj_pref . $pj_seq; } /** * @brief Show all the operation * @param$sql is the sql stmt, normally created by build_search_sql * @param$offset the offset * @param$p_paid if we want to see info about payment @code // Example // Build the sql list($sql,$where)=$Ledger->build_search_sql($_GET); // Count nb of line $max_line=$this->db->count_sql($sql); $step=$_SESSION['g_pagesize']; $page=(isset($_GET['offset']))?$_GET['page']:1; $offset=(isset($_GET['offset']))?$_GET['offset']:0; // create the nav. bar $bar=navigation_bar($offset,$max_line,$step,$page); // show a part list($count,$html)= $Ledger->list_operation($sql,$offset,0); echo $html; // show nav bar echo $bar; @endcode * @see build_search_sql * @see display_search_form * @see search_form * @return HTML string */ public function list_operation_to_reconcile($sql,$p_target) { global $g_parameter, $g_user; $gDossier = dossier::id(); $limit = " LIMIT ".MAX_RECONCILE; // Sort // Count $count = $this->db->count_sql($sql); // Add the limit $sql.=" order by jr_date asc " . $limit; // Execute SQL stmt $Res = $this->db->exec_sql($sql); //starting from here we can refactor, so that instead of returning the generated HTML, //this function returns a tree structure. $r = ""; $Max = Database::num_row($Res); if ($Max == 0) return array(0, _("Aucun enregistrement trouvé")); $r.=HtmlInput::hidden("target", $p_target); $r.=''; $r.=""; $r.=""; $r.=""; if ($this->type == 'ALL') { $r.=th(_('Journal')); } $r.=''; $r.=''; $r.=th(_('Notes'), ' '); $r.=''; $r.=""; $r.=""; // Total Amount $tot = 0.0; $gDossier = dossier::id(); $str_dossier = Dossier::id(); for ($i = 0; $i < $Max; $i++) { $row = Database::fetch_array($Res, $i); if ($i % 2 == 0) $tr = ''; else $tr = ''; $r.=$tr; // Radiobox // $r.=''; //internal code // button modify $r.=""; if ($this->type == 'ALL') $r.=td($row['jrn_def_name']); // date $r.=""; // pj $r.=""; // Tiers $other = ($row['quick_code'] != '') ? '[' . $row['quick_code'] . '] ' . $row['name'] . ' ' . $row['first_name'] : ''; $r.=td($other); // comment $r.=""; $r.=td(h($row['n_text']), ' style="font-size:0.87em"'); // Amount // If the ledger is financial : // the credit must be negative and written in red $positive = 0; // Check ledger type : if ($row['jrn_def_type'] == 'FIN') { $positive = $this->db->get_value("select qf_amount from quant_fin where jr_id=$1", array($row['jr_id'])); if ($this->db->count() != 0) $positive = ($positive < 0) ? 1 : 0; } $r.=""; // Rapprochement $rec = new Acc_Reconciliation($this->db); $rec->set_jr_id($row['jr_id']); $a = $rec->get(); $r.=""; if ($row['jr_valid'] == 'f') { $r.=""; } // end row $r.=""; } $r.='
"._("Selection").""._("Internal")."'._("Date").''._("Pièce").''; $r.=th(_('tiers')); $r.=''._("Description").''._("Montant").'" . _('Concerne') . "
"; // If url contains // $href = basename($_SERVER['PHP_SELF']); $r.=sprintf('%s ', $row['jr_id'], $gDossier, $row['jr_internal']); $r.=""; $r.=$row['str_jr_date']; $r.=""; $r.=$row['jr_pj_number']; $r.=""; $tmp_jr_comment = h($row['jr_comment']); $r.=$tmp_jr_comment; $r.=""; $r.=( $positive != 0 ) ? " - " . nbm($row['jr_montant']) . "" : nbm($row['jr_montant']); $r.=""; if ($a != null) { foreach ($a as $key => $element) { $operation = new Acc_Operation($this->db); $operation->jr_id = $element; $l_amount = $this->db->get_value("select jr_montant from jrn " . " where jr_id=$element"); $r.= " " . $operation->get_internal() . "[" . nbm($l_amount) . "]"; }//for }// if ( $a != null ) { $r.=""._("Opération annulée")."
'; return array($count, $r); } /** * @brief Show all the operation * @param$sql is the sql stmt, normally created by build_search_sql * @param$offset the offset * @param$p_paid if we want to see info about payment \code // Example // Build the sql list($sql,$where)=$Ledger->build_search_sql($_GET); // Count nb of line $max_line=$cn->count_sql($sql); $step=$_SESSION['g_pagesize']; $page=(isset($_GET['offset']))?$_GET['page']:1; $offset=(isset($_GET['offset']))?$_GET['offset']:0; // create the nav. bar $bar=navigation_bar($offset,$max_line,$step,$page); // show a part list($count,$html)= $Ledger->list_operation($sql,$offset,0); echo $html; // show nav bar echo $bar; \endcode * \see build_search_sql * \see display_search_form * \see search_form * \return HTML string */ public function list_operation($sql, $offset, $p_paid = 0) { global $g_parameter, $g_user; bcscale(2); $table = new Sort_Table(); $gDossier = dossier::id(); $amount_paid = 0.0; $amount_unpaid = 0.0; $limit = ($_SESSION['g_pagesize'] != -1) ? " LIMIT " . $_SESSION['g_pagesize'] : ""; $offset = ($_SESSION['g_pagesize'] != -1) ? " OFFSET " . Database::escape_string($offset) : ""; $order = " order by jr_date_order asc,jr_internal asc"; // Sort $url = "?" . CleanUrl(); $str_dossier = dossier::get(); $table->add(_("Date"), $url, 'order by jr_date asc,substring(jr_pj_number,\'[0-9]+$\')::numeric asc', 'order by jr_date desc,substring(jr_pj_number,\'[0-9]+$\')::numeric desc', "da", "dd"); $table->add(_('Echeance'), $url, " order by jr_ech asc", " order by jr_ech desc", 'ea', 'ed'); $table->add(_('Paiement'), $url, " order by jr_date_paid asc", " order by jr_date_paid desc", 'eap', 'edp'); $table->add(_('Pièce'), $url, ' order by substring(jr_pj_number,\'[0-9]+$\')::numeric asc ', ' order by substring(jr_pj_number,\'[0-9]+$\')::numeric desc ', "pja", "pjd"); $table->add(_('Tiers'), $url, " order by name asc", " order by name desc", 'na', 'nd'); $table->add(_('Montant'), $url, " order by jr_montant asc", " order by jr_montant desc", "ma", "md"); $table->add(_("Description"), $url, "order by jr_comment asc", "order by jr_comment desc", "ca", "cd"); $ord = (!isset($_GET['ord'])) ? 'da' : $_GET['ord']; $order = $table->get_sql_order($ord); // Count $count = $this->db->count_sql($sql); // Add the limit $sql.=$order . $limit . $offset; // Execute SQL stmt $Res = $this->db->exec_sql($sql); //starting from here we can refactor, so that instead of returning the generated HTML, //this function returns a tree structure. $r = ""; $Max = Database::num_row($Res); if ($Max == 0) return array(0, _("Aucun enregistrement trouvé")); $r.=''; $r.=""; $r.=""; if ($this->type == 'ALL') { $r.=th('Journal'); } $r.=''; if ($p_paid != 0 ) $r.=''; $r.=''; $r.=''; $r.=''; $r.=th('Notes', ' style="width:15%"'); $r.=''; // if $p_paid is not equal to 0 then we have a paid column if ($p_paid != 0) { $r.=""; } $r.=""; $r.=""; $r.=""; // Total Amount $tot = 0.0; $gDossier = dossier::id(); for ($i = 0; $i < $Max; $i++) { $row = Database::fetch_array($Res, $i); if ($i % 2 == 0) $tr = ''; else $tr = ''; $r.=$tr; //internal code // button modify $r.=""; if ($this->type == 'ALL') $r.=td($row['jrn_def_name']); // date $r.=""; // echeance if ($p_paid != 0 ) { $r.=""; $r.=""; } // pj $r.=""; // Tiers $other = ($row['quick_code'] != '') ? '[' . $row['quick_code'] . '] ' . $row['name'] . ' ' . $row['first_name'] : ''; $r.=td($other); // comment $r.=""; $r.=td(h($row['n_text']), ' style="font-size:0.87em%"'); // Amount // If the ledger is financial : // the credit must be negative and written in red $positive = 0; // Check ledger type : if ($row['jrn_def_type'] == 'FIN') { $positive = $this->db->get_value("select qf_amount from quant_fin where jr_id=$1", array($row['jr_id'])); if ($this->db->count() != 0) $positive = ($positive < 0) ? 1 : 0; } $r.=""; // Show the paid column if p_paid is not null if ($p_paid != 0) { $w = new ICheckBox(); $w->name = "rd_paid" . $row['jr_id']; $w->selected = ($row['jr_rapt'] == 'paid') ? true : false; // if p_paid == 2 then readonly $w->readonly = ( $p_paid == 2) ? true : false; $h = new IHidden(); $h->name = "set_jr_id" . $row['jr_id']; $r.=''; if ($row['jr_rapt'] == 'paid') $amount_paid=bcadd($amount_paid,$t_amount); else $amount_unpaid=bcadd($amount_unpaid,$t_amount); } // Rapprochement $rec = new Acc_Reconciliation($this->db); $rec->set_jr_id($row['jr_id']); $a = $rec->get(); $r.=""; if ($row['jr_valid'] == 'f') { $r.=""; } else { } // else //document if ($row['jr_pj_name'] != "") { $r.=''; } else $r.=""; // end row $r.=""; } $amount_paid = round($amount_paid, 4); $amount_unpaid = round($amount_unpaid, 4); $tot = round($tot, 4); $r.=""; $r.=''; $r.='"; $r.=""; if ($p_paid != 0) { $r.=""; $r.=''; $r.='"; $r.=""; $r.=""; $r.=''; $r.='"; $r.=""; } $r.="
"._("n° interne")."' . $table->get_header(0) . '' . $table->get_header(1) . ''; if ($p_paid != 0 ) $r.='' . $table->get_header(2) . '' . $table->get_header(3) . '' . $table->get_header(4) . '' . $table->get_header(6) . '' . $table->get_header(5) . ' " . _('Payé') . "" . _('Concerne') . "" . _('Document') . "
"; // If url contains // $href = basename($_SERVER['PHP_SELF']); $r.=sprintf('%s ', $row['jr_id'], $gDossier, $row['jr_internal']); $r.=""; $r.=$row['str_jr_date']; $r.=""; $r.=$row['str_jr_ech']; $r.=""; $r.=$row['str_jr_date_paid']; $r.=""; $r.=$row['jr_pj_number']; $r.=""; $tmp_jr_comment = h($row['jr_comment']); $r.=$tmp_jr_comment; $r.=""; $t_amount=$row['jr_montant']; if ($row['total_invoice'] != null && $row['total_invoice'] != $row['jr_montant']) $t_amount=$row['total_invoice']; $tot = ($positive != 0) ? bcsub($tot , $t_amount ): bcadd($tot , $t_amount); //STAN $positive always == 0 if ($row [ 'jrn_def_type']=='FIN') { $r.=( $positive != 0 ) ? " - " . nbm($t_amount) . "" : nbm($t_amount); } else { $r.=( $t_amount < 0 ) ? " " . nbm($t_amount) . "" : nbm($t_amount); } $r.="' . $w->input() . $h->input() . '"; if ($a != null) { foreach ($a as $key => $element) { $operation = new Acc_Operation($this->db); $operation->jr_id = $element; $l_amount = $this->db->get_value("select jr_montant from jrn " . " where jr_id=$element"); $r.= " " . $operation->get_internal() . "[" . nbm($l_amount) . "]"; }//for }// if ( $a != null ) { $r.=""._("Opération annulée")."'.HtmlInput::show_receipt_document($row['jr_id']).'
Total' . nbm($tot) . "
'._("Payé").'' . nbm($amount_paid) . "
'._("Non payé").'' . nbm($amount_unpaid) . "
"; return array($count, $r); } /** * @brief get_detail gives the detail of row * this array must contains at least the field * * the following field will be added * * * @paramp_array the structure is set in get_rowSimple, this array is * modified, * @param $trunc if the data must be truncated, usefull for pdf export * @paramp_jrn_type is the type of the ledger (ACH or VEN) * @param $a_TVA TVA Array (default null) * @param $a_ParmCode Array (default null) * \return p_array */ function get_detail(&$p_array, $p_jrn_type, $trunc = 0, $a_TVA = null, $a_ParmCode = null) { bcscale(2); if ($a_TVA == null) { //Load TVA array $a_TVA = $this->db->get_array('select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0 order by tva_rate,tva_label,tva_id'); } if ($a_ParmCode == null) { //Load Parm_code $a_ParmCode = $this->db->get_array('select p_code,p_value from parm_code'); } // init $p_array['client'] = ""; $p_array['TVAC'] = 0; $p_array['TVA'] = array(); $p_array['AMOUNT_TVA'] = 0.0; $p_array['dep_priv'] = 0; $p_array['dna'] = 0; $p_array['tva_dna'] = 0; $p_array['tva_np'] = 0; $dep_priv = 0.0; // // Retrieve data from jrnx $sql = "select j_id,j_poste,j_montant, j_debit,j_qcode from jrnx where " . " j_grpt=" . $p_array['grpt_id']; $Res2 = $this->db->exec_sql($sql); $data_jrnx = Database::fetch_all($Res2); $c = 0; // Parse data from jrnx and fill diff. field foreach ($data_jrnx as $code) { $idx_tva = 0; $poste = new Acc_Account_Ledger($this->db, $code['j_poste']); // if card retrieve name if the account is not a VAT account if (strlen(trim($code['j_qcode'])) != 0 && $poste->isTva() == 0) { $fiche = new Fiche($this->db); $fiche->get_by_qcode(trim($code['j_qcode']), false); $fiche_def_id = $fiche->get_fiche_def_ref_id(); // Customer or supplier if ($fiche_def_id == FICHE_TYPE_CLIENT || $fiche_def_id == FICHE_TYPE_FOURNISSEUR ||$fiche_def_id == FICHE_TYPE_ADM_TAX) { $p_array['TVAC'] = $code['j_montant']; $p_array['client'] = ($trunc == 0) ? $fiche->getName() : mb_substr($fiche->getName(), 0, 20); $p_array['reversed'] = false; if ($fiche_def_id == FICHE_TYPE_CLIENT && $code['j_debit'] == 'f') { $p_array['reversed'] = true; $p_array['TVAC']*=-1; } if ($fiche_def_id == FICHE_TYPE_ADM_TAX && $code['j_debit'] == 'f') { $p_array['reversed'] = true; $p_array['TVAC']*=-1; } if ($fiche_def_id == FICHE_TYPE_FOURNISSEUR && $code['j_debit'] == 't') { $p_array['reversed'] = true; $p_array['TVAC']*=-1; } } else { // if we use the ledger ven / ach for others card than supplier and customer if ($fiche_def_id != FICHE_TYPE_VENTE && $fiche_def_id != FICHE_TYPE_ACH_MAR && $fiche_def_id != FICHE_TYPE_ACH_SER && $fiche_def_id != FICHE_TYPE_ACH_MAT ) { $p_array['TVAC'] = $code['j_montant']; $p_array['client'] = ($trunc == 0) ? $fiche->getName() : mb_substr($fiche->getName(), 0, 20); $p_array['reversed'] = false; if ($p_jrn_type == 'ACH' && $code['j_debit'] == 't') { $p_array['reversed'] = true; $p_array['TVAC']*=-1; } if ($p_jrn_type == 'VEN' && $code['j_debit'] == 'f') { $p_array['reversed'] = true; $p_array['TVAC']*=-1; } } } } // if TVA, load amount, tva id and rate in array foreach ($a_TVA as $line_tva) { list($tva_deb, $tva_cred) = explode(',', $line_tva['tva_poste']); if ($code['j_poste'] == $tva_deb || $code['j_poste'] == $tva_cred) { // For the reversed operation if ($p_jrn_type == 'ACH' && $code['j_debit'] == 'f') { $code['j_montant'] = -1 * $code['j_montant']; } if ($p_jrn_type == 'VEN' && $code['j_debit'] == 't') { $code['j_montant'] = -1 * $code['j_montant']; } $p_array['AMOUNT_TVA']+=$code['j_montant']; $p_array['TVA'][$c] = array($idx_tva, array($line_tva['tva_id'], $line_tva['tva_label'], $code['j_montant'])); $c++; $idx_tva++; } } // isDNA // If operation is reversed then amount are negatif /* if ND */ if ($p_array['jrn_def_type'] == 'ACH') { $purchase = new Gestion_Purchase($this->db); $purchase->search_by_jid($code['j_id']); $purchase->load(); $dep_priv+=$purchase->qp_dep_priv; $p_array['dep_priv'] = $dep_priv; $p_array['dna']=bcadd($p_array['dna'],$purchase->qp_nd_amount); $p_array['tva_dna']=bcadd($p_array['tva_dna'],bcadd($purchase->qp_nd_tva,$purchase->qp_nd_tva_recup)); $p_array['tva_np']=bcadd($purchase->qp_vat_sided,$p_array['tva_np']); } if ($p_array['jrn_def_type'] == 'VEN') { $sold=new gestion_sold($this->db); $sold->search_by_jid($code['j_id']); $sold->load(); $p_array['tva_np']=bcadd($sold->qs_vat_sided,$p_array['tva_np']); } } $p_array['TVAC'] = sprintf('% 10.2f', $p_array['TVAC'] ); $p_array['HTVA'] = sprintf('% 10.2f', $p_array['TVAC'] - $p_array['AMOUNT_TVA']-$p_array['tva_dna']); $r = ""; $a_tva_amount = array(); // inline TVA (used for the PDF) foreach ($p_array['TVA'] as $linetva) { foreach ($a_TVA as $tva) { if ($tva['tva_id'] == $linetva[1][0]) { $a = $tva['tva_id']; $a_tva_amount[$a] = $linetva[1][2]; } } } foreach ($a_TVA as $line_tva) { $a = $line_tva['tva_id']; if (isset($a_tva_amount[$a])) { $tmp = sprintf("% 10.2f", $a_tva_amount[$a]); $r.="$tmp"; } else $r.=sprintf("% 10.2f", 0); } $p_array['TVA_INLINE'] = $r; return $p_array; } // retrieve data from jrnx /** * @brief Get the properties of a journal * * \return an array containing properties * */ function get_propertie() { if ($this->id == 0) return; $Res = $this->db->exec_sql("select jrn_Def_id,jrn_def_name,jrn_def_class_deb,jrn_def_class_cred,jrn_def_type, jrn_deb_max_line,jrn_cred_max_line,jrn_def_ech,jrn_def_ech_lib,jrn_def_code, jrn_def_fiche_deb,jrn_def_fiche_cred,jrn_def_pj_pref from jrn_Def where jrn_def_id=$1", array($this->id)); $Count = Database::num_row($Res); if ($Count == 0) { echo '

' . _('Parametres journaux non trouves') . '

'; return null; } return Database::fetch_array($Res, 0); } /** \function GetDefLine * @brief Get the number of lines of a journal * @param$p_cred deb or cred * * \return an integer */ function GetDefLine() { $sql_cred = 'jrn_deb_max_line'; $sql = "select jrn_deb_max_line as value from jrn_def where jrn_def_id=$1"; $r = $this->db->exec_sql($sql, array($this->id)); $Res = Database::fetch_all($r); if (sizeof($Res) == 0) return 1; return $Res[0]['value']; } /** * @brief get the saldo of a ledger for a specific period * @param$p_from start period * @param$p_to end period */ function get_solde($p_from, $p_to) { $ledger = ""; if ($this->id != 0) { $ledger = " and j_jrn_def = " . $this->id; } $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'j_tech_per'); $sql = 'select j_montant as montant,j_debit as deb from jrnx where ' . $periode . $ledger; $ret = $this->db->exec_sql($sql); $array = Database::fetch_all($ret); $deb = 0.0; $cred = 0.0; foreach ($array as $line) { if ($line['deb'] == 't') $deb+=$line['montant']; else $cred+=$line['montant']; } $response = array($deb, $cred); return $response; } /** * @brief Show a select list of the ledgers you can access in * writing, reading or simply accessing. * @param$p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS) * @param$p_access =3 for READ and WRITE, 2 for write and 1 for readonly * \return object HtmlInput select */ function select_ledger($p_type = "ALL", $p_access = 3) { global $g_user; $array = $g_user->get_ledger($p_type, $p_access); if ($array == null) return null; $idx = 0; $ret = array(); foreach ($array as $value) { $ret[$idx]['value'] = $value['jrn_def_id']; $ret[$idx]['label'] = h($value['jrn_def_name']); $idx++; } $select = new ISelect(); $select->name = 'p_jrn'; $select->value = $ret; $select->selected = $this->id; return $select; } /** * @brief retrieve the jrn_def_fiche and return them into a array * index deb, cred * \param * \param * \param * * * \return return an array ('deb'=> ,'cred'=>) */ function get_fiche_def() { $sql = "select jrn_def_fiche_deb as deb,jrn_def_fiche_cred as cred " . " from jrn_def where " . " jrn_def_id = $1 "; $r = $this->db->exec_sql($sql, array($this->id)); $res = Database::fetch_all($r); if (empty($res)) return null; return $res[0]; } /** * @brief retrieve the jrn_def_class_deb and return it * * * \return return an string */ function get_class_def() { $sql = "select jrn_def_class_deb " . " from jrn_def where " . " jrn_def_id = $1"; $r = $this->db->exec_sql($sql, array($this->id)); $res = Database::fetch_all($r); if (empty($res)) return null; return $res[0]; } /** * @brief show the result of the array to confirm * before inserting * @param$p_array array from the form * \return string */ function confirm($p_array, $p_readonly = false) { global $g_parameter; $msg = array(); if (!$p_readonly) $msg = $this->verify($p_array); $this->id = $p_array['p_jrn']; if (empty($p_array)) return 'Aucun résultat'; $anc = null; extract($p_array); $lPeriode = new Periode($this->db); if ($this->check_periode() == true) { $lPeriode->p_id = $period; } else { $lPeriode->find_periode($e_date); } $total_deb = 0; $total_cred = 0; bcscale(2); $ret = ""; if (!empty($msg)) { $ret.=$this->display_warning($msg, _("Attention : il vaut mieux utiliser les fiches que les postes comptables")); } $ret.=""; $ret.=""; /* display periode */ $date_limit = $lPeriode->get_date_limit(); $ret.=' ' . td(_('Période Comptable')) . td($date_limit['p_start'] . '-' . $date_limit['p_end']) . ''; $ret.=""; $ret.=""; $ret.='
" . _('Date') . " : $e_date
" . _('Libellé') . " " . h($desc) . "
" . _('PJ Num') . " " . h($e_pj) . "
'; $ret.=""; $ret.=""; $ret.=""; $ret.=""; $ret.=""; $ret.=""; /* if we use the AC */ if ($g_parameter->MY_ANALYTIC != 'nu') { $anc = new Anc_Plan($this->db); $a_anc = $anc->get_list(); $x = count($a_anc); /* set the width of the col */ $ret.=''; /* add hidden variables pa[] to hold the value of pa_id */ $ret.=Anc_Plan::hidden($a_anc); } $ret.=""; $ret.=HtmlInput::hidden('e_date', $e_date); $ret.=HtmlInput::hidden('desc', $desc); $ret.=HtmlInput::hidden('period', $lPeriode->p_id); $ret.=HtmlInput::hidden('e_pj', $e_pj); $ret.=HtmlInput::hidden('e_pj_suggest', $e_pj_suggest); $mt = microtime(true); $ret.=HtmlInput::hidden('mt', $mt); // For predefined operation $ret.=HtmlInput::hidden('e_comm', $desc); $ret.=HtmlInput::hidden('jrn_type', $this->get_type()); $ret.=HtmlInput::hidden('p_jrn', $this->id); $ret.=HtmlInput::hidden('nb_item', $nb_item); if ($this->with_concerned == true) { $ret.=HtmlInput::hidden('jrn_concerned', $jrn_concerned); } $ret.=dossier::hidden(); $count = 0; for ($i = 0; $i < $nb_item; $i++) { if ($p_readonly == true) { if (!isset(${'qc_' . $i})) ${'qc_' . $i} = ''; if (!isset(${'poste' . $i})) ${'poste' . $i} = ''; if (!isset(${'amount' . $i})) ${'amount' . $i} = ''; } $class=($i%2==0)?' class="even" ':' class="odd" '; $ret.=" "; if (trim(${'qc_' . $i}) != "") { $oqc = new Fiche($this->db); $oqc->get_by_qcode(${'qc_' . $i}, false); $strPoste = $oqc->strAttribut(ATTR_DEF_ACCOUNT); $ret.="'; } if (trim(${'qc_' . $i}) == "" && trim(${'poste' . $i}) != "") { $oposte = new Acc_Account_Ledger($this->db, ${'poste' . $i}); $strPoste = $oposte->id; $ret.="'; } if (trim(${'qc_' . $i}) == "" && trim(${'poste' . $i}) == "") continue; $ret.=""; if (isset(${"ck$i"})) { $ret.="" . td(""); $total_deb = bcadd($total_deb, ${'amount' . $i}); } else { $ret.=td("") . ""; $total_cred = bcadd($total_cred, ${"amount" . $i}); } /*$ret.="";*/ // CA if ($g_parameter->MY_ANALYTIC != 'nu') // use of AA { if (preg_match("/^[6,7]+/", $strPoste) == 1) { // show form $op = new Anc_Operation($this->db); $null = ($g_parameter->MY_ANALYTIC == 'op') ? 1 : 0; $p_array['pa_id'] = $a_anc; /* op is the operation it contains either a sequence or a jrnx.j_id */ $ret.=HtmlInput::hidden('op[]=', $i); $ret.=''; $count++; } } $ret.=""; } $ret.=tr(td('') . td(_('Totaux')) . td($total_deb, 'class="num"') . td($total_cred, 'class="num"'), 'class="highlight"'); $ret.="
" . _('Quick Code ou '); $ret.=_("Poste") . " " . _("Libellé") . " " . _("Débit") . "" . _("Crédit") . "' . _('Compt. Analytique') . '
" . ${'qc_' . $i} . ' - ' . $oqc->strAttribut(ATTR_DEF_NAME) . HtmlInput::hidden('qc_' . $i, ${'qc_' . $i}) . '" . h(${"poste" . $i} . " - " . $oposte->get_name()) . HtmlInput::hidden('poste' . $i, ${'poste' . $i}) . '" . h(${"ld" . $i}) . HtmlInput::hidden('ld' . $i, ${'ld' . $i}) ; $ret .=(isset(${"ck$i"})) ? HtmlInput::hidden('ck' . $i, ${'ck' . $i}) : ""; $ret .= "" . nbm(${"amount" . $i}) . HtmlInput::hidden('amount' . $i, ${'amount' . $i}) . "" . nbm(${"amount" . $i}) . HtmlInput::hidden('amount' . $i, ${'amount' . $i}) . ""; $ret.=(isset(${"ck$i"})) ? HtmlInput::hidden('ck' . $i, ${'ck' . $i}) : ""; $ret.="'; $read = ($p_readonly == true) ? 0 : 1; $ret.=$op->display_form_plan($p_array, $null, $read, $count, round(${'amount' . $i}, 2)); $ret.='
"; if ($g_parameter->MY_ANALYTIC != 'nu' && $p_readonly == false) $ret.=''; return $ret; } function get_min_row() { $row=$this->db->get_value("select jrn_deb_max_line from jrn_def where jrn_def_id=$1",array($this->id)); return $row; } /** * @brief Show the form to encode your operation * @param$p_array if you correct or use a predef operation (default = null) * @param$p_readonly 1 for readonly 0 for writable (default 0) *@exception if ledger not found * \return a string containing the form */ function input($p_array = null, $p_readonly = 0) { global $g_parameter, $g_user; $this->nb=$this->get_min_row(); if ($p_readonly == 1) return $this->confirm($p_array); if ($p_array != null) extract($p_array); $add_js = ""; if ($g_parameter->MY_PJ_SUGGEST == 'Y') { $add_js = "update_pj();"; } if ($g_parameter->MY_DATE_SUGGEST=='Y') { $add_js.='get_last_date();'; } $add_js.='update_row("quick_item");'; $ret = ""; if ($g_user->check_action(FICADD) == 1) { /* Add button */ $f_add_button = new IButton('add_card'); $f_add_button->label = _('Créer une nouvelle fiche'); $f_add_button->set_attribute('ipopup', 'ipop_newcard'); $f_add_button->set_attribute('jrn', $this->id); $f_add_button->javascript = " this.jrn=\$('p_jrn').value;select_card_type(this);"; $f_add_button->input(); } $wLedger = $this->select_ledger('ODS', 2); if ($wLedger == null) throw new Exception(_('Pas de journal disponible')); $wLedger->javascript = "onChange='update_name();update_predef(\"ods\",\"t\",\"".$_REQUEST['ac']."\");$add_js'"; $label = " Journal " . HtmlInput::infobulle(2); $ret.=$label . $wLedger->input(); // Load the javascript // $ret.=""; $ret.= ''; /* insert periode if needed */ // Periode //-- if ($this->check_periode() == true) { $l_user_per = $g_user->get_periode(); $def = (isset($periode)) ? $periode : $l_user_per; $period = new IPeriod("period"); $period->user = $g_user; $period->cn = $this->db; $period->value = $def; $period->type = OPEN; try { $l_form_per = $period->input(); } catch (Exception $e) { if ($e->getCode() == 1) { echo _("Aucune période ouverte"); exit(); } } $label = HtmlInput::infobulle(3); $f_periode = _("Période comptable") . " $label " . $l_form_per; $ret.=td($f_periode); } $wPJ = new IText('e_pj'); $wPJ->readonly = false; $wPJ->size = 10; /* suggest PJ ? */ $default_pj = ''; if ($g_parameter->MY_PJ_SUGGEST == 'Y') { $default_pj = $this->guess_pj(); } $wPJ->value = (isset($e_pj)) ? $e_pj : $default_pj; $ret.= ''; $ret.=''; $ret.=''; $ret.= ''; $ret.= ''; $ret.=''; $ret.=''; $ret.= '
'; $wDate = new IDate('e_date'); $wDate->readonly = $p_readonly; $e_date = (isset($e_date) && trim($e_date) != '') ? $e_date : ''; $wDate->value = $e_date; $ret.=_("Date") . ' : ' . $wDate->input(); $ret.= '
' . _('Pièce') . ' : ' . $wPJ->input(); $ret.=HtmlInput::hidden('e_pj_suggest', $default_pj); $ret.= '
'; $ret.=_('Libellé'); $wDescription = new IText('desc'); $wDescription->readonly = $p_readonly; $wDescription->size = "50"; $wDescription->value = (isset($desc)) ? $desc : ''; $ret.=$wDescription->input(); $ret.= '
'; $nb_row = (isset($nb_item) ) ? $nb_item : $this->nb; $ret.=HtmlInput::hidden('nb_item', $nb_row); $ret.=dossier::hidden(); $ret.=dossier::hidden(); $ret.=HtmlInput::hidden('jrn_type', $this->get_type()); $info = HtmlInput::infobulle(0); $info_poste = HtmlInput::infobulle(9); if ($g_user->check_action(FICADD) == 1) $ret.=$f_add_button->input(); $ret.=''; $ret.='' . '' . '' . '' . '' . '' . ''; for ($i = 0; $i < $nb_row; $i++) { // Quick Code $quick_code = new ICard('qc_' . $i); $quick_code->set_dblclick("fill_ipopcard(this);"); $quick_code->set_attribute('ipopup', 'ipopcard'); // name of the field to update with the name of the card $quick_code->set_attribute('label', "ld" . $i); // name of the field to update with the name of the card $quick_code->set_attribute('typecard', 'filter'); // Add the callback function to filter the card on the jrn $quick_code->set_callback('filter_card'); $quick_code->set_function('fill_data'); $quick_code->javascript = sprintf(' onchange="fill_data_onchange(\'%s\');" ', $quick_code->name); $quick_code->value = (isset(${'qc_' . $i})) ? ${'qc_' . $i} : ""; $quick_code->readonly = $p_readonly; $label = ''; if ($quick_code->value != '') { $Fiche = new Fiche($this->db); $Fiche->get_by_qcode($quick_code->value); $label = $Fiche->strAttribut(ATTR_DEF_NAME); } // Account $poste = new IPoste(); $poste->name = 'poste' . $i; $poste->set_attribute('jrn', $this->id); $poste->set_attribute('ipopup', 'ipop_account'); $poste->set_attribute('label', 'ld' . $i); $poste->set_attribute('account', 'poste' . $i); $poste->set_attribute('dossier', Dossier::id()); $poste->value = (isset(${'poste' . $i})) ? ${"poste" . $i} : '' ; $poste->dbl_click_history(); $poste->readonly = $p_readonly; if ($poste->value != '') { $Poste = new Acc_Account($this->db); $Poste->set_parameter('value', $poste->value); $label = $Poste->get_lib(); } // Description of the line $line_desc = new IText(); $line_desc->name = 'ld' . $i; $line_desc->size = 30; $line_desc->value = (isset(${"ld" . $i})) ? ${"ld" . $i} : $label; // Amount $amount = new INum(); $amount->size = 10; $amount->name = 'amount' . $i; $amount->value = (isset(${'amount' . $i})) ? ${"amount" . $i} : '' ; $amount->readonly = $p_readonly; $amount->javascript = ' onChange="format_number(this);checkTotalDirect()"'; // D/C $deb = new ICheckBox(); $deb->name = 'ck' . $i; $deb->selected = (isset(${'ck' . $i})) ? true : false; $deb->readonly = $p_readonly; $deb->javascript = ' onChange="checkTotalDirect()"'; $ret.=''; $ret.=''; $ret.=''; $ret.=''; $ret.=''; $ret.=''; $ret.=''; // If readonly == 1 then show CA } $ret.='
Quickcode' . $info . '' . _('Poste') . $info_poste . '' . _('Libellé') . '' . _('Montant') . '' . _('Débit') . '
' . $quick_code->input() . $quick_code->search() . '' . $poste->input() . '' . '' . $line_desc->input() . '' . $amount->input() . '' . $deb->input() . '
'; if (isset($this->with_concerned) && $this->with_concerned == true) { $oRapt = new Acc_Reconciliation($this->db); $w = $oRapt->widget(); $w->name = 'jrn_concerned'; $w->value = (isset($jrn_concerned)) ? $jrn_concerned : ""; $ret.="Réconciliation/rapprochements : " . $w->input(); } $ret.= create_script("$('".$wDate->id."').focus()"); return $ret; } /** * @brief * check if the current ledger is closed * \return 1 for yes, otherwise 0 * \see Periode::is_closed */ function is_closed($p_periode) { $per = new Periode($this->db); $per->set_jrn($this->id); $per->set_periode($p_periode); $ret = $per->is_closed(); return $ret; } /** * @brief verify that the operation can be saved * @param$p_array array of data same layout that the $_POST from show_form * * * \throw the getcode value is 1 incorrect balance, 2 date * invalid, 3 invalid amount, 4 the card is not in the range of * permitted card, 5 not in the user's period, 6 closed period * */ function verify($p_array) { if (is_array($p_array ) == false || empty($p_array)) throw new Exception ("Array empty"); /* * Check needed value */ check_parameter($p_array,'p_jrn,e_date'); extract($p_array); global $g_user; $tot_cred = 0; $tot_deb = 0; $msg = array(); /* check if we can write into this ledger */ if ($g_user->check_jrn($p_jrn) != 'W') throw new Exception(_('Accès interdit'), 20); /* check for a double reload */ if (isset($mt) && $this->db->count_sql('select jr_mt from jrn where jr_mt=$1', array($mt)) != 0) throw new Exception('Double Encodage', 5); // Check the periode and the date if (isDate($e_date) == null) { throw new Exception('Date invalide', 2); } $periode = new Periode($this->db); /* find the periode if we have enabled the check_periode */ if ($this->check_periode() == false) { $periode->find_periode($e_date); } else { $periode->p_id = $period; list ($min, $max) = $periode->get_date_limit(); if (cmpDate($e_date, $min) < 0 || cmpDate($e_date, $max) > 0) throw new Exception(_('Date et periode ne correspondent pas'), 6); } // Periode ferme if ($this->is_closed($periode->p_id) == 1) { throw new Exception('Periode fermee', 6); } /* check if we are using the strict mode */ if ($this->check_strict() == true) { /* if we use the strict mode, we get the date of the last operation */ $last_date = $this->get_last_date(); if ($last_date != null && cmpDate($e_date, $last_date) < 0) throw new Exception(_('Vous utilisez le mode strict la dernière operation est la date du ') . $last_date . ' ' . _('vous ne pouvez pas encoder à une date antérieure'), 15); } for ($i = 0; $i < $nb_item; $i++) { $err = 0; // Check the balance if (!isset(${'amount' . $i})) continue; $amount = round(${'amount' . $i}, 2); $tot_deb+=(isset(${'ck' . $i})) ? $amount : 0; $tot_cred+=(!isset(${'ck' . $i})) ? $amount : 0; // Check if the card is permitted if (isset(${'qc_' . $i}) && trim(${'qc_' . $i}) != "") { $f = new Fiche($this->db); $f->quick_code = ${'qc_' . $i}; if ($f->belong_ledger($p_jrn) < 0) throw new Exception("La fiche quick_code = " . $f->quick_code . " n'est pas dans ce journal", 4); if (strlen(trim(${'qc_' . $i})) != 0 && isNumber(${'amount' . $i}) == 0) throw new Exception('Montant invalide', 3); $strPoste = $f->strAttribut(ATTR_DEF_ACCOUNT); if ($strPoste == '') throw new Exception(sprintf(_("La fiche %s n'a pas de poste comptable"), ${"qc_" . $i})); $p = new Acc_Account_Ledger($this->db, $strPoste); if ($p->do_exist() == 0) throw new Exception(_('Poste Inexistant pour la fiche [' . ${'qc_' . $i} . ']'), 4); } // Check if the account is permitted if (isset(${'poste' . $i}) && strlen(trim(${'poste' . $i})) != 0) { $p = new Acc_Account_Ledger($this->db, ${'poste' . $i}); if ($p->belong_ledger($p_jrn) < 0) throw new Exception(_("Le poste") . " " . $p->id . " " . _("n'est pas dans ce journal"), 5); if (strlen(trim(${'poste' . $i})) != 0 && isNumber(${'amount' . $i}) == 0) throw new Exception(_('Poste invalide [' . ${'poste' . $i} . ']'), 3); if ($p->do_exist() == 0) throw new Exception(_('Poste Inexistant [' . ${'poste' . $i} . ']'), 4); $card_id = $p->find_card(); if (!empty($card_id)) { $str_msg = " Le poste " . $p->id . " appartient à " . count($card_id) . " fiche(s) dont :"; $max = (count($card_id) > MAX_COMPTE_CARD) ? MAX_COMPTE_CARD : count($card_id); for ($x = 0; $x < $max; $x++) { $card = new Fiche($this->db, $card_id[$x]['f_id']); $str_msg.=HtmlInput::card_detail($card->strAttribut(ATTR_DEF_QUICKCODE), $card->strAttribut(ATTR_DEF_NAME), 'style="color:red;display:inline;text-decoration:underline"'); $str_msg.=" "; } $msg[] = $str_msg; } } } $tot_deb = round($tot_deb, 4); $tot_cred = round($tot_cred, 4); if ($tot_deb != $tot_cred) { throw new Exception(_("Balance incorrecte ") . " debit = $tot_deb credit=$tot_cred ", 1); } return $msg; } /** * @brief compute the internal code of the saved operation and set the $this->jr_internal to * the computed value * * @param$p_grpt id in jr_grpt_ * * \return string internal_code * - * */ function compute_internal_code($p_grpt) { if ($this->id == 0) return; $num = $this->db->get_next_seq('s_internal'); $atype = $this->get_propertie(); $type = substr($atype['jrn_def_code'], 0, 1); $internal_code = sprintf("%s%06X", $type, $num); $this->jr_internal = $internal_code; return $internal_code; } /** * @brief save the operation into the jrnx,jrn, , * CA and pre_def * @param$p_array * * \return array with [0] = false if failed otherwise true, [1] error * code */ function save($p_array = null) { if ($p_array == null) throw new Exception('save cannot use a empty array'); global $g_parameter; extract($p_array); try { $msg = $this->verify($p_array); if (!empty($msg)) { echo $this->display_warning($msg, _("Attention : il vaut mieux utiliser les fiches que les postes comptables ")); } $this->db->start(); $seq = $this->db->get_next_seq('s_grpt'); $internal = $this->compute_internal_code($seq); $group = $this->db->get_next_seq("s_oa_group"); $tot_amount = 0; $tot_deb = 0; $tot_cred = 0; $oPeriode = new Periode($this->db); $check_periode = $this->check_periode(); if ($check_periode == false) { $oPeriode->find_periode($e_date); } else { $oPeriode->id = $period; } $count = 0; for ($i = 0; $i < $nb_item; $i++) { if (!isset(${'qc_' . $i}) && !isset(${'poste' . $i})) continue; $acc_op = new Acc_Operation($this->db); $quick_code = ""; // First we save the jrnx if (isset(${'qc_' . $i})) { $qc = new Fiche($this->db); $qc->get_by_qcode(${'qc_' . $i}, false); $sposte = $qc->strAttribut(ATTR_DEF_ACCOUNT); /* if there are 2 accounts take following the deb or cred */ if (strpos($sposte, ',') != 0) { $array = explode(",", $sposte); $poste = (isset(${'ck' . $i})) ? $array[0] : $array[1]; } else { $poste = $sposte; if ($poste == '') throw new Exception(sprintf(_("La fiche %s n'a pas de poste comptable"), ${"qc_" . $i})); } $quick_code = ${'qc_' . $i}; } else { $poste = ${'poste' . $i}; } $acc_op->date = $e_date; // compute the periode is do not check it if ($check_periode == false) $acc_op->periode = $oPeriode->p_id; $acc_op->desc = null; if (strlen(trim(${'ld' . $i})) != 0) $acc_op->desc = ${'ld' . $i}; $acc_op->amount = round(${'amount' . $i}, 2); $acc_op->grpt = $seq; $acc_op->poste = $poste; $acc_op->jrn = $this->id; $acc_op->type = (isset(${'ck' . $i})) ? 'd' : 'c'; $acc_op->qcode = $quick_code; $j_id = $acc_op->insert_jrnx(); $tot_amount+=round($acc_op->amount, 2); $tot_deb+=($acc_op->type == 'd') ? $acc_op->amount : 0; $tot_cred+=($acc_op->type == 'c') ? $acc_op->amount : 0; if ($g_parameter->MY_ANALYTIC != "nu") { if (preg_match("/^[6,7]+/", $poste) == 1) { // for each item, insert into operation_analytique */ $op = new Anc_Operation($this->db); $op->oa_group = $group; $op->j_id = $j_id; $op->oa_date = $e_date; $op->oa_debit = ($acc_op->type == 'd' ) ? 't' : 'f'; $op->oa_description = $desc; $op->save_form_plan($p_array, $count, $j_id); $count++; } } }// loop for each item $acc_end = new Acc_Operation($this->db); $acc_end->amount = $tot_deb; if ($check_periode == false) $acc_end->periode = $oPeriode->p_id; $acc_end->date = $e_date; $acc_end->desc = $desc; $acc_end->grpt = $seq; $acc_end->jrn = $this->id; $acc_end->mt = $mt; $jr_id = $acc_end->insert_jrn(); $this->jr_id = $jr_id; if ($jr_id == false) throw new Exception(_('Balance incorrecte')); $acc_end->pj = $e_pj; /* if e_suggest != e_pj then do not increment sequence */ if (strcmp($e_pj, $e_pj_suggest) == 0 && strlen(trim($e_pj)) != 0) { $this->inc_seq_pj(); } $this->pj = $acc_end->set_pj(); $this->db->exec_sql("update jrn set jr_internal='" . $internal . "' where " . " jr_grpt_id = " . $seq); $this->internal = $internal; // Save now the predef op //------------------------ if (isset ($opd_name) && trim($opd_name) != "" ){ $opd = new Pre_Op_Advanced($this->db); $opd->get_post(); $opd->save(); } if (isset($this->with_concerned) && $this->with_concerned == true) { $orap = new acc_reconciliation($this->db); $orap->jr_id = $jr_id; $orap->insert($jrn_concerned); } /** * Save the file is any */ if (isset($_FILES["pj"])) { $this->db->save_upload_document($seq); } } catch (Exception $a) { throw $a; } catch (Exception $e) { $this->db->rollback(); echo _('OPERATION ANNULEE '); echo '
'; echo __FILE__ . __LINE__ . $e->getMessage(); exit(); } $this->db->commit(); return true; } /** * @brief get all the data from request and build the object */ function get_request() { $this->id = $_REQUEST['p_jrn']; } /** * @brief retrieve the next number for this type of ledger * @paramp_cn connx * @paramp_type ledger type * * \return the number * * */ static function next_number($p_cn, $p_type) { $Ret = $p_cn->count_sql("select * from jrn_def where jrn_def_type='" . $p_type . "'"); return $Ret + 1; } /** * @brief get the first ledger * @paramthe type * \return the j_id */ public function get_first($p_type, $p_access = 3) { global $g_user; $all = $g_user->get_ledger($p_type, $p_access); return $all[0]; } /** * @brief Update the paiment in the list of operation * @param$p_array is normally $_GET */ function update_paid($p_array) { // reset all the paid flag because the checkbox is post only // when checked foreach ($p_array as $name => $paid) { list($ad) = sscanf($name, "set_jr_id%d"); if ($ad == null) continue; $sql = "update jrn set jr_rapt='' where jr_id=$ad"; $Res = $this->db->exec_sql($sql); } // set a paid flag for the checked box foreach ($p_array as $name => $paid) { list ($id) = sscanf($name, "rd_paid%d"); if ($id == null) continue; $sql = "update jrn set jr_rapt='paid' where jr_id=$id"; $Res = $this->db->exec_sql($sql); } } function update_internal_code($p_internal) { if (!isset($this->grpt_id)) throw new Exception(('ERREUR ' . __FILE__ . ":" . __LINE__)); $Res = $this->db->exec_sql("update jrn set jr_internal='" . $p_internal . "' where " . " jr_grpt_id = " . $this->grpt_id); } /** * Return an array of default card for the ledger type given * * @param $p_ledger_type VEN ACH ODS or FIN * @param $p_side D for Debit or C for credit or NA No Applicable */ function get_default_card($p_ledger_type,$p_side) { $array=array(); $fiche_def_ref=new Fiche_Def_Ref($this->db); // ----- for FINANCIAL ---- if ($p_ledger_type =='FIN') { $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_CLIENT); $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_FOURNISSEUR)); $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_FIN)); $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_ADM_TAX)); $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_EMPL)); } // --- for miscellaneous ---- if ($p_ledger_type == 'ODS') { $result=$this->db->get_array('select fd_id from fiche_def'); for ($i = 0;$iget_by_modele(FICHE_TYPE_CLIENT); break; case 'ACH': $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_SER); $array=array_merge ($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_MAR)); $array=array_merge ($array,$fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_MAT)); break; default : throw new Exception(_('get_default_card p_ledger_side is invalide ['.$p_ledger_type.']')); } } elseif ($p_side == 'C') { switch($p_ledger_type) { case 'VEN': $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_VENTE); break; case 'ACH': $array= array_merge($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_ADM_TAX)); $array= array_merge($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_FOURNISSEUR)); break; default : throw new Exception(_('get_default_card p_ledger_side is invalide ['.$p_ledger_type.']')); } } return $array; /* $return=array(); $return = array_values($array); for ($i = 0;$idb->exec_sql($sql, array($this->id)); $res = Database::fetch_all($r); if (empty($res)) return null; $card = ""; $comma = ''; foreach ($res as $item) { if (strlen(trim($item['deb'])) != 0) { $card.=$comma . $item['deb']; $comma = ','; } if (strlen(trim($item['cred'])) != '') { $card.=$comma . $item['cred']; $comma = ','; } } return $card; } /** * @brief get the saldo of an exercice, used for the opening of a folder * @param$p_exercice is the exercice we want * \return an array * index = * - solde (debit > 0 ; credit < 0) * - j_poste * - j_qcode */ function get_saldo_exercice($p_exercice) { $sql = "select sum(a.montant) as solde, j_poste, j_qcode from (select j_id, case when j_debit='t' then j_montant else j_montant * (-1) end as montant from jrnx) as a join jrnx using (j_id) join parm_periode on (j_tech_per = p_id ) where p_exercice=$1 and j_poste::text not like '7%' and j_poste::text not like '6%' group by j_poste,j_qcode having (sum(a.montant) != 0 )"; $res = $this->db->get_array($sql, array($p_exercice)); return $res; } /** * @brief Check if a Dossier is using the strict mode or not * \return true if we are using the strict_mode */ function check_strict() { global $g_parameter; if ($g_parameter->MY_STRICT == 'Y') return true; if ($g_parameter->MY_STRICT == 'N') return false; throw new Exception("Valeur invalid " . __FILE__ . ':' . __LINE__); } /** * @brief Check if a Dossier is using the check on the periode, if true than the user has to enter the date * and the periode, it is a security check * \return true if we are using the double encoding (date+periode) */ function check_periode() { global $g_parameter; if ($g_parameter->MY_CHECK_PERIODE == 'Y') return true; if ($g_parameter->MY_CHECK_PERIODE == 'N') return false; throw new Exception("Valeur invalid " . __FILE__ . ':' . __LINE__); } /** * @brief get the date of the last operation */ function get_last_date() { if ($this->id == 0) throw new Exception(__FILE__ . ":" . __LINE__ . "Journal incorrect "); $sql = "select to_char(max(jr_date),'DD.MM.YYYY') from jrn where jr_def_id=$1"; $date = $this->db->get_value($sql, array($this->id)); return $date; } /** * @brief retrieve the jr_id thanks the internal code, do not change * anything to the current object * @paramthe internal code * \return the jr_id or 0 if not found */ function get_id($p_internal) { $sql = 'select jr_id from jrn where jr_internal=$1'; $value = $this->db->get_value($sql, array($p_internal)); if ($value == '') $value = 0; return $value; } /** * @brief create the invoice and saved it as attachment to the * operation, * @param$internal is the internal code * @param$p_array is normally the $_POST * \return a string */ function create_document($internal, $p_array) { extract($p_array); $doc = new Document($this->db); $doc->f_id = $e_client; $doc->md_id = $gen_doc; $doc->ag_id = 0; $p_array['e_pj']=$this->pj; $filename=""; $doc->Generate($p_array,$p_array['e_pj']); // Move the document to the jrn $doc->MoveDocumentPj($internal); // Update the comment with invoice number, if the comment is empty if (!isset($e_comm) || strlen(trim($e_comm)) == 0) { $sql = "update jrn set jr_comment=' document " . $doc->d_number . "' where jr_internal='$internal'"; $this->db->exec_sql($sql); } return h($doc->d_name . ' (' . $doc->d_filename . ')'); } /** * @brief check if the payment method is valid * @param$e_mp is the value and $e_mp_qcode is the quickcode * \return nothing throw an Exception */ public function check_payment($e_mp, $e_mp_qcode) { /* Check if the "paid by" is empty, */ if ($e_mp != 0) { /* the paid by is not empty then check if valid */ $empl = new Fiche($this->db); $empl->get_by_qcode($e_mp_qcode); if ($empl->empty_attribute(ATTR_DEF_ACCOUNT) == true) { throw new Exception(_("Celui qui paie n' a pas de poste comptable"), 20); } /* get the account and explode if necessary */ $sposte = $empl->strAttribut(ATTR_DEF_ACCOUNT); // if 2 accounts, take only the debit one for customer if (strpos($sposte, ',') != 0) { $array = explode(',', $sposte); $poste_val = $array[0]; } else { $poste_val = $sposte; } $poste = new Acc_Account_Ledger($this->db, $poste_val); if ($poste->load() == false) { throw new Exception(sprintf(_("Pour la fiche %s le poste comptable [%s] n'existe pas"),$empl->quick_code,$poste->id ), 9); } } } /** * @brief increment the sequence for the pj */ function inc_seq_pj() { $sql = "select nextval('s_jrn_pj" . $this->id . "')"; $this->db->exec_sql($sql); } /** * @brief return a HTML string with the form for the search * @param $p_type if the type of ledger possible values=ALL,VEN,ACH,ODS,FIN * @param $all_type_ledger * values : * - 1 means all the ledger of this type * - 0 No have the "Tous les journaux" availables * @param $div is the div (for reconciliation) * @return a HTML String without the tag FORM or DIV * * @see build_search_sql * @see display_search_form * @see list_operation */ function search_form($p_type, $all_type_ledger = 1, $div = "") { global $g_user; $r=""; $bledger_param= json_encode(array( 'dossier'=>$_REQUEST['gDossier'], 'type'=>$p_type, 'all_type'=>$all_type_ledger, 'div'=>$div )); $bledger_param= str_replace('"', "'", $bledger_param); $bledger=new ISmallButton('l'); $bledger->label=_("choix des journaux"); $bledger->javascript=" show_ledger_choice($bledger_param)"; $f_ledger=$bledger->input(); $hid_jrn=""; if ( isset ($_REQUEST[$div.'nb_jrn']) ){ for ($i=0;$i < $_REQUEST[$div.'nb_jrn'];$i++) { if ( isset ($_REQUEST[$div."r_jrn"][$i])) $hid_jrn.=HtmlInput::hidden($div.'r_jrn['.$i.']',$_REQUEST[$div."r_jrn"][$i]); } $hid_jrn.=HtmlInput::hidden($div.'nb_jrn',$_REQUEST[$div.'nb_jrn']); } else { $hid_jrn=HtmlInput::hidden($div.'nb_jrn',0); } /* Compute date for exercice */ $period = $g_user->get_periode(); $per = new Periode($this->db, $period); $exercice = $per->get_exercice(); list($per_start, $per_end) = $per->get_limit($exercice); $date_end = $per_end->last_day(); $date_start=$per_start->first_day(); /* widget for date_start */ $f_date_start = new IDate('date_start'); /* all periode or only the selected one */ if (isset($_REQUEST['date_start'])) { $f_date_start->value = $_REQUEST['date_start']; } else { $f_date_start->value=$date_start; } /* widget for date_end */ $f_date_end = new IDate('date_end'); /* all date or only the selected one */ if (isset($_REQUEST['date_end'])) { $f_date_end->value = $_REQUEST['date_end']; } else { $f_date_end->value = $date_end; } /* widget for date term */ $f_date_paid_start=new IDate('date_paid_start'); $f_date_paid_end=new IDate('date_paid_end'); $f_date_paid_start->value=(isset($_REQUEST['date_paid_start']))?$_REQUEST['date_paid_start']:''; $f_date_paid_end->value=(isset($_REQUEST['date_paid_end']))?$_REQUEST['date_paid_end']:''; /* widget for desc */ $f_descript = new IText('desc'); $f_descript->size = 40; if (isset($_REQUEST['desc'])) { $f_descript->value = $_REQUEST['desc']; } /* widget for amount */ $f_amount_min = new INum('amount_min'); $f_amount_min->value = (isset($_REQUEST['amount_min'])) ? abs($_REQUEST['amount_min']) : 0; $f_amount_max = new INum('amount_max'); $f_amount_max->value = (isset($_REQUEST['amount_max'])) ? abs($_REQUEST['amount_max']) : 0; /* input quick code */ $f_qcode = new ICard('qcode' . $div); $f_qcode->set_attribute('typecard', 'all'); /* $f_qcode->set_attribute('p_jrn','0'); $f_qcode->set_callback('filter_card'); */ $f_qcode->set_dblclick("fill_ipopcard(this);"); // Add the callback function to filter the card on the jrn //$f_qcode->set_callback('filter_card'); $f_qcode->set_function('fill_data'); $f_qcode->javascript = sprintf(' onchange="fill_data_onchange(%s);" ', $f_qcode->name); $f_qcode->value = (isset($_REQUEST['qcode' . $div])) ? $_REQUEST['qcode' . $div] : ''; /* $f_txt_qcode=new IText('qcode'); $f_txt_qcode->value=(isset($_REQUEST['qcode']))?$_REQUEST['qcode']:''; */ /* input poste comptable */ $f_accounting = new IPoste('accounting'); $f_accounting->value = (isset($_REQUEST['accounting'])) ? $_REQUEST['accounting'] : ''; if ($this->id == -1) $jrn = 0; else $jrn = $this->id; $f_accounting->set_attribute('jrn', $jrn); $f_accounting->set_attribute('ipopup', 'ipop_account'); $f_accounting->set_attribute('label', 'ld'); $f_accounting->set_attribute('account', 'accounting'); $info = HtmlInput::infobulle(13); $f_paid = new ICheckbox('unpaid'); $f_paid->selected = (isset($_REQUEST['unpaid'])) ? true : false; $r.=dossier::hidden(); $r.=HtmlInput::hidden('ledger_type', $this->type); $r.=HtmlInput::hidden('ac', $_REQUEST['ac']); ob_start(); require_once NOALYSS_INCLUDE.'/template/ledger_search.php'; $r.=ob_get_contents(); ob_end_clean(); return $r; } /** * @brief this function will create a sql stmt to use to create the list for * the ledger, * @param$p_array is usually the $_GET, * @param$p_order the order of the row * @param$p_where is the sql condition if not null then the $p_array will not be used * \note the p_action will be used to filter the ledger but gl means ALL * struct array $p_array \verbatim ( [gDossier] => 13 [p_jrn] => -1 [date_start] => [date_end] => [amount_min] => 0 [amount_max] => 0 [desc] => [search] => Rechercher [p_action] => ven [sa] => l ) \endverbatim * \return an array with a valid sql statement, an the where clause => array[sql] array[where] * \see list_operation * \see display_search_form * \see search_form */ public function build_search_sql($p_array, $p_order = "", $p_where = "") { $sql = "select jr_id , jr_montant, substr(jr_comment,1,60) as jr_comment, to_char(jr_ech,'DD.MM.YY') as str_jr_ech, to_char(jr_date,'DD.MM.YY') as str_jr_date, jr_date as jr_date_order, jr_grpt_id, jr_rapt, jr_internal, jrn_def_id, jrn_def_name, jrn_def_ech, jrn_def_type, jr_valid, jr_tech_per, jr_pj_name, p_closed, jr_pj_number, n_text, case when jrn_def_type='VEN' then (select ad_value from fiche_detail where ad_id=1 and f_id=(select max(qs_client) from quant_sold join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'ACH' then (select ad_value from fiche_detail where ad_id=1 and f_id=(select max(qp_supplier) from quant_purchase join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'FIN' then (select ad_value from fiche_detail where ad_id=1 and f_id=(select qf_other from quant_fin where quant_fin.jr_id=x.jr_id)) end as name, case when jrn_def_type='VEN' then (select ad_value from fiche_detail where ad_id=32 and f_id=(select max(qs_client) from quant_sold join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'ACH' then (select ad_value from fiche_detail where ad_id=32 and f_id=(select max(qp_supplier) from quant_purchase join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'FIN' then (select ad_value from fiche_detail where ad_id=32 and f_id=(select qf_other from quant_fin where quant_fin.jr_id=x.jr_id)) end as first_name, case when jrn_def_type='VEN' then (select ad_value from fiche_detail where ad_id=23 and f_id=(select max(qs_client) from quant_sold join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'ACH' then (select ad_value from fiche_detail where ad_id=23 and f_id=(select max(qp_supplier) from quant_purchase join jrnx using (j_id) join jrn as e on (e.jr_grpt_id=j_grpt) where e.jr_id=x.jr_id)) when jrn_def_type = 'FIN' then (select ad_value from fiche_detail where ad_id=23 and f_id=(select qf_other from quant_fin where quant_fin.jr_id=x.jr_id)) end as quick_code, case when jrn_def_type='VEN' then (select sum(qs_price)+sum(vat) from (select qs_internal,qs_price,case when qs_vat_sided<>0 then 0 else qs_vat end as vat from quant_sold where qs_internal=X.jr_internal) as ven_invoice ) when jrn_def_type = 'ACH' then ( select sum(qp_price)+sum(vat)+sum(qp_nd_tva)+sum(qp_nd_tva_recup) from (select qp_internal,qp_price,qp_nd_tva,qp_nd_tva_recup,qp_vat-qp_vat_sided as vat from quant_purchase where qp_internal=X.jr_internal) as invoice_purchase ) else null end as total_invoice, jr_date_paid, to_char(jr_date_paid,'DD.MM.YY') as str_jr_date_paid from jrn as X left join jrn_note using(jr_id) join jrn_def on jrn_def_id=jr_def_id join parm_periode on p_id=jr_tech_per"; if (!empty($p_array)) extract($p_array); if (isset($op) ) $r_jrn = (isset(${$op."r_jrn"})) ? ${$op."r_jrn"} : -1; else { $r_jrn = (isset($r_jrn)) ? $r_jrn : -1; } /* if no variable are set then give them a default * value */ if ($p_array == null || empty($p_array) || !isset($amount_min)) { $amount_min = 0; $amount_max = 0; $desc = ''; $qcode = (isset($qcode)) ? $qcode : ""; if (isset($qcodesearch_op)) $qcode = $qcodesearch_op; $accounting = (isset($accounting)) ? $accounting : ""; $periode = new Periode($this->db); $g_user = new User($this->db); $p_id = $g_user->get_periode(); if ($p_id != null) { list($date_start, $date_end) = $periode->get_date_limit($p_id); } } /* if p_jrn : 0 if means all ledgers, if -1 means all ledger of this * type otherwise only one ledger */ $fil_ledger = ''; $fil_amount = ''; $fil_date = ''; $fil_desc = ''; $fil_sec = ''; $fil_qcode = ''; $fil_account = ''; $fil_paid = ''; $fil_date_paid=''; $and = ''; $g_user = new User($this->db); $p_action = $ledger_type; if ($p_action == '') $p_action = 'ALL'; if ($r_jrn == -1) { /* from compta.php the p_action is quick_writing instead of ODS */ if ($p_action == 'quick_writing') $p_action = 'ODS'; $fil_ledger = $g_user->get_ledger_sql($p_action, 3); $and = ' and '; } else { if ($p_action == 'quick_writing') $p_action = 'ODS'; $aLedger = $g_user->get_ledger($p_action, 3); $fil_ledger = ''; $sp = ''; for ($i = 0; $i < count($r_jrn); $i++) { if (isset($r_jrn[$i]) ) { $a=$r_jrn[$i]; $fil_ledger.=$sp . $a; $sp = ','; } } $fil_ledger = ' jrn_def_id in (' . $fil_ledger . ')'; $and = ' and '; /* no ledger selected */ if ($sp == '') { $fil_ledger = ''; $and = ''; } } /* format the number */ $amount_min = abs(toNumber($amount_min)); $amount_max = abs(toNumber($amount_max)); if ($amount_min > 0 && isNumber($amount_min)) { $fil_amount = $and . ' jr_montant >=' . $amount_min; $and = ' and '; } if ($amount_max > 0 && isNumber($amount_max)) { $fil_amount.=$and . ' jr_montant <=' . $amount_max; $and = ' and '; } /* -------------------------------------------------------------------------- * * if both amount are the same then we need to search into the detail * and we reset the fil_amount * -------------------------------------------------------------------------- */ if (isNumber($amount_min) && isNumber($amount_max) && $amount_min > 0 && bccomp($amount_min, $amount_max, 2) == 0) { $fil_amount = $and . ' ( '; // Look in detail $fil_amount .= 'jr_grpt_id in ( select distinct j_grpt from jrnx where j_montant = ' . $amount_min . ') '; //and the total operation $fil_amount .= ' or '; $fil_amount .= ' jr_montant = '.$amount_min; $fil_amount .= ')'; $and = " and "; } // date if (isset($date_start) && isDate($date_start) != null) { $fil_date = $and . " jr_date >= to_date('" . $date_start . "','DD.MM.YYYY')"; $and = " and "; } if (isset($date_end) && isDate($date_end) != null) { $fil_date.=$and . " jr_date <= to_date('" . $date_end . "','DD.MM.YYYY')"; $and = " and "; } // date paiement if (isset($date_paid_start) && isDate($date_paid_start) != null) { $fil_date_paid = $and . " jr_date_paid >= to_date('" . $date_paid_start . "','DD.MM.YYYY')"; $and = " and "; } if (isset($date_paid_end) && isDate($date_paid_end) != null) { $fil_date_paid.=$and . " jr_date_paid <= to_date('" . $date_paid_end . "','DD.MM.YYYY')"; $and = " and "; } // comment if (isset($desc) && $desc != null) { $desc = sql_string($desc); $fil_desc = $and . " ( upper(jr_comment) like upper('%" . $desc . "%') or upper(jr_pj_number) like upper('%" . $desc . "%') " . " or upper(jr_internal) like upper('%" . $desc . "%') or jr_grpt_id in (select j_grpt from jrnx where j_text ~* '" . $desc . "') or jr_id in (select jr_id from jrn_info where ji_value is not null and ji_value ~* '$desc') )"; $and = " and "; } // Poste if (isset($accounting) && $accounting != null) { $fil_account = $and . " jr_grpt_id in (select j_grpt from jrnx where j_poste::text like '" . sql_string($accounting) . "%' ) "; $and = " and "; } // Quick Code if (isset($qcodesearch_op)) $qcode = $qcodesearch_op; if (isset($qcode) && $qcode != null) { $fil_qcode = $and . " jr_grpt_id in ( select j_grpt from jrnx where trim(j_qcode) = upper(trim('" . sql_string($qcode) . "')))"; $and = " and "; } // Only the unpaid if (isset($unpaid)) { $fil_paid = $and . SQL_LIST_UNPAID_INVOICE; $and = " and "; } $g_user = new User(new Database()); $g_user->Check(); $g_user->check_dossier(dossier::id()); if ($g_user->admin == 0 && $g_user->is_local_admin() == 0) { $fil_sec = $and . " jr_def_id in ( select uj_jrn_id " . " from user_sec_jrn where " . " uj_login='" . $_SESSION['g_user'] . "'" . " and uj_priv in ('R','W'))"; } $where = $fil_ledger . $fil_amount . $fil_date . $fil_desc . $fil_sec . $fil_amount . $fil_qcode . $fil_paid . $fil_account.$fil_date_paid; $sql.=" where " . $where; return array($sql, $where); } /** * @brief return a html string with the search_form * \return a HTML string with the FORM * \see build_search_sql * \see search_form * \see list_operation */ function display_search_form() { $r = ''; $type = $this->type; if ($type == "") $type = 'ALL'; $r.=''; $button = new IButton('tfs'); $button->label = _("Filtrer"); $button->javascript = "toggleHideShow('search_form','tfs');"; $r.=$button->input(); return $r; } /** * @brief return the last p_limit operation into an array * @param$p_limit is the max of operation to return * \return $p_array of Follow_Up object */ function get_last($p_limit) { global $g_user; $filter_ledger = $g_user->get_ledger_sql('ALL', 3); $filter_ledger = str_replace('jrn_def_id', 'jr_def_id', $filter_ledger); $sql = " select jr_id,jr_pj_number,jr_date,to_char(jr_date,'DD.MM.YYYY') as jr_date_fmt,jr_montant, jr_comment,jr_internal,jrn_def_code from jrn join jrn_def on (jrn_def_id=jr_def_id) where $filter_ledger order by jr_date desc , substring(jr_pj_number,'[0-9]+$')::numeric desc limit $p_limit"; $array = $this->db->get_array($sql); return $array; } /** * @brief retreive the jr_grpt_id from a ledger * @param $p_what the column to seek * possible values are * - internal * @param $p_value the value of the col. */ function search_group($p_what, $p_value) { switch ($p_what) { case 'internal': return $this->db->get_value('select jr_grpt_id from jrn where jr_internal=$1', array($p_value)); } } /** * @brief retrieve operation from jrn * @param $p_from periode (id) * @param $p_to periode (id) * @return an array */ function get_operation($p_from, $p_to) { global $g_user; $jrn = ($this->id == 0) ? 'and ' . $g_user->get_ledger_sql() : ' and jr_def_id = ' . $this->id; $sql = "select jr_id as id ,jr_internal as internal, " . "jr_pj_number as pj,jr_grpt_id," . " to_char(jr_date,'DDMMYY') as date_fmt, " . " jr_comment as comment, jr_montant as montant ," . " jr_grpt_id,jr_def_id" . " from jrn join jrn_def on (jr_def_id=jrn_def_id) where " . " jr_date >= (select p_start from parm_periode where p_id = $1) and jr_date <= (select p_end from parm_periode where p_id = $2)" . ' ' . $jrn . ' order by jr_date,substring(jr_pj_number,\'[0-9]+$\')::numeric asc'; $ret = $this->db->get_array($sql, array($p_from, $p_to)); return $ret; } /** * @brief return the used VAT code with a rate > 0 * @return an array of tva_id,tva_label,tva_poste */ public function existing_vat() { if ($this->type == 'ACH') { $array = $this->db->get_array("select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0.0000 " . " and exists (select qp_vat_code from quant_purchase where qp_vat_code=tva_id and exists (select j_id from jrnx where j_jrn_def = $1)) order by tva_id", array($this->id)); } if ($this->type == 'VEN') { $array = $this->db->get_array("select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0.0000 " . " and exists (select qs_vat_code from quant_sold where qs_vat_code=tva_id and exists (select j_id from jrnx where j_jrn_def = $1)) order by tva_id", array($this->id)); } return $array; } /** * @brief get the amount of vat for a given jr_grpt_id from the table * quant_purchase * @param the jr_grpt_id * @return array price=htva, [1] = vat, * @note * @see @code array 'price' => string '91.3500' (length=7) 'vat' => string '0.0000' (length=6) 'priv' => string '0.0000' (length=6) 'tva_nd_recup' => string '0.0000' (length=6) @endcode */ function get_other_amount($p_jr_id) { if ($this->type == 'ACH') { $array = $this->db->get_array('select sum(qp_price) as price,sum(qp_vat) as vat ' . ',sum(coalesce(qp_nd_amount,0)+coalesce(qp_dep_priv,0)) as priv' . ',sum(coalesce(qp_nd_tva_recup,0)+coalesce(qp_nd_tva,0)) as tva_nd' . ',sum(qp_vat_sided) as tva_np' . ' from quant_purchase join jrnx using(j_id) where j_grpt=$1 ', array($p_jr_id)); $ret = $array[0]; } if ($this->type == 'VEN') { $array = $this->db->get_array('select sum(qs_price) as price,sum(qs_vat) as vat ' . ',0 as priv' . ',0 as tva_nd' . ',sum(qs_vat_sided) as tva_np' . ' from quant_sold join jrnx using(j_id) where j_grpt=$1 ', array($p_jr_id)); $ret = $array[0]; } return $ret; } /** * @brief get the amount of vat for a given jr_grpt_id from the table * quant_purchase * @param the jr_grpt_id * @return array of sum_vat, tva_label * @note * @see @code @endcode */ function vat_operation($p_jr_id) { if ($this->type == 'ACH') { $array = $this->db->get_array('select coalesce(sum(qp_vat),0) as sum_vat,tva_id from quant_purchase as p right join tva_rate on (qp_vat_code=tva_id) join jrnx using(j_id) where tva_rate !=0.0 and j_grpt=$1 group by tva_id', array($p_jr_id)); } if ($this->type == 'VEN') { $array = $this->db->get_array('select coalesce(sum(qs_vat),0) as sum_vat,tva_id from quant_sold as p right join tva_rate on (qs_vat_code=tva_id) join jrnx using(j_id) where tva_rate !=0.0 and j_grpt=$1 group by tva_id', array($p_jr_id)); } return $array; } /** * @brief retrieve amount of previous periode * @param $p_to frmo the start of the exercise until $p_to * @return $array with vat, price,other_amount * @note * @see @code array 'price' => string '446.1900' (length=8) 'vat' => string '21.7600' (length=7) 'priv' => string '0.0000' (length=6) 'tva_nd_recup' => string '0.0000' (length=6) 'tva' => array 0 => array 'sum_vat' => string '13.7200' (length=7) 'tva_id' => string '1' (length=1) 1 => array 'sum_vat' => string '8.0400' (length=6) 'tva_id' => string '3' (length=1) 2 => array 'sum_vat' => string '0.0000' (length=6) 'tva_id' => string '4' (length=1) @endcode */ function previous_amount($p_to) { /* get the first periode of exercise */ $periode = new Periode($this->db, $p_to); $exercise = $periode->get_exercice(); list ($min, $max) = $periode->get_limit($exercise); // transform min into date $min_date=$min->first_day(); // transform $p_to into date $periode_max=new Periode($this->db,$p_to); $max_date=$periode_max->first_day(); bcscale(2); // min periode if ($this->type == 'ACH') { /* get all amount exclude vat */ $sql = "select coalesce(sum(qp_price),0) as price" . " ,coalesce(sum(qp_vat),0) as vat " . ',coalesce(sum(qp_dep_priv),0) as priv' . ',coalesce(sum(qp_vat_sided),0) as reversed' . ',coalesce(sum(qp_nd_tva_recup),0)+coalesce(sum(qp_nd_tva),0) as tva_nd' . ',coalesce(sum(qp_vat_sided),0) as tva_np' . ' from quant_purchase join jrnx using(j_id) ' . " where j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') ". ' and j_jrn_def = $3'; $array = $this->db->get_array($sql, array($min_date, $max_date,$this->id)); $ret = $array[0]; /* retrieve all vat code */ $array = $this->db->get_array("select coalesce(sum(qp_vat),0) as sum_vat,tva_id from quant_purchase as p right join tva_rate on (qp_vat_code=tva_id) join jrnx using(j_id) where tva_rate !=0 and j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') and j_jrn_def = $3 group by tva_id", array($min_date, $max_date,$this->id)); $ret['tva'] = $array; } if ($this->type == 'VEN') { /* get all amount exclude vat */ $sql = "select coalesce(sum(qs_price),0) as price" . " ,coalesce(sum(qs_vat),0) as vat " . ',0 as priv' . ',0 as tva_nd' . ',coalesce(sum(qs_vat_sided),0) as tva_np' . ' from quant_sold join jrnx using(j_id) ' . " where j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') ". ' and j_jrn_def = $3'; $array = $this->db->get_array($sql, array($min_date, $max_date,$this->id)); $ret = $array[0]; /* retrieve all vat code */ $array = $this->db->get_array("select coalesce(sum(qs_vat),0) as sum_vat,tva_id from quant_sold as p right join tva_rate on (qs_vat_code=tva_id) join jrnx using(j_id) where tva_rate !=0 and j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') and j_jrn_def = $3 group by tva_id", array($min_date, $max_date,$this->id)); $ret['tva'] = $array; } if ($this->type=="FIN") { /* find the quick code of this ledger */ $ledger=new Acc_Ledger_Fin($this->db,$this->id); $qcode=$ledger->get_bank(); $bank_card=new Fiche($this->db,$qcode); /*add the amount from Opening Writing */ $cond=sprintf(" j_jrn_def <> %d and j_date >= to_date('%s','DD.MM.YYYY') and j_date < to_date('%s','DD.MM.YYYY') ",$this->id,$min_date,$max_date); $saldo = $bank_card->get_bk_balance ($cond); $ret['amount']=bcsub($saldo['debit'],$saldo['credit']); } return $ret; } //////////////////////////////////////////////////////////////////////////////// // TEST MODULE //////////////////////////////////////////////////////////////////////////////// /** * @brief this function is intended to test this class */ static function test_me($pCase = '') { if ($pCase == '') { echo Acc_Reconciliation::$javascript; html_page_start(); $cn = new Database(dossier::id()); $_SESSION['g_user'] = 'phpcompta'; $_SESSION['g_pass'] = 'phpcompta'; $id = (isset($_REQUEST['p_jrn'])) ? $_REQUEST['p_jrn'] : -1; $a = new Acc_Ledger($cn, $id); $a->with_concerned = true; // Vide echo '
'; echo $a->select_ledger()->input(); echo HtmlInput::submit('go', 'Test it'); echo '
'; if (isset($_POST['go'])) { echo "Ok "; echo '
'; echo $a->show_form(); echo HtmlInput::submit('post_id', 'Try me'); echo '
'; // Show the predef operation // Don't forget the p_jrn echo '
'; echo dossier::hidden(); echo ''; $op = new Pre_operation($cn); $op->p_jrn = $id; $op->od_direct = 't'; if ($op->count() != 0) { echo HtmlInput::submit('use_opd', 'Utilisez une opération prédéfinie',"","smallbutton"); echo $op->show_button(); } echo '
'; exit('test_me'); } if (isset($_POST['post_id'])) { echo '
'; echo $a->show_form($_POST, 1); echo HtmlInput::button('add', 'Ajout d\'une ligne', 'onClick="quick_writing_add_row()"'); echo HtmlInput::submit('save_it', _("Sauver")); echo '
'; exit('test_me'); } if (isset($_POST['save_it'])) { print 'saving'; $array = $_POST; $array['save_opd'] = 1; try { $a->save($array); } catch (Exception $e) { alert($e->getMessage()); echo '
'; echo $a->show_form($_POST); echo HtmlInput::submit('post_id', 'Try me'); echo '
'; } return; } // The GET at the end because automatically repost when you don't // specify the url in the METHOD field if (isset($_GET['use_opd'])) { $op = new Pre_op_advanced($cn); $op->set_od_id($_REQUEST['pre_def']); //$op->p_jrn=$id; $p_post = $op->compute_array(); echo '
'; echo $a->show_form($p_post); echo HtmlInput::submit('post_id', 'Use predefined operation'); echo '
'; return; } }// if case = '' /////////////////////////////////////////////////////////////////////////// // search if ($pCase == 'search') { html_page_start(); $cn = new Database(dossier::id()); $ledger = new Acc_Ledger($cn, 0); $_SESSION['g_user'] = 'phpcompta'; $_SESSION['g_pass'] = 'phpcompta'; echo $ledger->search_form('ALL'); } /////////////////////////////////////////////////////////////////////////// // reverse // Give yourself the var and check in your tables /////////////////////////////////////////////////////////////////////////// if ($pCase == 'reverse') { $cn = new Database(dossier::id()); $jr_internal = 'OD-01-272'; try { $cn->start(); $jrn_def_id = $cn->get_value('select jr_def_id from jrn where jr_internal=$1', array($jr_internal)); $ledger = new Acc_Ledger($cn, $jrn_def_id); $ledger->jr_id = $cn->get_value('select jr_id from jrn where jr_internal=$1', array($jr_internal)); echo "Ouvrez le fichier " . __FILE__ . " à la ligne " . __LINE__ . " pour changer jr_internal et vérifier le résultat de l'extourne"; $ledger->reverse('01.07.2010'); } catch (Exception $e) { $cn->rollback(); var_dump($e); } $cn->commit(); } } /** * create an array of the existing cat, to be used in a checkbox form * */ static function array_cat() { $r = array( array('cat' => 'VEN', 'name' => _("Journaux de vente")), array('cat' => 'ACH', 'name' => _("Journaux d'achat")), array('cat' => 'FIN', 'name' => _("Journaux Financier")), array('cat' => 'ODS', 'name' => _("Journaux d'Opérations diverses")) ); return $r; } /** * Retrieve the third : supplier for purchase, customer for sale, bank for fin, * @param $p_jrn_type type of the ledger FIN, VEN ACH or ODS */ function get_tiers($p_jrn_type, $jr_id) { if ($p_jrn_type == 'ODS') return ' '; $tiers = ''; switch ($p_jrn_type) { case 'VEN': $tiers = $this->db->get_value('select max(qs_client) from quant_sold join jrnx using (j_id) join jrn on (jr_grpt_id=j_grpt) where jrn.jr_id=$1', array($jr_id)); break; case 'ACH': $tiers = $this->db->get_value('select max(qp_supplier) from quant_purchase join jrnx using (j_id) join jrn on (jr_grpt_id=j_grpt) where jrn.jr_id=$1', array($jr_id)); break; case 'FIN': $tiers = $this->db->get_value('select qf_other from quant_fin where jr_id=$1', array($jr_id)); break; } if ($this->db->count() == 0) return ''; $name = $this->db->get_value('select ad_value from fiche_detail where ad_id=1 and f_id=$1', array($tiers)); $first_name = $this->db->get_value('select ad_value from fiche_detail where ad_id=32 and f_id=$1', array($tiers)); return $name . ' ' . $first_name; } /** * @brief listing of all ledgers * @return HTML string */ function listing() { $str_dossier = dossier::get(); $base_url = "?" . dossier::get() . "&ac=" . $_REQUEST['ac']; $r = ""; $r.=_('Filtre')." ".HtmlInput::filter_table("cfgledger_table_id", "0", "1"); $r.=''; $r.=''; $ret = $this->db->exec_sql("select distinct jrn_def_id,jrn_def_name, jrn_def_class_deb,jrn_def_class_cred,jrn_def_type from jrn_def order by jrn_def_name"); $Max = Database::num_row($ret); for ($i = 0; $i < $Max; $i++) { $l_line = Database::fetch_array($ret, $i); $url = $base_url . "&sa=detail&p_jrn=" . $l_line['jrn_def_id']; $r.=sprintf('', $url, h($l_line['jrn_def_name']).' ('.$l_line['jrn_def_type'].')'); } $r.= "
' . _('Ajout journal') . '
%s
"; return $r; } /** * display detail of a ledger * */ function display_ledger() { if ($this->load() == -1) { throw new Exception(_("Journal n'existe pas"), -1); } $type = $this->jrn_def_type; $name = $this->jrn_def_name; $code = $this->jrn_def_code; $str_add_button=""; /* widget for searching an account */ $wSearch = new IPoste(); $wSearch->set_attribute('ipopup', 'ipop_account'); $wSearch->set_attribute('account', 'p_jrn_class_deb'); $wSearch->set_attribute('no_overwrite', '1'); $wSearch->set_attribute('noquery', '1'); $wSearch->table = 3; $wSearch->name = "p_jrn_class_deb"; $wSearch->size = 20; $wSearch->value = $this->jrn_def_class_deb; $search = $wSearch->input(); $wPjPref = new IText(); $wPjPref->name = 'jrn_def_pj_pref'; $wPjPref->value = $this->jrn_def_pj_pref; $pj_pref = $wPjPref->input(); $wPjSeq = new INum(); $wPjSeq->value = 0; $wPjSeq->name = 'jrn_def_pj_seq'; $pj_seq = $wPjSeq->input(); $last_seq = $this->get_last_pj(); $name = $this->jrn_def_name; $hidden = HtmlInput::hidden('p_jrn', $this->id); $hidden.= HtmlInput::hidden('sa', 'detail'); $hidden.= dossier::hidden(); $hidden.=HtmlInput::hidden('p_jrn_deb_max_line', 10); $hidden.=HtmlInput::hidden('p_ech_lib', 'echeance'); $hidden.=HtmlInput::hidden('p_jrn_type', $type); $min_row = new INum("min_row",$this->jrn_deb_max_line); $min_row->prec=0; $description=new ITextarea('p_description'); $description->style='class="itextarea" style="margin:0px;"'; $description->value=$this->jrn_def_description; $str_description=$description->input(); /* Load the card */ $card = $this->get_fiche_def(); $rdeb = explode(',', $card['deb']); $rcred = explode(',', $card['cred']); /* Numbering (only FIN) */ $num_op = new ICheckBox('numb_operation'); if ($this->jrn_def_num_op == 1) $num_op->selected = true; /* bank card */ $qcode_bank = ''; if ($type == 'FIN') { $f_id = $this->jrn_def_bank; if (isNumber($f_id) == 1) { $fBank = new Fiche($this->db, $f_id); $qcode_bank = $fBank->get_quick_code(); } } $new = 0; $cn = $this->db; echo $hidden; require_once NOALYSS_INCLUDE.'/template/param_jrn.php'; } /** * Verify before update * * @param type $array * 'p_jrn' => string '3' (length=1) 'sa' => string 'detail' (length=6) 'gDossier' => string '82' (length=2) 'p_jrn_deb_max_line' => string '10' (length=2) 'p_ech_lib' => string 'echeance' (length=8) 'p_jrn_type' => string 'ACH' (length=3) 'p_jrn_name' => string 'Achat' (length=5) 'jrn_def_pj_pref' => string 'ACH' (length=3) 'jrn_def_pj_seq' => string '0' (length=1) 'FICHECRED' => array 0 => string '4' (length=1) 'FICHEDEB' => array 0 => string '7' (length=1) 1 => string '5' (length=1) 2 => string '13' (length=2) 'update' => string 'Sauve' (length=5 * @exception is throw is test are not valid */ function verify_ledger($array) { extract($array); try { if (isNumber($p_jrn) == 0) throw new Exception("Id invalide"); if (isNumber($p_jrn_deb_max_line) == 0) throw new Exception(_("Nombre de ligne incorrect")); if (trim($p_jrn_name) == "") throw new Exception("Nom de journal invalide"); if ($this->db->get_value("select count(*) from jrn_def where jrn_def_name=$1 and jrn_Def_id<>$2", array($p_jrn_name, $p_jrn)) > 0) throw new Exception(_("Un journal avec ce nom existe déjà")); if ($p_jrn_type == 'FIN') { $a = new Fiche($this->db); $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false); if ($result == 1) throw new Exception(_("Aucun compte en banque n'est donné")); } if ($p_jrn_type == "-1") { throw new Exception(_('Choix du type de journal est obligatoire')); } } catch (Exception $e) { throw $e; } } /** * update a ledger * @param type $array normally post * @see verify_ledger */ function update($array = '') { if ($array == null) throw new Exception('save cannot use a empty array'); extract($array); $this->jrn_def_id = $p_jrn; $this->jrn_def_name = $p_jrn_name; $this->jrn_def_ech_lib = $p_ech_lib; $this->jrn_def_max_line_deb = ($p_jrn_deb_max_line<1)?1:$p_jrn_deb_max_line; $this->jrn_def_type = $p_jrn_type; $this->jrn_def_pj_pref = $jrn_def_pj_pref; $this->jrn_def_fiche_deb = (isset($FICHEDEB)) ? join($FICHEDEB, ',') : ""; $this->jrn_deb_max_line=($min_row<1)?1:$min_row; $this->jrn_def_description=$p_description; switch ($this->jrn_def_type) { case 'ACH': case 'VEN': $this->jrn_def_fiche_cred = (isset($FICHECRED)) ? join($FICHECRED, ',') : ''; break; case 'ODS': $this->jrn_def_class_deb = $p_jrn_class_deb; $this->jrn_def_fiche_cred=null; break; case 'FIN': $a = new Fiche($this->db); $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false); $bank = $a->id; $this->jrn_def_bank = $bank; if ($result == -1) throw new Exception(_("Aucun compte en banque n'est donné")); $this->jrn_def_num_op = (isset($numb_operation)) ? 1 : 0; break; } parent::update(); //Reset sequence if needed if ($jrn_def_pj_seq != 0) { $Res = $this->db->alter_seq("s_jrn_pj" . $p_jrn, $jrn_def_pj_seq); } } function input_paid() { $r = ''; $r.='
'; $r.='

' . _('Payé par') . '

'; $mp = new Acc_Payment($this->db); $mp->set_parameter('ledger_source', $this->id); $r.=$mp->select(); $r.='
'; return $r; } /** * display screen to enter a new ledger */ function input_new() { $retry=HtmlInput::default_value_post("sa", ""); // if ( $retry == "add") { $default_type=HtmlInput::default_value_post("p_jrn_type", -1); $previous_jrn_def_pj_pref=HtmlInput::default_value_post("jrn_def_pj_pref",""); $previous_p_description=HtmlInput::default_value_post("p_description",""); $previous_p_jrn_name=HtmlInput::default_value_post('p_jrn_name',''); $previous_p_jrn_type = HtmlInput::default_value_post("p_jrn_type",""); // } global $g_user; $f_add_button=new ISmallButton('add_card'); $f_add_button->label=_('Créer une nouvelle fiche'); $f_add_button->tabindex=-1; $f_add_button->set_attribute('jrn',-1); $f_add_button->javascript=" this.jrn=-1;select_card_type({type_cat:4});"; $str_add_button=""; if ($g_user->check_action(FICADD)==1) { $str_add_button=$f_add_button->input(); } $wSearch = new IPoste(); $wSearch->table = 3; $wSearch->set_attribute('ipopup', 'ipop_account'); $wSearch->set_attribute('account', 'p_jrn_class_deb'); $wSearch->set_attribute('no_overwrite', '1'); $wSearch->set_attribute('noquery', '1'); $wSearch->name = "p_jrn_class_deb"; $wSearch->size = 20; $search = $wSearch->input(); // default for ACH $default_deb_purchase = $this->get_default_card('ACH', 'D'); $default_cred_purchase = $this->get_default_card('ACH', 'C'); // default for VEN $default_deb_sale = $this->get_default_card('VEN', 'D'); $default_cred_sale = $this->get_default_card('VEN', 'C'); // default for FIN $default_fin = $this->get_default_card("FIN", ""); //default ods $default_ods = $this->get_default_card("ODS", ""); /* construct all the hidden */ $hidden = HtmlInput::hidden('p_jrn', -1); $hidden.= HtmlInput::hidden('p_action', 'jrn'); $hidden.= HtmlInput::hidden('sa', 'add'); $hidden.= dossier::hidden(); $hidden.=HtmlInput::hidden('p_jrn_deb_max_line', 10); $hidden.=HtmlInput::hidden('p_ech_lib', 'echeance'); /* properties of the ledger */ $name = $previous_p_jrn_name; $code = ""; $wType = new ISelect(); $a_jrn= $this->db->make_array("select '-1',' -- "._("choix du type de journal")." -- ' union select jrn_type_id,jrn_desc from jrn_type"); $wType->selected='-1'; $wType->value =$a_jrn; $wType->name = "p_jrn_type"; $wType->id= "p_jrn_type_select_id"; $wType->javascript=' onchange="show_ledger_div()"'; $wType->selected=$default_type; $type = $wType->input(); $rcred = $rdeb = array(); $wPjPref = new IText(); $wPjPref->name = 'jrn_def_pj_pref'; $wPjPref->value=$previous_jrn_def_pj_pref; $pj_pref = $wPjPref->input(); $pj_seq = ''; $last_seq = 0; $new = 1; $description=new ITextarea('p_description'); $description->style='class="itextarea" style="margin:0px;"'; $description->value=$previous_p_description; $str_description=$description->input(); /* bank card */ $qcode_bank = ''; /* Numbering (only FIN) */ $num_op = new ICheckBox('numb_operation'); echo dossier::hidden(); echo HtmlInput::hidden('ac', $_REQUEST['ac']); echo $hidden; $cn = $this->db; $min_row = new INum("min_row",MAX_ARTICLE); $min_row->prec=0; require_once NOALYSS_INCLUDE.'/template/param_jrn.php'; } /** * Insert a new ledger * @param type $array normally $_POST * @see verify_ledger */ function save_new($array) { $this->load(); extract($array); $this->jrn_def_id = -1; $this->jrn_def_name = $p_jrn_name; $this->jrn_def_ech_lib = $p_ech_lib; $this->jrn_def_max_line_deb = $p_jrn_deb_max_line; $this->jrn_def_type = $p_jrn_type; $this->jrn_def_pj_pref = $jrn_def_pj_pref; $this->jrn_def_fiche_deb = (isset($FICHEDEB)) ? join($FICHEDEB, ',') : ""; $this->jrn_deb_max_line=$min_row; $this->jrn_def_code = sprintf("%s%02d", trim(substr($this->jrn_def_type, 0, 1)), Acc_Ledger::next_number($this->db, $this->jrn_def_type)); $this->jrn_def_description=$p_description; switch ($this->jrn_def_type) { case 'ACH': case 'VEN': $this->jrn_def_fiche_cred = (isset($FICHECRED)) ? join($FICHECRED, ',') : ''; break; case 'ODS': $this->jrn_def_class_deb = $p_jrn_class_deb; $this->jrn_def_fiche_cred = null; break; case 'FIN': $a = new Fiche($this->db); $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false); $bank = $a->id; $this->jrn_def_bank = $bank; if ($result == -1) throw new Exception(_("Aucun compte en banque n'est donné")); $this->jrn_def_num_op = (isset($numb_operation)) ? 1 : 0; break; } parent::insert(); } /** * delete a ledger IF is not already used * @exeption : cannot delete */ function delete_ledger() { try { if ($this->db->get_value("select count(jr_id) from jrn where jr_def_id=$1", array($this->jrn_def_id)) > 0) throw new Exception(_("Impossible d'effacer un journal qui contient des opérations")); parent::delete(); } catch (Exception $e) { throw $e; } } /** * Get operation from the ledger type before, after or with the * given date . The array is filtered by the ledgers granted to the * user * @global type $g_user * @param $p_date Date (d.m.Y) * @param $p_ledger_type VEN ACH * @param type $sql_op < > or = * @return array from jrn (jr_id, jr_internal, jr_date, jr_comment,jr_pj_number,jr_montant) * @throws Exception */ function get_operation_date($p_date,$p_ledger_type,$sql_op) { global $g_user; switch ($p_ledger_type) { case 'ACH': $filter=$g_user->get_ledger_sql('ACH',3); break; case 'VEN': $filter=$g_user->get_ledger_sql('VEN',3); break; default: throw new Exception ('Ledger_type invalid : '.$p_ledger_type); } $sql = "select jr_id, jr_internal, jr_date, jr_comment,jr_pj_number,jr_montant from jrn join jrn_def on (jrn_def_id=jr_def_id) where jr_ech is not null and jr_ech $sql_op to_date($1,'DD.MM.YYYY') and coalesce (jr_rapt,'xx') <> 'paid' and $filter "; $array=$this->db->get_array($sql,array($p_date)); return $array; } /** * @brief get info from supplier to pay today */ function get_supplier_now() { $array=$this->get_operation_date(Date('d.m.Y'), 'ACH', '='); return $array; } /** * @brief get info from supplier not yet paid */ function get_supplier_late() { $array=$this->get_operation_date(Date('d.m.Y'), 'ACH', '<'); return $array; } /** * @brief get info from customer to pay today */ function get_customer_now() { $array=$this->get_operation_date(Date('d.m.Y'), 'VEN', '='); return $array; } /** * @brief get info from customer not yet paid */ function get_customer_late() { $array=$this->get_operation_date(Date('d.m.Y'), 'VEN', '<'); return $array; } function convert_from_follow($p_ag_id) { global $g_user; if (isNumber($p_ag_id)==0) return null; if (! $g_user->can_read_action($p_ag_id)) die (_('Action non accessible')); $array=array(); // retrieve info from action_gestion $tiers_id=$this->db->get_value('select f_id_dest from action_gestion where ag_id=$1',array($p_ag_id)); if ( $this->db->size() !=0 ) $qcode=$this->db->get_value('select j_qcode from vw_poste_qcode where f_id=$1',array($tiers_id)); else $qcode=""; $comment=$this->db->get_value('select ag_title from action_gestion where ag_id=$1',array($p_ag_id)); $array['e_client']=$qcode; $array['e_comm']=$comment; // retrieve info from action_detail $a_item=$this->db->get_array('select f_id,ad_text,ad_pu,ad_quant,ad_tva_id,ad_tva_amount,j_qcode from action_detail left join vw_poste_qcode using(f_id) where ag_id=$1',array($p_ag_id)); $array['nb_item']=($this->nb > count($a_item))?$this->nb:count($a_item); for ($i=0;$idb->get_value('select pcm_lib from tmp_pcmn where pcm_val=$1',array($p_value)); return $lib; } /** * Let you select the repository before confirming a sale or a purchase. * Returns an empty string if the company doesn't use stock * @brief Let you select the repository before confirming a sale or a purchase. * @global type $g_parameter check if company is using stock * @param type $p_readonly * @param type $p_repo * @return string */ public function select_depot($p_readonly, $p_repo) { global $g_parameter; $r=($p_readonly==false)?'
':'
'; // Show the available repository if ($g_parameter->MY_STOCK=='Y') { $sel=HtmlInput::select_stock($this->db, 'repo', 'W'); $sel->readOnly=$p_readonly; if ($p_readonly==true) $sel->selected=$p_repo; $r.="

"._('Dans le dépôt')." : "; $r.=$sel->input(); $r.='

'; } else { $r.=''.'Stock non utilisé'.''; } $r.='
'; return $r; } /** * Create a button to encode a new operation into the same ledger * @return string */ function button_new_operation() { $url=http_build_query(array('ac'=>$_REQUEST['ac'],'gDossier'=>$_REQUEST['gDossier'],'p_jrn'=>$_REQUEST['p_jrn'])); $button = HtmlInput::button_anchor(_("Nouvelle opération"), 'do.php?'.$url); return '

'.$button.'

'; } } ?>