dolibarr 24.0.0-beta
workflow.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
4 * Copyright (C) 2005-2021 Laurent Destailleur <eldy@users.sourceforge.net>
5 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
6 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
7 * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
29// Load Dolibarr environment
30require '../main.inc.php';
31require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
32
41// security check
42if (!$user->admin) {
44}
45
46// Load translation files required by the page
47$langs->loadLangs(array("admin", "workflow", "propal", "workflow", "orders", "supplier_proposal", "receptions", "errors", 'sendings'));
48
49$action = GETPOST('action', 'aZ09');
50
51
52/*
53 * Actions
54 */
55
56if (preg_match('/set(.*)/', $action, $reg)) {
57 if (!dolibarr_set_const($db, $reg[1], '1', 'chaine', 0, '', $conf->entity) > 0) {
59 }
60}
61
62if (preg_match('/del(.*)/', $action, $reg)) {
63 if (!dolibarr_set_const($db, $reg[1], '0', 'chaine', 0, '', $conf->entity) > 0) {
65 }
66}
67
68
69// List of workflow we can enable
70clearstatcache();
71
73$workflowcodes = array(
74 // Automatic creation
75 'WORKFLOW_PROPAL_AUTOCREATE_ORDER' => array(
76 'family' => 'create',
77 'position' => 10,
78 'enabled' => (isModEnabled("propal") && isModEnabled('order')),
79 'picto' => 'order'
80 ),
81 'WORKFLOW_ORDER_AUTOCREATE_INVOICE' => array(
82 'family' => 'create',
83 'position' => 20,
84 'enabled' => (isModEnabled('order') && isModEnabled('invoice')),
85 'picto' => 'bill'
86 ),
87 'WORKFLOW_TICKET_CREATE_INTERVENTION' => array(
88 'family' => 'create',
89 'position' => 25,
90 'enabled' => (isModEnabled('ticket') && isModEnabled('intervention')),
91 'picto' => 'ticket'
92 ),
93
94 'separator1' => array('family' => 'separator', 'position' => 25, 'title' => '', 'enabled' => ((isModEnabled("propal") && isModEnabled('order')) || (isModEnabled('order') && isModEnabled('invoice')) || (isModEnabled('ticket') && isModEnabled('intervention')))),
95
96 // Automatic classification of proposal
97 'WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL' => array(
98 'family' => 'classify_proposal',
99 'position' => 30,
100 'enabled' => (isModEnabled("propal") && isModEnabled('order')),
101 'picto' => 'propal',
102 'warning' => ''
103 ),
104 'WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL' => array(
105 'family' => 'classify_proposal',
106 'position' => 31,
107 'enabled' => (isModEnabled("propal") && isModEnabled('invoice')),
108 'picto' => 'propal',
109 'warning' => ''
110 ),
111
112 // Automatic classification of order
113 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING' => array( // when shipping validated
114 'family' => 'classify_order',
115 'position' => 40,
116 'enabled' => (isModEnabled("shipping") && isModEnabled('order')),
117 'picto' => 'order'
118 ),
119 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED' => array( // when shipping closed
120 'family' => 'classify_order',
121 'position' => 41,
122 'enabled' => (isModEnabled("shipping") && isModEnabled('order')),
123 'picto' => 'order'
124 ),
125 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER' => array(
126 'family' => 'classify_order',
127 'position' => 42,
128 'enabled' => (isModEnabled('invoice') && isModEnabled('order')),
129 'picto' => 'order',
130 'warning' => ''
131 ), // For this option, if module invoice is disabled, it does not exists, so "Classify billed" for order must be done manually from order card.
132
133 'WORKFLOW_SUM_INVOICES_AMOUNT_CLASSIFY_BILLED_ORDER' => array(
134 'family' => 'classify_order',
135 'position' => 43,
136 'enabled' => (isModEnabled('invoice') && isModEnabled('order')),
137 'picto' => 'order',
138 'warning' => ''
139 ), // For this option, if module invoice is disabled, it does not exists, so "Classify billed" for order must be done manually from order card.
140
141 // Automatic classification supplier proposal
142 'WORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL' => array(
143 'family' => 'classify_supplier_proposal',
144 'position' => 60,
145 'enabled' => (isModEnabled('supplier_proposal') && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))),
146 'picto' => 'supplier_proposal',
147 'warning' => ''
148 ),
149
150 // Automatic classification supplier order
151 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION' => array(
152 'family' => 'classify_supplier_order',
153 'position' => 63,
154 'enabled' => (getDolGlobalString('MAIN_FEATURES_LEVEL') && isModEnabled("reception") && isModEnabled('supplier_order')),
155 'picto' => 'supplier_order',
156 'warning' => ''
157 ),
158
159 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED' => array(
160 'family' => 'classify_supplier_order',
161 'position' => 64,
162 'enabled' => (getDolGlobalString('MAIN_FEATURES_LEVEL') && isModEnabled("reception") && isModEnabled('supplier_order')),
163 'picto' => 'supplier_order',
164 'warning' => ''
165 ),
166
167 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER' => array(
168 'family' => 'classify_supplier_order',
169 'position' => 65,
170 'enabled' => (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")),
171 'picto' => 'supplier_order',
172 'warning' => ''
173 ),
174
175 // Automatic classification shipping
176 /* Replaced by next option
177 'WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE' => array(
178 'family' => 'classify_shipping',
179 'position' => 90,
180 'enabled' => isModEnabled("shipping") && isModEnabled("invoice"),
181 'picto' => 'shipment',
182 'deprecated' => 1
183 ),
184 */
185
186 'WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE' => array(
187 'family' => 'classify_shipping',
188 'position' => 91,
189 'enabled' => isModEnabled("shipping") && isModEnabled("invoice") && getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0',
190 'picto' => 'shipment'
191 ),
192
193 // Automatic classification reception
194 /*
195 'WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE'=>array(
196 'family'=>'classify_reception',
197 'position'=>95,
198 'enabled'=>(isModEnabled("reception") && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))),
199 'picto'=>'reception'
200 ),
201 */
202
203 'WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE' => array(
204 'family' => 'classify_reception',
205 'position' => 91,
206 'enabled' => isModEnabled("reception") && isModEnabled("supplier_invoice") && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0',
207 'picto' => 'shipment'
208 ),
209
210
211 'separator2' => array('family' => 'separator', 'position' => 400, 'enabled' => (isModEnabled('ticket') && isModEnabled('contract'))),
212
213 // Automatic link ticket -> contract
214 'WORKFLOW_TICKET_LINK_CONTRACT' => array(
215 'family' => 'link_ticket',
216 'position' => 500,
217 'enabled' => (isModEnabled('ticket') && isModEnabled('contract')),
218 'picto' => 'ticket',
219 'reloadpage' => 1 // So next option can be shown
220 ),
221 // This one depends on previous one WORKFLOW_TICKET_LINK_CONTRACT
222 'WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS' => array(
223 'family' => 'link_ticket',
224 'position' => 501,
225 'enabled' => (isModEnabled('ticket') && isModEnabled('contract') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT')),
226 'picto' => 'ticket'
227 ),
228);
229
230if (!empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) {
231 foreach ($conf->modules_parts['workflow'] as $workflow) {
233 $workflowcodes = array_merge($workflowcodes, $workflow);
234 }
235}
236
237// remove not available workflows (based on activated modules and global defined keys)
238$workflowcodes = array_filter(
239 $workflowcodes,
244 static function ($var) {
245 return (bool) $var['enabled'];
246 }
247);
248
249if ($action == 'setvarworkflow') { // Test on permission already done
250 if (GETPOSTISSET('product_category_id')) {
251 $param_ticket_product_category = GETPOSTINT('product_category_id');
252 $res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity);
253 }
254}
255
256
257/*
258 * View
259 */
260
261llxHeader('', $langs->trans("WorkflowSetup"), "EN:Module_Workflow_En|FR:Module_Workflow|ES:Módulo_Workflow", '', 0, 0, '', '', '', 'mod-admin page-workflow');
262
263$linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
264
265print load_fiche_titre($langs->trans("WorkflowSetup"), $linkback, 'title_setup');
266
267print '<span class="opacitymedium">'.$langs->trans("WorkflowDesc").'</span>';
268print '<br>';
269print '<br>';
270
271// current module setup don't support any automatic workflow of this module
272if (count($workflowcodes) < 1) {
273 print $langs->trans("ThereIsNoWorkflowToModify");
274
275 llxFooter();
276 $db->close();
277 return;
278}
279
280// Sort on position
281$workflowcodes = dol_sort_array($workflowcodes, 'position');
282
283print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
284print '<input type="hidden" name="token" value="'.newToken().'">';
285print '<input type="hidden" name="action" value="setvarworkflow">';
286print '<input type="hidden" name="page_y" value="">';
287
288$oldfamily = '';
289$tableopen = 0;
290$atleastoneline = 0;
291
292foreach ($workflowcodes as $key => $params) {
293 if ($params['family'] == 'separator') {
294 if ($atleastoneline) {
295 print '</table>';
296 print '<br>'."\n";
297
298 $oldfamily = '';
299 $atleastoneline = 0;
300 }
301 continue;
302 }
303
304 $reg = array();
305 if ($oldfamily != $params['family']) {
306 // New group
307 if ($params['family'] == 'create') {
308 $headerfamily = $langs->trans("AutomaticCreation");
309 $header = $langs->trans("AutomaticCreation");
310 } elseif (preg_match('/classify_(.*)/', $params['family'], $reg)) {
311 $headerfamily = $langs->trans("AutomaticClassification");
312 $header = $langs->trans("AutomaticClassification");
313 if ($reg[1] == 'proposal') {
314 $header .= ' - '.$langs->trans('Proposal');
315 }
316 if ($reg[1] == 'order') {
317 $header .= ' - '.$langs->trans('Order');
318 }
319 if ($reg[1] == 'supplier_proposal') {
320 $header .= ' - '.$langs->trans('SupplierProposal');
321 }
322 if ($reg[1] == 'supplier_order') {
323 $header .= ' - '.$langs->trans('SupplierOrder');
324 }
325 if ($reg[1] == 'reception') {
326 $header .= ' - '.$langs->trans('Reception');
327 }
328 if ($reg[1] == 'shipping') {
329 $header .= ' - '.$langs->trans('Shipment');
330 }
331 } elseif (preg_match('/link_(.*)/', $params['family'], $reg)) {
332 $headerfamily = $langs->trans("AutomaticLinking");
333 $header = $langs->trans("AutomaticLinking");
334 if ($reg[1] == 'ticket') {
335 $header .= ' - '.$langs->trans('Ticket');
336 }
337 } else {
338 $headerfamily = $langs->trans("Other");
339 $header = $langs->trans("Description");
340 }
341
342 if ($tableopen) {
343 print '</table><br>'."\n";
344 }
345
346 if ($oldfamily == '') {
347 print load_fiche_titre($headerfamily);
348 }
349
350 print "\n";
351 print '<table class="noborder centpercent">';
352 $tableopen = 1;
353
354 print '<tr class="liste_titre">';
355 print '<th>'.$header.'</th>';
356 print '<th class="right"></th>';
357 print '</tr>';
358
359 $oldfamily = $params['family'];
360 }
361
362 $atleastoneline = 1;
363
364 print '<tr class="oddeven">';
365 print '<td>';
366 print img_object('', $params['picto'], 'class="pictofixedwidth"');
367 print ' '.$langs->trans('desc'.$key);
368
369 if (!empty($params['warning'])) {
370 print ' '.img_warning($langs->transnoentitiesnoconv($params['warning']));
371 }
372 if (!empty($params['deprecated'])) {
373 print ' '.img_warning($langs->transnoentitiesnoconv("Deprecated"));
374 }
375
376 if ($key == 'WORKFLOW_TICKET_LINK_CONTRACT' && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT')) {
377 require_once DOL_DOCUMENT_ROOT."/core/class/html.formcategory.class.php";
378
379 $formcategory = new FormCategory($db);
380
381 $htmlname = "product_category_id";
382 print '<br>';
383 print $formcategory->textwithpicto($langs->trans("TicketChooseProductCategory"), $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help');
384 if (isModEnabled('category')) {
385 print ' &nbsp; '.img_picto('', 'category', 'class="pictofixedwidth"');
386 $formcategory->selectProductCategory(getDolGlobalInt('TICKET_PRODUCT_CATEGORY'), $htmlname, 1);
387 if ($conf->use_javascript_ajax) {
388 print ajax_combobox('select_'.$htmlname);
389 }
390 print '<input class="button smallpaddingimp" type="submit" value="'.$langs->trans("Save").'">';
391 } else {
392 print 'Module category must be enabled';
393 }
394 }
395
396 print '</td>';
397
398 print '<td class="right">';
399
400 if (!empty($conf->use_javascript_ajax)) {
401 if (!empty($params['reloadpage'])) {
402 print ajax_constantonoff($key, array(), null, 0, 0, 1);
403 } else {
404 print ajax_constantonoff($key);
405 }
406 } else {
407 if (getDolGlobalString($key)) {
408 print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=del'.$key.'&token='.newToken().'">';
409 print img_picto($langs->trans("Activated"), 'switch_on');
410 print '</a>';
411 } else {
412 print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=set'.$key.'&token='.newToken().'">';
413 print img_picto($langs->trans("Disabled"), 'switch_off');
414 print '</a>';
415 }
416 }
417
418 print '</td>';
419 print '</tr>';
420}
421
422if ($tableopen) {
423 print '</table>';
424}
425
426print '</form>';
427
428
429// End of page
430llxFooter();
431$db->close();
dolibarr_set_const($db, $name, $value, $type='chaine', $visible=0, $note='', $entity=1)
Insert a parameter (key,value) into database (delete old key then insert it again).
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:476
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 forms for categories.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
GETPOSTINT($paramname, $method=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $allowothertags=array())
Show a picto called object_picto (generic function)
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_sort_array(&$array, $index, $order='asc', $natsort=0, $case_sensitive=0, $keepindex=0)
Advanced sort array by the value of a given key, which produces ascending (default) or descending out...
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.
isModEnabled($module)
Is Dolibarr module enabled.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.