card.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. <?php
  2. /* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
  3. * Copyright (C) 2013-2024 Alexandre Spangaro <aspangaro@easya.solutions>
  4. * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
  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/admin/card.php
  21. * \ingroup Accountancy (Double entries)
  22. * \brief Card of accounting account
  23. */
  24. // Load Dolibarr environment
  25. require '../../main.inc.php';
  26. require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
  27. require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
  28. require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancysystem.class.php';
  29. require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
  30. $error = 0;
  31. // Load translation files required by the page
  32. $langs->loadLangs(array('accountancy', 'bills', 'compta'));
  33. $action = GETPOST('action', 'aZ09');
  34. $backtopage = GETPOST('backtopage', 'alpha');
  35. $id = GETPOST('id', 'int');
  36. $ref = GETPOST('ref', 'alpha');
  37. $rowid = GETPOST('rowid', 'int');
  38. $cancel = GETPOST('cancel', 'alpha');
  39. $account_number = GETPOST('account_number', 'alphanohtml');
  40. $label = GETPOST('label', 'alpha');
  41. // Security check
  42. if ($user->socid > 0) {
  43. accessforbidden();
  44. }
  45. if (!$user->hasRight('accounting', 'chartofaccount')) {
  46. accessforbidden();
  47. }
  48. $object = new AccountingAccount($db);
  49. /*
  50. * Action
  51. */
  52. if (GETPOST('cancel', 'alpha')) {
  53. $urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
  54. header("Location: ".$urltogo);
  55. exit;
  56. }
  57. if ($action == 'add' && $user->hasRight('accounting', 'chartofaccount')) {
  58. if (!$cancel) {
  59. if (!$account_number) {
  60. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
  61. $action = 'create';
  62. } elseif (!$label) {
  63. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  64. $action = 'create';
  65. } else {
  66. $sql = "SELECT pcg_version FROM " . MAIN_DB_PREFIX . "accounting_system WHERE rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
  67. dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
  68. $result = $db->query($sql);
  69. $obj = $db->fetch_object($result);
  70. // Clean code
  71. // To manage zero or not at the end of the accounting account
  72. if (getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
  73. $account_number = $account_number;
  74. } else {
  75. $account_number = clean_account($account_number);
  76. }
  77. if (GETPOST('account_parent', 'int') <= 0) {
  78. $account_parent = 0;
  79. } else {
  80. $account_parent = GETPOST('account_parent', 'int');
  81. }
  82. $object->fk_pcg_version = $obj->pcg_version;
  83. $object->pcg_type = GETPOST('pcg_type', 'alpha');
  84. $object->account_number = $account_number;
  85. $object->account_parent = $account_parent;
  86. $object->account_category = GETPOST('account_category', 'alpha');
  87. $object->label = $label;
  88. $object->labelshort = GETPOST('labelshort', 'alpha');
  89. $object->active = 1;
  90. $res = $object->create($user);
  91. if ($res == -3) {
  92. $error = 1;
  93. $action = "create";
  94. setEventMessages($object->error, $object->errors, 'errors');
  95. } elseif ($res == -4) {
  96. $error = 2;
  97. $action = "create";
  98. setEventMessages($object->error, $object->errors, 'errors');
  99. } elseif ($res < 0) {
  100. $error++;
  101. setEventMessages($object->error, $object->errors, 'errors');
  102. $action = "create";
  103. }
  104. if (!$error) {
  105. setEventMessages("RecordCreatedSuccessfully", null, 'mesgs');
  106. $urltogo = $backtopage ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php';
  107. header("Location: " . $urltogo);
  108. exit;
  109. }
  110. }
  111. }
  112. } elseif ($action == 'edit' && $user->hasRight('accounting', 'chartofaccount')) {
  113. if (!$cancel) {
  114. if (!$account_number) {
  115. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
  116. $action = 'update';
  117. } elseif (!$label) {
  118. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
  119. $action = 'update';
  120. } else {
  121. $result = $object->fetch($id);
  122. $sql = "SELECT pcg_version FROM ".MAIN_DB_PREFIX."accounting_system WHERE rowid=".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
  123. dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
  124. $result2 = $db->query($sql);
  125. $obj = $db->fetch_object($result2);
  126. // Clean code
  127. // To manage zero or not at the end of the accounting account
  128. if (getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
  129. $account_number = $account_number;
  130. } else {
  131. $account_number = clean_account($account_number);
  132. }
  133. if (GETPOST('account_parent', 'int') <= 0) {
  134. $account_parent = 0;
  135. } else {
  136. $account_parent = GETPOST('account_parent', 'int');
  137. }
  138. $object->fk_pcg_version = $obj->pcg_version;
  139. $object->pcg_type = GETPOST('pcg_type', 'alpha');
  140. $object->account_number = $account_number;
  141. $object->account_parent = $account_parent;
  142. $object->account_category = GETPOST('account_category', 'alpha');
  143. $object->label = $label;
  144. $object->labelshort = GETPOST('labelshort', 'alpha');
  145. $result = $object->update($user);
  146. if ($result > 0) {
  147. $urltogo = $backtopage ? $backtopage : ($_SERVER["PHP_SELF"] . "?id=" . $id);
  148. header("Location: " . $urltogo);
  149. exit();
  150. } elseif ($result == -2) {
  151. setEventMessages($langs->trans("ErrorAccountNumberAlreadyExists", $object->account_number), null, 'errors');
  152. } else {
  153. setEventMessages($object->error, null, 'errors');
  154. }
  155. }
  156. } else {
  157. $urltogo = $backtopage ? $backtopage : ($_SERVER["PHP_SELF"]."?id=".$id);
  158. header("Location: ".$urltogo);
  159. exit();
  160. }
  161. } elseif ($action == 'delete' && $user->hasRight('accounting', 'chartofaccount')) {
  162. $result = $object->fetch($id);
  163. if (!empty($object->id)) {
  164. $result = $object->delete($user);
  165. if ($result > 0) {
  166. header("Location: account.php");
  167. exit;
  168. }
  169. }
  170. if ($result < 0) {
  171. setEventMessages($object->error, $object->errors, 'errors');
  172. }
  173. }
  174. /*
  175. * View
  176. */
  177. $form = new Form($db);
  178. $formaccounting = new FormAccounting($db);
  179. $accountsystem = new AccountancySystem($db);
  180. $accountsystem->fetch(getDolGlobalInt('CHARTOFACCOUNTS'));
  181. $title = $langs->trans('AccountAccounting')." - ".$langs->trans('Card');
  182. $help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilit&eacute;_en_Partie_Double#Configuration';
  183. llxheader('', $title, $help_url);
  184. // Create mode
  185. if ($action == 'create') {
  186. print load_fiche_titre($langs->trans('NewAccountingAccount'));
  187. print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
  188. print '<input type="hidden" name="token" value="'.newToken().'">';
  189. print '<input type="hidden" name="action" value="add">';
  190. print dol_get_fiche_head();
  191. print '<table class="border centpercent">';
  192. // Chart of account
  193. print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Chartofaccounts").'</span></td>';
  194. print '<td>';
  195. print $accountsystem->ref;
  196. print '</td></tr>';
  197. // Account number
  198. print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("AccountNumber").'</span></td>';
  199. print '<td><input name="account_number" size="30" value="'.$account_number.'"></td></tr>';
  200. // Label
  201. print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td>';
  202. print '<td><input name="label" size="70" value="'.$object->label.'"></td></tr>';
  203. // Label short
  204. print '<tr><td>'.$langs->trans("LabelToShow").'</td>';
  205. print '<td><input name="labelshort" size="70" value="'.$object->labelshort.'"></td></tr>';
  206. // Account parent
  207. print '<tr><td>'.$langs->trans("Accountparent").'</td>';
  208. print '<td>';
  209. print $formaccounting->select_account($object->account_parent, 'account_parent', 1, null, 0, 0, 'minwidth200');
  210. print '</td></tr>';
  211. // Chart of accounts type
  212. print '<tr><td>';
  213. print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
  214. print '</td>';
  215. print '<td>';
  216. print '<input type="text" name="pcg_type" list="pcg_type_datalist" value="'.dol_escape_htmltag(GETPOSTISSET('pcg_type') ? GETPOST('pcg_type', 'alpha') : $object->pcg_type).'">';
  217. // autosuggest from existing account types if found
  218. print '<datalist id="pcg_type_datalist">';
  219. $sql = "SELECT DISTINCT pcg_type FROM " . MAIN_DB_PREFIX . "accounting_account";
  220. $sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
  221. $sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
  222. $sql .= ' LIMIT 50000'; // just as a sanity check
  223. $resql = $db->query($sql);
  224. if ($resql) {
  225. while ($obj = $db->fetch_object($resql)) {
  226. print '<option value="' . dol_escape_htmltag($obj->pcg_type) . '">';
  227. }
  228. }
  229. print '</datalist>';
  230. print '</td></tr>';
  231. // Category
  232. print '<tr><td>';
  233. print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
  234. print '</td>';
  235. print '<td>';
  236. print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1, 0, 1);
  237. print '</td></tr>';
  238. print '</table>';
  239. print dol_get_fiche_end();
  240. print '<div class="center">';
  241. print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">';
  242. print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
  243. print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
  244. print '</div>';
  245. print '</form>';
  246. } elseif ($id > 0 || $ref) {
  247. $result = $object->fetch($id, $ref, 1);
  248. if ($result > 0) {
  249. $head = accounting_prepare_head($object);
  250. // Edit mode
  251. if ($action == 'update') {
  252. print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'accounting_account');
  253. print '<form name="update" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
  254. print '<input type="hidden" name="token" value="'.newToken().'">';
  255. print '<input type="hidden" name="action" value="edit">';
  256. print '<input type="hidden" name="id" value="'.$id.'">';
  257. print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
  258. print '<table class="border centpercent">';
  259. // Account number
  260. print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("AccountNumber").'</span></td>';
  261. print '<td><input name="account_number" size="30" value="'.$object->account_number.'"</td></tr>';
  262. // Label
  263. print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td>';
  264. print '<td><input name="label" size="70" value="'.$object->label.'"</td></tr>';
  265. // Label short
  266. print '<tr><td>'.$langs->trans("LabelToShow").'</td>';
  267. print '<td><input name="labelshort" size="70" value="'.$object->labelshort.'"</td></tr>';
  268. // Account parent
  269. print '<tr><td>'.$langs->trans("Accountparent").'</td>';
  270. print '<td>';
  271. // Note: We accept disabled account as parent account so we can build a hierarchy and use only childs
  272. print $formaccounting->select_account($object->account_parent, 'account_parent', 1, array(), 0, 0, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1, '');
  273. print '</td></tr>';
  274. // Chart of accounts type
  275. print '<tr><td>';
  276. print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
  277. print '</td>';
  278. print '<td>';
  279. print '<input type="text" name="pcg_type" list="pcg_type_datalist" value="'.dol_escape_htmltag(GETPOSTISSET('pcg_type') ? GETPOST('pcg_type', 'alpha') : $object->pcg_type).'">';
  280. // autosuggest from existing account types if found
  281. print '<datalist id="pcg_type_datalist">';
  282. $sql = 'SELECT DISTINCT pcg_type FROM ' . MAIN_DB_PREFIX . 'accounting_account';
  283. $sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
  284. $sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
  285. $sql .= ' LIMIT 50000'; // just as a sanity check
  286. $resql = $db->query($sql);
  287. if ($resql) {
  288. while ($obj = $db->fetch_object($resql)) {
  289. print '<option value="' . dol_escape_htmltag($obj->pcg_type) . '">';
  290. }
  291. }
  292. print '</datalist>';
  293. print '</td></tr>';
  294. // Category
  295. print '<tr><td>';
  296. print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
  297. print '</td>';
  298. print '<td>';
  299. print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1);
  300. print '</td></tr>';
  301. print '</table>';
  302. print dol_get_fiche_end();
  303. print $form->buttonsSaveCancel();
  304. print '</form>';
  305. } else {
  306. // View mode
  307. $linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/account.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
  308. print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), -1, 'accounting_account');
  309. dol_banner_tab($object, 'ref', $linkback, 1, 'account_number', 'ref');
  310. print '<div class="fichecenter">';
  311. print '<div class="underbanner clearboth"></div>';
  312. print '<table class="border centpercent tableforfield">';
  313. // Label
  314. print '<tr><td class="titlefield">'.$langs->trans("Label").'</td>';
  315. print '<td colspan="2">'.$object->label.'</td></tr>';
  316. // Label to show
  317. print '<tr><td class="titlefield">'.$langs->trans("LabelToShow").'</td>';
  318. print '<td colspan="2">'.$object->labelshort.'</td></tr>';
  319. // Account parent
  320. $accp = new AccountingAccount($db);
  321. if (!empty($object->account_parent)) {
  322. $accp->fetch($object->account_parent, '');
  323. }
  324. print '<tr><td>'.$langs->trans("Accountparent").'</td>';
  325. print '<td colspan="2">'.$accp->account_number.' - '.$accp->label.'</td></tr>';
  326. // Group of accounting account
  327. print '<tr><td>';
  328. print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
  329. print '</td>';
  330. print '<td colspan="2">'.$object->pcg_type.'</td></tr>';
  331. // Custom group of accounting account
  332. print "<tr><td>";
  333. print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
  334. print "</td><td colspan='2'>".$object->account_category_label."</td>";
  335. print '</table>';
  336. print '</div>';
  337. print dol_get_fiche_end();
  338. /*
  339. * Actions buttons
  340. */
  341. print '<div class="tabsAction">';
  342. if ($user->hasRight('accounting', 'chartofaccount')) {
  343. print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Modify').'</a>';
  344. } else {
  345. print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Modify').'</a>';
  346. }
  347. // Delete
  348. $permissiontodelete = $user->hasRight('accounting', 'chartofaccount');
  349. print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete);
  350. print '</div>';
  351. }
  352. } else {
  353. dol_print_error($db, $object->error, $object->errors);
  354. }
  355. }
  356. // End of page
  357. llxFooter();
  358. $db->close();