dolibarr 19.0.3
accountingjournal.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2017-2022 OpenDSI <support@open-dsi.fr>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
28{
32 public $element = 'accounting_journal';
33
37 public $table_element = 'accounting_journal';
38
42 public $fk_element = '';
43
47 public $ismultientitymanaged = 0;
48
52 public $picto = 'generic';
53
57 public $rowid;
58
62 public $code;
63
67 public $label;
68
72 public $nature;
73
77 public $active;
78
82 public $lines;
83
87 public static $accounting_account_cached = array();
88
92 public static $nature_maps = array(
93 1 => 'variousoperations',
94 2 => 'sells',
95 3 => 'purchases',
96 4 => 'bank',
97 5 => 'expensereports',
98 8 => 'inventories',
99 9 => 'hasnew',
100 );
101
107 public function __construct($db)
108 {
109 $this->db = $db;
110 }
111
119 public function fetch($rowid = null, $journal_code = null)
120 {
121 global $conf;
122
123 if ($rowid || $journal_code) {
124 $sql = "SELECT rowid, code, label, nature, active";
125 $sql .= " FROM ".MAIN_DB_PREFIX."accounting_journal";
126 $sql .= " WHERE";
127 if ($rowid) {
128 $sql .= " rowid = ".((int) $rowid);
129 } elseif ($journal_code) {
130 $sql .= " code = '".$this->db->escape($journal_code)."'";
131 $sql .= " AND entity = ".$conf->entity;
132 }
133
134 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
135 $result = $this->db->query($sql);
136 if ($result) {
137 $obj = $this->db->fetch_object($result);
138
139 if ($obj) {
140 $this->id = $obj->rowid;
141 $this->rowid = $obj->rowid;
142
143 $this->code = $obj->code;
144 $this->ref = $obj->code;
145 $this->label = $obj->label;
146 $this->nature = $obj->nature;
147 $this->active = $obj->active;
148
149 return $this->id;
150 } else {
151 return 0;
152 }
153 } else {
154 $this->error = "Error ".$this->db->lasterror();
155 $this->errors[] = "Error ".$this->db->lasterror();
156 }
157 }
158 return -1;
159 }
160
173 public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
174 {
175 $sql = "SELECT rowid, code, label, nature, active";
176 $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
177 // Manage filter
178 $sqlwhere = array();
179 if (count($filter) > 0) {
180 foreach ($filter as $key => $value) {
181 if ($key == 't.code' || $key == 't.label' || $key == 't.nature') {
182 $sqlwhere[] = $key.'\''.$this->db->escape($value).'\'';
183 } elseif ($key == 't.rowid' || $key == 't.active') {
184 $sqlwhere[] = $key.'='.$value;
185 }
186 }
187 }
188 $sql .= ' WHERE 1 = 1';
189 $sql .= " AND entity IN (".getEntity('accountancy').")";
190 if (count($sqlwhere) > 0) {
191 $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere);
192 }
193
194 if (!empty($sortfield)) {
195 $sql .= $this->db->order($sortfield, $sortorder);
196 }
197 if (!empty($limit)) {
198 $sql .= $this->db->plimit($limit + 1, $offset);
199 }
200 $this->lines = array();
201
202 dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
203 $resql = $this->db->query($sql);
204 if ($resql) {
205 $num = $this->db->num_rows($resql);
206
207 while ($obj = $this->db->fetch_object($resql)) {
208 $line = new self($this->db);
209
210 $line->id = $obj->rowid;
211 $line->code = $obj->code;
212 $line->label = $obj->label;
213 $line->nature = $obj->nature;
214 $line->active = $obj->active;
215
216 $this->lines[] = $line;
217 }
218
219 $this->db->free($resql);
220
221 return $num;
222 } else {
223 $this->errors[] = 'Error '.$this->db->lasterror();
224 dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
225
226 return -1;
227 }
228 }
229
240 public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0)
241 {
242 global $langs, $conf, $user, $hookmanager;
243
244 if (!empty($conf->dol_no_mouse_hover)) {
245 $notooltip = 1; // Force disable tooltips
246 }
247
248 $result = '';
249
250 $url = DOL_URL_ROOT.'/accountancy/admin/journals_list.php?id=35';
251
252 $label = '<u>'.$langs->trans("ShowAccountingJournal").'</u>';
253 if (!empty($this->code)) {
254 $label .= '<br><b>'.$langs->trans('Code').':</b> '.$this->code;
255 }
256 if (!empty($this->label)) {
257 $label .= '<br><b>'.$langs->trans('Label').':</b> '.$langs->transnoentities($this->label);
258 }
259 if ($moretitle) {
260 $label .= ' - '.$moretitle;
261 }
262
263 $linkclose = '';
264 if (empty($notooltip)) {
265 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
266 $label = $langs->trans("ShowAccountingJournal");
267 $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
268 }
269 $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
270 $linkclose .= ' class="classfortooltip"';
271 }
272
273 $linkstart = '<a href="'.$url.'"';
274 $linkstart .= $linkclose.'>';
275 $linkend = '</a>';
276
277 if ($nourl) {
278 $linkstart = '';
279 $linkclose = '';
280 $linkend = '';
281 }
282
283 $label_link = $this->code;
284 if ($withlabel == 1 && !empty($this->label)) {
285 $label_link .= ' - '.($nourl ? '<span class="opacitymedium">' : '').$langs->transnoentities($this->label).($nourl ? '</span>' : '');
286 }
287 if ($withlabel == 2 && !empty($this->nature)) {
288 $key = $langs->trans("AccountingJournalType".strtoupper($this->nature));
289 $transferlabel = ($this->nature && $key != "AccountingJournalType".strtoupper($langs->trans($this->nature)) ? $key : $this->label);
290 $label_link .= ' - '.($nourl ? '<span class="opacitymedium">' : '').$transferlabel.($nourl ? '</span>' : '');
291 }
292
293 $result .= $linkstart;
294 if ($withpicto) {
295 $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);
296 }
297 if ($withpicto != 2) {
298 $result .= $label_link;
299 }
300 $result .= $linkend;
301
302 global $action;
303 $hookmanager->initHooks(array('accountingjournaldao'));
304 $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
305 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
306 if ($reshook > 0) {
307 $result = $hookmanager->resPrint;
308 } else {
309 $result .= $hookmanager->resPrint;
310 }
311 return $result;
312 }
313
320 public function getLibType($mode = 0)
321 {
322 return $this->LibType($this->nature, $mode);
323 }
324
325 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
333 public function LibType($nature, $mode = 0)
334 {
335 // phpcs:enable
336 global $langs;
337
338 $langs->loadLangs(array("accountancy"));
339
340 if ($mode == 0) {
341 $prefix = '';
342 if ($nature == 9) {
343 return $langs->trans('AccountingJournalType9');
344 } elseif ($nature == 5) {
345 return $langs->trans('AccountingJournalType5');
346 } elseif ($nature == 4) {
347 return $langs->trans('AccountingJournalType4');
348 } elseif ($nature == 3) {
349 return $langs->trans('AccountingJournalType3');
350 } elseif ($nature == 2) {
351 return $langs->trans('AccountingJournalType2');
352 } elseif ($nature == 1) {
353 return $langs->trans('AccountingJournalType1');
354 }
355 } elseif ($mode == 1) {
356 if ($nature == 9) {
357 return $langs->trans('AccountingJournalType9');
358 } elseif ($nature == 5) {
359 return $langs->trans('AccountingJournalType5');
360 } elseif ($nature == 4) {
361 return $langs->trans('AccountingJournalType4');
362 } elseif ($nature == 3) {
363 return $langs->trans('AccountingJournalType3');
364 } elseif ($nature == 2) {
365 return $langs->trans('AccountingJournalType2');
366 } elseif ($nature == 1) {
367 return $langs->trans('AccountingJournalType1');
368 }
369 }
370 return "";
371 }
372
373
384 public function getData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet')
385 {
386 global $hookmanager;
387
388 // Clean parameters
389 if (empty($type)) {
390 $type = 'view';
391 }
392 if (empty($in_bookkeeping)) {
393 $in_bookkeeping = 'notyet';
394 }
395
396 $data = array();
397
398 $hookmanager->initHooks(array('accountingjournaldao'));
399 $parameters = array('data' => &$data, 'user' => $user, 'type' => $type, 'date_start' => $date_start, 'date_end' => $date_end, 'in_bookkeeping' => $in_bookkeeping);
400 $reshook = $hookmanager->executeHooks('getData', $parameters, $this); // Note that $action and $object may have been
401 if ($reshook < 0) {
402 $this->error = $hookmanager->error;
403 $this->errors = $hookmanager->errors;
404 return -1;
405 } elseif (empty($reshook)) {
406 switch ($this->nature) {
407 case 1: // Various Journal
408 $data = $this->getAssetData($user, $type, $date_start, $date_end, $in_bookkeeping);
409 break;
410 // case 2: // Sells Journal
411 // case 3: // Purchases Journal
412 // case 4: // Bank Journal
413 // case 5: // Expense reports Journal
414 // case 8: // Inventory Journal
415 // case 9: // hasnew Journal
416 }
417 }
418
419 return $data;
420 }
421
432 public function getAssetData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet')
433 {
434 global $conf, $langs;
435
436 if (!isModEnabled('asset')) {
437 return array();
438 }
439
440 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
441 require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
442 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
443 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
444
445 $langs->loadLangs(array("assets"));
446
447 // Clean parameters
448 if (empty($type)) {
449 $type = 'view';
450 }
451 if (empty($in_bookkeeping)) {
452 $in_bookkeeping = 'notyet';
453 }
454
455 $sql = "";
456 $sql .= "SELECT ad.fk_asset AS rowid, a.ref AS asset_ref, a.label AS asset_label, a.acquisition_value_ht AS asset_acquisition_value_ht";
457 $sql .= ", a.disposal_date AS asset_disposal_date, a.disposal_amount_ht AS asset_disposal_amount_ht, a.disposal_subject_to_vat AS asset_disposal_subject_to_vat";
458 $sql .= ", ad.rowid AS depreciation_id, ad.depreciation_mode, ad.ref AS depreciation_ref, ad.depreciation_date, ad.depreciation_ht, ad.accountancy_code_debit, ad.accountancy_code_credit";
459 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation as ad";
460 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "asset as a ON a.rowid = ad.fk_asset";
461 $sql .= " WHERE a.entity IN (" . getEntity('asset', 0) . ')'; // We don't share object for accountancy, we use source object sharing
462 if ($in_bookkeeping == 'already') {
463 $sql .= " AND EXISTS (SELECT iab.fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS iab WHERE iab.fk_docdet = ad.rowid AND doc_type = 'asset')";
464 } elseif ($in_bookkeeping == 'notyet') {
465 $sql .= " AND NOT EXISTS (SELECT iab.fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping AS iab WHERE iab.fk_docdet = ad.rowid AND doc_type = 'asset')";
466 }
467 $sql .= " AND ad.ref != ''"; // not reversal lines
468 if ($date_start && $date_end) {
469 $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($date_start) . "' AND ad.depreciation_date <= '" . $this->db->idate($date_end) . "'";
470 }
471 // Define begin binding date
472 if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
473 $sql .= " AND ad.depreciation_date >= '" . $this->db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) . "'";
474 }
475 $sql .= " ORDER BY ad.depreciation_date";
476
477 dol_syslog(__METHOD__, LOG_DEBUG);
478 $resql = $this->db->query($sql);
479 if (!$resql) {
480 $this->errors[] = $this->db->lasterror();
481 return -1;
482 }
483
484 $pre_data = array(
485 'elements' => array(),
486 );
487 while ($obj = $this->db->fetch_object($resql)) {
488 if (!isset($pre_data['elements'][$obj->rowid])) {
489 $pre_data['elements'][$obj->rowid] = array(
490 'ref' => $obj->asset_ref,
491 'label' => $obj->asset_label,
492 'acquisition_value_ht' => $obj->asset_acquisition_value_ht,
493 'depreciation' => array(),
494 );
495
496 // Disposal infos
497 if (isset($obj->asset_disposal_date)) {
498 $pre_data['elements'][$obj->rowid]['disposal'] = array(
499 'date' => $this->db->jdate($obj->asset_disposal_date),
500 'amount' => $obj->asset_disposal_amount_ht,
501 'subject_to_vat' => !empty($obj->asset_disposal_subject_to_vat),
502 );
503 }
504 }
505
506 $compta_debit = empty($obj->accountancy_code_debit) ? 'NotDefined' : $obj->accountancy_code_debit;
507 $compta_credit = empty($obj->accountancy_code_credit) ? 'NotDefined' : $obj->accountancy_code_credit;
508
509 $pre_data['elements'][$obj->rowid]['depreciation'][$obj->depreciation_id] = array(
510 'date' => $this->db->jdate($obj->depreciation_date),
511 'ref' => $obj->depreciation_ref,
512 'lines' => array(
513 $compta_debit => -$obj->depreciation_ht,
514 $compta_credit => $obj->depreciation_ht,
515 ),
516 );
517 }
518
519 $disposal_ref = $langs->transnoentitiesnoconv('AssetDisposal');
520 $journal = $this->code;
521 $journal_label = $this->label;
522 $journal_label_formatted = $langs->transnoentities($journal_label);
523 $now = dol_now();
524
525 $element_static = new Asset($this->db);
526
527 $journal_data = array();
528 foreach ($pre_data['elements'] as $pre_data_id => $pre_data_info) {
529 $element_static->id = $pre_data_id;
530 $element_static->ref = (string) $pre_data_info["ref"];
531 $element_static->label = (string) $pre_data_info["label"];
532 $element_static->acquisition_value_ht = $pre_data_info["acquisition_value_ht"];
533 $element_link = $element_static->getNomUrl(1, 'with_label');
534
535 $element_name_formatted_0 = dol_trunc($element_static->label, 16);
536 $label_operation = $element_static->getNomUrl(0, 'label', 16);
537
538 $element = array(
539 'ref' => dol_trunc($element_static->ref, 16, 'right', 'UTF-8', 1),
540 'error' => $pre_data_info['error'],
541 'blocks' => array(),
542 );
543
544 // Depreciation lines
545 //--------------------
546 foreach ($pre_data_info['depreciation'] as $depreciation_id => $line) {
547 $depreciation_ref = $line["ref"];
548 $depreciation_date = $line["date"];
549 $depreciation_date_formatted = dol_print_date($depreciation_date, 'day');
550
551 // lines
552 $blocks = array();
553 foreach ($line['lines'] as $account => $mt) {
554 $account_infos = $this->getAccountingAccountInfos($account);
555
556 if ($type == 'view') {
557 $account_to_show = length_accounta($account);
558 if (($account_to_show == "") || $account_to_show == 'NotDefined') {
559 $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
560 }
561
562 $blocks[] = array(
563 'date' => $depreciation_date_formatted,
564 'piece' => $element_link,
565 'account_accounting' => $account_to_show,
566 'subledger_account' => '',
567 'label_operation' => $label_operation . ' - ' . $depreciation_ref,
568 'debit' => $mt < 0 ? price(-$mt) : '',
569 'credit' => $mt >= 0 ? price($mt) : '',
570 );
571 } elseif ($type == 'bookkeeping') {
572 if ($account_infos['found']) {
573 $blocks[] = array(
574 'doc_date' => $depreciation_date,
575 'date_lim_reglement' => '',
576 'doc_ref' => $element_static->ref,
577 'date_creation' => $now,
578 'doc_type' => 'asset',
579 'fk_doc' => $element_static->id,
580 'fk_docdet' => $depreciation_id, // Useless, can be several lines that are source of this record to add
581 'thirdparty_code' => '',
582 'subledger_account' => '',
583 'subledger_label' => '',
584 'numero_compte' => $account,
585 'label_compte' => $account_infos['label'],
586 'label_operation' => $element_name_formatted_0 . ' - ' . $depreciation_ref,
587 'montant' => $mt,
588 'sens' => $mt < 0 ? 'D' : 'C',
589 'debit' => $mt < 0 ? -$mt : 0,
590 'credit' => $mt >= 0 ? $mt : 0,
591 'code_journal' => $journal,
592 'journal_label' => $journal_label_formatted,
593 'piece_num' => '',
594 'import_key' => '',
595 'fk_user_author' => $user->id,
596 'entity' => $conf->entity,
597 );
598 }
599 } else { // $type == 'csv'
600 $blocks[] = array(
601 $depreciation_date, // Date
602 $element_static->ref, // Piece
603 $account_infos['code_formatted_1'], // AccountAccounting
604 $element_name_formatted_0 . ' - ' . $depreciation_ref, // LabelOperation
605 $mt < 0 ? price(-$mt) : '', // Debit
606 $mt >= 0 ? price($mt) : '', // Credit
607 );
608 }
609 }
610 $element['blocks'][] = $blocks;
611 }
612
613 // Disposal line
614 //--------------------
615 if (!empty($pre_data_info['disposal'])) {
616 $disposal_date = $pre_data_info['disposal']['date'];
617
618 if ((!($date_start && $date_end) || ($date_start <= $disposal_date && $disposal_date <= $date_end)) &&
619 (!getDolGlobalString('ACCOUNTING_DATE_START_BINDING') || getDolGlobalInt('ACCOUNTING_DATE_START_BINDING') <= $disposal_date)
620 ) {
621 $disposal_amount = $pre_data_info['disposal']['amount'];
622 $disposal_subject_to_vat = $pre_data_info['disposal']['subject_to_vat'];
623 $disposal_date_formatted = dol_print_date($disposal_date, 'day');
624 $disposal_vat = getDolGlobalInt('ASSET_DISPOSAL_VAT') > 0 ? getDolGlobalInt('ASSET_DISPOSAL_VAT') : 20;
625
626 // Get accountancy codes
627 //---------------------------
628 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
629 $accountancy_codes = new AssetAccountancyCodes($this->db);
630 $result = $accountancy_codes->fetchAccountancyCodes($element_static->id);
631 if ($result < 0) {
632 $element['error'] = $accountancy_codes->errorsToString();
633 } else {
634 // Get last depreciation cumulative amount
635 $element_static->fetchDepreciationLines();
636 foreach ($element_static->depreciation_lines as $mode_key => $depreciation_lines) {
637 $accountancy_codes_list = $accountancy_codes->accountancy_codes[$mode_key];
638
639 if (!isset($accountancy_codes_list['value_asset_sold'])) {
640 continue;
641 }
642
643 $accountancy_code_value_asset_sold = empty($accountancy_codes_list['value_asset_sold']) ? 'NotDefined' : $accountancy_codes_list['value_asset_sold'];
644 $accountancy_code_depreciation_asset = empty($accountancy_codes_list['depreciation_asset']) ? 'NotDefined' : $accountancy_codes_list['depreciation_asset'];
645 $accountancy_code_asset = empty($accountancy_codes_list['asset']) ? 'NotDefined' : $accountancy_codes_list['asset'];
646 $accountancy_code_receivable_on_assignment = empty($accountancy_codes_list['receivable_on_assignment']) ? 'NotDefined' : $accountancy_codes_list['receivable_on_assignment'];
647 $accountancy_code_vat_collected = empty($accountancy_codes_list['vat_collected']) ? 'NotDefined' : $accountancy_codes_list['vat_collected'];
648 $accountancy_code_proceeds_from_sales = empty($accountancy_codes_list['proceeds_from_sales']) ? 'NotDefined' : $accountancy_codes_list['proceeds_from_sales'];
649
650 $last_cumulative_amount_ht = 0;
651 $depreciated_ids = array_keys($pre_data_info['depreciation']);
652 foreach ($depreciation_lines as $line) {
653 $last_cumulative_amount_ht = $line['cumulative_depreciation_ht'];
654 if (!in_array($line['id'], $depreciated_ids) && empty($line['bookkeeping']) && !empty($line['ref'])) {
655 break;
656 }
657 }
658
659 $lines = array();
660 $lines[0][$accountancy_code_value_asset_sold] = -($element_static->acquisition_value_ht - $last_cumulative_amount_ht);
661 $lines[0][$accountancy_code_depreciation_asset] = -$last_cumulative_amount_ht;
662 $lines[0][$accountancy_code_asset] = $element_static->acquisition_value_ht;
663
664 $disposal_amount_vat = $disposal_subject_to_vat ? (float) price2num($disposal_amount * $disposal_vat / 100, 'MT') : 0;
665 $lines[1][$accountancy_code_receivable_on_assignment] = -($disposal_amount + $disposal_amount_vat);
666 if ($disposal_subject_to_vat) {
667 $lines[1][$accountancy_code_vat_collected] = $disposal_amount_vat;
668 }
669 $lines[1][$accountancy_code_proceeds_from_sales] = $disposal_amount;
670
671 foreach ($lines as $lines_block) {
672 $blocks = array();
673 foreach ($lines_block as $account => $mt) {
674 $account_infos = $this->getAccountingAccountInfos($account);
675
676 if ($type == 'view') {
677 $account_to_show = length_accounta($account);
678 if (($account_to_show == "") || $account_to_show == 'NotDefined') {
679 $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
680 }
681
682 $blocks[] = array(
683 'date' => $disposal_date_formatted,
684 'piece' => $element_link,
685 'account_accounting' => $account_to_show,
686 'subledger_account' => '',
687 'label_operation' => $label_operation . ' - ' . $disposal_ref,
688 'debit' => $mt < 0 ? price(-$mt) : '',
689 'credit' => $mt >= 0 ? price($mt) : '',
690 );
691 } elseif ($type == 'bookkeeping') {
692 if ($account_infos['found']) {
693 $blocks[] = array(
694 'doc_date' => $disposal_date,
695 'date_lim_reglement' => '',
696 'doc_ref' => $element_static->ref,
697 'date_creation' => $now,
698 'doc_type' => 'asset',
699 'fk_doc' => $element_static->id,
700 'fk_docdet' => 0, // Useless, can be several lines that are source of this record to add
701 'thirdparty_code' => '',
702 'subledger_account' => '',
703 'subledger_label' => '',
704 'numero_compte' => $account,
705 'label_compte' => $account_infos['label'],
706 'label_operation' => $element_name_formatted_0 . ' - ' . $disposal_ref,
707 'montant' => $mt,
708 'sens' => $mt < 0 ? 'D' : 'C',
709 'debit' => $mt < 0 ? -$mt : 0,
710 'credit' => $mt >= 0 ? $mt : 0,
711 'code_journal' => $journal,
712 'journal_label' => $journal_label_formatted,
713 'piece_num' => '',
714 'import_key' => '',
715 'fk_user_author' => $user->id,
716 'entity' => $conf->entity,
717 );
718 }
719 } else { // $type == 'csv'
720 $blocks[] = array(
721 $disposal_date, // Date
722 $element_static->ref, // Piece
723 $account_infos['code_formatted_1'], // AccountAccounting
724 $element_name_formatted_0 . ' - ' . $disposal_ref, // LabelOperation
725 $mt < 0 ? price(-$mt) : '', // Debit
726 $mt >= 0 ? price($mt) : '', // Credit
727 );
728 }
729 }
730 $element['blocks'][] = $blocks;
731 }
732 }
733 }
734 }
735 }
736
737 $journal_data[(int) $pre_data_id] = $element;
738 }
739 unset($pre_data);
740
741 return $journal_data;
742 }
743
787 public function writeIntoBookkeeping(User $user, &$journal_data = array(), $max_nb_errors = 10)
788 {
789 global $conf, $langs, $hookmanager;
790 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php';
791
792 $error = 0;
793
794 $hookmanager->initHooks(array('accountingjournaldao'));
795 $parameters = array('journal_data' => &$journal_data);
796 $reshook = $hookmanager->executeHooks('writeBookkeeping', $parameters, $this); // Note that $action and $object may have been
797 if ($reshook < 0) {
798 $this->error = $hookmanager->error;
799 $this->errors = $hookmanager->errors;
800 return -1;
801 } elseif (empty($reshook)) {
802 // Clean parameters
803 $journal_data = is_array($journal_data) ? $journal_data : array();
804
805 foreach ($journal_data as $element_id => $element) {
806 $error_for_line = 0;
807 $total_credit = 0;
808 $total_debit = 0;
809
810 $this->db->begin();
811
812 if ($element['error'] == 'somelinesarenotbound') {
813 $error++;
814 $error_for_line++;
815 $this->errors[] = $langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $element['ref']);
816 }
817
818 if (!$error_for_line) {
819 foreach ($element['blocks'] as $lines) {
820 foreach ($lines as $line) {
821 $bookkeeping = new BookKeeping($this->db);
822 $bookkeeping->doc_date = $line['doc_date'];
823 $bookkeeping->date_lim_reglement = $line['date_lim_reglement'];
824 $bookkeeping->doc_ref = $line['doc_ref'];
825 $bookkeeping->date_creation = $line['date_creation']; // not used
826 $bookkeeping->doc_type = $line['doc_type'];
827 $bookkeeping->fk_doc = $line['fk_doc'];
828 $bookkeeping->fk_docdet = $line['fk_docdet'];
829 $bookkeeping->thirdparty_code = $line['thirdparty_code'];
830 $bookkeeping->subledger_account = $line['subledger_account'];
831 $bookkeeping->subledger_label = $line['subledger_label'];
832 $bookkeeping->numero_compte = $line['numero_compte'];
833 $bookkeeping->label_compte = $line['label_compte'];
834 $bookkeeping->label_operation = $line['label_operation'];
835 $bookkeeping->montant = $line['montant'];
836 $bookkeeping->sens = $line['sens'];
837 $bookkeeping->debit = $line['debit'];
838 $bookkeeping->credit = $line['credit'];
839 $bookkeeping->code_journal = $line['code_journal'];
840 $bookkeeping->journal_label = $line['journal_label'];
841 $bookkeeping->piece_num = $line['piece_num'];
842 $bookkeeping->import_key = $line['import_key'];
843 $bookkeeping->fk_user_author = $user->id;
844 $bookkeeping->entity = $conf->entity;
845
846 $total_debit += $bookkeeping->debit;
847 $total_credit += $bookkeeping->credit;
848
849 $result = $bookkeeping->create($user);
850 if ($result < 0) {
851 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
852 $error++;
853 $error_for_line++;
854 $journal_data[$element_id]['error'] = 'alreadyjournalized';
855 } else {
856 $error++;
857 $error_for_line++;
858 $journal_data[$element_id]['error'] = 'other';
859 $this->errors[] = $bookkeeping->errorsToString();
860 }
861 }
862 //
863 // if (!$error_for_line && isModEnabled('asset') && $this->nature == 1 && $bookkeeping->fk_doc > 0) {
864 // // Set last cumulative depreciation
865 // require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
866 // $asset = new Asset($this->db);
867 // $result = $asset->setLastCumulativeDepreciation($bookkeeping->fk_doc);
868 // if ($result < 0) {
869 // $error++;
870 // $error_for_line++;
871 // $journal_data[$element_id]['error'] = 'other';
872 // $this->errors[] = $asset->errorsToString();
873 // }
874 // }
875 }
876
877 if ($error_for_line) {
878 break;
879 }
880 }
881 }
882
883 // Protection against a bug on lines before
884 if (!$error_for_line && (price2num($total_debit, 'MT') != price2num($total_credit, 'MT'))) {
885 $error++;
886 $error_for_line++;
887 $journal_data[$element_id]['error'] = 'amountsnotbalanced';
888 $this->errors[] = 'Try to insert a non balanced transaction in book for ' . $element['blocks'] . '. Canceled. Surely a bug.';
889 }
890
891 if (!$error_for_line) {
892 $this->db->commit();
893 } else {
894 $this->db->rollback();
895
896 if ($error >= $max_nb_errors) {
897 $this->errors[] = $langs->trans("ErrorTooManyErrorsProcessStopped");
898 break; // Break in the foreach
899 }
900 }
901 }
902 }
903
904 return $error ? -$error : 1;
905 }
906
928 public function exportCsv(&$journal_data = array(), $search_date_end = 0, $sep = '')
929 {
930 global $conf, $langs, $hookmanager;
931
932 if (empty($sep)) {
933 $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
934 }
935 $out = '';
936
937 // Hook
938 $hookmanager->initHooks(array('accountingjournaldao'));
939 $parameters = array('journal_data' => &$journal_data, 'search_date_end' => &$search_date_end, 'sep' => &$sep, 'out' => &$out);
940 $reshook = $hookmanager->executeHooks('exportCsv', $parameters, $this); // Note that $action and $object may have been
941 if ($reshook < 0) {
942 $this->error = $hookmanager->error;
943 $this->errors = $hookmanager->errors;
944 return -1;
945 } elseif (empty($reshook)) {
946 // Clean parameters
947 $journal_data = is_array($journal_data) ? $journal_data : array();
948
949 // CSV header line
950 $header = array();
951 if ($this->nature == 4) {
952 $header = array(
953 $langs->transnoentitiesnoconv("BankId"),
954 $langs->transnoentitiesnoconv("Date"),
955 $langs->transnoentitiesnoconv("PaymentMode"),
956 $langs->transnoentitiesnoconv("AccountAccounting"),
957 $langs->transnoentitiesnoconv("LedgerAccount"),
958 $langs->transnoentitiesnoconv("SubledgerAccount"),
959 $langs->transnoentitiesnoconv("Label"),
960 $langs->transnoentitiesnoconv("AccountingDebit"),
961 $langs->transnoentitiesnoconv("AccountingCredit"),
962 $langs->transnoentitiesnoconv("Journal"),
963 $langs->transnoentitiesnoconv("Note"),
964 );
965 } elseif ($this->nature == 5) {
966 $header = array(
967 $langs->transnoentitiesnoconv("Date"),
968 $langs->transnoentitiesnoconv("Piece"),
969 $langs->transnoentitiesnoconv("AccountAccounting"),
970 $langs->transnoentitiesnoconv("LabelOperation"),
971 $langs->transnoentitiesnoconv("AccountingDebit"),
972 $langs->transnoentitiesnoconv("AccountingCredit"),
973 );
974 } elseif ($this->nature == 1) {
975 $header = array(
976 $langs->transnoentitiesnoconv("Date"),
977 $langs->transnoentitiesnoconv("Piece"),
978 $langs->transnoentitiesnoconv("AccountAccounting"),
979 $langs->transnoentitiesnoconv("LabelOperation"),
980 $langs->transnoentitiesnoconv("AccountingDebit"),
981 $langs->transnoentitiesnoconv("AccountingCredit"),
982 );
983 }
984
985 if (!empty($header)) {
986 $out .= '"' . implode('"' . $sep . '"', $header) . '"' . "\n";
987 }
988 foreach ($journal_data as $element_id => $element) {
989 foreach ($element['blocks'] as $lines) {
990 foreach ($lines as $line) {
991 $out .= '"' . implode('"' . $sep . '"', $line) . '"' . "\n";
992 }
993 }
994 }
995 }
996
997 return $out;
998 }
999
1006 public function getAccountingAccountInfos($account)
1007 {
1008 if (!isset(self::$accounting_account_cached[$account])) {
1009 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
1010 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php';
1011 $accountingaccount = new AccountingAccount($this->db);
1012 $result = $accountingaccount->fetch(null, $account, true);
1013 if ($result > 0) {
1014 self::$accounting_account_cached[$account] = array(
1015 'found' => true,
1016 'label' => $accountingaccount->label,
1017 'code_formatted_1' => length_accounta(html_entity_decode($account)),
1018 'label_formatted_1' => mb_convert_encoding(dol_trunc($accountingaccount->label, 32), 'ISO-8859-1'),
1019 'label_formatted_2' => dol_trunc($accountingaccount->label, 32),
1020 );
1021 } else {
1022 self::$accounting_account_cached[$account] = array(
1023 'found' => false,
1024 'label' => '',
1025 'code_formatted_1' => length_accounta(html_entity_decode($account)),
1026 'label_formatted_1' => '',
1027 'label_formatted_2' => '',
1028 );
1029 }
1030 }
1031
1032 return self::$accounting_account_cached[$account];
1033 }
1034}
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
$object ref
Definition info.php:79
Class to manage accounting accounts.
Class to manage accounting journals.
fetchAll($sortorder='', $sortfield='', $limit=0, $offset=0, array $filter=array(), $filtermode='AND')
Load object in memory from the database.
writeIntoBookkeeping(User $user, &$journal_data=array(), $max_nb_errors=10)
Write bookkeeping.
getData(User $user, $type='view', $date_start=null, $date_end=null, $in_bookkeeping='notyet')
Get journal data.
exportCsv(&$journal_data=array(), $search_date_end=0, $sep='')
Export journal CSV ISO and not UTF8 !
getNomUrl($withpicto=0, $withlabel=0, $nourl=0, $moretitle='', $notooltip=0)
Return clickable name (with picto eventually)
LibType($nature, $mode=0)
Return type of an accounting journal.
getAccountingAccountInfos($account)
Get accounting account infos.
fetch($rowid=null, $journal_code=null)
Load an object from database.
getAssetData(User $user, $type='view', $date_start=null, $date_end=null, $in_bookkeeping='notyet')
Get asset data for various journal.
getLibType($mode=0)
Return the label of the status.
Class for AssetAccountancyCodes.
Class for Asset.
Class to manage Ledger (General Ledger and Subledger)
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage Dolibarr users.
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=false, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_trunc($string, $size=40, $trunc='right', $stringencoding='UTF-8', $nodot=0, $display=0)
Truncate a string to a particular length adding '…' if string larger than length.
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.
publicphonebutton2 phonegreen basiclayout basiclayout TotalHT VATCode TotalVAT TotalLT1 TotalLT2 TotalTTC TotalHT clearboth nowraponall right right takeposterminal SELECT e rowid
Definition invoice.php:1907