dolibarr 18.0.6
repair.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
3 * Copyright (C) 2004-2012 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
5 * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
6 * Copyright (C) 2021 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2023 Gauthier VERDOL <gauthier.verdol@atm-consulting.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
28include_once 'inc.php';
29if (file_exists($conffile)) {
30 include_once $conffile;
31}
32require_once $dolibarr_main_document_root.'/core/lib/admin.lib.php';
33include_once $dolibarr_main_document_root.'/core/lib/images.lib.php';
34require_once $dolibarr_main_document_root.'/core/class/extrafields.class.php';
35require_once 'lib/repair.lib.php';
36
37$step = 2;
38$ok = 0;
39
40
41// Cette page peut etre longue. On augmente le delai autorise.
42// Ne fonctionne que si on est pas en safe_mode.
43$err = error_reporting();
44error_reporting(0);
45@set_time_limit(120);
46error_reporting($err);
47
48$setuplang = GETPOST("selectlang", 'aZ09', 3) ?GETPOST("selectlang", 'aZ09', 3) : 'auto';
49$langs->setDefaultLang($setuplang);
50
51$langs->loadLangs(array("admin", "install", "other"));
52
53if ($dolibarr_main_db_type == "mysqli") {
54 $choix = 1;
55}
56if ($dolibarr_main_db_type == "pgsql") {
57 $choix = 2;
58}
59if ($dolibarr_main_db_type == "mssql") {
60 $choix = 3;
61}
62
63
64dolibarr_install_syslog("--- repair: entering upgrade.php page");
65if (!is_object($conf)) {
66 dolibarr_install_syslog("repair: conf file not initialized", LOG_ERR);
67}
68
69
70/*
71 * View
72 */
73
74pHeader('', "upgrade2", GETPOST('action', 'aZ09'));
75
76// Action to launch the repair script
77$actiondone = 1;
78
79print '<h3>'.$langs->trans("Repair").'</h3>';
80
81print 'Option standard (\'test\' or \'confirmed\') is '.(GETPOST('standard', 'alpha') ?GETPOST('standard', 'alpha') : 'undefined').'<br>'."\n";
82// Disable modules
83print 'Option force_disable_of_modules_not_found (\'test\' or \'confirmed\') is '.(GETPOST('force_disable_of_modules_not_found', 'alpha') ?GETPOST('force_disable_of_modules_not_found', 'alpha') : 'undefined').'<br>'."\n";
84// Files
85print 'Option restore_thirdparties_logos (\'test\' or \'confirmed\') is '.(GETPOST('restore_thirdparties_logos', 'alpha') ?GETPOST('restore_thirdparties_logos', 'alpha') : 'undefined').'<br>'."\n";
86print 'Option restore_user_pictures (\'test\' or \'confirmed\') is '.(GETPOST('restore_user_pictures', 'alpha') ?GETPOST('restore_user_pictures', 'alpha') : 'undefined').'<br>'."\n";
87print 'Option rebuild_product_thumbs (\'test\' or \'confirmed\') is '.(GETPOST('rebuild_product_thumbs', 'alpha') ?GETPOST('rebuild_product_thumbs', 'alpha') : 'undefined').'<br>'."\n";
88// Clean tables and data
89print 'Option clean_linked_elements (\'test\' or \'confirmed\') is '.(GETPOST('clean_linked_elements', 'alpha') ?GETPOST('clean_linked_elements', 'alpha') : 'undefined').'<br>'."\n";
90print 'Option clean_menus (\'test\' or \'confirmed\') is '.(GETPOST('clean_menus', 'alpha') ?GETPOST('clean_menus', 'alpha') : 'undefined').'<br>'."\n";
91print 'Option clean_orphelin_dir (\'test\' or \'confirmed\') is '.(GETPOST('clean_orphelin_dir', 'alpha') ?GETPOST('clean_orphelin_dir', 'alpha') : 'undefined').'<br>'."\n";
92print 'Option clean_product_stock_batch (\'test\' or \'confirmed\') is '.(GETPOST('clean_product_stock_batch', 'alpha') ?GETPOST('clean_product_stock_batch', 'alpha') : 'undefined').'<br>'."\n";
93print 'Option clean_perm_table (\'test\' or \'confirmed\') is '.(GETPOST('clean_perm_table', 'alpha') ?GETPOST('clean_perm_table', 'alpha') : 'undefined').'<br>'."\n";
94print 'Option repair_link_dispatch_lines_supplier_order_lines, (\'test\' or \'confirmed\') is '.(GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha') ?GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha') : 'undefined').'<br>'."\n";
95// Init data
96print 'Option set_empty_time_spent_amount (\'test\' or \'confirmed\') is '.(GETPOST('set_empty_time_spent_amount', 'alpha') ?GETPOST('set_empty_time_spent_amount', 'alpha') : 'undefined').'<br>'."\n";
97// Structure
98print 'Option force_utf8_on_tables (force utf8 + row=dynamic), for mysql/mariadb only (\'test\' or \'confirmed\') is '.(GETPOST('force_utf8_on_tables', 'alpha') ?GETPOST('force_utf8_on_tables', 'alpha') : 'undefined').'<br>'."\n";
99print "Option force_utf8mb4_on_tables (force utf8mb4 + row=dynamic, EXPERIMENTAL!), for mysql/mariadb only ('test' or 'confirmed') is ".(GETPOST('force_utf8mb4_on_tables', 'alpha') ? GETPOST('force_utf8mb4_on_tables', 'alpha') : 'undefined')."<br>\n";
100// Rebuild sequence
101print 'Option rebuild_sequences, for postgresql only (\'test\' or \'confirmed\') is '.(GETPOST('rebuild_sequences', 'alpha') ?GETPOST('rebuild_sequences', 'alpha') : 'undefined').'<br>'."\n";
102print '<br>';
103
104print '<table cellspacing="0" cellpadding="1" border="0" width="100%">';
105$error = 0;
106
107// If password is encoded, we decode it
108if (preg_match('/crypted:/i', $dolibarr_main_db_pass) || !empty($dolibarr_main_db_encrypted_pass)) {
109 require_once $dolibarr_main_document_root.'/core/lib/security.lib.php';
110 if (preg_match('/crypted:/i', $dolibarr_main_db_pass)) {
111 $dolibarr_main_db_pass = preg_replace('/crypted:/i', '', $dolibarr_main_db_pass);
112 $dolibarr_main_db_pass = dol_decode($dolibarr_main_db_pass);
113 $dolibarr_main_db_encrypted_pass = $dolibarr_main_db_pass; // We need to set this as it is used to know the password was initially crypted
114 } else {
115 $dolibarr_main_db_pass = dol_decode($dolibarr_main_db_encrypted_pass);
116 }
117}
118
119// $conf is already instancied inside inc.php
120$conf->db->type = $dolibarr_main_db_type;
121$conf->db->host = $dolibarr_main_db_host;
122$conf->db->port = $dolibarr_main_db_port;
123$conf->db->name = $dolibarr_main_db_name;
124$conf->db->user = $dolibarr_main_db_user;
125$conf->db->pass = $dolibarr_main_db_pass;
126
127// For encryption
128$conf->db->dolibarr_main_db_encryption = isset($dolibarr_main_db_encryption) ? $dolibarr_main_db_encryption : '';
129$conf->db->dolibarr_main_db_cryptkey = isset($dolibarr_main_db_cryptkey) ? $dolibarr_main_db_cryptkey : '';
130
131$db = getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, (int) $conf->db->port);
132
133if ($db->connected) {
134 print '<tr><td class="nowrap">';
135 print $langs->trans("ServerConnection")." : $dolibarr_main_db_host</td><td class=\"right\">".$langs->trans("OK")."</td></tr>";
136 dolibarr_install_syslog("repair: ".$langs->transnoentities("ServerConnection").": ".$dolibarr_main_db_host.$langs->transnoentities("OK"));
137 $ok = 1;
138} else {
139 print "<tr><td>".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)."</td><td class=\"right\">".$langs->transnoentities("Error")."</td></tr>";
140 dolibarr_install_syslog("repair: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
141 $ok = 0;
142}
143
144if ($ok) {
145 if ($db->database_selected) {
146 print '<tr><td class="nowrap">';
147 print $langs->trans("DatabaseConnection")." : ".$dolibarr_main_db_name."</td><td class=\"right\">".$langs->trans("OK")."</td></tr>";
148 dolibarr_install_syslog("repair: database connection successful: ".$dolibarr_main_db_name);
149 $ok = 1;
150 } else {
151 print "<tr><td>".$langs->trans("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name)."</td><td class=\"right\">".$langs->trans("Error")."</td></tr>";
152 dolibarr_install_syslog("repair: ".$langs->transnoentities("ErrorFailedToConnectToDatabase", $dolibarr_main_db_name));
153 $ok = 0;
154 }
155}
156
157// Show database version
158if ($ok) {
159 $version = $db->getVersion();
160 $versionarray = $db->getVersionArray();
161 print '<tr><td>'.$langs->trans("ServerVersion").'</td>';
162 print '<td class="right">'.$version.'</td></tr>';
163 dolibarr_install_syslog("repair: ".$langs->transnoentities("ServerVersion").": ".$version);
164 //print '<td class="right">'.join('.',$versionarray).'</td></tr>';
165}
166
167$conf->setValues($db);
168// Reset forced setup after the setValues
169if (defined('SYSLOG_FILE')) {
170 $conf->global->SYSLOG_FILE = constant('SYSLOG_FILE');
171}
172$conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
173
174
175/* Start action here */
176$oneoptionset = 0;
177$oneoptionset = (GETPOST('standard', 'alpha') || GETPOST('restore_thirdparties_logos', 'alpha') || GETPOST('clean_linked_elements', 'alpha') || GETPOST('clean_menus', 'alpha')
178 || GETPOST('clean_orphelin_dir', 'alpha') || GETPOST('clean_product_stock_batch', 'alpha') || GETPOST('set_empty_time_spent_amount', 'alpha') || GETPOST('rebuild_product_thumbs', 'alpha')
179 || GETPOST('clean_perm_table', 'alpha')
180 || GETPOST('force_disable_of_modules_not_found', 'alpha')
181 || GETPOST('force_utf8_on_tables', 'alpha') || GETPOST('force_utf8mb4_on_tables', 'alpha')
182 || GETPOST('rebuild_sequences', 'alpha'));
183
184if ($ok && $oneoptionset) {
185 // Show wait message
186 print '<tr><td colspan="2">'.$langs->trans("PleaseBePatient").'<br><br></td></tr>';
187 flush();
188}
189
190
191// run_sql: Run repair SQL file
192if ($ok && GETPOST('standard', 'alpha')) {
193 $dir = "mysql/migration/";
194
195 $filelist = array();
196 $i = 0;
197 $ok = 0;
198
199 // Recupere list fichier
200 $filesindir = array();
201 $handle = opendir($dir);
202 if (is_resource($handle)) {
203 while (($file = readdir($handle)) !== false) {
204 if (preg_match('/\.sql$/i', $file)) {
205 $filesindir[] = $file;
206 }
207 }
208 }
209 sort($filesindir);
210
211 foreach ($filesindir as $file) {
212 if (preg_match('/repair/i', $file)) {
213 $filelist[] = $file;
214 }
215 }
216
217 // Loop on each file
218 foreach ($filelist as $file) {
219 print '<tr><td class="nowrap">*** ';
220 print $langs->trans("Script").'</td><td class="right">'.$file.'</td></tr>';
221
222 $name = substr($file, 0, dol_strlen($file) - 4);
223
224 // Run sql script
225 $ok = run_sql($dir.$file, 0, '', 1);
226 }
227}
228
229
230// sync_extrafields: Search list of fields declared and list of fields created into databases, then create fields missing
231
232if ($ok && GETPOST('standard', 'alpha')) {
233 $extrafields = new ExtraFields($db);
234
235 // List of tables that has an extrafield table
236 $listofmodulesextra = array('societe'=>'societe', 'adherent'=>'adherent', 'product'=>'product',
237 'socpeople'=>'socpeople', 'propal'=>'propal', 'commande'=>'commande',
238 'facture'=>'facture', 'facturedet'=>'facturedet', 'facture_rec'=>'facture_rec', 'facturedet_rec'=>'facturedet_rec',
239 'supplier_proposal'=>'supplier_proposal', 'commande_fournisseur'=>'commande_fournisseur',
240 'facture_fourn'=>'facture_fourn', 'facture_fourn_rec'=>'facture_fourn_rec', 'facture_fourn_det'=>'facture_fourn_det', 'facture_fourn_det_rec'=>'facture_fourn_det_rec',
241 'fichinter'=>'fichinter', 'fichinterdet'=>'fichinterdet',
242 'inventory'=>'inventory',
243 'actioncomm'=>'actioncomm', 'bom_bom'=>'bom_bom', 'mrp_mo'=>'mrp_mo',
244 'adherent_type'=>'adherent_type', 'user'=>'user', 'partnership'=>'partnership', 'projet'=>'projet', 'projet_task'=>'projet_task', 'ticket'=>'ticket');
245 //$listofmodulesextra = array('fichinter'=>'fichinter');
246
247 print '<tr><td colspan="2"><br>*** Check fields into extra table structure match table of definition. If not add column into table</td></tr>';
248 foreach ($listofmodulesextra as $tablename => $elementtype) {
249 // Get list of fields
250 $tableextra = MAIN_DB_PREFIX.$tablename.'_extrafields';
251
252 // Define $arrayoffieldsdesc
253 $arrayoffieldsdesc = $extrafields->fetch_name_optionals_label($elementtype);
254
255 // Define $arrayoffieldsfound
256 $arrayoffieldsfound = array();
257 $resql = $db->DDLDescTable($tableextra);
258 if ($resql) {
259 print '<tr><td>Check availability of extra field for '.$tableextra;
260 $i = 0;
261 while ($obj = $db->fetch_object($resql)) {
262 $fieldname = $fieldtype = '';
263 if (preg_match('/mysql/', $db->type)) {
264 $fieldname = $obj->Field;
265 $fieldtype = $obj->Type;
266 } else {
267 $fieldname = isset($obj->Key) ? $obj->Key : $obj->attname;
268 $fieldtype = isset($obj->Type) ? $obj->Type : 'varchar';
269 }
270
271 if (empty($fieldname)) {
272 continue;
273 }
274 if (in_array($fieldname, array('rowid', 'tms', 'fk_object', 'import_key'))) {
275 continue;
276 }
277 $arrayoffieldsfound[$fieldname] = array('type'=>$fieldtype);
278 }
279 print ' - Found '.count($arrayoffieldsfound).' fields into table';
280 if (count($arrayoffieldsfound) > 0) {
281 print ' <span class="opacitymedium">('.join(', ', array_keys($arrayoffieldsfound)).')</span>';
282 }
283 print '<br>'."\n";
284
285 // If it does not match, we create fields
286 foreach ($arrayoffieldsdesc as $code => $label) {
287 if (!in_array($code, array_keys($arrayoffieldsfound))) {
288 print 'Found field '.$code.' declared into '.MAIN_DB_PREFIX.'extrafields table but not found into desc of table '.$tableextra." -> ";
289 $type = $extrafields->attributes[$elementtype]['type'][$code]; $length = $extrafields->attributes[$elementtype]['size'][$code]; $attribute = ''; $default = ''; $extra = ''; $null = 'null';
290
291 if ($type == 'boolean') {
292 $typedb = 'int';
293 $lengthdb = '1';
294 } elseif ($type == 'price') {
295 $typedb = 'double';
296 $lengthdb = '24,8';
297 } elseif ($type == 'phone') {
298 $typedb = 'varchar';
299 $lengthdb = '20';
300 } elseif ($type == 'mail') {
301 $typedb = 'varchar';
302 $lengthdb = '128';
303 } elseif (($type == 'select') || ($type == 'sellist') || ($type == 'radio') || ($type == 'checkbox') || ($type == 'chkbxlst')) {
304 $typedb = 'text';
305 $lengthdb = '';
306 } elseif ($type == 'link') {
307 $typedb = 'int';
308 $lengthdb = '11';
309 } else {
310 $typedb = $type;
311 $lengthdb = $length;
312 }
313
314 $field_desc = array(
315 'type'=>$typedb,
316 'value'=>$lengthdb,
317 'attribute'=>$attribute,
318 'default'=>$default,
319 'extra'=>$extra,
320 'null'=>$null
321 );
322 //var_dump($field_desc);exit;
323
324 $result = 0;
325 if (GETPOST('standard', 'alpha') == 'confirmed') {
326 $result = $db->DDLAddField($tableextra, $code, $field_desc, "");
327
328 if ($result < 0) {
329 print "KO ".$db->lasterror."<br>\n";
330 } else {
331 print "OK<br>\n";
332 }
333 } else {
334 print ' - Mode test, no column added.';
335 }
336 }
337 }
338
339 print "</td><td>&nbsp;</td></tr>\n";
340 } else {
341 print '<tr><td>Table '.$tableextra.' is not found</td><td></td></tr>'."\n";
342 }
343 }
344}
345
346
347// clean_data_ecm_dir: Clean data into ecm_directories table
348if ($ok && GETPOST('standard', 'alpha')) {
350}
351
352
353// clean declaration constants
354if ($ok && GETPOST('standard', 'alpha')) {
355 print '<tr><td colspan="2"><br>*** Clean constant record of modules not enabled</td></tr>';
356
357 $sql = "SELECT name, entity, value";
358 $sql .= " FROM ".MAIN_DB_PREFIX."const as c";
359 $sql .= " WHERE name LIKE 'MAIN_MODULE_%_TPL' OR name LIKE 'MAIN_MODULE_%_CSS' OR name LIKE 'MAIN_MODULE_%_JS' OR name LIKE 'MAIN_MODULE_%_HOOKS'";
360 $sql .= " OR name LIKE 'MAIN_MODULE_%_TRIGGERS' OR name LIKE 'MAIN_MODULE_%_THEME' OR name LIKE 'MAIN_MODULE_%_SUBSTITUTIONS' OR name LIKE 'MAIN_MODULE_%_MODELS'";
361 $sql .= " OR name LIKE 'MAIN_MODULE_%_MENUS' OR name LIKE 'MAIN_MODULE_%_LOGIN' OR name LIKE 'MAIN_MODULE_%_BARCODE' OR name LIKE 'MAIN_MODULE_%_TABS_%'";
362 $sql .= " OR name LIKE 'MAIN_MODULE_%_MODULEFOREXTERNAL'";
363 $sql .= " ORDER BY name, entity";
364
365 $resql = $db->query($sql);
366 if ($resql) {
367 $num = $db->num_rows($resql);
368
369 if ($num) {
370 $db->begin();
371
372 $i = 0;
373 while ($i < $num) {
374 $obj = $db->fetch_object($resql);
375
376 $reg = array();
377 if (preg_match('/MAIN_MODULE_([^_]+)_(.+)/i', $obj->name, $reg)) {
378 $name = $reg[1];
379 $type = $reg[2];
380
381 $sql2 = "SELECT COUNT(*) as nb";
382 $sql2 .= " FROM ".MAIN_DB_PREFIX."const as c";
383 $sql2 .= " WHERE name = 'MAIN_MODULE_".$name."'";
384 $sql2 .= " AND entity = ".((int) $obj->entity);
385 $resql2 = $db->query($sql2);
386 if ($resql2) {
387 $obj2 = $db->fetch_object($resql2);
388 if ($obj2 && $obj2->nb == 0) {
389 // Module not found, so we can remove entry
390 $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = '".$db->escape($obj->name)."' AND entity = ".((int) $obj->entity);
391
392 if (GETPOST('standard', 'alpha') == 'confirmed') {
393 $db->query($sqldelete);
394
395 print '<tr><td>Widget '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module '.$name.' not enabled in entity '.((int) $obj->entity).', we delete record</td></tr>';
396 } else {
397 print '<tr><td>Widget '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module '.$name.' not enabled in entity '.((int) $obj->entity).', we should delete record (not done, mode test)</td></tr>';
398 }
399 } else {
400 //print '<tr><td>Constant '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module found in entity '.$obj->entity.', we keep record</td></tr>';
401 }
402 }
403 }
404
405 $i++;
406 }
407
408 $db->commit();
409 }
410 } else {
411 dol_print_error($db);
412 }
413}
414
415
416// clean box of not enabled modules
417if ($ok && GETPOST('standard', 'alpha')) {
418 print '<tr><td colspan="2"><br>*** Clean definition of boxes of modules not enabled</td></tr>';
419
420 $sql = "SELECT file, entity FROM ".MAIN_DB_PREFIX."boxes_def";
421 $sql .= " WHERE file like '%@%'";
422
423 $resql = $db->query($sql);
424 if ($resql) {
425 $num = $db->num_rows($resql);
426
427 if ($num) {
428 $db->begin();
429
430 $i = 0;
431 while ($i < $num) {
432 $obj = $db->fetch_object($resql);
433
434 $reg = array();
435 if (preg_match('/^(.+)@(.+)$/i', $obj->file, $reg)) {
436 $name = $reg[1];
437 $module = $reg[2];
438
439 $sql2 = "SELECT COUNT(*) as nb";
440 $sql2 .= " FROM ".MAIN_DB_PREFIX."const as c";
441 $sql2 .= " WHERE name = 'MAIN_MODULE_".strtoupper($module)."'";
442 $sql2 .= " AND entity = ".((int) $obj->entity);
443 $sql2 .= " AND value <> 0";
444 $resql2 = $db->query($sql2);
445 if ($resql2) {
446 $obj2 = $db->fetch_object($resql2);
447 if ($obj2 && $obj2->nb == 0) {
448 // Module not found, so we canremove entry
449 $sqldeletea = "DELETE FROM ".MAIN_DB_PREFIX."boxes WHERE entity = ".((int) $obj->entity)." AND box_id IN (SELECT rowid FROM ".MAIN_DB_PREFIX."boxes_def WHERE file = '".$db->escape($obj->file)."' AND entity = ".((int) $obj->entity).")";
450 $sqldeleteb = "DELETE FROM ".MAIN_DB_PREFIX."boxes_def WHERE file = '".$db->escape($obj->file)."' AND entity = ".((int) $obj->entity);
451
452 if (GETPOST('standard', 'alpha') == 'confirmed') {
453 $db->query($sqldeletea);
454 $db->query($sqldeleteb);
455
456 print '<tr><td>Constant '.$obj->file.' set in boxes_def for entity '.$obj->entity.' but MAIN_MODULE_'.strtoupper($module).' not defined in entity '.((int) $obj->entity).', we delete record</td></tr>';
457 } else {
458 print '<tr><td>Constant '.$obj->file.' set in boxes_def for entity '.$obj->entity.' but MAIN_MODULE_'.strtoupper($module).' not defined in entity '.((int) $obj->entity).', we should delete record (not done, mode test)</td></tr>';
459 }
460 } else {
461 //print '<tr><td>Constant '.$obj->name.' set in entity '.$obj->entity.' with value '.$obj->value.' -> Module found in entity '.$obj->entity.', we keep record</td></tr>';
462 }
463 }
464 }
465
466 $i++;
467 }
468
469 $db->commit();
470 }
471 }
472}
473
474
475// restore_thirdparties_logos: Move logos to correct new directory.
476if ($ok && GETPOST('restore_thirdparties_logos')) {
477 //$exts=array('gif','png','jpg');
478
479 $ext = '';
480
481 print '<tr><td colspan="2"><br>*** Restore thirdparties logo<br>';
482
483 $sql = "SELECT s.rowid, s.nom as name, s.logo FROM ".MAIN_DB_PREFIX."societe as s ORDER BY s.nom";
484 $resql = $db->query($sql);
485 if ($resql) {
486 $num = $db->num_rows($resql);
487 $i = 0;
488
489 while ($i < $num) {
490 $obj = $db->fetch_object($resql);
491
492 /*
493 $name=preg_replace('/é/','',$obj->name);
494 $name=preg_replace('/ /','_',$name);
495 $name=preg_replace('/\'/','',$name);
496 */
497
498 $tmp = explode('.', $obj->logo);
499 $name = $tmp[0];
500 if (isset($tmp[1])) {
501 $ext = '.'.$tmp[1];
502 }
503
504 if (!empty($name)) {
505 $filetotest = $dolibarr_main_data_root.'/societe/logos/'.$name.$ext;
506 $filetotestsmall = $dolibarr_main_data_root.'/societe/logos/thumbs/'.$name.'_small'.$ext;
507 $exists = dol_is_file($filetotest);
508 print 'Check thirdparty '.$obj->rowid.' name='.$obj->name.' logo='.$obj->logo.' file '.$filetotest." exists=".$exists."<br>\n";
509 if ($exists) {
510 $filetarget = $dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/'.$name.$ext;
511 $filetargetsmall = $dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/thumbs/'.$name.'_small'.$ext;
512 $existt = dol_is_file($filetarget);
513 if (!$existt) {
514 if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
515 dol_mkdir($dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos');
516 }
517
518 print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotest." -> ".$filetarget."<br>\n";
519 if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
520 dol_copy($filetotest, $filetarget, '', 0);
521 }
522 }
523
524 $existtt = dol_is_file($filetargetsmall);
525 if (!$existtt) {
526 if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
527 dol_mkdir($dolibarr_main_data_root.'/societe/'.$obj->rowid.'/logos/thumbs');
528 }
529 print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestsmall." -> ".$filetargetsmall."<br>\n";
530 if (GETPOST('restore_thirdparties_logos', 'alpha') == 'confirmed') {
531 dol_copy($filetotestsmall, $filetargetsmall, '', 0);
532 }
533 }
534 }
535 }
536
537 $i++;
538 }
539 } else {
540 $ok = 0;
541 dol_print_error($db);
542 }
543
544 print '</td></tr>';
545}
546
547
548
549// restore_user_pictures: Move pictures to correct new directory.
550if ($ok && GETPOST('restore_user_pictures', 'alpha')) {
551 //$exts=array('gif','png','jpg');
552
553 $ext = '';
554
555 print '<tr><td colspan="2"><br>*** Restore user pictures<br>';
556
557 $sql = "SELECT s.rowid, s.firstname, s.lastname, s.login, s.photo FROM ".MAIN_DB_PREFIX."user as s ORDER BY s.rowid";
558 $resql = $db->query($sql);
559 if ($resql) {
560 $num = $db->num_rows($resql);
561 $i = 0;
562
563 while ($i < $num) {
564 $obj = $db->fetch_object($resql);
565
566 /*
567 $name=preg_replace('/é/','',$obj->name);
568 $name=preg_replace('/ /','_',$name);
569 $name=preg_replace('/\'/','',$name);
570 */
571
572 $tmp = explode('.', $obj->photo);
573 $name = $tmp[0];
574 if (isset($tmp[1])) {
575 $ext = '.'.$tmp[1];
576 }
577
578 if (!empty($name)) {
579 $filetotest = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/'.$name.$ext;
580 $filetotestsmall = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_small'.$ext;
581 $filetotestmini = $dolibarr_main_data_root.'/users/'.substr(sprintf('%08d', $obj->rowid), -1, 1).'/'.substr(sprintf('%08d', $obj->rowid), -2, 1).'/thumbs/'.$name.'_mini'.$ext;
582 $exists = dol_is_file($filetotest);
583 print 'Check user '.$obj->rowid.' lastname='.$obj->lastname.' firstname='.$obj->firstname.' photo='.$obj->photo.' file '.$filetotest." exists=".$exists."<br>\n";
584 if ($exists) {
585 $filetarget = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/'.$name.$ext;
586 $filetargetsmall = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs/'.$name.'_small'.$ext;
587 $filetargetmini = $dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs/'.$name.'_mini'.$ext;
588
589 $existt = dol_is_file($filetarget);
590 if (!$existt) {
591 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
592 dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid);
593 }
594
595 print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotest." -> ".$filetarget."<br>\n";
596 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
597 dol_copy($filetotest, $filetarget, '', 0);
598 }
599 }
600
601 $existtt = dol_is_file($filetargetsmall);
602 if (!$existtt) {
603 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
604 dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs');
605 }
606
607 print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestsmall." -> ".$filetargetsmall."<br>\n";
608 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
609 dol_copy($filetotestsmall, $filetargetsmall, '', 0);
610 }
611 }
612
613 $existtt = dol_is_file($filetargetmini);
614 if (!$existtt) {
615 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
616 dol_mkdir($dolibarr_main_data_root.'/users/'.$obj->rowid.'/thumbs');
617 }
618
619 print " &nbsp; &nbsp; &nbsp; -> Copy file ".$filetotestmini." -> ".$filetargetmini."<br>\n";
620 if (GETPOST('restore_user_pictures', 'alpha') == 'confirmed') {
621 dol_copy($filetotestmini, $filetargetmini, '', 0);
622 }
623 }
624 }
625 }
626
627 $i++;
628 }
629 } else {
630 $ok = 0;
631 dol_print_error($db);
632 }
633
634 print '</td></tr>';
635}
636
637
638// rebuild_product_thumbs: Rebuild thumbs for product files
639if ($ok && GETPOST('rebuild_product_thumbs', 'alpha')) {
640 $ext = '';
641 global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
642
643 print '<tr><td colspan="2"><br>*** Rebuild product thumbs<br>';
644
645 $sql = "SELECT s.rowid, s.ref FROM ".MAIN_DB_PREFIX."product as s ORDER BY s.ref";
646 $resql = $db->query($sql);
647 if ($resql) {
648 $num = $db->num_rows($resql);
649 $i = 0;
650
651 while ($i < $num) {
652 $obj = $db->fetch_object($resql);
653
654 if (!empty($obj->ref)) {
655 $files = dol_dir_list($dolibarr_main_data_root.'/produit/'.$obj->ref, 'files', 0);
656 foreach ($files as $file) {
657 // Generate thumbs.
658 if (image_format_supported($file['fullname']) == 1) {
659 $imgThumbSmall = 'notbuild';
660 if (GETPOST('rebuild_product_thumbs', 'alpha') == 'confirmed') {
661 // Used on logon for example
662 $imgThumbSmall = vignette($file['fullname'], $maxwidthsmall, $maxheightsmall, '_small', 50, "thumbs");
663 }
664 print 'Check product '.$obj->rowid.", file ".$file['fullname']." -> ".$imgThumbSmall." maxwidthsmall=".$maxwidthsmall." maxheightsmall=".$maxheightsmall."<br>\n";
665 $imgThumbMini = 'notbuild';
666 if (GETPOST('rebuild_product_thumbs', 'alpha') == 'confirmed') {
667 // Create mini thumbs for image (Ratio is near 16/9)
668 // Used on menu or for setup page for example
669 $imgThumbMini = vignette($file['fullname'], $maxwidthmini, $maxheightmini, '_mini', 50, "thumbs");
670 }
671 print 'Check product '.$obj->rowid.", file ".$file['fullname']." -> ".$imgThumbMini." maxwidthmini=".$maxwidthmini." maxheightmini=".$maxheightmini."<br>\n";
672 }
673 }
674 }
675
676 $i++;
677 }
678 } else {
679 $ok = 0;
680 dol_print_error($db);
681 }
682
683 print '</td></tr>';
684}
685
686// clean_linked_elements: Check and clean linked elements
687if ($ok && GETPOST('clean_linked_elements', 'alpha')) {
688 print '<tr><td colspan="2"><br>*** Check table of linked elements and delete orphelins links</td></tr>';
689 // propal => order
690 print '<tr><td colspan="2">'.checkLinkedElements('propal', 'commande')."</td></tr>\n";
691
692 // propal => invoice
693 print '<tr><td colspan="2">'.checkLinkedElements('propal', 'facture')."</td></tr>\n";
694
695 // order => invoice
696 print '<tr><td colspan="2">'.checkLinkedElements('commande', 'facture')."</td></tr>\n";
697
698 // order => shipping
699 print '<tr><td colspan="2">'.checkLinkedElements('commande', 'shipping')."</td></tr>\n";
700
701 // shipping => delivery
702 print '<tr><td colspan="2">'.checkLinkedElements('shipping', 'delivery')."</td></tr>\n";
703
704 // order_supplier => invoice_supplier
705 print '<tr><td colspan="2">'.checkLinkedElements('order_supplier', 'invoice_supplier')."</td></tr>\n";
706}
707
708
709// clean_menus: Check orphelins menus
710if ($ok && GETPOST('clean_menus', 'alpha')) {
711 print '<tr><td colspan="2"><br>*** Clean menu entries coming from disabled modules</td></tr>';
712
713 $sql = "SELECT rowid, module";
714 $sql .= " FROM ".MAIN_DB_PREFIX."menu as c";
715 $sql .= " WHERE module IS NOT NULL AND module <> ''";
716 $sql .= " ORDER BY module";
717
718 $resql = $db->query($sql);
719 if ($resql) {
720 $num = $db->num_rows($resql);
721 if ($num) {
722 $i = 0;
723 while ($i < $num) {
724 $obj = $db->fetch_object($resql);
725
726 $modulecond = $obj->module;
727 $modulecondarray = explode('|', $obj->module); // Name of module
728
729 print '<tr><td>';
730 print $modulecond;
731
732 $db->begin();
733
734 if ($modulecond) { // And menu entry for module $modulecond was found in database.
735 $moduleok = 0;
736 foreach ($modulecondarray as $tmpname) {
737 if ($tmpname == 'margins') {
738 $tmpname = 'margin'; // TODO Remove this when normalized
739 }
740
741 $result = 0;
742 if (!empty($conf->$tmpname)) {
743 $result = $conf->$tmpname->enabled;
744 }
745 if ($result) {
746 $moduleok++;
747 }
748 }
749
750 if (!$moduleok && $modulecond) {
751 print ' - Module condition '.$modulecond.' seems ko, we delete menu entry.';
752 if (GETPOST('clean_menus') == 'confirmed') {
753 $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."menu WHERE module = '".$db->escape($modulecond)."'";
754 $resql2 = $db->query($sql2);
755 if (!$resql2) {
756 $error++;
757 dol_print_error($db);
758 } else {
759 print ' - <span class="warning">Cleaned</span>';
760 }
761 } else {
762 print ' - <span class="warning">Canceled (test mode)</span>';
763 }
764 } else {
765 print ' - Module condition '.$modulecond.' is ok, we do nothing.';
766 }
767 }
768
769 if (!$error) {
770 $db->commit();
771 } else {
772 $db->rollback();
773 }
774
775 print'</td></tr>';
776
777 if ($error) {
778 break;
779 }
780
781 $i++;
782 }
783 } else {
784 print '<tr><td>No menu entries of disabled menus found</td></tr>';
785 }
786 } else {
787 dol_print_error($db);
788 }
789}
790
791
792
793// clean_orphelin_dir: Run purge of directory
794if ($ok && GETPOST('clean_orphelin_dir', 'alpha')) {
795 $listmodulepart = array('company', 'invoice', 'invoice_supplier', 'propal', 'order', 'order_supplier', 'contract', 'tax');
796 foreach ($listmodulepart as $modulepart) {
797 $filearray = array();
798 $upload_dir = isset($conf->$modulepart->dir_output) ? $conf->$modulepart->dir_output : '';
799 if ($modulepart == 'company') {
800 $upload_dir = $conf->societe->dir_output; // TODO change for multicompany sharing
801 }
802 if ($modulepart == 'invoice') {
803 $upload_dir = $conf->facture->dir_output;
804 }
805 if ($modulepart == 'invoice_supplier') {
806 $upload_dir = $conf->fournisseur->facture->dir_output;
807 }
808 if ($modulepart == 'order') {
809 $upload_dir = $conf->commande->dir_output;
810 }
811 if ($modulepart == 'order_supplier') {
812 $upload_dir = $conf->fournisseur->commande->dir_output;
813 }
814 if ($modulepart == 'contract') {
815 $upload_dir = $conf->contrat->dir_output;
816 }
817
818 if (empty($upload_dir)) {
819 continue;
820 }
821
822 print '<tr><td colspan="2"><br>*** Clean orphelins files into files '.$upload_dir.'</td></tr>';
823
824 $filearray = dol_dir_list($upload_dir, "files", 1, '', array('^SPECIMEN\.pdf$', '^\.', '(\.meta|_preview.*\.png)$', '^temp$', '^payments$', '^CVS$', '^thumbs$'), '', SORT_DESC, 1, true);
825
826 // To show ref or specific information according to view to show (defined by $module)
827 if ($modulepart == 'company') {
828 include_once DOL_DOCUMENT_ROOT.'/societe/class/societe.class.php';
829 $object_instance = new Societe($db);
830 }
831 if ($modulepart == 'invoice') {
832 include_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
833 $object_instance = new Facture($db);
834 } elseif ($modulepart == 'invoice_supplier') {
835 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.facture.class.php';
836 $object_instance = new FactureFournisseur($db);
837 } elseif ($modulepart == 'propal') {
838 include_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
839 $object_instance = new Propal($db);
840 } elseif ($modulepart == 'order') {
841 include_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
842 $object_instance = new Commande($db);
843 } elseif ($modulepart == 'order_supplier') {
844 include_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
845 $object_instance = new CommandeFournisseur($db);
846 } elseif ($modulepart == 'contract') {
847 include_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
848 $object_instance = new Contrat($db);
849 } elseif ($modulepart == 'tax') {
850 include_once DOL_DOCUMENT_ROOT.'/compta/sociales/class/chargesociales.class.php';
851 $object_instance = new ChargeSociales($db);
852 }
853
854 foreach ($filearray as $key => $file) {
855 if (!is_dir($file['name'])
856 && $file['name'] != '.'
857 && $file['name'] != '..'
858 && $file['name'] != 'CVS'
859 ) {
860 // Define relative path used to store the file
861 $relativefile = preg_replace('/'.preg_quote($upload_dir.'/', '/').'/', '', $file['fullname']);
862
863 //var_dump($file);
864 $id = 0; $ref = ''; $object_instance->id = 0; $object_instance->ref = ''; $label = '';
865
866 // To show ref or specific information according to view to show (defined by $module)
867 if ($modulepart == 'invoice') {
868 preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
869 }
870 if ($modulepart == 'invoice_supplier') {
871 preg_match('/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = empty($reg[1]) ? '' : $reg[1];
872 }
873 if ($modulepart == 'propal') {
874 preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
875 }
876 if ($modulepart == 'order') {
877 preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
878 }
879 if ($modulepart == 'order_supplier') {
880 preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
881 }
882 if ($modulepart == 'contract') {
883 preg_match('/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
884 }
885 if ($modulepart == 'tax') {
886 preg_match('/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = $reg[1];
887 }
888
889 if ($id || $ref) {
890 //print 'Fetch '.$id.' or '.$ref.'<br>';
891 $result = $object_instance->fetch($id, $ref);
892 //print $result.'<br>';
893 if ($result == 0) { // Not found but no error
894 // Clean of orphelins directories are done into repair.php
895 print '<tr><td colspan="2">';
896 print 'Delete orphelins file '.$file['fullname'].'<br>';
897 if (GETPOST('clean_orphelin_dir', 'alpha') == 'confirmed') {
898 dol_delete_file($file['fullname'], 1, 1, 1);
899 dol_delete_dir(dirname($file['fullname']), 1);
900 }
901 print "</td></tr>";
902 } elseif ($result < 0) {
903 print 'Error in '.get_class($object_instance).'.fetch of id'.$id.' ref='.$ref.', result='.$result.'<br>';
904 }
905 }
906 }
907 }
908 }
909}
910
911// clean_linked_elements: Check and clean linked elements
912if ($ok && GETPOST('clean_product_stock_batch', 'alpha')) {
913 $methodtofix = GETPOST('methodtofix', 'alpha') ?GETPOST('methodtofix', 'alpha') : 'updatestock';
914
915 print '<tr><td colspan="2"><br>*** Clean table product_batch, methodtofix='.$methodtofix.' (possible values: updatestock or updatebatch)</td></tr>';
916
917 $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
918 $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps LEFT JOIN ".MAIN_DB_PREFIX."product_batch as pb ON ps.rowid = pb.fk_product_stock";
919 $sql .= " WHERE p.rowid = ps.fk_product";
920 $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
921 $sql .= " HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
922 print $sql;
923 $resql = $db->query($sql);
924 if ($resql) {
925 $num = $db->num_rows($resql);
926
927 if ($num) {
928 $i = 0;
929 while ($i < $num) {
930 $obj = $db->fetch_object($resql);
931 print '<tr><td>Product '.$obj->rowid.'-'.$obj->ref.' in warehouse id='.$obj->fk_entrepot.' (product_stock.id='.$obj->psrowid.'): '.$obj->reel.' (Stock product_stock.reel) != '.($obj->reelbatch ? $obj->reelbatch : '0').' (Stock batch sum product_batch)';
932
933 // Fix is required
934 if ($obj->reel != $obj->reelbatch) {
935 if (empty($obj->tobatch)) {
936 // If product is not a product that support batches, we can clean stock by deleting the product batch lines
937 print ' -> Delete qty '.$obj->reelbatch.' for any lot linked to fk_product_stock='.$obj->psrowid;
938 $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."product_batch";
939 $sql2 .= " WHERE fk_product_stock = ".((int) $obj->psrowid);
940 print '<br>'.$sql2;
941
942 if (GETPOST('clean_product_stock_batch') == 'confirmed') {
943 $resql2 = $db->query($sql2);
944 if (!$resql2) {
945 $error++;
946 dol_print_error($db);
947 }
948 }
949 } else {
950 if ($methodtofix == 'updatebatch') {
951 // Method 1
952 print ' -> Insert qty '.($obj->reel - $obj->reelbatch).' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
953 $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."product_batch(fk_product_stock, batch, qty)";
954 $sql2 .= "VALUES(".((int) $obj->psrowid).", '000000', ".((float) ($obj->reel - $obj->reelbatch)).")";
955 print '<br>'.$sql2;
956
957 if (GETPOST('clean_product_stock_batch') == 'confirmed') {
958 $resql2 = $db->query($sql2);
959 if (!$resql2) {
960 // TODO If it fails, we must make update
961 //$sql2 ="UPDATE ".MAIN_DB_PREFIX."product_batch";
962 //$sql2.=" SET ".$obj->psrowid.", '000000', ".($obj->reel - $obj->reelbatch).")";
963 //$sql2.=" WHERE fk_product_stock = ".((int) $obj->psrowid)
964 }
965 }
966 }
967 if ($methodtofix == 'updatestock') {
968 // Method 2
969 print ' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((float) $obj->reelbatch) : '0').' for ps.rowid = '.((int) $obj->psrowid);
970 $sql2 = "UPDATE ".MAIN_DB_PREFIX."product_stock";
971 $sql2 .= " SET reel = ".($obj->reelbatch ? ((float) $obj->reelbatch) : '0')." WHERE rowid = ".((int) $obj->psrowid);
972 print '<br>'.$sql2;
973
974 if (GETPOST('clean_product_stock_batch') == 'confirmed') {
975 $error = 0;
976
977 $db->begin();
978
979 $resql2 = $db->query($sql2);
980 if ($resql2) {
981 // We update product_stock, so we must fill p.stock into product too.
982 $sql3 = 'UPDATE '.MAIN_DB_PREFIX.'product p SET p.stock= (SELECT SUM(ps.reel) FROM '.MAIN_DB_PREFIX.'product_stock ps WHERE ps.fk_product = p.rowid)';
983 $resql3 = $db->query($sql3);
984 if (!$resql3) {
985 $error++;
986 dol_print_error($db);
987 }
988 } else {
989 $error++;
990 dol_print_error($db);
991 }
992
993 if (!$error) {
994 $db->commit();
995 } else {
996 $db->rollback();
997 }
998 }
999 }
1000 }
1001 }
1002
1003 print'</td></tr>';
1004
1005 $i++;
1006 }
1007 } else {
1008 print '<tr><td colspan="2">Nothing to do</td></tr>';
1009 }
1010 } else {
1011 dol_print_error($db);
1012 }
1013}
1014
1015
1016// clean_product_stock_negative_if_batch
1017if ($ok && GETPOST('clean_product_stock_negative_if_batch', 'alpha')) {
1018 print '<tr><td colspan="2"><br>Clean table product_batch, methodtofix='.$methodtofix.' (possible values: updatestock or updatebatch)</td></tr>';
1019
1020 $sql = "SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
1021 $sql .= " FROM ".MAIN_DB_PREFIX."product as p, ".MAIN_DB_PREFIX."product_stock as ps, ".MAIN_DB_PREFIX."product_batch as pb";
1022 $sql .= " WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock";
1023 $sql .= " AND p.tobatch > 0";
1024 $sql .= " GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
1025 $sql .= " HAVING reel != SUM(pb.qty)";
1026 $resql = $db->query($sql);
1027 if ($resql) {
1028 $num = $db->num_rows($resql);
1029
1030 if ($num) {
1031 $i = 0;
1032 while ($i < $num) {
1033 $obj = $db->fetch_object($resql);
1034 print '<tr><td>'.$obj->rowid.'-'.$obj->ref.'-'.$obj->fk_entrepot.' -> '.$obj->psrowid.': '.$obj->reel.' != '.$obj->reelbatch;
1035
1036 // TODO
1037 }
1038 }
1039 }
1040}
1041
1042// set_empty_time_spent_amount
1043if ($ok && GETPOST('set_empty_time_spent_amount', 'alpha')) {
1044 print '<tr><td colspan="2"><br>*** Set value of time spent without amount</td></tr>';
1045
1046 $sql = "SELECT COUNT(ptt.rowid) as nb, u.rowid as user_id, u.login, u.thm as user_thm";
1047 $sql .= " FROM ".MAIN_DB_PREFIX."element_time as ptt, ".MAIN_DB_PREFIX."user as u";
1048 $sql .= " WHERE ptt.fk_user = u.rowid";
1049 $sql .= " AND ptt.thm IS NULL and u.thm > 0";
1050 $sql .= " GROUP BY u.rowid, u.login, u.thm";
1051
1052 $resql = $db->query($sql);
1053 if ($resql) {
1054 $num = $db->num_rows($resql);
1055
1056 if ($num) {
1057 $i = 0;
1058 while ($i < $num) {
1059 $obj = $db->fetch_object($resql);
1060 print '<tr><td>'.$obj->login.'-'.$obj->user_id.' ('.$obj->nb.' lines to fix) -> '.$obj->user_thm;
1061
1062 $db->begin();
1063
1064 if (GETPOST('set_empty_time_spent_amount') == 'confirmed') {
1065 $sql2 = "UPDATE ".MAIN_DB_PREFIX."element_time";
1066 $sql2 .= " SET thm = ".$obj->user_thm." WHERE thm IS NULL AND fk_user = ".((int) $obj->user_id);
1067 $resql2 = $db->query($sql2);
1068 if (!$resql2) {
1069 $error++;
1070 dol_print_error($db);
1071 }
1072 }
1073
1074 if (!$error) {
1075 $db->commit();
1076 } else {
1077 $db->rollback();
1078 }
1079
1080 print'</td></tr>';
1081
1082 if ($error) {
1083 break;
1084 }
1085
1086 $i++;
1087 }
1088 } else {
1089 print '<tr><td>No time spent with empty line on users with a hourly rate defined</td></tr>';
1090 }
1091 } else {
1092 dol_print_error($db);
1093 }
1094}
1095
1096
1097// force_disable_of_modules_not_found
1098if ($ok && GETPOST('force_disable_of_modules_not_found', 'alpha')) {
1099 print '<tr><td colspan="2"><br>*** Force modules not found physicaly to be disabled (only modules adding js, css or hooks can be detected as removed physicaly)</td></tr>';
1100
1101 $arraylistofkey = array('hooks', 'js', 'css');
1102
1103 foreach ($arraylistofkey as $key) {
1104 $sql = "SELECT DISTINCT name, value";
1105 $sql .= " FROM ".MAIN_DB_PREFIX."const as c";
1106 $sql .= " WHERE name LIKE 'MAIN_MODULE_%_".strtoupper($key)."'";
1107 $sql .= " ORDER BY name";
1108
1109 $resql = $db->query($sql);
1110 if ($resql) {
1111 $num = $db->num_rows($resql);
1112 if ($num) {
1113 $i = 0;
1114 while ($i < $num) {
1115 $obj = $db->fetch_object($resql);
1116 $constantname = $obj->name; // Name of constant for hook or js or css declaration
1117
1118 print '<tr><td>';
1119 print dol_escape_htmltag($constantname);
1120
1121 $db->begin();
1122
1123 $reg = array();
1124 if (preg_match('/MAIN_MODULE_(.*)_'.strtoupper($key).'/i', $constantname, $reg)) {
1125 $name = strtolower($reg[1]);
1126
1127 if ($name) { // An entry for key $key and module $name was found in database.
1128 $reloffile = '';
1129 $result = 'found';
1130
1131 if ($key == 'hooks') {
1132 $reloffile = $name.'/class/actions_'.$name.'.class.php';
1133 }
1134 if ($key == 'js') {
1135 $value = $obj->value;
1136 $valuearray = (array) json_decode($value); // Force cast into array because sometimes it is a stdClass
1137 $reloffile = $valuearray[0];
1138 $reloffile = preg_replace('/^\//', '', $valuearray[0]);
1139 }
1140 if ($key == 'css') {
1141 $value = $obj->value;
1142 $valuearray = (array) json_decode($value); // Force cast into array because sometimes it is a stdClass
1143 if ($value && (!is_array($valuearray) || count($valuearray) == 0)) {
1144 $valuearray = array();
1145 $valuearray[0] = $value; // If value was not a json array but a string
1146 }
1147 $reloffile = preg_replace('/^\//', '', $valuearray[0]);
1148 }
1149
1150 if ($reloffile) {
1151 //var_dump($key.' - '.$value.' - '.$reloffile);
1152 try {
1153 $result = dol_buildpath($reloffile, 0, 2);
1154 } catch (Exception $e) {
1155 $result = 'found'; // If error, we force like if we found to avoid any deletion
1156 }
1157 } else {
1158 $result = 'found'; //
1159 }
1160
1161 if (!$result) {
1162 print ' - File of '.$key.' ('.$reloffile.') NOT found, we disable the module.';
1163 if (GETPOST('force_disable_of_modules_not_found') == 'confirmed') {
1164 $sql2 = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = 'MAIN_MODULE_".strtoupper($name)."_".strtoupper($key)."'";
1165 $resql2 = $db->query($sql2);
1166 if (!$resql2) {
1167 $error++;
1168 dol_print_error($db);
1169 }
1170 $sql3 = "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = 'MAIN_MODULE_".strtoupper($name)."'";
1171 $resql3 = $db->query($sql3);
1172 if (!$resql3) {
1173 $error++;
1174 dol_print_error($db);
1175 } else {
1176 print ' - <span class="warning">Cleaned</span>';
1177 }
1178 } else {
1179 print ' - <span class="warning">Canceled (test mode)</span>';
1180 }
1181 } else {
1182 print ' - File of '.$key.' ('.$reloffile.') found, we do nothing.';
1183 }
1184 }
1185
1186 if (!$error) {
1187 $db->commit();
1188 } else {
1189 $db->rollback();
1190 }
1191 }
1192
1193 print'</td></tr>';
1194
1195 if ($error) {
1196 break;
1197 }
1198
1199 $i++;
1200 }
1201 } else {
1202 print '<tr><td>No active module with missing files found by searching on MAIN_MODULE_(.*)_'.strtoupper($key).'</td></tr>';
1203 }
1204 } else {
1205 dol_print_error($db);
1206 }
1207 }
1208}
1209
1210
1211// clean_old_module_entries: Clean data into const when files of module were removed without being
1212if ($ok && GETPOST('clean_perm_table', 'alpha')) {
1213 print '<tr><td colspan="2"><br>*** Clean table user_rights from lines of external modules no more enabled</td></tr>';
1214
1215 $listofmods = '';
1216 foreach ($conf->modules as $key => $val) {
1217 $listofmods .= ($listofmods ? ',' : '')."'".$db->escape($val)."'";
1218 }
1219
1220 $sql = "SELECT id, libelle as label, module from ".MAIN_DB_PREFIX."rights_def WHERE module NOT IN (".$db->sanitize($listofmods, 1).") AND id > 100000";
1221
1222 $resql = $db->query($sql);
1223 if ($resql) {
1224 $num = $db->num_rows($resql);
1225 if ($num) {
1226 $i = 0;
1227 while ($i < $num) {
1228 $obj = $db->fetch_object($resql);
1229 if ($obj->id > 0) {
1230 print '<tr><td>Found line with id '.$obj->id.', label "'.$obj->label.'" of module "'.$obj->module.'" to delete';
1231 if (GETPOST('clean_perm_table', 'alpha') == 'confirmed') {
1232 $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."rights_def WHERE id = ".((int) $obj->id);
1233 $resqldelete = $db->query($sqldelete);
1234 if (!$resqldelete) {
1235 dol_print_error($db);
1236 }
1237 print ' - deleted';
1238 }
1239 print '</td></tr>';
1240 }
1241 $i++;
1242 }
1243 } else {
1244 print '<tr><td>No lines of a disabled external module (with id > 100000) found into table rights_def</td></tr>';
1245 }
1246 } else {
1247 dol_print_error($db);
1248 }
1249}
1250
1251
1252
1253// force utf8 on tables
1254if ($ok && GETPOST('force_utf8_on_tables', 'alpha')) {
1255 print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8/utf8_unicode_ci and row_format=dynamic (for mysql/mariadb only)</td></tr>';
1256
1257 if ($db->type == "mysql" || $db->type == "mysqli") {
1258 $force_utf8_on_tables = GETPOST('force_utf8_on_tables', 'alpha');
1259
1260 $listoftables = $db->DDLListTablesFull($db->database_name);
1261
1262 // Disable foreign key checking for avoid errors
1263 if ($force_utf8_on_tables == 'confirmed') {
1264 $sql = 'SET FOREIGN_KEY_CHECKS=0';
1265 print '<!-- '.$sql.' -->';
1266 $resql = $db->query($sql);
1267 }
1268
1269 foreach ($listoftables as $table) {
1270 // do not convert llx_const if mysql encrypt/decrypt is used
1271 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match('/\_const$/', $table[0])) {
1272 continue;
1273 }
1274 if ($table[1] == 'VIEW') {
1275 print '<tr><td colspan="2">'.$table[0].' is a '.$table[1].' (Skipped)</td></tr>';
1276 continue;
1277 }
1278
1279 print '<tr><td colspan="2">';
1280 print $table[0];
1281 $sql1 = "ALTER TABLE ".$table[0]." ROW_FORMAT=dynamic";
1282 $sql2 = "ALTER TABLE ".$table[0]." CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci";
1283 print '<!-- '.$sql1.' -->';
1284 print '<!-- '.$sql2.' -->';
1285 if ($force_utf8_on_tables == 'confirmed') {
1286 $resql1 = $db->query($sql1);
1287 if ($resql1) {
1288 $resql2 = $db->query($sql2);
1289 } else {
1290 $resql2 = false;
1291 }
1292 print ' - Done ('.(($resql1 && $resql2) ? 'OK' : 'KO').')';
1293 } else {
1294 print ' - Disabled';
1295 }
1296 print '</td></tr>';
1297 }
1298
1299 // Enable foreign key checking
1300 if ($force_utf8_on_tables == 'confirmed') {
1301 $sql = 'SET FOREIGN_KEY_CHECKS=1';
1302 print '<!-- '.$sql.' -->';
1303 $resql = $db->query($sql);
1304 }
1305 } else {
1306 print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1307 }
1308}
1309
1310// force utf8mb4 on tables EXPERIMENTAL !
1311if ($ok && GETPOST('force_utf8mb4_on_tables', 'alpha')) {
1312 print '<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8mb4/utf8mb4_unicode_ci (for mysql/mariadb only)</td></tr>';
1313
1314 if ($db->type == "mysql" || $db->type == "mysqli") {
1315 $force_utf8mb4_on_tables = GETPOST('force_utf8mb4_on_tables', 'alpha');
1316
1317 $listoftables = $db->DDLListTablesFull($db->database_name);
1318
1319 // Disable foreign key checking for avoid errors
1320 if ($force_utf8mb4_on_tables == 'confirmed') {
1321 $sql = 'SET FOREIGN_KEY_CHECKS=0';
1322 print '<!-- '.$sql.' -->';
1323 $resql = $db->query($sql);
1324 }
1325
1326 foreach ($listoftables as $table) {
1327 // do not convert llx_const if mysql encrypt/decrypt is used
1328 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match('/\_const$/', $table[0])) {
1329 continue;
1330 }
1331 if ($table[1] == 'VIEW') {
1332 print '<tr><td colspan="2">'.$table[0].' is a '.$table[1].' (Skipped)</td></tr>';
1333 continue;
1334 }
1335
1336 print '<tr><td colspan="2">';
1337 print $table[0];
1338 $sql1 = "ALTER TABLE ".$table[0]." ROW_FORMAT=dynamic";
1339 $sql2 = "ALTER TABLE ".$table[0]." CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
1340 print '<!-- '.$sql1.' -->';
1341 print '<!-- '.$sql2.' -->';
1342 if ($force_utf8mb4_on_tables == 'confirmed') {
1343 $resql1 = $db->query($sql1);
1344 if ($resql1) {
1345 $resql2 = $db->query($sql2);
1346 } else {
1347 $resql2 = false;
1348 }
1349 print ' - Done ('.(($resql1 && $resql2) ? 'OK' : 'KO').')';
1350 } else {
1351 print ' - Disabled';
1352 }
1353 print '</td></tr>';
1354 flush();
1355 ob_flush();
1356 }
1357
1358 // Enable foreign key checking
1359 if ($force_utf8mb4_on_tables == 'confirmed') {
1360 $sql = 'SET FOREIGN_KEY_CHECKS=1';
1361 print '<!-- '.$sql.' -->';
1362 $resql = $db->query($sql);
1363 }
1364 } else {
1365 print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1366 }
1367}
1368
1369// rebuild sequences for pgsql
1370if ($ok && GETPOST('rebuild_sequences', 'alpha')) {
1371 print '<tr><td colspan="2"><br>*** Force to rebuild sequences (for postgresql only)</td></tr>';
1372
1373 if ($db->type == "pgsql") {
1374 $rebuild_sequence = GETPOST('rebuild_sequences', 'alpha');
1375
1376 if ($rebuild_sequence == 'confirmed') {
1377 $sql = "SELECT dol_util_rebuild_sequences();";
1378 print '<!-- '.$sql.' -->';
1379 $resql = $db->query($sql);
1380 }
1381 } else {
1382 print '<tr><td colspan="2">Not available with database type '.$db->type.'</td></tr>';
1383 }
1384}
1385
1386//
1387if ($ok && GETPOST('repair_link_dispatch_lines_supplier_order_lines')) {
1388 /*
1389 * This script is meant to be run when upgrading from a dolibarr version < 3.8
1390 * to a newer version.
1391 *
1392 * Version 3.8 introduces a new column in llx_commande_fournisseur_dispatch, which
1393 * matches the dispatch to a specific supplier order line (so that if there are
1394 * several with the same product, the user can specifically tell which products of
1395 * which line were dispatched where).
1396 *
1397 * However when migrating, the new column has a default value of 0, which means that
1398 * old supplier orders whose lines were dispatched using the old dolibarr version
1399 * have unspecific dispatch lines, which are not taken into account by the new version,
1400 * thus making the order look like it was never dispatched at all.
1401 *
1402 * This scripts sets this foreign key to the first matching supplier order line whose
1403 * product (and supplier order of course) are the same as the dispatch’s.
1404 *
1405 * If the dispatched quantity is more than indicated on the order line (this happens if
1406 * there are several order lines for the same product), it creates new dispatch lines
1407 * pointing to the other order lines accordingly, until all the dispatched quantity is
1408 * accounted for.
1409 */
1410
1411 $repair_link_dispatch_lines_supplier_order_lines = GETPOST('repair_link_dispatch_lines_supplier_order_lines', 'alpha');
1412
1413
1414 echo '<tr><th>Repair llx_commande_fournisseur_dispatch.fk_commandefourndet</th></tr>';
1415 echo '<tr><td>Repair in progress. This may take a while.</td></tr>';
1416
1417 $sql_dispatch = 'SELECT * FROM '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch WHERE COALESCE(fk_commandefourndet, 0) = 0';
1418 $db->begin();
1419 $resql_dispatch = $db->query($sql_dispatch);
1420 $n_processed_rows = 0;
1421 $errors = array();
1422 if ($resql_dispatch) {
1423 if ($db->num_rows($resql_dispatch) == 0) {
1424 echo '<tr><td>Nothing to do.</td></tr>';
1425 exit;
1426 }
1427 while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
1428 $sql_line = 'SELECT line.rowid, line.qty FROM '.MAIN_DB_PREFIX.'commande_fournisseurdet AS line';
1429 $sql_line .= ' WHERE line.fk_commande = '.((int) $obj_dispatch->fk_commande);
1430 $sql_line .= ' AND line.fk_product = '.((int) $obj_dispatch->fk_product);
1431 $resql_line = $db->query($sql_line);
1432
1433 // s’il y a plusieurs lignes avec le même produit sur cette commande fournisseur,
1434 // on divise la ligne de dispatch en autant de lignes qu’on en a sur la commande pour le produit
1435 // et on met la quantité de la ligne dans la limite du "budget" indiqué par dispatch.qty
1436
1437 $remaining_qty = $obj_dispatch->qty;
1438 $first_iteration = true;
1439 if (!$resql_line) {
1440 echo '<tr><td>Unable to find a matching supplier order line for dispatch #'.$obj_dispatch->rowid.'</td></tr>';
1441 $errors[] = $sql_line;
1442 $n_processed_rows++;
1443 continue;
1444 }
1445 if ($db->num_rows($resql_line) == 0) {
1446 continue;
1447 }
1448 while ($obj_line = $db->fetch_object($resql_line)) {
1449 if (!$remaining_qty) {
1450 break;
1451 }
1452 if (!$obj_line->rowid) {
1453 continue;
1454 }
1455 $qty_for_line = min($remaining_qty, $obj_line->qty);
1456 if ($first_iteration) {
1457 $sql_attach = 'UPDATE '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch';
1458 $sql_attach .= ' SET fk_commandefourndet = '.((int) $obj_line->rowid).', qty = '.((float) $qty_for_line);
1459 $sql_attach .= ' WHERE rowid = '.((int) $obj_dispatch->rowid);
1460 $first_iteration = false;
1461 } else {
1462 $sql_attach_values = array(
1463 ((int) $obj_dispatch->fk_commande),
1464 ((int) $obj_dispatch->fk_product),
1465 ((int) $obj_line->rowid),
1466 ((float) $qty_for_line),
1467 ((int) $obj_dispatch->fk_entrepot),
1468 ((int) $obj_dispatch->fk_user),
1469 $obj_dispatch->datec ? "'".$db->idate($db->jdate($obj_dispatch->datec))."'" : 'NULL',
1470 $obj_dispatch->comment ? "'".$db->escape($obj_dispatch->comment)."'" : 'NULL',
1471 $obj_dispatch->status ? ((int) $obj_dispatch->status) : 'NULL',
1472 $obj_dispatch->tms ? "'".$db->idate($db->jdate($obj_dispatch->tms))."'" : 'NULL',
1473 $obj_dispatch->batch ? "'".$db->escape($obj_dispatch->batch)."'" : 'NULL',
1474 $obj_dispatch->eatby ? "'".$db->escape($obj_dispatch->eatby)."'" : 'NULL',
1475 $obj_dispatch->sellby ? "'".$db->escape($obj_dispatch->sellby)."'" : 'NULL'
1476 );
1477 $sql_attach_values = join(', ', $sql_attach_values);
1478
1479 $sql_attach = 'INSERT INTO '.MAIN_DB_PREFIX.'commande_fournisseur_dispatch';
1480 $sql_attach .= ' (fk_commande, fk_product, fk_commandefourndet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)';
1481 $sql_attach .= " VALUES (".$sql_attach_values.")";
1482 }
1483
1484 if ($repair_link_dispatch_lines_supplier_order_lines == 'confirmed') {
1485 $resql_attach = $db->query($sql_attach);
1486 } else {
1487 $resql_attach = true; // Force success in test mode
1488 }
1489
1490 if ($resql_attach) {
1491 $remaining_qty -= $qty_for_line;
1492 } else {
1493 $errors[] = $sql_attach;
1494 }
1495
1496 $first_iteration = false;
1497 }
1498 $n_processed_rows++;
1499
1500 // report progress every 256th row
1501 if (!($n_processed_rows & 0xff)) {
1502 echo '<tr><td>Processed '.$n_processed_rows.' rows with '.count($errors).' errors…'."</td></tr>\n";
1503 flush();
1504 ob_flush();
1505 }
1506 }
1507 } else {
1508 echo '<tr><td>Unable to find any dispatch without an fk_commandefourndet.'."</td></tr>\n";
1509 echo $sql_dispatch."\n";
1510 }
1511 echo '<tr><td>Fixed '.$n_processed_rows.' rows with '.count($errors).' errors…'."</td></tr>\n";
1512 echo '<tr><td>DONE.'."</td></tr>\n";
1513
1514 if (count($errors)) {
1515 $db->rollback();
1516 echo '<tr><td>The transaction was rolled back due to errors: nothing was changed by the script.</td></tr>';
1517 } else {
1518 $db->commit();
1519 }
1520 $db->close();
1521
1522 echo '<tr><td><h3>SQL queries with errors:</h3></tr></td>';
1523 echo '<tr><td>'.join('</td></tr><tr><td>', $errors).'</td></tr>';
1524}
1525
1526// Repair llx_commande_fournisseur to eleminate duplicate reference
1527if ($ok && GETPOST('repair_supplier_order_duplicate_ref')) {
1528 require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.commande.class.php';
1529 include_once DOL_DOCUMENT_ROOT . '/societe/class/societe.class.php';
1530
1531 $db->begin();
1532
1533 $err = 0;
1534
1535 // Query to find all duplicate supplier orders
1536 $sql = "SELECT * FROM " . MAIN_DB_PREFIX . "commande_fournisseur";
1537 $sql .= " WHERE ref IN (SELECT cf.ref FROM " . MAIN_DB_PREFIX . "commande_fournisseur cf GROUP BY cf.ref, cf.entity HAVING COUNT(cf.rowid) > 1)";
1538
1539 // Build a list of ref => []CommandeFournisseur
1540 $duplicateSupplierOrders = [];
1541 $resql = $db->query($sql);
1542 if ($resql) {
1543 while ($rawSupplierOrder = $db->fetch_object($resql)) {
1544 $supplierOrder = new CommandeFournisseur($db);
1545 $supplierOrder->setVarsFromFetchObj($rawSupplierOrder);
1546
1547 $duplicateSupplierOrders[$rawSupplierOrder->ref] [] = $supplierOrder;
1548 }
1549 } else {
1550 $err++;
1551 }
1552
1553 // Process all duplicate supplier order and regenerate the reference for all except the first one
1554 foreach ($duplicateSupplierOrders as $ref => $supplierOrders) {
1556 foreach (array_slice($supplierOrders, 1) as $supplierOrder) {
1557 // Definition of supplier order numbering model name
1558 $soc = new Societe($db);
1559 $soc->fetch($supplierOrder->fourn_id);
1560
1561 $newRef = $supplierOrder->getNextNumRef($soc);
1562
1563 $sql = "UPDATE " . MAIN_DB_PREFIX . "commande_fournisseur cf SET cf.ref = '" . $db->escape($newRef) . "' WHERE cf.rowid = " . (int) $supplierOrder->id;
1564 if (!$db->query($sql)) {
1565 $err++;
1566 }
1567 }
1568 }
1569
1570 if ($err == 0) {
1571 $db->commit();
1572 } else {
1573 $db->rollback();
1574 }
1575}
1576
1577print '</table>';
1578
1579
1580
1581if (empty($actiondone)) {
1582 print '<div class="error">'.$langs->trans("ErrorWrongParameters").'</div>';
1583}
1584
1585if ($oneoptionset) {
1586 print '<div class="center" style="padding-top: 10px"><a href="../index.php?mainmenu=home&leftmenu=home'.(GETPOSTISSET("login") ? '&username='.urlencode(GETPOST("login")) : '').'">';
1587 print $langs->trans("GoToDolibarr");
1588 print '</a></div>';
1589} else {
1590 print '<div class="center warning" style="padding-top: 10px">';
1591 print $langs->trans("SetAtLeastOneOptionAsUrlParameter");
1592 print '</div>';
1593}
1594
1595dolibarr_install_syslog("--- repair: end");
1596pFooter(1, $setuplang);
1597
1598if ($db->connected) {
1599 $db->close();
1600}
1601
1602// Return code if ran from command line
1603if (!$ok && isset($argv[1])) {
1604 exit(1);
1605}
run_sql($sqlfile, $silent=1, $entity=0, $usesavepoint=1, $handler='', $okerror='default', $linelengthlimit=32768, $nocommentremoval=0, $offsetforchartofaccount=0, $colspan=0, $onlysqltoimportwebsite=0, $database='')
Launch a sql file.
Classe permettant la gestion des paiements des charges La tva collectee n'est calculee que sur les fa...
Class to manage predefined suppliers products.
Class to manage customers orders.
Class to manage contracts.
Class to manage standard extra fields.
Class to manage suppliers invoices.
Class to manage invoices.
Class to manage proposals.
Class to manage third parties objects (customers, suppliers, prospects...)
dol_delete_file($file, $disableglob=0, $nophperrors=0, $nohook=0, $object=null, $allowdotdot=false, $indexdatabase=1, $nolog=0)
Remove a file or several files with a mask.
dol_delete_dir($dir, $nophperrors=0)
Remove a directory (not recursive, so content must be empty).
dol_is_file($pathoffile)
Return if path is a file.
dol_copy($srcfile, $destfile, $newmask=0, $overwriteifexists=1, $testvirus=0, $indexdatabase=0)
Copy a file to another file.
dol_dir_list($path, $types="all", $recursive=0, $filter="", $excludefilter=null, $sortcriteria="name", $sortorder=SORT_ASC, $mode=0, $nohook=0, $relativename="", $donotfollowsymlinks=0, $nbsecondsold=0)
Scan a directory and return a list of files/directories.
Definition files.lib.php:62
dol_print_error($db='', $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0)
Return value of a param into GET or POST supervariable.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_mkdir($dir, $dataroot='', $newmask='')
Creation of a directory (this can create recursive subdir)
getDoliDBInstance($type, $host, $user, $pass, $name, $port)
Return a DoliDB instance (database handler).
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...
vignette($file, $maxWidth=160, $maxHeight=120, $extName='_small', $quality=50, $outdir='thumbs', $targetformat=0)
Create a thumbnail from an image file (Supported extensions are gif, jpg, png and bmp).
image_format_supported($file, $acceptsvg=0)
Return if a filename is file name of a supported image format.
pHeader($subtitle, $next, $action='set', $param='', $forcejqueryurl='', $csstable='main-inside')
Show HTML header of install pages.
Definition inc.php:513
pFooter($nonext=0, $setuplang='', $jscheckfunction='', $withpleasewait=0, $morehtml='')
Print HTML footer of install pages.
Definition inc.php:602
dolibarr_install_syslog($message, $level=LOG_DEBUG)
Log function for install pages.
Definition inc.php:663
clean_data_ecm_directories()
Clean data into ecm_directories table.
dol_decode($chain, $key='1')
Decode a base 64 encoded + specific delta change.