dolibarr 24.0.0-beta
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2013-2014 Olivier Geffroy <jeff@jeffinfo.com>
3 * Copyright (C) 2013-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
4 * Copyright (C) 2014 Florian Henry <florian.henry@open-concept.pro>
5 * Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
6 * Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
28// Load Dolibarr environment
29require '../../main.inc.php';
30require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
31require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingaccount.class.php';
32require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountancysystem.class.php';
33require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
34
43$error = 0;
44
45// Load translation files required by the page
46$langs->loadLangs(array('accountancy', 'bills', 'compta'));
47
48$action = GETPOST('action', 'aZ09');
49$backtopage = GETPOST('backtopage', 'alpha');
50$id = GETPOSTINT('id');
51$ref = GETPOST('ref', 'alpha');
52$rowid = GETPOSTINT('rowid');
53$cancel = GETPOST('cancel', 'alpha');
54
55$account_number = GETPOST('account_number', 'alphanohtml');
56$label = GETPOST('label', 'alpha');
57
58// Security check
59if ($user->socid > 0) {
61}
62if (!$user->hasRight('accounting', 'chartofaccount')) {
64}
65
66
68
69
70/*
71 * Action
72 */
73
74if (GETPOST('cancel', 'alpha')) {
75 $urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
76 header("Location: ".$urltogo);
77 exit;
78}
79
80if ($action == 'add' /* && $user->hasRight('accounting', 'chartofaccount') // already checked */) {
81 if (!$cancel) {
82 if ((string) $account_number === '') {
83 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
84 $action = 'create';
85 } elseif ((string) $label === '') {
86 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
87 $action = 'create';
88 } else {
89 $sql = "SELECT pcg_version FROM " . MAIN_DB_PREFIX . "accounting_system WHERE rowid = ".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
90
91 dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
92 $result = $db->query($sql);
93 $obj = $db->fetch_object($result);
94
95 // Clean code
96
97 // To manage zero or not at the end of the accounting account
98 if (!getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
99 $account_number = clean_account($account_number);
100 }
101
102 $account_parent = (GETPOSTINT('account_parent') > 0) ? GETPOSTINT('account_parent') : 0;
103
104 $object->fk_pcg_version = $obj->pcg_version;
105 $object->pcg_type = GETPOST('pcg_type', 'alpha');
106 $object->account_number = $account_number;
107 $object->account_parent = $account_parent;
108 $object->account_category = GETPOSTINT('account_category');
109 $object->label = $label;
110 $object->labelshort = GETPOST('labelshort', 'alpha');
111 $object->active = 1;
112
113 $res = $object->create($user);
114 if ($res == -3) {
115 $error = 1;
116 $action = "create";
117 setEventMessages($object->error, $object->errors, 'errors');
118 } elseif ($res == -4) {
119 $error = 2;
120 $action = "create";
121 setEventMessages($object->error, $object->errors, 'errors');
122 } elseif ($res < 0) {
123 $error++;
124 setEventMessages($object->error, $object->errors, 'errors');
125 $action = "create";
126 }
127 if (!$error) {
128 setEventMessages("RecordCreatedSuccessfully", null, 'mesgs');
129 $urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
130 header("Location: " . $urltogo);
131 exit;
132 }
133 }
134 }
135} elseif ($action == 'edit' /* && $user->hasRight('accounting', 'chartofaccount') // already checked */) {
136 if (!$cancel) {
137 if ((string) $account_number === '') {
138 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("AccountNumber")), null, 'errors');
139 $action = 'update';
140 } elseif ((string) $label === '') {
141 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Label")), null, 'errors');
142 $action = 'update';
143 } else {
144 $result = $object->fetch($id);
145
146 $sql = "SELECT pcg_version FROM ".MAIN_DB_PREFIX."accounting_system WHERE rowid=".((int) getDolGlobalInt('CHARTOFACCOUNTS'));
147
148 dol_syslog('accountancy/admin/card.php:: $sql=' . $sql);
149 $result2 = $db->query($sql);
150 $obj = $db->fetch_object($result2);
151
152 // Clean code
153
154 // To manage zero or not at the end of the accounting account
155 if (!getDolGlobalString('ACCOUNTING_MANAGE_ZERO')) {
156 $account_number = clean_account($account_number);
157 }
158
159 $account_parent = (GETPOSTINT('account_parent') > 0) ? GETPOSTINT('account_parent') : 0;
160
161 $object->fk_pcg_version = $obj->pcg_version;
162 $object->pcg_type = GETPOST('pcg_type', 'alpha');
163 $object->account_number = $account_number;
164 $object->account_parent = $account_parent;
165 $object->account_category = GETPOSTINT('account_category');
166 $object->label = $label;
167 $object->labelshort = GETPOST('labelshort', 'alpha');
168
169 $result = $object->update($user);
170
171 if ($result > 0) {
172 $urltogo = (!empty($backtopage) ? $backtopage : ($_SERVER["PHP_SELF"] . "?id=" . $id));
173 header("Location: " . $urltogo);
174 exit();
175 } elseif ($result == -2) {
176 setEventMessages($langs->trans("ErrorAccountNumberAlreadyExists", $object->account_number), null, 'errors');
177 } else {
178 setEventMessages($object->error, null, 'errors');
179 }
180 }
181 } else {
182 $urltogo = (!empty($backtopage) ? $backtopage : ($_SERVER["PHP_SELF"]."?id=".$id));
183 header("Location: ".$urltogo);
184 exit();
185 }
186} elseif ($action == 'delete' && $user->hasRight('accounting', 'chartofaccount')) {
187 $result = $object->fetch($id);
188
189 if (!empty($object->id)) {
190 $result = $object->delete($user);
191
192 if ($result > 0) {
193 $urltogo = (!empty($backtopage) ? $backtopage : DOL_URL_ROOT.'/accountancy/admin/account.php');
194 header("Location: ".$urltogo);
195 exit;
196 }
197 }
198
199 if ($result < 0) {
200 setEventMessages($object->error, $object->errors, 'errors');
201 }
202}
203
204
205/*
206 * View
207 */
208
209$form = new Form($db);
210$formaccounting = new FormAccounting($db);
211
212$accountsystem = new AccountancySystem($db);
213$accountsystem->fetch(getDolGlobalInt('CHARTOFACCOUNTS'));
214
215$title = $langs->trans('AccountAccounting')." - ".$langs->trans('Card');
216
217$help_url = 'EN:Module_Double_Entry_Accounting#Setup|FR:Module_Comptabilit&eacute;_en_Partie_Double#Configuration';
218
219llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-accountancy page-admin_card');
220
221
222// Create mode
223if ($action == 'create') {
224 print load_fiche_titre($langs->trans('NewAccountingAccount'));
225
226 print '<form name="add" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
227 print '<input type="hidden" name="token" value="'.newToken().'">';
228 print '<input type="hidden" name="action" value="add">';
229
230 print dol_get_fiche_head();
231
232 print '<table class="border centpercent">';
233
234 // Chart of account
235 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("Chartofaccounts").'</span></td>';
236 print '<td>';
237 print $accountsystem->ref;
238 print '</td></tr>';
239
240 // Account number
241 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("AccountNumber").'</span></td>';
242 print '<td><input name="account_number" size="30" value="'.$account_number.'"></td></tr>';
243
244 // Label
245 print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td>';
246 print '<td><input name="label" size="70" value="'.$object->label.'"></td></tr>';
247
248 // Label short
249 print '<tr><td>'.$langs->trans("ShortLabel").'</td>';
250 print '<td><input name="labelshort" size="70" value="'.$object->labelshort.'"></td></tr>';
251
252 // Account parent
253 print '<tr><td>'.$langs->trans("Accountparent").'</td>';
254 print '<td>';
255 print $formaccounting->select_account((string) $object->account_parent, 'account_parent', 1, [], 0, 0, 'minwidth200');
256 print '</td></tr>';
257
258 // Chart of accounts type
259 print '<tr><td>';
260 print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
261 print '</td>';
262 print '<td>';
263 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).'">';
264 // autosuggest from existing account types if found
265 print '<datalist id="pcg_type_datalist">';
266 $sql = "SELECT DISTINCT pcg_type FROM " . MAIN_DB_PREFIX . "accounting_account";
267 $sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
268 $sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
269 $sql .= ' LIMIT 50000'; // just as a sanity check
270 $resql = $db->query($sql);
271 if ($resql) {
272 while ($obj = $db->fetch_object($resql)) {
273 print '<option value="' . dol_escape_htmltag($obj->pcg_type) . '">';
274 }
275 }
276 print '</datalist>';
277 print '</td></tr>';
278
279 // Category
280 print '<tr><td>';
281 print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
282 print '</td>';
283 print '<td>';
284 print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1, 0, 1);
285 print '</td></tr>';
286
287 print '</table>';
288
289 print dol_get_fiche_end();
290
291 print '<div class="center">';
292 print '<input class="button button-save" type="submit" value="'.$langs->trans("Save").'">';
293 print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
294 print '<input class="button button-cancel" type="submit" name="cancel" value="'.$langs->trans("Cancel").'">';
295 print '</div>';
296
297 print '</form>';
298} elseif ($id > 0 || $ref) {
299 $result = $object->fetch($id, $ref, 1);
300
301 if ($result > 0) {
302 $head = accounting_prepare_head($object);
303
304 // Edit mode
305 if ($action == 'update') {
306 print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), 0, 'accounting_account');
307
308 print '<form name="update" action="'.$_SERVER["PHP_SELF"].'" method="POST">'."\n";
309 print '<input type="hidden" name="token" value="'.newToken().'">';
310 print '<input type="hidden" name="action" value="edit">';
311 print '<input type="hidden" name="id" value="'.$id.'">';
312 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
313
314 print '<table class="border centpercent">';
315
316 // Account number
317 print '<tr><td class="titlefieldcreate"><span class="fieldrequired">'.$langs->trans("AccountNumber").'</span></td>';
318 print '<td><input class="minwidth300" name="account_number" value="'.$object->account_number.'"></td></tr>';
319
320 // Label
321 print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td>';
322 print '<td><input class="minwidth500" name="label" value="'.$object->label.'"></td></tr>';
323
324 // Label short
325 print '<tr><td>'.$langs->trans("ShortLabel").'</td>';
326 print '<td><input class="minwidth300" name="labelshort" value="'.$object->labelshort.'"></td></tr>';
327
328 // Account parent
329 print '<tr><td>'.$langs->trans("Accountparent").'</td>';
330 print '<td>';
331 // Note: We accept disabled account as parent account so we can build a hierarchy and use only children
332 print $formaccounting->select_account((string) $object->account_parent, 'account_parent', 1, array(), 0, 0, 'minwidth100 maxwidth300 maxwidthonsmartphone', '1', '');
333 print '</td></tr>';
334
335 // Chart of accounts type
336 print '<tr><td>';
337 print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
338 print '</td>';
339 print '<td>';
340 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).'">';
341 // autosuggest from existing account types if found
342 print '<datalist id="pcg_type_datalist">';
343 $sql = 'SELECT DISTINCT pcg_type FROM ' . MAIN_DB_PREFIX . 'accounting_account';
344 $sql .= " WHERE fk_pcg_version = '" . $db->escape($accountsystem->ref) . "'";
345 $sql .= ' AND entity in ('.getEntity('accounting_account', 0).')'; // Always limit to current entity. No sharing in accountancy.
346 $sql .= ' LIMIT 50000'; // just as a sanity check
347 $resql = $db->query($sql);
348 if ($resql) {
349 while ($obj = $db->fetch_object($resql)) {
350 print '<option value="' . dol_escape_htmltag($obj->pcg_type) . '">';
351 }
352 }
353 print '</datalist>';
354 print '</td></tr>';
355
356 // Category
357 print '<tr><td>';
358 print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
359 print '</td>';
360 print '<td>';
361 print $formaccounting->select_accounting_category($object->account_category, 'account_category', 1);
362 print '</td></tr>';
363
364 print '</table>';
365
366 print dol_get_fiche_end();
367
368 print $form->buttonsSaveCancel();
369
370 print '</form>';
371 } else {
372 // View mode
373 $linkback = '<a href="'.DOL_URL_ROOT.'/accountancy/admin/account.php?restore_lastsearch_values=1">'.$langs->trans("BackToList").'</a>';
374
375 print dol_get_fiche_head($head, 'card', $langs->trans('AccountAccounting'), -1, 'accounting_account');
376
377 dol_banner_tab($object, 'ref', $linkback, 1, 'account_number', 'ref');
378
379
380 print '<div class="fichecenter">';
381 print '<div class="underbanner clearboth"></div>';
382
383 print '<table class="border centpercent tableforfield">';
384
385 // Label
386 print '<tr><td class="titlefield">'.$langs->trans("Label").'</td>';
387 print '<td colspan="2">'.$object->label.'</td></tr>';
388
389 // Label to show
390 print '<tr><td class="titlefield">'.$langs->trans("ShortLabel").'</td>';
391 print '<td colspan="2">'.$object->labelshort.'</td></tr>';
392
393 // Account parent
394 $accp = new AccountingAccount($db);
395 if (!empty($object->account_parent)) {
396 $accp->fetch($object->account_parent, '');
397 }
398 print '<tr><td>'.$langs->trans("Accountparent").'</td>';
399 print '<td colspan="2">'.$accp->account_number.' - '.$accp->label.'</td></tr>';
400
401 // Group of accounting account
402 print '<tr><td>';
403 print $form->textwithpicto($langs->trans("Pcgtype"), $langs->transnoentitiesnoconv("PcgtypeDesc"));
404 print '</td>';
405 print '<td colspan="2">'.$object->pcg_type.'</td></tr>';
406
407 // Custom group of accounting account
408 print "<tr><td>";
409 print $form->textwithpicto($langs->trans("AccountingCategory"), $langs->transnoentitiesnoconv("AccountingAccountGroupsDesc"));
410 print "</td><td colspan='2'>".$object->account_category_label."</td>";
411
412 print '</table>';
413
414 print '</div>';
415
416 print dol_get_fiche_end();
417
418 /*
419 * Actions buttons
420 */
421 print '<div class="tabsAction">';
422
423 // if ($user->hasRight('accounting', 'chartofaccount')) { // already checked
424 print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=update&token='.newToken().'&id='.$object->id.'">'.$langs->trans('Modify').'</a>';
425 // } else {
426 // print '<a class="butActionRefused classfortooltip" href="#" title="'.dol_escape_htmltag($langs->trans("NotAllowed")).'">'.$langs->trans('Modify').'</a>';
427 // }
428
429 // Delete
430 $permissiontodelete = $user->hasRight('accounting', 'chartofaccount');
431 print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken(), 'delete', $permissiontodelete);
432
433 print '</div>';
434 }
435 } else {
436 dol_print_error($db, $object->error, $object->errors);
437 }
438}
439
440// End of page
441llxFooter();
442$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
accounting_prepare_head(AccountingAccount $object)
Prepare array with list of tabs.
clean_account($account)
Return accounting account without zero on the right.
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage accountancy systems.
Class to manage accounting accounts.
Class to manage generation of HTML components for accounting management.
Class to manage generation of HTML components Only common components must be here.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
setEventMessages($mesg, $mesgs, $style='mesgs', $messagekey='', $noduplicate=0, $attop=0)
Set event messages in dol_events session object.
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='', $logcontext=null)
Write log message into outputs.
dol_escape_htmltag($stringtoescape, $keepb=0, $keepn=0, $noescapetags='', $escapeonlyhtmltags=0, $cleanalsojavascript=0)
Returns text escaped for inclusion in HTML alt or title or value tags, or into values of HTML input f...
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.