bookkeeping.class.php 71 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227
  1. <?php
  2. /* Copyright (C) 2014-2017 Olivier Geffroy <jeff@jeffinfo.com>
  3. * Copyright (C) 2015-2022 Alexandre Spangaro <aspangaro@open-dsi.fr>
  4. * Copyright (C) 2015-2020 Florian Henry <florian.henry@open-concept.pro>
  5. * Copyright (C) 2018-2020 Frédéric France <frederic.france@netlogic.fr>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file htdocs/accountancy/class/bookkeeping.class.php
  22. * \ingroup Accountancy (Double entries)
  23. * \brief File of class to manage Ledger (General Ledger and Subledger)
  24. */
  25. // Class
  26. require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
  27. /**
  28. * Class to manage Ledger (General Ledger and Subledger)
  29. */
  30. class BookKeeping extends CommonObject
  31. {
  32. /**
  33. * @var string Id to identify managed objects
  34. */
  35. public $element = 'accountingbookkeeping';
  36. /**
  37. * @var string Name of table without prefix where object is stored
  38. */
  39. public $table_element = 'accounting_bookkeeping';
  40. /**
  41. * @var int Entity
  42. */
  43. public $entity;
  44. /**
  45. * @var BookKeepingLine[] Lines
  46. */
  47. public $lines = array();
  48. /**
  49. * @var int ID
  50. */
  51. public $id;
  52. /**
  53. * @var string Date of source document, in db date NOT NULL
  54. */
  55. public $doc_date;
  56. /**
  57. * @var int Deadline for payment
  58. */
  59. public $date_lim_reglement;
  60. /**
  61. * @var string doc_type
  62. */
  63. public $doc_type;
  64. /**
  65. * @var string doc_ref
  66. */
  67. public $doc_ref;
  68. /**
  69. * @var int ID
  70. */
  71. public $fk_doc;
  72. /**
  73. * @var int ID
  74. */
  75. public $fk_docdet;
  76. /**
  77. * @var string thirdparty code
  78. */
  79. public $thirdparty_code;
  80. /**
  81. * @var string subledger account
  82. */
  83. public $subledger_account;
  84. /**
  85. * @var string subledger label
  86. */
  87. public $subledger_label;
  88. /**
  89. * @var string doc_type
  90. */
  91. public $numero_compte;
  92. /**
  93. * @var string label compte
  94. */
  95. public $label_compte;
  96. /**
  97. * @var string label operation
  98. */
  99. public $label_operation;
  100. /**
  101. * @var float FEC:Debit
  102. */
  103. public $debit;
  104. /**
  105. * @var float FEC:Credit
  106. */
  107. public $credit;
  108. /**
  109. * @var float FEC:Amount (Not necessary)
  110. * @deprecated No more used (we have info into debit/credit and sens)
  111. */
  112. public $montant;
  113. /**
  114. * @var float FEC:Amount (Not necessary)
  115. * @deprecated No more used (we have info into debit/credit and sens)
  116. */
  117. public $amount;
  118. /**
  119. * @var string FEC:Sens (Not necessary)
  120. */
  121. public $sens;
  122. /**
  123. * @var int ID
  124. */
  125. public $fk_user_author;
  126. /**
  127. * @var string key for import
  128. */
  129. public $import_key;
  130. /**
  131. * @var string code journal
  132. */
  133. public $code_journal;
  134. /**
  135. * @var string label journal
  136. */
  137. public $journal_label;
  138. /**
  139. * @var int accounting transaction id
  140. */
  141. public $piece_num;
  142. /**
  143. * @var integer|string date of movement validated & lock
  144. */
  145. public $date_validation;
  146. /**
  147. * @var integer|string date of movement who are noticed like exported
  148. */
  149. public $date_export;
  150. /**
  151. * @var string String with name of icon for myobject. Must be the part after the 'object_' into object_myobject.png
  152. */
  153. public $picto = 'generic';
  154. /**
  155. * Constructor
  156. *
  157. * @param DoliDb $db Database handler
  158. */
  159. public function __construct(DoliDB $db)
  160. {
  161. $this->db = $db;
  162. }
  163. /**
  164. * Create object into database
  165. *
  166. * @param User $user User that creates
  167. * @param bool $notrigger false=launch triggers after, true=disable triggers
  168. * @return int <0 if KO, Id of created object if OK
  169. */
  170. public function create(User $user, $notrigger = false)
  171. {
  172. global $conf, $langs;
  173. dol_syslog(__METHOD__, LOG_DEBUG);
  174. $error = 0;
  175. // Clean parameters</center>
  176. if (isset($this->doc_type)) {
  177. $this->doc_type = trim($this->doc_type);
  178. }
  179. if (isset($this->doc_ref)) {
  180. $this->doc_ref = trim($this->doc_ref);
  181. }
  182. if (isset($this->fk_doc)) {
  183. $this->fk_doc = (int) $this->fk_doc;
  184. }
  185. if (isset($this->fk_docdet)) {
  186. $this->fk_docdet = (int) $this->fk_docdet;
  187. }
  188. if (isset($this->thirdparty_code)) {
  189. $this->thirdparty_code = trim($this->thirdparty_code);
  190. }
  191. if (isset($this->subledger_account)) {
  192. $this->subledger_account = trim($this->subledger_account);
  193. }
  194. if (isset($this->subledger_label)) {
  195. $this->subledger_label = trim($this->subledger_label);
  196. }
  197. if (isset($this->numero_compte)) {
  198. $this->numero_compte = trim($this->numero_compte);
  199. }
  200. if (isset($this->label_compte)) {
  201. $this->label_compte = trim($this->label_compte);
  202. }
  203. if (isset($this->label_operation)) {
  204. $this->label_operation = trim($this->label_operation);
  205. }
  206. if (isset($this->debit)) {
  207. $this->debit = (float) $this->debit;
  208. }
  209. if (isset($this->credit)) {
  210. $this->credit = (float) $this->credit;
  211. }
  212. if (isset($this->montant)) {
  213. $this->montant = (float) $this->montant;
  214. }
  215. if (isset($this->amount)) {
  216. $this->amount = (float) $this->amount;
  217. }
  218. if (isset($this->sens)) {
  219. $this->sens = trim($this->sens);
  220. }
  221. if (isset($this->import_key)) {
  222. $this->import_key = trim($this->import_key);
  223. }
  224. if (isset($this->code_journal)) {
  225. $this->code_journal = trim($this->code_journal);
  226. }
  227. if (isset($this->journal_label)) {
  228. $this->journal_label = trim($this->journal_label);
  229. }
  230. if (isset($this->piece_num)) {
  231. $this->piece_num = trim($this->piece_num);
  232. }
  233. if (empty($this->debit)) {
  234. $this->debit = 0.0;
  235. }
  236. if (empty($this->credit)) {
  237. $this->credit = 0.0;
  238. }
  239. // Check parameters
  240. if (($this->numero_compte == "") || $this->numero_compte == '-1' || $this->numero_compte == 'NotDefined') {
  241. $langs->loadLangs(array("errors"));
  242. if (in_array($this->doc_type, array('bank', 'expense_report'))) {
  243. $this->errors[] = $langs->trans('ErrorFieldAccountNotDefinedForBankLine', $this->fk_docdet, $this->doc_type);
  244. } else {
  245. //$this->errors[]=$langs->trans('ErrorFieldAccountNotDefinedForInvoiceLine', $this->doc_ref, $this->label_compte);
  246. $mesg = $this->doc_ref.', '.$langs->trans("AccountAccounting").': '.$this->numero_compte;
  247. if ($this->subledger_account && $this->subledger_account != $this->numero_compte) {
  248. $mesg .= ', '.$langs->trans("SubledgerAccount").': '.$this->subledger_account;
  249. }
  250. $this->errors[] = $langs->trans('ErrorFieldAccountNotDefinedForLine', $mesg);
  251. }
  252. return -1;
  253. }
  254. $this->db->begin();
  255. $this->piece_num = 0;
  256. // First check if line not yet already in bookkeeping.
  257. // Note that we must include 'doc_type - fk_doc - numero_compte - label' to be sure to have unicity of line (because we may have several lines
  258. // with same doc_type, fk_doc, numero_compte for 1 invoice line when using localtaxes with same account)
  259. // WARNING: This is not reliable, label may have been modified. This is just a small protection.
  260. // The page that make transfer make the test on couple (doc_type - fk_doc) only.
  261. $sql = "SELECT count(*) as nb";
  262. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  263. $sql .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'";
  264. $sql .= " AND fk_doc = ".((int) $this->fk_doc);
  265. if (!empty($conf->global->ACCOUNTANCY_ENABLE_FKDOCDET)) {
  266. // DO NOT USE THIS IN PRODUCTION. This will generate a lot of trouble into reports and will corrupt database (by generating duplicate entries.
  267. $sql .= " AND fk_docdet = ".((int) $this->fk_docdet); // This field can be 0 if record is for several lines
  268. }
  269. $sql .= " AND numero_compte = '".$this->db->escape($this->numero_compte)."'";
  270. $sql .= " AND label_operation = '".$this->db->escape($this->label_operation)."'";
  271. $sql .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
  272. $resql = $this->db->query($sql);
  273. if ($resql) {
  274. $row = $this->db->fetch_object($resql);
  275. if ($row->nb == 0) { // Not already into bookkeeping
  276. // Check to know if piece_num already exists for data we try to insert to reuse the same value
  277. $sqlnum = "SELECT piece_num";
  278. $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  279. $sqlnum .= " WHERE doc_type = '".$this->db->escape($this->doc_type)."'"; // For example doc_type = 'bank'
  280. $sqlnum .= " AND fk_doc = ".((int) $this->fk_doc);
  281. if (!empty($conf->global->ACCOUNTANCY_ENABLE_FKDOCDET)) {
  282. // fk_docdet is rowid into llx_bank or llx_facturedet or llx_facturefourndet, or ...
  283. $sqlnum .= " AND fk_docdet = ".((int) $this->fk_docdet);
  284. }
  285. $sqlnum .= " AND doc_ref = '".$this->db->escape($this->doc_ref)."'"; // ref of source object
  286. $sqlnum .= " AND entity = ".$conf->entity; // Do not use getEntity for accounting features
  287. dol_syslog(get_class($this).":: create sqlnum=".$sqlnum, LOG_DEBUG);
  288. $resqlnum = $this->db->query($sqlnum);
  289. if ($resqlnum) {
  290. $objnum = $this->db->fetch_object($resqlnum);
  291. $this->piece_num = $objnum->piece_num;
  292. }
  293. dol_syslog(get_class($this).":: create this->piece_num=".$this->piece_num, LOG_DEBUG);
  294. if (empty($this->piece_num)) {
  295. $sqlnum = "SELECT MAX(piece_num)+1 as maxpiecenum";
  296. $sqlnum .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  297. $sqlnum .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  298. $resqlnum = $this->db->query($sqlnum);
  299. if ($resqlnum) {
  300. $objnum = $this->db->fetch_object($resqlnum);
  301. $this->piece_num = $objnum->maxpiecenum;
  302. }
  303. dol_syslog(get_class($this).":: create now this->piece_num=".$this->piece_num, LOG_DEBUG);
  304. }
  305. if (empty($this->piece_num)) {
  306. $this->piece_num = 1;
  307. }
  308. $now = dol_now();
  309. $sql = "INSERT INTO ".MAIN_DB_PREFIX.$this->table_element." (";
  310. $sql .= "doc_date";
  311. $sql .= ", date_lim_reglement";
  312. $sql .= ", doc_type";
  313. $sql .= ", doc_ref";
  314. $sql .= ", fk_doc";
  315. $sql .= ", fk_docdet";
  316. $sql .= ", thirdparty_code";
  317. $sql .= ", subledger_account";
  318. $sql .= ", subledger_label";
  319. $sql .= ", numero_compte";
  320. $sql .= ", label_compte";
  321. $sql .= ", label_operation";
  322. $sql .= ", debit";
  323. $sql .= ", credit";
  324. $sql .= ", montant";
  325. $sql .= ", sens";
  326. $sql .= ", fk_user_author";
  327. $sql .= ", date_creation";
  328. $sql .= ", code_journal";
  329. $sql .= ", journal_label";
  330. $sql .= ", piece_num";
  331. $sql .= ', entity';
  332. $sql .= ") VALUES (";
  333. $sql .= "'".$this->db->idate($this->doc_date)."'";
  334. $sql .= ", ".(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'");
  335. $sql .= ", '".$this->db->escape($this->doc_type)."'";
  336. $sql .= ", '".$this->db->escape($this->doc_ref)."'";
  337. $sql .= ", ".((int) $this->fk_doc);
  338. $sql .= ", ".((int) $this->fk_docdet);
  339. $sql .= ", ".(!empty($this->thirdparty_code) ? ("'".$this->db->escape($this->thirdparty_code)."'") : "NULL");
  340. $sql .= ", ".(!empty($this->subledger_account) ? ("'".$this->db->escape($this->subledger_account)."'") : "NULL");
  341. $sql .= ", ".(!empty($this->subledger_label) ? ("'".$this->db->escape($this->subledger_label)."'") : "NULL");
  342. $sql .= ", '".$this->db->escape($this->numero_compte)."'";
  343. $sql .= ", ".(!empty($this->label_compte) ? ("'".$this->db->escape($this->label_compte)."'") : "NULL");
  344. $sql .= ", '".$this->db->escape($this->label_operation)."'";
  345. $sql .= ", ".((float) $this->debit);
  346. $sql .= ", ".((float) $this->credit);
  347. $sql .= ", ".((float) $this->montant);
  348. $sql .= ", ".(!empty($this->sens) ? ("'".$this->db->escape($this->sens)."'") : "NULL");
  349. $sql .= ", '".$this->db->escape($this->fk_user_author)."'";
  350. $sql .= ", '".$this->db->idate($now)."'";
  351. $sql .= ", '".$this->db->escape($this->code_journal)."'";
  352. $sql .= ", ".(!empty($this->journal_label) ? ("'".$this->db->escape($this->journal_label)."'") : "NULL");
  353. $sql .= ", ".((int) $this->piece_num);
  354. $sql .= ", ".(!isset($this->entity) ? $conf->entity : $this->entity);
  355. $sql .= ")";
  356. $resql = $this->db->query($sql);
  357. if ($resql) {
  358. $id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element);
  359. if ($id > 0) {
  360. $this->id = $id;
  361. $result = 0;
  362. } else {
  363. $result = -2;
  364. $error++;
  365. $this->errors[] = 'Error Create Error '.$result.' lecture ID';
  366. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  367. }
  368. } else {
  369. $result = -1;
  370. $error++;
  371. $this->errors[] = 'Error '.$this->db->lasterror();
  372. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  373. }
  374. } else { // Already exists
  375. $result = -3;
  376. $error++;
  377. $this->error = 'BookkeepingRecordAlreadyExists';
  378. dol_syslog(__METHOD__.' '.$this->error, LOG_WARNING);
  379. }
  380. } else {
  381. $result = -5;
  382. $error++;
  383. $this->errors[] = 'Error '.$this->db->lasterror();
  384. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  385. }
  386. // Uncomment this and change MYOBJECT to your own tag if you
  387. // want this action to call a trigger.
  388. //if (! $error && ! $notrigger) {
  389. // // Call triggers
  390. // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
  391. // if ($result < 0) $error++;
  392. // // End call triggers
  393. //}
  394. // Commit or rollback
  395. if ($error) {
  396. $this->db->rollback();
  397. return -1 * $error;
  398. } else {
  399. $this->db->commit();
  400. return $result;
  401. }
  402. }
  403. /**
  404. * Return a link to the object card (with optionally the picto)
  405. *
  406. * @param int $withpicto Include picto in link (0=No picto, 1=Include picto into link, 2=Only picto)
  407. * @param string $option On what the link point to ('nolink', ...)
  408. * @param int $notooltip 1=Disable tooltip
  409. * @param string $morecss Add more css on link
  410. * @param int $save_lastsearch_value -1=Auto, 0=No save of lastsearch_values when clicking, 1=Save lastsearch_values whenclicking
  411. * @return string String with URL
  412. */
  413. public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $morecss = '', $save_lastsearch_value = -1)
  414. {
  415. global $db, $conf, $langs;
  416. global $dolibarr_main_authentication, $dolibarr_main_demo;
  417. global $menumanager, $hookmanager;
  418. if (!empty($conf->dol_no_mouse_hover)) {
  419. $notooltip = 1; // Force disable tooltips
  420. }
  421. $result = '';
  422. $companylink = '';
  423. $label = '<u>'.$langs->trans("Transaction").'</u>';
  424. $label .= '<br>';
  425. $label .= '<b>'.$langs->trans('Ref').':</b> '.$this->piece_num;
  426. $url = DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?piece_num='.$this->piece_num;
  427. if ($option != 'nolink') {
  428. // Add param to save lastsearch_values or not
  429. $add_save_lastsearch_values = ($save_lastsearch_value == 1 ? 1 : 0);
  430. if ($save_lastsearch_value == -1 && preg_match('/list\.php/', $_SERVER["PHP_SELF"])) {
  431. $add_save_lastsearch_values = 1;
  432. }
  433. if ($add_save_lastsearch_values) {
  434. $url .= '&save_lastsearch_values=1';
  435. }
  436. }
  437. $linkclose = '';
  438. if (empty($notooltip)) {
  439. if (!empty($conf->global->MAIN_OPTIMIZEFORTEXTBROWSER)) {
  440. $label = $langs->trans("ShowTransaction");
  441. $linkclose .= ' alt="'.dol_escape_htmltag($label, 1).'"';
  442. }
  443. $linkclose .= ' title="'.dol_escape_htmltag($label, 1).'"';
  444. $linkclose .= ' class="classfortooltip'.($morecss ? ' '.$morecss : '').'"';
  445. } else {
  446. $linkclose = ($morecss ? ' class="'.$morecss.'"' : '');
  447. }
  448. $linkstart = '<a href="'.$url.'"';
  449. $linkstart .= $linkclose.'>';
  450. $linkend = '</a>';
  451. $result .= $linkstart;
  452. if ($withpicto) {
  453. $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);
  454. }
  455. if ($withpicto != 2) {
  456. $result .= $this->piece_num;
  457. }
  458. $result .= $linkend;
  459. //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
  460. global $action;
  461. $hookmanager->initHooks(array($this->element . 'dao'));
  462. $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
  463. $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
  464. if ($reshook > 0) {
  465. $result = $hookmanager->resPrint;
  466. } else {
  467. $result .= $hookmanager->resPrint;
  468. }
  469. return $result;
  470. }
  471. /**
  472. * Create object into database
  473. *
  474. * @param User $user User that creates
  475. * @param bool $notrigger false=launch triggers after, true=disable triggers
  476. * @param string $mode Mode
  477. * @return int <0 if KO, Id of created object if OK
  478. */
  479. public function createStd(User $user, $notrigger = false, $mode = '')
  480. {
  481. global $conf, $langs;
  482. $langs->loadLangs(array("accountancy", "bills", "compta"));
  483. dol_syslog(__METHOD__, LOG_DEBUG);
  484. $error = 0;
  485. // Clean parameters
  486. if (isset($this->doc_type)) {
  487. $this->doc_type = trim($this->doc_type);
  488. }
  489. if (isset($this->doc_ref)) {
  490. $this->doc_ref = trim($this->doc_ref);
  491. }
  492. if (isset($this->fk_doc)) {
  493. $this->fk_doc = (int) $this->fk_doc;
  494. }
  495. if (isset($this->fk_docdet)) {
  496. $this->fk_docdet = (int) $this->fk_docdet;
  497. }
  498. if (isset($this->thirdparty_code)) {
  499. $this->thirdparty_code = trim($this->thirdparty_code);
  500. }
  501. if (isset($this->subledger_account)) {
  502. $this->subledger_account = trim($this->subledger_account);
  503. }
  504. if (isset($this->subledger_label)) {
  505. $this->subledger_label = trim($this->subledger_label);
  506. }
  507. if (isset($this->numero_compte)) {
  508. $this->numero_compte = trim($this->numero_compte);
  509. }
  510. if (isset($this->label_compte)) {
  511. $this->label_compte = trim($this->label_compte);
  512. }
  513. if (isset($this->label_operation)) {
  514. $this->label_operation = trim($this->label_operation);
  515. }
  516. if (isset($this->debit)) {
  517. $this->debit = trim($this->debit);
  518. }
  519. if (isset($this->credit)) {
  520. $this->credit = trim($this->credit);
  521. }
  522. if (isset($this->montant)) {
  523. $this->montant = trim($this->montant);
  524. }
  525. if (isset($this->amount)) {
  526. $this->amount = trim($this->amount);
  527. }
  528. if (isset($this->sens)) {
  529. $this->sens = trim($this->sens);
  530. }
  531. if (isset($this->import_key)) {
  532. $this->import_key = trim($this->import_key);
  533. }
  534. if (isset($this->code_journal)) {
  535. $this->code_journal = trim($this->code_journal);
  536. }
  537. if (isset($this->journal_label)) {
  538. $this->journal_label = trim($this->journal_label);
  539. }
  540. if (isset($this->piece_num)) {
  541. $this->piece_num = trim($this->piece_num);
  542. }
  543. if (empty($this->debit)) {
  544. $this->debit = 0;
  545. }
  546. if (empty($this->credit)) {
  547. $this->credit = 0;
  548. }
  549. if (empty($this->montant)) {
  550. $this->montant = 0;
  551. }
  552. $this->debit = price2num($this->debit, 'MT');
  553. $this->credit = price2num($this->credit, 'MT');
  554. $this->montant = price2num($this->montant, 'MT');
  555. $now = dol_now();
  556. // Check parameters
  557. $this->journal_label = $langs->trans($this->journal_label);
  558. // Insert request
  559. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.$mode.' (';
  560. $sql .= 'doc_date,';
  561. $sql .= 'date_lim_reglement,';
  562. $sql .= 'doc_type,';
  563. $sql .= 'doc_ref,';
  564. $sql .= 'fk_doc,';
  565. $sql .= 'fk_docdet,';
  566. $sql .= 'thirdparty_code,';
  567. $sql .= 'subledger_account,';
  568. $sql .= 'subledger_label,';
  569. $sql .= 'numero_compte,';
  570. $sql .= 'label_compte,';
  571. $sql .= 'label_operation,';
  572. $sql .= 'debit,';
  573. $sql .= 'credit,';
  574. $sql .= 'montant,';
  575. $sql .= 'sens,';
  576. $sql .= 'fk_user_author,';
  577. $sql .= 'date_creation,';
  578. $sql .= 'code_journal,';
  579. $sql .= 'journal_label,';
  580. $sql .= 'piece_num,';
  581. $sql .= 'entity';
  582. $sql .= ') VALUES (';
  583. $sql .= ' '.(!isset($this->doc_date) || dol_strlen($this->doc_date) == 0 ? 'NULL' : "'".$this->db->idate($this->doc_date)."'").',';
  584. $sql .= ' '.(!isset($this->date_lim_reglement) || dol_strlen($this->date_lim_reglement) == 0 ? 'NULL' : "'".$this->db->idate($this->date_lim_reglement)."'").',';
  585. $sql .= ' '.(!isset($this->doc_type) ? 'NULL' : "'".$this->db->escape($this->doc_type)."'").',';
  586. $sql .= ' '.(!isset($this->doc_ref) ? 'NULL' : "'".$this->db->escape($this->doc_ref)."'").',';
  587. $sql .= ' '.(empty($this->fk_doc) ? '0' : (int) $this->fk_doc).',';
  588. $sql .= ' '.(empty($this->fk_docdet) ? '0' : (int) $this->fk_docdet).',';
  589. $sql .= ' '.(!isset($this->thirdparty_code) ? 'NULL' : "'".$this->db->escape($this->thirdparty_code)."'").',';
  590. $sql .= ' '.(!isset($this->subledger_account) ? 'NULL' : "'".$this->db->escape($this->subledger_account)."'").',';
  591. $sql .= ' '.(!isset($this->subledger_label) ? 'NULL' : "'".$this->db->escape($this->subledger_label)."'").',';
  592. $sql .= ' '.(!isset($this->numero_compte) ? 'NULL' : "'".$this->db->escape($this->numero_compte)."'").',';
  593. $sql .= ' '.(!isset($this->label_compte) ? 'NULL' : "'".$this->db->escape($this->label_compte)."'").',';
  594. $sql .= ' '.(!isset($this->label_operation) ? 'NULL' : "'".$this->db->escape($this->label_operation)."'").',';
  595. $sql .= ' '.(!isset($this->debit) ? 'NULL' : $this->debit).',';
  596. $sql .= ' '.(!isset($this->credit) ? 'NULL' : $this->credit).',';
  597. $sql .= ' '.(!isset($this->montant) ? 'NULL' : $this->montant).',';
  598. $sql .= ' '.(!isset($this->sens) ? 'NULL' : "'".$this->db->escape($this->sens)."'").',';
  599. $sql .= ' '.((int) $user->id).',';
  600. $sql .= ' '."'".$this->db->idate($now)."',";
  601. $sql .= ' '.(empty($this->code_journal) ? 'NULL' : "'".$this->db->escape($this->code_journal)."'").',';
  602. $sql .= ' '.(empty($this->journal_label) ? 'NULL' : "'".$this->db->escape($this->journal_label)."'").',';
  603. $sql .= ' '.(empty($this->piece_num) ? 'NULL' : $this->db->escape($this->piece_num)).',';
  604. $sql .= ' '.(!isset($this->entity) ? $conf->entity : $this->entity);
  605. $sql .= ')';
  606. $this->db->begin();
  607. $resql = $this->db->query($sql);
  608. if (!$resql) {
  609. $error++;
  610. $this->errors[] = 'Error '.$this->db->lasterror();
  611. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  612. }
  613. if (!$error) {
  614. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX.$this->table_element.$mode);
  615. // Uncomment this and change MYOBJECT to your own tag if you
  616. // want this action to call a trigger.
  617. //if (! $notrigger) {
  618. // // Call triggers
  619. // $result=$this->call_trigger('MYOBJECT_CREATE',$user);
  620. // if ($result < 0) $error++;
  621. // // End call triggers
  622. //}
  623. }
  624. // Commit or rollback
  625. if ($error) {
  626. $this->db->rollback();
  627. return -1 * $error;
  628. } else {
  629. $this->db->commit();
  630. return $this->id;
  631. }
  632. }
  633. /**
  634. * Load object in memory from the database
  635. *
  636. * @param int $id Id object
  637. * @param string $ref Ref
  638. * @param string $mode Mode
  639. *
  640. * @return int <0 if KO, 0 if not found, >0 if OK
  641. */
  642. public function fetch($id, $ref = null, $mode = '')
  643. {
  644. global $conf;
  645. dol_syslog(__METHOD__, LOG_DEBUG);
  646. $sql = 'SELECT';
  647. $sql .= ' t.rowid,';
  648. $sql .= " t.doc_date,";
  649. $sql .= " t.date_lim_reglement,";
  650. $sql .= " t.doc_type,";
  651. $sql .= " t.doc_ref,";
  652. $sql .= " t.fk_doc,";
  653. $sql .= " t.fk_docdet,";
  654. $sql .= " t.thirdparty_code,";
  655. $sql .= " t.subledger_account,";
  656. $sql .= " t.subledger_label,";
  657. $sql .= " t.numero_compte,";
  658. $sql .= " t.label_compte,";
  659. $sql .= " t.label_operation,";
  660. $sql .= " t.debit,";
  661. $sql .= " t.credit,";
  662. $sql .= " t.montant as amount,";
  663. $sql .= " t.sens,";
  664. $sql .= " t.fk_user_author,";
  665. $sql .= " t.import_key,";
  666. $sql .= " t.code_journal,";
  667. $sql .= " t.journal_label,";
  668. $sql .= " t.piece_num,";
  669. $sql .= " t.date_creation,";
  670. // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
  671. if ($mode != "_tmp") {
  672. $sql .= " t.date_export,";
  673. }
  674. $sql .= " t.date_validated as date_validation";
  675. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.$mode.' as t';
  676. $sql .= ' WHERE 1 = 1';
  677. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  678. if (null !== $ref) {
  679. $sql .= " AND t.ref = '".$this->db->escape($ref)."'";
  680. } else {
  681. $sql .= ' AND t.rowid = '.((int) $id);
  682. }
  683. $resql = $this->db->query($sql);
  684. if ($resql) {
  685. $numrows = $this->db->num_rows($resql);
  686. if ($numrows) {
  687. $obj = $this->db->fetch_object($resql);
  688. $this->id = $obj->rowid;
  689. $this->doc_date = $this->db->jdate($obj->doc_date);
  690. $this->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
  691. $this->doc_type = $obj->doc_type;
  692. $this->doc_ref = $obj->doc_ref;
  693. $this->fk_doc = $obj->fk_doc;
  694. $this->fk_docdet = $obj->fk_docdet;
  695. $this->thirdparty_code = $obj->thirdparty_code;
  696. $this->subledger_account = $obj->subledger_account;
  697. $this->subledger_label = $obj->subledger_label;
  698. $this->numero_compte = $obj->numero_compte;
  699. $this->label_compte = $obj->label_compte;
  700. $this->label_operation = $obj->label_operation;
  701. $this->debit = $obj->debit;
  702. $this->credit = $obj->credit;
  703. $this->montant = $obj->amount;
  704. $this->amount = $obj->amount;
  705. $this->sens = $obj->sens;
  706. $this->fk_user_author = $obj->fk_user_author;
  707. $this->import_key = $obj->import_key;
  708. $this->code_journal = $obj->code_journal;
  709. $this->journal_label = $obj->journal_label;
  710. $this->piece_num = $obj->piece_num;
  711. $this->date_creation = $this->db->jdate($obj->date_creation);
  712. $this->date_export = $this->db->jdate($obj->date_export);
  713. $this->date_validation = isset($obj->date_validated) ? $this->db->jdate($obj->date_validated) : '';
  714. }
  715. $this->db->free($resql);
  716. if ($numrows) {
  717. return 1;
  718. } else {
  719. return 0;
  720. }
  721. } else {
  722. $this->errors[] = 'Error '.$this->db->lasterror();
  723. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  724. return -1;
  725. }
  726. }
  727. /**
  728. * Load object in memory from the database
  729. *
  730. * @param string $sortorder Sort Order
  731. * @param string $sortfield Sort field
  732. * @param int $limit offset limit
  733. * @param int $offset offset limit
  734. * @param array $filter filter array
  735. * @param string $filtermode filter mode (AND or OR)
  736. * @param int $option option (0: general account or 1: subaccount)
  737. *
  738. * @return int <0 if KO, >=0 if OK
  739. */
  740. public function fetchAllByAccount($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $option = 0)
  741. {
  742. global $conf;
  743. dol_syslog(__METHOD__, LOG_DEBUG);
  744. $this->lines = array();
  745. $sql = 'SELECT';
  746. $sql .= ' t.rowid,';
  747. $sql .= " t.doc_date,";
  748. $sql .= " t.doc_type,";
  749. $sql .= " t.doc_ref,";
  750. $sql .= " t.fk_doc,";
  751. $sql .= " t.fk_docdet,";
  752. $sql .= " t.thirdparty_code,";
  753. $sql .= " t.subledger_account,";
  754. $sql .= " t.subledger_label,";
  755. $sql .= " t.numero_compte,";
  756. $sql .= " t.label_compte,";
  757. $sql .= " t.label_operation,";
  758. $sql .= " t.debit,";
  759. $sql .= " t.credit,";
  760. $sql .= " t.montant as amount,";
  761. $sql .= " t.sens,";
  762. $sql .= " t.multicurrency_amount,";
  763. $sql .= " t.multicurrency_code,";
  764. $sql .= " t.lettering_code,";
  765. $sql .= " t.date_lettering,";
  766. $sql .= " t.fk_user_author,";
  767. $sql .= " t.import_key,";
  768. $sql .= " t.code_journal,";
  769. $sql .= " t.journal_label,";
  770. $sql .= " t.piece_num,";
  771. $sql .= " t.date_creation,";
  772. $sql .= " t.date_export,";
  773. $sql .= " t.date_validated as date_validation,";
  774. $sql .= " t.import_key";
  775. // Manage filter
  776. $sqlwhere = array();
  777. if (count($filter) > 0) {
  778. foreach ($filter as $key => $value) {
  779. if ($key == 't.doc_date') {
  780. $sqlwhere[] = $key.'=\''.$this->db->idate($value).'\'';
  781. } elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') {
  782. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  783. } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.subledger_account>=' || $key == 't.subledger_account<=') {
  784. $sqlwhere[] = $key.'\''.$this->db->escape($value).'\'';
  785. } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
  786. $sqlwhere[] = $key.'='.$value;
  787. } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
  788. $sqlwhere[] = $key.' LIKE \''.$this->db->escape($value).'%\'';
  789. } elseif ($key == 't.date_creation>=' || $key == 't.date_creation<=') {
  790. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  791. } elseif ($key == 't.date_export>=' || $key == 't.date_export<=') {
  792. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  793. } elseif ($key == 't.date_validated>=' || $key == 't.date_validated<=') {
  794. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  795. } elseif ($key == 't.credit' || $key == 't.debit') {
  796. $sqlwhere[] = natural_search($key, $value, 1, 1);
  797. } elseif ($key == 't.reconciled_option') {
  798. $sqlwhere[] = 't.lettering_code IS NULL';
  799. } elseif ($key == 't.code_journal' && !empty($value)) {
  800. if (is_array($value)) {
  801. $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1);
  802. } else {
  803. $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
  804. }
  805. } else {
  806. $sqlwhere[] = natural_search($key, $value, 0, 1);
  807. }
  808. }
  809. }
  810. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  811. $sql .= ' WHERE 1 = 1';
  812. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  813. if (count($sqlwhere) > 0) {
  814. $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere);
  815. }
  816. // Affichage par compte comptable
  817. if (!empty($option)) {
  818. $sql .= " AND t.subledger_account IS NOT NULL";
  819. $sql .= " AND t.subledger_account <> ''";
  820. $sortfield = 't.subledger_account'.($sortfield ? ','.$sortfield : '');
  821. $sortorder = 'ASC'.($sortfield ? ','.$sortfield : '');
  822. } else {
  823. $sortfield = 't.numero_compte'.($sortfield ? ','.$sortfield : '');
  824. $sortorder = 'ASC'.($sortorder ? ','.$sortorder : '');
  825. }
  826. $sql .= $this->db->order($sortfield, $sortorder);
  827. if (!empty($limit)) {
  828. $sql .= $this->db->plimit($limit + 1, $offset);
  829. }
  830. $resql = $this->db->query($sql);
  831. if ($resql) {
  832. $num = $this->db->num_rows($resql);
  833. $i = 0;
  834. while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
  835. $line = new BookKeepingLine();
  836. $line->id = $obj->rowid;
  837. $line->doc_date = $this->db->jdate($obj->doc_date);
  838. $line->doc_type = $obj->doc_type;
  839. $line->doc_ref = $obj->doc_ref;
  840. $line->fk_doc = $obj->fk_doc;
  841. $line->fk_docdet = $obj->fk_docdet;
  842. $line->thirdparty_code = $obj->thirdparty_code;
  843. $line->subledger_account = $obj->subledger_account;
  844. $line->subledger_label = $obj->subledger_label;
  845. $line->numero_compte = $obj->numero_compte;
  846. $line->label_compte = $obj->label_compte;
  847. $line->label_operation = $obj->label_operation;
  848. $line->debit = $obj->debit;
  849. $line->credit = $obj->credit;
  850. $line->montant = $obj->amount; // deprecated
  851. $line->amount = $obj->amount;
  852. $line->sens = $obj->sens;
  853. $line->multicurrency_amount = $obj->multicurrency_amount;
  854. $line->multicurrency_code = $obj->multicurrency_code;
  855. $line->lettering_code = $obj->lettering_code;
  856. $line->date_lettering = $obj->date_lettering;
  857. $line->fk_user_author = $obj->fk_user_author;
  858. $line->import_key = $obj->import_key;
  859. $line->code_journal = $obj->code_journal;
  860. $line->journal_label = $obj->journal_label;
  861. $line->piece_num = $obj->piece_num;
  862. $line->date_creation = $this->db->jdate($obj->date_creation);
  863. $line->date_export = $this->db->jdate($obj->date_export);
  864. $line->date_validation = $this->db->jdate($obj->date_validation);
  865. $line->import_key = $obj->import_key;
  866. $this->lines[] = $line;
  867. $i++;
  868. }
  869. $this->db->free($resql);
  870. return $num;
  871. } else {
  872. $this->errors[] = 'Error '.$this->db->lasterror();
  873. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  874. return -1;
  875. }
  876. }
  877. /**
  878. * Load object in memory from the database
  879. *
  880. * @param string $sortorder Sort Order
  881. * @param string $sortfield Sort field
  882. * @param int $limit Offset limit
  883. * @param int $offset Offset limit
  884. * @param array $filter Filter array
  885. * @param string $filtermode Filter mode (AND or OR)
  886. * @param int $showAlreadyExportMovements Show movements when field 'date_export' is not empty (0:No / 1:Yes (Default))
  887. * @return int <0 if KO, >0 if OK
  888. */
  889. public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND', $showAlreadyExportMovements = 1)
  890. {
  891. global $conf;
  892. dol_syslog(__METHOD__, LOG_DEBUG);
  893. $sql = 'SELECT';
  894. $sql .= ' t.rowid,';
  895. $sql .= " t.doc_date,";
  896. $sql .= " t.doc_type,";
  897. $sql .= " t.doc_ref,";
  898. $sql .= " t.fk_doc,";
  899. $sql .= " t.fk_docdet,";
  900. $sql .= " t.thirdparty_code,";
  901. $sql .= " t.subledger_account,";
  902. $sql .= " t.subledger_label,";
  903. $sql .= " t.numero_compte,";
  904. $sql .= " t.label_compte,";
  905. $sql .= " t.label_operation,";
  906. $sql .= " t.debit,";
  907. $sql .= " t.credit,";
  908. $sql .= " t.lettering_code,";
  909. $sql .= " t.date_lettering,";
  910. $sql .= " t.montant as amount,";
  911. $sql .= " t.sens,";
  912. $sql .= " t.fk_user_author,";
  913. $sql .= " t.import_key,";
  914. $sql .= " t.code_journal,";
  915. $sql .= " t.journal_label,";
  916. $sql .= " t.piece_num,";
  917. $sql .= " t.date_creation,";
  918. $sql .= " t.date_lim_reglement,";
  919. $sql .= " t.tms as date_modification,";
  920. $sql .= " t.date_export,";
  921. $sql .= " t.date_validated as date_validation";
  922. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  923. // Manage filter
  924. $sqlwhere = array();
  925. if (count($filter) > 0) {
  926. foreach ($filter as $key => $value) {
  927. if ($key == 't.doc_date') {
  928. $sqlwhere[] = $key.'=\''.$this->db->idate($value).'\'';
  929. } elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=') {
  930. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  931. } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.subledger_account>=' || $key == 't.subledger_account<=') {
  932. $sqlwhere[] = $key.'\''.$this->db->escape($value).'\'';
  933. } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
  934. $sqlwhere[] = $key.'='.((int) $value);
  935. } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
  936. $sqlwhere[] = $key.' LIKE \''.$this->db->escape($value).'%\'';
  937. } elseif ($key == 't.date_creation>=' || $key == 't.date_creation<=') {
  938. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  939. } elseif ($key == 't.tms>=' || $key == 't.tms<=') {
  940. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  941. } elseif ($key == 't.date_export>=' || $key == 't.date_export<=') {
  942. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  943. } elseif ($key == 't.date_validated>=' || $key == 't.date_validated<=') {
  944. $sqlwhere[] = $key.'\''.$this->db->idate($value).'\'';
  945. } elseif ($key == 't.credit' || $key == 't.debit') {
  946. $sqlwhere[] = natural_search($key, $value, 1, 1);
  947. } elseif ($key == 't.code_journal' && !empty($value)) {
  948. if (is_array($value)) {
  949. $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1);
  950. } else {
  951. $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
  952. }
  953. } else {
  954. $sqlwhere[] = natural_search($key, $value, 0, 1);
  955. }
  956. }
  957. }
  958. $sql .= ' WHERE t.entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
  959. if ($showAlreadyExportMovements == 0) {
  960. $sql .= " AND t.date_export IS NULL";
  961. }
  962. if (count($sqlwhere) > 0) {
  963. $sql .= ' AND '.implode(" ".$filtermode." ", $sqlwhere);
  964. }
  965. if (!empty($sortfield)) {
  966. $sql .= $this->db->order($sortfield, $sortorder);
  967. }
  968. if (!empty($limit)) {
  969. $sql .= $this->db->plimit($limit + 1, $offset);
  970. }
  971. $this->lines = array();
  972. $resql = $this->db->query($sql);
  973. if ($resql) {
  974. $num = $this->db->num_rows($resql);
  975. $i = 0;
  976. while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
  977. $line = new BookKeepingLine();
  978. $line->id = $obj->rowid;
  979. $line->doc_date = $this->db->jdate($obj->doc_date);
  980. $line->doc_type = $obj->doc_type;
  981. $line->doc_ref = $obj->doc_ref;
  982. $line->fk_doc = $obj->fk_doc;
  983. $line->fk_docdet = $obj->fk_docdet;
  984. $line->thirdparty_code = $obj->thirdparty_code;
  985. $line->subledger_account = $obj->subledger_account;
  986. $line->subledger_label = $obj->subledger_label;
  987. $line->numero_compte = $obj->numero_compte;
  988. $line->label_compte = $obj->label_compte;
  989. $line->label_operation = $obj->label_operation;
  990. $line->debit = $obj->debit;
  991. $line->credit = $obj->credit;
  992. $line->montant = $obj->amount; // deprecated
  993. $line->amount = $obj->amount;
  994. $line->sens = $obj->sens;
  995. $line->lettering_code = $obj->lettering_code;
  996. $line->date_lettering = $obj->date_lettering;
  997. $line->fk_user_author = $obj->fk_user_author;
  998. $line->import_key = $obj->import_key;
  999. $line->code_journal = $obj->code_journal;
  1000. $line->journal_label = $obj->journal_label;
  1001. $line->piece_num = $obj->piece_num;
  1002. $line->date_creation = $this->db->jdate($obj->date_creation);
  1003. $line->date_lim_reglement = $this->db->jdate($obj->date_lim_reglement);
  1004. $line->date_modification = $this->db->jdate($obj->date_modification);
  1005. $line->date_export = $this->db->jdate($obj->date_export);
  1006. $line->date_validation = $this->db->jdate($obj->date_validation);
  1007. $this->lines[] = $line;
  1008. $i++;
  1009. }
  1010. $this->db->free($resql);
  1011. return $num;
  1012. } else {
  1013. $this->errors[] = 'Error '.$this->db->lasterror();
  1014. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1015. return -1;
  1016. }
  1017. }
  1018. /**
  1019. * Load object in memory from the database
  1020. *
  1021. * @param string $sortorder Sort Order
  1022. * @param string $sortfield Sort field
  1023. * @param int $limit offset limit
  1024. * @param int $offset offset limit
  1025. * @param array $filter filter array
  1026. * @param string $filtermode filter mode (AND or OR)
  1027. * @return int <0 if KO, >0 if OK
  1028. */
  1029. public function fetchAllBalance($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND')
  1030. {
  1031. global $conf;
  1032. $this->lines = array();
  1033. dol_syslog(__METHOD__, LOG_DEBUG);
  1034. $sql = 'SELECT';
  1035. $sql .= " t.numero_compte,";
  1036. $sql .= " SUM(t.debit) as debit,";
  1037. $sql .= " SUM(t.credit) as credit";
  1038. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t';
  1039. // Manage filter
  1040. $sqlwhere = array();
  1041. if (count($filter) > 0) {
  1042. foreach ($filter as $key => $value) {
  1043. if ($key == 't.doc_date') {
  1044. $sqlwhere[] = $key." = '".$this->db->idate($value)."'";
  1045. } elseif ($key == 't.doc_date>=' || $key == 't.doc_date<=' || $key == 't.doc_date>' || $key == 't.doc_date<') {
  1046. $sqlwhere[] = $key."'".$this->db->idate($value)."'";
  1047. } elseif ($key == 't.numero_compte>=' || $key == 't.numero_compte<=' || $key == 't.subledger_account>=' || $key == 't.subledger_account<=') {
  1048. $sqlwhere[] = $key."'".$this->db->escape($value)."'";
  1049. } elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
  1050. $sqlwhere[] = $key." = ".((int) $value);
  1051. } elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
  1052. $sqlwhere[] = $key." LIKE '".$this->db->escape($value)."%'";
  1053. } elseif ($key == 't.subledger_label') {
  1054. $sqlwhere[] = $key." LIKE '".$this->db->escape($value)."%'";
  1055. } elseif ($key == 't.code_journal' && !empty($value)) {
  1056. if (is_array($value)) {
  1057. $sqlwhere[] = natural_search("t.code_journal", join(',', $value), 3, 1);
  1058. } else {
  1059. $sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
  1060. }
  1061. } else {
  1062. $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'";
  1063. }
  1064. }
  1065. }
  1066. $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features
  1067. if (count($sqlwhere) > 0) {
  1068. $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere);
  1069. }
  1070. $sql .= ' GROUP BY t.numero_compte';
  1071. if (!empty($sortfield)) {
  1072. $sql .= $this->db->order($sortfield, $sortorder);
  1073. }
  1074. if (!empty($limit)) {
  1075. $sql .= $this->db->plimit($limit + 1, $offset);
  1076. }
  1077. $resql = $this->db->query($sql);
  1078. if ($resql) {
  1079. $num = $this->db->num_rows($resql);
  1080. $i = 0;
  1081. while (($obj = $this->db->fetch_object($resql)) && (empty($limit) || $i < min($limit, $num))) {
  1082. $line = new BookKeepingLine();
  1083. $line->numero_compte = $obj->numero_compte;
  1084. $line->debit = $obj->debit;
  1085. $line->credit = $obj->credit;
  1086. $this->lines[] = $line;
  1087. $i++;
  1088. }
  1089. $this->db->free($resql);
  1090. return $num;
  1091. } else {
  1092. $this->errors[] = 'Error '.$this->db->lasterror();
  1093. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1094. return -1;
  1095. }
  1096. }
  1097. /**
  1098. * Update object into database
  1099. *
  1100. * @param User $user User that modifies
  1101. * @param bool $notrigger false=launch triggers after, true=disable triggers
  1102. * @param string $mode Mode ('' or _tmp')
  1103. * @return int <0 if KO, >0 if OK
  1104. */
  1105. public function update(User $user, $notrigger = false, $mode = '')
  1106. {
  1107. $error = 0;
  1108. dol_syslog(__METHOD__, LOG_DEBUG);
  1109. // Clean parameters
  1110. if (isset($this->doc_type)) {
  1111. $this->doc_type = trim($this->doc_type);
  1112. }
  1113. if (isset($this->doc_ref)) {
  1114. $this->doc_ref = trim($this->doc_ref);
  1115. }
  1116. if (isset($this->fk_doc)) {
  1117. $this->fk_doc = (int) $this->fk_doc;
  1118. }
  1119. if (isset($this->fk_docdet)) {
  1120. $this->fk_docdet = (int) $this->fk_docdet;
  1121. }
  1122. if (isset($this->thirdparty_code)) {
  1123. $this->thirdparty_code = trim($this->thirdparty_code);
  1124. }
  1125. if (isset($this->subledger_account)) {
  1126. $this->subledger_account = trim($this->subledger_account);
  1127. }
  1128. if (isset($this->subledger_label)) {
  1129. $this->subledger_label = trim($this->subledger_label);
  1130. }
  1131. if (isset($this->numero_compte)) {
  1132. $this->numero_compte = trim($this->numero_compte);
  1133. }
  1134. if (isset($this->label_compte)) {
  1135. $this->label_compte = trim($this->label_compte);
  1136. }
  1137. if (isset($this->label_operation)) {
  1138. $this->label_operation = trim($this->label_operation);
  1139. }
  1140. if (isset($this->debit)) {
  1141. $this->debit = trim($this->debit);
  1142. }
  1143. if (isset($this->credit)) {
  1144. $this->credit = trim($this->credit);
  1145. }
  1146. if (isset($this->amount)) {
  1147. $this->amount = trim($this->amount);
  1148. }
  1149. if (isset($this->sens)) {
  1150. $this->sens = trim($this->sens);
  1151. }
  1152. if (isset($this->import_key)) {
  1153. $this->import_key = trim($this->import_key);
  1154. }
  1155. if (isset($this->code_journal)) {
  1156. $this->code_journal = trim($this->code_journal);
  1157. }
  1158. if (isset($this->journal_label)) {
  1159. $this->journal_label = trim($this->journal_label);
  1160. }
  1161. if (isset($this->piece_num)) {
  1162. $this->piece_num = trim($this->piece_num);
  1163. }
  1164. $this->debit = price2num($this->debit, 'MT');
  1165. $this->credit = price2num($this->credit, 'MT');
  1166. // Check parameters
  1167. // Put here code to add a control on parameters values
  1168. // Update request
  1169. $sql = 'UPDATE '.MAIN_DB_PREFIX.$this->table_element.$mode.' SET';
  1170. $sql .= ' doc_date = '.(!isset($this->doc_date) || dol_strlen($this->doc_date) != 0 ? "'".$this->db->idate($this->doc_date)."'" : 'null').',';
  1171. $sql .= ' doc_type = '.(isset($this->doc_type) ? "'".$this->db->escape($this->doc_type)."'" : "null").',';
  1172. $sql .= ' doc_ref = '.(isset($this->doc_ref) ? "'".$this->db->escape($this->doc_ref)."'" : "null").',';
  1173. $sql .= ' fk_doc = '.(isset($this->fk_doc) ? $this->fk_doc : "null").',';
  1174. $sql .= ' fk_docdet = '.(isset($this->fk_docdet) ? $this->fk_docdet : "null").',';
  1175. $sql .= ' thirdparty_code = '.(isset($this->thirdparty_code) ? "'".$this->db->escape($this->thirdparty_code)."'" : "null").',';
  1176. $sql .= ' subledger_account = '.(isset($this->subledger_account) ? "'".$this->db->escape($this->subledger_account)."'" : "null").',';
  1177. $sql .= ' subledger_label = '.(isset($this->subledger_label) ? "'".$this->db->escape($this->subledger_label)."'" : "null").',';
  1178. $sql .= ' numero_compte = '.(isset($this->numero_compte) ? "'".$this->db->escape($this->numero_compte)."'" : "null").',';
  1179. $sql .= ' label_compte = '.(isset($this->label_compte) ? "'".$this->db->escape($this->label_compte)."'" : "null").',';
  1180. $sql .= ' label_operation = '.(isset($this->label_operation) ? "'".$this->db->escape($this->label_operation)."'" : "null").',';
  1181. $sql .= ' debit = '.(isset($this->debit) ? $this->debit : "null").',';
  1182. $sql .= ' credit = '.(isset($this->credit) ? $this->credit : "null").',';
  1183. $sql .= ' montant = '.(isset($this->montant) ? $this->montant : "null").',';
  1184. $sql .= ' sens = '.(isset($this->sens) ? "'".$this->db->escape($this->sens)."'" : "null").',';
  1185. $sql .= ' fk_user_author = '.(isset($this->fk_user_author) ? $this->fk_user_author : "null").',';
  1186. $sql .= ' import_key = '.(isset($this->import_key) ? "'".$this->db->escape($this->import_key)."'" : "null").',';
  1187. $sql .= ' code_journal = '.(isset($this->code_journal) ? "'".$this->db->escape($this->code_journal)."'" : "null").',';
  1188. $sql .= ' journal_label = '.(isset($this->journal_label) ? "'".$this->db->escape($this->journal_label)."'" : "null").',';
  1189. $sql .= ' piece_num = '.(isset($this->piece_num) ? $this->piece_num : "null");
  1190. $sql .= ' WHERE rowid='.((int) $this->id);
  1191. $this->db->begin();
  1192. $resql = $this->db->query($sql);
  1193. if (!$resql) {
  1194. $error++;
  1195. $this->errors[] = 'Error '.$this->db->lasterror();
  1196. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1197. }
  1198. // Uncomment this and change MYOBJECT to your own tag if you
  1199. // want this action calls a trigger.
  1200. //if (! $error && ! $notrigger) {
  1201. // // Call triggers
  1202. // $result=$this->call_trigger('MYOBJECT_MODIFY',$user);
  1203. // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
  1204. // // End call triggers
  1205. //}
  1206. // Commit or rollback
  1207. if ($error) {
  1208. $this->db->rollback();
  1209. return -1 * $error;
  1210. } else {
  1211. $this->db->commit();
  1212. return 1;
  1213. }
  1214. }
  1215. /**
  1216. * Update accounting movement
  1217. *
  1218. * @param string $piece_num Piece num
  1219. * @param string $field Field
  1220. * @param string $value Value
  1221. * @param string $mode Mode ('' or _tmp')
  1222. * @return number <0 if KO, >0 if OK
  1223. */
  1224. public function updateByMvt($piece_num = '', $field = '', $value = '', $mode = '')
  1225. {
  1226. $error = 0;
  1227. $this->db->begin();
  1228. $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element.$mode;
  1229. $sql .= " SET ".$field." = ".(is_numeric($value) ? ((float) $value) : "'".$this->db->escape($value)."'");
  1230. $sql .= " WHERE piece_num = ".((int) $piece_num);
  1231. $resql = $this->db->query($sql);
  1232. if (!$resql) {
  1233. $error++;
  1234. $this->errors[] = 'Error '.$this->db->lasterror();
  1235. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1236. }
  1237. if ($error) {
  1238. $this->db->rollback();
  1239. return -1 * $error;
  1240. } else {
  1241. $this->db->commit();
  1242. return 1;
  1243. }
  1244. }
  1245. /**
  1246. * Delete object in database
  1247. *
  1248. * @param User $user User that deletes
  1249. * @param bool $notrigger false=launch triggers after, true=disable triggers
  1250. * @param string $mode Mode
  1251. * @return int <0 if KO, >0 if OK
  1252. */
  1253. public function delete(User $user, $notrigger = false, $mode = '')
  1254. {
  1255. dol_syslog(__METHOD__, LOG_DEBUG);
  1256. $error = 0;
  1257. $this->db->begin();
  1258. // Uncomment this and change MYOBJECT to your own tag if you
  1259. // want this action calls a trigger.
  1260. //if (! $error && ! $notrigger) {
  1261. // // Call triggers
  1262. // $result=$this->call_trigger('MYOBJECT_DELETE',$user);
  1263. // if ($result < 0) { $error++; //Do also what you must do to rollback action if trigger fail}
  1264. // // End call triggers
  1265. //}
  1266. if (!$error) {
  1267. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.$mode;
  1268. $sql .= ' WHERE rowid='.((int) $this->id);
  1269. $resql = $this->db->query($sql);
  1270. if (!$resql) {
  1271. $error++;
  1272. $this->errors[] = 'Error '.$this->db->lasterror();
  1273. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1274. }
  1275. }
  1276. // Commit or rollback
  1277. if ($error) {
  1278. $this->db->rollback();
  1279. return -1 * $error;
  1280. } else {
  1281. $this->db->commit();
  1282. return 1;
  1283. }
  1284. }
  1285. /**
  1286. * Delete bookkeeping by importkey
  1287. *
  1288. * @param string $importkey Import key
  1289. * @return int Result
  1290. */
  1291. public function deleteByImportkey($importkey)
  1292. {
  1293. $this->db->begin();
  1294. // first check if line not yet in bookkeeping
  1295. $sql = "DELETE";
  1296. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  1297. $sql .= " WHERE import_key = '".$this->db->escape($importkey)."'";
  1298. $resql = $this->db->query($sql);
  1299. if (!$resql) {
  1300. $this->errors[] = "Error ".$this->db->lasterror();
  1301. dol_syslog(get_class($this)."::delete Error ".$this->db->lasterror(), LOG_ERR);
  1302. $this->db->rollback();
  1303. return -1;
  1304. }
  1305. $this->db->commit();
  1306. return 1;
  1307. }
  1308. /**
  1309. * Delete bookkeeping by year
  1310. *
  1311. * @param int $delyear Year to delete
  1312. * @param string $journal Journal to delete
  1313. * @param string $mode Mode
  1314. * @param int $delmonth Month
  1315. * @return int <0 if KO, >0 if OK
  1316. */
  1317. public function deleteByYearAndJournal($delyear = 0, $journal = '', $mode = '', $delmonth = 0)
  1318. {
  1319. global $conf, $langs;
  1320. if (empty($delyear) && empty($journal)) {
  1321. $this->error = 'ErrorOneFieldRequired';
  1322. return -1;
  1323. }
  1324. if (!empty($delmonth) && empty($delyear)) {
  1325. $this->error = 'YearRequiredIfMonthDefined';
  1326. return -2;
  1327. }
  1328. $this->db->begin();
  1329. // Delete record in bookkeeping
  1330. $sql = "DELETE";
  1331. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
  1332. $sql .= " WHERE 1 = 1";
  1333. $sql .= dolSqlDateFilter('doc_date', 0, $delmonth, $delyear);
  1334. if (!empty($journal)) {
  1335. $sql .= " AND code_journal = '".$this->db->escape($journal)."'";
  1336. }
  1337. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1338. // Exclusion of validated entries at the time of deletion
  1339. $sql .= " AND date_validated IS NULL";
  1340. // TODO: In a future we must forbid deletion if record is inside a closed fiscal period.
  1341. $resql = $this->db->query($sql);
  1342. if (!$resql) {
  1343. $this->errors[] = "Error ".$this->db->lasterror();
  1344. foreach ($this->errors as $errmsg) {
  1345. dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
  1346. $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
  1347. }
  1348. $this->db->rollback();
  1349. return -1;
  1350. }
  1351. $this->db->commit();
  1352. return 1;
  1353. }
  1354. /**
  1355. * Delete bookkeeping by piece number
  1356. *
  1357. * @param int $piecenum Piecenum to delete
  1358. * @return int Result
  1359. */
  1360. public function deleteMvtNum($piecenum)
  1361. {
  1362. global $conf;
  1363. $this->db->begin();
  1364. // first check if line not yet in bookkeeping
  1365. $sql = "DELETE";
  1366. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  1367. $sql .= " WHERE piece_num = ".(int) $piecenum;
  1368. $sql .= " AND date_validated IS NULL"; // For security, exclusion of validated entries at the time of deletion
  1369. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1370. $resql = $this->db->query($sql);
  1371. if (!$resql) {
  1372. $this->errors[] = "Error ".$this->db->lasterror();
  1373. foreach ($this->errors as $errmsg) {
  1374. dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
  1375. $this->error .= ($this->error ? ', '.$errmsg : $errmsg);
  1376. }
  1377. $this->db->rollback();
  1378. return -1;
  1379. }
  1380. $this->db->commit();
  1381. return 1;
  1382. }
  1383. /**
  1384. * Load an object from its id and create a new one in database
  1385. *
  1386. * @param User $user User making the clone
  1387. * @param int $fromid Id of object to clone
  1388. * @return int New id of clone
  1389. */
  1390. public function createFromClone(User $user, $fromid)
  1391. {
  1392. dol_syslog(__METHOD__, LOG_DEBUG);
  1393. $error = 0;
  1394. $object = new BookKeeping($this->db);
  1395. $this->db->begin();
  1396. // Load source object
  1397. $object->fetch($fromid);
  1398. // Reset object
  1399. $object->id = 0;
  1400. // Clear fields
  1401. // ...
  1402. // Create clone
  1403. $object->context['createfromclone'] = 'createfromclone';
  1404. $result = $object->create($user);
  1405. // Other options
  1406. if ($result < 0) {
  1407. $error++;
  1408. $this->errors = $object->errors;
  1409. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1410. }
  1411. unset($object->context['createfromclone']);
  1412. // End
  1413. if (!$error) {
  1414. $this->db->commit();
  1415. return $object->id;
  1416. } else {
  1417. $this->db->rollback();
  1418. return -1;
  1419. }
  1420. }
  1421. /**
  1422. * Initialise object with example values
  1423. * Id must be 0 if object instance is a specimen
  1424. *
  1425. * @return void
  1426. */
  1427. public function initAsSpecimen()
  1428. {
  1429. global $user;
  1430. $now = dol_now();
  1431. $this->id = 0;
  1432. $this->doc_date = $now;
  1433. $this->doc_type = '';
  1434. $this->doc_ref = '';
  1435. $this->fk_doc = 0;
  1436. $this->fk_docdet = 0;
  1437. $this->thirdparty_code = 'CU001';
  1438. $this->subledger_account = '41100001';
  1439. $this->subledger_label = 'My customer company';
  1440. $this->numero_compte = '411';
  1441. $this->label_compte = 'Customer';
  1442. $this->label_operation = 'Sales of pea';
  1443. $this->debit = 99.9;
  1444. $this->credit = 0.0;
  1445. $this->amount = 0.0;
  1446. $this->sens = 'D';
  1447. $this->fk_user_author = $user->id;
  1448. $this->import_key = '20201027';
  1449. $this->code_journal = 'VT';
  1450. $this->journal_label = 'Journal de vente';
  1451. $this->piece_num = 1234;
  1452. $this->date_creation = $now;
  1453. }
  1454. /**
  1455. * Load an accounting document into memory from database
  1456. *
  1457. * @param int $piecenum Accounting document to get
  1458. * @param string $mode Mode
  1459. * @return int <0 if KO, >0 if OK
  1460. */
  1461. public function fetchPerMvt($piecenum, $mode = '')
  1462. {
  1463. global $conf;
  1464. $sql = "SELECT piece_num, doc_date,code_journal, journal_label, doc_ref, doc_type,";
  1465. $sql .= " date_creation, tms as date_modification, date_validated as date_validation";
  1466. // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
  1467. if ($mode != "_tmp") {
  1468. $sql .= ", date_export";
  1469. }
  1470. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
  1471. $sql .= " WHERE piece_num = ".((int) $piecenum);
  1472. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1473. dol_syslog(__METHOD__, LOG_DEBUG);
  1474. $result = $this->db->query($sql);
  1475. if ($result) {
  1476. $obj = $this->db->fetch_object($result);
  1477. $this->piece_num = $obj->piece_num;
  1478. $this->code_journal = $obj->code_journal;
  1479. $this->journal_label = $obj->journal_label;
  1480. $this->doc_date = $this->db->jdate($obj->doc_date);
  1481. $this->doc_ref = $obj->doc_ref;
  1482. $this->doc_type = $obj->doc_type;
  1483. $this->date_creation = $this->db->jdate($obj->date_creation);
  1484. $this->date_modification = $this->db->jdate($obj->date_modification);
  1485. if ($mode != "_tmp") {
  1486. $this->date_export = $this->db->jdate($obj->date_export);
  1487. }
  1488. $this->date_validation = $this->db->jdate($obj->date_validation);
  1489. } else {
  1490. $this->error = "Error ".$this->db->lasterror();
  1491. dol_syslog(__METHOD__.$this->error, LOG_ERR);
  1492. return -1;
  1493. }
  1494. return 1;
  1495. }
  1496. /**
  1497. * Return next number movement
  1498. *
  1499. * @param string $mode Mode
  1500. * @return string Next numero to use
  1501. */
  1502. public function getNextNumMvt($mode = '')
  1503. {
  1504. global $conf;
  1505. $sql = "SELECT MAX(piece_num)+1 as max FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
  1506. $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1507. dol_syslog(get_class($this)."::getNextNumMvt", LOG_DEBUG);
  1508. $result = $this->db->query($sql);
  1509. if ($result) {
  1510. $obj = $this->db->fetch_object($result);
  1511. if ($obj) {
  1512. $result = $obj->max;
  1513. }
  1514. if (empty($result)) {
  1515. $result = 1;
  1516. }
  1517. return $result;
  1518. } else {
  1519. $this->error = "Error ".$this->db->lasterror();
  1520. dol_syslog(get_class($this)."::getNextNumMvt ".$this->error, LOG_ERR);
  1521. return -1;
  1522. }
  1523. }
  1524. /**
  1525. * Load all informations of accountancy document
  1526. *
  1527. * @param int $piecenum Id of line to get
  1528. * @param string $mode Mode
  1529. * @return int <0 if KO, >0 if OK
  1530. */
  1531. public function fetchAllPerMvt($piecenum, $mode = '')
  1532. {
  1533. global $conf;
  1534. $sql = "SELECT rowid, doc_date, doc_type,";
  1535. $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,";
  1536. $sql .= " numero_compte, label_compte, label_operation, debit, credit,";
  1537. $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, journal_label, piece_num,";
  1538. $sql .= " date_creation, tms as date_modification, date_validated as date_validation";
  1539. // In llx_accounting_bookkeeping_tmp, field date_export doesn't exist
  1540. if ($mode != "_tmp") {
  1541. $sql .= ", date_export";
  1542. }
  1543. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element.$mode;
  1544. $sql .= " WHERE piece_num = ".((int) $piecenum);
  1545. $sql .= " AND entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1546. dol_syslog(__METHOD__, LOG_DEBUG);
  1547. $result = $this->db->query($sql);
  1548. if ($result) {
  1549. while ($obj = $this->db->fetch_object($result)) {
  1550. $line = new BookKeepingLine();
  1551. $line->id = $obj->rowid;
  1552. $line->doc_date = $this->db->jdate($obj->doc_date);
  1553. $line->doc_type = $obj->doc_type;
  1554. $line->doc_ref = $obj->doc_ref;
  1555. $line->fk_doc = $obj->fk_doc;
  1556. $line->fk_docdet = $obj->fk_docdet;
  1557. $line->thirdparty_code = $obj->thirdparty_code;
  1558. $line->subledger_account = $obj->subledger_account;
  1559. $line->subledger_label = $obj->subledger_label;
  1560. $line->numero_compte = $obj->numero_compte;
  1561. $line->label_compte = $obj->label_compte;
  1562. $line->label_operation = $obj->label_operation;
  1563. $line->debit = $obj->debit;
  1564. $line->credit = $obj->credit;
  1565. $line->montant = $obj->amount;
  1566. $line->amount = $obj->amount;
  1567. $line->sens = $obj->sens;
  1568. $line->code_journal = $obj->code_journal;
  1569. $line->journal_label = $obj->journal_label;
  1570. $line->piece_num = $obj->piece_num;
  1571. $line->date_creation = $obj->date_creation;
  1572. $line->date_modification = $obj->date_modification;
  1573. if ($mode != "_tmp") {
  1574. $line->date_export = $obj->date_export;
  1575. }
  1576. $line->date_validation = $obj->date_validation;
  1577. $this->linesmvt[] = $line;
  1578. }
  1579. } else {
  1580. $this->error = "Error ".$this->db->lasterror();
  1581. dol_syslog(__METHOD__.$this->error, LOG_ERR);
  1582. return -1;
  1583. }
  1584. return 1;
  1585. }
  1586. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  1587. /**
  1588. * Export bookkeeping
  1589. *
  1590. * @param string $model Model
  1591. * @return int Result
  1592. */
  1593. public function export_bookkeeping($model = 'ebp')
  1594. {
  1595. // phpcs:enable
  1596. global $conf;
  1597. $sql = "SELECT rowid, doc_date, doc_type,";
  1598. $sql .= " doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,";
  1599. $sql .= " numero_compte, label_compte, label_operation, debit, credit,";
  1600. $sql .= " montant as amount, sens, fk_user_author, import_key, code_journal, piece_num,";
  1601. $sql .= " date_validated as date_validation";
  1602. $sql .= " FROM ".MAIN_DB_PREFIX.$this->table_element;
  1603. $sql .= " WHERE entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1604. dol_syslog(get_class($this)."::export_bookkeeping", LOG_DEBUG);
  1605. $resql = $this->db->query($sql);
  1606. if ($resql) {
  1607. $this->linesexport = array();
  1608. $num = $this->db->num_rows($resql);
  1609. while ($obj = $this->db->fetch_object($resql)) {
  1610. $line = new BookKeepingLine();
  1611. $line->id = $obj->rowid;
  1612. $line->doc_date = $this->db->jdate($obj->doc_date);
  1613. $line->doc_type = $obj->doc_type;
  1614. $line->doc_ref = $obj->doc_ref;
  1615. $line->fk_doc = $obj->fk_doc;
  1616. $line->fk_docdet = $obj->fk_docdet;
  1617. $line->thirdparty_code = $obj->thirdparty_code;
  1618. $line->subledger_account = $obj->subledger_account;
  1619. $line->subledger_label = $obj->subledger_label;
  1620. $line->numero_compte = $obj->numero_compte;
  1621. $line->label_compte = $obj->label_compte;
  1622. $line->label_operation = $obj->label_operation;
  1623. $line->debit = $obj->debit;
  1624. $line->credit = $obj->credit;
  1625. $line->montant = $obj->amount;
  1626. $line->amount = $obj->amount;
  1627. $line->sens = $obj->sens;
  1628. $line->code_journal = $obj->code_journal;
  1629. $line->piece_num = $obj->piece_num;
  1630. $line->date_validation = $obj->date_validation;
  1631. $this->linesexport[] = $line;
  1632. }
  1633. $this->db->free($resql);
  1634. return $num;
  1635. } else {
  1636. $this->error = "Error ".$this->db->lasterror();
  1637. dol_syslog(get_class($this)."::export_bookkeeping ".$this->error, LOG_ERR);
  1638. return -1;
  1639. }
  1640. }
  1641. /**
  1642. * Transform transaction
  1643. *
  1644. * @param number $direction If 0: tmp => real, if 1: real => tmp
  1645. * @param string $piece_num Piece num = Transaction ref
  1646. * @return int int <0 if KO, >0 if OK
  1647. */
  1648. public function transformTransaction($direction = 0, $piece_num = '')
  1649. {
  1650. global $conf;
  1651. $error = 0;
  1652. $this->db->begin();
  1653. if ($direction == 0) {
  1654. $next_piecenum = $this->getNextNumMvt();
  1655. $now = dol_now();
  1656. if ($next_piecenum < 0) {
  1657. $error++;
  1658. }
  1659. if (!$error) {
  1660. // Delete if there is an empty line
  1661. $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";
  1662. $resql = $this->db->query($sql);
  1663. if (!$resql) {
  1664. $error++;
  1665. $this->errors[] = 'Error '.$this->db->lasterror();
  1666. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1667. }
  1668. }
  1669. if (!$error) {
  1670. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.' (doc_date, doc_type,';
  1671. $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
  1672. $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
  1673. $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num, date_creation)';
  1674. $sql .= ' SELECT doc_date, doc_type,';
  1675. $sql .= ' doc_ref, fk_doc, fk_docdet, entity, thirdparty_code, subledger_account, subledger_label,';
  1676. $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
  1677. $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, '.((int) $next_piecenum).", '".$this->db->idate($now)."'";
  1678. $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);
  1679. $resql = $this->db->query($sql);
  1680. if (!$resql) {
  1681. $error++;
  1682. $this->errors[] = 'Error '.$this->db->lasterror();
  1683. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1684. }
  1685. }
  1686. if (!$error) {
  1687. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
  1688. $resql = $this->db->query($sql);
  1689. if (!$resql) {
  1690. $error++;
  1691. $this->errors[] = 'Error '.$this->db->lasterror();
  1692. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1693. }
  1694. }
  1695. } elseif ($direction == 1) {
  1696. if (!$error) {
  1697. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
  1698. $resql = $this->db->query($sql);
  1699. if (!$resql) {
  1700. $error++;
  1701. $this->errors[] = 'Error '.$this->db->lasterror();
  1702. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1703. }
  1704. }
  1705. if (!$error) {
  1706. $sql = 'INSERT INTO '.MAIN_DB_PREFIX.$this->table_element.'_tmp (doc_date, doc_type,';
  1707. $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
  1708. $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
  1709. $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num)';
  1710. $sql .= ' SELECT doc_date, doc_type,';
  1711. $sql .= ' doc_ref, fk_doc, fk_docdet, thirdparty_code, subledger_account, subledger_label,';
  1712. $sql .= ' numero_compte, label_compte, label_operation, debit, credit,';
  1713. $sql .= ' montant, sens, fk_user_author, import_key, code_journal, journal_label, piece_num';
  1714. $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
  1715. $resql = $this->db->query($sql);
  1716. if (!$resql) {
  1717. $error++;
  1718. $this->errors[] = 'Error '.$this->db->lasterror();
  1719. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1720. }
  1721. }
  1722. if (!$error) {
  1723. $sql = 'DELETE FROM '.MAIN_DB_PREFIX.$this->table_element.'_tmp WHERE piece_num = '.((int) $piece_num).' AND entity = ' .((int) $conf->entity);
  1724. $resql = $this->db->query($sql);
  1725. if (!$resql) {
  1726. $error++;
  1727. $this->errors[] = 'Error '.$this->db->lasterror();
  1728. dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR);
  1729. }
  1730. }
  1731. }
  1732. if (!$error) {
  1733. $this->db->commit();
  1734. return 1;
  1735. } else {
  1736. $this->db->rollback();
  1737. return -1;
  1738. }
  1739. /*
  1740. $sql = "DELETE FROM ";
  1741. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab";
  1742. $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ab.numero_compte";
  1743. $sql .= " AND aa.active = 1";
  1744. $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  1745. $sql .= " AND asy.rowid = " . ((int) $pcgver);
  1746. $sql .= " AND ab.entity IN (" . getEntity('accountancy') . ")";
  1747. $sql .= " ORDER BY account_number ASC";
  1748. */
  1749. }
  1750. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  1751. /**
  1752. * Return list of accounts with label by chart of accounts
  1753. *
  1754. * @param string $selectid Preselected chart of accounts
  1755. * @param string $htmlname Name of field in html form
  1756. * @param int $showempty Add an empty field
  1757. * @param array $event Event options
  1758. * @param int $select_in Value is a aa.rowid (0 default) or aa.account_number (1)
  1759. * @param int $select_out Set value returned by select 0=rowid (default), 1=account_number
  1760. * @param int $aabase Set accounting_account base class to display empty=all or from 1 to 8 will display only account beginning by this number
  1761. * @return string String with HTML select
  1762. */
  1763. public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $aabase = '')
  1764. {
  1765. // phpcs:enable
  1766. global $conf;
  1767. require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
  1768. $pcgver = $conf->global->CHARTOFACCOUNTS;
  1769. $sql = "SELECT DISTINCT ab.numero_compte as account_number, aa.label as label, aa.rowid as rowid, aa.fk_pcg_version";
  1770. $sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as ab";
  1771. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON aa.account_number = ab.numero_compte";
  1772. $sql .= " AND aa.active = 1";
  1773. $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  1774. $sql .= " AND asy.rowid = ".((int) $pcgver);
  1775. $sql .= " AND ab.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1776. $sql .= " ORDER BY account_number ASC";
  1777. dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
  1778. $resql = $this->db->query($sql);
  1779. if (!$resql) {
  1780. $this->error = "Error ".$this->db->lasterror();
  1781. dol_syslog(get_class($this)."::select_account ".$this->error, LOG_ERR);
  1782. return -1;
  1783. }
  1784. $out = ajax_combobox($htmlname, $event);
  1785. $options = array();
  1786. $selected = null;
  1787. while ($obj = $this->db->fetch_object($resql)) {
  1788. $label = length_accountg($obj->account_number).' - '.$obj->label;
  1789. $select_value_in = $obj->rowid;
  1790. $select_value_out = $obj->rowid;
  1791. if ($select_in == 1) {
  1792. $select_value_in = $obj->account_number;
  1793. }
  1794. if ($select_out == 1) {
  1795. $select_value_out = $obj->account_number;
  1796. }
  1797. // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number
  1798. // Because same account_number can be share between different accounting_system and do have the same meaning
  1799. if (($selectid != '') && $selectid == $select_value_in) {
  1800. $selected = $select_value_out;
  1801. }
  1802. $options[$select_value_out] = $label;
  1803. }
  1804. $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', 'maxwidth300');
  1805. $this->db->free($resql);
  1806. return $out;
  1807. }
  1808. /**
  1809. * Return id and description of a root accounting account.
  1810. * FIXME: This function takes the parent of parent to get the root account !
  1811. *
  1812. * @param string $account Accounting account
  1813. * @return array Array with root account information (max 2 upper level)
  1814. */
  1815. public function getRootAccount($account = null)
  1816. {
  1817. global $conf;
  1818. $pcgver = $conf->global->CHARTOFACCOUNTS;
  1819. $sql = "SELECT root.rowid, root.account_number, root.label as label,";
  1820. $sql .= " parent.rowid as parent_rowid, parent.account_number as parent_account_number, parent.label as parent_label";
  1821. $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa";
  1822. $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  1823. $sql .= " AND asy.rowid = ".((int) $pcgver);
  1824. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as parent ON aa.account_parent = parent.rowid AND parent.active = 1";
  1825. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as root ON parent.account_parent = root.rowid AND root.active = 1";
  1826. $sql .= " WHERE aa.account_number = '".$this->db->escape($account)."'";
  1827. $sql .= " AND aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1828. dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
  1829. $resql = $this->db->query($sql);
  1830. if ($resql) {
  1831. $obj = '';
  1832. if ($this->db->num_rows($resql)) {
  1833. $obj = $this->db->fetch_object($resql);
  1834. }
  1835. $result = array('id'=>$obj->rowid, 'account_number'=>$obj->account_number, 'label'=>$obj->label);
  1836. return $result;
  1837. } else {
  1838. $this->error = "Error ".$this->db->lasterror();
  1839. dol_syslog(__METHOD__." ".$this->error, LOG_ERR);
  1840. return -1;
  1841. }
  1842. }
  1843. // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
  1844. /**
  1845. * Description of accounting account
  1846. *
  1847. * @param string $account Accounting account
  1848. * @return string Account desc
  1849. */
  1850. public function get_compte_desc($account = null)
  1851. {
  1852. // phpcs:enable
  1853. global $conf;
  1854. $pcgver = $conf->global->CHARTOFACCOUNTS;
  1855. $sql = "SELECT aa.account_number, aa.label, aa.rowid, aa.fk_pcg_version, cat.label as category";
  1856. $sql .= " FROM ".MAIN_DB_PREFIX."accounting_account as aa ";
  1857. $sql .= " INNER JOIN ".MAIN_DB_PREFIX."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  1858. $sql .= " AND aa.account_number = '".$this->db->escape($account)."'";
  1859. $sql .= " AND asy.rowid = ".((int) $pcgver);
  1860. $sql .= " AND aa.active = 1";
  1861. $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_accounting_category as cat ON aa.fk_accounting_category = cat.rowid";
  1862. $sql .= " WHERE aa.entity = " . ((int) $conf->entity); // Do not use getEntity for accounting features
  1863. dol_syslog(get_class($this)."::select_account", LOG_DEBUG);
  1864. $resql = $this->db->query($sql);
  1865. if ($resql) {
  1866. $obj = '';
  1867. if ($this->db->num_rows($resql)) {
  1868. $obj = $this->db->fetch_object($resql);
  1869. }
  1870. if (empty($obj->category)) {
  1871. return $obj->label;
  1872. } else {
  1873. return $obj->label.' ('.$obj->category.')';
  1874. }
  1875. } else {
  1876. $this->error = "Error ".$this->db->lasterror();
  1877. dol_syslog(__METHOD__." ".$this->error, LOG_ERR);
  1878. return -1;
  1879. }
  1880. }
  1881. }
  1882. /**
  1883. * Class BookKeepingLine
  1884. */
  1885. class BookKeepingLine
  1886. {
  1887. /**
  1888. * @var int ID
  1889. */
  1890. public $id;
  1891. public $doc_date = '';
  1892. public $doc_type;
  1893. public $doc_ref;
  1894. /**
  1895. * @var int ID
  1896. */
  1897. public $fk_doc;
  1898. /**
  1899. * @var int ID
  1900. */
  1901. public $fk_docdet;
  1902. public $thirdparty_code;
  1903. public $subledger_account;
  1904. public $subledger_label;
  1905. public $numero_compte;
  1906. public $label_compte;
  1907. public $label_operation;
  1908. public $debit;
  1909. public $credit;
  1910. /**
  1911. * @var float Amount
  1912. * @deprecated see $amount
  1913. */
  1914. public $montant;
  1915. /**
  1916. * @var float Amount
  1917. */
  1918. public $amount;
  1919. /**
  1920. * @var float Multicurrency amount
  1921. */
  1922. public $multicurrency_amount;
  1923. /**
  1924. * @var float Multicurrency code
  1925. */
  1926. public $multicurrency_code;
  1927. /**
  1928. * @var string Sens
  1929. */
  1930. public $sens;
  1931. public $lettering_code;
  1932. public $date_lettering;
  1933. /**
  1934. * @var int ID
  1935. */
  1936. public $fk_user_author;
  1937. public $import_key;
  1938. public $code_journal;
  1939. public $journal_label;
  1940. public $piece_num;
  1941. /**
  1942. * @var integer|string date_creation
  1943. */
  1944. public $date_creation;
  1945. /**
  1946. * @var integer|string $date_modification;
  1947. */
  1948. public $date_modification;
  1949. /**
  1950. * @var integer|string $date_export;
  1951. */
  1952. public $date_export;
  1953. /**
  1954. * @var integer|string $date_validation;
  1955. */
  1956. public $date_validation;
  1957. /**
  1958. * @var integer|string $date_lim_reglement;
  1959. */
  1960. public $date_lim_reglement;
  1961. }