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