dolibarr 20.0.0
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 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/admin.lib.php';
31
32// security check
33if (!$user->admin) {
35}
36
37// Load translation files required by the page
38$langs->loadLangs(array("admin", "workflow", "propal", "workflow", "orders", "supplier_proposal", "receptions", "errors", 'sendings'));
39
40$action = GETPOST('action', 'aZ09');
41
42
43/*
44 * Actions
45 */
46
47if (preg_match('/set(.*)/', $action, $reg)) {
48 if (!dolibarr_set_const($db, $reg[1], '1', 'chaine', 0, '', $conf->entity) > 0) {
49 dol_print_error($db);
50 }
51}
52
53if (preg_match('/del(.*)/', $action, $reg)) {
54 if (!dolibarr_set_const($db, $reg[1], '0', 'chaine', 0, '', $conf->entity) > 0) {
55 dol_print_error($db);
56 }
57}
58
59// List of workflow we can enable
60clearstatcache();
61
62$workflowcodes = array(
63 // Automatic creation
64 'WORKFLOW_PROPAL_AUTOCREATE_ORDER' => array(
65 'family' => 'create',
66 'position' => 10,
67 'enabled' => (isModEnabled("propal") && isModEnabled('order')),
68 'picto' => 'order'
69 ),
70 'WORKFLOW_ORDER_AUTOCREATE_INVOICE' => array(
71 'family' => 'create',
72 'position' => 20,
73 'enabled' => (isModEnabled('order') && isModEnabled('invoice')),
74 'picto' => 'bill'
75 ),
76 'WORKFLOW_TICKET_CREATE_INTERVENTION' => array(
77 'family' => 'create',
78 'position' => 25,
79 'enabled' => (isModEnabled('ticket') && isModEnabled('intervention')),
80 'picto' => 'ticket'
81 ),
82
83 'separator1' => array('family' => 'separator', 'position' => 25, 'title' => '', 'enabled' => ((isModEnabled("propal") && isModEnabled('order')) || (isModEnabled('order') && isModEnabled('invoice')) || (isModEnabled('ticket') && isModEnabled('intervention')))),
84
85 // Automatic classification of proposal
86 'WORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL' => array(
87 'family' => 'classify_proposal',
88 'position' => 30,
89 'enabled' => (isModEnabled("propal") && isModEnabled('order')),
90 'picto' => 'propal',
91 'warning' => ''
92 ),
93 'WORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL' => array(
94 'family' => 'classify_proposal',
95 'position' => 31,
96 'enabled' => (isModEnabled("propal") && isModEnabled('invoice')),
97 'picto' => 'propal',
98 'warning' => ''
99 ),
100
101 // Automatic classification of order
102 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING' => array( // when shipping validated
103 'family' => 'classify_order',
104 'position' => 40,
105 'enabled' => (isModEnabled("shipping") && isModEnabled('order')),
106 'picto' => 'order'
107 ),
108 'WORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED' => array( // when shipping closed
109 'family' => 'classify_order',
110 'position' => 41,
111 'enabled' => (isModEnabled("shipping") && isModEnabled('order')),
112 'picto' => 'order'
113 ),
114 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER' => array(
115 'family' => 'classify_order',
116 'position' => 42,
117 'enabled' => (isModEnabled('invoice') && isModEnabled('order')),
118 'picto' => 'order',
119 'warning' => ''
120 ), // For this option, if module invoice is disabled, it does not exists, so "Classify billed" for order must be done manually from order card.
121
122 'WORKFLOW_SUM_INVOICES_AMOUNT_CLASSIFY_BILLED_ORDER' => array(
123 'family' => 'classify_order',
124 'position' => 43,
125 'enabled' => (isModEnabled('invoice') && isModEnabled('order')),
126 'picto' => 'order',
127 'warning' => ''
128 ), // For this option, if module invoice is disabled, it does not exists, so "Classify billed" for order must be done manually from order card.
129
130 // Automatic classification supplier proposal
131 'WORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL' => array(
132 'family' => 'classify_supplier_proposal',
133 'position' => 60,
134 'enabled' => (isModEnabled('supplier_proposal') && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))),
135 'picto' => 'supplier_proposal',
136 'warning' => ''
137 ),
138
139 // Automatic classification supplier order
140 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION' => array(
141 'family' => 'classify_supplier_order',
142 'position' => 63,
143 'enabled' => (getDolGlobalString('MAIN_FEATURES_LEVEL') && isModEnabled("reception") && isModEnabled('supplier_order')),
144 'picto' => 'supplier_order',
145 'warning' => ''
146 ),
147
148 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED' => array(
149 'family' => 'classify_supplier_order',
150 'position' => 64,
151 'enabled' => (getDolGlobalString('MAIN_FEATURES_LEVEL') && isModEnabled("reception") && isModEnabled('supplier_order')),
152 'picto' => 'supplier_order',
153 'warning' => ''
154 ),
155
156 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER' => array(
157 'family' => 'classify_supplier_order',
158 'position' => 65,
159 'enabled' => (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")),
160 'picto' => 'supplier_order',
161 'warning' => ''
162 ),
163
164 // Automatic classification shipping
165 /* Replaced by next option
166 'WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE' => array(
167 'family' => 'classify_shipping',
168 'position' => 90,
169 'enabled' => isModEnabled("shipping") && isModEnabled("invoice"),
170 'picto' => 'shipment',
171 'deprecated' => 1
172 ),
173 */
174
175 'WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE' => array(
176 'family' => 'classify_shipping',
177 'position' => 91,
178 'enabled' => isModEnabled("shipping") && isModEnabled("invoice") && getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0',
179 'picto' => 'shipment'
180 ),
181
182 // Automatic classification reception
183 /*
184 'WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE'=>array(
185 'family'=>'classify_reception',
186 'position'=>95,
187 'enabled'=>(isModEnabled("reception") && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))),
188 'picto'=>'reception'
189 ),
190 */
191
192 'WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE' => array(
193 'family' => 'classify_reception',
194 'position' => 91,
195 'enabled' => isModEnabled("reception") && isModEnabled("supplier_invoice") && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0',
196 'picto' => 'shipment'
197 ),
198
199
200 'separator2' => array('family' => 'separator', 'position' => 400, 'enabled' => (isModEnabled('ticket') && isModEnabled('contract'))),
201
202 // Automatic link ticket -> contract
203 'WORKFLOW_TICKET_LINK_CONTRACT' => array(
204 'family' => 'link_ticket',
205 'position' => 500,
206 'enabled' => (isModEnabled('ticket') && isModEnabled('contract')),
207 'picto' => 'ticket',
208 'reloadpage' => 1 // So next option can be shown
209 ),
210 // This one depends on previous one WORKFLOW_TICKET_LINK_CONTRACT
211 'WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS' => array(
212 'family' => 'link_ticket',
213 'position' => 501,
214 'enabled' => (isModEnabled('ticket') && isModEnabled('contract') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT')),
215 'picto' => 'ticket'
216 ),
217);
218
219if (!empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) {
220 foreach ($conf->modules_parts['workflow'] as $workflow) {
221 $workflowcodes = array_merge($workflowcodes, $workflow);
222 }
223}
224
225// remove not available workflows (based on activated modules and global defined keys)
226$workflowcodes = array_filter(
227 $workflowcodes,
232 static function ($var) {
233 return (bool) $var['enabled'];
234 }
235);
236
237if ($action == 'setvarworkflow') { // Test on permission already done
238 if (GETPOSTISSET('product_category_id')) {
239 $param_ticket_product_category = GETPOSTINT('product_category_id');
240 $res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity);
241 }
242}
243
244
245/*
246 * View
247 */
248
249llxHeader('', $langs->trans("WorkflowSetup"), "EN:Module_Workflow_En|FR:Module_Workflow|ES:Módulo_Workflow", '', 0, 0, '', '', '', 'mod-admin page-workflow');
250
251$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
252print load_fiche_titre($langs->trans("WorkflowSetup"), $linkback, 'title_setup');
253
254print '<span class="opacitymedium">'.$langs->trans("WorkflowDesc").'</span>';
255print '<br>';
256print '<br>';
257
258// current module setup don't support any automatic workflow of this module
259if (count($workflowcodes) < 1) {
260 print $langs->trans("ThereIsNoWorkflowToModify");
261
262 llxFooter();
263 $db->close();
264 return;
265}
266
267// Sort on position
268$workflowcodes = dol_sort_array($workflowcodes, 'position');
269
270print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'" enctype="multipart/form-data" >';
271print '<input type="hidden" name="token" value="'.newToken().'">';
272print '<input type="hidden" name="action" value="setvarworkflow">';
273print '<input type="hidden" name="page_y" value="">';
274
275$oldfamily = '';
276$tableopen = 0;
277$atleastoneline = 0;
278
279foreach ($workflowcodes as $key => $params) {
280 if ($params['family'] == 'separator') {
281 if ($atleastoneline) {
282 print '</table>';
283 print '<br>';
284
285 $oldfamily = '';
286 $atleastoneline = 0;
287 }
288 continue;
289 }
290
291 $reg = array();
292 if ($oldfamily != $params['family']) {
293 // New group
294 if ($params['family'] == 'create') {
295 $header = $langs->trans("AutomaticCreation");
296 } elseif (preg_match('/classify_(.*)/', $params['family'], $reg)) {
297 $header = $langs->trans("AutomaticClassification");
298 if ($reg[1] == 'proposal') {
299 $header .= ' - '.$langs->trans('Proposal');
300 }
301 if ($reg[1] == 'order') {
302 $header .= ' - '.$langs->trans('Order');
303 }
304 if ($reg[1] == 'supplier_proposal') {
305 $header .= ' - '.$langs->trans('SupplierProposal');
306 }
307 if ($reg[1] == 'supplier_order') {
308 $header .= ' - '.$langs->trans('SupplierOrder');
309 }
310 if ($reg[1] == 'reception') {
311 $header .= ' - '.$langs->trans('Reception');
312 }
313 if ($reg[1] == 'shipping') {
314 $header .= ' - '.$langs->trans('Shipment');
315 }
316 } elseif (preg_match('/link_(.*)/', $params['family'], $reg)) {
317 $header = $langs->trans("AutomaticLinking");
318 if ($reg[1] == 'ticket') {
319 $header .= ' - '.$langs->trans('Ticket');
320 }
321 } else {
322 $header = $langs->trans("Description");
323 }
324
325 print '<table class="noborder centpercent">';
326 $tableopen = 1;
327
328 print '<tr class="liste_titre">';
329 print '<th>'.$header.'</th>';
330 print '<th class="right">'.$langs->trans("Status").'</th>';
331 print '</tr>';
332
333 $oldfamily = $params['family'];
334 }
335
336 $atleastoneline = 1;
337
338 print '<tr class="oddeven">';
339 print '<td>';
340 print img_object('', $params['picto'], 'class="pictofixedwidth"');
341 print ' '.$langs->trans('desc'.$key);
342
343 if (!empty($params['warning'])) {
344 print ' '.img_warning($langs->transnoentitiesnoconv($params['warning']));
345 }
346 if (!empty($params['deprecated'])) {
347 print ' '.img_warning($langs->transnoentitiesnoconv("Deprecated"));
348 }
349
350 if ($key == 'WORKFLOW_TICKET_LINK_CONTRACT' && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT')) {
351 require_once DOL_DOCUMENT_ROOT."/core/class/html.formcategory.class.php";
352
353 $formcategory = new FormCategory($db);
354
355 $htmlname = "product_category_id";
356 print '<br>';
357 print $formcategory->textwithpicto($langs->trans("TicketChooseProductCategory"), $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help');
358 if (isModEnabled('category')) {
359 print ' &nbsp; '.img_picto('', 'category', 'class="pictofixedwidth"');
360 $formcategory->selectProductCategory(getDolGlobalInt('TICKET_PRODUCT_CATEGORY'), $htmlname, 1);
361 if ($conf->use_javascript_ajax) {
362 print ajax_combobox('select_'.$htmlname);
363 }
364 print '<input class="button smallpaddingimp" type="submit" value="'.$langs->trans("Save").'">';
365 } else {
366 print 'Module category must be enabled';
367 }
368 }
369
370 print '</td>';
371
372 print '<td class="right">';
373
374 if (!empty($conf->use_javascript_ajax)) {
375 if (!empty($params['reloadpage'])) {
376 print ajax_constantonoff($key, array(), null, 0, 0, 1);
377 } else {
378 print ajax_constantonoff($key);
379 }
380 } else {
381 if (getDolGlobalString($key)) {
382 print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=del'.$key.'&token='.newToken().'">';
383 print img_picto($langs->trans("Activated"), 'switch_on');
384 print '</a>';
385 } else {
386 print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=set'.$key.'&token='.newToken().'">';
387 print img_picto($langs->trans("Disabled"), 'switch_off');
388 print '</a>';
389 }
390 }
391
392 print '</td>';
393 print '</tr>';
394}
395
396if ($tableopen) {
397 print '</table>';
398}
399
400print '</form>';
401
402
403// End of page
404llxFooter();
405$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:456
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader()
Empty header.
Definition wrapper.php:55
llxFooter()
Empty footer.
Definition wrapper.php:69
Class to manage forms for categories.
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='')
Load a title with picto.
img_object($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0)
Show a picto called object_picto (generic function)
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2)
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.
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...
newToken()
Return the value of token currently saved into session with name 'newtoken'.
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...
getDolGlobalString($key, $default='')
Return dolibarr global constant string value.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.