accountancycategory.class.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. <?php
  2. /* Copyright (C) 2016 Jamal Elbaz <jamelbaz@gmail.pro>
  3. * Copyright (C) 2016-2017 Alexandre Spangaro <aspangaro@open-dsi.fr>
  4. * Copyright (C) 2018-2019 Frédéric France <frederic.france@netlogic.fr>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. /**
  20. * \file htdocs/accountancy/class/accountancycategory.class.php
  21. * \ingroup Accountancy (Double entries)
  22. * \brief File of class to manage categories of an accounting category_type
  23. */
  24. // Class
  25. require_once DOL_DOCUMENT_ROOT . '/core/lib/accounting.lib.php';
  26. /**
  27. * Class to manage categories of an accounting account
  28. */
  29. class AccountancyCategory // extends CommonObject
  30. {
  31. /**
  32. * @var DoliDB Database handler.
  33. */
  34. public $db;
  35. /**
  36. * @var string Error string
  37. * @see $errors
  38. */
  39. public $error;
  40. /**
  41. * @var string[] Error codes (or messages)
  42. */
  43. public $errors = array();
  44. /**
  45. * @var string ID to identify managed object
  46. */
  47. public $element='c_accounting_category';
  48. /**
  49. * @var string Name of table without prefix where object is stored
  50. */
  51. public $table_element='c_accounting_category';
  52. /**
  53. * @var int ID
  54. */
  55. public $id;
  56. /**
  57. * @var string Accountancy code
  58. */
  59. public $code;
  60. /**
  61. * @var string Accountancy Category label
  62. */
  63. public $label;
  64. /**
  65. * @var string Accountancy range account
  66. */
  67. public $range_account;
  68. /**
  69. * @var int Sens of the account: 0: credit - debit, 1: debit - credit
  70. */
  71. public $sens;
  72. /**
  73. * @var int Category type of accountancy
  74. */
  75. public $category_type;
  76. /**
  77. * @var string Formula
  78. */
  79. public $formula;
  80. /**
  81. * @var int Position
  82. */
  83. public $position;
  84. /**
  85. * @var int country id
  86. */
  87. public $fk_country;
  88. /**
  89. * @var int Is active
  90. */
  91. public $active;
  92. /**
  93. * @var array Lines cptbk
  94. */
  95. public $lines_cptbk;
  96. /**
  97. * @var array Lines display
  98. */
  99. public $lines_display;
  100. /**
  101. * @var mixed Sample property 1
  102. */
  103. public $sdc;
  104. /**
  105. * Constructor
  106. *
  107. * @param DoliDb $db Database handler
  108. */
  109. public function __construct($db)
  110. {
  111. $this->db = $db;
  112. }
  113. /**
  114. * Create object into database
  115. *
  116. * @param User $user User that create
  117. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  118. * @return int <0 if KO, Id of created object if OK
  119. */
  120. public function create($user, $notrigger = 0)
  121. {
  122. global $conf, $langs;
  123. $error=0;
  124. // Clean parameters
  125. if (isset($this->code)) $this->code=trim($this->code);
  126. if (isset($this->label)) $this->label=trim($this->label);
  127. if (isset($this->range_account)) $this->range_account=trim($this->range_account);
  128. if (isset($this->sens)) $this->sens = (int) $this->sens;
  129. if (isset($this->category_type)) $this->category_type = (int) $this->category_type;
  130. if (isset($this->formula)) $this->formula=trim($this->formula);
  131. if (isset($this->position)) $this->position = (int) $this->position;
  132. if (isset($this->fk_country)) $this->fk_country = (int) $this->fk_country;
  133. if (isset($this->active)) $this->active = (int) $this->active;
  134. // Check parameters
  135. // Put here code to add control on parameters values
  136. // Insert request
  137. $sql = "INSERT INTO ".MAIN_DB_PREFIX."c_accounting_category(";
  138. if ($this->rowid > 0) $sql.= "rowid, ";
  139. $sql.= "code, ";
  140. $sql.= "label, ";
  141. $sql.= "range_account, ";
  142. $sql.= "sens, ";
  143. $sql.= "category_type, ";
  144. $sql.= "formula, ";
  145. $sql.= "position, ";
  146. $sql.= "fk_country, ";
  147. $sql.= "active, ";
  148. $sql.= "entity";
  149. $sql.= ") VALUES (";
  150. if ($this->rowid > 0) $sql.= " ".$this->rowid.",";
  151. $sql.= " ".(! isset($this->code)?'NULL':"'".$this->db->escape($this->code)."'").",";
  152. $sql.= " ".(! isset($this->label)?'NULL':"'".$this->db->escape($this->label)."'").",";
  153. $sql.= " ".(! isset($this->range_account)?'NULL':"'".$this->db->escape($this->range_account)."'").",";
  154. $sql.= " ".(! isset($this->sens)?'NULL':"'".$this->db->escape($this->sens)."'").",";
  155. $sql.= " ".(! isset($this->category_type)?'NULL':"'".$this->db->escape($this->category_type)."'").",";
  156. $sql.= " ".(! isset($this->formula)?'NULL':"'".$this->db->escape($this->formula)."'").",";
  157. $sql.= " ".(! isset($this->position)?'NULL':$this->db->escape($this->position)).",";
  158. $sql.= " ".(! isset($this->fk_country)?'NULL':$this->db->escape($this->fk_country)).",";
  159. $sql.= " ".(! isset($this->active)?'NULL':$this->db->escape($this->active));
  160. $sql.= ", ".$conf->entity;
  161. $sql.= ")";
  162. $this->db->begin();
  163. dol_syslog(get_class($this)."::create", LOG_DEBUG);
  164. $resql=$this->db->query($sql);
  165. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  166. if (! $error)
  167. {
  168. $this->id = $this->db->last_insert_id(MAIN_DB_PREFIX."c_accounting_category");
  169. // Uncomment this and change MYOBJECT to your own tag if you
  170. // want this action call a trigger.
  171. //if (! $notrigger)
  172. //{
  173. // // Call triggers
  174. // include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  175. // $interface=new Interfaces($this->db);
  176. // $result=$interface->run_triggers('MYOBJECT_CREATE',$this,$user,$langs,$conf);
  177. // if ($result < 0) { $error++; $this->errors=$interface->errors; }
  178. // // End call triggers
  179. //}
  180. }
  181. // Commit or rollback
  182. if ($error)
  183. {
  184. foreach($this->errors as $errmsg)
  185. {
  186. dol_syslog(get_class($this)."::create ".$errmsg, LOG_ERR);
  187. $this->error.=($this->error?', '.$errmsg:$errmsg);
  188. }
  189. $this->db->rollback();
  190. return -1*$error;
  191. }
  192. else
  193. {
  194. $this->db->commit();
  195. return $this->id;
  196. }
  197. }
  198. /**
  199. * Load object in memory from database
  200. *
  201. * @param int $id Id object
  202. * @param string $code Code
  203. * @param string $label Label
  204. * @return int <0 if KO, >0 if OK
  205. */
  206. public function fetch($id, $code = '', $label = '')
  207. {
  208. $sql = "SELECT";
  209. $sql.= " t.rowid,";
  210. $sql.= " t.code,";
  211. $sql.= " t.label,";
  212. $sql.= " t.range_account,";
  213. $sql.= " t.sens,";
  214. $sql.= " t.category_type,";
  215. $sql.= " t.formula,";
  216. $sql.= " t.position,";
  217. $sql.= " t.fk_country,";
  218. $sql.= " t.active";
  219. $sql.= " FROM ".MAIN_DB_PREFIX."c_accounting_category as t";
  220. if ($id) $sql.= " WHERE t.rowid = ".$id;
  221. else
  222. {
  223. $sql.= " WHERE t.entity IN (".getEntity('c_accounting_category').")"; // Dont't use entity if you use rowid
  224. if ($code) $sql.= " AND t.code = '".$this->db->escape($code)."'";
  225. elseif ($label) $sql.= " AND t.label = '".$this->db->escape($label)."'";
  226. }
  227. dol_syslog(get_class($this)."::fetch", LOG_DEBUG);
  228. $resql=$this->db->query($sql);
  229. if ($resql)
  230. {
  231. if ($this->db->num_rows($resql))
  232. {
  233. $obj = $this->db->fetch_object($resql);
  234. $this->id = $obj->rowid;
  235. $this->code = $obj->code;
  236. $this->label = $obj->label;
  237. $this->range_account = $obj->range_account;
  238. $this->sens = $obj->sens;
  239. $this->category_type = $obj->category_type;
  240. $this->formula = $obj->formula;
  241. $this->position = $obj->position;
  242. $this->fk_country = $obj->fk_country;
  243. $this->active = $obj->active;
  244. }
  245. $this->db->free($resql);
  246. return 1;
  247. }
  248. else
  249. {
  250. $this->error="Error ".$this->db->lasterror();
  251. return -1;
  252. }
  253. }
  254. /**
  255. * Update object into database
  256. *
  257. * @param User $user User that modify
  258. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  259. * @return int <0 if KO, >0 if OK
  260. */
  261. public function update($user = null, $notrigger = 0)
  262. {
  263. global $conf, $langs;
  264. $error=0;
  265. // Clean parameters
  266. if (isset($this->code)) $this->code=trim($this->code);
  267. if (isset($this->label)) $this->label=trim($this->label);
  268. if (isset($this->range_account)) $this->range_account=trim($this->range_account);
  269. if (isset($this->sens)) $this->sens = (int) $this->sens;
  270. if (isset($this->category_type)) $this->category_type = (int) $this->category_type;
  271. if (isset($this->formula)) $this->formula=trim($this->formula);
  272. if (isset($this->position)) $this->position = (int) $this->position;
  273. if (isset($this->fk_country)) $this->fk_country = (int) $this->fk_country;
  274. if (isset($this->active)) $this->active = (int) $this->active;
  275. // Check parameters
  276. // Put here code to add control on parameters values
  277. // Update request
  278. $sql = "UPDATE ".MAIN_DB_PREFIX."c_accounting_category SET";
  279. $sql.= " code=".(isset($this->code)?"'".$this->db->escape($this->code)."'":"null").",";
  280. $sql.= " label=".(isset($this->label)?"'".$this->db->escape($this->label)."'":"null").",";
  281. $sql.= " range_account=".(isset($this->range_account)?"'".$this->db->escape($this->range_account)."'":"null").",";
  282. $sql.= " sens=".(isset($this->sens)?$this->sens:"null").",";
  283. $sql.= " category_type=".(isset($this->category_type)?$this->category_type:"null").",";
  284. $sql.= " formula=".(isset($this->formula)?"'".$this->db->escape($this->formula)."'":"null").",";
  285. $sql.= " position=".(isset($this->position)?$this->position:"null").",";
  286. $sql.= " fk_country=".(isset($this->fk_country)?$this->fk_country:"null").",";
  287. $sql.= " active=".(isset($this->active)?$this->active:"null")."";
  288. $sql.= " WHERE rowid=".$this->id;
  289. $this->db->begin();
  290. dol_syslog(get_class($this)."::update", LOG_DEBUG);
  291. $resql = $this->db->query($sql);
  292. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  293. //if (! $error)
  294. //{
  295. // Uncomment this and change MYOBJECT to your own tag if you
  296. // want this action call a trigger.
  297. //if (! $notrigger)
  298. //{
  299. // // Call triggers
  300. // include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  301. // $interface=new Interfaces($this->db);
  302. // $result=$interface->run_triggers('MYOBJECT_MODIFY',$this,$user,$langs,$conf);
  303. // if ($result < 0) { $error++; $this->errors=$interface->errors; }
  304. // // End call triggers
  305. //}
  306. //}
  307. // Commit or rollback
  308. if ($error)
  309. {
  310. foreach($this->errors as $errmsg)
  311. {
  312. dol_syslog(get_class($this)."::update ".$errmsg, LOG_ERR);
  313. $this->error.=($this->error?', '.$errmsg:$errmsg);
  314. }
  315. $this->db->rollback();
  316. return -1*$error;
  317. }
  318. else
  319. {
  320. $this->db->commit();
  321. return 1;
  322. }
  323. }
  324. /**
  325. * Delete object in database
  326. *
  327. * @param User $user User that delete
  328. * @param int $notrigger 0=launch triggers after, 1=disable triggers
  329. * @return int <0 if KO, >0 if OK
  330. */
  331. public function delete($user, $notrigger = 0)
  332. {
  333. global $conf, $langs;
  334. $error=0;
  335. $sql = "DELETE FROM ".MAIN_DB_PREFIX."c_accounting_category";
  336. $sql.= " WHERE rowid=".$this->id;
  337. $this->db->begin();
  338. dol_syslog(get_class($this)."::delete", LOG_DEBUG);
  339. $resql = $this->db->query($sql);
  340. if (! $resql) { $error++; $this->errors[]="Error ".$this->db->lasterror(); }
  341. //if (! $error)
  342. //{
  343. // Uncomment this and change MYOBJECT to your own tag if you
  344. // want this action call a trigger.
  345. //if (! $notrigger)
  346. //{
  347. // // Call triggers
  348. // include_once DOL_DOCUMENT_ROOT . '/core/class/interfaces.class.php';
  349. // $interface=new Interfaces($this->db);
  350. // $result=$interface->run_triggers('MYOBJECT_DELETE',$this,$user,$langs,$conf);
  351. // if ($result < 0) { $error++; $this->errors=$interface->errors; }
  352. // // End call triggers
  353. //}
  354. //}
  355. // Commit or rollback
  356. if ($error)
  357. {
  358. foreach($this->errors as $errmsg)
  359. {
  360. dol_syslog(get_class($this)."::delete ".$errmsg, LOG_ERR);
  361. $this->error.=($this->error?', '.$errmsg:$errmsg);
  362. }
  363. $this->db->rollback();
  364. return -1*$error;
  365. }
  366. else
  367. {
  368. $this->db->commit();
  369. return 1;
  370. }
  371. }
  372. /**
  373. * Function to select all accounting accounts from an accounting category
  374. *
  375. * @param int $id Id
  376. * @return int <0 if KO, 0 if not found, >0 if OK
  377. */
  378. public function display($id)
  379. {
  380. global $conf;
  381. $sql = "SELECT t.rowid, t.account_number, t.label";
  382. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
  383. $sql .= " WHERE t.fk_accounting_category = " . $id;
  384. $sql .= " AND t.entity = " . $conf->entity;
  385. $this->lines_display = array();
  386. dol_syslog(__METHOD__ . " sql=" . $sql, LOG_DEBUG);
  387. $resql = $this->db->query($sql);
  388. if ($resql) {
  389. $num = $this->db->num_rows($resql);
  390. if ($num) {
  391. while ( $obj = $this->db->fetch_object($resql) ) {
  392. $this->lines_display[] = $obj;
  393. }
  394. }
  395. return $num;
  396. } else {
  397. $this->error = "Error " . $this->db->lasterror();
  398. $this->errors[] = $this->error;
  399. dol_syslog(__METHOD__ . " " . implode(',' . $this->errors), LOG_ERR);
  400. return - 1;
  401. }
  402. }
  403. /**
  404. * Function to select accounting category of an accounting account present in chart of accounts
  405. *
  406. * @param int $id Id category
  407. *
  408. * @return int <0 if KO, 0 if not found, >0 if OK
  409. */
  410. public function getCptBK($id)
  411. {
  412. global $conf;
  413. $sql = "SELECT t.numero_compte, t.label_operation, t.doc_ref";
  414. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
  415. $sql .= " WHERE t.numero_compte NOT IN (";
  416. $sql .= " SELECT t.account_number";
  417. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
  418. $sql .= " WHERE t.fk_accounting_category = " . $id . " AND t.entity = " . $conf->entity.")";
  419. $sql .= " AND t.numero_compte IN (";
  420. $sql .= " SELECT DISTINCT aa.account_number";
  421. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa";
  422. $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  423. $sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
  424. $sql .= " AND aa.active = 1";
  425. $sql .= " AND aa.entity = " . $conf->entity . ")";
  426. $sql .= " GROUP BY t.numero_compte, t.label_operation, t.doc_ref";
  427. $sql .= " ORDER BY t.numero_compte";
  428. $this->lines_CptBk = array ();
  429. dol_syslog(__METHOD__, LOG_DEBUG);
  430. $resql = $this->db->query($sql);
  431. if ($resql) {
  432. $num = $this->db->num_rows($resql);
  433. if ($num) {
  434. while ( $obj = $this->db->fetch_object($resql) ) {
  435. $this->lines_cptbk[] = $obj;
  436. }
  437. }
  438. return $num;
  439. } else {
  440. $this->error = "Error " . $this->db->lasterror();
  441. $this->errors[] = $this->error;
  442. dol_syslog(__METHOD__ . " " . implode(',' . $this->errors), LOG_ERR);
  443. return - 1;
  444. }
  445. }
  446. /**
  447. * Function to select accounting category of an accounting account present in chart of accounts
  448. *
  449. * @param int $id Id of category to know which account to exclude
  450. *
  451. * @return int <0 if KO, 0 if not found, >0 if OK
  452. */
  453. public function getAccountsWithNoCategory($id)
  454. {
  455. global $conf;
  456. $sql = "SELECT aa.account_number as numero_compte, aa.label as label_compte";
  457. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa";
  458. $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  459. $sql .= " WHERE (aa.fk_accounting_category != ".$id." OR aa.fk_accounting_category IS NULL)";
  460. $sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
  461. $sql .= " AND aa.active = 1";
  462. $sql .= " AND aa.entity = " . $conf->entity;
  463. $sql .= " GROUP BY aa.account_number, aa.label";
  464. $sql .= " ORDER BY aa.account_number, aa.label";
  465. $this->lines_CptBk = array ();
  466. dol_syslog(__METHOD__, LOG_DEBUG);
  467. $resql = $this->db->query($sql);
  468. if ($resql) {
  469. $num = $this->db->num_rows($resql);
  470. if ($num) {
  471. while ( $obj = $this->db->fetch_object($resql) ) {
  472. $this->lines_cptbk[] = $obj;
  473. }
  474. }
  475. return $num;
  476. } else {
  477. $this->error = "Error " . $this->db->lasterror();
  478. $this->errors[] = $this->error;
  479. dol_syslog(__METHOD__ . " " . implode(',' . $this->errors), LOG_ERR);
  480. return - 1;
  481. }
  482. }
  483. /**
  484. * Function to add an accounting account in an accounting category
  485. *
  486. * @param int $id_cat Id category
  487. * @param array $cpts list of accounts array
  488. *
  489. * @return int <0 if KO, >0 if OK
  490. */
  491. public function updateAccAcc($id_cat, $cpts = array())
  492. {
  493. global $conf;
  494. $error = 0;
  495. require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
  496. $sql = "SELECT aa.rowid, aa.account_number";
  497. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as aa";
  498. $sql .= " INNER JOIN " . MAIN_DB_PREFIX . "accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
  499. $sql .= " AND asy.rowid = " . $conf->global->CHARTOFACCOUNTS;
  500. $sql .= " AND aa.active = 1";
  501. $sql .= " AND aa.entity = " . $conf->entity;
  502. $sql .= " ORDER BY LENGTH(aa.account_number) DESC;"; // LENGTH is ok with mysql and postgresql
  503. $this->db->begin();
  504. dol_syslog(__METHOD__, LOG_DEBUG);
  505. $resql = $this->db->query($sql);
  506. if (! $resql) {
  507. $error ++;
  508. $this->errors[] = "Error " . $this->db->lasterror();
  509. $this->db->rollback();
  510. return -1;
  511. }
  512. $accountincptsadded=array();
  513. while ($obj = $this->db->fetch_object($resql))
  514. {
  515. $account_number_formated=length_accountg($obj->account_number);
  516. if (! empty($accountincptsadded[$account_number_formated])) continue;
  517. if (array_key_exists($account_number_formated, $cpts))
  518. {
  519. $accountincptsadded[$account_number_formated]=1;
  520. // We found an account number that is in list $cpts of account to add
  521. $sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account";
  522. $sql .= " SET fk_accounting_category=" . $id_cat;
  523. $sql .= " WHERE rowid=".$obj->rowid;
  524. dol_syslog(__METHOD__, LOG_DEBUG);
  525. $resqlupdate = $this->db->query($sql);
  526. if (! $resqlupdate) {
  527. $error ++;
  528. $this->errors[] = "Error " . $this->db->lasterror();
  529. }
  530. }
  531. }
  532. // Commit or rollback
  533. if ($error) {
  534. foreach ($this->errors as $errmsg) {
  535. dol_syslog(__METHOD__ . " " . $errmsg, LOG_ERR);
  536. $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
  537. }
  538. $this->db->rollback();
  539. return - 1 * $error;
  540. } else {
  541. $this->db->commit();
  542. return 1;
  543. }
  544. }
  545. /**
  546. * Function to delete an accounting account from an accounting category
  547. *
  548. * @param int $cpt_id Id of accounting account
  549. *
  550. * @return int <0 if KO, >0 if OK
  551. */
  552. public function deleteCptCat($cpt_id)
  553. {
  554. $error = 0;
  555. $sql = "UPDATE " . MAIN_DB_PREFIX . "accounting_account as aa";
  556. $sql .= " SET fk_accounting_category= 0";
  557. $sql .= " WHERE aa.rowid= " . $cpt_id;
  558. $this->db->begin();
  559. dol_syslog(__METHOD__ . " sql=" . $sql, LOG_DEBUG);
  560. $resql = $this->db->query($sql);
  561. if (! $resql) {
  562. $error ++;
  563. $this->errors[] = "Error " . $this->db->lasterror();
  564. }
  565. // Commit or rollback
  566. if ($error) {
  567. foreach ($this->errors as $errmsg) {
  568. dol_syslog(__METHOD__ . " " . $errmsg, LOG_ERR);
  569. $this->error .= ($this->error ? ', ' . $errmsg : $errmsg);
  570. }
  571. $this->db->rollback();
  572. return - 1 * $error;
  573. } else {
  574. $this->db->commit();
  575. return 1;
  576. }
  577. }
  578. /**
  579. * Function to know all category from accounting account
  580. *
  581. * @return array|integer Result in table (array), -1 if KO
  582. */
  583. public function getCatsCpts()
  584. {
  585. global $mysoc, $conf;
  586. if (empty($mysoc->country_id)) {
  587. dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined');
  588. exit();
  589. }
  590. $sql = "SELECT t.rowid, t.account_number, t.label as account_label, cat.code, cat.position, cat.label as name_cat, cat.sens ";
  591. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t, " . MAIN_DB_PREFIX . "c_accounting_category as cat";
  592. $sql .= " WHERE t.fk_accounting_category IN ( SELECT c.rowid ";
  593. $sql .= " FROM " . MAIN_DB_PREFIX . "c_accounting_category as c";
  594. $sql .= " WHERE c.active = 1";
  595. $sql .= " AND c.entity = " . $conf->entity;
  596. $sql .= " AND (c.fk_country = ".$mysoc->country_id." OR c.fk_country = 0)";
  597. $sql .= " AND cat.rowid = t.fk_accounting_category";
  598. $sql .= " AND t.entity = " . $conf->entity;
  599. $sql .= " ORDER BY cat.position ASC";
  600. $resql = $this->db->query($sql);
  601. if ($resql) {
  602. $i = 0;
  603. $obj = '';
  604. $num = $this->db->num_rows($resql);
  605. $data = array ();
  606. if ($num) {
  607. while ( $obj = $this->db->fetch_object($resql) ) {
  608. $name_cat = $obj->name_cat;
  609. $data[$name_cat][$i] = array (
  610. 'id' => $obj->rowid,
  611. 'code' => $obj->code,
  612. 'position' => $obj->position,
  613. 'account_number' => $obj->account_number,
  614. 'account_label' => $obj->account_label,
  615. 'sens' => $obj->sens
  616. );
  617. $i ++;
  618. }
  619. }
  620. return $data;
  621. } else {
  622. $this->error = "Error " . $this->db->lasterror();
  623. dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
  624. return -1;
  625. }
  626. }
  627. /**
  628. * Function to show result of an accounting account from the ledger with a direction and a period
  629. *
  630. * @param int|array $cpt Accounting account or array of accounting account
  631. * @param string $date_start Date start
  632. * @param string $date_end Date end
  633. * @param int $sens Sens of the account: 0: credit - debit (use this by default), 1: debit - credit
  634. * @param string $thirdparty_code Thirdparty code
  635. * @param int $month Specifig month - Can be empty
  636. * @param int $year Specifig year - Can be empty
  637. * @return integer <0 if KO, >= 0 if OK
  638. */
  639. public function getSumDebitCredit($cpt, $date_start, $date_end, $sens, $thirdparty_code = 'nofilter', $month = 0, $year = 0)
  640. {
  641. global $conf;
  642. $this->sdc = 0;
  643. $this->sdcpermonth = array();
  644. $sql = "SELECT SUM(t.debit) as debit, SUM(t.credit) as credit";
  645. if (is_array($cpt)) $sql.=", t.numero_compte as accountancy_account";
  646. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as t";
  647. //if (in_array($this->db->type, array('mysql', 'mysqli'))) $sql.=' USE INDEX idx_accounting_bookkeeping_doc_date';
  648. $sql .= " WHERE t.entity = ".$conf->entity;
  649. if (is_array($cpt))
  650. {
  651. $listofaccount='';
  652. foreach($cpt as $cptcursor)
  653. {
  654. if ($listofaccount) $listofaccount.=",";
  655. $listofaccount.="'".$cptcursor."'";
  656. }
  657. $sql .= " AND t.numero_compte IN (" .$listofaccount. ")";
  658. }
  659. else
  660. {
  661. $sql .= " AND t.numero_compte = '" . $this->db->escape($cpt) . "'";
  662. }
  663. if (! empty($date_start) && ! empty($date_end) && (empty($month) || empty($year))) // If month/year provided, it is stronger than filter date_start/date_end
  664. $sql .= " AND (t.doc_date BETWEEN '".$this->db->idate($date_start)."' AND '".$this->db->idate($date_end)."')";
  665. if (! empty($month) && ! empty($year)) {
  666. $sql .= " AND (t.doc_date BETWEEN '".$this->db->idate(dol_get_first_day($year, $month))."' AND '".$this->db->idate(dol_get_last_day($year, $month))."')";
  667. }
  668. if ($thirdparty_code != 'nofilter')
  669. {
  670. $sql .= " AND t.thirdparty_code = '".$this->db->escape($thirdparty_code)."'";
  671. }
  672. if (is_array($cpt)) $sql.=" GROUP BY t.numero_compte";
  673. //print $sql;
  674. $resql = $this->db->query($sql);
  675. if ($resql)
  676. {
  677. $num = $this->db->num_rows($resql);
  678. if ($num)
  679. {
  680. $obj = $this->db->fetch_object($resql);
  681. if ($sens == 1) {
  682. $this->sdc = $obj->debit - $obj->credit;
  683. } else {
  684. $this->sdc = $obj->credit - $obj->debit;
  685. }
  686. if (is_array($cpt))
  687. {
  688. $this->sdcperaccount[$obj->accountancy_account] = $this->sdc;
  689. }
  690. }
  691. return $num;
  692. } else {
  693. $this->error = "Error " . $this->db->lasterror();
  694. $this->errors[] = $this->error;
  695. dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
  696. return -1;
  697. }
  698. }
  699. /**
  700. * Return list of personalized groups that are active
  701. *
  702. * @param int $categorytype -1=All, 0=Only non computed groups, 1=Only computed groups
  703. * @return array|int Array of groups or -1 if error
  704. */
  705. public function getCats($categorytype = -1)
  706. {
  707. global $conf, $mysoc;
  708. if (empty($mysoc->country_id)) {
  709. dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined');
  710. exit();
  711. }
  712. $sql = "SELECT c.rowid, c.code, c.label, c.formula, c.position, c.category_type, c.sens";
  713. $sql .= " FROM " . MAIN_DB_PREFIX . "c_accounting_category as c";
  714. $sql .= " WHERE c.active = 1";
  715. $sql .= " AND c.entity = " . $conf->entity;
  716. if ($categorytype >= 0) $sql.=" AND c.category_type = 1";
  717. $sql .= " AND (c.fk_country = ".$mysoc->country_id." OR c.fk_country = 0)";
  718. $sql .= " ORDER BY c.position ASC";
  719. $resql = $this->db->query($sql);
  720. if ($resql) {
  721. $i = 0;
  722. $obj = '';
  723. $num = $this->db->num_rows($resql);
  724. $data = array ();
  725. if ($num) {
  726. while ( $i < $num ) {
  727. $obj = $this->db->fetch_object($resql);
  728. $data[] = array (
  729. 'rowid' => $obj->rowid,
  730. 'code' => $obj->code,
  731. 'label' => $obj->label,
  732. 'formula' => $obj->formula,
  733. 'position' => $obj->position,
  734. 'category_type' => $obj->category_type,
  735. 'bc' => $obj->sens
  736. );
  737. $i++;
  738. }
  739. }
  740. return $data;
  741. } else {
  742. $this->error = "Error " . $this->db->lasterror();
  743. $this->errors[] = $this->error;
  744. dol_syslog(__METHOD__ . " " . implode(',', $this->errors), LOG_ERR);
  745. return - 1;
  746. }
  747. }
  748. /**
  749. * Get all accounting account of a group.
  750. * You must choose between first parameter (personalized group) or the second (free criteria filter)
  751. *
  752. * @param int $cat_id Id if personalized accounting group/category
  753. * @param string $predefinedgroupwhere Sql criteria filter to select accounting accounts
  754. * @return array|int Array of accounting accounts or -1 if error
  755. */
  756. public function getCptsCat($cat_id, $predefinedgroupwhere = '')
  757. {
  758. global $conf, $mysoc;
  759. $sql = '';
  760. if (empty($mysoc->country_id) && empty($mysoc->country_code)) {
  761. dol_print_error('', 'Call to select_accounting_account with mysoc country not yet defined');
  762. exit();
  763. }
  764. if (! empty($cat_id))
  765. {
  766. $sql = "SELECT t.rowid, t.account_number, t.label as account_label";
  767. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
  768. $sql .= " WHERE t.fk_accounting_category = ".$cat_id;
  769. $sql .= " AND t.entity = " . $conf->entity;
  770. $sql .= " ORDER BY t.account_number";
  771. }
  772. else
  773. {
  774. $sql = "SELECT t.rowid, t.account_number, t.label as account_label";
  775. $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_account as t";
  776. $sql .= " WHERE ".$predefinedgroupwhere;
  777. $sql .= " AND t.entity = " . $conf->entity;
  778. $sql .= " ORDER BY t.account_number";
  779. }
  780. //echo $sql;
  781. $resql = $this->db->query($sql);
  782. if ($resql) {
  783. $i = 0;
  784. $obj = '';
  785. $num = $this->db->num_rows($resql);
  786. $data = array();
  787. if ($num) {
  788. while ($obj = $this->db->fetch_object($resql))
  789. {
  790. $data[] = array (
  791. 'id' => $obj->rowid,
  792. 'account_number' => $obj->account_number,
  793. 'account_label' => $obj->account_label,
  794. );
  795. $i++;
  796. }
  797. }
  798. return $data;
  799. } else {
  800. $this->error = "Error " . $this->db->lasterror();
  801. dol_syslog(__METHOD__ . " " . $this->error, LOG_ERR);
  802. return -1;
  803. }
  804. }
  805. }