dolibarr 24.0.0-beta
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-2025 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
78 public $ref;
79
85 public $datec;
86
90 public $fk_pcg_version;
91
95 public $pcg_type;
96
100 public $account_number;
101
105 public $account_parent;
106
110 public $account_category;
111
115 public $account_category_label;
116
120 public $status;
121
125 public $label;
126
130 public $labelshort;
131
135 public $fk_user_author;
136
140 public $fk_user_modif;
141
145 public $active;
146
150 public $reconcilable;
151
155 private $accountingaccount_codetotid_cache = array();
156
157
158 const STATUS_ENABLED = 1;
159 const STATUS_DISABLED = 0;
160
161
167 public function __construct($db)
168 {
169 $this->db = $db;
170
171 $this->ismultientitymanaged = 1;
172 $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
173 }
174
184 public function fetch($rowid = 0, $account_number = null, $limittocurrentchart = 0, $limittoachartaccount = '')
185 {
186 global $conf;
187
188 if ($rowid || $account_number) {
189 $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";
190 $sql .= ", ca.label as category_label";
191 $sql .= " FROM ".$this->db->prefix().$this->table_element." as a";
192 $sql .= " LEFT JOIN ".$this->db->prefix()."c_accounting_category as ca ON a.fk_accounting_category = ca.rowid";
193 $sql .= " WHERE";
194 if ($rowid) {
195 $sql .= " a.rowid = ".(int) $rowid;
196 } elseif ($account_number) {
197 $sql .= " a.account_number = '".$this->db->escape($account_number)."'";
198 $sql .= " AND a.entity = ".$conf->entity;
199 }
200 if (!empty($limittocurrentchart)) {
201 $sql .= ' AND a.fk_pcg_version IN (SELECT pcg_version FROM '.$this->db->prefix().'accounting_system WHERE rowid = '.((int) getDolGlobalInt('CHARTOFACCOUNTS')).')';
202 }
203 if (!empty($limittoachartaccount)) {
204 $sql .= " AND a.fk_pcg_version = '".$this->db->escape($limittoachartaccount)."'";
205 }
206
207 dol_syslog(get_class($this)."::fetch rowid=".$rowid." account_number=".$account_number, LOG_DEBUG);
208
209 $result = $this->db->query($sql);
210 if ($result) {
211 $obj = $this->db->fetch_object($result);
212
213 if ($obj) {
214 $this->id = $obj->rowid;
215 $this->rowid = $obj->rowid;
216 $this->ref = $obj->account_number;
217 $this->datec = $this->db->jdate($obj->datec);
218 $this->date_creation = $this->db->jdate($obj->datec);
219 $this->date_modification = $this->db->jdate($obj->tms);
220 //$this->tms = $this->datem;
221 $this->fk_pcg_version = $obj->fk_pcg_version;
222 $this->pcg_type = $obj->pcg_type;
223 $this->account_number = $obj->account_number;
224 $this->account_parent = $obj->account_parent;
225 $this->label = $obj->label;
226 $this->labelshort = $obj->labelshort;
227 $this->account_category = $obj->fk_accounting_category;
228 $this->account_category_label = $obj->category_label;
229 $this->fk_user_author = $obj->fk_user_author;
230 $this->fk_user_modif = $obj->fk_user_modif;
231 $this->active = $obj->active;
232 $this->status = $obj->active;
233 $this->reconcilable = $obj->reconcilable;
234
235 return $this->id;
236 } else {
237 return 0;
238 }
239 } else {
240 $this->error = "Error ".$this->db->lasterror();
241 $this->errors[] = "Error ".$this->db->lasterror();
242 }
243 }
244 return -1;
245 }
246
254 public function create($user, $notrigger = 0)
255 {
256 global $conf;
257 $error = 0;
258 $now = dol_now();
259
260 // Clean parameters
261 if (isset($this->fk_pcg_version)) {
262 $this->fk_pcg_version = trim($this->fk_pcg_version);
263 }
264 if (isset($this->pcg_type)) {
265 $this->pcg_type = trim($this->pcg_type);
266 }
267 if (isset($this->account_number)) {
268 $this->account_number = trim($this->account_number);
269 }
270 if (isset($this->label)) {
271 $this->label = trim($this->label);
272 }
273 if (isset($this->labelshort)) {
274 $this->labelshort = trim($this->labelshort);
275 }
276
277 if (empty($this->pcg_type) || $this->pcg_type == '-1') {
278 $this->pcg_type = 'XXXXXX';
279 }
280 // Check parameters
281 // Put here code to add control on parameters values
282
283 // Insert request
284 $sql = "INSERT INTO " . $this->db->prefix() . $this->table_element . " (";
285 $sql .= "datec";
286 $sql .= ", entity";
287 $sql .= ", fk_pcg_version";
288 $sql .= ", pcg_type";
289 $sql .= ", account_number";
290 $sql .= ", account_parent";
291 $sql .= ", label";
292 $sql .= ", labelshort";
293 $sql .= ", fk_accounting_category";
294 $sql .= ", fk_user_author";
295 $sql .= ", active";
296 $sql .= ", reconcilable";
297 $sql .= ") VALUES (";
298 $sql .= " '".$this->db->idate($now)."'";
299 $sql .= ", ".((int) $conf->entity);
300 $sql .= ", ".(empty($this->fk_pcg_version) ? 'NULL' : "'".$this->db->escape($this->fk_pcg_version)."'");
301 $sql .= ", ".(empty($this->pcg_type) ? 'NULL' : "'".$this->db->escape($this->pcg_type)."'");
302 $sql .= ", ".(empty($this->account_number) ? 'NULL' : "'".$this->db->escape($this->account_number)."'");
303 $sql .= ", ".(empty($this->account_parent) ? 0 : (int) $this->account_parent);
304 $sql .= ", ".(empty($this->label) ? "''" : "'".$this->db->escape($this->label)."'");
305 $sql .= ", ".(empty($this->labelshort) ? "''" : "'".$this->db->escape($this->labelshort)."'");
306 $sql .= ", ".(empty($this->account_category) ? 0 : (int) $this->account_category);
307 $sql .= ", ".((int) $user->id);
308 $sql .= ", ".(int) $this->active;
309 $sql .= ", ".(int) $this->reconcilable;
310 $sql .= ")";
311
312 $this->db->begin();
313
314 dol_syslog(get_class($this)."::create", LOG_DEBUG);
315 $resql = $this->db->query($sql);
316 if (!$resql) {
317 $error++;
318 $this->errors[] = "Error " . $this->db->lasterror();
319 }
320
321 if (!$error) {
322 $this->id = $this->db->last_insert_id($this->db->prefix() . $this->table_element);
323
324 // Uncomment this and change MYOBJECT to your own tag if you
325 // want this action to call a trigger.
326 //if (! $error && ! $notrigger) {
327
328 // // Call triggers
329 // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
330 // if ($result < 0) $error++;
331 // // End call triggers
332 //}
333 }
334
335 // Commit or rollback
336 if ($error) {
337 foreach ($this->errors as $errmsg) {
338 dol_syslog(get_class($this) . "::create " . $errmsg, LOG_ERR);
339 $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
340 }
341 $this->db->rollback();
342 return -1 * $error;
343 } else {
344 $this->db->commit();
345 return $this->id;
346 }
347 }
348
355 public function update($user)
356 {
357 // Check parameters
358 if (empty($this->pcg_type) || $this->pcg_type == '-1') {
359 $this->pcg_type = 'XXXXXX';
360 }
361
362 $this->db->begin();
363
364 $sql = "UPDATE " . $this->db->prefix() . $this->table_element;
365 $sql .= " SET fk_pcg_version = " . ($this->fk_pcg_version ? "'" . $this->db->escape($this->fk_pcg_version) . "'" : "null");
366 $sql .= " , pcg_type = '" . $this->db->escape($this->pcg_type) . "'";
367 $sql .= " , account_number = '" . $this->db->escape($this->account_number) . "'";
368 $sql .= " , account_parent = " . (int) $this->account_parent;
369 $sql .= " , label = " . ($this->label ? "'" . $this->db->escape($this->label) . "'" : "''");
370 $sql .= " , labelshort = " . ($this->labelshort ? "'" . $this->db->escape($this->labelshort) . "'" : "''");
371 $sql .= " , fk_accounting_category = " . (empty($this->account_category) ? 0 : (int) $this->account_category);
372 $sql .= " , fk_user_modif = " . ((int) $user->id);
373 $sql .= " , active = " . (int) $this->active;
374 $sql .= " , reconcilable = " . (int) $this->reconcilable;
375 $sql .= " WHERE rowid = " . ((int) $this->id);
376
377 dol_syslog(get_class($this)."::update", LOG_DEBUG);
378 $result = $this->db->query($sql);
379 if ($result) {
380 $this->db->commit();
381 return 1;
382 } else {
383 if ($this->db->lasterrno() == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
384 $this->error = $this->db->lasterror();
385 $this->db->rollback();
386 return -2;
387 }
388
389 $this->error = $this->db->lasterror();
390 $this->db->rollback();
391 return -1;
392 }
393 }
394
400 public function checkUsage()
401 {
402 global $langs;
403
404 // TODO Looks a stupid check
405 $sql = "(SELECT fk_code_ventilation FROM ".$this->db->prefix()."facturedet";
406 $sql .= " WHERE fk_code_ventilation=".((int) $this->id).")";
407 $sql .= "UNION";
408 $sql .= " (SELECT fk_code_ventilation FROM ".$this->db->prefix()."facture_fourn_det";
409 $sql .= " WHERE fk_code_ventilation=".((int) $this->id).")";
410
411 dol_syslog(get_class($this)."::checkUsage", LOG_DEBUG);
412 $resql = $this->db->query($sql);
413
414 if ($resql) {
415 $num = $this->db->num_rows($resql);
416 if ($num > 0) {
417 $this->error = $langs->trans('ErrorAccountancyCodeIsAlreadyUse');
418 return 0;
419 } else {
420 return 1;
421 }
422 } else {
423 $this->error = $this->db->lasterror();
424 return -1;
425 }
426 }
427
435 public function delete($user, $notrigger = 0)
436 {
437 $error = 0;
438
439 $result = $this->checkUsage();
440
441 if ($result > 0) {
442 $this->db->begin();
443
444 $sql = "DELETE FROM " . $this->db->prefix() . $this->table_element;
445 $sql .= " WHERE rowid=" . ((int) $this->id);
446
447 dol_syslog(get_class($this) . "::delete sql=" . $sql);
448 $resql = $this->db->query($sql);
449 if (!$resql) {
450 $error++;
451 $this->errors[] = "Error " . $this->db->lasterror();
452 }
453
454 // Commit or rollback
455 if ($error) {
456 foreach ($this->errors as $errmsg) {
457 dol_syslog(get_class($this) . "::delete " . $errmsg, LOG_ERR);
458 $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
459 }
460 $this->db->rollback();
461 return -1 * $error;
462 } else {
463 $this->db->commit();
464 return 1;
465 }
466 } else {
467 return -1;
468 }
469 }
470
484 public function getNomUrl($withpicto = 0, $withlabel = 0, $nourl = 0, $moretitle = '', $notooltip = 0, $save_lastsearch_value = -1, $withcompletelabel = 0, $option = '')
485 {
486 global $langs, $conf, $hookmanager;
487 require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
488
489 if (!empty($conf->dol_no_mouse_hover)) {
490 $notooltip = 1; // Force disable tooltips
491 }
492
493 $result = '';
494
495 $url = '';
496 $labelurl = '';
497 if (empty($option) || $option == 'ledger') {
498 $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 : ''));
499 $labelurl = $langs->trans("ShowAccountingAccountInLedger");
500 } elseif ($option == 'journals') {
501 $url = DOL_URL_ROOT . '/accountancy/bookkeeping/list.php?search_accountancy_code_start=' . urlencode($this->account_number) . '&search_accountancy_code_end=' . urlencode($this->account_number);
502 $labelurl = $langs->trans("ShowAccountingAccountInJournals");
503 } elseif ($option == 'accountcard') {
504 $url = DOL_URL_ROOT . '/accountancy/admin/card.php?id=' . urlencode((string) ($this->id));
505 $labelurl = $langs->trans("ShowAccountingAccount");
506 }
507
508 // Add param to save lastsearch_values or not
509 $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
510 if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
511 $add_save_lastsearch_values = 1;
512 }
513 if ($add_save_lastsearch_values) {
514 $url .= '&save_lastsearch_values=1';
515 }
516
517 $picto = 'accounting_account';
518 $label = '';
519
520 if (empty($this->labelshort) || $withcompletelabel == 1) {
521 $labeltoshow = $this->label;
522 } else {
523 $labeltoshow = $this->labelshort;
524 }
525
526 $label = '<u>' . $labelurl . '</u>';
527 if (!empty($this->account_number)) {
528 $label .= '<br><b>' . $langs->trans('AccountAccounting') . ':</b> ' . length_accountg($this->account_number);
529 }
530 if (!empty($labeltoshow)) {
531 $label .= '<br><b>' . $langs->trans('Label') . ':</b> ' . $labeltoshow;
532 }
533 if ($moretitle) {
534 $label .= ' - ' . $moretitle;
535 }
536
537 $linkclose = '';
538 if (empty($notooltip)) {
539 if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) {
540 $label = $labelurl;
541 $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"';
542 }
543 $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"';
544 $linkclose .= ' class="classfortooltip"';
545 }
546
547 $linkstart = '<a href="' . $url . '"';
548 $linkstart .= $linkclose . '>';
549 $linkend = '</a>';
550
551 if ($nourl) {
552 $linkstart = '';
553 $linkclose = '';
554 $linkend = '';
555 }
556
557 $label_link = length_accountg($this->account_number);
558 if ($withlabel) {
559 $label_link .= ' - ' . ($nourl ? '<span class="opacitymedium">' : '') . $labeltoshow . ($nourl ? '</span>' : '');
560 }
561
562 if ($withpicto) {
563 $result .= ($linkstart . img_object(($notooltip ? '' : $label), $picto, ($notooltip ? '' : 'class="classfortooltip"'), 0, 0, $notooltip ? 0 : 1) . $linkend);
564 }
565 if ($withpicto && $withpicto != 2) {
566 $result .= ' ';
567 }
568 if ($withpicto != 2) {
569 $result .= $linkstart . $label_link . $linkend;
570 }
571 global $action;
572 $hookmanager->initHooks(array($this->element . 'dao'));
573 $parameters = array('id' => $this->id, 'getnomurl' => &$result);
574 $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
575 if ($reshook > 0) {
576 $result = $hookmanager->resPrint;
577 } else {
578 $result .= $hookmanager->resPrint;
579 }
580 return $result;
581 }
582
589 public function info($id)
590 {
591 $sql = 'SELECT a.rowid, a.datec, a.fk_user_author, a.fk_user_modif, a.tms as date_modification';
592 $sql .= ' FROM ' . $this->db->prefix() . $this->table_element . ' as a';
593 $sql .= ' WHERE a.rowid = ' . ((int) $id);
594
595 dol_syslog(get_class($this) . '::info sql=' . $sql);
596 $resql = $this->db->query($sql);
597
598 if ($resql) {
599 if ($this->db->num_rows($resql)) {
600 $obj = $this->db->fetch_object($resql);
601
602 $this->id = $obj->rowid;
603
604 $this->user_creation_id = $obj->fk_user_author;
605 $this->user_modification_id = $obj->fk_user_modif;
606 $this->date_creation = $this->db->jdate($obj->datec);
607 $this->date_modification = $this->db->jdate($obj->date_modification);
608 }
609 $this->db->free($resql);
610 } else {
611 dol_print_error($this->db);
612 }
613 }
614
622 public function accountDeactivate($id, $mode = 0)
623 {
624 $result = $this->checkUsage();
625
626 $fieldtouse = 'active';
627 if ($mode == 1) {
628 $fieldtouse = 'reconcilable';
629 }
630 if ($mode == 2) {
631 $fieldtouse = 'centralized';
632 }
633
634 if ($result > 0) {
635 $this->db->begin();
636
637 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
638 $sql .= " SET ".$this->db->sanitize($fieldtouse)." = 0";
639 $sql .= " WHERE rowid = ".((int) $id);
640
641 dol_syslog(get_class($this)."::accountDeactivate ".$fieldtouse, LOG_DEBUG);
642 $result = $this->db->query($sql);
643
644 if ($result) {
645 $this->db->commit();
646 return 1;
647 } else {
648 $this->error = $this->db->lasterror();
649 $this->db->rollback();
650 return -1;
651 }
652 } else {
653 return -1;
654 }
655 }
656
657
665 public function accountActivate($id, $mode = 0)
666 {
667 // phpcs:enable
668 $this->db->begin();
669
670 $fieldtouse = 'active';
671 if ($mode == 1) {
672 $fieldtouse = 'reconcilable';
673 }
674 if ($mode == 2) {
675 $fieldtouse = 'centralized';
676 }
677
678 $sql = "UPDATE ".$this->db->prefix().$this->table_element;
679 $sql .= " SET ".$this->db->sanitize($fieldtouse)." = 1";
680 $sql .= " WHERE rowid = ".((int) $id);
681
682 dol_syslog(get_class($this)."::account_activate ".$fieldtouse, LOG_DEBUG);
683 $result = $this->db->query($sql);
684 if ($result) {
685 $this->db->commit();
686 return 1;
687 } else {
688 $this->error = $this->db->lasterror();
689 $this->db->rollback();
690 return -1;
691 }
692 }
693
700 public function getLibStatut($mode = 0)
701 {
702 return $this->LibStatut($this->status, $mode);
703 }
704
705 // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
713 public function LibStatut($status, $mode = 0)
714 {
715 // phpcs:enable
716 if (empty($this->labelStatus) || empty($this->labelStatusShort)) {
717 global $langs;
718 $langs->load("users");
719 $this->labelStatus[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
720 $this->labelStatus[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
721 $this->labelStatusShort[self::STATUS_ENABLED] = $langs->transnoentitiesnoconv('Enabled');
722 $this->labelStatusShort[self::STATUS_DISABLED] = $langs->transnoentitiesnoconv('Disabled');
723 }
724
725 $statusType = 'status4';
726 if ($status == self::STATUS_DISABLED) {
727 $statusType = 'status5';
728 }
729
730 return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode);
731 }
732
747 public function getAccountingCodeToBind(Societe $buyer, Societe $seller, Product $product, $facture, $factureDet, $accountingAccount = array(), $type = '')
748 {
749 global $hookmanager;
750 // Instantiate hooks for external modules
751 $hookmanager->initHooks(array('accountancyBindingCalculation'));
752
753 // Execute hook accountancyBindingCalculation
754 $parameters = array('buyer' => $buyer, 'seller' => $seller, 'product' => $product, 'facture' => $facture, 'factureDet' => $factureDet ,'accountingAccount' => $accountingAccount, 0 => $type);
755 $reshook = $hookmanager->executeHooks('accountancyBindingCalculation', $parameters); // Note that $action and $object may have been modified by some hooks
756
757 $result = -1; // Init for static analysis
758 if (empty($reshook)) {
759 $const_name = '';
760 if ($type == 'customer') {
761 $const_name = "SOLD";
762 } elseif ($type == 'supplier') {
763 $const_name = "BUY";
764 }
765
766 require_once DOL_DOCUMENT_ROOT . '/core/lib/company.lib.php';
767 $isBuyerInEEC = isInEEC($buyer);
768 $isSellerInEEC = isInEEC($seller);
769 $code_l = ''; // Default value for generic product/service
770 $code_p = ''; // Value for the product/service in parameter ($product)
771 $code_t = ''; // Default value of product account for the thirdparty
772 $suggestedid = '';
773
774 // Level 1 (define $code_l): Search suggested default account for product/service
775 $suggestedaccountingaccountbydefaultfor = '';
776 if ($factureDet->product_type == 1) {
777 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)
778 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
779 $suggestedaccountingaccountbydefaultfor = '';
780 } else {
781 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) { // European intravat sale, but with a VAT
782 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
783 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) { // European intravat sale, without VAT intra community number
784 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_ACCOUNT');
785 $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
786 } elseif ($isSellerInEEC && $isBuyerInEEC) { // European intravat sale
787 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_INTRA_ACCOUNT');
788 $suggestedaccountingaccountbydefaultfor = 'eec';
789 } else { // Foreign sale
790 $code_l = getDolGlobalString('ACCOUNTING_SERVICE_' . $const_name . '_EXPORT_ACCOUNT');
791 $suggestedaccountingaccountbydefaultfor = 'export';
792 }
793 }
794 } elseif ($factureDet->product_type == 0) {
795 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)
796 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
797 $suggestedaccountingaccountbydefaultfor = '';
798 } else {
799 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) { // European intravat sale, but with a VAT
800 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
801 $suggestedaccountingaccountbydefaultfor = 'eecwithvat';
802 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) { // European intravat sale, without VAT intra community number
803 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_ACCOUNT');
804 $suggestedaccountingaccountbydefaultfor = 'eecwithoutvatnumber';
805 } elseif ($isSellerInEEC && $isBuyerInEEC) { // European intravat sale
806 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_INTRA_ACCOUNT');
807 $suggestedaccountingaccountbydefaultfor = 'eec';
808 } else {
809 $code_l = getDolGlobalString('ACCOUNTING_PRODUCT_' . $const_name . '_EXPORT_ACCOUNT');
810 $suggestedaccountingaccountbydefaultfor = 'export';
811 }
812 }
813 }
814 if ($code_l == -1) {
815 $code_l = '';
816 }
817
818 // Level 2 (define $code_p): Search suggested account for product/service (similar code exists in page index.php to make automatic binding)
819 $suggestedaccountingaccountfor = '';
820 if ((($buyer->country_code == $seller->country_code) || empty($buyer->country_code))) {
821 // If buyer in same country than seller (if not defined, we assume it is same country)
822 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
823 $code_p = $product->accountancy_code_sell;
824 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
825 $code_p = $product->accountancy_code_buy;
826 }
827 $suggestedid = $accountingAccount['dom'];
828 $suggestedaccountingaccountfor = 'prodserv';
829 } else {
830 if ($isSellerInEEC && $isBuyerInEEC && $factureDet->tva_tx != 0) {
831 // European intravat sale, but with VAT
832 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
833 $code_p = $product->accountancy_code_sell;
834 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
835 $code_p = $product->accountancy_code_buy;
836 }
837 $suggestedid = $accountingAccount['dom'];
838 $suggestedaccountingaccountfor = 'eecwithvat';
839 } elseif ($isSellerInEEC && $isBuyerInEEC && empty($buyer->tva_intra)) {
840 // European intravat sale, without VAT intra community number
841 if ($type == 'customer' && !empty($product->accountancy_code_sell)) {
842 $code_p = $product->accountancy_code_sell;
843 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy)) {
844 $code_p = $product->accountancy_code_buy;
845 }
846 $suggestedid = $accountingAccount['dom']; // There is a doubt for this case. Is it an error on vat or we just forgot to fill vat number ?
847 $suggestedaccountingaccountfor = 'eecwithoutvatnumber';
848 } elseif ($isSellerInEEC && $isBuyerInEEC && (($type == 'customer' && !empty($product->accountancy_code_sell_intra)) || ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)))) {
849 // European intravat sale
850 if ($type == 'customer' && !empty($product->accountancy_code_sell_intra)) {
851 $code_p = $product->accountancy_code_sell_intra;
852 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_intra)) {
853 $code_p = $product->accountancy_code_buy_intra;
854 }
855 $suggestedid = $accountingAccount['intra'];
856 $suggestedaccountingaccountfor = 'eec';
857 } else {
858 // Foreign sale
859 if ($type == 'customer' && !empty($product->accountancy_code_sell_export)) {
860 $code_p = $product->accountancy_code_sell_export;
861 } elseif ($type == 'supplier' && !empty($product->accountancy_code_buy_export)) {
862 $code_p = $product->accountancy_code_buy_export;
863 }
864 $suggestedid = $accountingAccount['export'];
865 $suggestedaccountingaccountfor = 'export';
866 }
867 }
868
869 // Level 3 (define $code_t): Search suggested account for this thirdparty (similar code exists in page index.php to make automatic binding)
870 if (getDolGlobalString('ACCOUNTANCY_USE_PRODUCT_ACCOUNT_ON_THIRDPARTY')) {
871 if ($type == 'customer' && !empty($buyer->code_compta_product)) {
872 $code_t = $buyer->code_compta_product;
873 $suggestedid = $accountingAccount['thirdparty'];
874 $suggestedaccountingaccountfor = 'thirdparty';
875 } elseif ($type == 'supplier' && !empty($seller->code_compta_product)) {
876 $code_t = $seller->code_compta_product;
877 $suggestedid = $accountingAccount['thirdparty'];
878 $suggestedaccountingaccountfor = 'thirdparty';
879 }
880 }
881
882 // Manage Deposit
883 $account_deposit = getDolGlobalString('ACCOUNTING_ACCOUNT_' . strtoupper($type) . '_DEPOSIT');
884 if (!empty($account_deposit) && $account_deposit != '-1') {
885 if ($factureDet->desc == "(DEPOSIT)" || $facture->type == $facture::TYPE_DEPOSIT) {
886 $accountdeposittoventilated = new self($this->db);
887 if ($type == 'customer') {
888 $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
889 } elseif ($type == 'supplier') {
890 $result = $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
891 }
892 if (isset($result) && $result < 0) {
893 return -1;
894 }
895
896 $code_l = (string) $accountdeposittoventilated->ref;
897 $code_p = '';
898 $code_t = '';
899 $suggestedid = (int) $accountdeposittoventilated->rowid;
900 $suggestedaccountingaccountfor = 'deposit';
901 }
902
903 // For credit note invoice, if origin invoice is a deposit invoice, force also on specific customer/supplier deposit account
904 if (!empty($facture->fk_facture_source)) {
905 $invoiceSource = new $facture($this->db);
906 $invoiceSource->fetch($facture->fk_facture_source);
907
908 if ($facture->type == $facture::TYPE_CREDIT_NOTE && $invoiceSource->type == $facture::TYPE_DEPOSIT) {
909 $accountdeposittoventilated = new self($this->db);
910 if ($type == 'customer') {
911 $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_CUSTOMER_DEPOSIT'), 1);
912 } elseif ($type == 'supplier') {
913 $accountdeposittoventilated->fetch(0, getDolGlobalString('ACCOUNTING_ACCOUNT_SUPPLIER_DEPOSIT'), 1);
914 }
915 $code_l = (string) $accountdeposittoventilated->ref;
916 $code_p = '';
917 $code_t = '';
918 $suggestedid = (int) $accountdeposittoventilated->rowid;
919 $suggestedaccountingaccountfor = 'deposit';
920 }
921 }
922 }
923
924 // If $suggestedid could not be guessed yet, we set it from the generic default accounting code $code_l
925 if (empty($suggestedid) && empty($code_p) && !empty($code_l) && !getDolGlobalString('ACCOUNTANCY_DO_NOT_AUTOFILL_ACCOUNT_WITH_GENERIC')) {
926 if (empty($this->accountingaccount_codetotid_cache[$code_l])) {
927 $tmpaccount = new self($this->db);
928 $result = $tmpaccount->fetch(0, $code_l, 1);
929 if ($result < 0) {
930 return -1;
931 }
932 if ($tmpaccount->id > 0) {
933 $suggestedid = $tmpaccount->id;
934 }
935 $this->accountingaccount_codetotid_cache[$code_l] = $tmpaccount->id;
936 } else {
937 $suggestedid = $this->accountingaccount_codetotid_cache[$code_l];
938 }
939 }
940 return array(
941 'suggestedaccountingaccountbydefaultfor' => $suggestedaccountingaccountbydefaultfor,
942 'suggestedaccountingaccountfor' => $suggestedaccountingaccountfor,
943 'suggestedid' => $suggestedid,
944 'code_l' => $code_l,
945 'code_p' => $code_p,
946 'code_t' => $code_t,
947 );
948 } else {
949 if (is_array($hookmanager->resArray) && !empty($hookmanager->resArray)) {
950 return $hookmanager->resArray;
951 }
952 }
953
954 return -1;
955 }
956}
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:168
isInEEC($object)
Return if a country of an object is inside the EEC (European Economic Community)
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_now($mode='gmt')
Return date for now.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
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...
editval_textarea active
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string
buildzip.php