noalyss  Version-6.9.1.8
 All Data Structures Namespaces Files Functions Variables Pages
class_acc_ledger.php
Go to the documentation of this file.
1 <?php
2 /*
3  * This file is part of NOALYSS.
4  *
5  * NOALYSS is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * NOALYSS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with NOALYSS; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  */
19 // Copyright Author Dany De Bontridder danydb@aevalys.eu
20 require_once NOALYSS_INCLUDE.'/lib/class_iselect.php';
21 require_once NOALYSS_INCLUDE.'/lib/class_icard.php';
22 require_once NOALYSS_INCLUDE.'/lib/class_ispan.php';
23 require_once NOALYSS_INCLUDE.'/lib/class_ihidden.php';
24 require_once NOALYSS_INCLUDE.'/lib/class_idate.php';
25 require_once NOALYSS_INCLUDE.'/lib/class_itext.php';
26 require_once NOALYSS_INCLUDE.'/lib/class_icheckbox.php';
27 require_once NOALYSS_INCLUDE.'/lib/class_iperiod.php';
28 require_once NOALYSS_INCLUDE.'/class/class_fiche.php';
29 require_once NOALYSS_INCLUDE.'/class/class_user.php';
30 require_once NOALYSS_INCLUDE.'/class/class_dossier.php';
31 require_once NOALYSS_INCLUDE.'/class/class_anc_operation.php';
32 require_once NOALYSS_INCLUDE.'/class/class_acc_operation.php';
33 require_once NOALYSS_INCLUDE.'/class/class_acc_account_ledger.php';
34 require_once NOALYSS_INCLUDE.'/class/class_pre_op_advanced.php';
35 require_once NOALYSS_INCLUDE.'/class/class_acc_reconciliation.php';
36 require_once NOALYSS_INCLUDE.'/class/class_periode.php';
37 require_once NOALYSS_INCLUDE.'/class/class_gestion_purchase.php';
38 require_once NOALYSS_INCLUDE.'/class/class_gestion_sold.php';
39 require_once NOALYSS_INCLUDE.'/class/class_acc_account.php';
40 require_once NOALYSS_INCLUDE.'/lib/ac_common.php';
41 require_once NOALYSS_INCLUDE.'/lib/class_inum.php';
42 require_once NOALYSS_INCLUDE.'/class/class_lettering.php';
43 require_once NOALYSS_INCLUDE.'/lib/class_sort_table.php';
44 require_once NOALYSS_INCLUDE.'/database/class_jrn_def_sql.php';
45 require_once NOALYSS_INCLUDE.'/class/class_acc_payment.php';
46 /** \file
47  * @brief Class for jrn, class acc_ledger for manipulating the ledger
48  */
49 
50 /** @brief Class for jrn, class acc_ledger for manipulating the ledger
51  *
52  */
53 
54 class Acc_Ledger extends jrn_def_sql
55 {
56 
57  var $id; /**< jrn_def.jrn_def_id */
58  var $name; /**< jrn_def.jrn_def_name */
59  var $db; /**< database connextion */
60  var $row; /**< row of the ledger */
61  var $type; /**< type of the ledger ACH ODS FIN
62  VEN or GL */
63  var $nb; /**< default number of rows by
64  default 10 */
65 
66  /**
67  * @param $p_cn database connexion
68  * @param $p_id jrn.jrn_def_id
69  */
70  function __construct($p_cn, $p_id)
71  {
72  $this->id = $p_id;
73  $this->name = &$this->jrn_def_name;
74  $this->jrn_def_id = &$this->id;
75  $this->db = $p_cn;
76  $this->row = null;
77  $this->nb = MAX_ARTICLE;
78  }
79 
80  function get_last_pj()
81  {
82  if (isNumber($this->id) == 0) {
83  throw new Exception(_("Paramètre invalide"));
84  return;
85  }
86  if ($this->db->exist_sequence("s_jrn_pj" . $this->id))
87  {
88  $ret = $this->db->get_array("select last_value,is_called from s_jrn_pj" . $this->id);
89  $last = $ret[0]['last_value'];
90  /**
91  * \note With PSQL sequence , the last_value column is 1 when before AND after the first call, to make the difference between them
92  * I have to check whether the sequence has been already called or not */
93  if ($ret[0]['is_called'] == 'f')
94  $last--;
95  return $last;
96  }
97  else
98  $this->db->create_sequence("s_jrn_pj" . $this->id);
99  return 0;
100  }
101 
102  /**
103  * @brief Return the type of a ledger (ACH,VEN,ODS or FIN) or GL
104  *
105  */
106 
107  function get_type()
108  {
109  if ($this->id == 0)
110  {
111  $this->name = _(" Tous les journaux");
112  $this->type = "GL";
113  return "GL";
114  }
115 
116  $Res = $this->db->exec_sql("select jrn_def_type from " .
117  " jrn_def where jrn_def_id=" .
118  $this->id);
120  if ($Max == 0)
121  return null;
123  $this->type = $ret['jrn_def_type'];
124  return $ret['jrn_def_type'];
125  }
126 
127  /**
128  * let you delete a operation
129  * @note by cascade it will delete also in
130  * - jrnx
131  * - stock
132  * - quant_purchase
133  * - quant_fin
134  * - quant_sold
135  * - operation_analytique
136  * - letter
137  * - reconciliation
138  * @bug the attached document is not deleted
139  * @bug Normally it should be named delete_operation, cause the id is the ledger_id
140  * (jrn_def_id) and not the operation id
141  */
142  function delete()
143  {
144  if ($this->id == 0)
145  return;
146  $grpt_id = $this->db->get_value('select jr_grpt_id from jrn where jr_id=$1', array($this->jr_id));
147  if ($this->db->count() == 0)
148  return;
149  $this->db->exec_sql('delete from jrnx where j_grpt=$1', array($grpt_id));
150  $this->db->exec_sql('delete from jrn where jr_id=$1', array($this->jr_id));
151  }
152 
153  /**
154  * Display warning contained in an array
155  * @return string with error message
156  */
157  function display_warning($pa_msg, $p_warning)
158  {
159  $str = '<p class="notice"> ' . $p_warning;
160  $str.="<ol class=\"notice\">";
161  for ($i = 0; $i < count($pa_msg); $i++)
162  {
163  $str.="<li>" . $pa_msg[$i] . "</li>";
164  }
165  $str.='</ol>';
166  $str.='</p>';
167  return $str;
168  }
169 
170  /**
171  * reverse the operation by creating the opposite one,
172  * the result is to avoid it
173  * it must be done in
174  * - jrn
175  * - jrnx
176  * - quant_fin
177  * - quant_sold
178  * - quant_purchase
179  * - stock
180  * - ANC
181  * @param $p_date is the date of the reversed op
182  * @exception if date is invalid or other prob
183  * @note automatically create a reconciliation between operation
184  * You must set the ledger_id $this->jrn_def_id
185  * This function should be in operation or call an acc_operation object
186  *
187  */
188  function reverse($p_date)
189  {
190  global $g_user;
191  try
192  {
193  $this->db->start();
194  if (!isset($this->jr_id) || $this->jr_id == '')
195  throw new Exception(_("this->jr_id is not set ou opération inconnue"));
196 
197  /* check if the date is valid */
198  if (isDate($p_date) == null)
199  throw new Exception(_('Date invalide') . $p_date);
200 
201  // if the operation is in a closed or centralized period
202  // the operation is voided thanks the opposite operation
203  $grp_new = $this->db->get_next_seq('s_grpt');
204  $seq = $this->db->get_next_seq("s_jrn");
205  $p_internal = $this->compute_internal_code($seq);
206  $this->jr_grpt_id = $this->db->get_value('select jr_grpt_id from jrn where jr_id=$1', array($this->jr_id));
207  if ($this->db->count() == 0)
208  throw new Exception(_("Cette opération n'existe pas"));
209  $this->jr_internal = $this->db->get_value('select jr_internal from jrn where jr_id=$1', array($this->jr_id));
210  if ($this->db->count() == 0 || trim($this->jr_internal) == '')
211  throw new Exception(_("Cette opération n'existe pas"));
212 
213  /* find the periode thanks the date */
214  $per = new Periode($this->db);
215  $per->jrn_def_id = $this->id;
216  $per->find_periode($p_date);
217 
218  if ($per->is_open() == 0)
219  throw new Exception(_('PERIODE FERMEE'));
220 
221 
222 
223 
224 
225  // Mark the operation invalid into the ledger
226  // to avoid to nullify twice the same op.
227  $sql = "update jrn set jr_comment='extourne : '||jr_comment where jr_id=$1";
228  $Res = $this->db->exec_sql($sql, array($this->jr_id));
229 
230  // Check return code
231  if ($Res == false)
232  throw new Exception(__FILE__ . __LINE__ . "sql a echoue [ $sql ]");
233 
234  //////////////////////////////////////////////////
235  // Reverse in jrnx* tables
236  //////////////////////////////////////////////////
237  $a_jid = $this->db->get_array("select j_id,j_debit from jrnx where j_grpt=$1", array($this->jr_grpt_id));
238  for ($l = 0; $l < count($a_jid); $l++)
239  {
240  $row = $a_jid[$l]['j_id'];
241  // Make also the change into jrnx
242  $sql = "insert into jrnx (
243  j_date,j_montant,j_poste,j_grpt,
244  j_jrn_def,j_debit,j_text,j_internal,j_tech_user,j_tech_per,j_qcode
245  ) select to_date($1,'DD.MM.YYYY'),j_montant,j_poste,$2,
246  j_jrn_def,not (j_debit),j_text,$3,$4,$5,
247  j_qcode
248  from
249  jrnx
250  where j_id=$6 returning j_id";
251  $Res = $this->db->exec_sql($sql, array($p_date, $grp_new, $p_internal, $g_user->id, $per->p_id, $row));
252  // Check return code
253  if ($Res == false)
254  throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]"));
255  $aj_id = $this->db->fetch(0);
256  $j_id = $aj_id['j_id'];
257 
258  /* automatic lettering */
259  $let = new Lettering($this->db);
260  $let->insert_couple($j_id, $row);
261 
262  // reverse in QUANT_SOLD
263  $Res = $this->db->exec_sql("INSERT INTO quant_sold(
264  qs_internal, qs_fiche, qs_quantite, qs_price, qs_vat,
265  qs_vat_code, qs_client, qs_valid, j_id)
266  SELECT $1, qs_fiche, qs_quantite*(-1), qs_price*(-1), qs_vat*(-1),
267  qs_vat_code, qs_client, qs_valid, $2
268  FROM quant_sold where j_id=$3", array($p_internal, $j_id, $row));
269 
270  if ($Res == false)
271  throw new Exception(__FILE__ . __LINE__ . "sql a echoue [ $sql ]");
272  $Res = $this->db->exec_sql("INSERT INTO quant_purchase(
273  qp_internal, j_id, qp_fiche, qp_quantite, qp_price, qp_vat,
274  qp_vat_code, qp_nd_amount, qp_nd_tva, qp_nd_tva_recup, qp_supplier,
275  qp_valid, qp_dep_priv)
276  SELECT $1, $2, qp_fiche, qp_quantite*(-1), qp_price*(-1), qp_vat*(-1),
277  qp_vat_code, qp_nd_amount*(-1), qp_nd_tva*(-1), qp_nd_tva_recup*(-1), qp_supplier,
278  qp_valid, qp_dep_priv*(-1)
279  FROM quant_purchase where j_id=$3", array($p_internal, $j_id, $row));
280 
281  if ($Res == false)
282  throw new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]");
283  }
284  $sql = "insert into jrn (
285  jr_id,
286  jr_def_id,
287  jr_montant,
288  jr_comment,
289  jr_date,
290  jr_grpt_id,
291  jr_internal
292  ,jr_tech_per, jr_valid
293  )
294  select $1,jr_def_id,jr_montant,jr_comment,
295  to_date($2,'DD.MM.YYYY'),$3,$4,
296  $5, true
297  from
298  jrn
299  where jr_id=$6";
300  $Res = $this->db->exec_sql($sql, array($seq, $p_date, $grp_new, $p_internal, $per->p_id, $this->jr_id));
301  // Check return code
302  if ($Res == false)
303  throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]"));
304  // reverse in QUANT_FIN table
305  $Res = $this->db->exec_sql(" INSERT INTO quant_fin(
306  qf_bank, qf_other, qf_amount,jr_id)
307  SELECT qf_bank, qf_other, qf_amount*(-1),$1
308  FROM quant_fin where jr_id=$2", array($seq, $this->jr_id));
309  if ($Res == false)
310  throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR[ $sql ]"));
311 
312  // Add a "concerned operation to bound these op.together
313  //
314  $rec = new Acc_Reconciliation($this->db);
315  $rec->set_jr_id($seq);
316  $rec->insert($this->jr_id);
317 
318  // Check return code
319  if ($Res == false)
320  {
321  throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]"));
322  }
323 
324 
325 
326  // the table stock must updated
327  // also in the stock table
328  $sql = "delete from stock_goods where sg_id = any ( select sg_id
329  from stock_goods natural join jrnx where j_grpt=" . $this->jr_grpt_id . ")";
330  $Res = $this->db->exec_sql($sql);
331  if ($Res == false)
332  throw (new Exception(__FILE__ . __LINE__ . "SQL ERROR [ $sql ]"));
333  $this->db->commit();
334  }
335  catch (Exception $e)
336  {
337  $this->db->rollback();
338  throw $e;
339  }
340  }
341 
342  /**
343  * @brief Return the name of a ledger
344  *
345  */
346 
347  function get_name()
348  {
349  if ($this->id == 0)
350  {
351  $this->name = _("Grand Livre");
352  return $this->name;
353  }
354 
355  $Res = $this->db->exec_sql("select jrn_def_name from " .
356  " jrn_def where jrn_def_id=$1", array($this->id));
358  if ($Max == 0)
359  return null;
361  $this->name = $ret['jrn_def_name'];
362  return $ret['jrn_def_name'];
363  }
364 
365  /**
366  * @brief Get The data
367  *
368  *
369  * @paramp_from from periode
370  * @paramp_to to periode
371  * @paramp_limit starting line
372  * @paramp_offset number of lines
373  * \return Array with the asked data
374  *
375  */
376 
377  function get_row($p_from, $p_to, $p_limit = -1, $p_offset = -1)
378  {
379  global $g_user;
380  $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'jr_tech_per');
381 
382  $cond_limite = ($p_limit != -1) ? " limit " . $p_limit . " offset " . $p_offset : "";
383  // retrieve the type
384  $this->get_type();
385  // Grand livre == 0
386  if ($this->id != 0)
387  {
388  $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,
389  jr_internal,
390  case j_debit when 't' then j_montant::text else ' ' end as deb_montant,
391  case j_debit when 'f' then j_montant::text else ' ' end as cred_montant,
392  j_debit as debit,j_poste as poste,j_qcode,jr_montant , " .
393  "case when j_text='' or j_text is null then pcm_lib else j_text end as description,j_grpt as grp,
394  jr_comment||' ('||jr_internal||')' as jr_comment,
395  jr_pj_number,
396  j_qcode,
397  jr_rapt as oc, j_tech_per as periode
398  from jrnx left join jrn on " .
399  "jr_grpt_id=j_grpt " .
400  " left join tmp_pcmn on pcm_val=j_poste " .
401  " where j_jrn_def=" . $this->id .
402  " and " . $periode . " order by j_date::date asc,substring(jr_pj_number,'[0-9]+$')::numeric asc,j_grpt,j_debit desc " .
403  $cond_limite);
404  }
405  else
406  {
407  $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,
408  jr_internal,
409  case j_debit when 't' then j_montant::text else ' ' end as deb_montant,
410  case j_debit when 'f' then j_montant::text else ' ' end as cred_montant,
411  j_debit as debit,j_poste as poste,j_qcode," .
412  "case when j_text='' or j_text is null then pcm_lib else j_text end as description,j_grpt as grp,
413  jr_comment||' ('||jr_internal||')' as jr_comment,
414  jr_pj_number,
415  jr_montant,
416  j_qcode,
417  jr_rapt as oc, j_tech_per as periode from jrnx left join jrn on " .
418  "jr_grpt_id=j_grpt left join tmp_pcmn on pcm_val=j_poste
419  join jrn_def on (jr_def_id=jrn_def_id)
420  where " .
421  $g_user->get_ledger_sql() . " and " .
422  " " . $periode . " order by j_date::date,substring(jr_pj_number,'[0-9]+$') asc,j_grpt,j_debit desc " .
423  $cond_limite);
424  }
425 
426 
427  $array = array();
429  if ($Max == 0)
430  return null;
431  $case = "";
432  $tot_deb = 0;
433  $tot_cred = 0;
435  for ($i = 0; $i < $Max; $i++)
436  {
437  $fiche = new Fiche($this->db);
438  $line = $row[$i];
439  $mont_deb = ($line['deb_montant'] != 0) ? sprintf("% 8.2f", $line['deb_montant']) : "";
440  $mont_cred = ($line['cred_montant'] != 0) ? sprintf("% 8.2f", $line['cred_montant']) : "";
441  $jr_montant = ($line['jr_montant'] != 0) ? sprintf("% 8.2f", $line['jr_montant']) : "";
442  $tot_deb+=$line['deb_montant'];
443  $tot_cred+=$line['cred_montant'];
444  $tot_op = $line['jr_montant'];
445 
446  /* Check first if there is a quickcode */
447  if (strlen(trim($line['description'])) == 0 && strlen(trim($line['j_qcode'])) != 0)
448  {
449  if ($fiche->get_by_qcode($line['j_qcode'], false) == 0)
450  {
451  $line['description'] = $fiche->strAttribut(ATTR_DEF_NAME);
452  }
453  }
454  if ($case != $line['grp'])
455  {
456  $case = $line['grp'];
457  // for financial, we show if the amount is or not in negative
458  if ($this->type == 'FIN')
459  {
460  $amount = $this->db->get_value('select qf_amount from quant_fin where jr_id=$1', array($line['jr_id']));
461  /* if nothing is found */
462  if ($this->db->count() == 0)
463  $tot_op = $jr_montant;
464  else if ($amount < 0)
465  {
466  $tot_op = $amount;
467  }
468  }
469  $array[] = array(
470  'jr_id' => $line['jr_id'],
471  'int_j_id' => $line['int_j_id'],
472  'j_id' => $line['j_id'],
473  'j_date' => $line['j_date'],
474  'internal' => $line['jr_internal'],
475  'deb_montant' => '',
476  'cred_montant' => ' ',
477  'description' => '<b><i>' . h($line['jr_comment']) . ' [' . $tot_op . '] </i></b>',
478  'poste' => $line['oc'],
479  'j_qcode' => $line['j_qcode'],
480  'periode' => $line['periode'],
481  'jr_pj_number' => $line ['jr_pj_number']);
482 
483  $array[] = array(
484  'jr_id' => '',
485  'int_j_id' => $line['int_j_id'],
486  'j_id' => '',
487  'j_date' => '',
488  'internal' => '',
489  'deb_montant' => $mont_deb,
490  'cred_montant' => $mont_cred,
491  'description' => $line['description'],
492  'poste' => $line['poste'],
493  'j_qcode' => $line['j_qcode'],
494  'periode' => $line['periode'],
495  'jr_pj_number' => ''
496  );
497  }
498  else
499  {
500  $array[] = array(
501  'jr_id' => $line['jr_id'],
502  'int_j_id' => $line['int_j_id'],
503  'j_id' => '',
504  'j_date' => '',
505  'internal' => '',
506  'deb_montant' => $mont_deb,
507  'cred_montant' => $mont_cred,
508  'description' => $line['description'],
509  'poste' => $line['poste'],
510  'j_qcode' => $line['j_qcode'],
511  'periode' => $line['periode'],
512  'jr_pj_number' => '');
513  }
514  }
515  $this->row = $array;
516  $a = array($array, $tot_deb, $tot_cred);
517  return $a;
518  }
519 
520  /** @brief Get simplified row from ledger
521  *
522  * @param p_from periode
523  * @param p_to periode
524  * @param p_limit starting line
525  * @param p_offset number of lines
526  * @param trunc if data must be truncated (pdf export)
527  *
528  * \return an Array with the asked data
529  */
530 
531  function get_rowSimple($p_from, $p_to, $trunc = 0, $p_limit = -1, $p_offset = -1)
532  {
533  global $g_user;
534  // Grand-livre : id= 0
535  //---
536  $jrn = ($this->id == 0 ) ? "and " . $g_user->get_ledger_sql() : "and jrn_def_id = " . $this->id;
537 
538  $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'jr_tech_per');
539 
540  $cond_limite = ($p_limit != -1) ? " limit " . $p_limit . " offset " . $p_offset : "";
541  //---
542  $sql = "
543  SELECT jrn.jr_id as jr_id ,
544  jrn.jr_id as num ,
545  jrn.jr_def_id as jr_def_id,
546  jrn.jr_montant as montant,
547  substr(jrn.jr_comment,1,35) as comment,
548  to_char(jrn.jr_date,'DD-MM-YYYY') as date,
549  to_char(jrn.jr_date_paid,'DD-MM-YYYY') as date_paid,
550  jr_pj_number,
551  jr_internal,
552  jrn.jr_grpt_id as grpt_id,
553  jrn.jr_pj_name as pj,
554  jrn_def_type,
555  jrn.jr_tech_per
556  FROM jrn join jrn_def on (jrn_def_id=jr_def_id)
557  WHERE $periode $jrn order by jr_date,substring(jrn.jr_pj_number,'[0-9]+$')::numeric asc $cond_limite";
558 
559  $Res = $this->db->exec_sql($sql);
561  if ($Max == 0)
562  {
563  return null;
564  }
565  $type = $this->get_type();
566  // for type ACH and Ven we take more info
567  if ($type == 'ACH' || $type == 'VEN')
568  {
569  $a_ParmCode = $this->db->get_array('select p_code,p_value from parm_code');
570  $a_TVA = $this->db->get_array('select tva_id,tva_label,tva_poste
571  from tva_rate where tva_rate != 0 order by tva_rate,tva_label,tva_id ');
572  for ($i = 0; $i < $Max; $i++)
573  {
574  $array[$i] = Database::fetch_array($Res, $i);
575  $p = $this->get_detail($array[$i], $type, $trunc, $a_TVA, $a_ParmCode);
576  if ($array[$i]['dep_priv'] != 0.0)
577  {
578  $array[$i]['comment'].="(priv. " . $array[$i]['dep_priv'] . ")";
579  }
580  }
581  }
582  else
583  {
585  }
586 
587  return $array;
588  }
589 
590 // end function get_rowSimple
591 
592  /**
593  * @brief guess what the next pj should be
594  */
595 
596  function guess_pj()
597  {
598  $prop = $this->get_propertie();
599  $pj_pref = $prop["jrn_def_pj_pref"];
600  $pj_seq = $this->get_last_pj() + 1;
601  return $pj_pref . $pj_seq;
602  }
603 
604  /**
605  * @brief Show all the operation
606  * @param$sql is the sql stmt, normally created by build_search_sql
607  * @param$offset the offset
608  * @param$p_paid if we want to see info about payment
609  @code
610  // Example
611  // Build the sql
612  list($sql,$where)=$Ledger->build_search_sql($_GET);
613  // Count nb of line
614  $max_line=$this->db->count_sql($sql);
615 
616  $step=$_SESSION['g_pagesize'];
617  $page=(isset($_GET['offset']))?$_GET['page']:1;
618  $offset=(isset($_GET['offset']))?$_GET['offset']:0;
619  // create the nav. bar
620  $bar=navigation_bar($offset,$max_line,$step,$page);
621  // show a part
622  list($count,$html)= $Ledger->list_operation($sql,$offset,0);
623  echo $html;
624  // show nav bar
625  echo $bar;
626 
627  @endcode
628  * @see build_search_sql
629  * @see display_search_form
630  * @see search_form
631 
632  * @return HTML string
633  */
634 
635  public function list_operation_to_reconcile($sql,$p_target)
636  {
637  global $g_parameter, $g_user;
639  $limit = " LIMIT ".MAX_RECONCILE;
640  // Sort
641  // Count
642  $count = $this->db->count_sql($sql);
643  // Add the limit
644  $sql.=" order by jr_date asc " . $limit;
645 
646  // Execute SQL stmt
647  $Res = $this->db->exec_sql($sql);
648 
649  //starting from here we can refactor, so that instead of returning the generated HTML,
650  //this function returns a tree structure.
651 
652  $r = "";
653 
654 
656 
657  if ($Max == 0)
658  return array(0, _("Aucun enregistrement trouvé"));
659  $r.=HtmlInput::hidden("target", $p_target);
660  $r.='<table class="result">';
661 
662 
663  $r.="<tr >";
664  $r.="<th>"._("Selection")."</th>";
665  $r.="<th>"._("Internal")."</th>";
666 
667  if ($this->type == 'ALL')
668  {
669  $r.=th(_('Journal'));
670  }
671 
672  $r.='<th>'._("Date").'</th>';
673  $r.='<th>'._("Pièce").'</td>';
674  $r.=th(_('tiers'));
675  $r.='<th>'._("Description").'</th>';
676  $r.=th(_('Notes'), ' ');
677  $r.='<th>'._("Montant").'</th>';
678  $r.="<th>" . _('Concerne') . "</th>";
679  $r.="</tr>";
680  // Total Amount
681  $tot = 0.0;
684  for ($i = 0; $i < $Max; $i++)
685  {
686 
687 
689 
690  if ($i % 2 == 0)
691  $tr = '<TR class="odd">';
692  else
693  $tr = '<TR class="even">';
694  $r.=$tr;
695  // Radiobox
696  //
697 
698  $r.='<td><INPUT TYPE="CHECKBOX" name="jr_concerned' . $row['jr_id'] . '" ID="jr_concerned' . $row['jr_id'] . '" value="'.$row['quick_code'].'"> </td>';
699  //internal code
700  // button modify
701  $r.="<TD>";
702  // If url contains
703  //
704 
705  $href = basename($_SERVER['PHP_SELF']);
706 
707 
708  $r.=sprintf('<A class="detail" style="text-decoration:underline" HREF="javascript:modifyOperation(\'%s\',\'%s\')" >%s </A>', $row['jr_id'], $gDossier, $row['jr_internal']);
709  $r.="</TD>";
710  if ($this->type == 'ALL')
711  $r.=td($row['jrn_def_name']);
712  // date
713  $r.="<TD>";
714  $r.=$row['str_jr_date'];
715  $r.="</TD>";
716 
717  // pj
718  $r.="<TD>";
719  $r.=$row['jr_pj_number'];
720  $r.="</TD>";
721 
722  // Tiers
723  $other = ($row['quick_code'] != '') ? '[' . $row['quick_code'] . '] ' . $row['name'] . ' ' . $row['first_name'] : '';
724  $r.=td($other);
725  // comment
726  $r.="<TD>";
727  $tmp_jr_comment = h($row['jr_comment']);
728  $r.=$tmp_jr_comment;
729  $r.="</TD>";
730  $r.=td(h($row['n_text']), ' style="font-size:0.87em"');
731  // Amount
732  // If the ledger is financial :
733  // the credit must be negative and written in red
734  $positive = 0;
735 
736  // Check ledger type :
737  if ($row['jrn_def_type'] == 'FIN')
738  {
739  $positive = $this->db->get_value("select qf_amount from quant_fin where jr_id=$1", array($row['jr_id']));
740  if ($this->db->count() != 0)
741  $positive = ($positive < 0) ? 1 : 0;
742  }
743  $r.="<TD align=\"right\">";
744 
745  $r.=( $positive != 0 ) ? "<font color=\"red\"> - " . nbm($row['jr_montant']) . "</font>" : nbm($row['jr_montant']);
746  $r.="</TD>";
747 
748 
749 
750  // Rapprochement
751  $rec = new Acc_Reconciliation($this->db);
752  $rec->set_jr_id($row['jr_id']);
753  $a = $rec->get();
754  $r.="<TD>";
755  if ($a != null)
756  {
757 
758  foreach ($a as $key => $element)
759  {
760  $operation = new Acc_Operation($this->db);
761  $operation->jr_id = $element;
762  $l_amount = $this->db->get_value("select jr_montant from jrn " .
763  " where jr_id=$1",array($element));
764  $r.= "<A class=\"detail\" HREF=\"javascript:modifyOperation('" . $element . "'," . $gDossier . ")\" > " . $operation->get_internal() . "[" . nbm($l_amount) . "]</A>";
765  }//for
766  }// if ( $a != null ) {
767  $r.="</TD>";
768 
769  if ($row['jr_valid'] == 'f')
770  {
771  $r.="<TD>"._("Opération annulée")."</TD>";
772  }
773  // end row
774  $r.="</tr>";
775  }
776  $r.='</table>';
777  return array($count, $r);
778  }
779 
780  /**
781  * @brief Show all the operation
782  * @param$sql is the sql stmt, normally created by build_search_sql
783  * @param$offset the offset
784  * @param$p_paid if we want to see info about payment
785  \code
786  // Example
787  // Build the sql
788  list($sql,$where)=$Ledger->build_search_sql($_GET);
789  // Count nb of line
790  $max_line=$cn->count_sql($sql);
791 
792  $step=$_SESSION['g_pagesize'];
793  $page=(isset($_GET['offset']))?$_GET['page']:1;
794  $offset=(isset($_GET['offset']))?$_GET['offset']:0;
795  // create the nav. bar
796  $bar=navigation_bar($offset,$max_line,$step,$page);
797  // show a part
798  list($count,$html)= $Ledger->list_operation($sql,$offset,0);
799  echo $html;
800  // show nav bar
801  echo $bar;
802 
803  \endcode
804  * \see build_search_sql
805  * \see display_search_form
806  * \see search_form
807 
808  * \return HTML string
809  */
810 
811  public function list_operation($sql, $offset, $p_paid = 0)
812  {
813  global $g_parameter, $g_user;
814  bcscale(2);
815  $table = new Sort_Table();
817  $amount_paid = 0.0;
818  $amount_unpaid = 0.0;
819  $limit = ($_SESSION['g_pagesize'] != -1) ? " LIMIT " . $_SESSION['g_pagesize'] : "";
820  $offset = ($_SESSION['g_pagesize'] != -1) ? " OFFSET " . Database::escape_string($offset) : "";
821  $order = " order by jr_date_order asc,jr_internal asc";
822  // Sort
823  $url = "?" . CleanUrl();
824  $str_dossier = dossier::get();
825  $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");
826  $table->add(_('Echeance'), $url, " order by jr_ech asc", " order by jr_ech desc", 'ea', 'ed');
827  $table->add(_('Paiement'), $url, " order by jr_date_paid asc", " order by jr_date_paid desc", 'eap', 'edp');
828  $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");
829  $table->add(_('Tiers'), $url, " order by name asc", " order by name desc", 'na', 'nd');
830  $table->add(_('Montant'), $url, " order by jr_montant asc", " order by jr_montant desc", "ma", "md");
831  $table->add(_("Description"), $url, "order by jr_comment asc", "order by jr_comment desc", "ca", "cd");
832 
833  $ord = (!isset($_GET['ord'])) ? 'da' : $_GET['ord'];
834  $order = $table->get_sql_order($ord);
835 
836  // Count
837  $count = $this->db->count_sql($sql);
838  // Add the limit
839  $sql.=$order . $limit . $offset;
840  // Execute SQL stmt
841  $Res = $this->db->exec_sql($sql);
842 
843  //starting from here we can refactor, so that instead of returning the generated HTML,
844  //this function returns a tree structure.
845 
846  $r = "";
847 
848 
850 
851  if ($Max == 0)
852  return array(0, _("Aucun enregistrement trouvé"));
853 
854  $r.='<table class="result">';
855 
856 
857  $r.="<tr >";
858  $r.="<th>"._("n° interne")."</th>";
859  if ($this->type == 'ALL')
860  {
861  $r.=th('Journal');
862  }
863  $r.='<th>' . $table->get_header(0) . '</th>';
864  if ($p_paid != 0 ) $r.='<th>' . $table->get_header(1) . '</td>';
865  if ($p_paid != 0 ) $r.='<th>' . $table->get_header(2) . '</th>';
866  $r.='<th>' . $table->get_header(3) . '</th>';
867  $r.='<th>' . $table->get_header(4) . '</th>';
868  $r.='<th>' . $table->get_header(6) . '</th>';
869  $r.=th('Notes', ' style="width:15%"');
870  $r.='<th>' . $table->get_header(5) . '</th>';
871  // if $p_paid is not equal to 0 then we have a paid column
872  if ($p_paid != 0)
873  {
874  $r.="<th> " . _('Payé') . "</th>";
875  }
876  $r.="<th>" . _('Concerne') . "</th>";
877  $r.="<th>" . _('Document') . "</th>";
878  $r.="</tr>";
879  // Total Amount
880  $tot = 0.0;
882  for ($i = 0; $i < $Max; $i++)
883  {
884 
885 
887 
888  if ($i % 2 == 0)
889  $tr = '<TR class="odd">';
890  else
891  $tr = '<TR class="even">';
892  $r.=$tr;
893  //internal code
894  // button modify
895  $r.="<TD>";
896  // If url contains
897  //
898 
899  $href = basename($_SERVER['PHP_SELF']);
900 
901 
902  $r.=sprintf('<A class="detail" style="text-decoration:underline" HREF="javascript:modifyOperation(\'%s\',\'%s\')" >%s </A>', $row['jr_id'], $gDossier, $row['jr_internal']);
903  $r.="</TD>";
904  if ($this->type == 'ALL')
905  $r.=td($row['jrn_def_name']);
906  // date
907  $r.="<TD>";
908  $r.=$row['str_jr_date'];
909  $r.="</TD>";
910  // echeance
911  if ($p_paid != 0 )
912  {
913  $r.="<TD>";
914  $r.=$row['str_jr_ech'];
915  $r.="</TD>";
916  $r.="<TD>";
917  $r.=$row['str_jr_date_paid'];
918  $r.="</TD>";
919  }
920 
921  // pj
922  $r.="<TD>";
923  $r.=$row['jr_pj_number'];
924  $r.="</TD>";
925 
926  // Tiers
927  $other = ($row['quick_code'] != '') ? '[' . $row['quick_code'] . '] ' . $row['name'] . ' ' . $row['first_name'] : '';
928  $r.=td($other);
929  // comment
930  $r.="<TD>";
931  $tmp_jr_comment = h($row['jr_comment']);
932  $r.=$tmp_jr_comment;
933  $r.="</TD>";
934  $r.=td(h($row['n_text']), ' style="font-size:0.87em%"');
935  // Amount
936  // If the ledger is financial :
937  // the credit must be negative and written in red
938  $positive = 0;
939 
940  // Check ledger type :
941  if ($row['jrn_def_type'] == 'FIN')
942  {
943  $positive = $this->db->get_value("select qf_amount from quant_fin where jr_id=$1", array($row['jr_id']));
944  if ($this->db->count() != 0)
945  $positive = ($positive < 0) ? 1 : 0;
946  }
947  $r.="<TD align=\"right\">";
948  $t_amount=$row['jr_montant'];
949  if ($row['total_invoice'] != null && $row['total_invoice'] != $row['jr_montant'])
950  $t_amount=$row['total_invoice'];
951  $tot = ($positive != 0) ? bcsub($tot , $t_amount ): bcadd($tot , $t_amount);
952  //STAN $positive always == 0
953  if ($row [ 'jrn_def_type']=='FIN')
954  {
955  $r.=( $positive != 0 ) ? "<font color=\"red\"> - " . nbm($t_amount) . "</font>" : nbm($t_amount);
956  }
957  else
958  {
959  $r.=( $t_amount < 0 ) ? "<font color=\"red\"> " . nbm($t_amount) . "</font>" : nbm($t_amount);
960  }
961  $r.="</TD>";
962 
963 
964  // Show the paid column if p_paid is not null
965  if ($p_paid != 0)
966  {
967  $w = new ICheckBox();
968  $w->name = "rd_paid" . $row['jr_id'];
969  $w->selected = ($row['jr_rapt'] == 'paid') ? true : false;
970  // if p_paid == 2 then readonly
971  $w->readonly = ( $p_paid == 2) ? true : false;
972  $h = new IHidden();
973  $h->name = "set_jr_id" . $row['jr_id'];
974  $r.='<TD>' . $w->input() . $h->input() . '</TD>';
975  if ($row['jr_rapt'] == 'paid')
976  $amount_paid=bcadd($amount_paid,$t_amount);
977  else
978  $amount_unpaid=bcadd($amount_unpaid,$t_amount);
979  }
980 
981  // Rapprochement
982  $rec = new Acc_Reconciliation($this->db);
983  $rec->set_jr_id($row['jr_id']);
984  $a = $rec->get();
985  $r.="<TD>";
986  if ($a != null)
987  {
988 
989  foreach ($a as $key => $element)
990  {
991  $operation = new Acc_Operation($this->db);
992  $operation->jr_id = $element;
993  $l_amount = $this->db->get_value("select jr_montant from jrn " .
994  " where jr_id=$1",array($element));
995  $r.= "<A class=\"detail\" HREF=\"javascript:modifyOperation('" . $element . "'," . $gDossier . ")\" > " . $operation->get_internal() . "[" . nbm($l_amount) . "]</A>";
996  }//for
997  }// if ( $a != null ) {
998  $r.="</TD>";
999 
1000  if ($row['jr_valid'] == 'f')
1001  {
1002  $r.="<TD>"._("Opération annulée")."</TD>";
1003  }
1004  else
1005  {
1006 
1007  } // else
1008  //document
1009  if ($row['jr_pj_name'] != "")
1010  {
1011  $r.='<td>'.HtmlInput::show_receipt_document($row['jr_id']).'</td>';
1012  }
1013  else
1014  $r.="<TD></TD>";
1015 
1016  // end row
1017  $r.="</tr>";
1018  }
1019  $amount_paid = round($amount_paid, 4);
1020  $amount_unpaid = round($amount_unpaid, 4);
1021  $tot = round($tot, 4);
1022  $r.="<TR>";
1023  $r.='<TD COLSPAN="5">Total</TD>';
1024  $r.='<TD ALIGN="RIGHT">' . nbm($tot) . "</TD>";
1025  $r.="</tr>";
1026  if ($p_paid != 0)
1027  {
1028  $r.="<TR>";
1029  $r.='<TD COLSPAN="5">'._("Payé").'</TD>';
1030  $r.='<TD ALIGN="RIGHT">' . nbm($amount_paid) . "</TD>";
1031  $r.="</tr>";
1032  $r.="<TR>";
1033  $r.='<TD COLSPAN="5">'._("Non payé").'</TD>';
1034  $r.='<TD ALIGN="RIGHT">' . nbm($amount_unpaid) . "</TD>";
1035  $r.="</tr>";
1036  }
1037  $r.="</table>";
1038 
1039  return array($count, $r);
1040  }
1041 
1042  /**
1043  * @brief get_detail gives the detail of row
1044  * this array must contains at least the field
1045  * <ul>
1046  * <li> montant</li>
1047  * <li> grpt_id
1048  * </ul>
1049  * the following field will be added
1050  * <ul>
1051  * <li> HTVA
1052  * <li> TVAC
1053  * <li> TVA array with
1054  * <ul>
1055  * <li> field 0 idx
1056  * <li> array containing tva_id,tva_label and tva_amount
1057  * </ul>
1058  * </ul>
1059  *
1060  * @paramp_array the structure is set in get_rowSimple, this array is
1061  * modified,
1062  * @param $trunc if the data must be truncated, usefull for pdf export
1063  * @paramp_jrn_type is the type of the ledger (ACH or VEN)
1064  * @param $a_TVA TVA Array (default null)
1065  * @param $a_ParmCode Array (default null)
1066  * \return p_array
1067  */
1068 
1069  function get_detail(&$p_array, $p_jrn_type, $trunc = 0, $a_TVA = null, $a_ParmCode = null)
1070  {
1071  bcscale(2);
1072 
1073  if ($a_TVA == null)
1074  {
1075  //Load TVA array
1076  $a_TVA = $this->db->get_array('select tva_id,tva_label,tva_poste
1077  from tva_rate where tva_rate != 0 order by tva_rate,tva_label,tva_id');
1078  }
1079  if ($a_ParmCode == null)
1080  {
1081  //Load Parm_code
1082  $a_ParmCode = $this->db->get_array('select p_code,p_value from parm_code');
1083  }
1084  // init
1085  $p_array['client'] = "";
1086  $p_array['TVAC'] = 0;
1087  $p_array['TVA'] = array();
1088  $p_array['AMOUNT_TVA'] = 0.0;
1089  $p_array['dep_priv'] = 0;
1090  $p_array['dna'] = 0;
1091  $p_array['tva_dna'] = 0;
1092  $p_array['tva_np'] = 0;
1093  $dep_priv = 0.0;
1094 
1095  //
1096  // Retrieve data from jrnx
1097  $sql = "select j_id,j_poste,j_montant, j_debit,j_qcode from jrnx where " .
1098  " j_grpt=" . $p_array['grpt_id'];
1099  $Res2 = $this->db->exec_sql($sql);
1100  $data_jrnx = Database::fetch_all($Res2);
1101  $c = 0;
1102 
1103  // Parse data from jrnx and fill diff. field
1104  foreach ($data_jrnx as $code)
1105  {
1106  $idx_tva = 0;
1107  $poste = new Acc_Account_Ledger($this->db, $code['j_poste']);
1108 
1109  // if card retrieve name if the account is not a VAT account
1110  if (strlen(trim($code['j_qcode'])) != 0 && $poste->isTva() == 0)
1111  {
1112  $fiche = new Fiche($this->db);
1113  $fiche->get_by_qcode(trim($code['j_qcode']), false);
1114  $fiche_def_id = $fiche->get_fiche_def_ref_id();
1115  // Customer or supplier
1116  if ($fiche_def_id == FICHE_TYPE_CLIENT ||
1117  $fiche_def_id == FICHE_TYPE_FOURNISSEUR
1118  ||$fiche_def_id == FICHE_TYPE_ADM_TAX)
1119  {
1120  $p_array['TVAC'] = $code['j_montant'];
1121 
1122  $p_array['client'] = ($trunc == 0) ? $fiche->getName() : mb_substr($fiche->getName(), 0, 20);
1123  $p_array['reversed'] = false;
1124  if ($fiche_def_id == FICHE_TYPE_CLIENT && $code['j_debit'] == 'f')
1125  {
1126  $p_array['reversed'] = true;
1127  $p_array['TVAC']*=-1;
1128  }
1129  if ($fiche_def_id == FICHE_TYPE_ADM_TAX && $code['j_debit'] == 'f')
1130  {
1131  $p_array['reversed'] = true;
1132  $p_array['TVAC']*=-1;
1133  }
1134  if ($fiche_def_id == FICHE_TYPE_FOURNISSEUR && $code['j_debit'] == 't')
1135  {
1136  $p_array['reversed'] = true;
1137  $p_array['TVAC']*=-1;
1138  }
1139  }
1140  else
1141  {
1142  // if we use the ledger ven / ach for others card than supplier and customer
1143  if ($fiche_def_id != FICHE_TYPE_VENTE &&
1144  $fiche_def_id != FICHE_TYPE_ACH_MAR &&
1145  $fiche_def_id != FICHE_TYPE_ACH_SER &&
1146  $fiche_def_id != FICHE_TYPE_ACH_MAT
1147  )
1148  {
1149  $p_array['TVAC'] = $code['j_montant'];
1150 
1151  $p_array['client'] = ($trunc == 0) ? $fiche->getName() : mb_substr($fiche->getName(), 0, 20);
1152  $p_array['reversed'] = false;
1153  if ($p_jrn_type == 'ACH' && $code['j_debit'] == 't')
1154  {
1155  $p_array['reversed'] = true;
1156  $p_array['TVAC']*=-1;
1157  }
1158  if ($p_jrn_type == 'VEN' && $code['j_debit'] == 'f')
1159  {
1160  $p_array['reversed'] = true;
1161  $p_array['TVAC']*=-1;
1162  }
1163  }
1164  }
1165  }
1166  // if TVA, load amount, tva id and rate in array
1167  foreach ($a_TVA as $line_tva)
1168  {
1169  list($tva_deb, $tva_cred) = explode(',', $line_tva['tva_poste']);
1170  if ($code['j_poste'] == $tva_deb ||
1171  $code['j_poste'] == $tva_cred)
1172  {
1173 
1174  // For the reversed operation
1175  if ($p_jrn_type == 'ACH' && $code['j_debit'] == 'f')
1176  {
1177  $code['j_montant'] = -1 * $code['j_montant'];
1178  }
1179  if ($p_jrn_type == 'VEN' && $code['j_debit'] == 't')
1180  {
1181  $code['j_montant'] = -1 * $code['j_montant'];
1182  }
1183 
1184  $p_array['AMOUNT_TVA']+=$code['j_montant'];
1185 
1186  $p_array['TVA'][$c] = array($idx_tva, array($line_tva['tva_id'], $line_tva['tva_label'], $code['j_montant']));
1187  $c++;
1188 
1189  $idx_tva++;
1190  }
1191  }
1192 
1193  // isDNA
1194  // If operation is reversed then amount are negatif
1195  /* if ND */
1196  if ($p_array['jrn_def_type'] == 'ACH')
1197  {
1198  $purchase = new Gestion_Purchase($this->db);
1199  $purchase->search_by_jid($code['j_id']);
1200  $purchase->load();
1201  $dep_priv+=$purchase->qp_dep_priv;
1202  $p_array['dep_priv'] = $dep_priv;
1203  $p_array['dna']=bcadd($p_array['dna'],$purchase->qp_nd_amount);
1204  $p_array['tva_dna']=bcadd($p_array['tva_dna'],bcadd($purchase->qp_nd_tva,$purchase->qp_nd_tva_recup));
1205  $p_array['tva_np']=bcadd($purchase->qp_vat_sided,$p_array['tva_np']);
1206  }
1207  if ($p_array['jrn_def_type'] == 'VEN') {
1208  $sold=new gestion_sold($this->db);
1209  $sold->search_by_jid($code['j_id']);
1210  $sold->load();
1211  $p_array['tva_np']=bcadd($sold->qs_vat_sided,$p_array['tva_np']);
1212  }
1213 
1214 
1215  }
1216  $p_array['TVAC'] = sprintf('% 10.2f', $p_array['TVAC'] );
1217  $p_array['HTVA'] = sprintf('% 10.2f', $p_array['TVAC'] - $p_array['AMOUNT_TVA']-$p_array['tva_dna']);
1218  $r = "";
1219  $a_tva_amount = array();
1220  // inline TVA (used for the PDF)
1221  foreach ($p_array['TVA'] as $linetva)
1222  {
1223  foreach ($a_TVA as $tva)
1224  {
1225  if ($tva['tva_id'] == $linetva[1][0])
1226  {
1227  $a = $tva['tva_id'];
1228  $a_tva_amount[$a] = $linetva[1][2];
1229  }
1230  }
1231  }
1232  foreach ($a_TVA as $line_tva)
1233  {
1234  $a = $line_tva['tva_id'];
1235  if (isset($a_tva_amount[$a]))
1236  {
1237  $tmp = sprintf("% 10.2f", $a_tva_amount[$a]);
1238  $r.="$tmp";
1239  }
1240  else
1241  $r.=sprintf("% 10.2f", 0);
1242  }
1243  $p_array['TVA_INLINE'] = $r;
1244 
1245  return $p_array;
1246  }
1247 
1248 // retrieve data from jrnx
1249  /**
1250  * @brief Get the properties of a journal
1251  *
1252  * \return an array containing properties
1253  *
1254  */
1255 
1256  function get_propertie()
1257  {
1258  if ($this->id == 0)
1259  return;
1260 
1261  $Res = $this->db->exec_sql("select jrn_Def_id,jrn_def_name,jrn_def_class_deb,jrn_def_class_cred,jrn_def_type,
1262  jrn_deb_max_line,jrn_cred_max_line,jrn_def_ech,jrn_def_ech_lib,jrn_def_code,
1263  jrn_def_fiche_deb,jrn_def_fiche_cred,jrn_def_pj_pref
1264  from jrn_Def
1265  where jrn_def_id=$1", array($this->id));
1266  $Count = Database::num_row($Res);
1267  if ($Count == 0)
1268  {
1269  echo '<DIV="redcontent"><H2 class="error">' . _('Parametres journaux non trouves') . '</H2> </DIV>';
1270  return null;
1271  }
1272  return Database::fetch_array($Res, 0);
1273  }
1274 
1275  /**
1276  * @brief Get the number of lines of a journal
1277  * @param$p_cred deb or cred
1278  *
1279  * \return an integer
1280  */
1281 
1282  function GetDefLine()
1283  {
1284  $sql_cred = 'jrn_deb_max_line';
1285  $sql = "select jrn_deb_max_line as value from jrn_def where jrn_def_id=$1";
1286  $r = $this->db->exec_sql($sql, array($this->id));
1288  if (sizeof($Res) == 0)
1289  return 1;
1290  return $Res[0]['value'];
1291  }
1292 
1293  /**
1294  * @brief get the saldo of a ledger for a specific period
1295  * @param$p_from start period
1296  * @param$p_to end period
1297  */
1298 
1299  function get_solde($p_from, $p_to)
1300  {
1301  $ledger = "";
1302  if ($this->id != 0)
1303  {
1304  $ledger = " and j_jrn_def = " . $this->id;
1305  }
1306 
1307  $periode = sql_filter_per($this->db, $p_from, $p_to, 'p_id', 'j_tech_per');
1308  $sql = 'select j_montant as montant,j_debit as deb from jrnx where '
1309  . $periode . $ledger;
1310 
1311  $ret = $this->db->exec_sql($sql);
1313  $deb = 0.0;
1314  $cred = 0.0;
1315  foreach ($array as $line)
1316  {
1317 
1318  if ($line['deb'] == 't')
1319  $deb+=$line['montant'];
1320  else
1321  $cred+=$line['montant'];
1322  }
1323  $response = array($deb, $cred);
1324  return $response;
1325  }
1326 
1327  /**
1328  * @brief Show a select list of the ledgers you can access in
1329  * writing, reading or simply accessing.
1330  * @param$p_type = ALL or the type of the ledger (ACH,VEN,FIN,ODS)
1331  * @param$p_access =3 for READ and WRITE, 2 for write and 1 for readonly
1332  * \return object HtmlInput select
1333  */
1334 
1335  function select_ledger($p_type = "ALL", $p_access = 3)
1336  {
1337  global $g_user;
1338  $array = $g_user->get_ledger($p_type, $p_access);
1339 
1340  if ($array == null)
1341  return null;
1342  $idx = 0;
1343  $ret = array();
1344 
1345  foreach ($array as $value)
1346  {
1347  $ret[$idx]['value'] = $value['jrn_def_id'];
1348  $ret[$idx]['label'] = h($value['jrn_def_name']);
1349  $idx++;
1350  }
1351 
1352  $select = new ISelect();
1353  $select->name = 'p_jrn';
1354  $select->value = $ret;
1355  $select->selected = $this->id;
1356  return $select;
1357  }
1358 
1359  /**
1360  * @brief retrieve the jrn_def_fiche and return them into a array
1361  * index deb, cred
1362  * \param
1363  * \param
1364  * \param
1365  *
1366  *
1367  * \return return an array ('deb'=> ,'cred'=>)
1368  */
1369 
1370  function get_fiche_def()
1371  {
1372  $sql = "select jrn_def_fiche_deb as deb,jrn_def_fiche_cred as cred " .
1373  " from jrn_def where " .
1374  " jrn_def_id = $1 ";
1375 
1376  $r = $this->db->exec_sql($sql, array($this->id));
1377 
1379  if (empty($res))
1380  return null;
1381 
1382  return $res[0];
1383  }
1384 
1385  /**
1386  * @brief retrieve the jrn_def_class_deb and return it
1387  *
1388  *
1389  * \return return an string
1390  */
1391 
1392  function get_class_def()
1393  {
1394  $sql = "select jrn_def_class_deb " .
1395  " from jrn_def where " .
1396  " jrn_def_id = $1";
1397 
1398  $r = $this->db->exec_sql($sql, array($this->id));
1399 
1401 
1402  if (empty($res))
1403  return null;
1404 
1405  return $res[0];
1406  }
1407 
1408  /**
1409  * @brief show the result of the array to confirm
1410  * before inserting
1411  * @param$p_array array from the form
1412  * \return string
1413  */
1414 
1415  function confirm($p_array, $p_readonly = false)
1416  {
1417  global $g_parameter;
1418  $msg = array();
1419  if (!$p_readonly)
1420  $msg = $this->verify($p_array);
1421  $this->id = $p_array['p_jrn'];
1422  if (empty($p_array))
1423  return 'Aucun r&eacute;sultat';
1424  $anc = null;
1425  extract($p_array, EXTR_SKIP);
1426  $lPeriode = new Periode($this->db);
1427  if ($this->check_periode() == true)
1428  {
1429  $lPeriode->p_id = $period;
1430  }
1431  else
1432  {
1433  $lPeriode->find_periode($e_date);
1434  }
1435  $total_deb = 0;
1436  $total_cred = 0;
1437  bcscale(2);
1438 
1439  $ret = "";
1440  if (!empty($msg))
1441  {
1442  $ret.=$this->display_warning($msg, _("Attention : il vaut mieux utiliser les fiches que les postes comptables"));
1443  }
1444  $ret.="<table >";
1445  $ret.="<tr><td>" . _('Date') . " : </td><td>$e_date</td></tr>";
1446  /* display periode */
1447  $date_limit = $lPeriode->get_date_limit();
1448  $ret.='<tr> ' . td(_('Période Comptable')) . td($date_limit['p_start'] . '-' . $date_limit['p_end']) . '</tr>';
1449  $ret.="<tr><td>" . _('Libellé') . " </td><td>" . h($desc) . "</td></tr>";
1450  $ret.="<tr><td>" . _('PJ Num') . " </td><td>" . h($e_pj) . "</td></tr>";
1451  $ret.='</table>';
1452  $ret.="<table class=\"result\">";
1453  $ret.="<tr>";
1454  $ret.="<th>" . _('Quick Code ou ');
1455  $ret.=_("Poste") . " </th>";
1456  $ret.="<th style=\"text-align:left\"> " . _("Libellé") . " </th>";
1457  $ret.="<th style=\"text-align:right\">" . _("Débit") . "</th>";
1458  $ret.="<th style=\"text-align:right\">" . _("Crédit") . "</th>";
1459  /* if we use the AC */
1460  if ($g_parameter->MY_ANALYTIC != 'nu')
1461  {
1462  $anc = new Anc_Plan($this->db);
1463  $a_anc = $anc->get_list();
1464  $x = count($a_anc);
1465  /* set the width of the col */
1466  $ret.='<th colspan="' . $x . '" style="width:auto;text-align:center" >' . _('Compt. Analytique') . '</th>';
1467 
1468  /* add hidden variables pa[] to hold the value of pa_id */
1469  $ret.=Anc_Plan::hidden($a_anc);
1470  }
1471  $ret.="</tr>";
1472 
1473  $ret.=HtmlInput::hidden('e_date', $e_date);
1474  $ret.=HtmlInput::hidden('desc', $desc);
1475  $ret.=HtmlInput::hidden('period', $lPeriode->p_id);
1476  $ret.=HtmlInput::hidden('e_pj', $e_pj);
1477  $ret.=HtmlInput::hidden('e_pj_suggest', $e_pj_suggest);
1478  $mt = microtime(true);
1479  $ret.=HtmlInput::hidden('mt', $mt);
1480  // For predefined operation
1481  $ret.=HtmlInput::hidden('e_comm', $desc);
1482  $ret.=HtmlInput::hidden('jrn_type', $this->get_type());
1483  $ret.=HtmlInput::hidden('p_jrn', $this->id);
1484  $ret.=HtmlInput::hidden('nb_item', $nb_item);
1485  if ($this->with_concerned == true)
1486  {
1487  $ret.=HtmlInput::hidden('jrn_concerned', $jrn_concerned);
1488  }
1489  $ret.=dossier::hidden();
1490  $count = 0;
1491  for ($i = 0; $i < $nb_item; $i++)
1492  {
1493  if ($p_readonly == true)
1494  {
1495  if (!isset(${'qc_' . $i}))
1496  ${'qc_' . $i} = '';
1497  if (!isset(${'poste' . $i}))
1498  ${'poste' . $i} = '';
1499  if (!isset(${'amount' . $i}))
1500  ${'amount' . $i} = '';
1501  }
1502  $class=($i%2==0)?' class="even" ':' class="odd" ';
1503  $ret.="<tr $class> ";
1504  if (trim(${'qc_' . $i}) != "")
1505  {
1506  $oqc = new Fiche($this->db);
1507  $oqc->get_by_qcode(${'qc_' . $i}, false);
1508  $strPoste = $oqc->strAttribut(ATTR_DEF_ACCOUNT);
1509  $ret.="<td>" .
1510  ${'qc_' . $i} . ' - ' .
1511  $oqc->strAttribut(ATTR_DEF_NAME) . HtmlInput::hidden('qc_' . $i, ${'qc_' . $i}) .
1512  '</td>';
1513  }
1514 
1515  if (trim(${'qc_' . $i}) == "" && trim(${'poste' . $i}) != "")
1516  {
1517  $oposte = new Acc_Account_Ledger($this->db, ${'poste' . $i});
1518  $strPoste = $oposte->id;
1519  $ret.="<td>" . h(${"poste" . $i} . " - " .
1520  $oposte->get_name()) . HtmlInput::hidden('poste' . $i, ${'poste' . $i}) .
1521  '</td>';
1522  }
1523 
1524  if (trim(${'qc_' . $i}) == "" && trim(${'poste' . $i}) == "")
1525  continue;
1526  $ret.="<td>" . h(${"ld" . $i}) . HtmlInput::hidden('ld' . $i, ${'ld' . $i}) ;
1527  $ret .=(isset(${"ck$i"})) ? HtmlInput::hidden('ck' . $i, ${'ck' . $i}) : "";
1528  $ret .= "</td>";
1529  if (isset(${"ck$i"}))
1530  {
1531  $ret.="<td class=\"num\">" . nbm(${"amount" . $i}) . HtmlInput::hidden('amount' . $i, ${'amount' . $i}) . "</td>" . td("");
1532  $total_deb = bcadd($total_deb, ${'amount' . $i});
1533  }
1534  else
1535  {
1536  $ret.=td("") . "<td class=\"num\">" . nbm(${"amount" . $i}) . HtmlInput::hidden('amount' . $i, ${'amount' . $i}) . "</td>";
1537  $total_cred = bcadd($total_cred, ${"amount" . $i});
1538  }
1539  /*$ret.="<td>";
1540  $ret.=(isset(${"ck$i"})) ? HtmlInput::hidden('ck' . $i, ${'ck' . $i}) : "";
1541  $ret.="</td>";*/
1542  // CA
1543 
1544  if ($g_parameter->MY_ANALYTIC != 'nu') // use of AA
1545  {
1546  if (preg_match("/^[6,7]+/", $strPoste) == 1)
1547  {
1548  // show form
1549  $op = new Anc_Operation($this->db);
1550  $null = ($g_parameter->MY_ANALYTIC == 'op') ? 1 : 0;
1551  $p_array['pa_id'] = $a_anc;
1552  /* op is the operation it contains either a sequence or a jrnx.j_id */
1553  $ret.=HtmlInput::hidden('op[]=', $i);
1554 
1555  $ret.='<td style="text-align:center">';
1556  $read = ($p_readonly == true) ? 0 : 1;
1557  $ret.=$op->display_form_plan($p_array, $null, $read, $count, round(${'amount' . $i}, 2));
1558  $ret.='</td>';
1559  $count++;
1560  }
1561  }
1562 
1563 
1564 
1565  $ret.="</tr>";
1566  }
1567  $ret.=tr(td('') . td(_('Totaux')) . td($total_deb, 'class="num"') . td($total_cred, 'class="num"'), 'class="highlight"');
1568  $ret.="</table>";
1569  if ($g_parameter->MY_ANALYTIC != 'nu' && $p_readonly == false)
1570  $ret.='<input type="button" class="button" value="' . _('verifie Imputation Analytique') . '" onClick="verify_ca(\'\');">';
1571  return $ret;
1572  }
1573  function get_min_row()
1574  {
1575  $row=$this->db->get_value("select jrn_deb_max_line from jrn_def where jrn_def_id=$1",array($this->id));
1576  return $row;
1577  }
1578  /**
1579  * @brief Show the form to encode your operation
1580  * @param$p_array if you correct or use a predef operation (default = null)
1581  * @param$p_readonly 1 for readonly 0 for writable (default 0)
1582  *@exception if ledger not found
1583  * \return a string containing the form
1584  */
1585 
1586  function input($p_array = null, $p_readonly = 0)
1587  {
1588  global $g_parameter, $g_user;
1589  $this->nb=$this->get_min_row();
1590  if ($p_readonly == 1)
1591  return $this->confirm($p_array);
1592 
1593  if ($p_array != null)
1594  extract($p_array, EXTR_SKIP);
1595  $add_js = "";
1596  if ($g_parameter->MY_PJ_SUGGEST == 'Y')
1597  {
1598  $add_js = "update_pj();";
1599  }
1600  if ($g_parameter->MY_DATE_SUGGEST=='Y')
1601  {
1602  $add_js.='get_last_date();';
1603  }
1604  $add_js.='update_row("quick_item");';
1605  $ret = "";
1606  if ($g_user->check_action(FICADD) == 1)
1607  {
1608  /* Add button */
1609  $f_add_button = new IButton('add_card');
1610  $f_add_button->label = _('Créer une nouvelle fiche');
1611  $f_add_button->set_attribute('ipopup', 'ipop_newcard');
1612  $f_add_button->set_attribute('jrn', $this->id);
1613  $f_add_button->javascript = " this.jrn=\$('p_jrn').value;select_card_type(this);";
1614  $f_add_button->input();
1615  }
1616  $wLedger = $this->select_ledger('ODS', 2);
1617  if ($wLedger == null)
1618  throw new Exception(_('Pas de journal disponible'));
1619  $wLedger->javascript = "onChange='update_name();update_predef(\"ods\",\"t\",\"".$_REQUEST['ac']."\");$add_js'";
1620  $label = " Journal " . HtmlInput::infobulle(2);
1621 
1622  $ret.="<table>";
1623  $ret.=tr(td($label ).td( $wLedger->input()));
1624 
1625 
1626  // Load the javascript
1627  //
1628  //$ret.= '<tr ><td colspan="2" style="width:auto">';
1629  $wDate = new IDate('e_date');
1630  $wDate->readonly = $p_readonly;
1631  $e_date = (isset($e_date) && trim($e_date) != '') ? $e_date : '';
1632  $wDate->value = $e_date;
1633 
1634  $ret.=tr(td(_("Date") ).td( $wDate->input()));
1635  /* insert periode if needed */
1636  // Periode
1637  //--
1638  if ($this->check_periode() == true)
1639  {
1640  $l_user_per = $g_user->get_periode();
1641  $def = (isset($periode)) ? $periode : $l_user_per;
1642 
1643  $period = new IPeriod("period");
1644  $period->user = $g_user;
1645  $period->cn = $this->db;
1646  $period->value = $def;
1647  $period->type = OPEN;
1648  try
1649  {
1650  $l_form_per = $period->input();
1651  }
1652  catch (Exception $e)
1653  {
1654  if ($e->getCode() == 1)
1655  {
1656  echo _("Aucune période ouverte");
1657  exit();
1658  }
1659  }
1661  $f_periode = td(_("Période comptable") . " $label " ).td( $l_form_per);
1662  $ret.=tr($f_periode);
1663  }
1664  $wPJ = new IText('e_pj');
1665  $wPJ->readonly = false;
1666  $wPJ->size = 10;
1667 
1668  /* suggest PJ ? */
1669  $default_pj = '';
1670  if ($g_parameter->MY_PJ_SUGGEST == 'Y')
1671  {
1672  $default_pj = $this->guess_pj();
1673  }
1674  $wPJ->value = (isset($e_pj)) ? $e_pj : $default_pj;
1675  $ret.= '</tr>';
1676  $ret.='<tr >';
1677  $ret.='<td colspan="2" style="width:auto"> ' . _('Pièce') . ' : ' . $wPJ->input();
1678  $ret.=HtmlInput::hidden('e_pj_suggest', $default_pj);
1679  $ret.= '</tr>';
1680  $ret.= '</td>';
1681 
1682  $ret.= '<tr>';
1683  $ret.='<td colspan="2" style="width:auto">';
1684  $ret.=_('Libellé');
1685  $wDescription = new IText('desc');
1686  $wDescription->readonly = $p_readonly;
1687  $wDescription->size = "50";
1688  $wDescription->value = (isset($desc)) ? $desc : '';
1689 
1690  $ret.=$wDescription->input();
1691  $ret.= '</td>';
1692  $ret.='</tr>';
1693 
1694  $ret.= '</table>';
1695  $nb_row = (isset($nb_item) ) ? $nb_item : $this->nb;
1696 
1697  $ret.=HtmlInput::hidden('nb_item', $nb_row);
1698  $ret.=dossier::hidden();
1699 
1700  $ret.=dossier::hidden();
1701 
1702  $ret.=HtmlInput::hidden('jrn_type', $this->get_type());
1703  $info = HtmlInput::infobulle(0);
1704  $info_poste = HtmlInput::infobulle(9);
1705  if ($g_user->check_action(FICADD) == 1)
1706  $ret.=$f_add_button->input();
1707  $ret.='<table id="quick_item" style="position:float;width:100%">';
1708  $ret.='<tr>' .
1709  '<th style="text-align:left">Quickcode' . $info . '</th>' .
1710  '<th style="text-align:left">' . _('Poste') . $info_poste . '</th>' .
1711  '<th style="text-align:left">' . _('Libellé') . '</th>' .
1712  '<th style="text-align:left">' . _('Montant') . '</th>' .
1713  '<th style="text-align:left">' . _('Débit') . '</th>' .
1714  '</tr>';
1715 
1716 
1717  for ($i = 0; $i < $nb_row; $i++)
1718  {
1719  // Quick Code
1720  $quick_code = new ICard('qc_' . $i);
1721  $quick_code->set_dblclick("fill_ipopcard(this);");
1722  $quick_code->set_attribute('ipopup', 'ipopcard');
1723 
1724  // name of the field to update with the name of the card
1725  $quick_code->set_attribute('label', "ld" . $i);
1726 
1727  // name of the field to update with the name of the card
1728  $quick_code->set_attribute('typecard', 'filter');
1729 
1730  // Add the callback function to filter the card on the jrn
1731  $quick_code->set_callback('filter_card');
1732  $quick_code->set_function('fill_data');
1733  $quick_code->javascript = sprintf(' onchange="fill_data_onchange(\'%s\');" ', $quick_code->name);
1734 
1735  $quick_code->value = (isset(${'qc_' . $i})) ? ${'qc_' . $i} : "";
1736  $quick_code->readonly = $p_readonly;
1737 
1738  $label = '';
1739  if ($quick_code->value != '')
1740  {
1741  $Fiche = new Fiche($this->db);
1742  $Fiche->get_by_qcode($quick_code->value);
1743  $label = $Fiche->strAttribut(ATTR_DEF_NAME);
1744  }
1745 
1746 
1747  // Account
1748  $poste = new IPoste();
1749  $poste->name = 'poste' . $i;
1750  $poste->set_attribute('jrn', $this->id);
1751  $poste->set_attribute('ipopup', 'ipop_account');
1752  $poste->set_attribute('label', 'ld' . $i);
1753  $poste->set_attribute('account', 'poste' . $i);
1754  $poste->set_attribute('dossier', Dossier::id());
1755 
1756  $poste->value = (isset(${'poste' . $i})) ? ${"poste" . $i} : ''
1757  ;
1758  $poste->dbl_click_history();
1759 
1760  $poste->readonly = $p_readonly;
1761 
1762  if ($poste->value != '')
1763  {
1764  $Poste = new Acc_Account($this->db);
1765  $Poste->set_parameter('value', $poste->value);
1766  $label = $Poste->get_lib();
1767  }
1768 
1769  // Description of the line
1770  $line_desc = new IText();
1771  $line_desc->name = 'ld' . $i;
1772  $line_desc->size = 30;
1773  $line_desc->value = (isset(${"ld" . $i})) ? ${"ld" . $i} :
1774  $label;
1775 
1776  // Amount
1777  $amount = new INum();
1778  $amount->size = 10;
1779  $amount->name = 'amount' . $i;
1780  $amount->value = (isset(${'amount' . $i})) ? ${"amount" . $i} : ''
1781  ;
1782  $amount->readonly = $p_readonly;
1783  $amount->javascript = ' onChange="format_number(this);checkTotalDirect()"';
1784  // D/C
1785  $deb = new ICheckBox();
1786  $deb->name = 'ck' . $i;
1787  $deb->selected = (isset(${'ck' . $i})) ? true : false;
1788  $deb->readonly = $p_readonly;
1789  $deb->javascript = ' onChange="checkTotalDirect()"';
1790 
1791  $ret.='<tr>';
1792  $ret.='<td>' . $quick_code->input() . $quick_code->search() . '</td>';
1793  $ret.='<td>' . $poste->input() .
1794  '<script> document.getElementById(\'poste' . $i . '\').onblur=function(){ if (trim(this.value) !=\'\') {document.getElementById(\'qc_' . $i . '\').value="";}}</script>' .
1795  '</td>';
1796  $ret.='<td>' . $line_desc->input() . '</td>';
1797  $ret.='<td>' . $amount->input() . '</td>';
1798  $ret.='<td>' . $deb->input() . '</td>';
1799  $ret.='</tr>';
1800  // If readonly == 1 then show CA
1801  }
1802  $ret.='</table>';
1803  if (isset($this->with_concerned) && $this->with_concerned == true)
1804  {
1805  $oRapt = new Acc_Reconciliation($this->db);
1806  $w = $oRapt->widget();
1807  $w->name = 'jrn_concerned';
1808  $w->value = (isset($jrn_concerned)) ? $jrn_concerned : "";
1809  $ret.="R&eacute;conciliation/rapprochements : " . $w->input();
1810  }
1811  $ret.= create_script("$('".$wDate->id."').focus()");
1812  return $ret;
1813  }
1814 
1815  /**
1816  * @brief
1817  * check if the current ledger is closed
1818  * \return 1 for yes, otherwise 0
1819  * \see Periode::is_closed
1820  */
1821 
1822  function is_closed($p_periode)
1823  {
1824  $per = new Periode($this->db);
1825  $per->set_jrn($this->id);
1826  $per->set_periode($p_periode);
1827  $ret = $per->is_closed();
1828  return $ret;
1829  }
1830 
1831  /**
1832  * @brief verify that the operation can be saved
1833  * @param$p_array array of data same layout that the $_POST from show_form
1834  *
1835  *
1836  * \throw the getcode value is 1 incorrect balance, 2 date
1837  * invalid, 3 invalid amount, 4 the card is not in the range of
1838  * permitted card, 5 not in the user's period, 6 closed period
1839  *
1840  */
1841 
1842  function verify($p_array)
1843  {
1844  if (is_array($p_array ) == false || empty($p_array))
1845  throw new Exception ("Array empty");
1846  /*
1847  * Check needed value
1848  */
1849  check_parameter($p_array,'p_jrn,e_date');
1850 
1851  extract($p_array, EXTR_SKIP);
1852  global $g_user;
1853  $tot_cred = 0;
1854  $tot_deb = 0;
1855  $msg = array();
1856 
1857  /* check if we can write into this ledger */
1858  if ($g_user->check_jrn($p_jrn) != 'W')
1859  throw new Exception(_('Accès interdit'), 20);
1860 
1861  /* check for a double reload */
1862  if (isset($mt) && $this->db->count_sql('select jr_mt from jrn where jr_mt=$1', array($mt)) != 0)
1863  throw new Exception('Double Encodage', 5);
1864 
1865  // Check the periode and the date
1866  if (isDate($e_date) == null)
1867  {
1868  throw new Exception('Date invalide', 2);
1869  }
1870  $periode = new Periode($this->db);
1871  /* find the periode if we have enabled the check_periode
1872  * or if period is not set
1873  */
1874  if ($this->check_periode() == false || ! isset ($p_array['period']) )
1875  {
1876  $periode->find_periode($e_date);
1877  }
1878  else
1879  {
1880  $periode->p_id = $p_array['period'];
1881  list ($min, $max) = $periode->get_date_limit();
1882  if (cmpDate($e_date, $min) < 0 ||
1883  cmpDate($e_date, $max) > 0)
1884  throw new Exception(_('Date et periode ne correspondent pas'), 6);
1885  }
1886 
1887 
1888 
1889  // Periode ferme
1890  if ($this->is_closed($periode->p_id) == 1)
1891  {
1892  throw new Exception('Periode fermee', 6);
1893  }
1894  /* check if we are using the strict mode */
1895  if ($this->check_strict() == true)
1896  {
1897  /* if we use the strict mode, we get the date of the last
1898  operation */
1899  $last_date = $this->get_last_date();
1900  if ($last_date != null && cmpDate($e_date, $last_date) < 0)
1901  throw new Exception(_('Vous utilisez le mode strict la dernière operation est la date du ')
1902  . $last_date . ' ' . _('vous ne pouvez pas encoder à une date antérieure'), 15);
1903  }
1904 
1905  for ($i = 0; $i < $nb_item; $i++)
1906  {
1907  $err = 0;
1908 
1909  // Check the balance
1910  if (!isset(${'amount' . $i}))
1911  continue;
1912 
1913  $amount = round(${'amount' . $i}, 2);
1914  $tot_deb+=(isset(${'ck' . $i})) ? $amount : 0;
1915  $tot_cred+=(!isset(${'ck' . $i})) ? $amount : 0;
1916 
1917  // Check if the card is permitted
1918  if (isset(${'qc_' . $i}) && trim(${'qc_' . $i}) != "")
1919  {
1920  $f = new Fiche($this->db);
1921  $f->quick_code = ${'qc_' . $i};
1922  if ($f->belong_ledger($p_jrn) < 0)
1923  throw new Exception("La fiche quick_code = " .
1924  $f->quick_code . " n'est pas dans ce journal", 4);
1925  if (strlen(trim(${'qc_' . $i})) != 0 && isNumber(${'amount' . $i}) == 0)
1926  throw new Exception('Montant invalide', 3);
1927 
1928  $strPoste = $f->strAttribut(ATTR_DEF_ACCOUNT);
1929  if ($strPoste == '')
1930  throw new Exception(sprintf(_("La fiche %s n'a pas de poste comptable"), ${"qc_" . $i}));
1931 
1932  $p = new Acc_Account_Ledger($this->db, $strPoste);
1933  if ($p->do_exist() == 0)
1934  throw new Exception(_('Poste Inexistant pour la fiche [' . ${'qc_' . $i} . ']'), 4);
1935  }
1936 
1937  // Check if the account is permitted
1938  if (isset(${'poste' . $i}) && strlen(trim(${'poste' . $i})) != 0)
1939  {
1940  $p = new Acc_Account_Ledger($this->db, ${'poste' . $i});
1941  if ($p->belong_ledger($p_jrn) < 0)
1942  throw new Exception(_("Le poste") . " " . $p->id . " " . _("n'est pas dans ce journal"), 5);
1943  if (strlen(trim(${'poste' . $i})) != 0 && isNumber(${'amount' . $i}) == 0)
1944  throw new Exception(_('Poste invalide [' . ${'poste' . $i} . ']'), 3);
1945  if ($p->do_exist() == 0)
1946  throw new Exception(_('Poste Inexistant [' . ${'poste' . $i} . ']'), 4);
1947  $card_id = $p->find_card();
1948  if (!empty($card_id))
1949  {
1950  $str_msg = " Le poste " . $p->id . " appartient à " . count($card_id) . " fiche(s) dont :";
1951  $max = (count($card_id) > MAX_COMPTE_CARD) ? MAX_COMPTE_CARD : count($card_id);
1952  for ($x = 0; $x < $max; $x++)
1953  {
1954  $card = new Fiche($this->db, $card_id[$x]['f_id']);
1955  $str_msg.=HtmlInput::card_detail($card->strAttribut(ATTR_DEF_QUICKCODE), $card->strAttribut(ATTR_DEF_NAME), 'style="color:red;display:inline;text-decoration:underline"');
1956  $str_msg.=" ";
1957  }
1958  $msg[] = $str_msg;
1959  }
1960  }
1961  }
1962  $tot_deb = round($tot_deb, 4);
1963  $tot_cred = round($tot_cred, 4);
1964  if ($tot_deb != $tot_cred)
1965  {
1966  throw new Exception(_("Balance incorrecte ") . " debit = $tot_deb credit=$tot_cred ", 1);
1967  }
1968 
1969  return $msg;
1970  }
1971 
1972  /**
1973  * @brief compute the internal code of the saved operation and set the $this->jr_internal to
1974  * the computed value
1975  *
1976  * @param$p_grpt id in jr_grpt_
1977  *
1978  * \return string internal_code
1979  * -
1980  *
1981  */
1982 
1983  function compute_internal_code($p_grpt)
1984  {
1985  if ($this->id == 0)
1986  return;
1987  $num = $this->db->get_next_seq('s_internal');
1988  $atype = $this->get_propertie();
1989  $type = substr($atype['jrn_def_code'], 0, 1);
1990  $internal_code = sprintf("%s%06X", $type, $num);
1991  $this->jr_internal = $internal_code;
1992  return $internal_code;
1993  }
1994 
1995  /**
1996  * @brief save the operation into the jrnx,jrn, ,
1997  * CA and pre_def
1998  * @param$p_array
1999  *
2000  * \return array with [0] = false if failed otherwise true, [1] error
2001  * code
2002  */
2003 
2004  function save($p_array = null)
2005  {
2006  if ($p_array == null)
2007  throw new Exception('save cannot use a empty array');
2008  global $g_parameter;
2009  extract($p_array, EXTR_SKIP);
2010  try
2011  {
2012  $msg = $this->verify($p_array);
2013  if (!empty($msg))
2014  {
2015  echo $this->display_warning($msg, _("Attention : il vaut mieux utiliser les fiches que les postes comptables "));
2016  }
2017  $this->db->start();
2018 
2019  $seq = $this->db->get_next_seq('s_grpt');
2020  $internal = $this->compute_internal_code($seq);
2021 
2022  $group = $this->db->get_next_seq("s_oa_group");
2023  $tot_amount = 0;
2024  $tot_deb = 0;
2025  $tot_cred = 0;
2026  $oPeriode = new Periode($this->db);
2027  $check_periode = $this->check_periode();
2028  if ($check_periode == false || ! isset ($p_array['period']))
2029  {
2030  $oPeriode->find_periode($e_date);
2031  }
2032  else
2033  {
2034  $oPeriode->id = $period;
2035  }
2036 
2037  $count = 0;
2038  for ($i = 0; $i < $nb_item; $i++)
2039  {
2040  if (!isset(${'qc_' . $i}) && !isset(${'poste' . $i}))
2041  continue;
2042  $acc_op = new Acc_Operation($this->db);
2043  $quick_code = "";
2044  // First we save the jrnx
2045  if (isset(${'qc_' . $i}))
2046  {
2047  $qc = new Fiche($this->db);
2048  $qc->get_by_qcode(${'qc_' . $i}, false);
2049  $sposte = $qc->strAttribut(ATTR_DEF_ACCOUNT);
2050  /* if there are 2 accounts take following the deb or cred */
2051  if (strpos($sposte, ',') != 0)
2052  {
2053  $array = explode(",", $sposte);
2054  $poste = (isset(${'ck' . $i})) ? $array[0] : $array[1];
2055  }
2056  else
2057  {
2058  $poste = $sposte;
2059  if ($poste == '')
2060  throw new Exception(sprintf(_("La fiche %s n'a pas de poste comptable"), ${"qc_" . $i}));
2061  }
2062  $quick_code = ${'qc_' . $i};
2063  }
2064  else
2065  {
2066  $poste = ${'poste' . $i};
2067  }
2068 
2069  $acc_op->date = $e_date;
2070  // compute the periode is do not check it
2071  if ($check_periode == false)
2072  $acc_op->periode = $oPeriode->p_id;
2073  $acc_op->desc = null;
2074  if (strlen(trim(${'ld' . $i})) != 0)
2075  $acc_op->desc = ${'ld' . $i};
2076  $acc_op->amount = round(${'amount' . $i}, 2);
2077  $acc_op->grpt = $seq;
2078  $acc_op->poste = $poste;
2079  $acc_op->jrn = $this->id;
2080  $acc_op->type = (isset(${'ck' . $i})) ? 'd' : 'c';
2081  $acc_op->qcode = $quick_code;
2082  $j_id = $acc_op->insert_jrnx();
2083  $tot_amount+=round($acc_op->amount, 2);
2084  $tot_deb+=($acc_op->type == 'd') ? $acc_op->amount : 0;
2085  $tot_cred+=($acc_op->type == 'c') ? $acc_op->amount : 0;
2086  if ($g_parameter->MY_ANALYTIC != "nu")
2087  {
2088  if (preg_match("/^[6,7]+/", $poste) == 1)
2089  {
2090 
2091  // for each item, insert into operation_analytique */
2092  $op = new Anc_Operation($this->db);
2093  $op->oa_group = $group;
2094  $op->j_id = $j_id;
2095  $op->oa_date = $e_date;
2096  $op->oa_debit = ($acc_op->type == 'd' ) ? 't' : 'f';
2097  $op->oa_description = $desc;
2098  $op->save_form_plan($p_array, $count, $j_id);
2099  $count++;
2100  }
2101  }
2102  }// loop for each item
2103  $acc_end = new Acc_Operation($this->db);
2104  $acc_end->amount = $tot_deb;
2105  if ($check_periode == false)
2106  $acc_end->periode = $oPeriode->p_id;
2107  $acc_end->date = $e_date;
2108  $acc_end->desc = $desc;
2109  $acc_end->grpt = $seq;
2110  $acc_end->jrn = $this->id;
2111  $acc_end->mt = $mt;
2112  $jr_id = $acc_end->insert_jrn();
2113  $this->jr_id = $jr_id;
2114  if ($jr_id == false)
2115  throw new Exception(_('Balance incorrecte'));
2116  $acc_end->pj = $e_pj;
2117 
2118  /* if e_suggest != e_pj then do not increment sequence */
2119  if (strcmp($e_pj, $e_pj_suggest) == 0 && strlen(trim($e_pj)) != 0)
2120  {
2121  $this->inc_seq_pj();
2122  }
2123 
2124  $this->pj = $acc_end->set_pj();
2125 
2126  $this->db->exec_sql("update jrn set jr_internal='" . $internal . "' where " .
2127  " jr_grpt_id = " . $seq);
2128  $this->internal = $internal;
2129  // Save now the predef op
2130  //------------------------
2131  if (isset ($opd_name) && trim($opd_name) != "" ){
2132  $opd = new Pre_Op_Advanced($this->db);
2133  $opd->get_post();
2134  $opd->save();
2135  }
2136 
2137  if (isset($this->with_concerned) && $this->with_concerned == true)
2138  {
2139  $orap = new acc_reconciliation($this->db);
2140  $orap->jr_id = $jr_id;
2141 
2142  $orap->insert($jrn_concerned);
2143  }
2144  /**
2145  * Save the file is any
2146  */
2147  if (isset($_FILES["pj"]))
2148  {
2149  $this->db->save_receipt($seq);
2150  }
2151 
2152  }
2153  catch (Exception $a)
2154  {
2155  throw $a;
2156  }
2157  catch (Exception $e)
2158  {
2159  $this->db->rollback();
2160  echo _('OPERATION ANNULEE ');
2161  echo '<hr>';
2162  echo __FILE__ . __LINE__ . $e->getMessage();
2163  exit();
2164  }
2165  $this->db->commit();
2166  return true;
2167  }
2168 
2169  /**
2170  * @brief get all the data from request and build the object
2171  */
2172 
2173  function get_request()
2174  {
2175  $this->id = $_REQUEST['p_jrn'];
2176  }
2177 
2178  /**
2179  * @brief retrieve the next number for this type of ledger
2180  * @param p_cn connx
2181  * @param p_type ledger type
2182  *
2183  * \return the number
2184  *
2185  *
2186  */
2187 
2188  static function next_number($p_cn, $p_type)
2189  {
2190 
2191  $Ret = $p_cn->count_sql("select * from jrn_def where jrn_def_type='" . $p_type . "'");
2192  return $Ret + 1;
2193  }
2194 
2195  /**
2196  * @brief get the first ledger
2197  * @param type
2198  * @return the j_id
2199  */
2200 
2201  public function get_first($p_type, $p_access = 3)
2202  {
2203  global $g_user;
2204  $all = $g_user->get_ledger($p_type, $p_access);
2205  return $all[0];
2206  }
2207 
2208  /**
2209  * @brief Update the paiment in the list of operation
2210  * @param $p_array is normally $_GET
2211  */
2212 
2214  {
2215  // reset all the paid flag because the checkbox is post only
2216  // when checked
2217  foreach ($p_array as $name => $paid)
2218  {
2219  list($ad) = sscanf($name, "set_jr_id%d");
2220  if ($ad == null)
2221  continue;
2222  $sql = "update jrn set jr_rapt='' where jr_id=$ad";
2223  $Res = $this->db->exec_sql($sql);
2224  }
2225  // set a paid flag for the checked box
2226  foreach ($p_array as $name => $paid)
2227  {
2228  list ($id) = sscanf($name, "rd_paid%d");
2229  if ($id == null)
2230  continue;
2231 
2232  $sql = "update jrn set jr_rapt='paid' where jr_id=$id";
2233  $Res = $this->db->exec_sql($sql);
2234  }
2235  }
2236 
2237  function update_internal_code($p_internal)
2238  {
2239  if (!isset($this->grpt_id))
2240  throw new Exception(('ERREUR ' . __FILE__ . ":" . __LINE__));
2241  $Res = $this->db->exec_sql("update jrn set jr_internal='" . $p_internal . "' where " .
2242  " jr_grpt_id = " . $this->grpt_id);
2243  }
2244  /**
2245  * Return an array of default card for the ledger type given
2246  *
2247  * @param $p_ledger_type VEN ACH ODS or FIN
2248  * @param $p_side D for Debit or C for credit or NA No Applicable
2249  */
2250  function get_default_card($p_ledger_type,$p_side)
2251  {
2252  $array=array();
2253  $fiche_def_ref=new Fiche_Def_Ref($this->db);
2254  // ----- for FINANCIAL ----
2255  if ($p_ledger_type =='FIN')
2256  {
2257  $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_CLIENT);
2258  $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_FOURNISSEUR));
2259  $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_FIN));
2260  $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_ADM_TAX));
2261  $array=array_merge ( $array , $fiche_def_ref->get_by_modele(FICHE_TYPE_EMPL));
2262 
2263  }
2264  // --- for miscellaneous ----
2265  if ($p_ledger_type == 'ODS')
2266  {
2267  $result=$this->db->get_array('select fd_id from fiche_def');
2268  for ($i = 0;$i<count($result);$i++ )
2269  {
2270  $array[$i]=$result[$i]['fd_id'];
2271  }
2272  }
2273  if ($p_side == 'D')
2274  {
2275  switch($p_ledger_type)
2276  {
2277  case 'VEN':
2278  $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_CLIENT);
2279  break;
2280  case 'ACH':
2281  $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_SER);
2282  $array=array_merge ($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_MAR));
2283  $array=array_merge ($array,$fiche_def_ref->get_by_modele(FICHE_TYPE_ACH_MAT));
2284  break;
2285  default :
2286  throw new Exception(_('get_default_card p_ledger_side is invalide ['.$p_ledger_type.']'));
2287 
2288  }
2289  } elseif ($p_side == 'C')
2290  {
2291  switch($p_ledger_type)
2292  {
2293  case 'VEN':
2294  $array=$fiche_def_ref->get_by_modele(FICHE_TYPE_VENTE);
2295  break;
2296  case 'ACH':
2297  $array= array_merge($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_ADM_TAX));
2298  $array= array_merge($array, $fiche_def_ref->get_by_modele(FICHE_TYPE_FOURNISSEUR));
2299  break;
2300  default :
2301  throw new Exception(_('get_default_card p_ledger_side is invalide ['.$p_ledger_type.']'));
2302 
2303  }
2304  }
2305  return $array;
2306  /*
2307  $return=array();
2308  $return = array_values($array);
2309  for ($i = 0;$i<count($array);$i++ )
2310  {
2311  $return[$i]=$array[$i]['fd_id'];
2312  }
2313  return $return;
2314  *
2315  */
2316  }
2317  /**
2318  * @brief retrieve all the card for this type of ledger, make them
2319  * into a string separated by comma
2320  * @return all the card or null is nothing is found
2321  */
2322 
2324  {
2325  $sql = "select jrn_def_fiche_deb as deb,jrn_def_fiche_cred as cred " .
2326  " from jrn_def where " .
2327  " jrn_def_id = $1 ";
2328 
2329  $r = $this->db->exec_sql($sql, array($this->id));
2330 
2332  if (empty($res))
2333  return null;
2334  $card = "";
2335  $comma = '';
2336  foreach ($res as $item)
2337  {
2338  if (strlen(trim($item['deb'])) != 0)
2339  {
2340  $card.=$comma . $item['deb'];
2341  $comma = ',';
2342  }
2343  if (strlen(trim($item['cred'])) != '')
2344  {
2345  $card.=$comma . $item['cred'];
2346  $comma = ',';
2347  }
2348  }
2349 
2350  return $card;
2351  }
2352 
2353  /**
2354  * @brief get the saldo of an exercice, used for the opening of a folder
2355  * @param$p_exercice is the exercice we want
2356  * \return an array
2357  * index =
2358  * - solde (debit > 0 ; credit < 0)
2359  * - j_poste
2360  * - j_qcode
2361  */
2362 
2364  {
2365  $sql = "select sum(a.montant) as solde, j_poste, j_qcode
2366  from
2367  (select j_id, case when j_debit='t' then j_montant
2368  else j_montant * (-1) end as montant
2369  from jrnx) as a
2370  join jrnx using (j_id)
2371  join parm_periode on (j_tech_per = p_id )
2372  where
2373  p_exercice=$1
2374  and j_poste::text not like '7%'
2375  and j_poste::text not like '6%'
2376  group by j_poste,j_qcode
2377  having (sum(a.montant) != 0 ) order by 1 desc";
2378  $res = $this->db->get_array($sql, array($p_exercice));
2379  return $res;
2380  }
2381 
2382  /**
2383  * @brief Check if a Dossier is using the strict mode or not
2384  * \return true if we are using the strict_mode
2385  */
2386 
2387  function check_strict()
2388  {
2389  global $g_parameter;
2390  if ($g_parameter->MY_STRICT == 'Y')
2391  return true;
2392  if ($g_parameter->MY_STRICT == 'N')
2393  return false;
2394  throw new Exception("Valeur invalid " . __FILE__ . ':' . __LINE__);
2395  }
2396 
2397  /**
2398  * @brief Check if a Dossier is using the check on the periode, if true than the user has to enter the date
2399  * and the periode, it is a security check
2400  * \return true if we are using the double encoding (date+periode)
2401  */
2402 
2403  function check_periode()
2404  {
2405  global $g_parameter;
2406  if ($g_parameter->MY_CHECK_PERIODE == 'Y')
2407  return true;
2408  if ($g_parameter->MY_CHECK_PERIODE == 'N')
2409  return false;
2410  throw new Exception("Valeur invalid " . __FILE__ . ':' . __LINE__);
2411  }
2412 
2413  /**
2414  * @brief get the date of the last operation
2415  */
2416 
2417  function get_last_date()
2418  {
2419  if ($this->id == 0)
2420  throw new Exception(__FILE__ . ":" . __LINE__ . "Journal incorrect ");
2421  $sql = "select to_char(max(jr_date),'DD.MM.YYYY') from jrn where jr_def_id=$1";
2422  $date = $this->db->get_value($sql, array($this->id));
2423  return $date;
2424  }
2425 
2426  /**
2427  * @brief retrieve the jr_id thanks the internal code, do not change
2428  * anything to the current object
2429  * @param internal code
2430  * \return the jr_id or 0 if not found
2431  */
2432 
2433  function get_id($p_internal)
2434  {
2435  $sql = 'select jr_id from jrn where jr_internal=$1';
2436  $value = $this->db->get_value($sql, array($p_internal));
2437  if ($value == '')
2438  $value = 0;
2439  return $value;
2440  }
2441 
2442  /**
2443  * @brief create the invoice and saved it as attachment to the
2444  * operation,
2445  * @param $internal is the internal code
2446  * @param $p_array is normally the $_POST
2447  * \return a string
2448  */
2449 
2450  function create_document($internal, $p_array)
2451  {
2452  extract($p_array, EXTR_SKIP);
2453  $doc = new Document($this->db);
2454  $doc->f_id = $e_client;
2455  $doc->md_id = $gen_doc;
2456  $doc->ag_id = 0;
2457  $p_array['e_pj']=$this->pj;
2458  $filename="";
2459  $doc->Generate($p_array,$p_array['e_pj']);
2460  // Move the document to the jrn
2461  $doc->MoveDocumentPj($internal);
2462  // Update the comment with invoice number, if the comment is empty
2463  if (!isset($e_comm) || strlen(trim($e_comm)) == 0)
2464  {
2465  $sql = "update jrn set jr_comment=' document " . $doc->d_number . "' where jr_internal='$internal'";
2466  $this->db->exec_sql($sql);
2467  }
2468  return h($doc->d_name . ' (' . $doc->d_filename . ')');
2469  }
2470 
2471  /**
2472  * @brief check if the payment method is valid
2473  * @param $e_mp is the value and $e_mp_qcode is the quickcode
2474  * \return nothing throw an Exception
2475  */
2476 
2477  public function check_payment($e_mp, $e_mp_qcode)
2478  {
2479  /* Check if the "paid by" is empty, */
2480  if ($e_mp != 0)
2481  {
2482  /* the paid by is not empty then check if valid */
2483  $empl = new Fiche($this->db);
2484  $empl->get_by_qcode($e_mp_qcode);
2485  if ($empl->empty_attribute(ATTR_DEF_ACCOUNT) == true)
2486  {
2487  throw new Exception(_("Celui qui paie n' a pas de poste comptable"), 20);
2488  }
2489  /* get the account and explode if necessary */
2490  $sposte = $empl->strAttribut(ATTR_DEF_ACCOUNT);
2491  // if 2 accounts, take only the debit one for customer
2492  if (strpos($sposte, ',') != 0)
2493  {
2494  $array = explode(',', $sposte);
2495  $poste_val = $array[0];
2496  }
2497  else
2498  {
2499  $poste_val = $sposte;
2500  }
2501  $poste = new Acc_Account_Ledger($this->db, $poste_val);
2502  if ($poste->load() == false)
2503  {
2504  throw new Exception(sprintf(_("Pour la fiche %s le poste comptable [%s] n'existe pas"),$empl->quick_code,$poste->id ), 9);
2505  }
2506  }
2507  }
2508 
2509  /**
2510  * @brief increment the sequence for the pj */
2511 
2512  function inc_seq_pj()
2513  {
2514  $sql = "select nextval('s_jrn_pj" . $this->id . "')";
2515  $this->db->exec_sql($sql);
2516  }
2517 
2518  /**
2519  * @brief return a HTML string with the form for the search
2520  * @param $p_type if the type of ledger possible values=ALL,VEN,ACH,ODS,FIN
2521  * @param $all_type_ledger
2522  * values :
2523  * - 1 means all the ledger of this type
2524  * - 0 No have the "Tous les journaux" availables
2525  * @param $div is the div (for reconciliation)
2526  * @return a HTML String without the tag FORM or DIV
2527  *
2528  * @see build_search_sql
2529  * @see display_search_form
2530  * @see list_operation
2531  */
2532 
2533  function search_form($p_type, $all_type_ledger = 1, $div = "")
2534  {
2535  global $g_user;
2536  $r="";
2537  $bledger_param= json_encode(array(
2538  'dossier'=>$_REQUEST['gDossier'],
2539  'type'=>$p_type,
2540  'all_type'=>$all_type_ledger,
2541  'div'=>$div
2542  ));
2543 
2544  $bledger_param= str_replace('"', "'", $bledger_param);
2545  $bledger=new ISmallButton('l');
2546  $bledger->label=_("choix des journaux");
2547  $bledger->javascript=" show_ledger_choice($bledger_param)";
2548  $f_ledger=$bledger->input();
2549  $hid_jrn="";
2550  if ( isset ($_REQUEST[$div.'nb_jrn']) ){
2551  for ($i=0;$i < $_REQUEST[$div.'nb_jrn'];$i++) {
2552  if ( isset ($_REQUEST[$div."r_jrn"][$i]))
2553  $hid_jrn.=HtmlInput::hidden($div.'r_jrn['.$i.']',$_REQUEST[$div."r_jrn"][$i]);
2554  }
2555  $hid_jrn.=HtmlInput::hidden($div.'nb_jrn',$_REQUEST[$div.'nb_jrn']);
2556  } else {
2557  $hid_jrn=HtmlInput::hidden($div.'nb_jrn',0);
2558  }
2559  /* Compute date for exercice */
2560  $period = $g_user->get_periode();
2561  $per = new Periode($this->db, $period);
2562  $exercice = $per->get_exercice();
2563  list($per_start, $per_end) = $per->get_limit($exercice);
2564  $date_end = $per_end->last_day();
2565  $date_start=$per_start->first_day();
2566 
2567  /* widget for date_start */
2568  $f_date_start = new IDate('date_start');
2569  /* all periode or only the selected one */
2570  if (isset($_REQUEST['date_start']))
2571  {
2572  $f_date_start->value = $_REQUEST['date_start'];
2573  }
2574  else
2575  {
2576  $f_date_start->value=$date_start;
2577  }
2578 
2579  /* widget for date_end */
2580  $f_date_end = new IDate('date_end');
2581  /* all date or only the selected one */
2582  if (isset($_REQUEST['date_end']))
2583  {
2584  $f_date_end->value = $_REQUEST['date_end'];
2585  }
2586  else
2587  {
2588  $f_date_end->value = $date_end;
2589  }
2590  /* widget for date term */
2591  $f_date_paid_start=new IDate('date_paid_start');
2592  $f_date_paid_end=new IDate('date_paid_end');
2593 
2594  $f_date_paid_start->value=(isset($_REQUEST['date_paid_start']))?$_REQUEST['date_paid_start']:'';
2595  $f_date_paid_end->value=(isset($_REQUEST['date_paid_end']))?$_REQUEST['date_paid_end']:'';
2596 
2597  /* widget for desc */
2598  $f_descript = new IText('desc');
2599  $f_descript->size = 40;
2600  if (isset($_REQUEST['desc']))
2601  {
2602  $f_descript->value = $_REQUEST['desc'];
2603  }
2604 
2605  /* widget for amount */
2606  $f_amount_min = new INum('amount_min');
2607  $f_amount_min->value = (isset($_REQUEST['amount_min'])) ? abs($_REQUEST['amount_min']) : 0;
2608  $f_amount_max = new INum('amount_max');
2609  $f_amount_max->value = (isset($_REQUEST['amount_max'])) ? abs($_REQUEST['amount_max']) : 0;
2610 
2611  /* input quick code */
2612  $f_qcode = new ICard('qcode' . $div);
2613 
2614  $f_qcode->set_attribute('typecard', 'all');
2615  /* $f_qcode->set_attribute('p_jrn','0');
2616 
2617  $f_qcode->set_callback('filter_card');
2618  */
2619  $f_qcode->set_dblclick("fill_ipopcard(this);");
2620  // Add the callback function to filter the card on the jrn
2621  //$f_qcode->set_callback('filter_card');
2622  $f_qcode->set_function('fill_data');
2623  $f_qcode->javascript = sprintf(' onchange="fill_data_onchange(%s);" ', $f_qcode->name);
2624  $f_qcode->value = (isset($_REQUEST['qcode' . $div])) ? $_REQUEST['qcode' . $div] : '';
2625 
2626  /* $f_txt_qcode=new IText('qcode');
2627  $f_txt_qcode->value=(isset($_REQUEST['qcode']))?$_REQUEST['qcode']:'';
2628  */
2629 
2630  /* input poste comptable */
2631  $f_accounting = new IPoste('accounting');
2632  $f_accounting->value = (isset($_REQUEST['accounting'])) ? $_REQUEST['accounting'] : '';
2633  if ($this->id == -1)
2634  $jrn = 0;
2635  else
2636  $jrn = $this->id;
2637  $f_accounting->set_attribute('jrn', $jrn);
2638  $f_accounting->set_attribute('ipopup', 'ipop_account');
2639  $f_accounting->set_attribute('label', 'ld');
2640  $f_accounting->set_attribute('account', 'accounting');
2641  $info = HtmlInput::infobulle(13);
2642 
2643  $f_paid = new ICheckbox('unpaid');
2644  $f_paid->selected = (isset($_REQUEST['unpaid'])) ? true : false;
2645 
2646  $r.=dossier::hidden();
2647  $r.=HtmlInput::hidden('ledger_type', $this->type);
2648  $r.=HtmlInput::hidden('ac', $_REQUEST['ac']);
2649  ob_start();
2650  require_once NOALYSS_TEMPLATE.'/ledger_search.php';
2651  $r.=ob_get_contents();
2652  ob_end_clean();
2653  return $r;
2654  }
2655 
2656  /**
2657  * @brief this function will create a sql stmt to use to create the list for
2658  * the ledger,
2659  * @param $p_array is usually the $_GET,
2660  * @param $p_order the order of the row
2661  * @param $p_where is the sql condition if not null then the $p_array will not be used
2662  * \note the p_action will be used to filter the ledger but gl means ALL
2663  * struct array $p_array
2664  \verbatim
2665  (
2666  [gDossier] => 13
2667  [p_jrn] => -1
2668  [date_start] =>
2669  [date_end] =>
2670  [amount_min] => 0
2671  [amount_max] => 0
2672  [desc] =>
2673  [search] => Rechercher
2674  [p_action] => ven
2675  [sa] => l
2676  )
2677  \endverbatim
2678  * \return an array with a valid sql statement, an the where clause => array[sql] array[where]
2679  * \see list_operation
2680  * \see display_search_form
2681  * \see search_form
2682  */
2683 
2684  public function build_search_sql($p_array, $p_order = "", $p_where = "")
2685  {
2686  $sql = "select jr_id ,
2687  jr_montant,
2688  substr(jr_comment,1,60) as jr_comment,
2689  to_char(jr_ech,'DD.MM.YY') as str_jr_ech,
2690  to_char(jr_date,'DD.MM.YY') as str_jr_date,
2691  jr_date as jr_date_order,
2692  jr_grpt_id,
2693  jr_rapt,
2694  jr_internal,
2695  jrn_def_id,
2696  jrn_def_name,
2697  jrn_def_ech,
2698  jrn_def_type,
2699  jr_valid,
2700  jr_tech_per,
2701  jr_pj_name,
2702  p_closed,
2703  jr_pj_number,
2704  n_text,
2705  case
2706  when jrn_def_type='VEN' then
2707  (select ad_value from fiche_detail where ad_id=1
2708  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))
2709  when jrn_def_type = 'ACH' then
2710  (select ad_value from fiche_detail where ad_id=1
2711  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))
2712  when jrn_def_type = 'FIN' then
2713  (select ad_value from fiche_detail where ad_id=1
2714  and f_id=(select qf_other from quant_fin where quant_fin.jr_id=x.jr_id))
2715  end as name,
2716  case
2717  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))
2718  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))
2719  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))
2720  end as first_name,
2721  case
2722  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))
2723  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))
2724  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))
2725  end as quick_code,
2726  case
2727  when jrn_def_type='VEN' then
2728  (select sum(qs_price)+sum(vat) from
2729  (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
2730  )
2731  when jrn_def_type = 'ACH' then
2732  (
2733  select sum(qp_price)+sum(vat)+sum(qp_nd_tva)+sum(qp_nd_tva_recup)
2734  from
2735  (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
2736  )
2737  else null
2738  end as total_invoice,
2739  jr_date_paid,
2740  to_char(jr_date_paid,'DD.MM.YY') as str_jr_date_paid
2741  from
2742  jrn as X left join jrn_note using(jr_id)
2743  join jrn_def on jrn_def_id=jr_def_id
2744  join parm_periode on p_id=jr_tech_per";
2745 
2746  if (!empty($p_array))
2747  extract($p_array, EXTR_SKIP);
2748 
2749  if (isset($op) )
2750  $r_jrn = (isset(${$op."r_jrn"})) ? ${$op."r_jrn"} : -1;
2751  else
2752  {
2753  $r_jrn = (isset($r_jrn)) ? $r_jrn : -1;
2754 
2755  }
2756 
2757  /* if no variable are set then give them a default
2758  * value */
2759  if ($p_array == null || empty($p_array) || !isset($amount_min))
2760  {
2761  $amount_min = 0;
2762  $amount_max = 0;
2763 
2764  $desc = '';
2765  $qcode = (isset($qcode)) ? $qcode : "";
2766  if (isset($qcodesearch_op))
2767  $qcode = $qcodesearch_op;
2768  $accounting = (isset($accounting)) ? $accounting : "";
2769  $periode = new Periode($this->db);
2770  $g_user = new User($this->db);
2771  $p_id = $g_user->get_periode();
2772  if ($p_id != null)
2773  {
2774  list($date_start, $date_end) = $periode->get_date_limit($p_id);
2775  }
2776  }
2777 
2778  /* if p_jrn : 0 if means all ledgers, if -1 means all ledger of this
2779  * type otherwise only one ledger */
2780  $fil_ledger = '';
2781  $fil_amount = '';
2782  $fil_date = '';
2783  $fil_desc = '';
2784  $fil_sec = '';
2785  $fil_qcode = '';
2786  $fil_account = '';
2787  $fil_paid = '';
2788  $fil_date_paid='';
2789 
2790  $and = '';
2791  $g_user = new User($this->db);
2793  if ($p_action == '')
2794  $p_action = 'ALL';
2795  if ($r_jrn == -1)
2796  {
2797 
2798  /* from compta.php the p_action is quick_writing instead of ODS */
2799  if ($p_action == 'quick_writing')
2800  $p_action = 'ODS';
2801 
2802 
2803  $fil_ledger = $g_user->get_ledger_sql($p_action, 3);
2804  $and = ' and ';
2805  }
2806  else
2807  {
2808 
2809  if ($p_action == 'quick_writing')
2810  $p_action = 'ODS';
2811 
2812  $aLedger = $g_user->get_ledger($p_action, 3);
2813  $fil_ledger = '';
2814  $sp = '';
2815  for ($i = 0; $i < count($r_jrn); $i++)
2816  {
2817  if (isset($r_jrn[$i]) )
2818  {
2819  $a=$r_jrn[$i];
2820  $fil_ledger.=$sp . $a;
2821  $sp = ',';
2822  }
2823  }
2824  $fil_ledger = ' jrn_def_id in (' . $fil_ledger . ')';
2825  $and = ' and ';
2826 
2827  /* no ledger selected */
2828  if ($sp == '')
2829  {
2830  $fil_ledger = '';
2831  $and = '';
2832  }
2833  }
2834 
2835  /* format the number */
2836  $amount_min = abs(toNumber($amount_min));
2837  $amount_max = abs(toNumber($amount_max));
2838  if ($amount_min > 0 && isNumber($amount_min))
2839  {
2840  $fil_amount = $and . ' jr_montant >=' . $amount_min;
2841  $and = ' and ';
2842  }
2843  if ($amount_max > 0 && isNumber($amount_max))
2844  {
2845  $fil_amount.=$and . ' jr_montant <=' . $amount_max;
2846  $and = ' and ';
2847  }
2848  /* -------------------------------------------------------------------------- *
2849  * if both amount are the same then we need to search into the detail
2850  * and we reset the fil_amount
2851  * -------------------------------------------------------------------------- */
2852  if (isNumber($amount_min) &&
2853  isNumber($amount_max) &&
2854  $amount_min > 0 &&
2855  bccomp($amount_min, $amount_max, 2) == 0)
2856  {
2857  $fil_amount = $and . ' ( ';
2858 
2859  // Look in detail
2860  $fil_amount .= 'jr_grpt_id in ( select distinct j_grpt from jrnx where j_montant = ' . $amount_min . ') ';
2861 
2862  //and the total operation
2863  $fil_amount .= ' or ';
2864  $fil_amount .= ' jr_montant = '.$amount_min;
2865 
2866  $fil_amount .= ')';
2867  $and = " and ";
2868  }
2869  // date
2870  if (isset($date_start) && isDate($date_start) != null)
2871  {
2872  $fil_date = $and . " jr_date >= to_date('" . $date_start . "','DD.MM.YYYY')";
2873  $and = " and ";
2874  }
2875  if (isset($date_end) && isDate($date_end) != null)
2876  {
2877  $fil_date.=$and . " jr_date <= to_date('" . $date_end . "','DD.MM.YYYY')";
2878  $and = " and ";
2879  }
2880  // date paiement
2881  if (isset($date_paid_start) && isDate($date_paid_start) != null)
2882  {
2883  $fil_date_paid = $and . " jr_date_paid >= to_date('" . $date_paid_start . "','DD.MM.YYYY')";
2884  $and = " and ";
2885  }
2886  if (isset($date_paid_end) && isDate($date_paid_end) != null)
2887  {
2888  $fil_date_paid.=$and . " jr_date_paid <= to_date('" . $date_paid_end . "','DD.MM.YYYY')";
2889  $and = " and ";
2890  }
2891  // comment
2892  if (isset($desc) && $desc != null)
2893  {
2894  $desc = sql_string($desc);
2895  $fil_desc = $and . " ( upper(jr_comment) like upper('%" . $desc . "%') or upper(jr_pj_number) like upper('%" . $desc . "%') " .
2896  " or upper(jr_internal) like upper('%" . $desc . "%')
2897  or jr_grpt_id in (select j_grpt from jrnx where j_text ~* '" . $desc . "')
2898  or jr_id in (select jr_id from jrn_info where ji_value is not null and ji_value ~* '$desc')
2899  )";
2900  $and = " and ";
2901  }
2902  // Poste
2903  if (isset($accounting) && $accounting != null)
2904  {
2905  $fil_account = $and . " jr_grpt_id in (select j_grpt
2906  from jrnx where j_poste::text like '" . sql_string($accounting) . "%' ) ";
2907  $and = " and ";
2908  }
2909  // Quick Code
2910  if (isset($qcodesearch_op))
2911  $qcode = $qcodesearch_op;
2912  if (isset($qcode) && $qcode != null)
2913  {
2914  $fil_qcode = $and . " jr_grpt_id in ( select j_grpt from
2915  jrnx where trim(j_qcode) = upper(trim('" . sql_string($qcode) . "')))";
2916  $and = " and ";
2917  }
2918 
2919  // Only the unpaid
2920  if (isset($unpaid))
2921  {
2922  $fil_paid = $and . SQL_LIST_UNPAID_INVOICE;
2923  $and = " and ";
2924  }
2925  $repo=new Database();
2926  $g_user = new User($repo);
2927  $g_user->Check();
2928  $g_user->check_dossier(dossier::id());
2929 
2930  if ($g_user->admin == 0 && $g_user->is_local_admin() == 0)
2931  {
2932  $fil_sec = $and . " jr_def_id in ( select uj_jrn_id " .
2933  " from user_sec_jrn where " .
2934  " uj_login='" . $_SESSION['g_user'] . "'" .
2935  " and uj_priv in ('R','W'))";
2936  }
2937  $where = $fil_ledger . $fil_amount . $fil_date . $fil_desc . $fil_sec . $fil_amount . $fil_qcode . $fil_paid . $fil_account.$fil_date_paid;
2938  $sql.=" where " . $where;
2939  return array($sql, $where);
2940  }
2941 
2942  /**
2943  * @brief return a html string with the search_form
2944  * \return a HTML string with the FORM
2945  * \see build_search_sql
2946  * \see search_form
2947  * \see list_operation
2948  */
2949 
2951  {
2952  $r = '';
2953  $type = $this->type;
2954 
2955  if ($type == "")
2956  $type = 'ALL';
2957  $r.='<div id="search_form" style="display:none">';
2958  $r.=HtmlInput::anchor_hide('&#10761;', '$(\'search_form\').style.display=\'none\';');
2959  $r.=h2('Recherche','class="title"');
2960  $r.='<FORM METHOD="GET">';
2961  $r.=$this->search_form($type);
2962  $r.=HtmlInput::submit('search', _('Rechercher'));
2963  $r.=HtmlInput::hidden('ac', $_REQUEST['ac']);
2964 
2965  /* when called from commercial.php some hidden values are needed */
2966  if (isset($_REQUEST['sa']))
2967  $r.= HtmlInput::hidden("sa", $_REQUEST['sa']);
2968  if (isset($_REQUEST['sb']))
2969  $r.= HtmlInput::hidden("sb", $_REQUEST['sb']);
2970  if (isset($_REQUEST['sc']))
2971  $r.= HtmlInput::hidden("sc", $_REQUEST['sc']);
2972  if (isset($_REQUEST['f_id']))
2973  $r.=HtmlInput::hidden("f_id", $_REQUEST['f_id']);
2974 
2975  $r.='</FORM>';
2976 
2977  $r.='</div>';
2978  $button = new IButton('tfs');
2979  $button->label = _("Filtrer");
2980  $button->javascript = "toggleHideShow('search_form','tfs');";
2981 
2982  $r.=$button->input();
2983  return $r;
2984  }
2985 
2986  /**
2987  * @brief return the last p_limit operation into an array
2988  * @param$p_limit is the max of operation to return
2989  * \return $p_array of Follow_Up object
2990  */
2991 
2992  function get_last($p_limit)
2993  {
2994  global $g_user;
2995  $filter_ledger = $g_user->get_ledger_sql('ALL', 3);
2996  $filter_ledger = str_replace('jrn_def_id', 'jr_def_id', $filter_ledger);
2997  $sql = "
2998  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
2999  from jrn
3000  join jrn_def on (jrn_def_id=jr_def_id)
3001  where $filter_ledger
3002  order by jr_date desc , substring(jr_pj_number,'[0-9]+$')::numeric desc limit $p_limit";
3003  $array = $this->db->get_array($sql);
3004  return $array;
3005  }
3006 
3007  /**
3008  * @brief retreive the jr_grpt_id from a ledger
3009  * @param $p_what the column to seek
3010  * possible values are
3011  * - internal
3012  * @param $p_value the value of the col.
3013  */
3014  function search_group($p_what, $p_value)
3015  {
3016  switch ($p_what)
3017  {
3018  case 'internal':
3019  return $this->db->get_value('select jr_grpt_id from jrn where jr_internal=$1', array($p_value));
3020  }
3021  }
3022 
3023  /**
3024  * @brief retrieve operation from jrn
3025  * @param $p_from periode (id)
3026  * @param $p_to periode (id)
3027  * @return an array
3028  */
3029  function get_operation($p_from, $p_to)
3030  {
3031  global $g_user;
3032  $jrn = ($this->id == 0) ? 'and ' . $g_user->get_ledger_sql() : ' and jr_def_id = ' . $this->id;
3033  $sql = "select jr_id as id ,jr_internal as internal, " .
3034  "jr_pj_number as pj,jr_grpt_id," .
3035  " to_char(jr_date,'DDMMYY') as date_fmt, " .
3036  " jr_comment as comment, jr_montant as montant ," .
3037  " jr_grpt_id,jr_def_id" .
3038  " from jrn join jrn_def on (jr_def_id=jrn_def_id) where " .
3039  " jr_date >= (select p_start from parm_periode where p_id = $1)
3040  and jr_date <= (select p_end from parm_periode where p_id = $2)" .
3041  ' ' . $jrn . ' order by jr_date,substring(jr_pj_number,\'[0-9]+$\')::numeric asc';
3042  $ret = $this->db->get_array($sql, array($p_from, $p_to));
3043  return $ret;
3044  }
3045 
3046  /**
3047  * @brief return the used VAT code with a rate > 0
3048  * @return an array of tva_id,tva_label,tva_poste
3049  */
3050  public function existing_vat()
3051  {
3052  if ($this->type == 'ACH')
3053  {
3054  $array = $this->db->get_array("select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0.0000 " .
3055  " and exists (select qp_vat_code from quant_purchase
3056  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));
3057  }
3058  if ($this->type == 'VEN')
3059  {
3060  $array = $this->db->get_array("select tva_id,tva_label,tva_poste from tva_rate where tva_rate != 0.0000 " .
3061  " and exists (select qs_vat_code from quant_sold
3062  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));
3063  }
3064  return $array;
3065  }
3066 
3067  /**
3068  * @brief get the amount of vat for a given jr_grpt_id from the table
3069  * quant_purchase
3070  * @param the jr_grpt_id
3071  * @return array price=htva, [1] = vat,
3072  * @note
3073  * @see
3074  @code
3075  array
3076  'price' => string '91.3500' (length=7)
3077  'vat' => string '0.0000' (length=6)
3078  'priv' => string '0.0000' (length=6)
3079  'tva_nd_recup' => string '0.0000' (length=6)
3080 
3081  @endcode
3082  */
3083  function get_other_amount($p_jr_id)
3084  {
3085  if ($this->type == 'ACH')
3086  {
3087  $array = $this->db->get_array('select sum(qp_price) as price,sum(qp_vat) as vat ' .
3088  ',sum(coalesce(qp_nd_amount,0)+coalesce(qp_dep_priv,0)) as priv' .
3089  ',sum(coalesce(qp_nd_tva_recup,0)+coalesce(qp_nd_tva,0)) as tva_nd' .
3090  ',sum(qp_vat_sided) as tva_np' .
3091  ' from quant_purchase join jrnx using(j_id)
3092  where j_grpt=$1 ', array($p_jr_id));
3093  $ret = $array[0];
3094  }
3095  if ($this->type == 'VEN')
3096  {
3097  $array = $this->db->get_array('select sum(qs_price) as price,sum(qs_vat) as vat ' .
3098  ',0 as priv' .
3099  ',0 as tva_nd' .
3100  ',sum(qs_vat_sided) as tva_np' .
3101  ' from quant_sold join jrnx using(j_id)
3102  where j_grpt=$1 ', array($p_jr_id));
3103  $ret = $array[0];
3104  }
3105  return $ret;
3106  }
3107 
3108  /**
3109  * @brief get the amount of vat for a given jr_grpt_id from the table
3110  * quant_purchase
3111  * @param the jr_grpt_id
3112  * @return array of sum_vat, tva_label
3113  * @note
3114  * @see
3115  @code
3116 
3117  @endcode
3118  */
3119  function vat_operation($p_jr_id)
3120  {
3121  if ($this->type == 'ACH')
3122  {
3123  $array = $this->db->get_array('select coalesce(sum(qp_vat),0) as sum_vat,tva_id
3124  from quant_purchase as p right join tva_rate on (qp_vat_code=tva_id) join jrnx using(j_id)
3125  where tva_rate !=0.0 and j_grpt=$1 group by tva_id', array($p_jr_id));
3126  }
3127  if ($this->type == 'VEN')
3128  {
3129  $array = $this->db->get_array('select coalesce(sum(qs_vat),0) as sum_vat,tva_id
3130  from quant_sold as p right join tva_rate on (qs_vat_code=tva_id) join jrnx using(j_id)
3131  where tva_rate !=0.0 and j_grpt=$1 group by tva_id', array($p_jr_id));
3132  }
3133  return $array;
3134  }
3135 
3136  /**
3137  * @brief retrieve amount of previous periode
3138  * @param $p_to frmo the start of the exercise until $p_to
3139  * @return $array with vat, price,other_amount
3140  * @note
3141  * @see
3142  @code
3143  array
3144  'price' => string '446.1900' (length=8)
3145  'vat' => string '21.7600' (length=7)
3146  'priv' => string '0.0000' (length=6)
3147  'tva_nd_recup' => string '0.0000' (length=6)
3148  'tva' =>
3149  array
3150  0 =>
3151  array
3152  'sum_vat' => string '13.7200' (length=7)
3153  'tva_id' => string '1' (length=1)
3154  1 =>
3155  array
3156  'sum_vat' => string '8.0400' (length=6)
3157  'tva_id' => string '3' (length=1)
3158  2 =>
3159  array
3160  'sum_vat' => string '0.0000' (length=6)
3161  'tva_id' => string '4' (length=1)
3162 
3163  @endcode
3164  */
3165  function previous_amount($p_to)
3166  {
3167  /* get the first periode of exercise */
3168  $periode = new Periode($this->db, $p_to);
3169  $exercise = $periode->get_exercice();
3170  list ($min, $max) = $periode->get_limit($exercise);
3171  // transform min into date
3172  $min_date=$min->first_day();
3173  // transform $p_to into date
3174  $periode_max=new Periode($this->db,$p_to);
3175  $max_date=$periode_max->first_day();
3176  bcscale(2);
3177  // min periode
3178  if ($this->type == 'ACH')
3179  {
3180  /* get all amount exclude vat */
3181  $sql = "select coalesce(sum(qp_price),0) as price" .
3182  " ,coalesce(sum(qp_vat),0) as vat " .
3183  ',coalesce(sum(qp_dep_priv),0) as priv' .
3184  ',coalesce(sum(qp_vat_sided),0) as reversed' .
3185  ',coalesce(sum(qp_nd_tva_recup),0)+coalesce(sum(qp_nd_tva),0) as tva_nd' .
3186  ',coalesce(sum(qp_vat_sided),0) as tva_np' .
3187  ' from quant_purchase join jrnx using(j_id) ' .
3188  " where j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') ".
3189  ' and j_jrn_def = $3';
3190  $array = $this->db->get_array($sql, array($min_date, $max_date,$this->id));
3191 
3192  $ret = $array[0];
3193  /* retrieve all vat code */
3194  $array = $this->db->get_array("select coalesce(sum(qp_vat),0) as sum_vat,tva_id
3195  from quant_purchase as p right join tva_rate on (qp_vat_code=tva_id) join jrnx using(j_id)
3196  where tva_rate !=0 and j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY')
3197  and j_jrn_def = $3
3198  group by tva_id",
3199  array($min_date, $max_date,$this->id));
3200  $ret['tva'] = $array;
3201  }
3202  if ($this->type == 'VEN')
3203  {
3204  /* get all amount exclude vat */
3205  $sql = "select coalesce(sum(qs_price),0) as price" .
3206  " ,coalesce(sum(qs_vat),0) as vat " .
3207  ',0 as priv' .
3208  ',0 as tva_nd' .
3209  ',coalesce(sum(qs_vat_sided),0) as tva_np' .
3210  ' from quant_sold join jrnx using(j_id) ' .
3211  " where j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY') ".
3212  ' and j_jrn_def = $3';
3213  $array = $this->db->get_array($sql, array($min_date, $max_date,$this->id));
3214  $ret = $array[0];
3215  /* retrieve all vat code */
3216  $array = $this->db->get_array("select coalesce(sum(qs_vat),0) as sum_vat,tva_id
3217  from quant_sold as p right join tva_rate on (qs_vat_code=tva_id) join jrnx using(j_id)
3218  where tva_rate !=0 and
3219  j_date >= to_date($1,'DD.MM.YYYY') and j_date < to_date($2,'DD.MM.YYYY')
3220  and j_jrn_def = $3
3221  group by tva_id", array($min_date, $max_date,$this->id));
3222  $ret['tva'] = $array;
3223  }
3224  if ($this->type=="FIN")
3225  {
3226 
3227  /* find the quick code of this ledger */
3228  $ledger=new Acc_Ledger_Fin($this->db,$this->id);
3229  $qcode=$ledger->get_bank();
3230  $bank_card=new Fiche($this->db,$qcode);
3231 
3232  /*add the amount from Opening Writing */
3233  $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);
3234  $saldo = $bank_card->get_bk_balance ($cond);
3235  $ret['amount']=bcsub($saldo['debit'],$saldo['credit']);
3236  }
3237  return $ret;
3238  }
3239 
3240  ////////////////////////////////////////////////////////////////////////////////
3241  // TEST MODULE
3242  ////////////////////////////////////////////////////////////////////////////////
3243  /**
3244  * @brief this function is intended to test this class
3245  */
3246  static function test_me($pCase = '')
3247  {
3248  if ($pCase == '')
3249  {
3250  echo Acc_Reconciliation::$javascript;
3251  html_page_start();
3252  $cn = Dossier::connect();
3253  $_SESSION['g_user'] = NOALYSS_ADMINISTRATOR ;
3254  $_SESSION['g_pass'] = 'phpcompta';
3255 
3256  $id = (isset($_REQUEST['p_jrn'])) ? $_REQUEST['p_jrn'] : -1;
3257  $a = new Acc_Ledger($cn, $id);
3258  $a->with_concerned = true;
3259  // Vide
3260  echo '<FORM method="post">';
3261  echo $a->select_ledger()->input();
3262  echo HtmlInput::submit('go', 'Test it');
3263  echo '</form>';
3264  if (isset($_POST['go']))
3265  {
3266  echo "Ok ";
3267  echo '<form method="post">';
3268  echo $a->show_form();
3269  echo HtmlInput::submit('post_id', 'Try me');
3270  echo '</form>';
3271  // Show the predef operation
3272  // Don't forget the p_jrn
3273  echo '<form>';
3274  echo dossier::hidden();
3275  echo '<input type="hidden" value="' . $id . '" name="p_jrn">';
3276  $op = new Pre_operation($cn);
3277  $op->p_jrn = $id;
3278  $op->od_direct = 't';
3279  if ($op->count() != 0)
3280  {
3281  echo HtmlInput::submit('use_opd', 'Utilisez une opération pr&eacute;d&eacute;finie',"","smallbutton");
3282  echo $op->show_button();
3283  }
3284  echo '</form>';
3285  exit('test_me');
3286  }
3287 
3288  if (isset($_POST['post_id']))
3289  {
3290 
3291  echo '<form method="post">';
3292  echo $a->show_form($_POST, 1);
3293  echo HtmlInput::button('add', 'Ajout d\'une ligne', 'onClick="quick_writing_add_row()"');
3294  echo HtmlInput::submit('save_it', _("Sauver"));
3295  echo '</form>';
3296  exit('test_me');
3297  }
3298  if (isset($_POST['save_it']))
3299  {
3300  print 'saving';
3301  $array = $_POST;
3302  $array['save_opd'] = 1;
3303  try
3304  {
3305  $a->save($array);
3306  }
3307  catch (Exception $e)
3308  {
3309  alert($e->getMessage());
3310  echo '<form method="post">';
3311 
3312  echo $a->show_form($_POST);
3313  echo HtmlInput::submit('post_id', 'Try me');
3314  echo '</form>';
3315  }
3316  return;
3317  }
3318  // The GET at the end because automatically repost when you don't
3319  // specify the url in the METHOD field
3320  if (isset($_GET['use_opd']))
3321  {
3322  $op = new Pre_op_advanced($cn);
3323  $op->set_od_id($_REQUEST['pre_def']);
3324  //$op->p_jrn=$id;
3325 
3326  $p_post = $op->compute_array();
3327 
3328  echo '<FORM method="post">';
3329 
3330  echo $a->show_form($p_post);
3331  echo HtmlInput::submit('post_id', 'Use predefined operation');
3332  echo '</form>';
3333  return;
3334  }
3335  }// if case = ''
3336  ///////////////////////////////////////////////////////////////////////////
3337  // search
3338  if ($pCase == 'search')
3339  {
3340  html_page_start();
3341  $cn = Dossier::connect();
3342  $ledger = new Acc_Ledger($cn, 0);
3343  $_SESSION['g_user'] = NOALYSS_ADMINISTRATOR;
3344  $_SESSION['g_pass'] = 'phpcompta';
3345  echo $ledger->search_form('ALL');
3346  }
3347  ///////////////////////////////////////////////////////////////////////////
3348  // reverse
3349  // Give yourself the var and check in your tables
3350  ///////////////////////////////////////////////////////////////////////////
3351  if ($pCase == 'reverse')
3352  {
3353  $cn = Dossier::connect();
3354  $jr_internal = 'OD-01-272';
3355  try
3356  {
3357  $cn->start();
3358  $jrn_def_id = $cn->get_value('select jr_def_id from jrn where jr_internal=$1', array($jr_internal));
3359  $ledger = new Acc_Ledger($cn, $jrn_def_id);
3360  $ledger->jr_id = $cn->get_value('select jr_id from jrn where jr_internal=$1', array($jr_internal));
3361 
3362  echo "Ouvrez le fichier " . __FILE__ . " à la ligne " . __LINE__ . " pour changer jr_internal et vérifier le résultat de l'extourne";
3363 
3364  $ledger->reverse('01.07.2010');
3365  }
3366  catch (Exception $e)
3367  {
3368  $cn->rollback();
3369  var_dump($e);
3370  }
3371  $cn->commit();
3372  }
3373  }
3374 
3375  /**
3376  * create an array of the existing cat, to be used in a checkbox form
3377  *
3378  */
3379  static function array_cat()
3380  {
3381  $r = array(
3382  array('cat' => 'VEN', 'name' => _("Journaux de vente")),
3383  array('cat' => 'ACH', 'name' => _("Journaux d'achat")),
3384  array('cat' => 'FIN', 'name' => _("Journaux Financier")),
3385  array('cat' => 'ODS', 'name' => _("Journaux d'Opérations diverses"))
3386  );
3387  return $r;
3388  }
3389  //---------------------------------------------------------------------
3390  /// Return the f_id of the tiers , called by get_tiers
3391  //!\param $p_jrn_type type of the ledger FIN, VEN ACH or ODS
3392  //!\param $jr_id jrn.jr_id
3393  //---------------------------------------------------------------------
3394  function get_tiers_id($p_jrn_type, $jr_id)
3395  {
3396  $tiers=0;
3397  switch ($p_jrn_type)
3398  {
3399  case 'VEN':
3400  $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));
3401  break;
3402  case 'ACH':
3403  $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));
3404 
3405  break;
3406  case 'FIN':
3407  $tiers = $this->db->get_value('select qf_other from quant_fin where jr_id=$1', array($jr_id));
3408  break;
3409  }
3410  if ($this->db->count() == 0)
3411  return 0;
3412  return $tiers;
3413  }
3414  /**
3415  * Retrieve the third : supplier for purchase, customer for sale, bank for fin,
3416  * @param $p_jrn_type type of the ledger FIN, VEN ACH or ODS
3417  * @param $jr_id jrn.jr_id
3418  */
3419  function get_tiers($p_jrn_type, $jr_id)
3420  {
3421  if ($p_jrn_type == 'ODS')
3422  return ' ';
3423  $tiers = $this->get_tiers_id($p_jrn_type, $jr_id);
3424  if ( $tiers == 0 )return "";
3425 
3426  $name = $this->db->get_value('select ad_value from fiche_detail where ad_id=1 and f_id=$1', array($tiers));
3427  $first_name = $this->db->get_value('select ad_value from fiche_detail where ad_id=32 and f_id=$1', array($tiers));
3428  return $name . ' ' . $first_name;
3429  }
3430 
3431  /**
3432  * @brief listing of all ledgers
3433  * @return HTML string
3434  */
3435  function listing()
3436  {
3437  $str_dossier = dossier::get();
3438  $base_url = "?" . dossier::get() . "&ac=" . $_REQUEST['ac'];
3439 
3440  $r = "";
3441  $r.=_('Cherche')." ".HtmlInput::filter_table("cfgledger_table_id", "0", "1");
3442  $r.='<TABLE id="cfgledger_table_id" class="vert_mtitle">';
3443  $r.='<TR><TD class="first"><A HREF="' . $base_url . '&sa=add">' . _('Ajout journal') . ' </A></TD></TR>';
3444  $ret = $this->db->exec_sql("select distinct jrn_def_id,jrn_def_name,
3445  jrn_def_class_deb,jrn_def_class_cred,jrn_def_type
3446  from jrn_def order by jrn_def_name");
3448 
3449 
3450  for ($i = 0; $i < $Max; $i++)
3451  {
3452  $l_line = Database::fetch_array($ret, $i);
3453  $url = $base_url . "&sa=detail&p_jrn=" . $l_line['jrn_def_id'];
3454  $r.=sprintf('<TR><TD><A HREF="%s">%s</A></TD></TR>', $url, h($l_line['jrn_def_name']).' ('.$l_line['jrn_def_type'].')');
3455  }
3456  $r.= "</TABLE>";
3457  return $r;
3458  }
3459 
3460  /**
3461  * display detail of a ledger
3462  *
3463  */
3464  function display_ledger()
3465  {
3466  if ($this->load() == -1)
3467  {
3468  throw new Exception(_("Journal n'existe pas"), -1);
3469  }
3470  $type = $this->jrn_def_type;
3472  $code = $this->jrn_def_code;
3473  $str_add_button="";
3474  /* widget for searching an account */
3475  $wSearch = new IPoste();
3476  $wSearch->set_attribute('ipopup', 'ipop_account');
3477  $wSearch->set_attribute('account', 'p_jrn_class_deb');
3478  $wSearch->set_attribute('no_overwrite', '1');
3479  $wSearch->set_attribute('noquery', '1');
3480  $wSearch->table = 3;
3481  $wSearch->name = "p_jrn_class_deb";
3482  $wSearch->size = 20;
3483  $wSearch->value = $this->jrn_def_class_deb;
3484  $search = $wSearch->input();
3485 
3486  $wPjPref = new IText();
3487  $wPjPref->name = 'jrn_def_pj_pref';
3488  $wPjPref->value = $this->jrn_def_pj_pref;
3489  $pj_pref = $wPjPref->input();
3490 
3491  $wPjSeq = new INum();
3492  $wPjSeq->value = 0;
3493  $wPjSeq->name = 'jrn_def_pj_seq';
3494  $pj_seq = $wPjSeq->input();
3495  $last_seq = $this->get_last_pj();
3497 
3498  $hidden = HtmlInput::hidden('p_jrn', $this->id);
3499  $hidden.= HtmlInput::hidden('sa', 'detail');
3500  $hidden.= dossier::hidden();
3501  $hidden.=HtmlInput::hidden('p_jrn_deb_max_line', 10);
3502  $hidden.=HtmlInput::hidden('p_ech_lib', 'echeance');
3503  $hidden.=HtmlInput::hidden('p_jrn_type', $type);
3504 
3505  $min_row = new INum("min_row",$this->jrn_deb_max_line);
3506  $min_row->prec=0;
3507 
3508  $description=new ITextarea('p_description');
3509  $description->style='class="itextarea" style="margin:0px;"';
3511  $str_description=$description->input();
3512 
3513  /* Load the card */
3514  $card = $this->get_fiche_def();
3515  $rdeb = explode(',', $card['deb']);
3516  $rcred = explode(',', $card['cred']);
3517  /* Numbering (only FIN) */
3518  $num_op = new ICheckBox('numb_operation');
3519  if ($this->jrn_def_num_op == 1)
3520  $num_op->selected = true;
3521  /* bank card */
3522  $qcode_bank = '';
3523  if ($type == 'FIN')
3524  {
3525  $f_id = $this->jrn_def_bank;
3526  if (isNumber($f_id) == 1)
3527  {
3528  $fBank = new Fiche($this->db, $f_id);
3529  $qcode_bank = $fBank->get_quick_code();
3530  }
3531  }
3532  $new = 0;
3533  $cn = $this->db;
3534  echo $hidden;
3535  require_once NOALYSS_TEMPLATE.'/param_jrn.php';
3536  }
3537 
3538  /**
3539  * Verify before update
3540  *
3541  * @param type $array
3542  * 'p_jrn' => string '3' (length=1)
3543  'sa' => string 'detail' (length=6)
3544  'gDossier' => string '82' (length=2)
3545  'p_jrn_deb_max_line' => string '10' (length=2)
3546  'p_ech_lib' => string 'echeance' (length=8)
3547  'p_jrn_type' => string 'ACH' (length=3)
3548  'p_jrn_name' => string 'Achat' (length=5)
3549  'jrn_def_pj_pref' => string 'ACH' (length=3)
3550  'jrn_def_pj_seq' => string '0' (length=1)
3551  'FICHECRED' =>
3552  array
3553  0 => string '4' (length=1)
3554  'FICHEDEB' =>
3555  array
3556  0 => string '7' (length=1)
3557  1 => string '5' (length=1)
3558  2 => string '13' (length=2)
3559  'update' => string 'Sauve' (length=5
3560  * @exception is throw is test are not valid
3561  */
3563  {
3564  extract($array, EXTR_SKIP);
3565  try
3566  {
3567  if (isNumber($p_jrn) == 0)
3568  throw new Exception("Id invalide");
3569  if (isNumber($p_jrn_deb_max_line) == 0)
3570  throw new Exception(_("Nombre de ligne incorrect"));
3571  if (trim($p_jrn_name) == "")
3572  throw new Exception("Nom de journal invalide");
3573  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)
3574  throw new Exception(_("Un journal avec ce nom existe déjà"));
3575  if ($p_jrn_type == 'FIN')
3576  {
3577  $a = new Fiche($this->db);
3578  $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false);
3579  if ($result == 1)
3580  throw new Exception(_("Aucun compte en banque n'est donné"));
3581  }
3582  if ($p_jrn_type == "-1") {
3583  throw new Exception(_('Choix du type de journal est obligatoire'));
3584  }
3585  }
3586  catch (Exception $e)
3587  {
3588  throw $e;
3589  }
3590  }
3591 
3592  /**
3593  * update a ledger
3594  * @param type $array normally post
3595  * @see verify_ledger
3596  */
3597  function update($array = '')
3598  {
3599  if ($array == null)
3600  throw new Exception('save cannot use a empty array');
3601 
3602  extract($array, EXTR_SKIP);
3603  $this->jrn_def_id = $p_jrn;
3604  $this->jrn_def_name = $p_jrn_name;
3605  $this->jrn_def_ech_lib = $p_ech_lib;
3606  $this->jrn_def_max_line_deb = ($p_jrn_deb_max_line<1)?1:$p_jrn_deb_max_line;
3607  $this->jrn_def_type = $p_jrn_type;
3608  $this->jrn_def_pj_pref = $jrn_def_pj_pref;
3609  $this->jrn_deb_max_line=($min_row<1)?1:$min_row;
3610  $this->jrn_def_description=$p_description;
3611  switch ($this->jrn_def_type)
3612  {
3613  case 'ACH':
3614  $this->jrn_def_fiche_cred = (isset($ACH_FICHECRED)) ? join($ACH_FICHECRED, ',') : '';
3615  $this->jrn_def_fiche_deb = (isset($ACH_FICHEDEB)) ? join($ACH_FICHEDEB, ',') : "";
3616  break;
3617  case 'VEN':
3618  $this->jrn_def_fiche_cred = (isset($VEN_FICHECRED)) ? join($VEN_FICHECRED, ',') : '';
3619  $this->jrn_def_fiche_deb = (isset($VEN_FICHEDEB)) ? join($VEN_FICHEDEB, ',') : "";
3620 
3621  break;
3622  case 'ODS':
3623  $this->jrn_def_class_deb = $p_jrn_class_deb;
3624  $this->jrn_def_fiche_deb = (isset($ODS_FICHEDEB)) ? join($ODS_FICHEDEB, ',') : '';;
3625  $this->jrn_def_fiche_cred = null;
3626  break;
3627 
3628  case 'FIN':
3629  $a = new Fiche($this->db);
3630  $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false);
3631  $bank = $a->id;
3632  $this->jrn_def_bank = $bank;
3633  $this->jrn_def_fiche_deb = (isset($FIN_FICHEDEB)) ? join($FIN_FICHEDEB, ',') : "";
3634  if ($result == -1)
3635  throw new Exception(_("Aucun compte en banque n'est donné"));
3636  $this->jrn_def_num_op = (isset($numb_operation)) ? 1 : 0;
3637  break;
3638  }
3639 
3640  parent::update();
3641  //Reset sequence if needed
3642  if ($jrn_def_pj_seq != 0)
3643  {
3644  $Res = $this->db->alter_seq("s_jrn_pj" . $p_jrn, $jrn_def_pj_seq);
3645  }
3646  }
3647 
3648  function input_paid($p_selected)
3649  {
3650  $r = '';
3651  $r.='<div id="payment"> ';
3652  $r.='<h2> ' . _('Payé par') . ' </h2>';
3653  $mp = new Acc_Payment($this->db);
3654  $mp->set_parameter('ledger_source', $this->id);
3655  $r.=$mp->select($p_selected);
3656  $r.='</div>';
3657  return $r;
3658  }
3659 
3660  /**
3661  * display screen to enter a new ledger
3662  */
3663  function input_new()
3664  {
3665  $retry=HtmlInput::default_value_post("sa", "");
3666 // if ( $retry == "add") {
3667  $default_type=HtmlInput::default_value_post("p_jrn_type", -1);
3668  $previous_jrn_def_pj_pref=HtmlInput::default_value_post("jrn_def_pj_pref","");
3669  $previous_p_description=HtmlInput::default_value_post("p_description","");
3670  $previous_p_jrn_name=HtmlInput::default_value_post('p_jrn_name','');
3671  $previous_p_jrn_type = HtmlInput::default_value_post("p_jrn_type","");
3672 // }
3673  global $g_user;
3674  $f_add_button=new ISmallButton('add_card');
3675  $f_add_button->label=_('Créer une nouvelle fiche');
3676  $f_add_button->tabindex=-1;
3677  $f_add_button->set_attribute('jrn',-1);
3678  $f_add_button->javascript=" this.jrn=-1;select_card_type({type_cat:4});";
3679 
3680  $str_add_button="";
3681  if ($g_user->check_action(FICADD)==1)
3682  {
3683  $str_add_button=$f_add_button->input();
3684  }
3685  $wSearch = new IPoste();
3686  $wSearch->table = 3;
3687  $wSearch->set_attribute('ipopup', 'ipop_account');
3688  $wSearch->set_attribute('account', 'p_jrn_class_deb');
3689  $wSearch->set_attribute('no_overwrite', '1');
3690  $wSearch->set_attribute('noquery', '1');
3691 
3692  $wSearch->name = "p_jrn_class_deb";
3693  $wSearch->size = 20;
3694 
3695  $search = $wSearch->input();
3696  // default for ACH
3697  $default_deb_purchase = $this->get_default_card('ACH', 'D');
3698  $default_cred_purchase = $this->get_default_card('ACH', 'C');
3699 
3700  // default for VEN
3701  $default_deb_sale = $this->get_default_card('VEN', 'D');
3702  $default_cred_sale = $this->get_default_card('VEN', 'C');
3703 
3704  // default for FIN
3705  $default_fin = $this->get_default_card("FIN", "");
3706 
3707  //default ods
3708  $default_ods = $this->get_default_card("ODS", "");
3709 
3710  /* construct all the hidden */
3711  $hidden = HtmlInput::hidden('p_jrn', -1);
3712  $hidden.= HtmlInput::hidden('p_action', 'jrn');
3713  $hidden.= HtmlInput::hidden('sa', 'add');
3714  $hidden.= dossier::hidden();
3715  $hidden.=HtmlInput::hidden('p_jrn_deb_max_line', 10);
3716  $hidden.=HtmlInput::hidden('p_ech_lib', 'echeance');
3717 
3718  /* properties of the ledger */
3719  $name = $previous_p_jrn_name;
3720  $code = "";
3721  $wType = new ISelect();
3722  $a_jrn= $this->db->make_array("select '-1',' -- "._("choix du type de journal")." -- ' union select jrn_type_id,jrn_desc from jrn_type");
3723  $wType->selected='-1';
3724  $wType->value =$a_jrn;
3725  $wType->name = "p_jrn_type";
3726  $wType->id= "p_jrn_type_select_id";
3727  $wType->javascript=' onchange="show_ledger_div()"';
3728  $wType->selected=$default_type;
3729  $type = $wType->input();
3730  $rcred = $rdeb = array();
3731  $wPjPref = new IText();
3732  $wPjPref->name = 'jrn_def_pj_pref';
3733  $wPjPref->value=$previous_jrn_def_pj_pref;
3734  $pj_pref = $wPjPref->input();
3735  $pj_seq = '';
3736  $last_seq = 0;
3737  $new = 1;
3738  $description=new ITextarea('p_description');
3739  $description->style='class="itextarea" style="margin:0px;"';
3740  $description->value=$previous_p_description;
3741  $str_description=$description->input();
3742  /* bank card */
3743  $qcode_bank = '';
3744  /* Numbering (only FIN) */
3745  $num_op = new ICheckBox('numb_operation');
3746  echo dossier::hidden();
3747  echo HtmlInput::hidden('ac', $_REQUEST['ac']);
3748  echo $hidden;
3749 
3750  $cn = $this->db;
3751  $min_row = new INum("min_row",MAX_ARTICLE);
3752  $min_row->prec=0;
3753  require_once NOALYSS_TEMPLATE.'/param_jrn.php';
3754  }
3755 
3756  /**
3757  * Insert a new ledger
3758  * @param type $array normally $_POST
3759  * @see verify_ledger
3760  */
3761  function save_new($array)
3762  {
3763  $this->load();
3764  extract($array, EXTR_SKIP);
3765  $this->jrn_def_id = -1;
3766  $this->jrn_def_name = $p_jrn_name;
3767  $this->jrn_def_ech_lib = $p_ech_lib;
3768  $this->jrn_def_max_line_deb = $p_jrn_deb_max_line;
3769  $this->jrn_def_type = $p_jrn_type;
3770  $this->jrn_def_pj_pref = $jrn_def_pj_pref;
3771  $this->jrn_deb_max_line=$min_row;
3772  $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));
3773  $this->jrn_def_description=$p_description;
3774  switch ($this->jrn_def_type)
3775  {
3776  case 'ACH':
3777  $this->jrn_def_fiche_cred = (isset($ACH_FICHECRED)) ? join($ACH_FICHECRED, ',') : '';
3778  $this->jrn_def_fiche_deb = (isset($ACH_FICHEDEB)) ? join($ACH_FICHEDEB, ',') : "";
3779  break;
3780  case 'VEN':
3781  $this->jrn_def_fiche_cred = (isset($VEN_FICHECRED)) ? join($VEN_FICHECRED, ',') : '';
3782  $this->jrn_def_fiche_deb = (isset($VEN_FICHEDEB)) ? join($VEN_FICHEDEB, ',') : "";
3783 
3784  break;
3785  case 'ODS':
3786  $this->jrn_def_class_deb = $p_jrn_class_deb;
3787  $this->jrn_def_fiche_deb = (isset($ODS_FICHEDEB)) ? join($ODS_FICHEDEB, ',') : '';;
3788  $this->jrn_def_fiche_cred = null;
3789  break;
3790  case 'FIN':
3791  $a = new Fiche($this->db);
3792  $result = $a->get_by_qcode(trim(strtoupper($_POST['bank'])), false);
3793  $bank = $a->id;
3794  $this->jrn_def_bank = $bank;
3795  $this->jrn_def_fiche_deb = (isset($FIN_FICHEDEB)) ? join($FIN_FICHEDEB, ',') : "";
3796  if ($result == -1)
3797  throw new Exception(_("Aucun compte en banque n'est donné"));
3798  $this->jrn_def_num_op = (isset($numb_operation)) ? 1 : 0;
3799  break;
3800  }
3801 
3802  parent::insert();
3803  }
3804 
3805  /**
3806  * delete a ledger IF is not already used
3807  * @exception : cannot delete
3808  */
3809  function delete_ledger()
3810  {
3811  try
3812  {
3813  if ($this->db->get_value("select count(jr_id) from jrn where jr_def_id=$1", array($this->jrn_def_id)) > 0)
3814  throw new Exception(_("Impossible d'effacer un journal qui contient des opérations"));
3815  parent::delete();
3816  }
3817  catch (Exception $e)
3818  {
3819  throw $e;
3820  }
3821  }
3822  /**
3823  * Get operation from the ledger type before, after or with the
3824  * given date . The array is filtered by the ledgers granted to the
3825  * user
3826  * @global type $g_user
3827  * @param $p_date Date (d.m.Y)
3828  * @param $p_ledger_type VEN ACH
3829  * @param type $sql_op < > or =
3830  * @return array from jrn (jr_id, jr_internal, jr_date, jr_comment,jr_pj_number,jr_montant)
3831  * @throws Exception
3832  */
3833  function get_operation_date($p_date,$p_ledger_type,$sql_op)
3834  {
3835  global $g_user;
3836  switch ($p_ledger_type)
3837  {
3838  case 'ACH':
3839  $filter=$g_user->get_ledger_sql('ACH',3);
3840  break;
3841  case 'VEN':
3842  $filter=$g_user->get_ledger_sql('VEN',3);
3843  break;
3844  default:
3845  throw new Exception ('Ledger_type invalid : '.$p_ledger_type);
3846  }
3847 
3848 
3849  $sql = "select jr_id, jr_internal, jr_date, jr_comment,jr_pj_number,jr_montant
3850  from jrn
3851  join jrn_def on (jrn_def_id=jr_def_id)
3852  where
3853  jr_ech is not null
3854  and jr_ech $sql_op to_date($1,'DD.MM.YYYY')
3855  and coalesce (jr_rapt,'xx') <> 'paid'
3856  and $filter
3857  ";
3858  $array=$this->db->get_array($sql,array($p_date));
3859  return $array;
3860  }
3861  /**
3862  * @brief get info from supplier to pay today
3863  */
3864  function get_supplier_now()
3865  {
3866  $array=$this->get_operation_date(Date('d.m.Y'), 'ACH', '=');
3867  return $array;
3868  }
3869  /**
3870  * @brief get info from supplier not yet paid
3871  */
3873  {
3874  $array=$this->get_operation_date(Date('d.m.Y'), 'ACH', '<');
3875  return $array;
3876  }
3877  /**
3878  * @brief get info from customer to pay today
3879  */
3880  function get_customer_now()
3881  {
3882  $array=$this->get_operation_date(Date('d.m.Y'), 'VEN', '=');
3883  return $array;
3884  }
3885  /**
3886  * @brief get info from customer not yet paid
3887  */
3889  {
3890  $array=$this->get_operation_date(Date('d.m.Y'), 'VEN', '<');
3891  return $array;
3892  }
3893  function convert_from_follow($p_ag_id)
3894  {
3895  global $g_user;
3896  if (isNumber($p_ag_id)==0) return null;
3897  if (! $g_user->can_read_action($p_ag_id)) die (_('Action non accessible'));
3898  $array=array();
3899 
3900  // retrieve info from action_gestion
3901  $tiers_id=$this->db->get_value('select f_id_dest from action_gestion where ag_id=$1',array($p_ag_id));
3902  if ( $this->db->size() !=0 )
3903  $qcode=$this->db->get_value('select j_qcode from vw_poste_qcode where f_id=$1',array($tiers_id));
3904  else
3905  $qcode="";
3906 
3907  $comment=$this->db->get_value('select ag_title from action_gestion where ag_id=$1',array($p_ag_id));
3908  $array['e_client']=$qcode;
3909  $array['e_comm']=$comment;
3910 
3911  // retrieve info from action_detail
3912  $a_item=$this->db->get_array('select f_id,ad_text,ad_pu,ad_quant,ad_tva_id,ad_tva_amount,j_qcode
3913  from
3914  action_detail
3915  left join vw_poste_qcode using(f_id)
3916  where
3917  ag_id=$1',array($p_ag_id));
3918 
3919  $array['nb_item']=($this->nb > count($a_item))?$this->nb:count($a_item);
3920  for ($i=0;$i<count($a_item);$i++)
3921  {
3922  $array['e_march'.$i]=$a_item[$i]['j_qcode'];
3923  $array['e_march'.$i.'_label']=$a_item[$i]['ad_text'];
3924  $array['e_march'.$i.'_price']=$a_item[$i]['ad_pu'];
3925  $array['e_march'.$i.'_tva_id']=$a_item[$i]['ad_tva_id'];
3926  $array['e_march'.$i.'_tva_amount']=$a_item[$i]['ad_tva_amount'];
3927  $array['e_quant'.$i]=$a_item[$i]['ad_quant'];
3928 
3929  }
3930  return $array;
3931 
3932  }
3933  /**
3934  * Retrieve the label of an accounting
3935  * @param $p_value tmp_pcmn.pcm_val
3936  * @return string
3937  */
3938  protected function find_label($p_value)
3939  {
3940  $lib=$this->db->get_value('select pcm_lib from tmp_pcmn where pcm_val=$1',array($p_value));
3941  return $lib;
3942  }
3943  /**
3944  * Let you select the repository before confirming a sale or a purchase.
3945  * Returns an empty string if the company doesn't use stock
3946  * @brief Let you select the repository before confirming a sale or a purchase.
3947  * @global type $g_parameter check if company is using stock
3948  * @param type $p_readonly
3949  * @param type $p_repo
3950  * @return string
3951  */
3952  public function select_depot($p_readonly, $p_repo)
3953  {
3954  global $g_parameter;
3955  $r=($p_readonly==false)?'<div id="repo_div_id" style="height:185px;height:10rem;">':'<div id="repo_div_id" >';
3956  // Show the available repository
3957  if ($g_parameter->MY_STOCK=='Y')
3958  {
3959  $sel=HtmlInput::select_stock($this->db, 'repo', 'W');
3960  $sel->readOnly=$p_readonly;
3961  if ($p_readonly==true)
3962  $sel->selected=$p_repo;
3963  $r.="<p class=\"decale\">"._('Dans le dépôt')." : ";
3964  $r.=$sel->input();
3965  $r.='</p>';
3966  } else
3967  {
3968  $r.='<span class="notice">'.'Stock non utilisé'.'</span>';
3969  }
3970  $r.='</div>';
3971  return $r;
3972 
3973  }
3974  /**
3975  * Create a button to encode a new operation into the same ledger
3976  * @return string
3977  */
3979  {
3980  $url=http_build_query(array('ac'=>$_REQUEST['ac'],'gDossier'=>$_REQUEST['gDossier'],'p_jrn'=>$_REQUEST['p_jrn']));
3981  $button = HtmlInput::button_anchor(_("Nouvelle opération"), 'do.php?'.$url,"","","smallbutton");
3982  return '<p>'.$button.'</p>';
3983  }
3984  /**
3985  *@brief Show a button to create an operation identical to the recorded
3986  * one. It is a form POST since it is a limit with get
3987  */
3988  public function button_copy_operation()
3989  {
3990  echo '<FORM METHOD="POST">';
3992  array("gDossier","ac","p_jrn","e_client","nb_item","desc","e_comm")
3993  );
3994  echo HtmlInput::hidden("correct","copy");
3995  // e_march
3996  $nb=HtmlInput::default_value_post("nb_item",0);
3997  for ( $i=0;$i<$nb;$i++)
3998  {
4000  array(
4001  "e_march".$i,
4002  "e_march".$i."_price",
4003  "e_march".$i."_quant",
4004  "e_march".$i."_label",
4005  "e_march".$i."_tva_id",
4006  "e_march".$i."_tva_amount",
4007  "e_quant".$i,
4008  "poste".$i,
4009  "ld".$i,
4010  "amount".$i,
4011  "ck".$i
4012 
4013  ));
4014  }
4015  echo HtmlInput::submit("copy_operation",_("Opération identique"));
4016 
4017  echo '</FORM>';
4018  }
4019 }
4020 ?>
get_name()
Return the name of a ledger.
alert($p_msg, $buffer=false)
alert in javascript
Definition: ac_common.php:666
$_GET['qcode']
$jrn_def_description[]
$_POST['ac']
Definition: do.php:279
$str
Definition: fiche.inc.php:97
get_supplier_late()
get info from supplier not yet paid
$select
get_last_date()
get the date of the last operation
Generate the form for the periode Data Members.
select_depot($p_readonly, $p_repo)
Let you select the repository before confirming a sale or a purchase.
list_operation($sql, $offset, $p_paid=0)
Show all the operation.
static default_value_post($ind, $default)
return default if the value if the value doesn't exist in $_POST
static card_detail($p_qcode, $pname='', $p_style="", $p_nohistory=false)
show the detail of a card
static fetch_all($ret)
wrapper for the function pg_fetch_all
get_tiers_id($p_jrn_type, $jr_id)
Return the f_id of the tiers , called by get_tiers.
if($g_user->check_dossier(dossier::id(), true)=='X') $op
Definition: ajax_ledger.php:89
this class is used to show the form for entering an operation only FOR analytic operation to save it...
get_propertie()
Get the properties of a journal.
mother class for the lettering by account and by card use the tables jnt_letter, letter_deb and lette...
check_payment($e_mp, $e_mp_qcode)
check if the payment method is valid
$bal jrn
delete_ledger()
delete a ledger IF is not already used cannot delete
sql_string($p_string)
Fix the problem with the quote char for the database.
Definition: ac_common.php:457
nb($p_number)
format the number for the CSV export
Definition: ac_common.php:107
td($p_string='', $p_extra='')
surround the string with td
Definition: ac_common.php:83
vat_operation($p_jr_id)
get the amount of vat for a given jr_grpt_id from the table quant_purchase
input_paid($p_selected)
static infobulle($p_comment)
const FICADD
static num_row($ret)
wrapper for the function pg_NumRows
Class Document corresponds to the table document.
const FICHE_TYPE_FOURNISSEUR
Definition: constant.php:216
$class
listing()
listing of all ledgers
Manage the account from the table tmp_pcmn.
h2($p_string, $p_class="", $raw="")
Definition: ac_common.php:68
th($p_string, $p_extra='', $raw='')
Definition: ac_common.php:58
show a button, for selecting a account and a input text for manually inserting an account the differe...
get_class_def()
retrieve the jrn_def_class_deb and return it
button_new_operation()
Create a button to encode a new operation into the same ledger.
$id
jrn_def.jrn_def_id
nbm($p_number, $p_dec=2)
format the number with a sep.
Definition: ac_common.php:121
get_rowSimple($p_from, $p_to, $trunc=0, $p_limit=-1, $p_offset=-1)
Get simplified row from ledger.
get_supplier_now()
get info from supplier to pay today
create_document($internal, $p_array)
create the invoice and saved it as attachment to the operation,
Data & function about connected users.
Definition: class_user.php:36
get_default_card($p_ledger_type, $p_side)
Return an array of default card for the ledger type given.
static hidden($p_array)
return an HTML string containing hidden input type to hold the differant PA_ID
for($i=0;$i< count($a);$i++)
manage the predefined operation, link to the table op_def and op_def_detail
display_ledger()
display detail of a ledger
const FICHE_TYPE_ACH_MAT
Definition: constant.php:223
convert_from_follow($p_ag_id)
Concerns the Analytic plan (table plan_analytique)
get_operation_date($p_date, $p_ledger_type, $sql_op)
Get operation from the ledger type before, after or with the given date .
const FICHE_TYPE_CLIENT
Definition: constant.php:214
Manage the account from the table jrn, jrnx or tmp_pcmn.
list_operation_to_reconcile($sql, $p_target)
Show all the operation.
get_type()
Return the type of a ledger (ACH,VEN,ODS or FIN) or GL.
const FICHE_TYPE_VENTE
Definition: constant.php:215
isNumber(&$p_int)
Definition: ac_common.php:202
$value
static button($p_name, $p_value, $p_javascript="", $p_class="smallbutton")
input_new()
display screen to enter a new ledger
const FICHE_TYPE_FIN
Definition: constant.php:217
verify($p_array)
verify that the operation can be saved
get_first($p_type, $p_access=3)
get the first ledger
__construct($p_cn, $p_id)
$jrn_def_name[]
toNumber($p_num)
remove the useless space, change comma by period and try to return a number
const MAX_COMPTE_CARD
Definition: constant.php:122
foreach($array as $idx=> $m) $w
$idx
reverse($p_date)
reverse the operation by creating the opposite one, the result is to avoid it it must be done in ...
CleanUrl()
Clean the url, remove the $_GET offset,step, page and size.
static escape_string($p_string)
wrapper for the function pg_escape_string
update_internal_code($p_internal)
$def
show a form for quick_writing
update_paid($p_array)
Update the paiment in the list of operation.
$row
row of the ledger
get_customer_late()
get info from customer not yet paid
compute_internal_code($p_grpt)
compute the internal code of the saved operation and set the $this->jr_internal to the computed value...
display_warning($pa_msg, $p_warning)
Display warning contained in an array.
guess_pj()
guess what the next pj should be
get_detail(&$p_array, $p_jrn_type, $trunc=0, $a_TVA=null, $a_ParmCode=null)
get_detail gives the detail of row this array must contains at least the field
$code
search_group($p_what, $p_value)
retreive the jr_grpt_id from a ledger
static anchor_hide($action, $javascript)
Return a html string with an anchor to hide a div, put it in the right corner.
static fetch_array($ret, $p_indice=0)
wrapper for the function pg_fetch_array
get_operation($p_from, $p_to)
retrieve operation from jrn
select_ledger($p_type="ALL", $p_access=3)
Show a select list of the ledgers you can access in writing, reading or simply accessing.
get_other_amount($p_jr_id)
get the amount of vat for a given jr_grpt_id from the table quant_purchase
get_all_fiche_def()
retrieve all the card for this type of ledger, make them into a string separated by comma ...
$ledger with_concerned
save_new($array)
Insert a new ledger.
function document
Definition: smoke.js:7
if(!isset($_REQUEST['act'])||!isset($_REQUEST['jr_id'])||!isset($_REQUEST['div'])) global $g_parameter
Definition: ajax_ledger.php:46
const OPEN
Definition: constant.php:170
check_strict()
Check if a Dossier is using the strict mode or not.
const FICHE_TYPE_ADM_TAX
Definition: constant.php:220
$div
For the periode tables parm_periode and jrn_periode.
define Class fiche and fiche def, those class are using class attribut. When adding or modifing new c...
Definition: class_fiche.php:44
sql_filter_per($p_cn, $p_from, $p_to, $p_form='p_id', $p_field='jr_tech_per')
Create the condition to filter on the j_tech_per thanks a from and to date.
Definition: ac_common.php:622
static post_to_hidden($array)
transform $_POST data to hidden
static select_stock($p_cn, $p_name, $p_mode)
Create an ISelect object containing the available repository for reading or writing.
get_row($p_from, $p_to, $p_limit=-1, $p_offset=-1)
Get The data.
const SQL_LIST_UNPAID_INVOICE
Definition: constant.php:295
static submit($p_name, $p_value, $p_javascript="", $p_class="smallbutton")
$str_dossier
Definition: anc_od.inc.php:38
previous_amount($p_to)
retrieve amount of previous periode
get_last($p_limit)
return the last p_limit operation into an array
static filter_table($p_table_id, $p_col, $start_row)
update($array= '')
update a ledger
for($i=0;$i<$nb_jrn;$i++) $deb
get_id($p_internal)
retrieve the jr_id thanks the internal code, do not change anything to the current object ...
global $g_user
Find the default module or the first one.
Definition: action.inc.php:24
$date_limit
Class for jrn, class acc_ledger for manipulating the ledger.
$from_poste name
$type
type of the ledger ACH ODS FIN VEN or GL
if($ck==0) $anc
static button_anchor($p_label, $p_value, $p_name="", $p_javascript="", $p_class="button")
create a button with a ref
search_form($p_type, $all_type_ledger=1, $div="")
return a HTML string with the form for the search
verify_ledger($array)
Verify before update.
$date_start
$_REQUEST['ac']
$bilan from
function trim(s)
remove trailing and heading space
Definition: scripts.js:95
new class for managing the reconciliation it must be used instead of the function InsertRapt...
if(!isset($_REQUEST['p_jrn'])) else $Ledger id
$all
get_tiers($p_jrn_type, $jr_id)
Retrieve the third : supplier for purchase, customer for sale, bank for fin,.
GetDefLine()
Get the number of lines of a journal.
build_search_sql($p_array, $p_order="", $p_where="")
this function will create a sql stmt to use to create the list for the ledger,
static id()
return the $_REQUEST['gDossier'] after a check
static array_cat()
create an array of the existing cat, to be used in a checkbox form
h($p_string)
to protect again bad characters which can lead to a cross scripting attack the string to be diplayed ...
Definition: ac_common.php:38
const FICHE_TYPE_EMPL
Definition: constant.php:219
this file match the tables jrn & jrnx the purpose is to remove or save accountant writing to these ta...
This class allow you to connect to the postgresql database, execute sql, retrieve data...
$count
Definition: modele.inc.php:255
isDate($p_date)
Definition: ac_common.php:223
$input_from type
Definition: balance.inc.php:70
get_solde($p_from, $p_to)
get the saldo of a ledger for a specific period
static connect()
Description of class_syn_sort_table.
vous n
Definition: modele.inc.php:258
save($p_array=null)
save the operation into the jrnx,jrn, , CA and pre_def
const ATTR_DEF_QUICKCODE
Definition: constant.php:206
get_customer_now()
get info from customer to pay today
Input HTML for the card show buttons, in the file, you have to add card.js How to use : ...
const FICHE_TYPE_ACH_MAR
Definition: constant.php:221
$check_periode
Definition: company.inc.php:93
button_copy_operation()
Show a button to create an operation identical to the recorded one.
get_saldo_exercice($p_exercice)
get the saldo of an exercice, used for the opening of a folder
$jr_id
Definition: ajax_ledger.php:56
$db
database connextion
$nb
default number of rows by default 10
tr($p_string, $p_extra='')
Definition: ac_common.php:88
const FICHE_TYPE_ACH_SER
Definition: constant.php:222
$limit
Definition: dashboard.php:157
const MAX_ARTICLE
Definition: constant.php:116
input($p_array=null, $p_readonly=0)
Show the form to encode your operation.
$SecUser db
Handle the table mod_payment.
fiche_def_ref, a fiche is owned by fiche_def which is owned by fiche_def_ref
if(!isset($_GET['submit_query'])) $p_action
check_periode()
Check if a Dossier is using the check on the periode, if true than the user has to enter the date and...
concerns the predefined operation for the operation from 'Ecriture direct'
$description
get_request()
get all the data from request and build the object
static test_me($pCase= '')
this function is intended to test this class
html_page_start($p_theme="", $p_script="", $p_script2="")
Default page header for each page.
Definition: ac_common.php:262
$select_type table
get_fiche_def()
retrieve the jrn_def_fiche and return them into a array index deb, cred
const ATTR_DEF_NAME
Definition: constant.php:185
inc_seq_pj()
increment the sequence for the pj
this object handles the table quant_sold
static next_number($p_cn, $p_type)
retrieve the next number for this type of ledger
if(isset($_REQUEST['gDossier'])&&$_REQUEST['gDossier']<>0) $repo
const ATTR_DEF_ACCOUNT
Definition: constant.php:184
static hidden($p_name, $p_value, $p_id="")
$oPeriode
Definition: do.php:177
$p
Definition: array.php:34
confirm($p_array, $p_readonly=false)
show the result of the array to confirm before inserting
existing_vat()
return the used VAT code with a rate > 0
$op jr_id
Definition: ajax_ledger.php:90
$type
$url
for($e=0;$e< count($afiche);$e++) exit
$name
jrn_def.jrn_def_name
$href
Definition: adm.inc.php:38
$r_jrn
display_search_form()
return a html string with the search_form
Html Input : Input a date format dd.mm.yyyy The property title should be set to indicate what it is e...
Definition: class_idate.php:31
This class handles only the numeric input, the input will call a javascript to change comma to period...
Definition: class_inum.php:40
find_label($p_value)
Retrieve the label of an accounting.