dolibarr 22.0.5
accountingaccount.class.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
4 * Copyright (C) 2013-2021 Florian Henry <florian.henry@open-concept.pro>
5 * Copyright (C) 2014 Juanjo Menent <jmenent@2byte.es>
6 * Copyright (C) 2015 Ari Elbaz (elarifr) <github@accedinfo.com>
7 * Copyright (C) 2018-2024 Frédéric France <frederic.france@free.fr>
8 * Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
31require_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
32require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
33
38{
42 public $element = 'accounting_account';
43
47 public $table_element = 'accounting_account';
48
52 public $picto = 'billr';
53
58 public $restrictiononfksoc = 1;
59
63 public $db;
64
68 public $id;
69
73 public $rowid;
74
80 public $datec;
81
85 public $fk_pcg_version;
86
90 public $pcg_type;
91
95 public $account_number;
96
100 public $account_parent;
101
105 public $account_category;
106
110 public $account_category_label;
111
115 public $status;
116
120 public $label;
121
125 public $labelshort;
126
130 public $fk_user_author;
131
135 public $fk_user_modif;
136
140 public $active;
141
145 public $reconcilable;
146
150 private $accountingaccount_codetotid_cache = array();
151
152
153 const STATUS_ENABLED = 1;
154 const STATUS_DISABLED = 0;
155
156
162 public function __construct($db)
163 {
164 $this->db = $db;
165
166 $this->ismultientitymanaged = 1;
167 $this->next_prev_filter = "fk_pcg_version IN (SELECT pcg_version FROM ".$this->db->prefix()."accounting_system WHERE rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS')).")"; // Used to add a filter in Form::showrefnav method
168 }
169
179 public function fetch($rowid = 0, $account_number = null, $limittocurrentchart = 0, $limittoachartaccount = '')
180 {
181 global $conf;
182
183 if ($rowid || $account_number) {
184 $sql = "SELECT a.rowid as rowid, a.datec, a.tms, a.fk_pcg_version, a.pcg_type, a.account_number, a.account_parent, a.label, a.labelshort, a.fk_accounting_category, a.fk_user_author, a.fk_user_modif, a.active, a.reconcilable";
185 $sql .= ", ca.label as category_label";
186 $sql .= " FROM ".$this->db->prefix().$this->table_element." as a";
187 $sql .= " LEFT JOIN ".$this->db->prefix()."c_accounting_category as ca ON a.fk_accounting_category = ca.rowid";
188 $sql .= " WHERE";
189 if ($rowid) {
190 $sql .= " a.rowid = ".(int) $rowid;
191 } elseif ($account_number) {
192 $sql .= " a.account_number = '".$this->db->escape($account_number)."'";
193 $sql .= " AND a.entity = ".$conf->entity;
194 }
195 if (!empty($limittocurrentchart)) {
196 $sql .= ' AND a.fk_pcg_version IN (SELECT pcg_version FROM '.$this->db->prefix().'accounting_system WHERE rowid = '.((int) getDolGlobalInt('CHARTOFACCOUNTS')).')';
197 }
198 if (!empty($limittoachartaccount)) {
199 $sql .= " AND a.fk_pcg_version = '".$this->db->escape($limittoachartaccount)."'";
200 }
201
202 dol_syslog(get_class($this)."::fetch rowid=".$rowid." account_number=".$account_number, LOG_DEBUG);
203
204 $result = $this->db->query($sql);
205 if ($result) {
206 $obj = $this->db->fetch_object($result);
207
208 if ($obj) {
209 $this->id = $obj->rowid;
210 $this->rowid = $obj->rowid;
211 $this->ref = $obj->account_number;
212 $this->datec = $this->db->jdate($obj->datec);
213 $this->date_creation = $this->db->jdate($obj->datec);
214 $this->date_modification = $this->db->jdate($obj->tms);
215 //$this->tms = $this->datem;
216 $this->fk_pcg_version = $obj->fk_pcg_version;
217 $this->pcg_type = $obj->pcg_type;
218 $this->account_number = $obj->account_number;
219 $this->account_parent = $obj->account_parent;
220 $this->label = $obj->label;
221 $this->labelshort = $obj->labelshort;
222 $this->account_category = $obj->fk_accounting_category;
223 $this->account_category_label = $obj->category_label;
224 $this->fk_user_author = $obj->fk_user_author;
225 $this->fk_user_modif = $obj->fk_user_modif;
226 $this->active = $obj->active;
227 $this->status = $obj->active;
228 $this->reconcilable = $obj->reconcilable;
229
230 return $this->id;
231 } else {
232 return 0;
233 }
234 } else {
235 $this->error = "Error ".$this->db->lasterror();
236 $this->errors[] = "Error ".$this->db->lasterror();
237 }
238 }
239 return -1;
240 }
241
249 public function create($user, $notrigger = 0)
250 {
251 global $conf;
252 $error = 0;
253 $now = dol_now();
254
255 // Clean parameters
256 if (isset($this->fk_pcg_version)) {
257 $this->fk_pcg_version = trim($this->fk_pcg_version);
258 }
259 if (isset($this->pcg_type)) {
260 $this->pcg_type = trim($this->pcg_type);
261 }
262 if (isset($this->account_number)) {
263 $this->account_number = trim($this->account_number);
264 }
265 if (isset($this->label)) {
266 $this->label = trim($this->label);
267 }
268 if (isset($this->labelshort)) {
269 $this->labelshort = trim($this->labelshort);
270 }
271
272 if (empty($this->pcg_type) || $this->pcg_type == '-1') {
273 $this->pcg_type = 'XXXXXX';
274 }
275 // Check parameters
276 // Put here code to add control on parameters values
277
278 // Insert request
279 $sql = "INSERT INTO " . $this->db->prefix() . $this->table_element . " (";
280 $sql .= "datec";
281 $sql .= ", entity";
282 $sql .= ", fk_pcg_version";
283 $sql .= ", pcg_type";
284 $sql .= ", account_number";
285 $sql .= ", account_parent";
286 $sql .= ", label";
287 $sql .= ", labelshort";
288 $sql .= ", fk_accounting_category";
289 $sql .= ", fk_user_author";
290 $sql .= ", active";
291 $sql .= ", reconcilable";
292 $sql .= ") VALUES (";
293 $sql .= " '".$this->db->idate($now)."'";
294 $sql .= ", ".((int) $conf->entity);
295 $sql .= ", ".(empty($this->fk_pcg_version) ? 'NULL' : "'".$this->db->escape($this->fk_pcg_version)."'");
296 $sql .= ", ".(empty($this->pcg_type) ? 'NULL' : "'".$this->db->escape($this->pcg_type)."'");
297 $sql .= ", ".(empty($this->account_number) ? 'NULL' : "'".$this->db->escape($this->account_number)."'");
298 $sql .= ", ".(empty($this->account_parent) ? 0 : (int) $this->account_parent);
299 $sql .= ", ".(empty($this->label) ? "''" : "'".$this->db->escape($this->label)."'");
300 $sql .= ", ".(empty($this->labelshort) ? "''" : "'".$this->db->escape($this->labelshort)."'");
301 $sql .= ", ".(empty($this->account_category) ? 0 : (int) $this->account_category);
302 $sql .= ", ".((int) $user->id);
303 $sql .= ", ".(int) $this->active;
304 $sql .= ", ".(int) $this->reconcilable;
305 $sql .= ")";
306
307 $this->db->begin();
308
309 dol_syslog(get_class($this)."::create", LOG_DEBUG);
310 $resql = $this->db->query($sql);
311 if (!$resql) {
312 $error++;
313 $this->errors[] = "Error " . $this->db->lasterror();
314 }
315
316 if (!$error) {
317 $this->id = $this->db->last_insert_id($this->db->prefix() . $this->table_element);
318
319 // Uncomment this and change MYOBJECT to your own tag if you
320 // want this action to call a trigger.
321 //if (! $error && ! $notrigger) {
322
323 // // Call triggers
324 // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
325 // if ($result < 0) $error++;
326 // // End call triggers
327 //}
328 }
329
330 // Commit or rollback
331 if ($error) {
332 foreach ($this->errors as $errmsg) {
333 dol_syslog(get_class($this) . "::create " . $errmsg, LOG_ERR);
334 $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
335 }
336 $this->db->rollback();
337 return -1 * $error;
338 } else {
339 $this->db->commit();
340 return $this->id;
341 }
342 }
343
350 public function update($user)
351 {
352 // Check parameters
353 if (empty($this->pcg_type) || $this->pcg_type == '-1') {
354 $this->pcg_type = 'XXXXXX';
355 }
356
357 $this->db->begin();
358
359 $sql = "UPDATE " . $this->db->prefix() . $this->table_element;
360 $sql .= " SET fk_pcg_version = " . ($this->fk_pcg_version ? "'" . $this->db->escape($this->fk_pcg_version) . "'" : "null");
361 $sql .= " , pcg_type = " . ($this->pcg_type ? "'" . $this->db->escape($this->pcg_type) . "'" : "null");
362 $sql .= " , account_number = '" . $this->db->escape($this->account_number) . "'";
363 $sql .= " , account_parent = " . (int) $this->account_parent;
364 $sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "''");
365 $sql .= " , labelshort = " . ($this->labelshort ? "'" . $this->db->escape($this->labelshort) . "'" : "''");
366 $sql .= " , fk_accounting_category = " . (empty($this->account_category) ? 0 : (int) $this->account_category);
367 $sql .= " , fk_user_modif = " . ((int) $user->id);
368 $sql .= " , active = " . (int) $this->active;
369 $sql .= " , reconcilable = " . (int) $this->reconcilable;
370 $sql .= " WHERE rowid = " . ((int) $this->id);
371
372 dol_syslog(get_class($this)."::update", LOG_DEBUG);
373 $result = $this->db->query($sql);
374 if ($result) {
375 $this->db->commit();
376 return 1;
377 } else {
378 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
379 $this->error = $this->db->lasterror();
380 $this->db->rollback();
381 return -2;
382 }
383
384 $this->error = $this->db->lasterror();
385 $this->db->rollback();
386 return -1;
387 }
388 }
389
395 public function checkUsage()
396 {
397 global $langs;
398
399 // TODO Looks a stupid check
400 $sql = "(SELECT fk_code_ventilation FROM ".$this->db->prefix()."facturedet";
401 $sql .= " WHERE fk_code_ventilation=".((int) $this->id).")";
402 $sql .= "UNION";
403 $sql .= " (SELECT fk_code_ventilation FROM ".$this->db->prefix()."facture_fourn_det";
404 $sql .= " WHERE fk_code_ventilation=".((int) $this->id).")";
405
406 dol_syslog(get_class($this)."::checkUsage", LOG_DEBUG);
407 $resql = $this->db->query($sql);
408
409 if ($resql) {
410 $num = $this->db->num_rows($resql);
411 if ($num > 0) {
412 $this->error = $langs->trans('ErrorAccountancyCodeIsAlreadyUse');
413 return 0;
414 } else {
415 return 1;
416 }
417 } else {
418 $this->error = $this->db->lasterror();
419 return -1;
420 }
421 }
422
430 public function delete($user, $notrigger = 0)
431 {
432 $error = 0;
433
434 $result = $this->checkUsage();
435
436 if ($result > 0) {
437 $this->db->begin();
438
439 if (!$error) {
440 $sql = "DELETE FROM " . $this->db->prefix() . $this->table_element;
441 $sql .= " WHERE rowid=" . ((int) $this->id);
442
443 dol_syslog(get_class($this) . "::delete sql=" . $sql);
444 $resql = $this->db->query($sql);
445 if (!$resql) {
446 $error++;
447 $this->errors[] = "Error " . $this->db->lasterror();
448 }
449 }
450
451 // Commit or rollback
452 if ($error) {
453 foreach ($this->errors as $errmsg) {
454 dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
455 $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
456 }
457 $this->db->rollback();
458 return -1 * $error;
459 } else {
460 $this->db->commit();
461 return 1;
462 }
463 } else {
464 return -1;
465 }
466 }
467
481 public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $withcompletelabel = 0, $option = '')
482 {
483 global $langs, $conf, $hookmanager;
484 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
485
486 if (!empty($conf->dol_no_mouse_hover)) {
487 $notooltip = 1; // Force disable tooltips
488 }
489
490 $result = '';
491
492 $url = '';
493 $labelurl = '';
494 if (empty($option) || $option == 'ledger') {
495 $url = DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?search_accountancy_code_start=' . urlencode((isset($this->account_number) ? $this->account_number : '')) . '&search_accountancy_code_end=' . urlencode((isset($this->account_number) ? $this->account_number : ''));
496 $labelurl = $langs->trans("ShowAccountingAccountInLedger");
497 } elseif ($option == 'journals') {
498 $url = DOL_URL_ROOT . '/accountancy/bookkeeping/list.php?search_accountancy_code_start=' . urlencode($this->account_number) . '&search_accountancy_code_end=' . urlencode($this->account_number);
499 $labelurl = $langs->trans("ShowAccountingAccountInJournals");
500 } elseif ($option == 'accountcard') {
501 $url = DOL_URL_ROOT . '/accountancy/admin/card.php?id=' . urlencode((string) ($this->id));
502 $labelurl = $langs->trans("ShowAccountingAccount");
503 }
504
505 // Add param to save lastsearch_values or not
506 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
507 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
508 $add_save_lastsearch_values = 1;
509 }
510 if ($add_save_lastsearch_values) {
511 $url .= '&save_lastsearch_values=1';
512 }
513
514 $picto = 'accounting_account';
515 $label = '';
516
517 if (empty($this->labelshort) || $withcompletelabel == 1) {
518 $labeltoshow = $this->label;
519 } else {
520 $labeltoshow = $this->labelshort;
521 }
522
523 $label = '<u>' . $labelurl . '</u>';
524 if (!empty($this->account_number)) {
525 $label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . length_accountg($this->account_number);
526 }
527 if (!empty($labeltoshow)) {
528 $label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $labeltoshow;
529 }
530 if ($moretitle) {
531 $label .= ' - ' . $moretitle;
532 }
533
534 $linkclose = '';
535 if (empty($notooltip)) {
536 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
537 $label = $labelurl;
538 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
539 }
540 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
541 $linkclose .= ' class="classfortooltip"';
542 }
543
544 $linkstart = '<a href="' . $url . '"';
545 $linkstart .= $linkclose . '>';
546 $linkend = '</a>';
547
548 if ($nourl) {
549 $linkstart = '';
550 $linkclose = '';
551 $linkend = '';
552 }
553
554 $label_link = length_accountg($this->account_number);
555 if ($withlabel) {
556 $label_link .= ' - ' . ($nourl ? '<span class="opacitymedium">' : '') . $labeltoshow . ($nourl ? '</span>' : '');
557 }
558
559 if ($withpicto) {
560 $result .= ($linkstart . img_object(($notooltip ? '' : $label), $picto, ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1) . $linkend);
561 }
562 if ($withpicto && $withpicto != 2) {
563 $result .= ' ';
564 }
565 if ($withpicto != 2) {
566 $result .= $linkstart . $label_link . $linkend;
567 }
568 global $action;
569 $hookmanager->initHooks(array($this->element . 'dao'));
570 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
571 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
572 if ($reshook > 0) {
573 $result = $hookmanager->resPrint;
574 } else {
575 $result .= $hookmanager->resPrint;
576 }
577 return $result;
578 }
579
586 public function info($id)
587 {
588 $sql = 'SELECT a.rowid, a.datec, a.fk_user_author, a.fk_user_modif, a.tms as date_modification';
589 $sql .= ' FROM ' . $this->db->prefix() . $this->table_element . ' as a';
590 $sql .= ' WHERE a.rowid = ' . ((int) $id);
591
592 dol_syslog(get_class($this) . '::info sql=' . $sql);
593 $resql = $this->db->query($sql);
594
595 if ($resql) {
596 if ($this->db->num_rows($resql)) {
597 $obj = $this->db->fetch_object($resql);
598
599 $this->id = $obj->rowid;
600
601 $this->user_creation_id = $obj->fk_user_author;
602 $this->user_modification_id = $obj->fk_user_modif;
603 $this->date_creation = $this->db->jdate($obj->datec);
604 $this->date_modification = $this->db->jdate($obj->date_modification);
605 }
606 $this->db->free($resql);
607 } else {
608 dol_print_error($this->db);
609 }
610 }
611
619 public function accountDeactivate($id, $mode = 0)
620 {
621 $result = $this->checkUsage();
622
623 $fieldtouse = 'active';
624 if ($mode == 1) {
625 $fieldtouse = 'reconcilable';
626 }
627 if ($mode == 2) {
628 $fieldtouse = 'centralized';
629 }
630
631 if ($result > 0) {
632 $this->db->begin();
633
634 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
635 $sql .= " SET ".$this->db->sanitize($fieldtouse)." = 0";
636 $sql .= " WHERE rowid = ".((int) $id);
637
638 dol_syslog(get_class($this)."::accountDeactivate ".$fieldtouse, LOG_DEBUG);
639 $result = $this->db->query($sql);
640
641 if ($result) {
642 $this->db->commit();
643 return 1;
644 } else {
645 $this->error = $this->db->lasterror();
646 $this->db->rollback();
647 return -1;
648 }
649 } else {
650 return -1;
651 }
652 }
653
654
662 public function accountActivate($id, $mode = 0)
663 {
664 // phpcs:enable
665 $this->db->begin();
666
667 $fieldtouse = 'active';
668 if ($mode == 1) {
669 $fieldtouse = 'reconcilable';
670 }
671 if ($mode == 2) {
672 $fieldtouse = 'centralized';
673 }
674
675 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
676 $sql .= " SET ".$this->db->sanitize($fieldtouse)." = 1";
677 $sql .= " WHERE rowid = ".((int) $id);
678
679 dol_syslog(get_class($this)."::account_activate ".$fieldtouse, LOG_DEBUG);
680 $result = $this->db->query($sql);
681 if ($result) {
682 $this->db->commit();
683 return 1;
684 } else {
685 $this->error = $this->db->lasterror();
686 $this->db->rollback();
687 return -1;
688 }
689 }
690
697 public function getLibStatut($mode = 0)
698 {
699 return $this->LibStatut($this->status, $mode);
700 }
701
702 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
710 public function LibStatut($status, $mode = 0)
711 {
712 // phpcs:enable
713 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
714 global $langs;
715 $langs->load("users");
716 $this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
717 $this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
718 $this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
719 $this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
720 }
721
722 $statusType = 'status4';
723 if ($status == self::STATUS_DISABLED) {
724 $statusType = 'status5';
725 }
726
727 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
728 }
729
744 public function getAccountingCodeToBind(Societe $buyer, Societe $seller, Product $product, $facture, $factureDet, $accountingAccount = array(), $type = '')
745 {
746 global $hookmanager;
747 // Instantiate hooks for external modules
748 $hookmanager->initHooks(array('accountancyBindingCalculation'));
749
750 // Execute hook accountancyBindingCalculation
751 $parameters = array('buyer' => $buyer, 'seller' => $seller, 'product' => $product, 'facture' => $facture, 'factureDet' => $factureDet ,'accountingAccount' => $accountingAccount, 0 => $type);
752 $reshook = $hookmanager->executeHooks('accountancyBindingCalculation', $parameters); // Note that $action and $object may have been modified by some hooks
753
754 $result = -1; // Init for static analysis
755 if (empty($reshook)) {
756 $const_name = '';
757 if ($type == 'customer') {
758 $const_name = "SOLD";
759 } elseif ($type == 'supplier') {
760 $const_name = "BUY";
761 }
762
763 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
764 $isBuyerInEEC = isInEEC($buyer);
765 $isSellerInEEC = isInEEC($seller);
766 $code_l = ''; // Default value for generic product/service
767 $code_p = ''; // Value for the product/service in parameter ($product)
768 $code_t = ''; // Default value of product account for the thirdparty
769 $suggestedid = '';
770
771 // Level 1 (define $code_l): Search suggested default account for product/service
772 $suggestedaccountingaccountbydefaultfor = '';
773 if ($factureDet->product_type == 1) {
774 if ($buyer->country_code == $seller->country_code || empty($buyer->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country)
775 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
776 $suggestedaccountingaccountbydefaultfor = '';
777 } else {
778 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) { // European intravat sale, but with a VAT
779 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
780 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) { // European intravat sale, without VAT intra community number
781 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
782 $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
783 } elseif ($isSellerInEEC && $isBuyerInEEC) { // European intravat sale
784 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_INTRA_ACCOUNT');
785 $suggestedaccountingaccountbydefaultfor = 'eec';
786 } else { // Foreign sale
787 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_EXPORT_ACCOUNT');
788 $suggestedaccountingaccountbydefaultfor = 'export';
789 }
790 }
791 } elseif ($factureDet->product_type == 0) {
792 if ($buyer->country_code == $seller->country_code || empty($buyer->country_code)) { // If buyer in same country than seller (if not defined, we assume it is same country)
793 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
794 $suggestedaccountingaccountbydefaultfor = '';
795 } else {
796 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) { // European intravat sale, but with a VAT
797 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
798 $suggestedaccountingaccountbydefaultfor = 'eecwithvat';
799 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) { // European intravat sale, without VAT intra community number
800 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
801 $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
802 } elseif ($isSellerInEEC && $isBuyerInEEC) { // European intravat sale
803 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_INTRA_ACCOUNT');
804 $suggestedaccountingaccountbydefaultfor = 'eec';
805 } else {
806 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_EXPORT_ACCOUNT');
807 $suggestedaccountingaccountbydefaultfor = 'export';
808 }
809 }
810 }
811 if ($code_l == -1) {
812 $code_l = '';
813 }
814
815 // Level 2 (define $code_p): Search suggested account for product/service (similar code exists in page index.php to make automatic binding)
816 $suggestedaccountingaccountfor = '';
817 if ((($buyer->country_code == $seller->country_code) || empty($buyer->country_code))) {
818 // If buyer in same country than seller (if not defined, we assume it is same country)
819 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
820 $code_p = $product->accountancy_code_sell;
821 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
822 $code_p = $product->accountancy_code_buy;
823 }
824 $suggestedid = $accountingAccount['dom'];
825 $suggestedaccountingaccountfor = 'prodserv';
826 } else {
827 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) {
828 // European intravat sale, but with VAT
829 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
830 $code_p = $product->accountancy_code_sell;
831 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
832 $code_p = $product->accountancy_code_buy;
833 }
834 $suggestedid = $accountingAccount['dom'];
835 $suggestedaccountingaccountfor = 'eecwithvat';
836 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) {
837 // European intravat sale, without VAT intra community number
838 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
839 $code_p = $product->accountancy_code_sell;
840 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
841 $code_p = $product->accountancy_code_buy;
842 }
843 $suggestedid = $accountingAccount['dom']; // There is a doubt for this case. Is it an error on vat or we just forgot to fill vat number ?
844 $suggestedaccountingaccountfor = 'eecwithoutvatnumber';
845 } elseif ($isSellerInEEC && $isBuyerInEEC && (($type == 'customer' && !empty($product->accountancy_code_sell_intra)) || ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)))) {
846 // European intravat sale
847 if ($type == 'customer' && !empty($product->accountancy_code_sell_intra)) {
848 $code_p = $product->accountancy_code_sell_intra;
849 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)) {
850 $code_p = $product->accountancy_code_buy_intra;
851 }
852 $suggestedid = $accountingAccount['intra'];
853 $suggestedaccountingaccountfor = 'eec';
854 } else {
855 // Foreign sale
856 if ($type == 'customer' && !empty($product->accountancy_code_sell_export)) {
857 $code_p = $product->accountancy_code_sell_export;
858 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_export)) {
859 $code_p = $product->accountancy_code_buy_export;
860 }
861 $suggestedid = $accountingAccount['export'];
862 $suggestedaccountingaccountfor = 'export';
863 }
864 }
865
866 // Level 3 (define $code_t): Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding)
867 if (getDolGlobalString('ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY')) {
868 if ($type == 'customer' && !empty($buyer->code_compta_product)) {
869 $code_t = $buyer->code_compta_product;
870 $suggestedid = $accountingAccount['thirdparty'];
871 $suggestedaccountingaccountfor = 'thirdparty';
872 } elseif ($type == 'supplier' && !empty($seller->code_compta_product)) {
873 $code_t = $seller->code_compta_product;
874 $suggestedid = $accountingAccount['thirdparty'];
875 $suggestedaccountingaccountfor = 'thirdparty';
876 }
877 }
878
879 // Manage Deposit
880 $account_deposit = getDolGlobalString('ACCOUNTING_ACCOUNT_' . strtoupper($type) . '_DEPOSIT');
881 if (!empty($account_deposit) && $account_deposit != '-1') {
882 if ($factureDet->desc == "(DEPOSIT)" || $facture->type == $facture::TYPE_DEPOSIT) {
883 $accountdeposittoventilated = new self($this->db);
884 if ($type == 'customer') {
885 $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
886 } elseif ($type == 'supplier') {
887 $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
888 }
889 if (isset($result) && $result < 0) {
890 return -1;
891 }
892
893 $code_l = $accountdeposittoventilated->ref;
894 $code_p = '';
895 $code_t = '';
896 $suggestedid = $accountdeposittoventilated->rowid;
897 $suggestedaccountingaccountfor = 'deposit';
898 }
899
900 // For credit note invoice, if origin invoice is a deposit invoice, force also on specific customer/supplier deposit account
901 if (!empty($facture->fk_facture_source)) {
902 $invoiceSource = new $facture($this->db);
903 $invoiceSource->fetch($facture->fk_facture_source);
904
905 if ($facture->type == $facture::TYPE_CREDIT_NOTE && $invoiceSource->type == $facture::TYPE_DEPOSIT) {
906 $accountdeposittoventilated = new self($this->db);
907 if ($type == 'customer') {
908 $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
909 } elseif ($type == 'supplier') {
910 $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
911 }
912 $code_l = $accountdeposittoventilated->ref;
913 $code_p = '';
914 $code_t = '';
915 $suggestedid = $accountdeposittoventilated->rowid;
916 $suggestedaccountingaccountfor = 'deposit';
917 }
918 }
919 }
920
921 // If $suggestedid could not be guessed yet, we set it from the generic default accounting code $code_l
922 if (empty($suggestedid) && empty($code_p) && !empty($code_l) && !getDolGlobalString('ACCOUNTANCY_DO_NOT_AUTOFILL_ACCOUNT_WITH_GENERIC')) {
923 if (empty($this->accountingaccount_codetotid_cache[$code_l])) {
924 $tmpaccount = new self($this->db);
925 $result = $tmpaccount->fetch(0, $code_l, 1);
926 if ($result < 0) {
927 return -1;
928 }
929 if ($tmpaccount->id > 0) {
930 $suggestedid = $tmpaccount->id;
931 }
932 $this->accountingaccount_codetotid_cache[$code_l] = $tmpaccount->id;
933 } else {
934 $suggestedid = $this->accountingaccount_codetotid_cache[$code_l];
935 }
936 }
937 return array(
938 'suggestedaccountingaccountbydefaultfor' => $suggestedaccountingaccountbydefaultfor,
939 'suggestedaccountingaccountfor' => $suggestedaccountingaccountfor,
940 'suggestedid' => $suggestedid,
941 'code_l' => $code_l,
942 'code_p' => $code_p,
943 'code_t' => $code_t,
944 );
945 } else {
946 if (is_array($hookmanager->resArray) && !empty($hookmanager->resArray)) {
947 return $hookmanager->resArray;
948 }
949 }
950
951 return -1;
952 }
953}
length_accountg($account)
Return General accounting account with defined length (used for product and miscellaneous)
$object ref
Definition info.php:90
Class to manage accounting accounts.
LibStatut($status, $mode=0)
Return the label of a given status.
accountDeactivate($id, $mode=0)
Deactivate an account (for status active or status reconcilable)
checkUsage()
Check usage of accounting code.
update($user)
Update record.
getNomUrl($withpicto=0, $withlabel=0, $nourl=0, $moretitle='', $notooltip=0, $save_lastsearch_value=-1, $withcompletelabel=0, $option='')
Return clickable name (with picto eventually)
create($user, $notrigger=0)
Insert new accounting account in chart of accounts.
accountActivate($id, $mode=0)
Account activated.
fetch($rowid=0, $account_number=null, $limittocurrentchart=0, $limittoachartaccount='')
Load record in memory.
info($id)
Information on record.
getAccountingCodeToBind(Societe $buyer, Societe $seller, Product $product, $facture, $factureDet, $accountingAccount=array(), $type='')
Return a suggested account (from chart of accounts) to bind.
getLibStatut($mode=0)
Return the label of the status.
Parent class of all other business classes (invoices, contracts, proposals, orders,...
Class to manage products or services.
Class to manage third parties objects (customers, suppliers, prospects...)
print $langs trans("Ref").' m titre as m m statut as status
Or an array listing all the potential status of the object: array: int of the status => translated la...
Definition index.php:171
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
dol_now($mode='auto')
Return date for now.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dolGetStatus($statusLabel='', $statusLabelShort='', $html='', $statusType='status0', $displayMode=0, $url='', $params=array())
Output the badge of a status.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
global $conf
The following vars must be defined: $type2label $form $conf, $lang, The following vars may also be de...
Definition member.php:79