accountancycategory.class.php 24 KB

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