dolibarr 21.0.0-alpha
bookkeeping.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2014-2017 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2015-2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
4 * Copyright (C) 2015-2020 Florian Henry <florian.henry@open-concept.pro>
5 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Class
29require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
30require_once DOL_DOCUMENT_ROOT.'/core/class/commonobjectline.class.php';
31require_once DOL_DOCUMENT_ROOT.'/core/class/fiscalyear.class.php';
32require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
33require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
34
39{
43 public $element = 'accountingbookkeeping';
44
48 public $table_element = 'accounting_bookkeeping';
49
53 public $entity;
54
58 public $lines = array();
59
63 public $id;
64
68 public $doc_date;
69
73 public $date_lim_reglement;
74
78 public $doc_type;
79
83 public $doc_ref;
84
88 public $fk_doc;
89
93 public $fk_docdet;
94
98 public $thirdparty_code;
99
103 public $subledger_account;
104
108 public $subledger_label;
109
113 public $numero_compte;
114
118 public $label_compte;
119
123 public $label_operation;
124
128 public $debit;
129
133 public $credit;
134
139 public $montant;
140
145 public $amount;
146
150 public $sens;
151
155 public $fk_user_author;
156
160 public $import_key;
161
165 public $code_journal;
166
170 public $journal_label;
171
175 public $piece_num;
176
180 public $linesmvt = array();
181
185 public $linesexport = array();
186
190 public $date_export;
191
195 public $picto = 'generic';
196
200 public static $can_modify_bookkeeping_sql_cached;
201
202
208 public function __construct(DoliDB $db)
209 {
210 $this->db = $db;
211 }
212
220 public function create(User $user, $notrigger = 0)
221 {
222 global $conf, $langs;
223
224 dol_syslog(__METHOD__, LOG_DEBUG);
225
226 $error = 0;
227
228 // Clean parameters</center>
229 if (isset($this->doc_type)) {
230 $this->doc_type = trim($this->doc_type);
231 }
232 if (isset($this->doc_ref)) {
233 $this->doc_ref = trim($this->doc_ref);
234 }
235 if (isset($this->fk_doc)) {
236 $this->fk_doc = (int) $this->fk_doc;
237 }
238 if (isset($this->fk_docdet)) {
239 $this->fk_docdet = (int) $this->fk_docdet;
240 }
241 if (isset($this->thirdparty_code)) {
242 $this->thirdparty_code = trim($this->thirdparty_code);
243 }
244 if (isset($this->subledger_account)) {
245 $this->subledger_account = trim($this->subledger_account);
246 }
247 if (isset($this->subledger_label)) {
248 $this->subledger_label = trim($this->subledger_label);
249 }
250 if (isset($this->numero_compte)) {
251 $this->numero_compte = trim($this->numero_compte);
252 }
253 if (isset($this->label_compte)) {
254 $this->label_compte = trim($this->label_compte);
255 }
256 if (isset($this->label_operation)) {
257 $this->label_operation = trim($this->label_operation);
258 }
259 if (isset($this->debit)) {
260 $this->debit = (float) $this->debit;
261 }
262 if (isset($this->credit)) {
263 $this->credit = (float) $this->credit;
264 }
265 if (isset($this->montant)) {
266 $this->montant = (float) $this->montant;
267 }
268 if (isset($this->amount)) {
269 $this->amount = (float) $this->amount;
270 }
271 if (isset($this->sens)) {
272 $this->sens = trim($this->sens);
273 }
274 if (isset($this->import_key)) {
275 $this->import_key = trim($this->import_key);
276 }
277 if (isset($this->code_journal)) {
278 $this->code_journal = trim($this->code_journal);
279 }
280 if (isset($this->journal_label)) {
281 $this->journal_label = trim($this->journal_label);
282 }
283 if (isset($this->piece_num)) {
284 $this->piece_num = (int) $this->piece_num;
285 }
286 if (empty($this->debit)) {
287 $this->debit = 0.0;
288 }
289 if (empty($this->credit)) {
290 $this->credit = 0.0;
291 }
292
293 $result = $this->validBookkeepingDate($this->doc_date);
294 if ($result < 0) {
295 return -1;
296 } elseif ($result == 0) {
297 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
298 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod');
299 } else {
300 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod');
301 }
302 return -1;
303 }
304
305 // Check parameters
306 if (($this->numero_compte == "") || $this->numero_compte == '-1' || $this->numero_compte == 'NotDefined') {
307 $langs->loadLangs(array("errors"));
308 if (in_array($this->doc_type, array('bank', 'expense_report'))) {
309 $this->errors[] = $langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet, $this->doc_type);
310 } else {
311 //$this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForInvoiceLine', $this->doc_ref, $this->label_compte);
312 $mesg = $this->doc_ref.', '.$langs->trans("AccountAccounting").': '.($this->numero_compte != -1 ? $this->numero_compte : $langs->trans("Unknown"));
313 if ($this->subledger_account && $this->subledger_account != $this->numero_compte) {
314 $mesg .= ', '.$langs->trans("SubledgerAccount").': '.$this->subledger_account;
315 }
316 $this->errors[] = $langs->trans('ErrorFieldAccountNotDefinedForLine', $mesg);
317 }
318
319 return -1;
320 }
321
322 $this->db->begin();
323
324 $this->piece_num = 0;
325
326 // First check if line not yet already in bookkeeping.
327 // Note that we must include 'doc_type - fk_doc - numero_compte - label' to be sure to have unicity of line (because we may have several lines
328 // with same doc_type, fk_doc, numero_compte for 1 invoice line when using localtaxes with same account)
329 // WARNING: This is not reliable, label may have been modified. This is just a small protection.
330 // The page that make transfer make the test on couple (doc_type - fk_doc) only.
331 $sql = "SELECT count(*) as nb";
332 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
333 $sql .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'";
334 $sql .= " AND fk_doc = ".((int) $this->fk_doc);
335 if (getDolGlobalString('ACCOUNTANCY_ENABLE_FKDOCDET')) {
336 // DO NOT USE THIS IN PRODUCTION. This will generate a lot of trouble into reports and will corrupt database (by generating duplicate entries.
337 $sql .= " AND fk_docdet = ".((int) $this->fk_docdet); // This field can be 0 if record is for several lines
338 }
339 $sql .= " AND numero_compte = '".$this->db->escape($this->numero_compte)."'";
340 $sql .= " AND label_operation = '".$this->db->escape($this->label_operation)."'";
341 $sql .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
342
343 $resql = $this->db->query($sql);
344
345 if ($resql) {
346 $row = $this->db->fetch_object($resql);
347 if ($row->nb == 0) { // Not already into bookkeeping
348 // Check to know if piece_num already exists for data we try to insert to reuse the same value
349 $sqlnum = "SELECT piece_num";
350 $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
351 $sqlnum .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'"; // For example doc_type = 'bank'
352 $sqlnum .= " AND fk_doc = ".((int) $this->fk_doc);
353 if (getDolGlobalString('ACCOUNTANCY_ENABLE_FKDOCDET')) {
354 // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ...
355 $sqlnum .= " AND fk_docdet = ".((int) $this->fk_docdet);
356 }
357 $sqlnum .= " AND doc_ref = '".$this->db->escape($this->doc_ref)."'"; // ref of source object
358 $sqlnum .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
359
360 dol_syslog(get_class($this).":: create sqlnum=".$sqlnum, LOG_DEBUG);
361 $resqlnum = $this->db->query($sqlnum);
362 if ($resqlnum) {
363 $objnum = $this->db->fetch_object($resqlnum);
364 $this->piece_num = $objnum->piece_num;
365 }
366
367 dol_syslog(get_class($this)."::create this->piece_num=".$this->piece_num, LOG_DEBUG);
368 if (empty($this->piece_num)) {
369 $sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum";
370 $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
371 $sqlnum .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
372
373 $resqlnum = $this->db->query($sqlnum);
374 if ($resqlnum) {
375 $objnum = $this->db->fetch_object($resqlnum);
376 $this->piece_num = $objnum->maxpiecenum;
377 }
378 dol_syslog(get_class($this).":: create now this->piece_num=".$this->piece_num, LOG_DEBUG);
379 }
380 if (empty($this->piece_num)) {
381 $this->piece_num = 1;
382 }
383
384 $now = dol_now();
385
386 $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
387 $sql .= "doc_date";
388 $sql .= ", date_lim_reglement";
389 $sql .= ", doc_type";
390 $sql .= ", doc_ref";
391 $sql .= ", fk_doc";
392 $sql .= ", fk_docdet";
393 $sql .= ", thirdparty_code";
394 $sql .= ", subledger_account";
395 $sql .= ", subledger_label";
396 $sql .= ", numero_compte";
397 $sql .= ", label_compte";
398 $sql .= ", label_operation";
399 $sql .= ", debit";
400 $sql .= ", credit";
401 $sql .= ", montant";
402 $sql .= ", sens";
403 $sql .= ", fk_user_author";
404 $sql .= ", date_creation";
405 $sql .= ", code_journal";
406 $sql .= ", journal_label";
407 $sql .= ", piece_num";
408 $sql .= ', entity';
409 $sql .= ") VALUES (";
410 $sql .= "'".$this->db->idate($this->doc_date)."'";
411 $sql .= ", ".(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'");
412 $sql .= ", '".$this->db->escape($this->doc_type)."'";
413 $sql .= ", '".$this->db->escape($this->doc_ref)."'";
414 $sql .= ", ".((int) $this->fk_doc);
415 $sql .= ", ".((int) $this->fk_docdet);
416 $sql .= ", ".(!empty($this->thirdparty_code) ? ("'".$this->db->escape($this->thirdparty_code)."'") : "NULL");
417 $sql .= ", ".(!empty($this->subledger_account) ? ("'".$this->db->escape($this->subledger_account)."'") : "NULL");
418 $sql .= ", ".(!empty($this->subledger_label) ? ("'".$this->db->escape($this->subledger_label)."'") : "NULL");
419 $sql .= ", '".$this->db->escape($this->numero_compte)."'";
420 $sql .= ", ".(!empty($this->label_compte) ? ("'".$this->db->escape($this->label_compte)."'") : "NULL");
421 $sql .= ", '".$this->db->escape($this->label_operation)."'";
422 $sql .= ", ".((float) $this->debit);
423 $sql .= ", ".((float) $this->credit);
424 $sql .= ", ".((float) $this->montant);
425 $sql .= ", ".(!empty($this->sens) ? ("'".$this->db->escape($this->sens)."'") : "NULL");
426 $sql .= ", '".$this->db->escape($this->fk_user_author)."'";
427 $sql .= ", '".$this->db->idate($now)."'";
428 $sql .= ", '".$this->db->escape($this->code_journal)."'";
429 $sql .= ", ".(!empty($this->journal_label) ? ("'".$this->db->escape($this->journal_label)."'") : "NULL");
430 $sql .= ", ".((int) $this->piece_num);
431 $sql .= ", ".(!isset($this->entity) ? $conf->entity : $this->entity);
432 $sql .= ")";
433
434 $resql = $this->db->query($sql);
435 if ($resql) {
436 $id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
437
438 if ($id > 0) {
439 $this->id = $id;
440 $result = 0;
441 } else {
442 $result = -2;
443 $error++;
444 $this->errors[] = 'Error Create Error '.$result.' lecture ID';
445 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
446 }
447 } else {
448 $result = -1;
449 $error++;
450 $this->errors[] = 'Error '.$this->db->lasterror();
451 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
452 }
453 } else { // Already exists
454 $result = -3;
455 $error++;
456 $this->error = 'BookkeepingRecordAlreadyExists';
457 dol_syslog(__METHOD__.' '.$this->error, LOG_WARNING);
458 }
459 } else {
460 $result = -5;
461 $error++;
462 $this->errors[] = 'Error '.$this->db->lasterror();
463 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
464 }
465
466 // Uncomment this and change MYOBJECT to your own tag if you
467 // want this action to call a trigger.
468 //if (! $error && ! $notrigger) {
469
470 // // Call triggers
471 // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
472 // if ($result < 0) $error++;
473 // // End call triggers
474 //}
475
476 // Commit or rollback
477 if ($error) {
478 $this->db->rollback();
479 return -1 * $error;
480 } else {
481 $this->db->commit();
482 return $result;
483 }
484 }
485
496 public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
497 {
498 global $db, $conf, $langs;
499 global $dolibarr_main_authentication, $dolibarr_main_demo;
500 global $menumanager, $hookmanager;
501
502 if (!empty($conf->dol_no_mouse_hover)) {
503 $notooltip = 1; // Force disable tooltips
504 }
505
506 $result = '';
507 $companylink = '';
508
509 $label = '<u>'.$langs->trans("Transaction").'</u>';
510 $label .= '<br>';
511 $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->piece_num;
512
513 $url = DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?piece_num='.$this->piece_num;
514
515 if ($option != 'nolink') {
516 // Add param to save lastsearch_values or not
517 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
518 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
519 $add_save_lastsearch_values = 1;
520 }
521 if ($add_save_lastsearch_values) {
522 $url .= '&save_lastsearch_values=1';
523 }
524 }
525
526 $linkclose = '';
527 if (empty($notooltip)) {
528 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
529 $label = $langs->trans("ShowTransaction");
530 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
531 }
532 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
533 $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
534 } else {
535 $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
536 }
537
538 $linkstart = '<a href="'.$url.'"';
539 $linkstart .= $linkclose.'>';
540 $linkend = '</a>';
541
542 $result .= $linkstart;
543 if ($withpicto) {
544 $result .= img_object(($notooltip ? '' : $label), ($this->picto ? $this->picto : 'generic'), ($notooltip ? (($withpicto != 2) ? 'class="paddingright"' : '') : 'class="'.(($withpicto != 2) ? 'paddingright ' : '').'classfortooltip"'), 0, 0, $notooltip ? 0 : 1);
545 }
546 if ($withpicto != 2) {
547 $result .= $this->piece_num;
548 }
549 $result .= $linkend;
550 //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
551
552 global $action;
553 $hookmanager->initHooks(array($this->element . 'dao'));
554 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
555 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
556 if ($reshook > 0) {
557 $result = $hookmanager->resPrint;
558 } else {
559 $result .= $hookmanager->resPrint;
560 }
561 return $result;
562 }
563
572 public function createStd(User $user, $notrigger = 0, $mode = '')
573 {
574 global $conf, $langs;
575
576 $langs->loadLangs(array("accountancy", "bills", "compta"));
577
578 dol_syslog(__METHOD__, LOG_DEBUG);
579
580 $error = 0;
581
582 // Clean parameters
583 if (isset($this->doc_type)) {
584 $this->doc_type = trim($this->doc_type);
585 }
586 if (isset($this->doc_ref)) {
587 $this->doc_ref = trim($this->doc_ref);
588 }
589 if (isset($this->fk_doc)) {
590 $this->fk_doc = (int) $this->fk_doc;
591 }
592 if (isset($this->fk_docdet)) {
593 $this->fk_docdet = (int) $this->fk_docdet;
594 }
595 if (isset($this->thirdparty_code)) {
596 $this->thirdparty_code = trim($this->thirdparty_code);
597 }
598 if (isset($this->subledger_account)) {
599 $this->subledger_account = trim($this->subledger_account);
600 }
601 if (isset($this->subledger_label)) {
602 $this->subledger_label = trim($this->subledger_label);
603 }
604 if (isset($this->numero_compte)) {
605 $this->numero_compte = trim($this->numero_compte);
606 }
607 if (isset($this->label_compte)) {
608 $this->label_compte = trim($this->label_compte);
609 }
610 if (isset($this->label_operation)) {
611 $this->label_operation = trim($this->label_operation);
612 }
613 if (isset($this->sens)) {
614 $this->sens = trim($this->sens);
615 }
616 if (isset($this->import_key)) {
617 $this->import_key = trim($this->import_key);
618 }
619 if (isset($this->code_journal)) {
620 $this->code_journal = trim($this->code_journal);
621 }
622 if (isset($this->journal_label)) {
623 $this->journal_label = trim($this->journal_label);
624 }
625 if (isset($this->piece_num)) {
626 $this->piece_num = (int) $this->piece_num;
627 }
628 if (empty($this->debit)) {
629 $this->debit = 0;
630 }
631 if (empty($this->credit)) {
632 $this->credit = 0;
633 }
634 if (empty($this->montant)) {
635 $this->montant = 0;
636 }
637
638 $result = $this->validBookkeepingDate($this->doc_date);
639 if ($result < 0) {
640 return -1;
641 } elseif ($result == 0) {
642 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
643 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod');
644 } else {
645 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod');
646 }
647 return -1;
648 }
649
650 $this->debit = (float) price2num($this->debit, 'MT');
651 $this->credit = (float) price2num($this->credit, 'MT');
652 $this->montant = (float) price2num($this->montant, 'MT');
653
654 $now = dol_now();
655
656 // Check parameters
657 $this->journal_label = $langs->trans($this->journal_label);
658
659 // Insert request
660 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.$mode.' (';
661 $sql .= 'doc_date,';
662 $sql .= 'date_lim_reglement,';
663 $sql .= 'doc_type,';
664 $sql .= 'doc_ref,';
665 $sql .= 'fk_doc,';
666 $sql .= 'fk_docdet,';
667 $sql .= 'thirdparty_code,';
668 $sql .= 'subledger_account,';
669 $sql .= 'subledger_label,';
670 $sql .= 'numero_compte,';
671 $sql .= 'label_compte,';
672 $sql .= 'label_operation,';
673 $sql .= 'debit,';
674 $sql .= 'credit,';
675 $sql .= 'montant,';
676 $sql .= 'sens,';
677 $sql .= 'fk_user_author,';
678 $sql .= 'date_creation,';
679 $sql .= 'code_journal,';
680 $sql .= 'journal_label,';
681 $sql .= 'piece_num,';
682 $sql .= 'entity';
683 $sql .= ') VALUES (';
684 $sql .= ' '.(!isset($this->doc_date) || dol_strlen($this->doc_date) == 0 ? 'NULL' : "'".$this->db->idate($this->doc_date)."'").',';
685 $sql .= ' '.(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'").',';
686 $sql .= ' '.(!isset($this->doc_type) ? 'NULL' : "'".$this->db->escape($this->doc_type)."'").',';
687 $sql .= ' '.(!isset($this->doc_ref) ? 'NULL' : "'".$this->db->escape($this->doc_ref)."'").',';
688 $sql .= ' '.(empty($this->fk_doc) ? '0' : (int) $this->fk_doc).',';
689 $sql .= ' '.(empty($this->fk_docdet) ? '0' : (int) $this->fk_docdet).',';
690 $sql .= ' '.(!isset($this->thirdparty_code) ? 'NULL' : "'".$this->db->escape($this->thirdparty_code)."'").',';
691 $sql .= ' '.(!isset($this->subledger_account) ? 'NULL' : "'".$this->db->escape($this->subledger_account)."'").',';
692 $sql .= ' '.(!isset($this->subledger_label) ? 'NULL' : "'".$this->db->escape($this->subledger_label)."'").',';
693 $sql .= ' '.(!isset($this->numero_compte) ? 'NULL' : "'".$this->db->escape($this->numero_compte)."'").',';
694 $sql .= ' '.(!isset($this->label_compte) ? 'NULL' : "'".$this->db->escape($this->label_compte)."'").',';
695 $sql .= ' '.(!isset($this->label_operation) ? 'NULL' : "'".$this->db->escape($this->label_operation)."'").',';
696 $sql .= ' '.(!isset($this->debit) ? 'NULL' : $this->debit).',';
697 $sql .= ' '.(!isset($this->credit) ? 'NULL' : $this->credit).',';
698 $sql .= ' '.(!isset($this->montant) ? 'NULL' : $this->montant).',';
699 $sql .= ' '.(!isset($this->sens) ? 'NULL' : "'".$this->db->escape($this->sens)."'").',';
700 $sql .= ' '.((int) $user->id).',';
701 $sql .= ' '."'".$this->db->idate($now)."',";
702 $sql .= ' '.(empty($this->code_journal) ? 'NULL' : "'".$this->db->escape($this->code_journal)."'").',';
703 $sql .= ' '.(empty($this->journal_label) ? 'NULL' : "'".$this->db->escape($this->journal_label)."'").',';
704 $sql .= ' '.(empty($this->piece_num) ? 'NULL' : $this->db->escape($this->piece_num)).',';
705 $sql .= ' '.(!isset($this->entity) ? $conf->entity : $this->entity);
706 $sql .= ')';
707
708 $this->db->begin();
709
710 $resql = $this->db->query($sql);
711 if (!$resql) {
712 $error++;
713 $this->errors[] = 'Error '.$this->db->lasterror();
714 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
715 }
716
717 if (!$error) {
718 $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element.$mode);
719 }
720
721 // Commit or rollback
722 if ($error) {
723 $this->db->rollback();
724
725 return -1 * $error;
726 } else {
727 $this->db->commit();
728
729 return $this->id;
730 }
731 }
732
741 public function fetch($id, $ref = null, $mode = '')
742 {
743 global $conf;
744
745 dol_syslog(__METHOD__, LOG_DEBUG);
746
747 $sql = 'SELECT';
748 $sql .= ' t.rowid,';
749 $sql .= " t.doc_date,";
750 $sql .= " t.date_lim_reglement,";
751 $sql .= " t.doc_type,";
752 $sql .= " t.doc_ref,";
753 $sql .= " t.fk_doc,";
754 $sql .= " t.fk_docdet,";
755 $sql .= " t.thirdparty_code,";
756 $sql .= " t.subledger_account,";
757 $sql .= " t.subledger_label,";
758 $sql .= " t.numero_compte,";
759 $sql .= " t.label_compte,";
760 $sql .= " t.label_operation,";
761 $sql .= " t.debit,";
762 $sql .= " t.credit,";
763 $sql .= " t.montant as amount,";
764 $sql .= " t.sens,";
765 $sql .= " t.fk_user_author,";
766 $sql .= " t.import_key,";
767 $sql .= " t.code_journal,";
768 $sql .= " t.journal_label,";
769 $sql .= " t.piece_num,";
770 $sql .= " t.date_creation,";
771 // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
772 if ($mode != "_tmp") {
773 $sql .= " t.date_export,";
774 }
775 $sql .= " t.date_validated as date_validation";
776 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.$mode.' as t';
777 $sql .= ' WHERE 1 = 1';
778 $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
779 if (null !== $ref) {
780 $sql .= " AND t.rowid = ".((int) $ref);
781 } else {
782 $sql .= " AND t.rowid = ".((int) $id);
783 }
784
785 $resql = $this->db->query($sql);
786 if ($resql) {
787 $numrows = $this->db->num_rows($resql);
788 if ($numrows) {
789 $obj = $this->db->fetch_object($resql);
790
791 $this->id = $obj->rowid;
792
793 $this->doc_date = $this->db->jdate($obj->doc_date);
794 $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
795 $this->doc_type = $obj->doc_type;
796 $this->doc_ref = $obj->doc_ref;
797 $this->fk_doc = $obj->fk_doc;
798 $this->fk_docdet = $obj->fk_docdet;
799 $this->thirdparty_code = $obj->thirdparty_code;
800 $this->subledger_account = $obj->subledger_account;
801 $this->subledger_label = $obj->subledger_label;
802 $this->numero_compte = $obj->numero_compte;
803 $this->label_compte = $obj->label_compte;
804 $this->label_operation = $obj->label_operation;
805 $this->debit = $obj->debit;
806 $this->credit = $obj->credit;
807 $this->montant = $obj->amount;
808 $this->amount = $obj->amount;
809 $this->sens = $obj->sens;
810 $this->fk_user_author = $obj->fk_user_author;
811 $this->import_key = $obj->import_key;
812 $this->code_journal = $obj->code_journal;
813 $this->journal_label = $obj->journal_label;
814 $this->piece_num = $obj->piece_num;
815 $this->date_creation = $this->db->jdate($obj->date_creation);
816 $this->date_export = $this->db->jdate($obj->date_export);
817 $this->date_validation = isset($obj->date_validation) ? $this->db->jdate($obj->date_validation) : '';
818 }
819 $this->db->free($resql);
820
821 if ($numrows) {
822 return 1;
823 } else {
824 return 0;
825 }
826 } else {
827 $this->errors[] = 'Error '.$this->db->lasterror();
828 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
829
830 return -1;
831 }
832 }
833
834
848 public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0, $countonly = 0)
849 {
850 global $conf;
851
852 dol_syslog(__METHOD__, LOG_DEBUG);
853
854 $this->lines = array();
855 $num = 0;
856
857 $sql = 'SELECT';
858 if ($countonly) {
859 $sql .= ' COUNT(t.rowid) as nb';
860 } else {
861 $sql .= ' t.rowid,';
862 $sql .= " t.doc_date,";
863 $sql .= " t.doc_type,";
864 $sql .= " t.doc_ref,";
865 $sql .= " t.fk_doc,";
866 $sql .= " t.fk_docdet,";
867 $sql .= " t.thirdparty_code,";
868 $sql .= " t.subledger_account,";
869 $sql .= " t.subledger_label,";
870 $sql .= " t.numero_compte,";
871 $sql .= " t.label_compte,";
872 $sql .= " t.label_operation,";
873 $sql .= " t.debit,";
874 $sql .= " t.credit,";
875 $sql .= " t.montant as amount,";
876 $sql .= " t.sens,";
877 $sql .= " t.multicurrency_amount,";
878 $sql .= " t.multicurrency_code,";
879 $sql .= " t.lettering_code,";
880 $sql .= " t.date_lettering,";
881 $sql .= " t.fk_user_author,";
882 $sql .= " t.import_key,";
883 $sql .= " t.code_journal,";
884 $sql .= " t.journal_label,";
885 $sql .= " t.piece_num,";
886 $sql .= " t.date_creation,";
887 $sql .= " t.date_export,";
888 $sql .= " t.date_validated as date_validation,";
889 $sql .= " t.date_lim_reglement,";
890 $sql .= " t.import_key";
891 }
892 // Manage filter
893 $sqlwhere = array();
894 if (count($filter) > 0) {
895 foreach ($filter as $key => $value) {
896 if ($key == 't.doc_date>=') {
897 $sqlwhere[] = "t.doc_date >= '".$this->db->idate($value)."'";
898 } elseif ($key == 't.doc_date<=') {
899 $sqlwhere[] = "t.doc_date <= '".$this->db->idate($value)."'";
900 } elseif ($key == 't.doc_date>') {
901 $sqlwhere[] = "t.doc_date > '".$this->db->idate($value)."'";
902 } elseif ($key == 't.doc_date<') {
903 $sqlwhere[] = "t.doc_date < '".$this->db->idate($value)."'";
904 } elseif ($key == 't.numero_compte>=') {
905 $sqlwhere[] = "t.numero_compte >= '".$this->db->escape($value)."'";
906 } elseif ($key == 't.numero_compte<=') {
907 $sqlwhere[] = "t.numero_compte <= '".$this->db->escape($value)."'";
908 } elseif ($key == 't.subledger_account>=') {
909 $sqlwhere[] = "t.subledger_account >= '".$this->db->escape($value)."'";
910 } elseif ($key == 't.subledger_account<=') {
911 $sqlwhere[] = "t.subledger_account <= '".$this->db->escape($value)."'";
912 } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
913 $sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
914 } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
915 $sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($this->db->escapeforlike($value)).'%\'';
916 } elseif ($key == 't.date_creation>=') {
917 $sqlwhere[] = 't.date_creation >= \''.$this->db->idate($value).'\'';
918 } elseif ($key == 't.date_creation<=') {
919 $sqlwhere[] = 't.date_creation <= \''.$this->db->idate($value).'\'';
920 } elseif ($key == 't.date_export>=') {
921 $sqlwhere[] = 't.date_export >= \''.$this->db->idate($value).'\'';
922 } elseif ($key == 't.date_export<=') {
923 $sqlwhere[] = 't.date_export <= \''.$this->db->idate($value).'\'';
924 } elseif ($key == 't.date_validated>=') {
925 $sqlwhere[] = 't.date_validated >= \''.$this->db->idate($value).'\'';
926 } elseif ($key == 't.date_validated<=') {
927 $sqlwhere[] = 't.date_validated <= \''.$this->db->idate($value).'\'';
928 } elseif ($key == 't.date_lim_reglement>=') {
929 $sqlwhere[] = 't.date_lim_reglement>=\''.$this->db->idate($value).'\'';
930 } elseif ($key == 't.date_lim_reglement<=') {
931 $sqlwhere[] = 't.date_lim_reglement<=\''.$this->db->idate($value).'\'';
932 } elseif ($key == 't.credit' || $key == 't.debit') {
933 $sqlwhere[] = natural_search($key, $value, 1, 1);
934 } elseif ($key == 't.reconciled_option') {
935 $sqlwhere[] = 't.lettering_code IS NULL';
936 } elseif ($key == 't.code_journal' && !empty($value)) {
937 if (is_array($value)) {
938 $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1);
939 } else {
940 $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
941 }
942 } elseif ($key == 't.search_accounting_code_in' && !empty($value)) {
943 $sqlwhere[] = 't.numero_compte IN ('.$this->db->sanitize($value, 1).')';
944 } else {
945 $sqlwhere[] = natural_search($key, $value, 0, 1);
946 }
947 }
948 }
949 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
950 $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
951 if (count($sqlwhere) > 0) {
952 $sql .= " AND ".implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
953 }
954 // Filter by ledger account or subledger account
955 if (!empty($option)) {
956 $sql .= " AND t.subledger_account IS NOT NULL";
957 $sql .= " AND t.subledger_account <> ''";
958 $sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : '');
959 $sortorder = 'ASC'.($sortfield ? ','.$sortfield : '');
960 } else {
961 $sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : '');
962 $sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
963 }
964
965 if (!$countonly) {
966 $sql .= $this->db->order($sortfield, $sortorder);
967 if (!empty($limit)) {
968 $sql .= $this->db->plimit($limit + 1, $offset);
969 }
970 }
971
972 $resql = $this->db->query($sql);
973 if ($resql) {
974 if ($countonly) {
975 $obj = $this->db->fetch_object($resql);
976 if ($obj) {
977 $num = $obj->nb;
978 }
979 } else {
980 $num = $this->db->num_rows($resql);
981
982 $i = 0;
983 while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
984 $line = new BookKeepingLine($this->db);
985
986 $line->id = $obj->rowid;
987
988 $line->doc_date = $this->db->jdate($obj->doc_date);
989 $line->doc_type = $obj->doc_type;
990 $line->doc_ref = $obj->doc_ref;
991 $line->fk_doc = $obj->fk_doc;
992 $line->fk_docdet = $obj->fk_docdet;
993 $line->thirdparty_code = $obj->thirdparty_code;
994 $line->subledger_account = $obj->subledger_account;
995 $line->subledger_label = $obj->subledger_label;
996 $line->numero_compte = $obj->numero_compte;
997 $line->label_compte = $obj->label_compte;
998 $line->label_operation = $obj->label_operation;
999 $line->debit = $obj->debit;
1000 $line->credit = $obj->credit;
1001 $line->montant = $obj->amount; // deprecated
1002 $line->amount = $obj->amount;
1003 $line->sens = $obj->sens;
1004 $line->multicurrency_amount = $obj->multicurrency_amount;
1005 $line->multicurrency_code = $obj->multicurrency_code;
1006 $line->lettering_code = $obj->lettering_code;
1007 $line->date_lettering = $obj->date_lettering;
1008 $line->fk_user_author = $obj->fk_user_author;
1009 $line->import_key = $obj->import_key;
1010 $line->code_journal = $obj->code_journal;
1011 $line->journal_label = $obj->journal_label;
1012 $line->piece_num = $obj->piece_num;
1013 $line->date_creation = $this->db->jdate($obj->date_creation);
1014 $line->date_export = $this->db->jdate($obj->date_export);
1015 $line->date_validation = $this->db->jdate($obj->date_validation);
1016 // Due date
1017 $line->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
1018 $line->import_key = $obj->import_key;
1019
1020 $this->lines[] = $line;
1021
1022 $i++;
1023 }
1024 }
1025 $this->db->free($resql);
1026
1027 return $num;
1028 } else {
1029 $this->errors[] = 'Error '.$this->db->lasterror();
1030 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1031
1032 return -1;
1033 }
1034 }
1035
1048 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND', $showAlreadyExportMovements = 1)
1049 {
1050 global $conf;
1051
1052 dol_syslog(__METHOD__, LOG_DEBUG);
1053
1054 $sql = 'SELECT';
1055 $sql .= ' t.rowid,';
1056 $sql .= " t.doc_date,";
1057 $sql .= " t.doc_type,";
1058 $sql .= " t.doc_ref,";
1059 $sql .= " t.fk_doc,";
1060 $sql .= " t.fk_docdet,";
1061 $sql .= " t.thirdparty_code,";
1062 $sql .= " t.subledger_account,";
1063 $sql .= " t.subledger_label,";
1064 $sql .= " t.numero_compte,";
1065 $sql .= " t.label_compte,";
1066 $sql .= " t.label_operation,";
1067 $sql .= " t.debit,";
1068 $sql .= " t.credit,";
1069 $sql .= " t.lettering_code,";
1070 $sql .= " t.date_lettering,";
1071 $sql .= " t.montant as amount,";
1072 $sql .= " t.sens,";
1073 $sql .= " t.fk_user_author,";
1074 $sql .= " t.import_key,";
1075 $sql .= " t.code_journal,";
1076 $sql .= " t.journal_label,";
1077 $sql .= " t.piece_num,";
1078 $sql .= " t.date_creation,";
1079 $sql .= " t.date_lim_reglement,";
1080 $sql .= " t.tms as date_modification,";
1081 $sql .= " t.date_export,";
1082 $sql .= " t.date_validated as date_validation";
1083 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1084
1085 $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
1086 if ($showAlreadyExportMovements == 0) {
1087 $sql .= " AND t.date_export IS NULL";
1088 }
1089
1090 // Manage filter
1091 if (is_array($filter)) { // deprecated, use $filter = USF syntax
1092 $sqlwhere = array();
1093 if (count($filter) > 0) {
1094 foreach ($filter as $key => $value) {
1095 if ($key == 't.doc_date') {
1096 $sqlwhere[] = $this->db->sanitize($key).' = \''.$this->db->idate($value).'\'';
1097 } elseif ($key == 't.doc_date>=') {
1098 $sqlwhere[] = "t.doc_date >= '".$this->db->idate($value)."'";
1099 } elseif ($key == 't.doc_date<=') {
1100 $sqlwhere[] = "t.doc_date <= '".$this->db->idate($value)."'";
1101 } elseif ($key == 't.doc_date>') {
1102 $sqlwhere[] = "t.doc_date > '".$this->db->idate($value)."'";
1103 } elseif ($key == 't.doc_date<') {
1104 $sqlwhere[] = "t.doc_date < '".$this->db->idate($value)."'";
1105 } elseif ($key == 't.numero_compte>=') {
1106 $sqlwhere[] = "t.numero_compte >= '".$this->db->escape($value)."'";
1107 } elseif ($key == 't.numero_compte<=') {
1108 $sqlwhere[] = "t.numero_compte <= '".$this->db->escape($value)."'";
1109 } elseif ($key == 't.subledger_account>=') {
1110 $sqlwhere[] = "t.subledger_account >= '".$this->db->escape($value)."'";
1111 } elseif ($key == 't.subledger_account<=') {
1112 $sqlwhere[] = "t.subledger_account <= '".$this->db->escape($value)."'";
1113 } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
1114 $sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
1115 } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
1116 $sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($value).'%\'';
1117 } elseif ($key == 't.date_creation>=') {
1118 $sqlwhere[] = 't.date_creation >= \''.$this->db->idate($value).'\'';
1119 } elseif ($key == 't.date_creation<=') {
1120 $sqlwhere[] = 't.date_creation <= \''.$this->db->idate($value).'\'';
1121 } elseif ($key == 't.tms>=') {
1122 $sqlwhere[] = 't.tms >= \''.$this->db->idate($value).'\'';
1123 } elseif ($key == 't.tms<=') {
1124 $sqlwhere[] = 't.tms <= \''.$this->db->idate($value).'\'';
1125 } elseif ($key == 't.date_export>=') {
1126 $sqlwhere[] = 't.date_export >= \''.$this->db->idate($value).'\'';
1127 } elseif ($key == 't.date_export<=') {
1128 $sqlwhere[] = 't.date_export <= \''.$this->db->idate($value).'\'';
1129 } elseif ($key == 't.date_validated>=') {
1130 $sqlwhere[] = 't.date_validated >= \''.$this->db->idate($value).'\'';
1131 } elseif ($key == 't.date_validated<=') {
1132 $sqlwhere[] = 't.date_validated <= \''.$this->db->idate($value).'\'';
1133 } elseif ($key == 't.credit' || $key == 't.debit') {
1134 $sqlwhere[] = natural_search($key, $value, 1, 1);
1135 } elseif ($key == 't.code_journal' && !empty($value)) {
1136 if (is_array($value)) {
1137 $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1);
1138 } else {
1139 $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
1140 }
1141 } else {
1142 $sqlwhere[] = natural_search($key, $value, 0, 1);
1143 }
1144 }
1145 }
1146 if (count($sqlwhere) > 0) {
1147 $sql .= ' AND '.implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
1148 }
1149
1150 $filter = '';
1151 }
1152
1153 // Manage filter
1154 $errormessage = '';
1155 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
1156 if ($errormessage) {
1157 $this->errors[] = $errormessage;
1158 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1159 return -1;
1160 }
1161
1162 if (!empty($sortfield)) {
1163 $sql .= $this->db->order($sortfield, $sortorder);
1164 }
1165 if (!empty($limit)) {
1166 $sql .= $this->db->plimit($limit + 1, $offset);
1167 }
1168 $this->lines = array();
1169
1170 $resql = $this->db->query($sql);
1171 if ($resql) {
1172 $num = $this->db->num_rows($resql);
1173
1174 $i = 0;
1175 while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
1176 $line = new BookKeepingLine($this->db);
1177
1178 $line->id = $obj->rowid;
1179
1180 $line->doc_date = $this->db->jdate($obj->doc_date);
1181 $line->doc_type = $obj->doc_type;
1182 $line->doc_ref = $obj->doc_ref;
1183 $line->fk_doc = $obj->fk_doc;
1184 $line->fk_docdet = $obj->fk_docdet;
1185 $line->thirdparty_code = $obj->thirdparty_code;
1186 $line->subledger_account = $obj->subledger_account;
1187 $line->subledger_label = $obj->subledger_label;
1188 $line->numero_compte = $obj->numero_compte;
1189 $line->label_compte = $obj->label_compte;
1190 $line->label_operation = $obj->label_operation;
1191 $line->debit = $obj->debit;
1192 $line->credit = $obj->credit;
1193 $line->montant = $obj->amount; // deprecated
1194 $line->amount = $obj->amount;
1195 $line->sens = $obj->sens;
1196 $line->lettering_code = $obj->lettering_code;
1197 $line->date_lettering = $obj->date_lettering;
1198 $line->fk_user_author = $obj->fk_user_author;
1199 $line->import_key = $obj->import_key;
1200 $line->code_journal = $obj->code_journal;
1201 $line->journal_label = $obj->journal_label;
1202 $line->piece_num = $obj->piece_num;
1203 $line->date_creation = $this->db->jdate($obj->date_creation);
1204 $line->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
1205 $line->date_modification = $this->db->jdate($obj->date_modification);
1206 $line->date_export = $this->db->jdate($obj->date_export);
1207 $line->date_validation = $this->db->jdate($obj->date_validation);
1208
1209 $this->lines[] = $line;
1210
1211 $i++;
1212 }
1213 $this->db->free($resql);
1214
1215 return $num;
1216 } else {
1217 $this->errors[] = 'Error '.$this->db->lasterror();
1218 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1219 return -1;
1220 }
1221 }
1222
1235 public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND', $option = 0)
1236 {
1237 global $conf;
1238
1239 $this->lines = array();
1240
1241 dol_syslog(__METHOD__, LOG_DEBUG);
1242
1243 $sql = 'SELECT';
1244 $sql .= " t.numero_compte,";
1245 if (!empty($option)) {
1246 $sql .= " t.subledger_account,";
1247 $sql .= " t.subledger_label,";
1248 }
1249 $sql .= " SUM(t.debit) as debit,";
1250 $sql .= " SUM(t.credit) as credit";
1251 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
1252 $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
1253
1254 // Manage filter
1255 if (is_array($filter)) {
1256 $sqlwhere = array();
1257 if (count($filter) > 0) {
1258 foreach ($filter as $key => $value) {
1259 if ($key == 't.doc_date') {
1260 $sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->idate($value)."'";
1261 } elseif ($key == 't.doc_date>=') {
1262 $sqlwhere[] = "t.doc_date >= '".$this->db->idate($value)."'";
1263 } elseif ($key == 't.doc_date<=') {
1264 $sqlwhere[] = "t.doc_date <= '".$this->db->idate($value)."'";
1265 } elseif ($key == 't.doc_date>') {
1266 $sqlwhere[] = "t.doc_date > '".$this->db->idate($value)."'";
1267 } elseif ($key == 't.doc_date<') {
1268 $sqlwhere[] = "t.doc_date < '".$this->db->idate($value)."'";
1269 } elseif ($key == 't.numero_compte>=') {
1270 $sqlwhere[] = "t.numero_compte >= '".$this->db->escape($value)."'";
1271 } elseif ($key == 't.numero_compte<=') {
1272 $sqlwhere[] = "t.numero_compte <= '".$this->db->escape($value)."'";
1273 } elseif ($key == 't.subledger_account>=') {
1274 $sqlwhere[] = "t.subledger_account >= '".$this->db->escape($value)."'";
1275 } elseif ($key == 't.subledger_account<=') {
1276 $sqlwhere[] = "t.subledger_account <= '".$this->db->escape($value)."'";
1277 } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
1278 $sqlwhere[] = $this->db->sanitize($key)." = ".((int) $value);
1279 } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
1280 $sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($value)."%'";
1281 } elseif ($key == 't.subledger_label') {
1282 $sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($value)."%'";
1283 } elseif ($key == 't.code_journal' && !empty($value)) {
1284 if (is_array($value)) {
1285 $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1);
1286 } else {
1287 $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
1288 }
1289 } elseif ($key == 't.reconciled_option') {
1290 $sqlwhere[] = 't.lettering_code IS NULL';
1291 } else {
1292 $sqlwhere[] = $this->db->sanitize($key)." LIKE '%".$this->db->escape($this->db->escapeforlike($value))."%'";
1293 }
1294 }
1295 }
1296 if (count($sqlwhere) > 0) {
1297 $sql .= " AND ".implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
1298 }
1299
1300 $filter = '';
1301 }
1302
1303 // Manage filter
1304 $errormessage = '';
1305 $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage);
1306 if ($errormessage) {
1307 $this->errors[] = $errormessage;
1308 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1309 return -1;
1310 }
1311
1312 if (!empty($option)) {
1313 $sql .= " AND t.subledger_account IS NOT NULL";
1314 $sql .= " AND t.subledger_account <> ''";
1315 $sql .= " GROUP BY t.numero_compte, t.subledger_account, t.subledger_label";
1316 $sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : '');
1317 $sortorder = 'ASC'.($sortfield ? ','.$sortfield : '');
1318 } else {
1319 $sql .= ' GROUP BY t.numero_compte';
1320 $sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : '');
1321 $sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
1322 }
1323
1324 if (!empty($sortfield)) {
1325 $sql .= $this->db->order($sortfield, $sortorder);
1326 }
1327 if (!empty($limit)) {
1328 $sql .= $this->db->plimit($limit + 1, $offset);
1329 }
1330
1331 //print $sql;
1332 $resql = $this->db->query($sql);
1333
1334 if ($resql) {
1335 $num = $this->db->num_rows($resql);
1336
1337 $i = 0;
1338 while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
1339 $line = new BookKeepingLine($this->db);
1340
1341 $line->numero_compte = $obj->numero_compte;
1342 //$line->label_compte = $obj->label_compte;
1343 if (!empty($option)) {
1344 $line->subledger_account = $obj->subledger_account;
1345 $line->subledger_label = $obj->subledger_label;
1346 }
1347 $line->debit = $obj->debit;
1348 $line->credit = $obj->credit;
1349
1350 $this->lines[] = $line;
1351
1352 $i++;
1353 }
1354 $this->db->free($resql);
1355
1356 return $num;
1357 } else {
1358 $this->errors[] = 'Error '.$this->db->lasterror();
1359 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1360
1361 return -1;
1362 }
1363 }
1364
1373 public function update(User $user, $notrigger = 0, $mode = '')
1374 {
1375 global $langs;
1376 $error = 0;
1377
1378 dol_syslog(__METHOD__, LOG_DEBUG);
1379
1380 // Clean parameters
1381 if (isset($this->doc_type)) {
1382 $this->doc_type = trim($this->doc_type);
1383 }
1384 if (isset($this->doc_ref)) {
1385 $this->doc_ref = trim($this->doc_ref);
1386 }
1387 if (isset($this->fk_doc)) {
1388 $this->fk_doc = (int) $this->fk_doc;
1389 }
1390 if (isset($this->fk_docdet)) {
1391 $this->fk_docdet = (int) $this->fk_docdet;
1392 }
1393 if (isset($this->thirdparty_code)) {
1394 $this->thirdparty_code = trim($this->thirdparty_code);
1395 }
1396 if (isset($this->subledger_account)) {
1397 $this->subledger_account = trim($this->subledger_account);
1398 }
1399 if (isset($this->subledger_label)) {
1400 $this->subledger_label = trim($this->subledger_label);
1401 }
1402 if (isset($this->numero_compte)) {
1403 $this->numero_compte = trim($this->numero_compte);
1404 }
1405 if (isset($this->label_compte)) {
1406 $this->label_compte = trim($this->label_compte);
1407 }
1408 if (isset($this->label_operation)) {
1409 $this->label_operation = trim($this->label_operation);
1410 }
1411 if (isset($this->sens)) {
1412 $this->sens = trim($this->sens);
1413 }
1414 if (isset($this->import_key)) {
1415 $this->import_key = trim($this->import_key);
1416 }
1417 if (isset($this->code_journal)) {
1418 $this->code_journal = trim($this->code_journal);
1419 }
1420 if (isset($this->journal_label)) {
1421 $this->journal_label = trim($this->journal_label);
1422 }
1423 if (isset($this->piece_num)) {
1424 $this->piece_num = (int) $this->piece_num;
1425 }
1426
1427 $result = $this->canModifyBookkeeping($this->id, $mode);
1428 if ($result < 0) {
1429 return -1;
1430 } elseif ($result == 0) {
1431 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
1432 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod');
1433 } else {
1434 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod');
1435 }
1436 return -1;
1437 }
1438
1439 $this->debit = (float) price2num($this->debit, 'MT');
1440 $this->credit = (float) price2num($this->credit, 'MT');
1441 $this->montant = (float) price2num($this->montant, 'MT');
1442
1443 // Check parameters
1444 // Put here code to add a control on parameters values
1445
1446 // Update request
1447 $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.$mode.' SET';
1448 $sql .= ' doc_date = '.(!isset($this->doc_date) || dol_strlen($this->doc_date) != 0 ? "'".$this->db->idate($this->doc_date)."'" : 'null').',';
1449 $sql .= ' doc_type = '.(isset($this->doc_type) ? "'".$this->db->escape($this->doc_type)."'" : "null").',';
1450 $sql .= ' doc_ref = '.(isset($this->doc_ref) ? "'".$this->db->escape($this->doc_ref)."'" : "null").',';
1451 $sql .= ' fk_doc = '.(isset($this->fk_doc) ? $this->fk_doc : "null").',';
1452 $sql .= ' fk_docdet = '.(isset($this->fk_docdet) ? $this->fk_docdet : "null").',';
1453 $sql .= ' thirdparty_code = '.(isset($this->thirdparty_code) ? "'".$this->db->escape($this->thirdparty_code)."'" : "null").',';
1454 $sql .= ' subledger_account = '.(isset($this->subledger_account) ? "'".$this->db->escape($this->subledger_account)."'" : "null").',';
1455 $sql .= ' subledger_label = '.(isset($this->subledger_label) ? "'".$this->db->escape($this->subledger_label)."'" : "null").',';
1456 $sql .= ' numero_compte = '.(isset($this->numero_compte) ? "'".$this->db->escape($this->numero_compte)."'" : "null").',';
1457 $sql .= ' label_compte = '.(isset($this->label_compte) ? "'".$this->db->escape($this->label_compte)."'" : "null").',';
1458 $sql .= ' label_operation = '.(isset($this->label_operation) ? "'".$this->db->escape($this->label_operation)."'" : "null").',';
1459 $sql .= ' debit = '.(isset($this->debit) ? $this->debit : "null").',';
1460 $sql .= ' credit = '.(isset($this->credit) ? $this->credit : "null").',';
1461 $sql .= ' montant = '.(isset($this->montant) ? $this->montant : "null").',';
1462 $sql .= ' sens = '.(isset($this->sens) ? "'".$this->db->escape($this->sens)."'" : "null").',';
1463 $sql .= ' fk_user_author = '.(isset($this->fk_user_author) ? $this->fk_user_author : "null").',';
1464 $sql .= ' import_key = '.(isset($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null").',';
1465 $sql .= ' code_journal = '.(isset($this->code_journal) ? "'".$this->db->escape($this->code_journal)."'" : "null").',';
1466 $sql .= ' journal_label = '.(isset($this->journal_label) ? "'".$this->db->escape($this->journal_label)."'" : "null").',';
1467 $sql .= ' piece_num = '.(isset($this->piece_num) ? $this->piece_num : "null");
1468 $sql .= ' WHERE rowid='.((int) $this->id);
1469
1470 $this->db->begin();
1471
1472 $resql = $this->db->query($sql);
1473 if (!$resql) {
1474 $error++;
1475 $this->errors[] = 'Error '.$this->db->lasterror();
1476 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1477 }
1478
1479 // Uncomment this and change MYOBJECT to your own tag if you
1480 // want this action calls a trigger.
1481 //if (! $error && ! $notrigger) {
1482
1483 // // Call triggers
1484 // $result=$this->call_trigger('MYOBJECT_MODIFY',$user);
1485 // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
1486 // // End call triggers
1487 //}
1488
1489 // Commit or rollback
1490 if ($error) {
1491 $this->db->rollback();
1492
1493 return -1 * $error;
1494 } else {
1495 $this->db->commit();
1496
1497 return 1;
1498 }
1499 }
1500
1510 public function updateByMvt($piece_num = '', $field = '', $value = '', $mode = '')
1511 {
1512 $error = 0;
1513
1514 $sql_filter = $this->getCanModifyBookkeepingSQL();
1515 if (!isset($sql_filter)) {
1516 return -1;
1517 }
1518
1519 $this->db->begin();
1520
1521 $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element.$mode;
1522 $sql .= " SET ".$this->db->sanitize($field)." = ".(is_numeric($value) ? ((float) $value) : "'".$this->db->escape($value)."'");
1523 $sql .= " WHERE piece_num = ".((int) $piece_num);
1524 $sql .= $sql_filter;
1525
1526 $resql = $this->db->query($sql);
1527
1528 if (!$resql) {
1529 $error++;
1530 $this->errors[] = 'Error '.$this->db->lasterror();
1531 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1532 }
1533 if ($error) {
1534 $this->db->rollback();
1535
1536 return -1 * $error;
1537 } else {
1538 $this->db->commit();
1539
1540 return 1;
1541 }
1542 }
1543
1552 public function delete(User $user, $notrigger = 0, $mode = '')
1553 {
1554 global $langs;
1555
1556 dol_syslog(__METHOD__, LOG_DEBUG);
1557
1558 $result = $this->canModifyBookkeeping($this->id, $mode);
1559 if ($result < 0) {
1560 return -1;
1561 } elseif ($result == 0) {
1562 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
1563 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod');
1564 } else {
1565 $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod');
1566 }
1567 return -1;
1568 }
1569
1570 $error = 0;
1571
1572 $this->db->begin();
1573
1574 // Uncomment this and change MYOBJECT to your own tag if you
1575 // want this action calls a trigger.
1576 //if (! $error && ! $notrigger) {
1577
1578 // // Call triggers
1579 // $result=$this->call_trigger('MYOBJECT_DELETE',$user);
1580 // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
1581 // // End call triggers
1582 //}
1583
1584 if (!$error) {
1585 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.$mode;
1586 $sql .= ' WHERE rowid='.((int) $this->id);
1587
1588 $resql = $this->db->query($sql);
1589 if (!$resql) {
1590 $error++;
1591 $this->errors[] = 'Error '.$this->db->lasterror();
1592 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1593 }
1594 }
1595
1596 // Commit or rollback
1597 if ($error) {
1598 $this->db->rollback();
1599
1600 return -1 * $error;
1601 } else {
1602 $this->db->commit();
1603
1604 return 1;
1605 }
1606 }
1607
1615 public function deleteByImportkey($importkey, $mode = '')
1616 {
1617 $this->db->begin();
1618
1619 $sql_filter = $this->getCanModifyBookkeepingSQL();
1620 if (!isset($sql_filter)) {
1621 return -1;
1622 }
1623
1624 // first check if line not yet in bookkeeping
1625 $sql = "DELETE";
1626 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1627 $sql .= " WHERE import_key = '".$this->db->escape($importkey)."'";
1628 $sql .= $sql_filter;
1629
1630 $resql = $this->db->query($sql);
1631
1632 if (!$resql) {
1633 $this->errors[] = "Error ".$this->db->lasterror();
1634 dol_syslog(get_class($this)."::delete Error ".$this->db->lasterror(), LOG_ERR);
1635 $this->db->rollback();
1636 return -1;
1637 }
1638
1639 $this->db->commit();
1640 return 1;
1641 }
1642
1652 public function deleteByYearAndJournal($delyear = 0, $journal = '', $mode = '', $delmonth = 0)
1653 {
1654 global $conf, $langs;
1655
1656 if (empty($delyear) && empty($journal)) {
1657 $this->error = 'ErrorOneFieldRequired';
1658 return -1;
1659 }
1660 if (!empty($delmonth) && empty($delyear)) {
1661 $this->error = 'YearRequiredIfMonthDefined';
1662 return -2;
1663 }
1664
1665 $sql_filter = $this->getCanModifyBookkeepingSQL();
1666 if (!isset($sql_filter)) {
1667 return -1;
1668 }
1669
1670 $this->db->begin();
1671
1672 // Delete record in bookkeeping
1673 $sql = "DELETE";
1674 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1675 $sql .= " WHERE 1 = 1";
1676 $sql .= dolSqlDateFilter('doc_date', 0, $delmonth, $delyear);
1677 if (!empty($journal)) {
1678 $sql .= " AND code_journal = '".$this->db->escape($journal)."'";
1679 }
1680 $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
1681 // Exclusion of validated entries at the time of deletion
1682 $sql .= " AND date_validated IS NULL";
1683 $sql .= $sql_filter;
1684
1685 // TODO: In a future we must forbid deletion if record is inside a closed fiscal period.
1686
1687 $resql = $this->db->query($sql);
1688
1689 if (!$resql) {
1690 $this->errors[] = "Error ".$this->db->lasterror();
1691 foreach ($this->errors as $errmsg) {
1692 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1693 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1694 }
1695 $this->db->rollback();
1696 return -1;
1697 }
1698
1699 $this->db->commit();
1700 return 1;
1701 }
1702
1710 public function deleteMvtNum($piecenum, $mode = '')
1711 {
1712 global $conf;
1713
1714 $sql_filter = $this->getCanModifyBookkeepingSQL();
1715 if (!isset($sql_filter)) {
1716 return -1;
1717 }
1718
1719 $this->db->begin();
1720
1721 // first check if line not yet in bookkeeping
1722 $sql = "DELETE";
1723 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1724 $sql .= " WHERE piece_num = ".(int) $piecenum;
1725 $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion
1726 $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
1727 $sql .= $sql_filter;
1728
1729 $resql = $this->db->query($sql);
1730
1731 if (!$resql) {
1732 $this->errors[] = "Error ".$this->db->lasterror();
1733 foreach ($this->errors as $errmsg) {
1734 dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
1735 $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
1736 }
1737 $this->db->rollback();
1738 return -1;
1739 }
1740
1741 $this->db->commit();
1742 return 1;
1743 }
1744
1752 public function createFromClone(User $user, $fromid)
1753 {
1754 dol_syslog(__METHOD__, LOG_DEBUG);
1755
1756 $error = 0;
1757 $object = new BookKeeping($this->db);
1758
1759 $this->db->begin();
1760
1761 // Load source object
1762 $object->fetch($fromid);
1763 // Reset object
1764 $object->id = 0;
1765
1766 // Clear fields
1767 // ...
1768
1769 // Create clone
1770 $object->context['createfromclone'] = 'createfromclone';
1771 $result = $object->create($user);
1772
1773 // Other options
1774 if ($result < 0) {
1775 $error++;
1776 $this->errors = $object->errors;
1777 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
1778 }
1779
1780 unset($object->context['createfromclone']);
1781
1782 // End
1783 if (!$error) {
1784 $this->db->commit();
1785
1786 return $object->id;
1787 } else {
1788 $this->db->rollback();
1789
1790 return -1;
1791 }
1792 }
1793
1800 public function initAsSpecimen()
1801 {
1802 global $user;
1803
1804 $now = dol_now();
1805
1806 $this->id = 0;
1807 $this->doc_date = $now;
1808 $this->doc_type = '';
1809 $this->doc_ref = '';
1810 $this->fk_doc = 0;
1811 $this->fk_docdet = 0;
1812 $this->thirdparty_code = 'CU001';
1813 $this->subledger_account = '41100001';
1814 $this->subledger_label = 'My customer company';
1815 $this->numero_compte = '411';
1816 $this->label_compte = 'Customer';
1817 $this->label_operation = 'Sales of pea';
1818 $this->debit = 99.9;
1819 $this->credit = 0.0;
1820 $this->amount = 0.0;
1821 $this->sens = 'D';
1822 $this->fk_user_author = $user->id;
1823 $this->import_key = '20201027';
1824 $this->code_journal = 'VT';
1825 $this->journal_label = 'Journal de vente';
1826 $this->piece_num = 1234;
1827 $this->date_creation = $now;
1828
1829 return 1;
1830 }
1831
1839 public function fetchPerMvt($piecenum, $mode = '')
1840 {
1841 global $conf;
1842
1843 $sql = "SELECT piece_num, doc_date, code_journal, journal_label, doc_ref, doc_type,";
1844 $sql .= " date_creation, tms as date_modification, date_validated as date_validation, date_lim_reglement, import_key";
1845 // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
1846 if ($mode != "_tmp") {
1847 $sql .= ", date_export";
1848 }
1849 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1850 $sql .= " WHERE piece_num = ".((int) $piecenum);
1851 $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
1852
1853 dol_syslog(__METHOD__, LOG_DEBUG);
1854 $result = $this->db->query($sql);
1855 if ($result) {
1856 $obj = $this->db->fetch_object($result);
1857
1858 $this->piece_num = $obj->piece_num;
1859 $this->code_journal = $obj->code_journal;
1860 $this->journal_label = $obj->journal_label;
1861 $this->doc_date = $this->db->jdate($obj->doc_date);
1862 $this->doc_ref = $obj->doc_ref;
1863 $this->doc_type = $obj->doc_type;
1864 $this->date_creation = $this->db->jdate($obj->date_creation);
1865 $this->date_modification = $this->db->jdate($obj->date_modification);
1866 if ($mode != "_tmp") {
1867 $this->date_export = $this->db->jdate($obj->date_export);
1868 }
1869 $this->date_validation = $this->db->jdate($obj->date_validation);
1870 $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
1871 $this->import_key = $obj->import_key;
1872 } else {
1873 $this->error = "Error ".$this->db->lasterror();
1874 dol_syslog(__METHOD__.$this->error, LOG_ERR);
1875 return -1;
1876 }
1877
1878 return 1;
1879 }
1880
1887 public function getNextNumMvt($mode = '')
1888 {
1889 global $conf;
1890
1891 $sql = "SELECT MAX(piece_num)+1 as max FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1892 $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
1893
1894 dol_syslog(get_class($this)."::getNextNumMvt", LOG_DEBUG);
1895
1896 $result = $this->db->query($sql);
1897
1898 if ($result) {
1899 $obj = $this->db->fetch_object($result);
1900 if ($obj) {
1901 $result = $obj->max;
1902 }
1903 if (empty($result)) {
1904 $result = 1;
1905 }
1906 return $result;
1907 } else {
1908 $this->error = "Error ".$this->db->lasterror();
1909 dol_syslog(get_class($this)."::getNextNumMvt ".$this->error, LOG_ERR);
1910 return -1;
1911 }
1912 }
1913
1921 public function fetchAllPerMvt($piecenum, $mode = '')
1922 {
1923 global $conf;
1924
1925 $sql = "SELECT rowid, doc_date, doc_type,";
1926 $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,";
1927 $sql .= " numero_compte, label_compte, label_operation, debit, credit,";
1928 $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, journal_label, piece_num,";
1929 $sql .= " date_creation, tms as date_modification, date_validated as date_validation";
1930 // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
1931 if ($mode != "_tmp") {
1932 $sql .= ", date_export";
1933 }
1934 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
1935 $sql .= " WHERE piece_num = ".((int) $piecenum);
1936 $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
1937
1938 dol_syslog(__METHOD__, LOG_DEBUG);
1939 $result = $this->db->query($sql);
1940 if ($result) {
1941 while ($obj = $this->db->fetch_object($result)) {
1942 $line = new BookKeepingLine($this->db);
1943
1944 $line->id = $obj->rowid;
1945
1946 $line->doc_date = $this->db->jdate($obj->doc_date);
1947 $line->doc_type = $obj->doc_type;
1948 $line->doc_ref = $obj->doc_ref;
1949 $line->fk_doc = $obj->fk_doc;
1950 $line->fk_docdet = $obj->fk_docdet;
1951 $line->thirdparty_code = $obj->thirdparty_code;
1952 $line->subledger_account = $obj->subledger_account;
1953 $line->subledger_label = $obj->subledger_label;
1954 $line->numero_compte = $obj->numero_compte;
1955 $line->label_compte = $obj->label_compte;
1956 $line->label_operation = $obj->label_operation;
1957 $line->debit = $obj->debit;
1958 $line->credit = $obj->credit;
1959 $line->montant = $obj->amount;
1960 $line->amount = $obj->amount;
1961 $line->sens = $obj->sens;
1962 $line->code_journal = $obj->code_journal;
1963 $line->journal_label = $obj->journal_label;
1964 $line->piece_num = $obj->piece_num;
1965 $line->date_creation = $obj->date_creation;
1966 $line->date_modification = $obj->date_modification;
1967 if ($mode != "_tmp") {
1968 $line->date_export = $obj->date_export;
1969 }
1970 $line->date_validation = $obj->date_validation;
1971
1972 $this->linesmvt[] = $line;
1973 }
1974 } else {
1975 $this->error = "Error ".$this->db->lasterror();
1976 dol_syslog(__METHOD__.$this->error, LOG_ERR);
1977 return -1;
1978 }
1979
1980 return 1;
1981 }
1982
1983 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
1990 public function export_bookkeeping($model = 'ebp')
1991 {
1992 // phpcs:enable
1993 global $conf;
1994
1995 $sql = "SELECT rowid, doc_date, doc_type,";
1996 $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,";
1997 $sql .= " numero_compte, label_compte, label_operation, debit, credit,";
1998 $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, piece_num,";
1999 $sql .= " date_validated as date_validation";
2000 $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
2001 $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
2002
2003 dol_syslog(get_class($this)."::export_bookkeeping", LOG_DEBUG);
2004
2005 $resql = $this->db->query($sql);
2006
2007 if ($resql) {
2008 $this->linesexport = array();
2009
2010 $num = $this->db->num_rows($resql);
2011 while ($obj = $this->db->fetch_object($resql)) {
2012 $line = new BookKeepingLine($this->db);
2013
2014 $line->id = $obj->rowid;
2015
2016 $line->doc_date = $this->db->jdate($obj->doc_date);
2017 $line->doc_type = $obj->doc_type;
2018 $line->doc_ref = $obj->doc_ref;
2019 $line->fk_doc = $obj->fk_doc;
2020 $line->fk_docdet = $obj->fk_docdet;
2021 $line->thirdparty_code = $obj->thirdparty_code;
2022 $line->subledger_account = $obj->subledger_account;
2023 $line->subledger_label = $obj->subledger_label;
2024 $line->numero_compte = $obj->numero_compte;
2025 $line->label_compte = $obj->label_compte;
2026 $line->label_operation = $obj->label_operation;
2027 $line->debit = $obj->debit;
2028 $line->credit = $obj->credit;
2029 $line->montant = $obj->amount;
2030 $line->amount = $obj->amount;
2031 $line->sens = $obj->sens;
2032 $line->code_journal = $obj->code_journal;
2033 $line->piece_num = $obj->piece_num;
2034 $line->date_validation = $obj->date_validation;
2035
2036 $this->linesexport[] = $line;
2037 }
2038 $this->db->free($resql);
2039
2040 return $num;
2041 } else {
2042 $this->error = "Error ".$this->db->lasterror();
2043 dol_syslog(get_class($this)."::export_bookkeeping ".$this->error, LOG_ERR);
2044 return -1;
2045 }
2046 }
2047
2055 public function transformTransaction($direction = 0, $piece_num = '')
2056 {
2057 global $conf;
2058
2059 $error = 0;
2060
2061 $sql_filter = $this->getCanModifyBookkeepingSQL();
2062
2063 if (!isset($sql_filter)) {
2064 return -1;
2065 }
2066
2067 $this->db->begin();
2068
2069 if ($direction == 0) {
2070 $next_piecenum = $this->getNextNumMvt();
2071 $now = dol_now();
2072
2073 if ($next_piecenum < 0) {
2074 $error++;
2075 }
2076
2077 if (!$error) {
2078 // Delete if there is an empty line
2079 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity)." AND numero_compte IS NULL AND debit = 0 AND credit = 0";
2080 $resql = $this->db->query($sql);
2081 if (!$resql) {
2082 $error++;
2083 $this->errors[] = 'Error '.$this->db->lasterror();
2084 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2085 }
2086 }
2087
2088 if (!$error) {
2089 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,';
2090 $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
2091 $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
2092 $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)';
2093 $sql .= ' SELECT doc_date, doc_type,';
2094 $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
2095 $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
2096 $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'";
2097 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND numero_compte IS NOT NULL AND entity = ' .((int) $conf->entity);
2098 $sql .= $sql_filter;
2099 $resql = $this->db->query($sql);
2100 if (!$resql) {
2101 $error++;
2102 $this->errors[] = 'Error '.$this->db->lasterror();
2103 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2104 }
2105 }
2106
2107 if (!$error) {
2108 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
2109 $resql = $this->db->query($sql);
2110 if (!$resql) {
2111 $error++;
2112 $this->errors[] = 'Error '.$this->db->lasterror();
2113 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2114 }
2115 }
2116 } elseif ($direction == 1) {
2117 if (!$error) {
2118 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
2119 $resql = $this->db->query($sql);
2120 if (!$resql) {
2121 $error++;
2122 $this->errors[] = 'Error '.$this->db->lasterror();
2123 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2124 }
2125 }
2126
2127 if (!$error) {
2128 $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,';
2129 $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
2130 $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
2131 $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)';
2132 $sql .= ' SELECT doc_date, doc_type,';
2133 $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
2134 $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
2135 $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num';
2136 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
2137 $sql .= $sql_filter;
2138 $resql = $this->db->query($sql);
2139 if (!$resql) {
2140 $error++;
2141 $this->errors[] = 'Error '.$this->db->lasterror();
2142 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2143 }
2144 }
2145
2146 if (!$error) {
2147 $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
2148 $sql .= $sql_filter;
2149 $resql = $this->db->query($sql);
2150 if (!$resql) {
2151 $error++;
2152 $this->errors[] = 'Error '.$this->db->lasterror();
2153 dol_syslog(__METHOD__.' '.implode(',', $this->errors), LOG_ERR);
2154 }
2155 }
2156 }
2157 if (!$error) {
2158 $this->db->commit();
2159 return 1;
2160 } else {
2161 $this->db->rollback();
2162 return -1;
2163 }
2164 /*
2165 $sql = "DELETE FROM ";
2166 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab";
2167 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte";
2168 $sql .= " AND aa.active = 1";
2169 $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
2170 $sql .= " AND asy.rowid = " . ((int) $pcgver);
2171 $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")";
2172 $sql .= " ORDER BY account_number ASC";
2173 */
2174 }
2175
2176 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2189 public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '')
2190 {
2191 // phpcs:enable
2192 global $conf;
2193
2194 require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
2195
2196 $pcgver = getDolGlobalInt('CHARTOFACCOUNTS');
2197
2198 $sql = "SELECT DISTINCT ab.numero_compte as account_number, aa.label as label, aa.rowid as rowid, aa.fk_pcg_version";
2199 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab";
2200 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.account_number = ab.numero_compte";
2201 $sql .= " AND aa.active = 1";
2202 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
2203 $sql .= " AND asy.rowid = ".((int) $pcgver);
2204 $sql .= " AND ab.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
2205 $sql .= " ORDER BY account_number ASC";
2206
2207 dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
2208 $resql = $this->db->query($sql);
2209
2210 if (!$resql) {
2211 $this->error = "Error ".$this->db->lasterror();
2212 dol_syslog(get_class($this)."::select_account ".$this->error, LOG_ERR);
2213 return "-1";
2214 }
2215
2216 $out = ajax_combobox($htmlname, $event);
2217
2218 $options = array();
2219 $selected = null;
2220
2221 while ($obj = $this->db->fetch_object($resql)) {
2222 $label = length_accountg($obj->account_number).' - '.$obj->label;
2223
2224 $select_value_in = $obj->rowid;
2225 $select_value_out = $obj->rowid;
2226
2227 if ($select_in == 1) {
2228 $select_value_in = $obj->account_number;
2229 }
2230 if ($select_out == 1) {
2231 $select_value_out = $obj->account_number;
2232 }
2233
2234 // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
2235 // Because same account_number can be share between different accounting_system and do have the same meaning
2236 if (($selectid != '') && $selectid == $select_value_in) {
2237 $selected = $select_value_out;
2238 }
2239
2240 $options[$select_value_out] = $label;
2241 }
2242
2243 $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', 'maxwidth300');
2244 $this->db->free($resql);
2245 return $out;
2246 }
2247
2255 public function getRootAccount($account = null)
2256 {
2257 global $conf;
2258 $pcgver = getDolGlobalInt('CHARTOFACCOUNTS');
2259
2260 $sql = "SELECT root.rowid, root.account_number, root.label as label,";
2261 $sql .= " parent.rowid as parent_rowid, parent.account_number as parent_account_number, parent.label as parent_label";
2262 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa";
2263 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
2264 $sql .= " AND asy.rowid = ".((int) $pcgver);
2265 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as parent ON aa.account_parent = parent.rowid AND parent.active = 1";
2266 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as root ON parent.account_parent = root.rowid AND root.active = 1";
2267 $sql .= " WHERE aa.account_number = '".$this->db->escape($account)."'";
2268 $sql .= " AND aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
2269
2270 dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
2271 $resql = $this->db->query($sql);
2272 if ($resql) {
2273 $obj = '';
2274 if ($this->db->num_rows($resql)) {
2275 $obj = $this->db->fetch_object($resql);
2276 }
2277
2278 $result = array('id' => $obj->rowid, 'account_number' => $obj->account_number, 'label' => $obj->label);
2279 return $result;
2280 } else {
2281 $this->error = "Error ".$this->db->lasterror();
2282 dol_syslog(__METHOD__." ".$this->error, LOG_ERR);
2283
2284 return -1;
2285 }
2286 }
2287
2288 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
2295 public function get_compte_desc($account = null)
2296 {
2297 // phpcs:enable
2298 global $conf;
2299
2300 $pcgver = getDolGlobalInt('CHARTOFACCOUNTS');
2301 $sql = "SELECT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version, cat.label as category";
2302 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa ";
2303 $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
2304 $sql .= " AND aa.account_number = '".$this->db->escape($account)."'";
2305 $sql .= " AND asy.rowid = ".((int) $pcgver);
2306 $sql .= " AND aa.active = 1";
2307 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid";
2308 $sql .= " WHERE aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
2309
2310 dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
2311 $resql = $this->db->query($sql);
2312 if ($resql) {
2313 $obj = '';
2314 if ($this->db->num_rows($resql)) {
2315 $obj = $this->db->fetch_object($resql);
2316 }
2317 if (empty($obj->category)) {
2318 return $obj->label;
2319 } else {
2320 return $obj->label.' ('.$obj->category.')';
2321 }
2322 } else {
2323 $this->error = "Error ".$this->db->lasterror();
2324 dol_syslog(__METHOD__." ".$this->error, LOG_ERR);
2325 return "-1";
2326 }
2327 }
2328
2336 public function getCanModifyBookkeepingSQL($alias = '', $force = false)
2337 {
2338 global $conf;
2339
2340 $alias = trim($alias);
2341 $alias = !empty($alias) && strpos($alias, '.') < 0 ? $alias . "." : $alias;
2342
2343 if (!isset(self::$can_modify_bookkeeping_sql_cached[$alias]) || $force) {
2344 $result = $this->loadFiscalPeriods($force, 'active');
2345 if ($result < 0) {
2346 return null;
2347 }
2348
2349 $sql_list = array();
2350 if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) {
2351 foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
2352 $sql_list[] = "('" . $this->db->idate($fiscal_period['date_start']) . "' <= ".$this->db->sanitize($alias)."doc_date AND ".$this->db->sanitize($alias)."doc_date <= '" . $this->db->idate($fiscal_period['date_end']) . "')";
2353 }
2354 }
2355 $sqlsanitized = implode(' OR ', $sql_list);
2356 self::$can_modify_bookkeeping_sql_cached[$alias] = !empty($sql_list) ? " AND (".$sqlsanitized.")" : "";
2357 }
2358
2359 return self::$can_modify_bookkeeping_sql_cached[$alias];
2360 }
2361
2369 public function canModifyBookkeeping($id, $mode = '')
2370 {
2371 global $conf;
2372
2373 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
2374 $result = $this->loadFiscalPeriods(false, 'closed');
2375
2376 if ($result < 0) {
2377 return -1;
2378 }
2379
2380 $bookkeeping = new BookKeeping($this->db);
2381 $result = $bookkeeping->fetch($id, null, $mode);
2382 if ($result <= 0) {
2383 return $result;
2384 }
2385
2386 if (!empty($conf->cache['closed_fiscal_period_cached']) && is_array($conf->cache['closed_fiscal_period_cached'])) {
2387 foreach ($conf->cache['closed_fiscal_period_cached'] as $fiscal_period) {
2388 if ($fiscal_period['date_start'] <= $bookkeeping->doc_date && $bookkeeping->doc_date <= $fiscal_period['date_end']) {
2389 return 0;
2390 }
2391 }
2392 }
2393
2394 return 1;
2395 } else {
2396 $result = $this->loadFiscalPeriods(false, 'active');
2397 if ($result < 0) {
2398 return -1;
2399 }
2400
2401 $bookkeeping = new BookKeeping($this->db);
2402 $result = $bookkeeping->fetch($id, null, $mode);
2403
2404 if ($result <= 0) {
2405 return $result;
2406 }
2407 if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) {
2408 foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
2409 if (!empty($fiscal_period['date_start']) && $fiscal_period['date_start'] <= $bookkeeping->doc_date && (empty($fiscal_period['date_end']) || $bookkeeping->doc_date <= $fiscal_period['date_end'])) {
2410 return 1;
2411 }
2412 }
2413 }
2414
2415 return 0;
2416 }
2417 }
2418
2425 public function validBookkeepingDate($date)
2426 {
2427 global $conf;
2428
2429 if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') {
2430 $result = $this->loadFiscalPeriods(false, 'closed');
2431
2432 if ($result < 0) {
2433 return -1;
2434 }
2435
2436 if (!empty($conf->cache['closed_fiscal_period_cached']) && is_array($conf->cache['closed_fiscal_period_cached'])) {
2437 foreach ($conf->cache['closed_fiscal_period_cached'] as $fiscal_period) {
2438 if ($fiscal_period['date_start'] <= $date && $date <= $fiscal_period['date_end']) {
2439 return 0;
2440 }
2441 }
2442 }
2443
2444 return 1;
2445 } else {
2446 $result = $this->loadFiscalPeriods(false, 'active');
2447 if ($result < 0) {
2448 return -1;
2449 }
2450
2451 if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) {
2452 foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) {
2453 if (!empty($fiscal_period['date_start']) && $fiscal_period['date_start'] <= $date && (empty($fiscal_period['date_end']) || $date <= $fiscal_period['date_end'])) {
2454 return 1;
2455 }
2456 }
2457 }
2458
2459 return 0;
2460 }
2461 }
2462
2470 public function loadFiscalPeriods($force = false, $mode = 'active')
2471 {
2472 global $conf;
2473
2474 if ($mode == 'active') {
2475 if (!isset($conf->cache['active_fiscal_period_cached']) || $force) {
2476 $sql = "SELECT date_start, date_end";
2477 $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear";
2478 $sql .= " WHERE entity = " . ((int) $conf->entity);
2479 $sql .= " AND statut = 0";
2480
2481 $resql = $this->db->query($sql);
2482 if (!$resql) {
2483 $this->errors[] = $this->db->lasterror();
2484 return -1;
2485 }
2486
2487 $list = array();
2488 while ($obj = $this->db->fetch_object($resql)) {
2489 $list[] = array(
2490 'date_start' => $this->db->jdate($obj->date_start),
2491 'date_end' => $this->db->jdate($obj->date_end),
2492 );
2493 }
2494 $conf->cache['active_fiscal_period_cached'] = $list;
2495 }
2496 }
2497 if ($mode == 'closed') {
2498 if (!isset($conf->cache['closed_fiscal_period_cached']) || $force) {
2499 $sql = "SELECT date_start, date_end";
2500 $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear";
2501 $sql .= " WHERE entity = " . ((int) $conf->entity);
2502 $sql .= " AND statut = 1";
2503
2504 $resql = $this->db->query($sql);
2505 if (!$resql) {
2506 $this->errors[] = $this->db->lasterror();
2507 return -1;
2508 }
2509
2510 $list = array();
2511 while ($obj = $this->db->fetch_object($resql)) {
2512 $list[] = array(
2513 'date_start' => $this->db->jdate($obj->date_start),
2514 'date_end' => $this->db->jdate($obj->date_end),
2515 );
2516 }
2517 $conf->cache['closed_fiscal_period_cached'] = $list;
2518 }
2519 }
2520
2521 return 1;
2522 }
2523
2530 public function getFiscalPeriods($filter = '')
2531 {
2532 global $conf;
2533 $list = array();
2534
2535 $sql = "SELECT rowid, label, date_start, date_end, statut";
2536 $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear";
2537 $sql .= " WHERE entity = " . ((int) $conf->entity);
2538 if (!empty($filter)) {
2539 $sql .= " AND (" . $this->db->sanitize($filter, 1, 1, 1) . ')';
2540 }
2541 $sql .= $this->db->order('date_start', 'ASC');
2542
2543 $resql = $this->db->query($sql);
2544 if (!$resql) {
2545 $this->errors[] = $this->db->lasterror();
2546 return -1;
2547 }
2548
2549 while ($obj = $this->db->fetch_object($resql)) {
2550 $list[$obj->rowid] = array(
2551 'id' => (int) $obj->rowid,
2552 'label' => $obj->label,
2553 'date_start' => $this->db->jdate($obj->date_start),
2554 'date_end' => $this->db->jdate($obj->date_end),
2555 'status' => (int) $obj->statut,
2556 );
2557 }
2558
2559 return $list;
2560 }
2561
2569 public function getCountByMonthForFiscalPeriod($date_start, $date_end)
2570 {
2571 $total = 0;
2572 $list = array();
2573
2574 $sql = "SELECT YEAR(b.doc_date) as year";
2575 for ($i = 1; $i <= 12; $i++) {
2576 $sql .= ", SUM(".$this->db->ifsql("MONTH(b.doc_date) = ".((int) $i), "1", "0") . ") AS month".((int) $i);
2577 }
2578 $sql .= ", COUNT(b.rowid) as total";
2579 $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as b";
2580 $sql .= " WHERE b.doc_date >= '" . $this->db->idate($date_start) . "'";
2581 $sql .= " AND b.doc_date <= '" . $this->db->idate($date_end) . "'";
2582 $sql .= " AND b.entity IN (" . getEntity('bookkeeping', 0) . ")"; // We don't share object for accountancy
2583
2584 // Get count for each month into the fiscal period
2585 if (getDolGlobalString("ACCOUNTANCY_DISABLE_CLOSURE_LINE_BY_LINE")) {
2586 // TODO Analyse is done by finding record not into a closed period
2587 // Loop on each closed period
2588 $sql .= " AND b.doc_date BETWEEN 0 AND 0";
2589 } else {
2590 // Analyse closed record using the unitary flag/date on each record
2591 $sql .= " AND date_validated IS NULL";
2592 }
2593
2594 $sql .= " GROUP BY YEAR(b.doc_date)";
2595 $sql .= $this->db->order("year", 'ASC');
2596
2597 dol_syslog(__METHOD__, LOG_DEBUG);
2598 $resql = $this->db->query($sql);
2599 if (!$resql) {
2600 $this->errors[] = $this->db->lasterror();
2601 return -1;
2602 }
2603
2604 while ($obj = $this->db->fetch_object($resql)) {
2605 $total += (int) $obj->total;
2606 $year_list = array(
2607 'year' => (int) $obj->year,
2608 'count' => array(),
2609 'total' => (int) $obj->total,
2610 );
2611 for ($i = 1; $i <= 12; $i++) {
2612 $year_list['count'][$i] = (int) $obj->{'month' . $i};
2613 }
2614
2615 $list[] = $year_list;
2616 }
2617
2618 $this->db->free($resql);
2619
2620 return array(
2621 'total' => $total,
2622 'list' => $list,
2623 );
2624 }
2625
2633 public function validateMovementForFiscalPeriod($date_start, $date_end)
2634 {
2635 global $conf;
2636
2637 $now = dol_now();
2638
2639 // Specify as export : update field date_validated on selected month/year
2640 $sql = " UPDATE " . MAIN_DB_PREFIX . "accounting_bookkeeping";
2641 $sql .= " SET date_validated = '" . $this->db->idate($now) . "'";
2642 $sql .= " WHERE entity = " . ((int) $conf->entity);
2643 $sql .= " AND DATE(doc_date) >= '" . $this->db->idate($date_start) . "'";
2644 $sql .= " AND DATE(doc_date) <= '" . $this->db->idate($date_end) . "'";
2645 $sql .= " AND date_validated IS NULL";
2646
2647 dol_syslog(__METHOD__, LOG_DEBUG);
2648 $resql = $this->db->query($sql);
2649 if (!$resql) {
2650 $this->errors[] = $this->db->lasterror();
2651 return -1;
2652 }
2653
2654 return 1;
2655 }
2656
2664 public function accountingResult($date_start, $date_end)
2665 {
2666 global $conf;
2667
2668 $this->db->begin();
2669
2670 $income_statement_amount = 0;
2671
2672 if (getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT')) {
2673 $accounting_groups_used_for_income_statement = array_filter(array_map('trim', explode(',', getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT'))), 'strlen');
2674
2675 $pcg_type_filter = array();
2676 foreach ($accounting_groups_used_for_income_statement as $item) {
2677 $pcg_type_filter[] = "'" . $this->db->escape($item) . "'";
2678 }
2679
2680 $sql = 'SELECT';
2681 $sql .= " t.numero_compte,";
2682 $sql .= " aa.pcg_type,";
2683 $sql .= " (SUM(t.credit) - SUM(t.debit)) as accounting_result";
2684 $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
2685 $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'accounting_account as aa ON aa.account_number = t.numero_compte';
2686 $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
2687 $sql .= " AND aa.entity = " . ((int) $conf->entity);
2688 $sql .= ' AND aa.fk_pcg_version IN (SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid = ' . ((int) getDolGlobalInt('CHARTOFACCOUNTS')) . ')';
2689 $sql .= ' AND aa.pcg_type IN (' . $this->db->sanitize(implode(',', $pcg_type_filter), 1) . ')';
2690 $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($date_start) . "'";
2691 $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($date_end) . "'";
2692 $sql .= ' GROUP BY t.numero_compte, aa.pcg_type';
2693
2694 $resql = $this->db->query($sql);
2695 if (!$resql) {
2696 $this->errors[] = 'Error ' . $this->db->lasterror();
2697 dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
2698 } else {
2699 while ($obj = $this->db->fetch_object($resql)) {
2700 $income_statement_amount += $obj->accounting_result;
2701 }
2702 }
2703 }
2704
2705 return (string) $income_statement_amount;
2706 }
2707
2717 public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $separate_auxiliary_account = false, $generate_bookkeeping_records = true)
2718 {
2719 global $conf, $langs, $user;
2720
2721 // Current fiscal period
2722 $fiscal_period_id = max(0, $fiscal_period_id);
2723 if (empty($fiscal_period_id)) {
2724 $langs->load('errors');
2725 $this->errors[] = $langs->trans('ErrorBadParameters');
2726 return -1;
2727 }
2728 $fiscal_period = new Fiscalyear($this->db);
2729 $result = $fiscal_period->fetch($fiscal_period_id);
2730 if ($result < 0) {
2731 $this->error = $fiscal_period->error;
2732 $this->errors = $fiscal_period->errors;
2733 return -1;
2734 } elseif (empty($fiscal_period->id)) {
2735 $langs->loadLangs(array('errors', 'compta'));
2736 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $fiscal_period_id . ')';
2737 return -1;
2738 }
2739
2740 // New fiscal period
2741 $new_fiscal_period_id = max(0, $new_fiscal_period_id);
2742 if (empty($new_fiscal_period_id)) {
2743 $langs->load('errors');
2744 $this->errors[] = $langs->trans('ErrorBadParameters');
2745 return -1;
2746 }
2747 $new_fiscal_period = new Fiscalyear($this->db);
2748 $result = $new_fiscal_period->fetch($new_fiscal_period_id);
2749 if ($result < 0) {
2750 $this->error = $new_fiscal_period->error;
2751 $this->errors = $new_fiscal_period->errors;
2752 return -1;
2753 } elseif (empty($new_fiscal_period->id)) {
2754 $langs->loadLangs(array('errors', 'compta'));
2755 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $new_fiscal_period_id . ')';
2756 return -1;
2757 }
2758
2759 $error = 0;
2760 $this->db->begin();
2761
2762 $fiscal_period->statut = Fiscalyear::STATUS_CLOSED;
2763 $fiscal_period->status = Fiscalyear::STATUS_CLOSED; // Actually not used
2764 $result = $fiscal_period->update($user);
2765 if ($result < 0) {
2766 $this->error = $fiscal_period->error;
2767 $this->errors = $fiscal_period->errors;
2768 $error++;
2769 }
2770
2771 if (!$error && !empty($generate_bookkeeping_records)) {
2772 $journal_id = max(0, getDolGlobalString('ACCOUNTING_CLOSURE_DEFAULT_JOURNAL'));
2773 if (empty($journal_id)) {
2774 $langs->loadLangs(array('errors', 'accountancy'));
2775 $this->errors[] = $langs->trans('ErrorBadParameters') . ' - ' . $langs->trans('Codejournal') . ' (' . $langs->trans('AccountingJournalType9') . ')';
2776 $error++;
2777 }
2778
2779 // Fetch journal
2780 if (!$error) {
2781 $journal = new AccountingJournal($this->db);
2782 $result = $journal->fetch($journal_id);
2783 if ($result < 0) {
2784 $this->error = $journal->error;
2785 $this->errors = $journal->errors;
2786 $error++;
2787 } elseif ($result == 0) {
2788 $langs->loadLangs(array('errors', 'accountancy'));
2789 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('Codejournal') . ' (' . $langs->trans('AccountingJournalType9') . ')';
2790 $error++;
2791 }
2792 }
2793
2794 if (!$error) {
2795 $accounting_groups_used_for_balance_sheet_account = array_filter(array_map('trim', explode(',', getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_BALANCE_SHEET_ACCOUNT'))), 'strlen');
2796 $accounting_groups_used_for_income_statement = array_filter(array_map('trim', explode(',', getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT'))), 'strlen');
2797
2798 $pcg_type_filter = array();
2799 $tmp = array_merge($accounting_groups_used_for_balance_sheet_account, $accounting_groups_used_for_income_statement);
2800 foreach ($tmp as $item) {
2801 $pcg_type_filter[] = "'" . $this->db->escape($item) . "'";
2802 }
2803
2804 $sql = 'SELECT';
2805 $sql .= " t.numero_compte,";
2806 $sql .= " t.label_compte,";
2807 if ($separate_auxiliary_account) {
2808 $sql .= " t.subledger_account,";
2809 $sql .= " t.subledger_label,";
2810 }
2811 $sql .= " aa.pcg_type,";
2812 $sql .= " (SUM(t.credit) - SUM(t.debit)) as opening_balance";
2813 $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
2814 $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'accounting_account as aa ON aa.account_number = t.numero_compte';
2815 $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
2816 $sql .= " AND aa.entity = ". ((int) $conf->entity);
2817 $sql .= ' AND aa.fk_pcg_version IN (SELECT pcg_version FROM '.MAIN_DB_PREFIX.'accounting_system WHERE rowid = '.((int) getDolGlobalInt('CHARTOFACCOUNTS')).')';
2818 $sql .= ' AND aa.pcg_type IN (' . $this->db->sanitize(implode(',', $pcg_type_filter), 1) . ')';
2819 $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($fiscal_period->date_start) . "'";
2820 $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($fiscal_period->date_end) . "'";
2821 $sql .= ' GROUP BY t.numero_compte, t.label_compte, aa.pcg_type';
2822 if ($separate_auxiliary_account) {
2823 $sql .= ' ,t.subledger_account, t.subledger_label';
2824 }
2825 $sql .= $this->db->order("t.numero_compte", "ASC");
2826
2827 $resql = $this->db->query($sql);
2828 if (!$resql) {
2829 $this->errors[] = 'Error ' . $this->db->lasterror();
2830 dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
2831
2832 $error++;
2833 } else {
2834 $now = dol_now();
2835 $income_statement_amount = 0;
2836 while ($obj = $this->db->fetch_object($resql)) {
2837 if (in_array($obj->pcg_type, $accounting_groups_used_for_income_statement)) {
2838 $income_statement_amount += $obj->opening_balance;
2839 } else {
2840 // Insert bookkeeping record for balance sheet account
2841 $mt = $obj->opening_balance;
2842
2843 $bookkeeping = new BookKeeping($this->db);
2844 $bookkeeping->doc_date = $new_fiscal_period->date_start;
2845 $bookkeeping->date_lim_reglement = 0;
2846 $bookkeeping->doc_ref = $new_fiscal_period->label;
2847 $bookkeeping->date_creation = $now;
2848 $bookkeeping->doc_type = 'closure';
2849 $bookkeeping->fk_doc = $new_fiscal_period->id;
2850 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
2851 $bookkeeping->thirdparty_code = '';
2852
2853 if ($separate_auxiliary_account) {
2854 $bookkeeping->subledger_account = $obj->subledger_account;
2855 $bookkeeping->subledger_label = $obj->subledger_label;
2856 } else {
2857 $bookkeeping->subledger_account = '';
2858 $bookkeeping->subledger_label = '';
2859 }
2860
2861 $bookkeeping->numero_compte = $obj->numero_compte;
2862 $bookkeeping->label_compte = $obj->label_compte;
2863
2864 $bookkeeping->label_operation = $new_fiscal_period->label;
2865 $bookkeeping->montant = $mt;
2866 $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
2867 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
2868 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
2869 $bookkeeping->code_journal = $journal->code;
2870 $bookkeeping->journal_label = $langs->transnoentities($journal->label);
2871 $bookkeeping->fk_user_author = $user->id;
2872 $bookkeeping->entity = $conf->entity;
2873
2874 $result = $bookkeeping->create($user);
2875 if ($result < 0) {
2876 $this->error = $bookkeeping->error;
2877 $this->errors = $bookkeeping->errors;
2878 $error++;
2879 break;
2880 }
2881 }
2882 }
2883
2884 // Insert bookkeeping record for income statement
2885 if (!$error && $income_statement_amount != 0) {
2886 $mt = $income_statement_amount;
2887 $accountingaccount = new AccountingAccount($this->db);
2888 $accountingaccount->fetch(null, getDolGlobalString($income_statement_amount < 0 ? 'ACCOUNTING_RESULT_LOSS' : 'ACCOUNTING_RESULT_PROFIT'), true);
2889
2890 $bookkeeping = new BookKeeping($this->db);
2891 $bookkeeping->doc_date = $new_fiscal_period->date_start;
2892 $bookkeeping->date_lim_reglement = 0;
2893 $bookkeeping->doc_ref = $new_fiscal_period->label;
2894 $bookkeeping->date_creation = $now;
2895 $bookkeeping->doc_type = 'closure';
2896 $bookkeeping->fk_doc = $new_fiscal_period->id;
2897 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
2898 $bookkeeping->thirdparty_code = '';
2899
2900 if ($separate_auxiliary_account) {
2901 $bookkeeping->subledger_label = '';
2902 $bookkeeping->subledger_account = $obj->subledger_account;
2903 $bookkeeping->subledger_label = $obj->subledger_label;
2904 } else {
2905 $bookkeeping->subledger_account = '';
2906 $bookkeeping->subledger_label = '';
2907 }
2908
2909 $bookkeeping->numero_compte = $accountingaccount->account_number;
2910 $bookkeeping->label_compte = $accountingaccount->label;
2911
2912 $bookkeeping->label_operation = $new_fiscal_period->label;
2913 $bookkeeping->montant = $mt;
2914 $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D';
2915 $bookkeeping->debit = ($mt < 0) ? -$mt : 0;
2916 $bookkeeping->credit = ($mt >= 0) ? $mt : 0;
2917 $bookkeeping->code_journal = $journal->code;
2918 $bookkeeping->journal_label = $langs->transnoentities($journal->label);
2919 $bookkeeping->fk_user_author = $user->id;
2920 $bookkeeping->entity = $conf->entity;
2921
2922 $result = $bookkeeping->create($user);
2923 if ($result < 0) {
2924 $this->error = $bookkeeping->error;
2925 $this->errors = $bookkeeping->errors;
2926 $error++;
2927 }
2928 }
2929 $this->db->free($resql);
2930 }
2931 }
2932 }
2933
2934 if ($error) {
2935 $this->db->rollback();
2936 return -1;
2937 } else {
2938 $this->db->commit();
2939 return 1;
2940 }
2941 }
2942
2953 public function insertAccountingReversal($fiscal_period_id, $inventory_journal_id, $new_fiscal_period_id, $date_start, $date_end)
2954 {
2955 global $conf, $langs, $user;
2956
2957 // Current fiscal period
2958 $fiscal_period_id = max(0, $fiscal_period_id);
2959 if (empty($fiscal_period_id)) {
2960 $langs->load('errors');
2961 $this->errors[] = $langs->trans('ErrorBadParameters');
2962 return -1;
2963 }
2964 $fiscal_period = new Fiscalyear($this->db);
2965 $result = $fiscal_period->fetch($fiscal_period_id);
2966 if ($result < 0) {
2967 $this->error = $fiscal_period->error;
2968 $this->errors = $fiscal_period->errors;
2969 return -1;
2970 } elseif (empty($fiscal_period->id)) {
2971 $langs->loadLangs(array('errors', 'compta'));
2972 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $fiscal_period_id . ')';
2973 return -1;
2974 }
2975
2976 // New fiscal period
2977 $new_fiscal_period_id = max(0, $new_fiscal_period_id);
2978 if (empty($new_fiscal_period_id)) {
2979 $langs->load('errors');
2980 $this->errors[] = $langs->trans('ErrorBadParameters');
2981 return -1;
2982 }
2983 $new_fiscal_period = new Fiscalyear($this->db);
2984 $result = $new_fiscal_period->fetch($new_fiscal_period_id);
2985 if ($result < 0) {
2986 $this->error = $new_fiscal_period->error;
2987 $this->errors = $new_fiscal_period->errors;
2988 return -1;
2989 } elseif (empty($new_fiscal_period->id)) {
2990 $langs->loadLangs(array('errors', 'compta'));
2991 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $new_fiscal_period_id . ')';
2992 return -1;
2993 }
2994
2995 // Inventory journal
2996 $inventory_journal_id = max(0, $inventory_journal_id);
2997 if (empty($inventory_journal_id)) {
2998 $langs->load('errors');
2999 $this->errors[] = $langs->trans('ErrorBadParameters');
3000 return -1;
3001 }
3002 // Fetch journal
3003 $inventory_journal = new AccountingJournal($this->db);
3004 $result = $inventory_journal->fetch($inventory_journal_id);
3005 if ($result < 0) {
3006 $this->error = $inventory_journal->error;
3007 $this->errors = $inventory_journal->errors;
3008 return -1;
3009 } elseif ($result == 0) {
3010 $langs->loadLangs(array('errors', 'accountancy'));
3011 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('InventoryJournal');
3012 return -1;
3013 }
3014
3015 $error = 0;
3016 $this->db->begin();
3017
3018 $sql = 'SELECT t.rowid';
3019 $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t';
3020 $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
3021 $sql .= " AND code_journal = '" . $this->db->escape($inventory_journal->code) . "'";
3022 $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($date_start) . "'";
3023 $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($date_end) . "'";
3024 $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($fiscal_period->date_start) . "'";
3025 $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($fiscal_period->date_end) . "'";
3026
3027 $resql = $this->db->query($sql);
3028 if (!$resql) {
3029 $this->errors[] = 'Error ' . $this->db->lasterror();
3030 dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR);
3031
3032 $error++;
3033 } else {
3034 $now = dol_now();
3035 while ($obj = $this->db->fetch_object($resql)) {
3036 $bookkeeping = new BookKeeping($this->db);
3037 $result = $bookkeeping->fetch($obj->rowid);
3038 if ($result < 0) {
3039 $this->error = $inventory_journal->error;
3040 $this->errors = $inventory_journal->errors;
3041 $error++;
3042 break;
3043 } elseif ($result == 0) {
3044 $langs->loadLangs(array('errors', 'accountancy'));
3045 $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('LineId') . ': ' . $obj->rowid;
3046 $error++;
3047 break;
3048 }
3049
3050 $bookkeeping->id = 0;
3051 $bookkeeping->doc_date = $new_fiscal_period->date_start;
3052 $bookkeeping->doc_ref = $new_fiscal_period->label;
3053 $bookkeeping->date_creation = $now;
3054 $bookkeeping->doc_type = 'accounting_reversal';
3055 $bookkeeping->fk_doc = $new_fiscal_period->id;
3056 $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add
3057
3058 $bookkeeping->montant = -$bookkeeping->montant;
3059 $bookkeeping->sens = ($bookkeeping->montant >= 0) ? 'C' : 'D';
3060 $old_debit = $bookkeeping->debit;
3061 $bookkeeping->debit = $bookkeeping->credit;
3062 $bookkeeping->credit = $old_debit;
3063
3064 $bookkeeping->fk_user_author = $user->id;
3065 $bookkeeping->entity = $conf->entity;
3066
3067 $result = $bookkeeping->create($user);
3068 if ($result < 0) {
3069 $this->error = $bookkeeping->error;
3070 $this->errors = $bookkeeping->errors;
3071 $error++;
3072 break;
3073 }
3074 }
3075 $this->db->free($resql);
3076 }
3077
3078 if ($error) {
3079 $this->db->rollback();
3080 return -1;
3081 } else {
3082 $this->db->commit();
3083 return 1;
3084 }
3085 }
3086}
3087
3092{
3096 public $id;
3097
3098 public $doc_date = null;
3099 public $doc_type;
3100 public $doc_ref;
3101
3105 public $fk_doc;
3106
3110 public $fk_docdet;
3111
3112 public $thirdparty_code;
3113 public $subledger_account;
3114 public $subledger_label;
3115 public $numero_compte;
3116 public $label_compte;
3117 public $label_operation;
3118 public $debit;
3119 public $credit;
3120
3125 public $montant;
3126
3130 public $amount;
3131
3135 public $multicurrency_amount;
3136
3140 public $multicurrency_code;
3141
3145 public $sens;
3146 public $lettering_code;
3147 public $date_lettering;
3148
3152 public $fk_user_author;
3153
3154 public $import_key;
3155 public $code_journal;
3156 public $journal_label;
3160 public $piece_num;
3161
3165 public $date_export;
3166
3170 public $date_lim_reglement;
3171}
if( $user->socid > 0) if(! $user->hasRight('accounting', 'chartofaccount')) $object
Definition card.php:58
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:456
Class to manage accounting accounts.
Class to manage accounting journals.
Class to manage Ledger (General Ledger and Subledger)
closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $separate_auxiliary_account=false, $generate_bookkeeping_records=true)
Close fiscal period.
getCountByMonthForFiscalPeriod($date_start, $date_end)
Get list of count by month into the fiscal period.
fetchAllBalance($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND', $option=0)
Load object in memory from the database.
getNomUrl($withpicto=0, $option='', $notooltip=0, $morecss='', $save_lastsearch_value=-1)
Return a link to the object card (with optionally the picto)
select_account($selectid, $htmlname='account', $showempty=0, $event=array(), $select_in=0, $select_out=0, $aabase='')
Return list of accounts with label by chart of accounts.
getNextNumMvt($mode='')
Return next movement number.
get_compte_desc($account=null)
Description of accounting account.
__construct(DoliDB $db)
Constructor.
createFromClone(User $user, $fromid)
Load an object from its id and create a new one in database.
deleteByImportkey($importkey, $mode='')
Delete bookkeeping by importkey.
getRootAccount($account=null)
Return id and description of a root accounting account.
transformTransaction($direction=0, $piece_num='')
Transform transaction.
insertAccountingReversal($fiscal_period_id, $inventory_journal_id, $new_fiscal_period_id, $date_start, $date_end)
Insert accounting reversal into the inventory journal of the new fiscal period.
fetchPerMvt($piecenum, $mode='')
Load an accounting document into memory from database.
create(User $user, $notrigger=0)
Create object into database.
updateByMvt($piece_num='', $field='', $value='', $mode='')
Update accounting movement.
createStd(User $user, $notrigger=0, $mode='')
Create object into database.
update(User $user, $notrigger=0, $mode='')
Update object into database.
deleteMvtNum($piecenum, $mode='')
Delete bookkeeping by piece number.
getFiscalPeriods($filter='')
Get list of fiscal period.
validBookkeepingDate($date)
Is the bookkeeping date valid (on an open period or not on a closed period) ?
deleteByYearAndJournal($delyear=0, $journal='', $mode='', $delmonth=0)
Delete bookkeeping by year.
loadFiscalPeriods($force=false, $mode='active')
Load list of active fiscal period.
fetchAllByAccount($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND', $option=0, $countonly=0)
Load object in memory from the database in ->lines.
initAsSpecimen()
Initialise object with example values Id must be 0 if object instance is a specimen.
getCanModifyBookkeepingSQL($alias='', $force=false)
Get SQL string for check if the bookkeeping can be modified or deleted ? (cached)
fetch($id, $ref=null, $mode='')
Load object in memory from the database.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, $filter='', $filtermode='AND', $showAlreadyExportMovements=1)
Load object in memory from the database.
accountingResult($date_start, $date_end)
Define accounting result.
canModifyBookkeeping($id, $mode='')
Is the bookkeeping can be modified or deleted ?
fetchAllPerMvt($piecenum, $mode='')
Load all accounting lines related to a given transaction ID $piecenum.
validateMovementForFiscalPeriod($date_start, $date_end)
Validate all movement between the specified dates.
export_bookkeeping($model='ebp')
Export bookkeeping.
Class BookKeepingLine.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Parent class for class inheritance lines of business objects This class is useless for the moment so ...
Class to manage Dolibarr database access.
Class to manage fiscal year.
static selectarray($htmlname, $array, $id='', $show_empty=0, $key_in_label=0, $value_as_key=0, $moreparam='', $translate=0, $maxlen=0, $disabled=0, $sort='', $morecss='minwidth75', $addjscombo=1, $moreparamonempty='', $disablebademail=0, $nohtmlescape=0)
Return a HTML select string, built from an array of key+value.
Class to manage Dolibarr users.
dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $excludefirstand=0, $gm=false)
Generate a SQL string to make a filter into a range (for second of date until last second of date).
Definition date.lib.php:377
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
natural_search($fields, $value, $mode=0, $nofirstand=0)
Generate natural SQL search string for a criteria (this criteria can be tested on one or several fiel...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
forgeSQLFromUniversalSearchCriteria($filter, &$errorstr='', $noand=0, $nopar=0, $noerror=0)
forgeSQLFromUniversalSearchCriteria
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
getEntity($element, $shared=1, $currentobject=null)
Get list of entity id to use.