Total Complexity | 501 |
Total Lines | 3051 |
Duplicated Lines | 0 % |
Changes | 1 | ||
Bugs | 0 | Features | 0 |
Complex classes like BookKeeping often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BookKeeping, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
43 | class BookKeeping extends CommonObject |
||
44 | { |
||
45 | /** |
||
46 | * @var string Id to identify managed objects |
||
47 | */ |
||
48 | public $element = 'accountingbookkeeping'; |
||
49 | |||
50 | /** |
||
51 | * @var string Name of table without prefix where object is stored |
||
52 | */ |
||
53 | public $table_element = 'accounting_bookkeeping'; |
||
54 | |||
55 | /** |
||
56 | * @var int Entity |
||
57 | */ |
||
58 | public $entity; |
||
59 | |||
60 | /** |
||
61 | * @var BookKeepingLine[] Lines |
||
62 | */ |
||
63 | public $lines = array(); |
||
64 | |||
65 | /** |
||
66 | * @var int ID |
||
67 | */ |
||
68 | public $id; |
||
69 | |||
70 | /** |
||
71 | * @var int Date of source document, in db date NOT NULL |
||
72 | */ |
||
73 | public $doc_date; |
||
74 | |||
75 | /** |
||
76 | * @var int Deadline for payment |
||
77 | */ |
||
78 | public $date_lim_reglement; |
||
79 | |||
80 | /** |
||
81 | * @var string doc_type |
||
82 | */ |
||
83 | public $doc_type; |
||
84 | |||
85 | /** |
||
86 | * @var string doc_ref |
||
87 | */ |
||
88 | public $doc_ref; |
||
89 | |||
90 | /** |
||
91 | * @var int ID |
||
92 | */ |
||
93 | public $fk_doc; |
||
94 | |||
95 | /** |
||
96 | * @var int ID |
||
97 | */ |
||
98 | public $fk_docdet; |
||
99 | |||
100 | /** |
||
101 | * @var string thirdparty code |
||
102 | */ |
||
103 | public $thirdparty_code; |
||
104 | |||
105 | /** |
||
106 | * @var string subledger account |
||
107 | */ |
||
108 | public $subledger_account; |
||
109 | |||
110 | /** |
||
111 | * @var string subledger label |
||
112 | */ |
||
113 | public $subledger_label; |
||
114 | |||
115 | /** |
||
116 | * @var string doc_type |
||
117 | */ |
||
118 | public $numero_compte; |
||
119 | |||
120 | /** |
||
121 | * @var string label compte |
||
122 | */ |
||
123 | public $label_compte; |
||
124 | |||
125 | /** |
||
126 | * @var string label operation |
||
127 | */ |
||
128 | public $label_operation; |
||
129 | |||
130 | /** |
||
131 | * @var float FEC:Debit |
||
132 | */ |
||
133 | public $debit; |
||
134 | |||
135 | /** |
||
136 | * @var float FEC:Credit |
||
137 | */ |
||
138 | public $credit; |
||
139 | |||
140 | /** |
||
141 | * @var float FEC:Amount (Not necessary) |
||
142 | * @deprecated No more used (we have info into debit/credit and sens) |
||
143 | */ |
||
144 | public $montant; |
||
145 | |||
146 | /** |
||
147 | * @var float FEC:Amount (Not necessary) |
||
148 | * @deprecated No more used (we have info into debit/credit and sens) |
||
149 | */ |
||
150 | public $amount; |
||
151 | |||
152 | /** |
||
153 | * @var string FEC:Sens (Not necessary) |
||
154 | */ |
||
155 | public $sens; |
||
156 | |||
157 | /** |
||
158 | * @var int ID |
||
159 | */ |
||
160 | public $fk_user_author; |
||
161 | |||
162 | /** |
||
163 | * @var string key for import |
||
164 | */ |
||
165 | public $import_key; |
||
166 | |||
167 | /** |
||
168 | * @var string code journal |
||
169 | */ |
||
170 | public $code_journal; |
||
171 | |||
172 | /** |
||
173 | * @var string label journal |
||
174 | */ |
||
175 | public $journal_label; |
||
176 | |||
177 | /** |
||
178 | * @var int accounting transaction id |
||
179 | */ |
||
180 | public $piece_num; |
||
181 | |||
182 | /** |
||
183 | * @var BookKeepingLine[] Movement line array |
||
184 | */ |
||
185 | public $linesmvt = array(); |
||
186 | |||
187 | /** |
||
188 | * @var BookKeepingLine[] export line array |
||
189 | */ |
||
190 | public $linesexport = array(); |
||
191 | |||
192 | /** |
||
193 | * @var integer|string date of movement validated & lock |
||
194 | */ |
||
195 | public $date_validation; |
||
196 | |||
197 | /** |
||
198 | * @var integer|string date of movement who are noticed like exported |
||
199 | */ |
||
200 | public $date_export; |
||
201 | |||
202 | /** |
||
203 | * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png |
||
204 | */ |
||
205 | public $picto = 'generic'; |
||
206 | |||
207 | /** |
||
208 | * @var string[] SQL filter used for check if the bookkeeping record can be created/inserted/modified/deleted (cached) |
||
209 | */ |
||
210 | public static $can_modify_bookkeeping_sql_cached; |
||
211 | |||
212 | |||
213 | /** |
||
214 | * Constructor |
||
215 | * |
||
216 | * @param DoliDB $db Database handler |
||
217 | */ |
||
218 | public function __construct(DoliDB $db) |
||
219 | { |
||
220 | $this->db = $db; |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Create object into database |
||
225 | * |
||
226 | * @param User $user User that creates |
||
227 | * @param int $notrigger false=launch triggers after, true=disable triggers |
||
228 | * @return int Return integer <0 if KO, Id of created object if OK |
||
229 | */ |
||
230 | public function create(User $user, $notrigger = 0) |
||
493 | } |
||
494 | } |
||
495 | |||
496 | /** |
||
497 | * Return a link to the object card (with optionally the picto) |
||
498 | * |
||
499 | * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto) |
||
500 | * @param string $option On what the link point to ('nolink', ...) |
||
501 | * @param int $notooltip 1=Disable tooltip |
||
502 | * @param string $morecss Add more css on link |
||
503 | * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking |
||
504 | * @return string String with URL |
||
505 | */ |
||
506 | public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1) |
||
507 | { |
||
508 | global $db, $conf, $langs; |
||
509 | global $dolibarr_main_authentication, $dolibarr_main_demo; |
||
510 | global $menumanager, $hookmanager; |
||
511 | |||
512 | if (!empty($conf->dol_no_mouse_hover)) { |
||
513 | $notooltip = 1; // Force disable tooltips |
||
514 | } |
||
515 | |||
516 | $result = ''; |
||
517 | $companylink = ''; |
||
518 | |||
519 | $label = '<u>' . $langs->trans("Transaction") . '</u>'; |
||
520 | $label .= '<br>'; |
||
521 | $label .= '<b>' . $langs->trans('Ref') . ':</b> ' . $this->piece_num; |
||
522 | |||
523 | $url = constant('BASE_URL') . '/accountancy/bookkeeping/card.php?piece_num=' . $this->piece_num; |
||
524 | |||
525 | if ($option != 'nolink') { |
||
526 | // Add param to save lastsearch_values or not |
||
527 | $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0); |
||
528 | if ($save_lastsearch_value == -1 && isset($_SERVER["PHP_SELF"]) && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) { |
||
529 | $add_save_lastsearch_values = 1; |
||
530 | } |
||
531 | if ($add_save_lastsearch_values) { |
||
532 | $url .= '&save_lastsearch_values=1'; |
||
533 | } |
||
534 | } |
||
535 | |||
536 | $linkclose = ''; |
||
537 | if (empty($notooltip)) { |
||
538 | if (getDolGlobalString('MAIN_OPTIMIZEFORTEXTBROWSER')) { |
||
539 | $label = $langs->trans("ShowTransaction"); |
||
540 | $linkclose .= ' alt="' . dol_escape_htmltag($label, 1) . '"'; |
||
541 | } |
||
542 | $linkclose .= ' title="' . dol_escape_htmltag($label, 1) . '"'; |
||
543 | $linkclose .= ' class="classfortooltip' . ($morecss ? ' ' . $morecss : '') . '"'; |
||
544 | } else { |
||
545 | $linkclose = ($morecss ? ' class="' . $morecss . '"' : ''); |
||
546 | } |
||
547 | |||
548 | $linkstart = '<a href="' . $url . '"'; |
||
549 | $linkstart .= $linkclose . '>'; |
||
550 | $linkend = '</a>'; |
||
551 | |||
552 | $result .= $linkstart; |
||
553 | if ($withpicto) { |
||
554 | $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); |
||
555 | } |
||
556 | if ($withpicto != 2) { |
||
557 | $result .= $this->piece_num; |
||
558 | } |
||
559 | $result .= $linkend; |
||
560 | //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); |
||
561 | |||
562 | global $action; |
||
563 | $hookmanager->initHooks(array($this->element . 'dao')); |
||
564 | $parameters = array('id' => $this->id, 'getnomurl' => &$result); |
||
565 | $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks |
||
566 | if ($reshook > 0) { |
||
567 | $result = $hookmanager->resPrint; |
||
568 | } else { |
||
569 | $result .= $hookmanager->resPrint; |
||
570 | } |
||
571 | return $result; |
||
572 | } |
||
573 | |||
574 | /** |
||
575 | * Create object into database |
||
576 | * |
||
577 | * @param User $user User that creates |
||
578 | * @param int $notrigger false=launch triggers after, true=disable triggers |
||
579 | * @param string $mode Mode |
||
580 | * @return int Return integer <0 if KO, Id of created object if OK |
||
581 | */ |
||
582 | public function createStd(User $user, $notrigger = 0, $mode = '') |
||
740 | } |
||
741 | } |
||
742 | |||
743 | /** |
||
744 | * Load object in memory from the database |
||
745 | * |
||
746 | * @param int $id Id object |
||
747 | * @param string|null $ref Ref |
||
748 | * @param string $mode Mode ('' or 'tmp_') |
||
749 | * @return int Return integer <0 if KO, 0 if not found, >0 if OK |
||
750 | */ |
||
751 | public function fetch($id, $ref = null, $mode = '') |
||
752 | { |
||
753 | global $conf; |
||
754 | |||
755 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
756 | |||
757 | $sql = 'SELECT'; |
||
758 | $sql .= ' t.rowid,'; |
||
759 | $sql .= " t.doc_date,"; |
||
760 | $sql .= " t.date_lim_reglement,"; |
||
761 | $sql .= " t.doc_type,"; |
||
762 | $sql .= " t.doc_ref,"; |
||
763 | $sql .= " t.fk_doc,"; |
||
764 | $sql .= " t.fk_docdet,"; |
||
765 | $sql .= " t.thirdparty_code,"; |
||
766 | $sql .= " t.subledger_account,"; |
||
767 | $sql .= " t.subledger_label,"; |
||
768 | $sql .= " t.numero_compte,"; |
||
769 | $sql .= " t.label_compte,"; |
||
770 | $sql .= " t.label_operation,"; |
||
771 | $sql .= " t.debit,"; |
||
772 | $sql .= " t.credit,"; |
||
773 | $sql .= " t.montant as amount,"; |
||
774 | $sql .= " t.sens,"; |
||
775 | $sql .= " t.fk_user_author,"; |
||
776 | $sql .= " t.import_key,"; |
||
777 | $sql .= " t.code_journal,"; |
||
778 | $sql .= " t.journal_label,"; |
||
779 | $sql .= " t.piece_num,"; |
||
780 | $sql .= " t.date_creation,"; |
||
781 | // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist |
||
782 | if ($mode != "_tmp") { |
||
783 | $sql .= " t.date_export,"; |
||
784 | } |
||
785 | $sql .= " t.date_validated as date_validation"; |
||
786 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . $mode . ' as t'; |
||
787 | $sql .= ' WHERE 1 = 1'; |
||
788 | $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
789 | if (null !== $ref) { |
||
790 | $sql .= " AND t.rowid = " . ((int) $ref); |
||
791 | } else { |
||
792 | $sql .= " AND t.rowid = " . ((int) $id); |
||
793 | } |
||
794 | |||
795 | $resql = $this->db->query($sql); |
||
796 | if ($resql) { |
||
797 | $numrows = $this->db->num_rows($resql); |
||
798 | if ($numrows) { |
||
799 | $obj = $this->db->fetch_object($resql); |
||
800 | |||
801 | $this->id = $obj->rowid; |
||
802 | |||
803 | $this->doc_date = $this->db->jdate($obj->doc_date); |
||
|
|||
804 | $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); |
||
805 | $this->doc_type = $obj->doc_type; |
||
806 | $this->doc_ref = $obj->doc_ref; |
||
807 | $this->fk_doc = $obj->fk_doc; |
||
808 | $this->fk_docdet = $obj->fk_docdet; |
||
809 | $this->thirdparty_code = $obj->thirdparty_code; |
||
810 | $this->subledger_account = $obj->subledger_account; |
||
811 | $this->subledger_label = $obj->subledger_label; |
||
812 | $this->numero_compte = $obj->numero_compte; |
||
813 | $this->label_compte = $obj->label_compte; |
||
814 | $this->label_operation = $obj->label_operation; |
||
815 | $this->debit = $obj->debit; |
||
816 | $this->credit = $obj->credit; |
||
817 | $this->montant = $obj->amount; |
||
818 | $this->amount = $obj->amount; |
||
819 | $this->sens = $obj->sens; |
||
820 | $this->fk_user_author = $obj->fk_user_author; |
||
821 | $this->import_key = $obj->import_key; |
||
822 | $this->code_journal = $obj->code_journal; |
||
823 | $this->journal_label = $obj->journal_label; |
||
824 | $this->piece_num = $obj->piece_num; |
||
825 | $this->date_creation = $this->db->jdate($obj->date_creation); |
||
826 | $this->date_export = $this->db->jdate($obj->date_export); |
||
827 | $this->date_validation = isset($obj->date_validation) ? $this->db->jdate($obj->date_validation) : ''; |
||
828 | } |
||
829 | $this->db->free($resql); |
||
830 | |||
831 | if ($numrows) { |
||
832 | return 1; |
||
833 | } else { |
||
834 | return 0; |
||
835 | } |
||
836 | } else { |
||
837 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
838 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
839 | |||
840 | return -1; |
||
841 | } |
||
842 | } |
||
843 | |||
844 | |||
845 | /** |
||
846 | * Load object in memory from the database in ->lines. Or just make a simple count if $countonly=1. |
||
847 | * |
||
848 | * @param string $sortorder Sort Order |
||
849 | * @param string $sortfield Sort field |
||
850 | * @param int $limit limit |
||
851 | * @param int $offset offset limit |
||
852 | * @param array $filter filter array |
||
853 | * @param string $filtermode filter mode (AND or OR) |
||
854 | * @param int $option option (0: general account or 1: subaccount) |
||
855 | * @param int $countonly Do not fill the $object->lines, return only the count. |
||
856 | * @return int Return integer <0 if KO, Number of lines if OK |
||
857 | */ |
||
858 | public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0, $countonly = 0) |
||
859 | { |
||
860 | global $conf; |
||
861 | |||
862 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
863 | |||
864 | $this->lines = array(); |
||
865 | $num = 0; |
||
866 | |||
867 | $sql = 'SELECT'; |
||
868 | if ($countonly) { |
||
869 | $sql .= ' COUNT(t.rowid) as nb'; |
||
870 | } else { |
||
871 | $sql .= ' t.rowid,'; |
||
872 | $sql .= " t.doc_date,"; |
||
873 | $sql .= " t.doc_type,"; |
||
874 | $sql .= " t.doc_ref,"; |
||
875 | $sql .= " t.fk_doc,"; |
||
876 | $sql .= " t.fk_docdet,"; |
||
877 | $sql .= " t.thirdparty_code,"; |
||
878 | $sql .= " t.subledger_account,"; |
||
879 | $sql .= " t.subledger_label,"; |
||
880 | $sql .= " t.numero_compte,"; |
||
881 | $sql .= " t.label_compte,"; |
||
882 | $sql .= " t.label_operation,"; |
||
883 | $sql .= " t.debit,"; |
||
884 | $sql .= " t.credit,"; |
||
885 | $sql .= " t.montant as amount,"; |
||
886 | $sql .= " t.sens,"; |
||
887 | $sql .= " t.multicurrency_amount,"; |
||
888 | $sql .= " t.multicurrency_code,"; |
||
889 | $sql .= " t.lettering_code,"; |
||
890 | $sql .= " t.date_lettering,"; |
||
891 | $sql .= " t.fk_user_author,"; |
||
892 | $sql .= " t.import_key,"; |
||
893 | $sql .= " t.code_journal,"; |
||
894 | $sql .= " t.journal_label,"; |
||
895 | $sql .= " t.piece_num,"; |
||
896 | $sql .= " t.date_creation,"; |
||
897 | $sql .= " t.date_export,"; |
||
898 | $sql .= " t.date_validated as date_validation,"; |
||
899 | $sql .= " t.date_lim_reglement,"; |
||
900 | $sql .= " t.import_key"; |
||
901 | } |
||
902 | // Manage filter |
||
903 | $sqlwhere = array(); |
||
904 | if (count($filter) > 0) { |
||
905 | foreach ($filter as $key => $value) { |
||
906 | if ($key == 't.doc_date>=') { |
||
907 | $sqlwhere[] = "t.doc_date >= '" . $this->db->idate($value) . "'"; |
||
908 | } elseif ($key == 't.doc_date<=') { |
||
909 | $sqlwhere[] = "t.doc_date <= '" . $this->db->idate($value) . "'"; |
||
910 | } elseif ($key == 't.doc_date>') { |
||
911 | $sqlwhere[] = "t.doc_date > '" . $this->db->idate($value) . "'"; |
||
912 | } elseif ($key == 't.doc_date<') { |
||
913 | $sqlwhere[] = "t.doc_date < '" . $this->db->idate($value) . "'"; |
||
914 | } elseif ($key == 't.numero_compte>=') { |
||
915 | $sqlwhere[] = "t.numero_compte >= '" . $this->db->escape($value) . "'"; |
||
916 | } elseif ($key == 't.numero_compte<=') { |
||
917 | $sqlwhere[] = "t.numero_compte <= '" . $this->db->escape($value) . "'"; |
||
918 | } elseif ($key == 't.subledger_account>=') { |
||
919 | $sqlwhere[] = "t.subledger_account >= '" . $this->db->escape($value) . "'"; |
||
920 | } elseif ($key == 't.subledger_account<=') { |
||
921 | $sqlwhere[] = "t.subledger_account <= '" . $this->db->escape($value) . "'"; |
||
922 | } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { |
||
923 | $sqlwhere[] = $this->db->sanitize($key) . ' = ' . ((int) $value); |
||
924 | } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { |
||
925 | $sqlwhere[] = $this->db->sanitize($key) . ' LIKE \'' . $this->db->escape($this->db->escapeforlike($value)) . '%\''; |
||
926 | } elseif ($key == 't.date_creation>=') { |
||
927 | $sqlwhere[] = 't.date_creation >= \'' . $this->db->idate($value) . '\''; |
||
928 | } elseif ($key == 't.date_creation<=') { |
||
929 | $sqlwhere[] = 't.date_creation <= \'' . $this->db->idate($value) . '\''; |
||
930 | } elseif ($key == 't.date_export>=') { |
||
931 | $sqlwhere[] = 't.date_export >= \'' . $this->db->idate($value) . '\''; |
||
932 | } elseif ($key == 't.date_export<=') { |
||
933 | $sqlwhere[] = 't.date_export <= \'' . $this->db->idate($value) . '\''; |
||
934 | } elseif ($key == 't.date_validated>=') { |
||
935 | $sqlwhere[] = 't.date_validated >= \'' . $this->db->idate($value) . '\''; |
||
936 | } elseif ($key == 't.date_validated<=') { |
||
937 | $sqlwhere[] = 't.date_validated <= \'' . $this->db->idate($value) . '\''; |
||
938 | } elseif ($key == 't.date_lim_reglement>=') { |
||
939 | $sqlwhere[] = 't.date_lim_reglement>=\'' . $this->db->idate($value) . '\''; |
||
940 | } elseif ($key == 't.date_lim_reglement<=') { |
||
941 | $sqlwhere[] = 't.date_lim_reglement<=\'' . $this->db->idate($value) . '\''; |
||
942 | } elseif ($key == 't.credit' || $key == 't.debit') { |
||
943 | $sqlwhere[] = natural_search($key, $value, 1, 1); |
||
944 | } elseif ($key == 't.reconciled_option') { |
||
945 | $sqlwhere[] = 't.lettering_code IS NULL'; |
||
946 | } elseif ($key == 't.code_journal' && !empty($value)) { |
||
947 | if (is_array($value)) { |
||
948 | $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1); |
||
949 | } else { |
||
950 | $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); |
||
951 | } |
||
952 | } elseif ($key == 't.search_accounting_code_in' && !empty($value)) { |
||
953 | $sqlwhere[] = 't.numero_compte IN (' . $this->db->sanitize($value, 1) . ')'; |
||
954 | } else { |
||
955 | $sqlwhere[] = natural_search($key, $value, 0, 1); |
||
956 | } |
||
957 | } |
||
958 | } |
||
959 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; |
||
960 | $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
961 | if (count($sqlwhere) > 0) { |
||
962 | $sql .= " AND " . implode(" " . $this->db->sanitize($filtermode) . " ", $sqlwhere); |
||
963 | } |
||
964 | // Filter by ledger account or subledger account |
||
965 | if (!empty($option)) { |
||
966 | $sql .= " AND t.subledger_account IS NOT NULL"; |
||
967 | $sql .= " AND t.subledger_account <> ''"; |
||
968 | $sortfield = 't.subledger_account' . ($sortfield ? ',' . $sortfield : ''); |
||
969 | $sortorder = 'ASC' . ($sortfield ? ',' . $sortfield : ''); |
||
970 | } else { |
||
971 | $sortfield = 't.numero_compte' . ($sortfield ? ',' . $sortfield : ''); |
||
972 | $sortorder = 'ASC' . ($sortorder ? ',' . $sortorder : ''); |
||
973 | } |
||
974 | |||
975 | if (!$countonly) { |
||
976 | $sql .= $this->db->order($sortfield, $sortorder); |
||
977 | if (!empty($limit)) { |
||
978 | $sql .= $this->db->plimit($limit + 1, $offset); |
||
979 | } |
||
980 | } |
||
981 | |||
982 | $resql = $this->db->query($sql); |
||
983 | if ($resql) { |
||
984 | if ($countonly) { |
||
985 | $obj = $this->db->fetch_object($resql); |
||
986 | if ($obj) { |
||
987 | $num = $obj->nb; |
||
988 | } |
||
989 | } else { |
||
990 | $num = $this->db->num_rows($resql); |
||
991 | |||
992 | $i = 0; |
||
993 | while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) { |
||
994 | $line = new BookKeepingLine($this->db); |
||
995 | |||
996 | $line->id = $obj->rowid; |
||
997 | |||
998 | $line->doc_date = $this->db->jdate($obj->doc_date); |
||
999 | $line->doc_type = $obj->doc_type; |
||
1000 | $line->doc_ref = $obj->doc_ref; |
||
1001 | $line->fk_doc = $obj->fk_doc; |
||
1002 | $line->fk_docdet = $obj->fk_docdet; |
||
1003 | $line->thirdparty_code = $obj->thirdparty_code; |
||
1004 | $line->subledger_account = $obj->subledger_account; |
||
1005 | $line->subledger_label = $obj->subledger_label; |
||
1006 | $line->numero_compte = $obj->numero_compte; |
||
1007 | $line->label_compte = $obj->label_compte; |
||
1008 | $line->label_operation = $obj->label_operation; |
||
1009 | $line->debit = $obj->debit; |
||
1010 | $line->credit = $obj->credit; |
||
1011 | $line->montant = $obj->amount; // deprecated |
||
1012 | $line->amount = $obj->amount; |
||
1013 | $line->sens = $obj->sens; |
||
1014 | $line->multicurrency_amount = $obj->multicurrency_amount; |
||
1015 | $line->multicurrency_code = $obj->multicurrency_code; |
||
1016 | $line->lettering_code = $obj->lettering_code; |
||
1017 | $line->date_lettering = $obj->date_lettering; |
||
1018 | $line->fk_user_author = $obj->fk_user_author; |
||
1019 | $line->import_key = $obj->import_key; |
||
1020 | $line->code_journal = $obj->code_journal; |
||
1021 | $line->journal_label = $obj->journal_label; |
||
1022 | $line->piece_num = $obj->piece_num; |
||
1023 | $line->date_creation = $this->db->jdate($obj->date_creation); |
||
1024 | $line->date_export = $this->db->jdate($obj->date_export); |
||
1025 | $line->date_validation = $this->db->jdate($obj->date_validation); |
||
1026 | // Due date |
||
1027 | $line->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); |
||
1028 | $line->import_key = $obj->import_key; |
||
1029 | |||
1030 | $this->lines[] = $line; |
||
1031 | |||
1032 | $i++; |
||
1033 | } |
||
1034 | } |
||
1035 | $this->db->free($resql); |
||
1036 | |||
1037 | return $num; |
||
1038 | } else { |
||
1039 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1040 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1041 | |||
1042 | return -1; |
||
1043 | } |
||
1044 | } |
||
1045 | |||
1046 | /** |
||
1047 | * Load object in memory from the database |
||
1048 | * |
||
1049 | * @param string $sortorder Sort Order |
||
1050 | * @param string $sortfield Sort field |
||
1051 | * @param int $limit Limit |
||
1052 | * @param int $offset Offset limit |
||
1053 | * @param string|array $filter Filter array |
||
1054 | * @param string $filtermode Filter mode (AND or OR) |
||
1055 | * @param int $showAlreadyExportMovements Show movements when field 'date_export' is not empty (0:No / 1:Yes (Default)) |
||
1056 | * @return int Return integer <0 if KO, >0 if OK |
||
1057 | */ |
||
1058 | public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND', $showAlreadyExportMovements = 1) |
||
1059 | { |
||
1060 | global $conf; |
||
1061 | |||
1062 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1063 | |||
1064 | $sql = 'SELECT'; |
||
1065 | $sql .= ' t.rowid,'; |
||
1066 | $sql .= " t.doc_date,"; |
||
1067 | $sql .= " t.doc_type,"; |
||
1068 | $sql .= " t.doc_ref,"; |
||
1069 | $sql .= " t.fk_doc,"; |
||
1070 | $sql .= " t.fk_docdet,"; |
||
1071 | $sql .= " t.thirdparty_code,"; |
||
1072 | $sql .= " t.subledger_account,"; |
||
1073 | $sql .= " t.subledger_label,"; |
||
1074 | $sql .= " t.numero_compte,"; |
||
1075 | $sql .= " t.label_compte,"; |
||
1076 | $sql .= " t.label_operation,"; |
||
1077 | $sql .= " t.debit,"; |
||
1078 | $sql .= " t.credit,"; |
||
1079 | $sql .= " t.lettering_code,"; |
||
1080 | $sql .= " t.date_lettering,"; |
||
1081 | $sql .= " t.montant as amount,"; |
||
1082 | $sql .= " t.sens,"; |
||
1083 | $sql .= " t.fk_user_author,"; |
||
1084 | $sql .= " t.import_key,"; |
||
1085 | $sql .= " t.code_journal,"; |
||
1086 | $sql .= " t.journal_label,"; |
||
1087 | $sql .= " t.piece_num,"; |
||
1088 | $sql .= " t.date_creation,"; |
||
1089 | $sql .= " t.date_lim_reglement,"; |
||
1090 | $sql .= " t.tms as date_modification,"; |
||
1091 | $sql .= " t.date_export,"; |
||
1092 | $sql .= " t.date_validated as date_validation"; |
||
1093 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; |
||
1094 | |||
1095 | $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1096 | if ($showAlreadyExportMovements == 0) { |
||
1097 | $sql .= " AND t.date_export IS NULL"; |
||
1098 | } |
||
1099 | |||
1100 | // Manage filter |
||
1101 | if (is_array($filter)) { // deprecated, use $filter = USF syntax |
||
1102 | $sqlwhere = array(); |
||
1103 | if (count($filter) > 0) { |
||
1104 | foreach ($filter as $key => $value) { |
||
1105 | if ($key == 't.doc_date') { |
||
1106 | $sqlwhere[] = $this->db->sanitize($key) . ' = \'' . $this->db->idate($value) . '\''; |
||
1107 | } elseif ($key == 't.doc_date>=') { |
||
1108 | $sqlwhere[] = "t.doc_date >= '" . $this->db->idate($value) . "'"; |
||
1109 | } elseif ($key == 't.doc_date<=') { |
||
1110 | $sqlwhere[] = "t.doc_date <= '" . $this->db->idate($value) . "'"; |
||
1111 | } elseif ($key == 't.doc_date>') { |
||
1112 | $sqlwhere[] = "t.doc_date > '" . $this->db->idate($value) . "'"; |
||
1113 | } elseif ($key == 't.doc_date<') { |
||
1114 | $sqlwhere[] = "t.doc_date < '" . $this->db->idate($value) . "'"; |
||
1115 | } elseif ($key == 't.numero_compte>=') { |
||
1116 | $sqlwhere[] = "t.numero_compte >= '" . $this->db->escape($value) . "'"; |
||
1117 | } elseif ($key == 't.numero_compte<=') { |
||
1118 | $sqlwhere[] = "t.numero_compte <= '" . $this->db->escape($value) . "'"; |
||
1119 | } elseif ($key == 't.subledger_account>=') { |
||
1120 | $sqlwhere[] = "t.subledger_account >= '" . $this->db->escape($value) . "'"; |
||
1121 | } elseif ($key == 't.subledger_account<=') { |
||
1122 | $sqlwhere[] = "t.subledger_account <= '" . $this->db->escape($value) . "'"; |
||
1123 | } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { |
||
1124 | $sqlwhere[] = $this->db->sanitize($key) . ' = ' . ((int) $value); |
||
1125 | } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { |
||
1126 | $sqlwhere[] = $this->db->sanitize($key) . ' LIKE \'' . $this->db->escape($value) . '%\''; |
||
1127 | } elseif ($key == 't.date_creation>=') { |
||
1128 | $sqlwhere[] = 't.date_creation >= \'' . $this->db->idate($value) . '\''; |
||
1129 | } elseif ($key == 't.date_creation<=') { |
||
1130 | $sqlwhere[] = 't.date_creation <= \'' . $this->db->idate($value) . '\''; |
||
1131 | } elseif ($key == 't.tms>=') { |
||
1132 | $sqlwhere[] = 't.tms >= \'' . $this->db->idate($value) . '\''; |
||
1133 | } elseif ($key == 't.tms<=') { |
||
1134 | $sqlwhere[] = 't.tms <= \'' . $this->db->idate($value) . '\''; |
||
1135 | } elseif ($key == 't.date_export>=') { |
||
1136 | $sqlwhere[] = 't.date_export >= \'' . $this->db->idate($value) . '\''; |
||
1137 | } elseif ($key == 't.date_export<=') { |
||
1138 | $sqlwhere[] = 't.date_export <= \'' . $this->db->idate($value) . '\''; |
||
1139 | } elseif ($key == 't.date_validated>=') { |
||
1140 | $sqlwhere[] = 't.date_validated >= \'' . $this->db->idate($value) . '\''; |
||
1141 | } elseif ($key == 't.date_validated<=') { |
||
1142 | $sqlwhere[] = 't.date_validated <= \'' . $this->db->idate($value) . '\''; |
||
1143 | } elseif ($key == 't.credit' || $key == 't.debit') { |
||
1144 | $sqlwhere[] = natural_search($key, $value, 1, 1); |
||
1145 | } elseif ($key == 't.code_journal' && !empty($value)) { |
||
1146 | if (is_array($value)) { |
||
1147 | $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1); |
||
1148 | } else { |
||
1149 | $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); |
||
1150 | } |
||
1151 | } else { |
||
1152 | $sqlwhere[] = natural_search($key, $value, 0, 1); |
||
1153 | } |
||
1154 | } |
||
1155 | } |
||
1156 | if (count($sqlwhere) > 0) { |
||
1157 | $sql .= ' AND ' . implode(" " . $this->db->sanitize($filtermode) . " ", $sqlwhere); |
||
1158 | } |
||
1159 | |||
1160 | $filter = ''; |
||
1161 | } |
||
1162 | |||
1163 | // Manage filter |
||
1164 | $errormessage = ''; |
||
1165 | $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); |
||
1166 | if ($errormessage) { |
||
1167 | $this->errors[] = $errormessage; |
||
1168 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1169 | return -1; |
||
1170 | } |
||
1171 | |||
1172 | if (!empty($sortfield)) { |
||
1173 | $sql .= $this->db->order($sortfield, $sortorder); |
||
1174 | } |
||
1175 | if (!empty($limit)) { |
||
1176 | $sql .= $this->db->plimit($limit + 1, $offset); |
||
1177 | } |
||
1178 | $this->lines = array(); |
||
1179 | |||
1180 | $resql = $this->db->query($sql); |
||
1181 | if ($resql) { |
||
1182 | $num = $this->db->num_rows($resql); |
||
1183 | |||
1184 | $i = 0; |
||
1185 | while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) { |
||
1186 | $line = new BookKeepingLine($this->db); |
||
1187 | |||
1188 | $line->id = $obj->rowid; |
||
1189 | |||
1190 | $line->doc_date = $this->db->jdate($obj->doc_date); |
||
1191 | $line->doc_type = $obj->doc_type; |
||
1192 | $line->doc_ref = $obj->doc_ref; |
||
1193 | $line->fk_doc = $obj->fk_doc; |
||
1194 | $line->fk_docdet = $obj->fk_docdet; |
||
1195 | $line->thirdparty_code = $obj->thirdparty_code; |
||
1196 | $line->subledger_account = $obj->subledger_account; |
||
1197 | $line->subledger_label = $obj->subledger_label; |
||
1198 | $line->numero_compte = $obj->numero_compte; |
||
1199 | $line->label_compte = $obj->label_compte; |
||
1200 | $line->label_operation = $obj->label_operation; |
||
1201 | $line->debit = $obj->debit; |
||
1202 | $line->credit = $obj->credit; |
||
1203 | $line->montant = $obj->amount; // deprecated |
||
1204 | $line->amount = $obj->amount; |
||
1205 | $line->sens = $obj->sens; |
||
1206 | $line->lettering_code = $obj->lettering_code; |
||
1207 | $line->date_lettering = $obj->date_lettering; |
||
1208 | $line->fk_user_author = $obj->fk_user_author; |
||
1209 | $line->import_key = $obj->import_key; |
||
1210 | $line->code_journal = $obj->code_journal; |
||
1211 | $line->journal_label = $obj->journal_label; |
||
1212 | $line->piece_num = $obj->piece_num; |
||
1213 | $line->date_creation = $this->db->jdate($obj->date_creation); |
||
1214 | $line->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); |
||
1215 | $line->date_modification = $this->db->jdate($obj->date_modification); |
||
1216 | $line->date_export = $this->db->jdate($obj->date_export); |
||
1217 | $line->date_validation = $this->db->jdate($obj->date_validation); |
||
1218 | |||
1219 | $this->lines[] = $line; |
||
1220 | |||
1221 | $i++; |
||
1222 | } |
||
1223 | $this->db->free($resql); |
||
1224 | |||
1225 | return $num; |
||
1226 | } else { |
||
1227 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1228 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1229 | return -1; |
||
1230 | } |
||
1231 | } |
||
1232 | |||
1233 | /** |
||
1234 | * Load object in memory from the database |
||
1235 | * |
||
1236 | * @param string $sortorder Sort Order |
||
1237 | * @param string $sortfield Sort field |
||
1238 | * @param int $limit Limit |
||
1239 | * @param int $offset Offset limit |
||
1240 | * @param string|array $filter Filter |
||
1241 | * @param string $filtermode Filter mode (AND or OR) |
||
1242 | * @param int $option option (0: aggregate by general account or 1: aggreegate by subaccount) |
||
1243 | * @return int Return integer <0 if KO, >0 if OK |
||
1244 | */ |
||
1245 | public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND', $option = 0) |
||
1246 | { |
||
1247 | global $conf; |
||
1248 | |||
1249 | $this->lines = array(); |
||
1250 | |||
1251 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1252 | |||
1253 | $sql = 'SELECT'; |
||
1254 | $sql .= " t.numero_compte,"; |
||
1255 | if (!empty($option)) { |
||
1256 | $sql .= " t.subledger_account,"; |
||
1257 | $sql .= " t.subledger_label,"; |
||
1258 | } |
||
1259 | $sql .= " SUM(t.debit) as debit,"; |
||
1260 | $sql .= " SUM(t.credit) as credit"; |
||
1261 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; |
||
1262 | $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1263 | |||
1264 | // Manage filter |
||
1265 | if (is_array($filter)) { |
||
1266 | $sqlwhere = array(); |
||
1267 | if (count($filter) > 0) { |
||
1268 | foreach ($filter as $key => $value) { |
||
1269 | if ($key == 't.doc_date') { |
||
1270 | $sqlwhere[] = $this->db->sanitize($key) . " = '" . $this->db->idate($value) . "'"; |
||
1271 | } elseif ($key == 't.doc_date>=') { |
||
1272 | $sqlwhere[] = "t.doc_date >= '" . $this->db->idate($value) . "'"; |
||
1273 | } elseif ($key == 't.doc_date<=') { |
||
1274 | $sqlwhere[] = "t.doc_date <= '" . $this->db->idate($value) . "'"; |
||
1275 | } elseif ($key == 't.doc_date>') { |
||
1276 | $sqlwhere[] = "t.doc_date > '" . $this->db->idate($value) . "'"; |
||
1277 | } elseif ($key == 't.doc_date<') { |
||
1278 | $sqlwhere[] = "t.doc_date < '" . $this->db->idate($value) . "'"; |
||
1279 | } elseif ($key == 't.numero_compte>=') { |
||
1280 | $sqlwhere[] = "t.numero_compte >= '" . $this->db->escape($value) . "'"; |
||
1281 | } elseif ($key == 't.numero_compte<=') { |
||
1282 | $sqlwhere[] = "t.numero_compte <= '" . $this->db->escape($value) . "'"; |
||
1283 | } elseif ($key == 't.subledger_account>=') { |
||
1284 | $sqlwhere[] = "t.subledger_account >= '" . $this->db->escape($value) . "'"; |
||
1285 | } elseif ($key == 't.subledger_account<=') { |
||
1286 | $sqlwhere[] = "t.subledger_account <= '" . $this->db->escape($value) . "'"; |
||
1287 | } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') { |
||
1288 | $sqlwhere[] = $this->db->sanitize($key) . " = " . ((int) $value); |
||
1289 | } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') { |
||
1290 | $sqlwhere[] = $this->db->sanitize($key) . " LIKE '" . $this->db->escape($value) . "%'"; |
||
1291 | } elseif ($key == 't.subledger_label') { |
||
1292 | $sqlwhere[] = $this->db->sanitize($key) . " LIKE '" . $this->db->escape($value) . "%'"; |
||
1293 | } elseif ($key == 't.code_journal' && !empty($value)) { |
||
1294 | if (is_array($value)) { |
||
1295 | $sqlwhere[] = natural_search("t.code_journal", implode(',', $value), 3, 1); |
||
1296 | } else { |
||
1297 | $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1); |
||
1298 | } |
||
1299 | } elseif ($key == 't.reconciled_option') { |
||
1300 | $sqlwhere[] = 't.lettering_code IS NULL'; |
||
1301 | } else { |
||
1302 | $sqlwhere[] = $this->db->sanitize($key) . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'"; |
||
1303 | } |
||
1304 | } |
||
1305 | } |
||
1306 | if (count($sqlwhere) > 0) { |
||
1307 | $sql .= " AND " . implode(" " . $this->db->sanitize($filtermode) . " ", $sqlwhere); |
||
1308 | } |
||
1309 | |||
1310 | $filter = ''; |
||
1311 | } |
||
1312 | |||
1313 | // Manage filter |
||
1314 | $errormessage = ''; |
||
1315 | $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); |
||
1316 | if ($errormessage) { |
||
1317 | $this->errors[] = $errormessage; |
||
1318 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1319 | return -1; |
||
1320 | } |
||
1321 | |||
1322 | if (!empty($option)) { |
||
1323 | $sql .= " AND t.subledger_account IS NOT NULL"; |
||
1324 | $sql .= " AND t.subledger_account <> ''"; |
||
1325 | $sql .= " GROUP BY t.numero_compte, t.subledger_account, t.subledger_label"; |
||
1326 | $sortfield = 't.subledger_account' . ($sortfield ? ',' . $sortfield : ''); |
||
1327 | $sortorder = 'ASC' . ($sortfield ? ',' . $sortfield : ''); |
||
1328 | } else { |
||
1329 | $sql .= ' GROUP BY t.numero_compte'; |
||
1330 | $sortfield = 't.numero_compte' . ($sortfield ? ',' . $sortfield : ''); |
||
1331 | $sortorder = 'ASC' . ($sortorder ? ',' . $sortorder : ''); |
||
1332 | } |
||
1333 | |||
1334 | if (!empty($sortfield)) { |
||
1335 | $sql .= $this->db->order($sortfield, $sortorder); |
||
1336 | } |
||
1337 | if (!empty($limit)) { |
||
1338 | $sql .= $this->db->plimit($limit + 1, $offset); |
||
1339 | } |
||
1340 | |||
1341 | //print $sql; |
||
1342 | $resql = $this->db->query($sql); |
||
1343 | |||
1344 | if ($resql) { |
||
1345 | $num = $this->db->num_rows($resql); |
||
1346 | |||
1347 | $i = 0; |
||
1348 | while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) { |
||
1349 | $line = new BookKeepingLine($this->db); |
||
1350 | |||
1351 | $line->numero_compte = $obj->numero_compte; |
||
1352 | //$line->label_compte = $obj->label_compte; |
||
1353 | if (!empty($option)) { |
||
1354 | $line->subledger_account = $obj->subledger_account; |
||
1355 | $line->subledger_label = $obj->subledger_label; |
||
1356 | } |
||
1357 | $line->debit = $obj->debit; |
||
1358 | $line->credit = $obj->credit; |
||
1359 | |||
1360 | $this->lines[] = $line; |
||
1361 | |||
1362 | $i++; |
||
1363 | } |
||
1364 | $this->db->free($resql); |
||
1365 | |||
1366 | return $num; |
||
1367 | } else { |
||
1368 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1369 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1370 | |||
1371 | return -1; |
||
1372 | } |
||
1373 | } |
||
1374 | |||
1375 | /** |
||
1376 | * Update object into database |
||
1377 | * |
||
1378 | * @param User $user User that modifies |
||
1379 | * @param int $notrigger false=launch triggers after, true=disable triggers |
||
1380 | * @param string $mode Mode ('' or _tmp') |
||
1381 | * @return int Return integer <0 if KO, >0 if OK |
||
1382 | */ |
||
1383 | public function update(User $user, $notrigger = 0, $mode = '') |
||
1384 | { |
||
1385 | global $langs; |
||
1386 | $error = 0; |
||
1387 | |||
1388 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1389 | |||
1390 | // Clean parameters |
||
1391 | if (isset($this->doc_type)) { |
||
1392 | $this->doc_type = trim($this->doc_type); |
||
1393 | } |
||
1394 | if (isset($this->doc_ref)) { |
||
1395 | $this->doc_ref = trim($this->doc_ref); |
||
1396 | } |
||
1397 | if (isset($this->fk_doc)) { |
||
1398 | $this->fk_doc = (int) $this->fk_doc; |
||
1399 | } |
||
1400 | if (isset($this->fk_docdet)) { |
||
1401 | $this->fk_docdet = (int) $this->fk_docdet; |
||
1402 | } |
||
1403 | if (isset($this->thirdparty_code)) { |
||
1404 | $this->thirdparty_code = trim($this->thirdparty_code); |
||
1405 | } |
||
1406 | if (isset($this->subledger_account)) { |
||
1407 | $this->subledger_account = trim($this->subledger_account); |
||
1408 | } |
||
1409 | if (isset($this->subledger_label)) { |
||
1410 | $this->subledger_label = trim($this->subledger_label); |
||
1411 | } |
||
1412 | if (isset($this->numero_compte)) { |
||
1413 | $this->numero_compte = trim($this->numero_compte); |
||
1414 | } |
||
1415 | if (isset($this->label_compte)) { |
||
1416 | $this->label_compte = trim($this->label_compte); |
||
1417 | } |
||
1418 | if (isset($this->label_operation)) { |
||
1419 | $this->label_operation = trim($this->label_operation); |
||
1420 | } |
||
1421 | if (isset($this->sens)) { |
||
1422 | $this->sens = trim($this->sens); |
||
1423 | } |
||
1424 | if (isset($this->import_key)) { |
||
1425 | $this->import_key = trim($this->import_key); |
||
1426 | } |
||
1427 | if (isset($this->code_journal)) { |
||
1428 | $this->code_journal = trim($this->code_journal); |
||
1429 | } |
||
1430 | if (isset($this->journal_label)) { |
||
1431 | $this->journal_label = trim($this->journal_label); |
||
1432 | } |
||
1433 | if (isset($this->piece_num)) { |
||
1434 | $this->piece_num = (int) $this->piece_num; |
||
1435 | } |
||
1436 | |||
1437 | $result = $this->canModifyBookkeeping($this->id, $mode); |
||
1438 | if ($result < 0) { |
||
1439 | return -1; |
||
1440 | } elseif ($result == 0) { |
||
1441 | if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') { |
||
1442 | $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod'); |
||
1443 | } else { |
||
1444 | $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod'); |
||
1445 | } |
||
1446 | return -1; |
||
1447 | } |
||
1448 | |||
1449 | $this->debit = (float) price2num($this->debit, 'MT'); |
||
1450 | $this->credit = (float) price2num($this->credit, 'MT'); |
||
1451 | $this->montant = (float) price2num($this->montant, 'MT'); |
||
1452 | |||
1453 | // Check parameters |
||
1454 | // Put here code to add a control on parameters values |
||
1455 | |||
1456 | // Update request |
||
1457 | $sql = 'UPDATE ' . MAIN_DB_PREFIX . $this->table_element . $mode . ' SET'; |
||
1458 | $sql .= ' doc_date = ' . (!isset($this->doc_date) || dol_strlen($this->doc_date) != 0 ? "'" . $this->db->idate($this->doc_date) . "'" : 'null') . ','; |
||
1459 | $sql .= ' doc_type = ' . (isset($this->doc_type) ? "'" . $this->db->escape($this->doc_type) . "'" : "null") . ','; |
||
1460 | $sql .= ' doc_ref = ' . (isset($this->doc_ref) ? "'" . $this->db->escape($this->doc_ref) . "'" : "null") . ','; |
||
1461 | $sql .= ' fk_doc = ' . (isset($this->fk_doc) ? $this->fk_doc : "null") . ','; |
||
1462 | $sql .= ' fk_docdet = ' . (isset($this->fk_docdet) ? $this->fk_docdet : "null") . ','; |
||
1463 | $sql .= ' thirdparty_code = ' . (isset($this->thirdparty_code) ? "'" . $this->db->escape($this->thirdparty_code) . "'" : "null") . ','; |
||
1464 | $sql .= ' subledger_account = ' . (isset($this->subledger_account) ? "'" . $this->db->escape($this->subledger_account) . "'" : "null") . ','; |
||
1465 | $sql .= ' subledger_label = ' . (isset($this->subledger_label) ? "'" . $this->db->escape($this->subledger_label) . "'" : "null") . ','; |
||
1466 | $sql .= ' numero_compte = ' . (isset($this->numero_compte) ? "'" . $this->db->escape($this->numero_compte) . "'" : "null") . ','; |
||
1467 | $sql .= ' label_compte = ' . (isset($this->label_compte) ? "'" . $this->db->escape($this->label_compte) . "'" : "null") . ','; |
||
1468 | $sql .= ' label_operation = ' . (isset($this->label_operation) ? "'" . $this->db->escape($this->label_operation) . "'" : "null") . ','; |
||
1469 | $sql .= ' debit = ' . (isset($this->debit) ? $this->debit : "null") . ','; |
||
1470 | $sql .= ' credit = ' . (isset($this->credit) ? $this->credit : "null") . ','; |
||
1471 | $sql .= ' montant = ' . (isset($this->montant) ? $this->montant : "null") . ','; |
||
1472 | $sql .= ' sens = ' . (isset($this->sens) ? "'" . $this->db->escape($this->sens) . "'" : "null") . ','; |
||
1473 | $sql .= ' fk_user_author = ' . (isset($this->fk_user_author) ? $this->fk_user_author : "null") . ','; |
||
1474 | $sql .= ' import_key = ' . (isset($this->import_key) ? "'" . $this->db->escape($this->import_key) . "'" : "null") . ','; |
||
1475 | $sql .= ' code_journal = ' . (isset($this->code_journal) ? "'" . $this->db->escape($this->code_journal) . "'" : "null") . ','; |
||
1476 | $sql .= ' journal_label = ' . (isset($this->journal_label) ? "'" . $this->db->escape($this->journal_label) . "'" : "null") . ','; |
||
1477 | $sql .= ' piece_num = ' . (isset($this->piece_num) ? $this->piece_num : "null"); |
||
1478 | $sql .= ' WHERE rowid=' . ((int) $this->id); |
||
1479 | |||
1480 | $this->db->begin(); |
||
1481 | |||
1482 | $resql = $this->db->query($sql); |
||
1483 | if (!$resql) { |
||
1484 | $error++; |
||
1485 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1486 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1487 | } |
||
1488 | |||
1489 | // Uncomment this and change MYOBJECT to your own tag if you |
||
1490 | // want this action calls a trigger. |
||
1491 | //if (! $error && ! $notrigger) { |
||
1492 | |||
1493 | // // Call triggers |
||
1494 | // $result=$this->call_trigger('MYOBJECT_MODIFY',$user); |
||
1495 | // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} |
||
1496 | // // End call triggers |
||
1497 | //} |
||
1498 | |||
1499 | // Commit or rollback |
||
1500 | if ($error) { |
||
1501 | $this->db->rollback(); |
||
1502 | |||
1503 | return -1 * $error; |
||
1504 | } else { |
||
1505 | $this->db->commit(); |
||
1506 | |||
1507 | return 1; |
||
1508 | } |
||
1509 | } |
||
1510 | |||
1511 | /** |
||
1512 | * Update accounting movement |
||
1513 | * |
||
1514 | * @param string $piece_num Piece num |
||
1515 | * @param string $field Field |
||
1516 | * @param string $value Value |
||
1517 | * @param string $mode Mode ('' or _tmp') |
||
1518 | * @return int Return integer <0 if KO, >0 if OK |
||
1519 | */ |
||
1520 | public function updateByMvt($piece_num = '', $field = '', $value = '', $mode = '') |
||
1521 | { |
||
1522 | $error = 0; |
||
1523 | |||
1524 | $sql_filter = $this->getCanModifyBookkeepingSQL(); |
||
1525 | if (!isset($sql_filter)) { |
||
1526 | return -1; |
||
1527 | } |
||
1528 | |||
1529 | $this->db->begin(); |
||
1530 | |||
1531 | $sql = "UPDATE " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1532 | $sql .= " SET " . $this->db->sanitize($field) . " = " . (is_numeric($value) ? ((float) $value) : "'" . $this->db->escape($value) . "'"); |
||
1533 | $sql .= " WHERE piece_num = " . ((int) $piece_num); |
||
1534 | $sql .= $sql_filter; |
||
1535 | |||
1536 | $resql = $this->db->query($sql); |
||
1537 | |||
1538 | if (!$resql) { |
||
1539 | $error++; |
||
1540 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1541 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1542 | } |
||
1543 | if ($error) { |
||
1544 | $this->db->rollback(); |
||
1545 | |||
1546 | return -1 * $error; |
||
1547 | } else { |
||
1548 | $this->db->commit(); |
||
1549 | |||
1550 | return 1; |
||
1551 | } |
||
1552 | } |
||
1553 | |||
1554 | /** |
||
1555 | * Delete object in database |
||
1556 | * |
||
1557 | * @param User $user User that deletes |
||
1558 | * @param int $notrigger 0=launch triggers after, 1=disable triggers |
||
1559 | * @param string $mode Mode ('' or 'tmp_') |
||
1560 | * @return int Return integer <0 if KO, >0 if OK |
||
1561 | */ |
||
1562 | public function delete(User $user, $notrigger = 0, $mode = '') |
||
1563 | { |
||
1564 | global $langs; |
||
1565 | |||
1566 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1567 | |||
1568 | $result = $this->canModifyBookkeeping($this->id, $mode); |
||
1569 | if ($result < 0) { |
||
1570 | return -1; |
||
1571 | } elseif ($result == 0) { |
||
1572 | if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') { |
||
1573 | $this->errors[] = $langs->trans('ErrorBookkeepingDocDateIsOnAClosedFiscalPeriod'); |
||
1574 | } else { |
||
1575 | $this->errors[] = $langs->trans('ErrorBookkeepingDocDateNotOnActiveFiscalPeriod'); |
||
1576 | } |
||
1577 | return -1; |
||
1578 | } |
||
1579 | |||
1580 | $error = 0; |
||
1581 | |||
1582 | $this->db->begin(); |
||
1583 | |||
1584 | // Uncomment this and change MYOBJECT to your own tag if you |
||
1585 | // want this action calls a trigger. |
||
1586 | //if (! $error && ! $notrigger) { |
||
1587 | |||
1588 | // // Call triggers |
||
1589 | // $result=$this->call_trigger('MYOBJECT_DELETE',$user); |
||
1590 | // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail} |
||
1591 | // // End call triggers |
||
1592 | //} |
||
1593 | |||
1594 | if (!$error) { |
||
1595 | $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1596 | $sql .= ' WHERE rowid=' . ((int) $this->id); |
||
1597 | |||
1598 | $resql = $this->db->query($sql); |
||
1599 | if (!$resql) { |
||
1600 | $error++; |
||
1601 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
1602 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1603 | } |
||
1604 | } |
||
1605 | |||
1606 | // Commit or rollback |
||
1607 | if ($error) { |
||
1608 | $this->db->rollback(); |
||
1609 | |||
1610 | return -1 * $error; |
||
1611 | } else { |
||
1612 | $this->db->commit(); |
||
1613 | |||
1614 | return 1; |
||
1615 | } |
||
1616 | } |
||
1617 | |||
1618 | /** |
||
1619 | * Delete bookkeeping by importkey |
||
1620 | * |
||
1621 | * @param string $importkey Import key |
||
1622 | * @param string $mode Mode |
||
1623 | * @return int Result |
||
1624 | */ |
||
1625 | public function deleteByImportkey($importkey, $mode = '') |
||
1626 | { |
||
1627 | $this->db->begin(); |
||
1628 | |||
1629 | $sql_filter = $this->getCanModifyBookkeepingSQL(); |
||
1630 | if (!isset($sql_filter)) { |
||
1631 | return -1; |
||
1632 | } |
||
1633 | |||
1634 | // first check if line not yet in bookkeeping |
||
1635 | $sql = "DELETE"; |
||
1636 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1637 | $sql .= " WHERE import_key = '" . $this->db->escape($importkey) . "'"; |
||
1638 | $sql .= $sql_filter; |
||
1639 | |||
1640 | $resql = $this->db->query($sql); |
||
1641 | |||
1642 | if (!$resql) { |
||
1643 | $this->errors[] = "Error " . $this->db->lasterror(); |
||
1644 | dol_syslog(get_only_class($this) . "::delete Error " . $this->db->lasterror(), LOG_ERR); |
||
1645 | $this->db->rollback(); |
||
1646 | return -1; |
||
1647 | } |
||
1648 | |||
1649 | $this->db->commit(); |
||
1650 | return 1; |
||
1651 | } |
||
1652 | |||
1653 | /** |
||
1654 | * Delete bookkeeping by year |
||
1655 | * |
||
1656 | * @param int $delyear Year to delete |
||
1657 | * @param string $journal Journal to delete |
||
1658 | * @param string $mode Mode |
||
1659 | * @param int $delmonth Month |
||
1660 | * @return int Return integer <0 if KO, >0 if OK |
||
1661 | */ |
||
1662 | public function deleteByYearAndJournal($delyear = 0, $journal = '', $mode = '', $delmonth = 0) |
||
1663 | { |
||
1664 | global $conf, $langs; |
||
1665 | |||
1666 | if (empty($delyear) && empty($journal)) { |
||
1667 | $this->error = 'ErrorOneFieldRequired'; |
||
1668 | return -1; |
||
1669 | } |
||
1670 | if (!empty($delmonth) && empty($delyear)) { |
||
1671 | $this->error = 'YearRequiredIfMonthDefined'; |
||
1672 | return -2; |
||
1673 | } |
||
1674 | |||
1675 | $sql_filter = $this->getCanModifyBookkeepingSQL(); |
||
1676 | if (!isset($sql_filter)) { |
||
1677 | return -1; |
||
1678 | } |
||
1679 | |||
1680 | $this->db->begin(); |
||
1681 | |||
1682 | // Delete record in bookkeeping |
||
1683 | $sql = "DELETE"; |
||
1684 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1685 | $sql .= " WHERE 1 = 1"; |
||
1686 | $sql .= dolSqlDateFilter('doc_date', 0, $delmonth, $delyear); |
||
1687 | if (!empty($journal)) { |
||
1688 | $sql .= " AND code_journal = '" . $this->db->escape($journal) . "'"; |
||
1689 | } |
||
1690 | $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1691 | // Exclusion of validated entries at the time of deletion |
||
1692 | $sql .= " AND date_validated IS NULL"; |
||
1693 | $sql .= $sql_filter; |
||
1694 | |||
1695 | // TODO: In a future we must forbid deletion if record is inside a closed fiscal period. |
||
1696 | |||
1697 | $resql = $this->db->query($sql); |
||
1698 | |||
1699 | if (!$resql) { |
||
1700 | $this->errors[] = "Error " . $this->db->lasterror(); |
||
1701 | foreach ($this->errors as $errmsg) { |
||
1702 | dol_syslog(get_only_class($this) . "::delete " . $errmsg, LOG_ERR); |
||
1703 | $this->error .= ($this->error ? ', ' . $errmsg : $errmsg); |
||
1704 | } |
||
1705 | $this->db->rollback(); |
||
1706 | return -1; |
||
1707 | } |
||
1708 | |||
1709 | $this->db->commit(); |
||
1710 | return 1; |
||
1711 | } |
||
1712 | |||
1713 | /** |
||
1714 | * Delete bookkeeping by piece number |
||
1715 | * |
||
1716 | * @param int $piecenum Piecenum to delete |
||
1717 | * @param string $mode Mode ('' or '_tmp') |
||
1718 | * @return int Result |
||
1719 | */ |
||
1720 | public function deleteMvtNum($piecenum, $mode = '') |
||
1721 | { |
||
1722 | global $conf; |
||
1723 | |||
1724 | $sql_filter = $this->getCanModifyBookkeepingSQL(); |
||
1725 | if (!isset($sql_filter)) { |
||
1726 | return -1; |
||
1727 | } |
||
1728 | |||
1729 | $this->db->begin(); |
||
1730 | |||
1731 | // first check if line not yet in bookkeeping |
||
1732 | $sql = "DELETE"; |
||
1733 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1734 | $sql .= " WHERE piece_num = " . (int) $piecenum; |
||
1735 | $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion |
||
1736 | $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1737 | $sql .= $sql_filter; |
||
1738 | |||
1739 | $resql = $this->db->query($sql); |
||
1740 | |||
1741 | if (!$resql) { |
||
1742 | $this->errors[] = "Error " . $this->db->lasterror(); |
||
1743 | foreach ($this->errors as $errmsg) { |
||
1744 | dol_syslog(get_only_class($this) . "::delete " . $errmsg, LOG_ERR); |
||
1745 | $this->error .= ($this->error ? ', ' . $errmsg : $errmsg); |
||
1746 | } |
||
1747 | $this->db->rollback(); |
||
1748 | return -1; |
||
1749 | } |
||
1750 | |||
1751 | $this->db->commit(); |
||
1752 | return 1; |
||
1753 | } |
||
1754 | |||
1755 | /** |
||
1756 | * Load an object from its id and create a new one in database |
||
1757 | * |
||
1758 | * @param User $user User making the clone |
||
1759 | * @param int $fromid Id of object to clone |
||
1760 | * @return int New id of clone |
||
1761 | */ |
||
1762 | public function createFromClone(User $user, $fromid) |
||
1763 | { |
||
1764 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1765 | |||
1766 | $error = 0; |
||
1767 | $object = new BookKeeping($this->db); |
||
1768 | |||
1769 | $this->db->begin(); |
||
1770 | |||
1771 | // Load source object |
||
1772 | $object->fetch($fromid); |
||
1773 | // Reset object |
||
1774 | $object->id = 0; |
||
1775 | |||
1776 | // Clear fields |
||
1777 | // ... |
||
1778 | |||
1779 | // Create clone |
||
1780 | $object->context['createfromclone'] = 'createfromclone'; |
||
1781 | $result = $object->create($user); |
||
1782 | |||
1783 | // Other options |
||
1784 | if ($result < 0) { |
||
1785 | $error++; |
||
1786 | $this->errors = $object->errors; |
||
1787 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
1788 | } |
||
1789 | |||
1790 | unset($object->context['createfromclone']); |
||
1791 | |||
1792 | // End |
||
1793 | if (!$error) { |
||
1794 | $this->db->commit(); |
||
1795 | |||
1796 | return $object->id; |
||
1797 | } else { |
||
1798 | $this->db->rollback(); |
||
1799 | |||
1800 | return -1; |
||
1801 | } |
||
1802 | } |
||
1803 | |||
1804 | /** |
||
1805 | * Initialise object with example values |
||
1806 | * Id must be 0 if object instance is a specimen |
||
1807 | * |
||
1808 | * @return int |
||
1809 | */ |
||
1810 | public function initAsSpecimen() |
||
1811 | { |
||
1812 | global $user; |
||
1813 | |||
1814 | $now = dol_now(); |
||
1815 | |||
1816 | $this->id = 0; |
||
1817 | $this->doc_date = $now; |
||
1818 | $this->doc_type = ''; |
||
1819 | $this->doc_ref = ''; |
||
1820 | $this->fk_doc = 0; |
||
1821 | $this->fk_docdet = 0; |
||
1822 | $this->thirdparty_code = 'CU001'; |
||
1823 | $this->subledger_account = '41100001'; |
||
1824 | $this->subledger_label = 'My customer company'; |
||
1825 | $this->numero_compte = '411'; |
||
1826 | $this->label_compte = 'Customer'; |
||
1827 | $this->label_operation = 'Sales of pea'; |
||
1828 | $this->debit = 99.9; |
||
1829 | $this->credit = 0.0; |
||
1830 | $this->amount = 0.0; |
||
1831 | $this->sens = 'D'; |
||
1832 | $this->fk_user_author = $user->id; |
||
1833 | $this->import_key = '20201027'; |
||
1834 | $this->code_journal = 'VT'; |
||
1835 | $this->journal_label = 'Journal de vente'; |
||
1836 | $this->piece_num = 1234; |
||
1837 | $this->date_creation = $now; |
||
1838 | |||
1839 | return 1; |
||
1840 | } |
||
1841 | |||
1842 | /** |
||
1843 | * Load an accounting document into memory from database |
||
1844 | * |
||
1845 | * @param int $piecenum Accounting document to get |
||
1846 | * @param string $mode Mode |
||
1847 | * @return int Return integer <0 if KO, >0 if OK |
||
1848 | */ |
||
1849 | public function fetchPerMvt($piecenum, $mode = '') |
||
1850 | { |
||
1851 | global $conf; |
||
1852 | |||
1853 | $sql = "SELECT piece_num, doc_date, code_journal, journal_label, doc_ref, doc_type,"; |
||
1854 | $sql .= " date_creation, tms as date_modification, date_validated as date_validation, date_lim_reglement, import_key"; |
||
1855 | // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist |
||
1856 | if ($mode != "_tmp") { |
||
1857 | $sql .= ", date_export"; |
||
1858 | } |
||
1859 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1860 | $sql .= " WHERE piece_num = " . ((int) $piecenum); |
||
1861 | $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1862 | |||
1863 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1864 | $result = $this->db->query($sql); |
||
1865 | if ($result) { |
||
1866 | $obj = $this->db->fetch_object($result); |
||
1867 | |||
1868 | $this->piece_num = $obj->piece_num; |
||
1869 | $this->code_journal = $obj->code_journal; |
||
1870 | $this->journal_label = $obj->journal_label; |
||
1871 | $this->doc_date = $this->db->jdate($obj->doc_date); |
||
1872 | $this->doc_ref = $obj->doc_ref; |
||
1873 | $this->doc_type = $obj->doc_type; |
||
1874 | $this->date_creation = $this->db->jdate($obj->date_creation); |
||
1875 | $this->date_modification = $this->db->jdate($obj->date_modification); |
||
1876 | if ($mode != "_tmp") { |
||
1877 | $this->date_export = $this->db->jdate($obj->date_export); |
||
1878 | } |
||
1879 | $this->date_validation = $this->db->jdate($obj->date_validation); |
||
1880 | $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement); |
||
1881 | $this->import_key = $obj->import_key; |
||
1882 | } else { |
||
1883 | $this->error = "Error " . $this->db->lasterror(); |
||
1884 | dol_syslog(__METHOD__ . $this->error, LOG_ERR); |
||
1885 | return -1; |
||
1886 | } |
||
1887 | |||
1888 | return 1; |
||
1889 | } |
||
1890 | |||
1891 | /** |
||
1892 | * Return next movement number |
||
1893 | * |
||
1894 | * @param string $mode Mode |
||
1895 | * @return int<1, max>|-1 Return next movement number or -1 if error |
||
1896 | */ |
||
1897 | public function getNextNumMvt($mode = '') |
||
1898 | { |
||
1899 | global $conf; |
||
1900 | |||
1901 | $sql = "SELECT MAX(piece_num)+1 as max FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1902 | $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1903 | |||
1904 | dol_syslog(get_only_class($this) . "::getNextNumMvt", LOG_DEBUG); |
||
1905 | |||
1906 | $result = $this->db->query($sql); |
||
1907 | |||
1908 | if ($result) { |
||
1909 | $obj = $this->db->fetch_object($result); |
||
1910 | if ($obj) { |
||
1911 | $result = $obj->max; |
||
1912 | } |
||
1913 | if (empty($result)) { |
||
1914 | $result = 1; |
||
1915 | } |
||
1916 | return $result; |
||
1917 | } else { |
||
1918 | $this->error = "Error " . $this->db->lasterror(); |
||
1919 | dol_syslog(get_only_class($this) . "::getNextNumMvt " . $this->error, LOG_ERR); |
||
1920 | return -1; |
||
1921 | } |
||
1922 | } |
||
1923 | |||
1924 | /** |
||
1925 | * Load all accounting lines related to a given transaction ID $piecenum |
||
1926 | * |
||
1927 | * @param int $piecenum Id of line to get |
||
1928 | * @param string $mode Mode ('' or '_tmp') |
||
1929 | * @return int Return integer <0 if KO, >0 if OK |
||
1930 | */ |
||
1931 | public function fetchAllPerMvt($piecenum, $mode = '') |
||
1932 | { |
||
1933 | global $conf; |
||
1934 | |||
1935 | $sql = "SELECT rowid, doc_date, doc_type,"; |
||
1936 | $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,"; |
||
1937 | $sql .= " numero_compte, label_compte, label_operation, debit, credit,"; |
||
1938 | $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, journal_label, piece_num,"; |
||
1939 | $sql .= " date_creation, tms as date_modification, date_validated as date_validation"; |
||
1940 | // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist |
||
1941 | if ($mode != "_tmp") { |
||
1942 | $sql .= ", date_export"; |
||
1943 | } |
||
1944 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element . $mode; |
||
1945 | $sql .= " WHERE piece_num = " . ((int) $piecenum); |
||
1946 | $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
1947 | |||
1948 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
1949 | $result = $this->db->query($sql); |
||
1950 | if ($result) { |
||
1951 | while ($obj = $this->db->fetch_object($result)) { |
||
1952 | $line = new BookKeepingLine($this->db); |
||
1953 | |||
1954 | $line->id = $obj->rowid; |
||
1955 | |||
1956 | $line->doc_date = $this->db->jdate($obj->doc_date); |
||
1957 | $line->doc_type = $obj->doc_type; |
||
1958 | $line->doc_ref = $obj->doc_ref; |
||
1959 | $line->fk_doc = $obj->fk_doc; |
||
1960 | $line->fk_docdet = $obj->fk_docdet; |
||
1961 | $line->thirdparty_code = $obj->thirdparty_code; |
||
1962 | $line->subledger_account = $obj->subledger_account; |
||
1963 | $line->subledger_label = $obj->subledger_label; |
||
1964 | $line->numero_compte = $obj->numero_compte; |
||
1965 | $line->label_compte = $obj->label_compte; |
||
1966 | $line->label_operation = $obj->label_operation; |
||
1967 | $line->debit = $obj->debit; |
||
1968 | $line->credit = $obj->credit; |
||
1969 | $line->montant = $obj->amount; |
||
1970 | $line->amount = $obj->amount; |
||
1971 | $line->sens = $obj->sens; |
||
1972 | $line->code_journal = $obj->code_journal; |
||
1973 | $line->journal_label = $obj->journal_label; |
||
1974 | $line->piece_num = $obj->piece_num; |
||
1975 | $line->date_creation = $obj->date_creation; |
||
1976 | $line->date_modification = $obj->date_modification; |
||
1977 | if ($mode != "_tmp") { |
||
1978 | $line->date_export = $obj->date_export; |
||
1979 | } |
||
1980 | $line->date_validation = $obj->date_validation; |
||
1981 | |||
1982 | $this->linesmvt[] = $line; |
||
1983 | } |
||
1984 | } else { |
||
1985 | $this->error = "Error " . $this->db->lasterror(); |
||
1986 | dol_syslog(__METHOD__ . $this->error, LOG_ERR); |
||
1987 | return -1; |
||
1988 | } |
||
1989 | |||
1990 | return 1; |
||
1991 | } |
||
1992 | |||
1993 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
1994 | /** |
||
1995 | * Export bookkeeping |
||
1996 | * |
||
1997 | * @param string $model Model |
||
1998 | * @return int Result |
||
1999 | */ |
||
2000 | public function export_bookkeeping($model = 'ebp') |
||
2001 | { |
||
2002 | // phpcs:enable |
||
2003 | global $conf; |
||
2004 | |||
2005 | $sql = "SELECT rowid, doc_date, doc_type,"; |
||
2006 | $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,"; |
||
2007 | $sql .= " numero_compte, label_compte, label_operation, debit, credit,"; |
||
2008 | $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, piece_num,"; |
||
2009 | $sql .= " date_validated as date_validation"; |
||
2010 | $sql .= " FROM " . MAIN_DB_PREFIX . $this->table_element; |
||
2011 | $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
2012 | |||
2013 | dol_syslog(get_only_class($this) . "::export_bookkeeping", LOG_DEBUG); |
||
2014 | |||
2015 | $resql = $this->db->query($sql); |
||
2016 | |||
2017 | if ($resql) { |
||
2018 | $this->linesexport = array(); |
||
2019 | |||
2020 | $num = $this->db->num_rows($resql); |
||
2021 | while ($obj = $this->db->fetch_object($resql)) { |
||
2022 | $line = new BookKeepingLine($this->db); |
||
2023 | |||
2024 | $line->id = $obj->rowid; |
||
2025 | |||
2026 | $line->doc_date = $this->db->jdate($obj->doc_date); |
||
2027 | $line->doc_type = $obj->doc_type; |
||
2028 | $line->doc_ref = $obj->doc_ref; |
||
2029 | $line->fk_doc = $obj->fk_doc; |
||
2030 | $line->fk_docdet = $obj->fk_docdet; |
||
2031 | $line->thirdparty_code = $obj->thirdparty_code; |
||
2032 | $line->subledger_account = $obj->subledger_account; |
||
2033 | $line->subledger_label = $obj->subledger_label; |
||
2034 | $line->numero_compte = $obj->numero_compte; |
||
2035 | $line->label_compte = $obj->label_compte; |
||
2036 | $line->label_operation = $obj->label_operation; |
||
2037 | $line->debit = $obj->debit; |
||
2038 | $line->credit = $obj->credit; |
||
2039 | $line->montant = $obj->amount; |
||
2040 | $line->amount = $obj->amount; |
||
2041 | $line->sens = $obj->sens; |
||
2042 | $line->code_journal = $obj->code_journal; |
||
2043 | $line->piece_num = $obj->piece_num; |
||
2044 | $line->date_validation = $obj->date_validation; |
||
2045 | |||
2046 | $this->linesexport[] = $line; |
||
2047 | } |
||
2048 | $this->db->free($resql); |
||
2049 | |||
2050 | return $num; |
||
2051 | } else { |
||
2052 | $this->error = "Error " . $this->db->lasterror(); |
||
2053 | dol_syslog(get_only_class($this) . "::export_bookkeeping " . $this->error, LOG_ERR); |
||
2054 | return -1; |
||
2055 | } |
||
2056 | } |
||
2057 | |||
2058 | /** |
||
2059 | * Transform transaction |
||
2060 | * |
||
2061 | * @param int $direction If 0: tmp => real, if 1: real => tmp |
||
2062 | * @param string $piece_num Piece num = Transaction ref |
||
2063 | * @return int int Return integer <0 if KO, >0 if OK |
||
2064 | */ |
||
2065 | public function transformTransaction($direction = 0, $piece_num = '') |
||
2066 | { |
||
2067 | global $conf; |
||
2068 | |||
2069 | $error = 0; |
||
2070 | |||
2071 | $sql_filter = $this->getCanModifyBookkeepingSQL(); |
||
2072 | |||
2073 | if (!isset($sql_filter)) { |
||
2074 | return -1; |
||
2075 | } |
||
2076 | |||
2077 | $this->db->begin(); |
||
2078 | |||
2079 | if ($direction == 0) { |
||
2080 | $next_piecenum = $this->getNextNumMvt(); |
||
2081 | $now = dol_now(); |
||
2082 | |||
2083 | if ($next_piecenum < 0) { |
||
2084 | $error++; |
||
2085 | } |
||
2086 | |||
2087 | if (!$error) { |
||
2088 | // Delete if there is an empty line |
||
2089 | $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . '_tmp WHERE piece_num = ' . ((int) $piece_num) . ' AND entity = ' . ((int) $conf->entity) . " AND numero_compte IS NULL AND debit = 0 AND credit = 0"; |
||
2090 | $resql = $this->db->query($sql); |
||
2091 | if (!$resql) { |
||
2092 | $error++; |
||
2093 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2094 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2095 | } |
||
2096 | } |
||
2097 | |||
2098 | if (!$error) { |
||
2099 | $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . ' (doc_date, doc_type,'; |
||
2100 | $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; |
||
2101 | $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; |
||
2102 | $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)'; |
||
2103 | $sql .= ' SELECT doc_date, doc_type,'; |
||
2104 | $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,'; |
||
2105 | $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; |
||
2106 | $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, ' . ((int) $next_piecenum) . ", '" . $this->db->idate($now) . "'"; |
||
2107 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . '_tmp WHERE piece_num = ' . ((int) $piece_num) . ' AND numero_compte IS NOT NULL AND entity = ' . ((int) $conf->entity); |
||
2108 | $sql .= $sql_filter; |
||
2109 | $resql = $this->db->query($sql); |
||
2110 | if (!$resql) { |
||
2111 | $error++; |
||
2112 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2113 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2114 | } |
||
2115 | } |
||
2116 | |||
2117 | if (!$error) { |
||
2118 | $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . '_tmp WHERE piece_num = ' . ((int) $piece_num) . ' AND entity = ' . ((int) $conf->entity); |
||
2119 | $resql = $this->db->query($sql); |
||
2120 | if (!$resql) { |
||
2121 | $error++; |
||
2122 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2123 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2124 | } |
||
2125 | } |
||
2126 | } elseif ($direction == 1) { |
||
2127 | if (!$error) { |
||
2128 | $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . '_tmp WHERE piece_num = ' . ((int) $piece_num) . ' AND entity = ' . ((int) $conf->entity); |
||
2129 | $resql = $this->db->query($sql); |
||
2130 | if (!$resql) { |
||
2131 | $error++; |
||
2132 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2133 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2134 | } |
||
2135 | } |
||
2136 | |||
2137 | if (!$error) { |
||
2138 | $sql = 'INSERT INTO ' . MAIN_DB_PREFIX . $this->table_element . '_tmp (doc_date, doc_type,'; |
||
2139 | $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; |
||
2140 | $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; |
||
2141 | $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)'; |
||
2142 | $sql .= ' SELECT doc_date, doc_type,'; |
||
2143 | $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,'; |
||
2144 | $sql .= ' numero_compte, label_compte, label_operation, debit, credit,'; |
||
2145 | $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num'; |
||
2146 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' WHERE piece_num = ' . ((int) $piece_num) . ' AND entity = ' . ((int) $conf->entity); |
||
2147 | $sql .= $sql_filter; |
||
2148 | $resql = $this->db->query($sql); |
||
2149 | if (!$resql) { |
||
2150 | $error++; |
||
2151 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2152 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2153 | } |
||
2154 | } |
||
2155 | |||
2156 | if (!$error) { |
||
2157 | $sql = 'DELETE FROM ' . MAIN_DB_PREFIX . $this->table_element . '_tmp WHERE piece_num = ' . ((int) $piece_num) . ' AND entity = ' . ((int) $conf->entity); |
||
2158 | $sql .= $sql_filter; |
||
2159 | $resql = $this->db->query($sql); |
||
2160 | if (!$resql) { |
||
2161 | $error++; |
||
2162 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2163 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2164 | } |
||
2165 | } |
||
2166 | } |
||
2167 | if (!$error) { |
||
2168 | $this->db->commit(); |
||
2169 | return 1; |
||
2170 | } else { |
||
2171 | $this->db->rollback(); |
||
2172 | return -1; |
||
2173 | } |
||
2174 | /* |
||
2175 | $sql = "DELETE FROM "; |
||
2176 | $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab"; |
||
2177 | $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte"; |
||
2178 | $sql .= " AND aa.active = 1"; |
||
2179 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; |
||
2180 | $sql .= " AND asy.rowid = " . ((int) $pcgver); |
||
2181 | $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")"; |
||
2182 | $sql .= " ORDER BY account_number ASC"; |
||
2183 | */ |
||
2184 | } |
||
2185 | |||
2186 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
2187 | /** |
||
2188 | * Return list of accounts with label by chart of accounts |
||
2189 | * |
||
2190 | * @param string $selectid Preselected chart of accounts |
||
2191 | * @param string $htmlname Name of field in html form |
||
2192 | * @param int $showempty Add an empty field |
||
2193 | * @param array $event Event options |
||
2194 | * @param int $select_in Value is a aa.rowid (0 default) or aa.account_number (1) |
||
2195 | * @param int $select_out Set value returned by select 0=rowid (default), 1=account_number |
||
2196 | * @param string $aabase Set accounting_account base class to display empty=all or from 1 to 8 will display only account beginning by this number |
||
2197 | * @return string|int String with HTML select or -1 if KO |
||
2198 | */ |
||
2199 | public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '') |
||
2256 | } |
||
2257 | |||
2258 | /** |
||
2259 | * Return id and description of a root accounting account. |
||
2260 | * FIXME: This function takes the parent of parent to get the root account ! |
||
2261 | * |
||
2262 | * @param string $account Accounting account |
||
2263 | * @return array|int Array with root account information (max 2 upper level), <0 if KO |
||
2264 | */ |
||
2265 | public function getRootAccount($account = null) |
||
2266 | { |
||
2267 | global $conf; |
||
2268 | $pcgver = getDolGlobalInt('CHARTOFACCOUNTS'); |
||
2269 | |||
2270 | $sql = "SELECT root.rowid, root.account_number, root.label as label,"; |
||
2271 | $sql .= " parent.rowid as parent_rowid, parent.account_number as parent_account_number, parent.label as parent_label"; |
||
2272 | $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa"; |
||
2273 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; |
||
2274 | $sql .= " AND asy.rowid = " . ((int) $pcgver); |
||
2275 | $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as parent ON aa.account_parent = parent.rowid AND parent.active = 1"; |
||
2276 | $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as root ON parent.account_parent = root.rowid AND root.active = 1"; |
||
2277 | $sql .= " WHERE aa.account_number = '" . $this->db->escape($account) . "'"; |
||
2278 | $sql .= " AND aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
2279 | |||
2280 | dol_syslog(get_only_class($this) . "::select_account", LOG_DEBUG); |
||
2281 | $resql = $this->db->query($sql); |
||
2282 | if ($resql) { |
||
2283 | $obj = ''; |
||
2284 | if ($this->db->num_rows($resql)) { |
||
2285 | $obj = $this->db->fetch_object($resql); |
||
2286 | } |
||
2287 | |||
2288 | $result = array('id' => $obj->rowid, 'account_number' => $obj->account_number, 'label' => $obj->label); |
||
2289 | return $result; |
||
2290 | } else { |
||
2291 | $this->error = "Error " . $this->db->lasterror(); |
||
2292 | dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR); |
||
2293 | |||
2294 | return -1; |
||
2295 | } |
||
2296 | } |
||
2297 | |||
2298 | // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps |
||
2299 | /** |
||
2300 | * Description of accounting account |
||
2301 | * |
||
2302 | * @param string $account Accounting account |
||
2303 | * @return string|int Account desc or -1 if KO |
||
2304 | */ |
||
2305 | public function get_compte_desc($account = null) |
||
2306 | { |
||
2307 | // phpcs:enable |
||
2308 | global $conf; |
||
2309 | |||
2310 | $pcgver = getDolGlobalInt('CHARTOFACCOUNTS'); |
||
2311 | $sql = "SELECT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version, cat.label as category"; |
||
2312 | $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa "; |
||
2313 | $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; |
||
2314 | $sql .= " AND aa.account_number = '" . $this->db->escape($account) . "'"; |
||
2315 | $sql .= " AND asy.rowid = " . ((int) $pcgver); |
||
2316 | $sql .= " AND aa.active = 1"; |
||
2317 | $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid"; |
||
2318 | $sql .= " WHERE aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
2319 | |||
2320 | dol_syslog(get_only_class($this) . "::select_account", LOG_DEBUG); |
||
2321 | $resql = $this->db->query($sql); |
||
2322 | if ($resql) { |
||
2323 | $obj = ''; |
||
2324 | if ($this->db->num_rows($resql)) { |
||
2325 | $obj = $this->db->fetch_object($resql); |
||
2326 | } |
||
2327 | if (empty($obj->category)) { |
||
2328 | return $obj->label; |
||
2329 | } else { |
||
2330 | return $obj->label . ' (' . $obj->category . ')'; |
||
2331 | } |
||
2332 | } else { |
||
2333 | $this->error = "Error " . $this->db->lasterror(); |
||
2334 | dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR); |
||
2335 | return "-1"; |
||
2336 | } |
||
2337 | } |
||
2338 | |||
2339 | /** |
||
2340 | * Get SQL string for check if the bookkeeping can be modified or deleted ? (cached) |
||
2341 | * |
||
2342 | * @param string $alias Bookkeeping alias table |
||
2343 | * @param bool $force Force reload |
||
2344 | * @return string|null SQL filter or null if error |
||
2345 | */ |
||
2346 | public function getCanModifyBookkeepingSQL($alias = '', $force = false) |
||
2347 | { |
||
2348 | global $conf; |
||
2349 | |||
2350 | $alias = trim($alias); |
||
2351 | $alias = !empty($alias) && strpos($alias, '.') < 0 ? $alias . "." : $alias; |
||
2352 | |||
2353 | if (!isset(self::$can_modify_bookkeeping_sql_cached[$alias]) || $force) { |
||
2354 | $result = $this->loadFiscalPeriods($force, 'active'); |
||
2355 | if ($result < 0) { |
||
2356 | return null; |
||
2357 | } |
||
2358 | |||
2359 | $sql_list = array(); |
||
2360 | if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) { |
||
2361 | foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) { |
||
2362 | $sql_list[] = "('" . $this->db->idate($fiscal_period['date_start']) . "' <= " . $this->db->sanitize($alias) . "doc_date AND " . $this->db->sanitize($alias) . "doc_date <= '" . $this->db->idate($fiscal_period['date_end']) . "')"; |
||
2363 | } |
||
2364 | } |
||
2365 | $sqlsanitized = implode(' OR ', $sql_list); |
||
2366 | self::$can_modify_bookkeeping_sql_cached[$alias] = !empty($sql_list) ? " AND (" . $sqlsanitized . ")" : ""; |
||
2367 | } |
||
2368 | |||
2369 | return self::$can_modify_bookkeeping_sql_cached[$alias]; |
||
2370 | } |
||
2371 | |||
2372 | /** |
||
2373 | * Is the bookkeeping can be modified or deleted ? |
||
2374 | * |
||
2375 | * @param int $id Bookkeeping ID |
||
2376 | * @param string $mode Mode ('' or 'tmp_') |
||
2377 | * @return int Return integer <0 if KO, == 0 if No, == 1 if Yes |
||
2378 | */ |
||
2379 | public function canModifyBookkeeping($id, $mode = '') |
||
2380 | { |
||
2381 | global $conf; |
||
2382 | |||
2383 | if (getDolGlobalString('ACCOUNTANCY_FISCAL_PERIOD_MODE') == 'blockedonclosed') { |
||
2384 | $result = $this->loadFiscalPeriods(false, 'closed'); |
||
2385 | |||
2386 | if ($result < 0) { |
||
2387 | return -1; |
||
2388 | } |
||
2389 | |||
2390 | $bookkeeping = new BookKeeping($this->db); |
||
2391 | $result = $bookkeeping->fetch($id, null, $mode); |
||
2392 | if ($result <= 0) { |
||
2393 | return $result; |
||
2394 | } |
||
2395 | |||
2396 | if (!empty($conf->cache['closed_fiscal_period_cached']) && is_array($conf->cache['closed_fiscal_period_cached'])) { |
||
2397 | foreach ($conf->cache['closed_fiscal_period_cached'] as $fiscal_period) { |
||
2398 | if ($fiscal_period['date_start'] <= $bookkeeping->doc_date && $bookkeeping->doc_date <= $fiscal_period['date_end']) { |
||
2399 | return 0; |
||
2400 | } |
||
2401 | } |
||
2402 | } |
||
2403 | |||
2404 | return 1; |
||
2405 | } else { |
||
2406 | $result = $this->loadFiscalPeriods(false, 'active'); |
||
2407 | if ($result < 0) { |
||
2408 | return -1; |
||
2409 | } |
||
2410 | |||
2411 | $bookkeeping = new BookKeeping($this->db); |
||
2412 | $result = $bookkeeping->fetch($id, null, $mode); |
||
2413 | |||
2414 | if ($result <= 0) { |
||
2415 | return $result; |
||
2416 | } |
||
2417 | if (!empty($conf->cache['active_fiscal_period_cached']) && is_array($conf->cache['active_fiscal_period_cached'])) { |
||
2418 | foreach ($conf->cache['active_fiscal_period_cached'] as $fiscal_period) { |
||
2419 | if (!empty($fiscal_period['date_start']) && $fiscal_period['date_start'] <= $bookkeeping->doc_date && (empty($fiscal_period['date_end']) || $bookkeeping->doc_date <= $fiscal_period['date_end'])) { |
||
2420 | return 1; |
||
2421 | } |
||
2422 | } |
||
2423 | } |
||
2424 | |||
2425 | return 0; |
||
2426 | } |
||
2427 | } |
||
2428 | |||
2429 | /** |
||
2430 | * Is the bookkeeping date valid (on an open period or not on a closed period) ? |
||
2431 | * |
||
2432 | * @param int $date Bookkeeping date |
||
2433 | * @return int Return integer <0 if KO, == 0 if No, == 1 if date is valid for a transfer |
||
2434 | */ |
||
2435 | public function validBookkeepingDate($date) |
||
2470 | } |
||
2471 | } |
||
2472 | |||
2473 | /** |
||
2474 | * Load list of active fiscal period |
||
2475 | * |
||
2476 | * @param bool $force Force reload |
||
2477 | * @param string $mode active or closed ? |
||
2478 | * @return int Return integer <0 if KO, >0 if OK |
||
2479 | */ |
||
2480 | public function loadFiscalPeriods($force = false, $mode = 'active') |
||
2481 | { |
||
2482 | global $conf; |
||
2483 | |||
2484 | if ($mode == 'active') { |
||
2485 | if (!isset($conf->cache['active_fiscal_period_cached']) || $force) { |
||
2486 | $sql = "SELECT date_start, date_end"; |
||
2487 | $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear"; |
||
2488 | $sql .= " WHERE entity = " . ((int) $conf->entity); |
||
2489 | $sql .= " AND statut = 0"; |
||
2490 | |||
2491 | $resql = $this->db->query($sql); |
||
2492 | if (!$resql) { |
||
2493 | $this->errors[] = $this->db->lasterror(); |
||
2494 | return -1; |
||
2495 | } |
||
2496 | |||
2497 | $list = array(); |
||
2498 | while ($obj = $this->db->fetch_object($resql)) { |
||
2499 | $list[] = array( |
||
2500 | 'date_start' => $this->db->jdate($obj->date_start), |
||
2501 | 'date_end' => $this->db->jdate($obj->date_end), |
||
2502 | ); |
||
2503 | } |
||
2504 | $conf->cache['active_fiscal_period_cached'] = $list; |
||
2505 | } |
||
2506 | } |
||
2507 | if ($mode == 'closed') { |
||
2508 | if (!isset($conf->cache['closed_fiscal_period_cached']) || $force) { |
||
2509 | $sql = "SELECT date_start, date_end"; |
||
2510 | $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear"; |
||
2511 | $sql .= " WHERE entity = " . ((int) $conf->entity); |
||
2512 | $sql .= " AND statut = 1"; |
||
2513 | |||
2514 | $resql = $this->db->query($sql); |
||
2515 | if (!$resql) { |
||
2516 | $this->errors[] = $this->db->lasterror(); |
||
2517 | return -1; |
||
2518 | } |
||
2519 | |||
2520 | $list = array(); |
||
2521 | while ($obj = $this->db->fetch_object($resql)) { |
||
2522 | $list[] = array( |
||
2523 | 'date_start' => $this->db->jdate($obj->date_start), |
||
2524 | 'date_end' => $this->db->jdate($obj->date_end), |
||
2525 | ); |
||
2526 | } |
||
2527 | $conf->cache['closed_fiscal_period_cached'] = $list; |
||
2528 | } |
||
2529 | } |
||
2530 | |||
2531 | return 1; |
||
2532 | } |
||
2533 | |||
2534 | /** |
||
2535 | * Get list of fiscal period |
||
2536 | * |
||
2537 | * @param string $filter Filter |
||
2538 | * @return array<array{id:int,label:string,date_start:string,date_end:string,status:int}>|int Return integer <0 if KO, Fiscal periods : [[id, date_start, date_end, label], ...] |
||
2539 | */ |
||
2540 | public function getFiscalPeriods($filter = '') |
||
2541 | { |
||
2542 | global $conf; |
||
2543 | $list = array(); |
||
2544 | |||
2545 | $sql = "SELECT rowid, label, date_start, date_end, statut"; |
||
2546 | $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear"; |
||
2547 | $sql .= " WHERE entity = " . ((int) $conf->entity); |
||
2548 | if (!empty($filter)) { |
||
2549 | $sql .= " AND (" . $this->db->sanitize($filter, 1, 1, 1) . ')'; |
||
2550 | } |
||
2551 | $sql .= $this->db->order('date_start', 'ASC'); |
||
2552 | |||
2553 | $resql = $this->db->query($sql); |
||
2554 | if (!$resql) { |
||
2555 | $this->errors[] = $this->db->lasterror(); |
||
2556 | return -1; |
||
2557 | } |
||
2558 | |||
2559 | while ($obj = $this->db->fetch_object($resql)) { |
||
2560 | $list[$obj->rowid] = array( |
||
2561 | 'id' => (int) $obj->rowid, |
||
2562 | 'label' => $obj->label, |
||
2563 | 'date_start' => $this->db->jdate($obj->date_start), |
||
2564 | 'date_end' => $this->db->jdate($obj->date_end), |
||
2565 | 'status' => (int) $obj->statut, |
||
2566 | ); |
||
2567 | } |
||
2568 | |||
2569 | return $list; |
||
2570 | } |
||
2571 | |||
2572 | /** |
||
2573 | * Get list of count by month into the fiscal period |
||
2574 | * |
||
2575 | * @param int $date_start Date start |
||
2576 | * @param int $date_end Date end |
||
2577 | * @return array|int Return integer <0 if KO, Fiscal periods : [[id, date_start, date_end, label], ...] |
||
2578 | */ |
||
2579 | public function getCountByMonthForFiscalPeriod($date_start, $date_end) |
||
2633 | ); |
||
2634 | } |
||
2635 | |||
2636 | /** |
||
2637 | * Validate all movement between the specified dates |
||
2638 | * |
||
2639 | * @param int $date_start Date start |
||
2640 | * @param int $date_end Date end |
||
2641 | * @return int int Return integer <0 if KO, >0 if OK |
||
2642 | */ |
||
2643 | public function validateMovementForFiscalPeriod($date_start, $date_end) |
||
2644 | { |
||
2645 | global $conf; |
||
2646 | |||
2647 | $now = dol_now(); |
||
2648 | |||
2649 | // Specify as export : update field date_validated on selected month/year |
||
2650 | $sql = " UPDATE " . MAIN_DB_PREFIX . "accounting_bookkeeping"; |
||
2651 | $sql .= " SET date_validated = '" . $this->db->idate($now) . "'"; |
||
2652 | $sql .= " WHERE entity = " . ((int) $conf->entity); |
||
2653 | $sql .= " AND DATE(doc_date) >= '" . $this->db->idate($date_start) . "'"; |
||
2654 | $sql .= " AND DATE(doc_date) <= '" . $this->db->idate($date_end) . "'"; |
||
2655 | $sql .= " AND date_validated IS NULL"; |
||
2656 | |||
2657 | dol_syslog(__METHOD__, LOG_DEBUG); |
||
2658 | $resql = $this->db->query($sql); |
||
2659 | if (!$resql) { |
||
2660 | $this->errors[] = $this->db->lasterror(); |
||
2661 | return -1; |
||
2662 | } |
||
2663 | |||
2664 | return 1; |
||
2665 | } |
||
2666 | |||
2667 | /** |
||
2668 | * Define accounting result |
||
2669 | * |
||
2670 | * @param int $date_start Date start |
||
2671 | * @param int $date_end Date end |
||
2672 | * @return string Accounting result |
||
2673 | */ |
||
2674 | public function accountingResult($date_start, $date_end) |
||
2716 | } |
||
2717 | |||
2718 | /** |
||
2719 | * Close fiscal period |
||
2720 | * |
||
2721 | * @param int $fiscal_period_id Fiscal year ID |
||
2722 | * @param int $new_fiscal_period_id New fiscal year ID |
||
2723 | * @param bool $separate_auxiliary_account Separate auxiliary account |
||
2724 | * @param bool $generate_bookkeeping_records Generate closure bookkeeping records |
||
2725 | * @return int int Return integer <0 if KO, >0 if OK |
||
2726 | */ |
||
2727 | public function closeFiscalPeriod($fiscal_period_id, $new_fiscal_period_id, $separate_auxiliary_account = false, $generate_bookkeeping_records = true) |
||
2728 | { |
||
2729 | global $conf, $langs, $user; |
||
2730 | |||
2731 | // Current fiscal period |
||
2732 | $fiscal_period_id = max(0, $fiscal_period_id); |
||
2733 | if (empty($fiscal_period_id)) { |
||
2734 | $langs->load('errors'); |
||
2735 | $this->errors[] = $langs->trans('ErrorBadParameters'); |
||
2736 | return -1; |
||
2737 | } |
||
2738 | $fiscal_period = new Fiscalyear($this->db); |
||
2739 | $result = $fiscal_period->fetch($fiscal_period_id); |
||
2740 | if ($result < 0) { |
||
2741 | $this->error = $fiscal_period->error; |
||
2742 | $this->errors = $fiscal_period->errors; |
||
2743 | return -1; |
||
2744 | } elseif (empty($fiscal_period->id)) { |
||
2745 | $langs->loadLangs(array('errors', 'compta')); |
||
2746 | $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $fiscal_period_id . ')'; |
||
2747 | return -1; |
||
2748 | } |
||
2749 | |||
2750 | // New fiscal period |
||
2751 | $new_fiscal_period_id = max(0, $new_fiscal_period_id); |
||
2752 | if (empty($new_fiscal_period_id)) { |
||
2753 | $langs->load('errors'); |
||
2754 | $this->errors[] = $langs->trans('ErrorBadParameters'); |
||
2755 | return -1; |
||
2756 | } |
||
2757 | $new_fiscal_period = new Fiscalyear($this->db); |
||
2758 | $result = $new_fiscal_period->fetch($new_fiscal_period_id); |
||
2759 | if ($result < 0) { |
||
2760 | $this->error = $new_fiscal_period->error; |
||
2761 | $this->errors = $new_fiscal_period->errors; |
||
2762 | return -1; |
||
2763 | } elseif (empty($new_fiscal_period->id)) { |
||
2764 | $langs->loadLangs(array('errors', 'compta')); |
||
2765 | $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('FiscalPeriod') . ' (' . $new_fiscal_period_id . ')'; |
||
2766 | return -1; |
||
2767 | } |
||
2768 | |||
2769 | $error = 0; |
||
2770 | $this->db->begin(); |
||
2771 | |||
2772 | $fiscal_period->statut = Fiscalyear::STATUS_CLOSED; |
||
2773 | $fiscal_period->status = Fiscalyear::STATUS_CLOSED; // Actually not used |
||
2774 | $result = $fiscal_period->update($user); |
||
2775 | if ($result < 0) { |
||
2776 | $this->error = $fiscal_period->error; |
||
2777 | $this->errors = $fiscal_period->errors; |
||
2778 | $error++; |
||
2779 | } |
||
2780 | |||
2781 | if (!$error && !empty($generate_bookkeeping_records)) { |
||
2782 | $journal_id = max(0, getDolGlobalString('ACCOUNTING_CLOSURE_DEFAULT_JOURNAL')); |
||
2783 | if (empty($journal_id)) { |
||
2784 | $langs->loadLangs(array('errors', 'accountancy')); |
||
2785 | $this->errors[] = $langs->trans('ErrorBadParameters') . ' - ' . $langs->trans('Codejournal') . ' (' . $langs->trans('AccountingJournalType9') . ')'; |
||
2786 | $error++; |
||
2787 | } |
||
2788 | |||
2789 | // Fetch journal |
||
2790 | if (!$error) { |
||
2791 | $journal = new AccountingJournal($this->db); |
||
2792 | $result = $journal->fetch($journal_id); |
||
2793 | if ($result < 0) { |
||
2794 | $this->error = $journal->error; |
||
2795 | $this->errors = $journal->errors; |
||
2796 | $error++; |
||
2797 | } elseif ($result == 0) { |
||
2798 | $langs->loadLangs(array('errors', 'accountancy')); |
||
2799 | $this->errors[] = $langs->trans('ErrorRecordNotFound') . ' - ' . $langs->trans('Codejournal') . ' (' . $langs->trans('AccountingJournalType9') . ')'; |
||
2800 | $error++; |
||
2801 | } |
||
2802 | } |
||
2803 | |||
2804 | if (!$error) { |
||
2805 | $accounting_groups_used_for_balance_sheet_account = array_filter(array_map('trim', explode(',', getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_BALANCE_SHEET_ACCOUNT'))), 'strlen'); |
||
2806 | $accounting_groups_used_for_income_statement = array_filter(array_map('trim', explode(',', getDolGlobalString('ACCOUNTING_CLOSURE_ACCOUNTING_GROUPS_USED_FOR_INCOME_STATEMENT'))), 'strlen'); |
||
2807 | |||
2808 | $pcg_type_filter = array(); |
||
2809 | $tmp = array_merge($accounting_groups_used_for_balance_sheet_account, $accounting_groups_used_for_income_statement); |
||
2810 | foreach ($tmp as $item) { |
||
2811 | $pcg_type_filter[] = "'" . $this->db->escape($item) . "'"; |
||
2812 | } |
||
2813 | |||
2814 | $sql = 'SELECT'; |
||
2815 | $sql .= " t.numero_compte,"; |
||
2816 | $sql .= " t.label_compte,"; |
||
2817 | if ($separate_auxiliary_account) { |
||
2818 | $sql .= " t.subledger_account,"; |
||
2819 | $sql .= " t.subledger_label,"; |
||
2820 | } |
||
2821 | $sql .= " aa.pcg_type,"; |
||
2822 | $sql .= " (SUM(t.credit) - SUM(t.debit)) as opening_balance"; |
||
2823 | $sql .= ' FROM ' . MAIN_DB_PREFIX . $this->table_element . ' as t'; |
||
2824 | $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'accounting_account as aa ON aa.account_number = t.numero_compte'; |
||
2825 | $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features |
||
2826 | $sql .= " AND aa.entity = " . ((int) $conf->entity); |
||
2827 | $sql .= ' AND aa.fk_pcg_version IN (SELECT pcg_version FROM ' . MAIN_DB_PREFIX . 'accounting_system WHERE rowid = ' . ((int) getDolGlobalInt('CHARTOFACCOUNTS')) . ')'; |
||
2828 | $sql .= ' AND aa.pcg_type IN (' . $this->db->sanitize(implode(',', $pcg_type_filter), 1) . ')'; |
||
2829 | $sql .= " AND DATE(t.doc_date) >= '" . $this->db->idate($fiscal_period->date_start) . "'"; |
||
2830 | $sql .= " AND DATE(t.doc_date) <= '" . $this->db->idate($fiscal_period->date_end) . "'"; |
||
2831 | $sql .= ' GROUP BY t.numero_compte, t.label_compte, aa.pcg_type'; |
||
2832 | if ($separate_auxiliary_account) { |
||
2833 | $sql .= ' ,t.subledger_account, t.subledger_label'; |
||
2834 | } |
||
2835 | $sql .= $this->db->order("t.numero_compte", "ASC"); |
||
2836 | |||
2837 | $resql = $this->db->query($sql); |
||
2838 | if (!$resql) { |
||
2839 | $this->errors[] = 'Error ' . $this->db->lasterror(); |
||
2840 | dol_syslog(__METHOD__ . ' ' . implode(',', $this->errors), LOG_ERR); |
||
2841 | |||
2842 | $error++; |
||
2843 | } else { |
||
2844 | $now = dol_now(); |
||
2845 | $income_statement_amount = 0; |
||
2846 | while ($obj = $this->db->fetch_object($resql)) { |
||
2847 | if (in_array($obj->pcg_type, $accounting_groups_used_for_income_statement)) { |
||
2848 | $income_statement_amount += $obj->opening_balance; |
||
2849 | } else { |
||
2850 | // Insert bookkeeping record for balance sheet account |
||
2851 | $mt = $obj->opening_balance; |
||
2852 | |||
2853 | $bookkeeping = new BookKeeping($this->db); |
||
2854 | $bookkeeping->doc_date = $new_fiscal_period->date_start; |
||
2855 | $bookkeeping->date_lim_reglement = 0; |
||
2856 | $bookkeeping->doc_ref = $new_fiscal_period->label; |
||
2857 | $bookkeeping->date_creation = $now; |
||
2858 | $bookkeeping->doc_type = 'closure'; |
||
2859 | $bookkeeping->fk_doc = $new_fiscal_period->id; |
||
2860 | $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add |
||
2861 | $bookkeeping->thirdparty_code = ''; |
||
2862 | |||
2863 | if ($separate_auxiliary_account) { |
||
2864 | $bookkeeping->subledger_account = $obj->subledger_account; |
||
2865 | $bookkeeping->subledger_label = $obj->subledger_label; |
||
2866 | } else { |
||
2867 | $bookkeeping->subledger_account = ''; |
||
2868 | $bookkeeping->subledger_label = ''; |
||
2869 | } |
||
2870 | |||
2871 | $bookkeeping->numero_compte = $obj->numero_compte; |
||
2872 | $bookkeeping->label_compte = $obj->label_compte; |
||
2873 | |||
2874 | $bookkeeping->label_operation = $new_fiscal_period->label; |
||
2875 | $bookkeeping->montant = $mt; |
||
2876 | $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D'; |
||
2877 | $bookkeeping->debit = ($mt < 0) ? -$mt : 0; |
||
2878 | $bookkeeping->credit = ($mt >= 0) ? $mt : 0; |
||
2879 | $bookkeeping->code_journal = $journal->code; |
||
2880 | $bookkeeping->journal_label = $langs->transnoentities($journal->label); |
||
2881 | $bookkeeping->fk_user_author = $user->id; |
||
2882 | $bookkeeping->entity = $conf->entity; |
||
2883 | |||
2884 | $result = $bookkeeping->create($user); |
||
2885 | if ($result < 0) { |
||
2886 | $this->error = $bookkeeping->error; |
||
2887 | $this->errors = $bookkeeping->errors; |
||
2888 | $error++; |
||
2889 | break; |
||
2890 | } |
||
2891 | } |
||
2892 | } |
||
2893 | |||
2894 | // Insert bookkeeping record for income statement |
||
2895 | if (!$error && $income_statement_amount != 0) { |
||
2896 | $mt = $income_statement_amount; |
||
2897 | $accountingaccount = new AccountingAccount($this->db); |
||
2898 | $accountingaccount->fetch(null, getDolGlobalString($income_statement_amount < 0 ? 'ACCOUNTING_RESULT_LOSS' : 'ACCOUNTING_RESULT_PROFIT'), true); |
||
2899 | |||
2900 | $bookkeeping = new BookKeeping($this->db); |
||
2901 | $bookkeeping->doc_date = $new_fiscal_period->date_start; |
||
2902 | $bookkeeping->date_lim_reglement = 0; |
||
2903 | $bookkeeping->doc_ref = $new_fiscal_period->label; |
||
2904 | $bookkeeping->date_creation = $now; |
||
2905 | $bookkeeping->doc_type = 'closure'; |
||
2906 | $bookkeeping->fk_doc = $new_fiscal_period->id; |
||
2907 | $bookkeeping->fk_docdet = 0; // Useless, can be several lines that are source of this record to add |
||
2908 | $bookkeeping->thirdparty_code = ''; |
||
2909 | |||
2910 | if ($separate_auxiliary_account) { |
||
2911 | $bookkeeping->subledger_label = ''; |
||
2912 | $bookkeeping->subledger_account = $obj->subledger_account; |
||
2913 | $bookkeeping->subledger_label = $obj->subledger_label; |
||
2914 | } else { |
||
2915 | $bookkeeping->subledger_account = ''; |
||
2916 | $bookkeeping->subledger_label = ''; |
||
2917 | } |
||
2918 | |||
2919 | $bookkeeping->numero_compte = $accountingaccount->account_number; |
||
2920 | $bookkeeping->label_compte = $accountingaccount->label; |
||
2921 | |||
2922 | $bookkeeping->label_operation = $new_fiscal_period->label; |
||
2923 | $bookkeeping->montant = $mt; |
||
2924 | $bookkeeping->sens = ($mt >= 0) ? 'C' : 'D'; |
||
2925 | $bookkeeping->debit = ($mt < 0) ? -$mt : 0; |
||
2926 | $bookkeeping->credit = ($mt >= 0) ? $mt : 0; |
||
2927 | $bookkeeping->code_journal = $journal->code; |
||
2928 | $bookkeeping->journal_label = $langs->transnoentities($journal->label); |
||
2929 | $bookkeeping->fk_user_author = $user->id; |
||
2930 | $bookkeeping->entity = $conf->entity; |
||
2931 | |||
2932 | $result = $bookkeeping->create($user); |
||
2933 | if ($result < 0) { |
||
2934 | $this->error = $bookkeeping->error; |
||
2935 | $this->errors = $bookkeeping->errors; |
||
2936 | $error++; |
||
2937 | } |
||
2938 | } |
||
2939 | $this->db->free($resql); |
||
2940 | } |
||
2941 | } |
||
2942 | } |
||
2943 | |||
2944 | if ($error) { |
||
2945 | $this->db->rollback(); |
||
2946 | return -1; |
||
2947 | } else { |
||
2948 | $this->db->commit(); |
||
2949 | return 1; |
||
2950 | } |
||
2951 | } |
||
2952 | |||
2953 | /** |
||
2954 | * Insert accounting reversal into the inventory journal of the new fiscal period |
||
2955 | * |
||
2956 | * @param int $fiscal_period_id Fiscal year ID |
||
2957 | * @param int $inventory_journal_id Inventory journal ID |
||
2958 | * @param int $new_fiscal_period_id New fiscal year ID |
||
2959 | * @param int $date_start Date start |
||
2960 | * @param int $date_end Date end |
||
2961 | * @return int int Return integer <0 if KO, >0 if OK |
||
2962 | */ |
||
2963 | public function insertAccountingReversal($fiscal_period_id, $inventory_journal_id, $new_fiscal_period_id, $date_start, $date_end) |
||
3094 | } |
||
3095 | } |
||
3096 | } |
||
3097 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.