dolibarr 18.0.6
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 static public $accounting_account_cached = array();
88
92 static public $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 (!empty($conf->global->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 != 2 && !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)) $type = 'view';
390 if (empty($in_bookkeeping)) $in_bookkeeping = 'notyet';
391
392 $data = array();
393
394 $hookmanager->initHooks(array('accountingjournaldao'));
395 $parameters = array('data' => &$data, 'user' => $user, 'type' => $type, 'date_start' => $date_start, 'date_end' => $date_end, 'in_bookkeeping' => $in_bookkeeping);
396 $reshook = $hookmanager->executeHooks('getData', $parameters, $this); // Note that $action and $object may have been
397 if ($reshook < 0) {
398 $this->error = $hookmanager->error;
399 $this->errors = $hookmanager->errors;
400 return -1;
401 } elseif (empty($reshook)) {
402 switch ($this->nature) {
403 case 1: // Various Journal
404 $data = $this->getAssetData($user, $type, $date_start, $date_end, $in_bookkeeping);
405 break;
406 // case 2: // Sells Journal
407 // case 3: // Purchases Journal
408 // case 4: // Bank Journal
409 // case 5: // Expense reports Journal
410 // case 8: // Inventory Journal
411 // case 9: // hasnew Journal
412 }
413 }
414
415 return $data;
416 }
417
428 public function getAssetData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet')
429 {
430 global $conf, $langs;
431
432 if (!isModEnabled('asset')) {
433 return array();
434 }
435
436 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
437 require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
438 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
439 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
440
441 $langs->loadLangs(array("assets"));
442
443 // Clean parameters
444 if (empty($type)) {
445 $type = 'view';
446 }
447 if (empty($in_bookkeeping)) {
448 $in_bookkeeping = 'notyet';
449 }
450
451 $sql = "";
452 $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";
453 $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";
454 $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";
455 $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation as ad";
456 $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "asset as a ON a.rowid = ad.fk_asset";
457 $sql .= " WHERE a.entity IN (" . getEntity('asset', 0) . ')'; // We don't share object for accountancy, we use source object sharing
458 if ($in_bookkeeping == 'already') {
459 $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')";
460 } elseif ($in_bookkeeping == 'notyet') {
461 $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')";
462 }
463 $sql .= " AND ad.ref != ''"; // not reversal lines
464 if ($date_start && $date_end) {
465 $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($date_start) . "' AND ad.depreciation_date <= '" . $this->db->idate($date_end) . "'";
466 }
467 // Define begin binding date
468 if (!empty($conf->global->ACCOUNTING_DATE_START_BINDING)) {
469 $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($conf->global->ACCOUNTING_DATE_START_BINDING) . "'";
470 }
471 $sql .= " ORDER BY ad.depreciation_date";
472
473 dol_syslog(__METHOD__, LOG_DEBUG);
474 $resql = $this->db->query($sql);
475 if (!$resql) {
476 $this->errors[] = $this->db->lasterror();
477 return -1;
478 }
479
480 $pre_data = array(
481 'elements' => array(),
482 );
483 while ($obj = $this->db->fetch_object($resql)) {
484 if (!isset($pre_data['elements'][$obj->rowid])) {
485 $pre_data['elements'][$obj->rowid] = array(
486 'ref' => $obj->asset_ref,
487 'label' => $obj->asset_label,
488 'acquisition_value_ht' => $obj->asset_acquisition_value_ht,
489 'depreciation' => array(),
490 );
491
492 // Disposal infos
493 if (isset($obj->asset_disposal_date)) {
494 $pre_data['elements'][$obj->rowid]['disposal'] = array(
495 'date' => $this->db->jdate($obj->asset_disposal_date),
496 'amount' => $obj->asset_disposal_amount_ht,
497 'subject_to_vat' => !empty($obj->asset_disposal_subject_to_vat),
498 );
499 }
500 }
501
502 $compta_debit = empty($obj->accountancy_code_debit) ? 'NotDefined' : $obj->accountancy_code_debit;
503 $compta_credit = empty($obj->accountancy_code_credit) ? 'NotDefined' : $obj->accountancy_code_credit;
504
505 $pre_data['elements'][$obj->rowid]['depreciation'][$obj->depreciation_id] = array(
506 'date' => $this->db->jdate($obj->depreciation_date),
507 'ref' => $obj->depreciation_ref,
508 'lines' => array(
509 $compta_debit => -$obj->depreciation_ht,
510 $compta_credit => $obj->depreciation_ht,
511 ),
512 );
513 }
514
515 $disposal_ref = $langs->transnoentitiesnoconv('AssetDisposal');
516 $journal = $this->code;
517 $journal_label = $this->label;
518 $journal_label_formatted = $langs->transnoentities($journal_label);
519 $now = dol_now();
520
521 $element_static = new Asset($this->db);
522
523 $journal_data = array();
524 foreach ($pre_data['elements'] as $pre_data_id => $pre_data_info) {
525 $element_static->id = $pre_data_id;
526 $element_static->ref = (string) $pre_data_info["ref"];
527 $element_static->label = (string) $pre_data_info["label"];
528 $element_static->acquisition_value_ht = $pre_data_info["acquisition_value_ht"];
529 $element_link = $element_static->getNomUrl(1, 'with_label');
530
531 $element_name_formatted_0 = dol_trunc($element_static->label, 16);
532 $element_name_formatted_1 = utf8_decode(dol_trunc($element_static->label, 32));
533 $element_name_formatted_2 = utf8_decode(dol_trunc($element_static->label, 16));
534 $label_operation = $element_static->getNomUrl(0, 'label', 16);
535
536 $element = array(
537 'ref' => dol_trunc($element_static->ref, 16, 'right', 'UTF-8', 1),
538 'error' => $pre_data_info['error'],
539 'blocks' => array(),
540 );
541
542 // Depreciation lines
543 //--------------------
544 foreach ($pre_data_info['depreciation'] as $depreciation_id => $line) {
545 $depreciation_ref = $line["ref"];
546 $depreciation_date = $line["date"];
547 $depreciation_date_formatted = dol_print_date($depreciation_date, 'day');
548
549 // lines
550 $blocks = array();
551 foreach ($line['lines'] as $account => $mt) {
552 $account_infos = $this->getAccountingAccountInfos($account);
553
554 if ($type == 'view') {
555 $account_to_show = length_accounta($account);
556 if (($account_to_show == "") || $account_to_show == 'NotDefined') {
557 $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
558 }
559
560 $blocks[] = array(
561 'date' => $depreciation_date_formatted,
562 'piece' => $element_link,
563 'account_accounting' => $account_to_show,
564 'subledger_account' => '',
565 'label_operation' => $label_operation . ' - ' . $depreciation_ref,
566 'debit' => $mt < 0 ? price(-$mt) : '',
567 'credit' => $mt >= 0 ? price($mt) : '',
568 );
569 } elseif ($type == 'bookkeeping') {
570 if ($account_infos['found']) {
571 $blocks[] = array(
572 'doc_date' => $depreciation_date,
573 'date_lim_reglement' => '',
574 'doc_ref' => $element_static->ref,
575 'date_creation' => $now,
576 'doc_type' => 'asset',
577 'fk_doc' => $element_static->id,
578 'fk_docdet' => $depreciation_id, // Useless, can be several lines that are source of this record to add
579 'thirdparty_code' => '',
580 'subledger_account' => '',
581 'subledger_label' => '',
582 'numero_compte' => $account,
583 'label_compte' => $account_infos['label'],
584 'label_operation' => $element_name_formatted_0 . ' - ' . $depreciation_ref,
585 'montant' => $mt,
586 'sens' => $mt < 0 ? 'D' : 'C',
587 'debit' => $mt < 0 ? -$mt : 0,
588 'credit' => $mt >= 0 ? $mt : 0,
589 'code_journal' => $journal,
590 'journal_label' => $journal_label_formatted,
591 'piece_num' => '',
592 'import_key' => '',
593 'fk_user_author' => $user->id,
594 'entity' => $conf->entity,
595 );
596 }
597 } else { // $type == 'csv'
598 $blocks[] = array(
599 $depreciation_date, // Date
600 $element_static->ref, // Piece
601 $account_infos['code_formatted_1'], // AccountAccounting
602 $element_name_formatted_0 . ' - ' . $depreciation_ref, // LabelOperation
603 $mt < 0 ? price(-$mt) : '', // Debit
604 $mt >= 0 ? price($mt) : '', // Credit
605 );
606 }
607 }
608 $element['blocks'][] = $blocks;
609 }
610
611 // Disposal line
612 //--------------------
613 if (!empty($pre_data_info['disposal'])) {
614 $disposal_date = $pre_data_info['disposal']['date'];
615
616 if ((!($date_start && $date_end) || ($date_start <= $disposal_date && $disposal_date <= $date_end)) &&
617 (empty($conf->global->ACCOUNTING_DATE_START_BINDING) || $conf->global->ACCOUNTING_DATE_START_BINDING <= $disposal_date)
618 ) {
619 $disposal_amount = $pre_data_info['disposal']['amount'];
620 $disposal_subject_to_vat = $pre_data_info['disposal']['subject_to_vat'];
621 $disposal_date_formatted = dol_print_date($disposal_date, 'day');
622 $disposal_vat = $conf->global->ASSET_DISPOSAL_VAT > 0 ? $conf->global->ASSET_DISPOSAL_VAT : 20;
623
624 // Get accountancy codes
625 //---------------------------
626 require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
627 $accountancy_codes = new AssetAccountancyCodes($this->db);
628 $result = $accountancy_codes->fetchAccountancyCodes($element_static->id);
629 if ($result < 0) {
630 $element['error'] = $accountancy_codes->errorsToString();
631 } else {
632 // Get last depreciation cumulative amount
633 $element_static->fetchDepreciationLines();
634 foreach ($element_static->depreciation_lines as $mode_key => $depreciation_lines) {
635 $accountancy_codes_list = $accountancy_codes->accountancy_codes[$mode_key];
636
637 if (!isset($accountancy_codes_list['value_asset_sold'])) {
638 continue;
639 }
640
641 $accountancy_code_value_asset_sold = empty($accountancy_codes_list['value_asset_sold']) ? 'NotDefined' : $accountancy_codes_list['value_asset_sold'];
642 $accountancy_code_depreciation_asset = empty($accountancy_codes_list['depreciation_asset']) ? 'NotDefined' : $accountancy_codes_list['depreciation_asset'];
643 $accountancy_code_asset = empty($accountancy_codes_list['asset']) ? 'NotDefined' : $accountancy_codes_list['asset'];
644 $accountancy_code_receivable_on_assignment = empty($accountancy_codes_list['receivable_on_assignment']) ? 'NotDefined' : $accountancy_codes_list['receivable_on_assignment'];
645 $accountancy_code_vat_collected = empty($accountancy_codes_list['vat_collected']) ? 'NotDefined' : $accountancy_codes_list['vat_collected'];
646 $accountancy_code_proceeds_from_sales = empty($accountancy_codes_list['proceeds_from_sales']) ? 'NotDefined' : $accountancy_codes_list['proceeds_from_sales'];
647
648 $last_cumulative_amount_ht = 0;
649 $depreciated_ids = array_keys($pre_data_info['depreciation']);
650 foreach ($depreciation_lines as $line) {
651 $last_cumulative_amount_ht = $line['cumulative_depreciation_ht'];
652 if (!in_array($line['id'], $depreciated_ids) && empty($line['bookkeeping']) && !empty($line['ref'])) {
653 break;
654 }
655 }
656
657 $lines = array();
658 $lines[0][$accountancy_code_value_asset_sold] = -($element_static->acquisition_value_ht - $last_cumulative_amount_ht);
659 $lines[0][$accountancy_code_depreciation_asset] = -$last_cumulative_amount_ht;
660 $lines[0][$accountancy_code_asset] = $element_static->acquisition_value_ht;
661
662 $disposal_amount_vat = $disposal_subject_to_vat ? (double) price2num($disposal_amount * $disposal_vat / 100, 'MT') : 0;
663 $lines[1][$accountancy_code_receivable_on_assignment] = -($disposal_amount + $disposal_amount_vat);
664 if ($disposal_subject_to_vat) $lines[1][$accountancy_code_vat_collected] = $disposal_amount_vat;
665 $lines[1][$accountancy_code_proceeds_from_sales] = $disposal_amount;
666
667 foreach ($lines as $lines_block) {
668 $blocks = array();
669 foreach ($lines_block as $account => $mt) {
670 $account_infos = $this->getAccountingAccountInfos($account);
671
672 if ($type == 'view') {
673 $account_to_show = length_accounta($account);
674 if (($account_to_show == "") || $account_to_show == 'NotDefined') {
675 $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
676 }
677
678 $blocks[] = array(
679 'date' => $disposal_date_formatted,
680 'piece' => $element_link,
681 'account_accounting' => $account_to_show,
682 'subledger_account' => '',
683 'label_operation' => $label_operation . ' - ' . $disposal_ref,
684 'debit' => $mt < 0 ? price(-$mt) : '',
685 'credit' => $mt >= 0 ? price($mt) : '',
686 );
687 } elseif ($type == 'bookkeeping') {
688 if ($account_infos['found']) {
689 $blocks[] = array(
690 'doc_date' => $disposal_date,
691 'date_lim_reglement' => '',
692 'doc_ref' => $element_static->ref,
693 'date_creation' => $now,
694 'doc_type' => 'asset',
695 'fk_doc' => $element_static->id,
696 'fk_docdet' => 0, // Useless, can be several lines that are source of this record to add
697 'thirdparty_code' => '',
698 'subledger_account' => '',
699 'subledger_label' => '',
700 'numero_compte' => $account,
701 'label_compte' => $account_infos['label'],
702 'label_operation' => $element_name_formatted_0 . ' - ' . $disposal_ref,
703 'montant' => $mt,
704 'sens' => $mt < 0 ? 'D' : 'C',
705 'debit' => $mt < 0 ? -$mt : 0,
706 'credit' => $mt >= 0 ? $mt : 0,
707 'code_journal' => $journal,
708 'journal_label' => $journal_label_formatted,
709 'piece_num' => '',
710 'import_key' => '',
711 'fk_user_author' => $user->id,
712 'entity' => $conf->entity,
713 );
714 }
715 } else { // $type == 'csv'
716 $blocks[] = array(
717 $disposal_date, // Date
718 $element_static->ref, // Piece
719 $account_infos['code_formatted_1'], // AccountAccounting
720 $element_name_formatted_0 . ' - ' . $disposal_ref, // LabelOperation
721 $mt < 0 ? price(-$mt) : '', // Debit
722 $mt >= 0 ? price($mt) : '', // Credit
723 );
724 }
725 }
726 $element['blocks'][] = $blocks;
727 }
728 }
729 }
730 }
731 }
732
733 $journal_data[(int) $pre_data_id] = $element;
734 }
735 unset($pre_data);
736
737 return $journal_data;
738 }
739
783 public function writeIntoBookkeeping(User $user, &$journal_data = array(), $max_nb_errors = 10)
784 {
785 global $conf, $langs, $hookmanager;
786 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php';
787
788 $error = 0;
789
790 $hookmanager->initHooks(array('accountingjournaldao'));
791 $parameters = array('journal_data' => &$journal_data);
792 $reshook = $hookmanager->executeHooks('writeBookkeeping', $parameters, $this); // Note that $action and $object may have been
793 if ($reshook < 0) {
794 $this->error = $hookmanager->error;
795 $this->errors = $hookmanager->errors;
796 return -1;
797 } elseif (empty($reshook)) {
798 // Clean parameters
799 $journal_data = is_array($journal_data) ? $journal_data : array();
800
801 foreach ($journal_data as $element_id => $element) {
802 $error_for_line = 0;
803 $total_credit = 0;
804 $total_debit = 0;
805
806 $this->db->begin();
807
808 if ($element['error'] == 'somelinesarenotbound') {
809 $error++;
810 $error_for_line++;
811 $this->errors[] = $langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $element['ref']);
812 }
813
814 if (!$error_for_line) {
815 foreach ($element['blocks'] as $lines) {
816 foreach ($lines as $line) {
817 $bookkeeping = new BookKeeping($this->db);
818 $bookkeeping->doc_date = $line['doc_date'];
819 $bookkeeping->date_lim_reglement = $line['date_lim_reglement'];
820 $bookkeeping->doc_ref = $line['doc_ref'];
821 $bookkeeping->date_creation = $line['date_creation']; // not used
822 $bookkeeping->doc_type = $line['doc_type'];
823 $bookkeeping->fk_doc = $line['fk_doc'];
824 $bookkeeping->fk_docdet = $line['fk_docdet'];
825 $bookkeeping->thirdparty_code = $line['thirdparty_code'];
826 $bookkeeping->subledger_account = $line['subledger_account'];
827 $bookkeeping->subledger_label = $line['subledger_label'];
828 $bookkeeping->numero_compte = $line['numero_compte'];
829 $bookkeeping->label_compte = $line['label_compte'];
830 $bookkeeping->label_operation = $line['label_operation'];
831 $bookkeeping->montant = $line['montant'];
832 $bookkeeping->sens = $line['sens'];
833 $bookkeeping->debit = $line['debit'];
834 $bookkeeping->credit = $line['credit'];
835 $bookkeeping->code_journal = $line['code_journal'];
836 $bookkeeping->journal_label = $line['journal_label'];
837 $bookkeeping->piece_num = $line['piece_num'];
838 $bookkeeping->import_key = $line['import_key'];
839 $bookkeeping->fk_user_author = $user->id;
840 $bookkeeping->entity = $conf->entity;
841
842 $total_debit += $bookkeeping->debit;
843 $total_credit += $bookkeeping->credit;
844
845 $result = $bookkeeping->create($user);
846 if ($result < 0) {
847 if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
848 $error++;
849 $error_for_line++;
850 $journal_data[$element_id]['error'] = 'alreadyjournalized';
851 } else {
852 $error++;
853 $error_for_line++;
854 $journal_data[$element_id]['error'] = 'other';
855 $this->errors[] = $bookkeeping->errorsToString();
856 }
857 }
858 //
859 // if (!$error_for_line && isModEnabled('asset') && $this->nature == 1 && $bookkeeping->fk_doc > 0) {
860 // // Set last cumulative depreciation
861 // require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
862 // $asset = new Asset($this->db);
863 // $result = $asset->setLastCumulativeDepreciation($bookkeeping->fk_doc);
864 // if ($result < 0) {
865 // $error++;
866 // $error_for_line++;
867 // $journal_data[$element_id]['error'] = 'other';
868 // $this->errors[] = $asset->errorsToString();
869 // }
870 // }
871 }
872
873 if ($error_for_line) {
874 break;
875 }
876 }
877 }
878
879 // Protection against a bug on lines before
880 if (!$error_for_line && (price2num($total_debit, 'MT') != price2num($total_credit, 'MT'))) {
881 $error++;
882 $error_for_line++;
883 $journal_data[$element_id]['error'] = 'amountsnotbalanced';
884 $this->errors[] = 'Try to insert a non balanced transaction in book for ' . $element['blocks'] . '. Canceled. Surely a bug.';
885 }
886
887 if (!$error_for_line) {
888 $this->db->commit();
889 } else {
890 $this->db->rollback();
891
892 if ($error >= $max_nb_errors) {
893 $this->errors[] = $langs->trans("ErrorTooManyErrorsProcessStopped");
894 break; // Break in the foreach
895 }
896 }
897 }
898 }
899
900 return $error ? -$error : 1;
901 }
902
924 public function exportCsv(&$journal_data = array(), $search_date_end = 0, $sep = '')
925 {
926 global $conf, $langs, $hookmanager;
927
928 if (empty($sep)) $sep = $conf->global->ACCOUNTING_EXPORT_SEPARATORCSV;
929 $out = '';
930
931 // Hook
932 $hookmanager->initHooks(array('accountingjournaldao'));
933 $parameters = array('journal_data' => &$journal_data, 'search_date_end' => &$search_date_end, 'sep' => &$sep, 'out' => &$out);
934 $reshook = $hookmanager->executeHooks('exportCsv', $parameters, $this); // Note that $action and $object may have been
935 if ($reshook < 0) {
936 $this->error = $hookmanager->error;
937 $this->errors = $hookmanager->errors;
938 return -1;
939 } elseif (empty($reshook)) {
940 // Clean parameters
941 $journal_data = is_array($journal_data) ? $journal_data : array();
942
943 // CSV header line
944 $header = array();
945 if ($this->nature == 4) {
946 $header = array(
947 $langs->transnoentitiesnoconv("BankId"),
948 $langs->transnoentitiesnoconv("Date"),
949 $langs->transnoentitiesnoconv("PaymentMode"),
950 $langs->transnoentitiesnoconv("AccountAccounting"),
951 $langs->transnoentitiesnoconv("LedgerAccount"),
952 $langs->transnoentitiesnoconv("SubledgerAccount"),
953 $langs->transnoentitiesnoconv("Label"),
954 $langs->transnoentitiesnoconv("AccountingDebit"),
955 $langs->transnoentitiesnoconv("AccountingCredit"),
956 $langs->transnoentitiesnoconv("Journal"),
957 $langs->transnoentitiesnoconv("Note"),
958 );
959 } elseif ($this->nature == 5) {
960 $header = array(
961 $langs->transnoentitiesnoconv("Date"),
962 $langs->transnoentitiesnoconv("Piece"),
963 $langs->transnoentitiesnoconv("AccountAccounting"),
964 $langs->transnoentitiesnoconv("LabelOperation"),
965 $langs->transnoentitiesnoconv("AccountingDebit"),
966 $langs->transnoentitiesnoconv("AccountingCredit"),
967 );
968 } elseif ($this->nature == 1) {
969 $header = array(
970 $langs->transnoentitiesnoconv("Date"),
971 $langs->transnoentitiesnoconv("Piece"),
972 $langs->transnoentitiesnoconv("AccountAccounting"),
973 $langs->transnoentitiesnoconv("LabelOperation"),
974 $langs->transnoentitiesnoconv("AccountingDebit"),
975 $langs->transnoentitiesnoconv("AccountingCredit"),
976 );
977 }
978
979 if (!empty($header)) $out .= '"' . implode('"' . $sep . '"', $header) . '"' . "\n";
980 foreach ($journal_data as $element_id => $element) {
981 foreach ($element['blocks'] as $lines) {
982 foreach ($lines as $line) {
983 $out .= '"' . implode('"' . $sep . '"', $line) . '"' . "\n";
984 }
985 }
986 }
987 }
988
989 return $out;
990 }
991
998 public function getAccountingAccountInfos($account)
999 {
1000 if (!isset(self::$accounting_account_cached[$account])) {
1001 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
1002 require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php';
1003 $accountingaccount = new AccountingAccount($this->db);
1004 $result = $accountingaccount->fetch(null, $account, true);
1005 if ($result > 0) {
1006 self::$accounting_account_cached[$account] = array(
1007 'found' => true,
1008 'label' => $accountingaccount->label,
1009 'code_formatted_1' => length_accounta(html_entity_decode($account)),
1010 'label_formatted_1' => utf8_decode(dol_trunc($accountingaccount->label, 32)),
1011 'label_formatted_2' => dol_trunc($accountingaccount->label, 32),
1012 );
1013 } else {
1014 self::$accounting_account_cached[$account] = array(
1015 'found' => false,
1016 'label' => '',
1017 'code_formatted_1' => length_accounta(html_entity_decode($account)),
1018 'label_formatted_1' => '',
1019 'label_formatted_2' => '',
1020 );
1021 }
1022 }
1023
1024 return self::$accounting_account_cached[$account];
1025 }
1026}
length_accounta($accounta)
Return Auxiliary accounting account of thirdparties with defined length.
$object ref
Definition info.php:78
Class to manage accounting accounts.
Class to manage accounting accounts.
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 clicable 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.
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.
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:1632