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