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