dolibarr  20.0.0-beta
accountingjournal.class.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2017-2022 OpenDSI <support@open-dsi.fr>
3  * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
4  * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <https://www.gnu.org/licenses/>.
18  */
19 
30 {
34  public $element = 'accounting_journal';
35 
39  public $table_element = 'accounting_journal';
40 
44  public $fk_element = '';
45 
49  public $picto = 'generic';
50 
54  public $rowid;
55 
59  public $code;
60 
64  public $label;
65 
69  public $nature;
70 
74  public $active;
75 
79  public static $accounting_account_cached = array();
80 
84  public static $nature_maps = array(
85  1 => 'variousoperations',
86  2 => 'sells',
87  3 => 'purchases',
88  4 => 'bank',
89  5 => 'expensereports',
90  8 => 'inventories',
91  9 => 'hasnew',
92  );
93 
99  public function __construct($db)
100  {
101  $this->db = $db;
102 
103  $this->ismultientitymanaged = 0;
104  }
105 
113  public function fetch($rowid = null, $journal_code = null)
114  {
115  global $conf;
116 
117  if ($rowid || $journal_code) {
118  $sql = "SELECT rowid, code, label, nature, active";
119  $sql .= " FROM ".MAIN_DB_PREFIX."accounting_journal";
120  $sql .= " WHERE";
121  if ($rowid) {
122  $sql .= " rowid = ".((int) $rowid);
123  } elseif ($journal_code) {
124  $sql .= " code = '".$this->db->escape($journal_code)."'";
125  $sql .= " AND entity = ".$conf->entity;
126  }
127 
128  dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
129  $result = $this->db->query($sql);
130  if ($result) {
131  $obj = $this->db->fetch_object($result);
132 
133  if ($obj) {
134  $this->id = $obj->rowid;
135  $this->rowid = $obj->rowid;
136 
137  $this->code = $obj->code;
138  $this->ref = $obj->code;
139  $this->label = $obj->label;
140  $this->nature = $obj->nature;
141  $this->active = $obj->active;
142 
143  return $this->id;
144  } else {
145  return 0;
146  }
147  } else {
148  $this->error = "Error ".$this->db->lasterror();
149  $this->errors[] = "Error ".$this->db->lasterror();
150  }
151  }
152  return -1;
153  }
154 
165  public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0)
166  {
167  global $langs, $conf, $hookmanager;
168 
169  if (!empty($conf->dol_no_mouse_hover)) {
170  $notooltip = 1; // Force disable tooltips
171  }
172 
173  $result = '';
174 
175  $url = DOL_URL_ROOT.'/accountancy/admin/journals_list.php?id=35';
176 
177  $label = '<u>'.$langs->trans("ShowAccountingJournal").'</u>';
178  if (!empty($this->code)) {
179  $label .= '<br><b>'.$langs->trans('Code').':</b> '.$this->code;
180  }
181  if (!empty($this->label)) {
182  $label .= '<br><b>'.$langs->trans('Label').':</b> '.$langs->transnoentities($this->label);
183  }
184  if ($moretitle) {
185  $label .= ' - '.$moretitle;
186  }
187 
188  $linkclose = '';
189  if (empty($notooltip)) {
190  if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
191  $label = $langs->trans("ShowAccountingJournal");
192  $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
193  }
194  $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
195  $linkclose .= ' class="classfortooltip"';
196  }
197 
198  $linkstart = '<a href="'.$url.'"';
199  $linkstart .= $linkclose.'>';
200  $linkend = '</a>';
201 
202  if ($nourl) {
203  $linkstart = '';
204  $linkclose = '';
205  $linkend = '';
206  }
207 
208  $label_link = $this->code;
209  if ($withlabel == 1 && !empty($this->label)) {
210  $label_link .= ' - '.($nourl ? '<span class="opacitymedium">' : '').$langs->transnoentities($this->label).($nourl ? '</span>' : '');
211  }
212  if ($withlabel == 2 && !empty($this->nature)) {
213  $key = $langs->trans("AccountingJournalType".$this->nature);
214  $transferlabel = ($this->nature && $key != "AccountingJournalType".strtoupper($langs->trans($this->nature)) ? $key : $this->label);
215  $label_link .= ' - '.($nourl ? '<span class="opacitymedium">' : '').$transferlabel.($nourl ? '</span>' : '');
216  }
217 
218  $result .= $linkstart;
219  if ($withpicto) {
220  $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);
221  }
222  if ($withpicto != 2) {
223  $result .= $label_link;
224  }
225  $result .= $linkend;
226 
227  global $action;
228  $hookmanager->initHooks(array('accountingjournaldao'));
229  $parameters = array('id' => $this->id, 'getnomurl' => &$result);
230  $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
231  if ($reshook > 0) {
232  $result = $hookmanager->resPrint;
233  } else {
234  $result .= $hookmanager->resPrint;
235  }
236  return $result;
237  }
238 
245  public function getLibType($mode = 0)
246  {
247  return $this->LibType($this->nature, $mode);
248  }
249 
250  // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
258  public function LibType($nature, $mode = 0)
259  {
260  // phpcs:enable
261  global $langs;
262 
263  $langs->loadLangs(array("accountancy"));
264 
265  if ($mode == 0) {
266  $prefix = '';
267  if ($nature == 9) {
268  return $langs->trans('AccountingJournalType9');
269  } elseif ($nature == 5) {
270  return $langs->trans('AccountingJournalType5');
271  } elseif ($nature == 4) {
272  return $langs->trans('AccountingJournalType4');
273  } elseif ($nature == 3) {
274  return $langs->trans('AccountingJournalType3');
275  } elseif ($nature == 2) {
276  return $langs->trans('AccountingJournalType2');
277  } elseif ($nature == 1) {
278  return $langs->trans('AccountingJournalType1');
279  }
280  } elseif ($mode == 1) {
281  if ($nature == 9) {
282  return $langs->trans('AccountingJournalType9');
283  } elseif ($nature == 5) {
284  return $langs->trans('AccountingJournalType5');
285  } elseif ($nature == 4) {
286  return $langs->trans('AccountingJournalType4');
287  } elseif ($nature == 3) {
288  return $langs->trans('AccountingJournalType3');
289  } elseif ($nature == 2) {
290  return $langs->trans('AccountingJournalType2');
291  } elseif ($nature == 1) {
292  return $langs->trans('AccountingJournalType1');
293  }
294  }
295  return "";
296  }
297 
298 
309  public function getData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet')
310  {
311  global $hookmanager;
312 
313  // Clean parameters
314  if (empty($type)) {
315  $type = 'view';
316  }
317  if (empty($in_bookkeeping)) {
318  $in_bookkeeping = 'notyet';
319  }
320 
321  $data = array();
322 
323  $hookmanager->initHooks(array('accountingjournaldao'));
324  $parameters = array('data' => &$data, 'user' => $user, 'type' => $type, 'date_start' => $date_start, 'date_end' => $date_end, 'in_bookkeeping' => $in_bookkeeping);
325  $reshook = $hookmanager->executeHooks('getData', $parameters, $this); // Note that $action and $object may have been
326  if ($reshook < 0) {
327  $this->error = $hookmanager->error;
328  $this->errors = $hookmanager->errors;
329  return -1;
330  } elseif (empty($reshook)) {
331  switch ($this->nature) {
332  case 1: // Various Journal
333  $data = $this->getAssetData($user, $type, $date_start, $date_end, $in_bookkeeping);
334  break;
335  // case 2: // Sells Journal
336  // case 3: // Purchases Journal
337  // case 4: // Bank Journal
338  // case 5: // Expense reports Journal
339  // case 8: // Inventory Journal
340  // case 9: // hasnew Journal
341  }
342  }
343 
344  return $data;
345  }
346 
357  public function getAssetData(User $user, $type = 'view', $date_start = null, $date_end = null, $in_bookkeeping = 'notyet')
358  {
359  global $conf, $langs;
360 
361  if (!isModEnabled('asset')) {
362  return array();
363  }
364 
365  require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
366  require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
367  require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
368  require_once DOL_DOCUMENT_ROOT . '/asset/class/assetdepreciationoptions.class.php';
369 
370  $langs->loadLangs(array("assets"));
371 
372  // Clean parameters
373  if (empty($type)) {
374  $type = 'view';
375  }
376  if (empty($in_bookkeeping)) {
377  $in_bookkeeping = 'notyet';
378  }
379 
380  $sql = "";
381  $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";
382  $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";
383  $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";
384  $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation as ad";
385  $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "asset as a ON a.rowid = ad.fk_asset";
386  $sql .= " WHERE a.entity IN (" . getEntity('asset', 0) . ')'; // We don't share object for accountancy, we use source object sharing
387  if ($in_bookkeeping == 'already') {
388  $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')";
389  } elseif ($in_bookkeeping == 'notyet') {
390  $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')";
391  }
392  $sql .= " AND ad.ref != ''"; // not reversal lines
393  if ($date_start && $date_end) {
394  $sql .= " AND ad.depreciation_date >= '" . $this->db->idate($date_start) . "' AND ad.depreciation_date <= '" . $this->db->idate($date_end) . "'";
395  }
396  // Define begin binding date
397  if (getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) {
398  $sql .= " AND ad.depreciation_date >= '" . $this->db->idate(getDolGlobalString('ACCOUNTING_DATE_START_BINDING')) . "'";
399  }
400  $sql .= " ORDER BY ad.depreciation_date";
401 
402  dol_syslog(__METHOD__, LOG_DEBUG);
403  $resql = $this->db->query($sql);
404  if (!$resql) {
405  $this->errors[] = $this->db->lasterror();
406  return -1;
407  }
408 
409  $pre_data = array(
410  'elements' => array(),
411  );
412  while ($obj = $this->db->fetch_object($resql)) {
413  if (!isset($pre_data['elements'][$obj->rowid])) {
414  $pre_data['elements'][$obj->rowid] = array(
415  'ref' => $obj->asset_ref,
416  'label' => $obj->asset_label,
417  'acquisition_value_ht' => $obj->asset_acquisition_value_ht,
418  'depreciation' => array(),
419  );
420 
421  // Disposal infos
422  if (isset($obj->asset_disposal_date)) {
423  $pre_data['elements'][$obj->rowid]['disposal'] = array(
424  'date' => $this->db->jdate($obj->asset_disposal_date),
425  'amount' => $obj->asset_disposal_amount_ht,
426  'subject_to_vat' => !empty($obj->asset_disposal_subject_to_vat),
427  );
428  }
429  }
430 
431  $compta_debit = empty($obj->accountancy_code_debit) ? 'NotDefined' : $obj->accountancy_code_debit;
432  $compta_credit = empty($obj->accountancy_code_credit) ? 'NotDefined' : $obj->accountancy_code_credit;
433 
434  $pre_data['elements'][$obj->rowid]['depreciation'][$obj->depreciation_id] = array(
435  'date' => $this->db->jdate($obj->depreciation_date),
436  'ref' => $obj->depreciation_ref,
437  'lines' => array(
438  $compta_debit => -$obj->depreciation_ht,
439  $compta_credit => $obj->depreciation_ht,
440  ),
441  );
442  }
443 
444  $disposal_ref = $langs->transnoentitiesnoconv('AssetDisposal');
445  $journal = $this->code;
446  $journal_label = $this->label;
447  $journal_label_formatted = $langs->transnoentities($journal_label);
448  $now = dol_now();
449 
450  $element_static = new Asset($this->db);
451 
452  $journal_data = array();
453  foreach ($pre_data['elements'] as $pre_data_id => $pre_data_info) {
454  $element_static->id = $pre_data_id;
455  $element_static->ref = (string) $pre_data_info["ref"];
456  $element_static->label = (string) $pre_data_info["label"];
457  $element_static->acquisition_value_ht = $pre_data_info["acquisition_value_ht"];
458  $element_link = $element_static->getNomUrl(1, 'with_label');
459 
460  $element_name_formatted_0 = dol_trunc($element_static->label, 16);
461  $label_operation = $element_static->getNomUrl(0, 'label', 16);
462 
463  $element = array(
464  'ref' => dol_trunc($element_static->ref, 16, 'right', 'UTF-8', 1),
465  'error' => $pre_data_info['error'],
466  'blocks' => array(),
467  );
468 
469  // Depreciation lines
470  //--------------------
471  foreach ($pre_data_info['depreciation'] as $depreciation_id => $line) {
472  $depreciation_ref = $line["ref"];
473  $depreciation_date = $line["date"];
474  $depreciation_date_formatted = dol_print_date($depreciation_date, 'day');
475 
476  // lines
477  $blocks = array();
478  foreach ($line['lines'] as $account => $mt) {
479  $account_infos = $this->getAccountingAccountInfos($account);
480 
481  if ($type == 'view') {
482  $account_to_show = length_accounta($account);
483  if (($account_to_show == "") || $account_to_show == 'NotDefined') {
484  $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
485  }
486 
487  $blocks[] = array(
488  'date' => $depreciation_date_formatted,
489  'piece' => $element_link,
490  'account_accounting' => $account_to_show,
491  'subledger_account' => '',
492  'label_operation' => $label_operation . ' - ' . $depreciation_ref,
493  'debit' => $mt < 0 ? price(-$mt) : '',
494  'credit' => $mt >= 0 ? price($mt) : '',
495  );
496  } elseif ($type == 'bookkeeping') {
497  if ($account_infos['found']) {
498  $blocks[] = array(
499  'doc_date' => $depreciation_date,
500  'date_lim_reglement' => '',
501  'doc_ref' => $element_static->ref,
502  'date_creation' => $now,
503  'doc_type' => 'asset',
504  'fk_doc' => $element_static->id,
505  'fk_docdet' => $depreciation_id, // Useless, can be several lines that are source of this record to add
506  'thirdparty_code' => '',
507  'subledger_account' => '',
508  'subledger_label' => '',
509  'numero_compte' => $account,
510  'label_compte' => $account_infos['label'],
511  'label_operation' => $element_name_formatted_0 . ' - ' . $depreciation_ref,
512  'montant' => $mt,
513  'sens' => $mt < 0 ? 'D' : 'C',
514  'debit' => $mt < 0 ? -$mt : 0,
515  'credit' => $mt >= 0 ? $mt : 0,
516  'code_journal' => $journal,
517  'journal_label' => $journal_label_formatted,
518  'piece_num' => '',
519  'import_key' => '',
520  'fk_user_author' => $user->id,
521  'entity' => $conf->entity,
522  );
523  }
524  } else { // $type == 'csv'
525  $blocks[] = array(
526  $depreciation_date, // Date
527  $element_static->ref, // Piece
528  $account_infos['code_formatted_1'], // AccountAccounting
529  $element_name_formatted_0 . ' - ' . $depreciation_ref, // LabelOperation
530  $mt < 0 ? price(-$mt) : '', // Debit
531  $mt >= 0 ? price($mt) : '', // Credit
532  );
533  }
534  }
535  $element['blocks'][] = $blocks;
536  }
537 
538  // Disposal line
539  //--------------------
540  if (!empty($pre_data_info['disposal'])) {
541  $disposal_date = $pre_data_info['disposal']['date'];
542 
543  if ((!($date_start && $date_end) || ($date_start <= $disposal_date && $disposal_date <= $date_end)) &&
544  (!getDolGlobalString('ACCOUNTING_DATE_START_BINDING') || getDolGlobalInt('ACCOUNTING_DATE_START_BINDING') <= $disposal_date)
545  ) {
546  $disposal_amount = $pre_data_info['disposal']['amount'];
547  $disposal_subject_to_vat = $pre_data_info['disposal']['subject_to_vat'];
548  $disposal_date_formatted = dol_print_date($disposal_date, 'day');
549  $disposal_vat = getDolGlobalInt('ASSET_DISPOSAL_VAT') > 0 ? getDolGlobalInt('ASSET_DISPOSAL_VAT') : 20;
550 
551  // Get accountancy codes
552  //---------------------------
553  require_once DOL_DOCUMENT_ROOT . '/asset/class/assetaccountancycodes.class.php';
554  $accountancy_codes = new AssetAccountancyCodes($this->db);
555  $result = $accountancy_codes->fetchAccountancyCodes($element_static->id);
556  if ($result < 0) {
557  $element['error'] = $accountancy_codes->errorsToString();
558  } else {
559  // Get last depreciation cumulative amount
560  $element_static->fetchDepreciationLines();
561  foreach ($element_static->depreciation_lines as $mode_key => $depreciation_lines) {
562  $accountancy_codes_list = $accountancy_codes->accountancy_codes[$mode_key];
563 
564  if (!isset($accountancy_codes_list['value_asset_sold'])) {
565  continue;
566  }
567 
568  $accountancy_code_value_asset_sold = empty($accountancy_codes_list['value_asset_sold']) ? 'NotDefined' : $accountancy_codes_list['value_asset_sold'];
569  $accountancy_code_depreciation_asset = empty($accountancy_codes_list['depreciation_asset']) ? 'NotDefined' : $accountancy_codes_list['depreciation_asset'];
570  $accountancy_code_asset = empty($accountancy_codes_list['asset']) ? 'NotDefined' : $accountancy_codes_list['asset'];
571  $accountancy_code_receivable_on_assignment = empty($accountancy_codes_list['receivable_on_assignment']) ? 'NotDefined' : $accountancy_codes_list['receivable_on_assignment'];
572  $accountancy_code_vat_collected = empty($accountancy_codes_list['vat_collected']) ? 'NotDefined' : $accountancy_codes_list['vat_collected'];
573  $accountancy_code_proceeds_from_sales = empty($accountancy_codes_list['proceeds_from_sales']) ? 'NotDefined' : $accountancy_codes_list['proceeds_from_sales'];
574 
575  $last_cumulative_amount_ht = 0;
576  $depreciated_ids = array_keys($pre_data_info['depreciation']);
577  foreach ($depreciation_lines as $line) {
578  $last_cumulative_amount_ht = $line['cumulative_depreciation_ht'];
579  if (!in_array($line['id'], $depreciated_ids) && empty($line['bookkeeping']) && !empty($line['ref'])) {
580  break;
581  }
582  }
583 
584  $lines = array();
585  $lines[0][$accountancy_code_value_asset_sold] = -($element_static->acquisition_value_ht - $last_cumulative_amount_ht);
586  $lines[0][$accountancy_code_depreciation_asset] = -$last_cumulative_amount_ht;
587  $lines[0][$accountancy_code_asset] = $element_static->acquisition_value_ht;
588 
589  $disposal_amount_vat = $disposal_subject_to_vat ? (float) price2num($disposal_amount * $disposal_vat / 100, 'MT') : 0;
590  $lines[1][$accountancy_code_receivable_on_assignment] = -($disposal_amount + $disposal_amount_vat);
591  if ($disposal_subject_to_vat) {
592  $lines[1][$accountancy_code_vat_collected] = $disposal_amount_vat;
593  }
594  $lines[1][$accountancy_code_proceeds_from_sales] = $disposal_amount;
595 
596  foreach ($lines as $lines_block) {
597  $blocks = array();
598  foreach ($lines_block as $account => $mt) {
599  $account_infos = $this->getAccountingAccountInfos($account);
600 
601  if ($type == 'view') {
602  $account_to_show = length_accounta($account);
603  if (($account_to_show == "") || $account_to_show == 'NotDefined') {
604  $account_to_show = '<span class="error">' . $langs->trans("AssetInAccountNotDefined") . '</span>';
605  }
606 
607  $blocks[] = array(
608  'date' => $disposal_date_formatted,
609  'piece' => $element_link,
610  'account_accounting' => $account_to_show,
611  'subledger_account' => '',
612  'label_operation' => $label_operation . ' - ' . $disposal_ref,
613  'debit' => $mt < 0 ? price(-$mt) : '',
614  'credit' => $mt >= 0 ? price($mt) : '',
615  );
616  } elseif ($type == 'bookkeeping') {
617  if ($account_infos['found']) {
618  $blocks[] = array(
619  'doc_date' => $disposal_date,
620  'date_lim_reglement' => '',
621  'doc_ref' => $element_static->ref,
622  'date_creation' => $now,
623  'doc_type' => 'asset',
624  'fk_doc' => $element_static->id,
625  'fk_docdet' => 0, // Useless, can be several lines that are source of this record to add
626  'thirdparty_code' => '',
627  'subledger_account' => '',
628  'subledger_label' => '',
629  'numero_compte' => $account,
630  'label_compte' => $account_infos['label'],
631  'label_operation' => $element_name_formatted_0 . ' - ' . $disposal_ref,
632  'montant' => $mt,
633  'sens' => $mt < 0 ? 'D' : 'C',
634  'debit' => $mt < 0 ? -$mt : 0,
635  'credit' => $mt >= 0 ? $mt : 0,
636  'code_journal' => $journal,
637  'journal_label' => $journal_label_formatted,
638  'piece_num' => '',
639  'import_key' => '',
640  'fk_user_author' => $user->id,
641  'entity' => $conf->entity,
642  );
643  }
644  } else { // $type == 'csv'
645  $blocks[] = array(
646  $disposal_date, // Date
647  $element_static->ref, // Piece
648  $account_infos['code_formatted_1'], // AccountAccounting
649  $element_name_formatted_0 . ' - ' . $disposal_ref, // LabelOperation
650  $mt < 0 ? price(-$mt) : '', // Debit
651  $mt >= 0 ? price($mt) : '', // Credit
652  );
653  }
654  }
655  $element['blocks'][] = $blocks;
656  }
657  }
658  }
659  }
660  }
661 
662  $journal_data[(int) $pre_data_id] = $element;
663  }
664  unset($pre_data);
665 
666  return $journal_data;
667  }
668 
712  public function writeIntoBookkeeping(User $user, &$journal_data = array(), $max_nb_errors = 10)
713  {
714  global $conf, $langs, $hookmanager;
715  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/bookkeeping.class.php';
716 
717  $error = 0;
718 
719  $hookmanager->initHooks(array('accountingjournaldao'));
720  $parameters = array('journal_data' => &$journal_data);
721  $reshook = $hookmanager->executeHooks('writeBookkeeping', $parameters, $this); // Note that $action and $object may have been
722  if ($reshook < 0) {
723  $this->error = $hookmanager->error;
724  $this->errors = $hookmanager->errors;
725  return -1;
726  } elseif (empty($reshook)) {
727  // Clean parameters
728  $journal_data = is_array($journal_data) ? $journal_data : array();
729 
730  foreach ($journal_data as $element_id => $element) {
731  $error_for_line = 0;
732  $total_credit = 0;
733  $total_debit = 0;
734 
735  $this->db->begin();
736 
737  if ($element['error'] == 'somelinesarenotbound') {
738  $error++;
739  $error_for_line++;
740  $this->errors[] = $langs->trans('ErrorInvoiceContainsLinesNotYetBounded', $element['ref']);
741  }
742 
743  if (!$error_for_line) {
744  foreach ($element['blocks'] as $lines) {
745  foreach ($lines as $line) {
746  $bookkeeping = new BookKeeping($this->db);
747  $bookkeeping->doc_date = $line['doc_date'];
748  $bookkeeping->date_lim_reglement = $line['date_lim_reglement'];
749  $bookkeeping->doc_ref = $line['doc_ref'];
750  $bookkeeping->date_creation = $line['date_creation']; // not used
751  $bookkeeping->doc_type = $line['doc_type'];
752  $bookkeeping->fk_doc = $line['fk_doc'];
753  $bookkeeping->fk_docdet = $line['fk_docdet'];
754  $bookkeeping->thirdparty_code = $line['thirdparty_code'];
755  $bookkeeping->subledger_account = $line['subledger_account'];
756  $bookkeeping->subledger_label = $line['subledger_label'];
757  $bookkeeping->numero_compte = $line['numero_compte'];
758  $bookkeeping->label_compte = $line['label_compte'];
759  $bookkeeping->label_operation = $line['label_operation'];
760  $bookkeeping->montant = $line['montant'];
761  $bookkeeping->sens = $line['sens'];
762  $bookkeeping->debit = $line['debit'];
763  $bookkeeping->credit = $line['credit'];
764  $bookkeeping->code_journal = $line['code_journal'];
765  $bookkeeping->journal_label = $line['journal_label'];
766  $bookkeeping->piece_num = $line['piece_num'];
767  $bookkeeping->import_key = $line['import_key'];
768  $bookkeeping->fk_user_author = $user->id;
769  $bookkeeping->entity = $conf->entity;
770 
771  $total_debit += $bookkeeping->debit;
772  $total_credit += $bookkeeping->credit;
773 
774  $result = $bookkeeping->create($user);
775  if ($result < 0) {
776  if ($bookkeeping->error == 'BookkeepingRecordAlreadyExists') { // Already exists
777  $error++;
778  $error_for_line++;
779  $journal_data[$element_id]['error'] = 'alreadyjournalized';
780  } else {
781  $error++;
782  $error_for_line++;
783  $journal_data[$element_id]['error'] = 'other';
784  $this->errors[] = $bookkeeping->errorsToString();
785  }
786  }
787  //
788  // if (!$error_for_line && isModEnabled('asset') && $this->nature == 1 && $bookkeeping->fk_doc > 0) {
789  // // Set last cumulative depreciation
790  // require_once DOL_DOCUMENT_ROOT . '/asset/class/asset.class.php';
791  // $asset = new Asset($this->db);
792  // $result = $asset->setLastCumulativeDepreciation($bookkeeping->fk_doc);
793  // if ($result < 0) {
794  // $error++;
795  // $error_for_line++;
796  // $journal_data[$element_id]['error'] = 'other';
797  // $this->errors[] = $asset->errorsToString();
798  // }
799  // }
800  }
801 
802  if ($error_for_line) {
803  break;
804  }
805  }
806  }
807 
808  // Protection against a bug on lines before
809  if (!$error_for_line && (price2num($total_debit, 'MT') != price2num($total_credit, 'MT'))) {
810  $error++;
811  $error_for_line++;
812  $journal_data[$element_id]['error'] = 'amountsnotbalanced';
813  $this->errors[] = 'Try to insert a non balanced transaction in book for ' . $element['blocks'] . '. Canceled. Surely a bug.';
814  }
815 
816  if (!$error_for_line) {
817  $this->db->commit();
818  } else {
819  $this->db->rollback();
820 
821  if ($error >= $max_nb_errors) {
822  $this->errors[] = $langs->trans("ErrorTooManyErrorsProcessStopped");
823  break; // Break in the foreach
824  }
825  }
826  }
827  }
828 
829  return $error ? -$error : 1;
830  }
831 
853  public function exportCsv(&$journal_data = array(), $search_date_end = 0, $sep = '')
854  {
855  global $conf, $langs, $hookmanager;
856 
857  if (empty($sep)) {
858  $sep = getDolGlobalString('ACCOUNTING_EXPORT_SEPARATORCSV');
859  }
860  $out = '';
861 
862  // Hook
863  $hookmanager->initHooks(array('accountingjournaldao'));
864  $parameters = array('journal_data' => &$journal_data, 'search_date_end' => &$search_date_end, 'sep' => &$sep, 'out' => &$out);
865  $reshook = $hookmanager->executeHooks('exportCsv', $parameters, $this); // Note that $action and $object may have been
866  if ($reshook < 0) {
867  $this->error = $hookmanager->error;
868  $this->errors = $hookmanager->errors;
869  return -1;
870  } elseif (empty($reshook)) {
871  // Clean parameters
872  $journal_data = is_array($journal_data) ? $journal_data : array();
873 
874  // CSV header line
875  $header = array();
876  if ($this->nature == 4) {
877  $header = array(
878  $langs->transnoentitiesnoconv("BankId"),
879  $langs->transnoentitiesnoconv("Date"),
880  $langs->transnoentitiesnoconv("PaymentMode"),
881  $langs->transnoentitiesnoconv("AccountAccounting"),
882  $langs->transnoentitiesnoconv("LedgerAccount"),
883  $langs->transnoentitiesnoconv("SubledgerAccount"),
884  $langs->transnoentitiesnoconv("Label"),
885  $langs->transnoentitiesnoconv("AccountingDebit"),
886  $langs->transnoentitiesnoconv("AccountingCredit"),
887  $langs->transnoentitiesnoconv("Journal"),
888  $langs->transnoentitiesnoconv("Note"),
889  );
890  } elseif ($this->nature == 5) {
891  $header = array(
892  $langs->transnoentitiesnoconv("Date"),
893  $langs->transnoentitiesnoconv("Piece"),
894  $langs->transnoentitiesnoconv("AccountAccounting"),
895  $langs->transnoentitiesnoconv("LabelOperation"),
896  $langs->transnoentitiesnoconv("AccountingDebit"),
897  $langs->transnoentitiesnoconv("AccountingCredit"),
898  );
899  } elseif ($this->nature == 1) {
900  $header = array(
901  $langs->transnoentitiesnoconv("Date"),
902  $langs->transnoentitiesnoconv("Piece"),
903  $langs->transnoentitiesnoconv("AccountAccounting"),
904  $langs->transnoentitiesnoconv("LabelOperation"),
905  $langs->transnoentitiesnoconv("AccountingDebit"),
906  $langs->transnoentitiesnoconv("AccountingCredit"),
907  );
908  }
909 
910  if (!empty($header)) {
911  $out .= '"' . implode('"' . $sep . '"', $header) . '"' . "\n";
912  }
913  foreach ($journal_data as $element_id => $element) {
914  foreach ($element['blocks'] as $lines) {
915  foreach ($lines as $line) {
916  $out .= '"' . implode('"' . $sep . '"', $line) . '"' . "\n";
917  }
918  }
919  }
920  }
921 
922  return $out;
923  }
924 
931  public function getAccountingAccountInfos($account)
932  {
933  if (!isset(self::$accounting_account_cached[$account])) {
934  require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
935  require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingaccount.class.php';
936  $accountingaccount = new AccountingAccount($this->db);
937  $result = $accountingaccount->fetch(null, $account, true);
938  if ($result > 0) {
939  self::$accounting_account_cached[$account] = array(
940  'found' => true,
941  'label' => $accountingaccount->label,
942  'code_formatted_1' => length_accounta(html_entity_decode($account)),
943  'label_formatted_1' => mb_convert_encoding(dol_trunc($accountingaccount->label, 32), 'ISO-8859-1'),
944  'label_formatted_2' => dol_trunc($accountingaccount->label, 32),
945  );
946  } else {
947  self::$accounting_account_cached[$account] = array(
948  'found' => false,
949  'label' => '',
950  'code_formatted_1' => length_accounta(html_entity_decode($account)),
951  'label_formatted_1' => '',
952  'label_formatted_2' => '',
953  );
954  }
955  }
956 
957  return self::$accounting_account_cached[$account];
958  }
959 }
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.
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)
__construct($db)
Constructor.
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.
Definition: asset.class.php:33
Class to manage Ledger (General Ledger and Subledger)
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage Dolibarr users.
Definition: user.class.php:50
if(isModEnabled('invoice') && $user->hasRight('facture', 'lire')) if((isModEnabled('fournisseur') &&!getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD') && $user->hasRight("fournisseur", "facture", "lire"))||(isModEnabled('supplier_invoice') && $user->hasRight("supplier_invoice", "lire"))) if(isModEnabled('don') && $user->hasRight('don', 'lire')) if(isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire')) if(isModEnabled('invoice') &&isModEnabled('order') && $user->hasRight("commande", "lire") &&!getDolGlobalString('WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER')) $sql
Social contributions to pay.
Definition: index.php:745
print *****$script_file(".$version.") pid c cd cd cd description as p label as s rowid
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 '.
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_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
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.
isModEnabled($module)
Is Dolibarr module enabled.
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.
div float
Buy price without taxes.
Definition: style.css.php:960
print *****$script_file(".$version.") pid code
1: frais de port 2: ecotaxe 3: option line (when qty = 0)