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