28 include_once
'inc.php';
29 if (file_exists($conffile)) {
30 include_once $conffile;
32 require_once $dolibarr_main_document_root.
'/core/lib/admin.lib.php';
33 include_once $dolibarr_main_document_root.
'/core/lib/images.lib.php';
34 require_once $dolibarr_main_document_root.
'/core/class/extrafields.class.php';
35 require_once
'lib/repair.lib.php';
43 $err = error_reporting();
46 error_reporting($err);
48 $setuplang =
GETPOST(
"selectlang",
'aZ09', 3) ?
GETPOST(
"selectlang",
'aZ09', 3) :
'auto';
49 $langs->setDefaultLang($setuplang);
51 $langs->loadLangs(array(
"admin",
"install",
"other"));
53 if ($dolibarr_main_db_type ==
"mysqli") {
56 if ($dolibarr_main_db_type ==
"pgsql") {
59 if ($dolibarr_main_db_type ==
"mssql") {
65 if (!is_object($conf)) {
79 print
'<h3>'.$langs->trans(
"Repair").
'</h3>';
81 print
'Option standard (\'test\' or \'confirmed\') is '.(GETPOST(
'standard',
'alpha') ?
GETPOST(
'standard',
'alpha') :
'undefined').
'<br>'.
"\n";
83 print
'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";
85 print
'Option restore_thirdparties_logos (\'test\' or \'confirmed\') is '.(GETPOST(
'restore_thirdparties_logos',
'alpha') ?
GETPOST(
'restore_thirdparties_logos',
'alpha') :
'undefined').
'<br>'.
"\n";
86 print
'Option restore_user_pictures (\'test\' or \'confirmed\') is '.(GETPOST(
'restore_user_pictures',
'alpha') ?
GETPOST(
'restore_user_pictures',
'alpha') :
'undefined').
'<br>'.
"\n";
87 print
'Option rebuild_product_thumbs (\'test\' or \'confirmed\') is '.(GETPOST(
'rebuild_product_thumbs',
'alpha') ?
GETPOST(
'rebuild_product_thumbs',
'alpha') :
'undefined').
'<br>'.
"\n";
89 print
'Option clean_linked_elements (\'test\' or \'confirmed\') is '.(GETPOST(
'clean_linked_elements',
'alpha') ?
GETPOST(
'clean_linked_elements',
'alpha') :
'undefined').
'<br>'.
"\n";
90 print
'Option clean_menus (\'test\' or \'confirmed\') is '.(GETPOST(
'clean_menus',
'alpha') ?
GETPOST(
'clean_menus',
'alpha') :
'undefined').
'<br>'.
"\n";
91 print
'Option clean_orphelin_dir (\'test\' or \'confirmed\') is '.(GETPOST(
'clean_orphelin_dir',
'alpha') ?
GETPOST(
'clean_orphelin_dir',
'alpha') :
'undefined').
'<br>'.
"\n";
92 print
'Option clean_product_stock_batch (\'test\' or \'confirmed\') is '.(GETPOST(
'clean_product_stock_batch',
'alpha') ?
GETPOST(
'clean_product_stock_batch',
'alpha') :
'undefined').
'<br>'.
"\n";
93 print
'Option clean_perm_table (\'test\' or \'confirmed\') is '.(GETPOST(
'clean_perm_table',
'alpha') ?
GETPOST(
'clean_perm_table',
'alpha') :
'undefined').
'<br>'.
"\n";
94 print
'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";
96 print
'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";
98 print
'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";
99 print
"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";
101 print
'Option rebuild_sequences, for postgresql only (\'test\' or \'confirmed\') is '.(GETPOST(
'rebuild_sequences',
'alpha') ?
GETPOST(
'rebuild_sequences',
'alpha') :
'undefined').
'<br>'.
"\n";
104 print
'<table cellspacing="0" cellpadding="1" border="0" width="100%">';
108 if (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;
115 $dolibarr_main_db_pass =
dol_decode($dolibarr_main_db_encrypted_pass);
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;
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 :
'';
131 $db =
getDoliDBInstance($conf->db->type, $conf->db->host, $conf->db->user, $conf->db->pass, $conf->db->name, (
int) $conf->db->port);
133 if ($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"));
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));
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>";
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));
159 $version = $db->getVersion();
160 $versionarray = $db->getVersionArray();
161 print
'<tr><td>'.$langs->trans(
"ServerVersion").
'</td>';
162 print
'<td class="right">'.$version.
'</td></tr>';
167 $conf->setValues($db);
169 if (defined(
'SYSLOG_FILE')) {
170 $conf->global->SYSLOG_FILE = constant(
'SYSLOG_FILE');
172 $conf->global->MAIN_ENABLE_LOG_TO_HTML = 1;
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'));
184 if ($ok && $oneoptionset) {
186 print
'<tr><td colspan="2">'.$langs->trans(
"PleaseBePatient").
'<br><br></td></tr>';
192 if ($ok &&
GETPOST(
'standard',
'alpha')) {
193 $dir =
"mysql/migration/";
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;
211 foreach ($filesindir as $file) {
212 if (preg_match(
'/repair/i', $file)) {
218 foreach ($filelist as $file) {
219 print
'<tr><td class="nowrap">*** ';
220 print $langs->trans(
"Script").
'</td><td class="right">'.$file.
'</td></tr>';
222 $name = substr($file, 0,
dol_strlen($file) - 4);
225 $ok =
run_sql($dir.$file, 0,
'', 1);
232 if ($ok &&
GETPOST(
'standard',
'alpha')) {
234 $listofmodulesextra = array(
'societe'=>
'societe',
'adherent'=>
'adherent',
'product'=>
'product',
235 'socpeople'=>
'socpeople',
'propal'=>
'propal',
'commande'=>
'commande',
'facture'=>
'facture',
236 'supplier_proposal'=>
'supplier_proposal',
'commande_fournisseur'=>
'commande_fournisseur',
'facture_fourn'=>
'facture_fourn',
237 'actioncomm'=>
'actioncomm',
'bom_bom'=>
'bom_bom',
'mrp_mo'=>
'mrp_mo',
238 'adherent_type'=>
'adherent_type',
'user'=>
'user',
'projet'=>
'projet',
'projet_task'=>
'projet_task');
239 print
'<tr><td colspan="2"><br>*** Check fields into extra table structure match table of definition. If not add column into table</td></tr>';
240 foreach ($listofmodulesextra as $tablename => $elementtype) {
242 $tableextra = MAIN_DB_PREFIX.$tablename.
'_extrafields';
245 $arrayoffieldsdesc = $extrafields->fetch_name_optionals_label($elementtype);
248 $arrayoffieldsfound = array();
249 $resql = $db->DDLDescTable($tableextra);
251 print
'<tr><td>Check availability of extra field for '.$tableextra.
"<br>\n";
253 while ($obj = $db->fetch_object($resql)) {
254 $fieldname = $fieldtype =
'';
255 if (preg_match(
'/mysql/', $db->type)) {
256 $fieldname = $obj->Field;
257 $fieldtype = $obj->Type;
259 $fieldname = isset($obj->Key) ? $obj->Key : $obj->attname;
260 $fieldtype = isset($obj->Type) ? $obj->Type :
'varchar';
263 if (empty($fieldname)) {
266 if (in_array($fieldname, array(
'rowid',
'tms',
'fk_object',
'import_key'))) {
269 $arrayoffieldsfound[$fieldname] = array(
'type'=>$fieldtype);
273 foreach ($arrayoffieldsdesc as $code => $label) {
274 if (!in_array($code, array_keys($arrayoffieldsfound))) {
275 print
'Found field '.$code.
' declared into '.MAIN_DB_PREFIX.
'extrafields table but not found into desc of table '.$tableextra.
" -> ";
276 $type = $extrafields->attributes[$elementtype][
'type'][$code]; $length = $extrafields->attributes[$elementtype][
'size'][$code]; $attribute =
''; $default =
''; $extra =
''; $null =
'null';
278 if ($type ==
'boolean') {
281 } elseif ($type ==
'price') {
284 } elseif ($type ==
'phone') {
287 } elseif ($type ==
'mail') {
290 } elseif (($type ==
'select') || ($type ==
'sellist') || ($type ==
'radio') || ($type ==
'checkbox') || ($type ==
'chkbxlst')) {
293 } elseif ($type ==
'link') {
304 'attribute'=>$attribute,
312 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
313 $result = $db->DDLAddField($tableextra, $code, $field_desc,
"");
316 print
"KO ".$db->lasterror.
"<br>\n";
321 print
' - Mode test, no column added.';
326 print
"</td><td> </td></tr>\n";
335 if ($ok &&
GETPOST(
'standard',
'alpha')) {
341 if ($ok &&
GETPOST(
'standard',
'alpha')) {
342 print
'<tr><td colspan="2"><br>*** Clean constant record of modules not enabled</td></tr>';
344 $sql =
"SELECT name, entity, value";
345 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
346 $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'";
347 $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'";
348 $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_%'";
349 $sql .=
" OR name LIKE 'MAIN_MODULE_%_MODULEFOREXTERNAL'";
350 $sql .=
" ORDER BY name, entity";
352 $resql = $db->query(
$sql);
354 $num = $db->num_rows($resql);
361 $obj = $db->fetch_object($resql);
364 if (preg_match(
'/MAIN_MODULE_([^_]+)_(.+)/i', $obj->name, $reg)) {
368 $sql2 =
"SELECT COUNT(*) as nb";
369 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
370 $sql2 .=
" WHERE name = 'MAIN_MODULE_".$name.
"'";
371 $sql2 .=
" AND entity = ".((int) $obj->entity);
372 $resql2 = $db->query($sql2);
374 $obj2 = $db->fetch_object($resql2);
375 if ($obj2 && $obj2->nb == 0) {
377 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = '".$db->escape($obj->name).
"' AND entity = ".((int) $obj->entity);
379 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
380 $db->query($sqldelete);
382 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>';
384 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>';
404 if ($ok &&
GETPOST(
'standard',
'alpha')) {
405 print
'<tr><td colspan="2"><br>*** Clean definition of boxes of modules not enabled</td></tr>';
407 $sql =
"SELECT file, entity FROM ".MAIN_DB_PREFIX.
"boxes_def";
408 $sql .=
" WHERE file like '%@%'";
410 $resql = $db->query(
$sql);
412 $num = $db->num_rows($resql);
419 $obj = $db->fetch_object($resql);
422 if (preg_match(
'/^(.+)@(.+)$/i', $obj->file, $reg)) {
426 $sql2 =
"SELECT COUNT(*) as nb";
427 $sql2 .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
428 $sql2 .=
" WHERE name = 'MAIN_MODULE_".strtoupper($module).
"'";
429 $sql2 .=
" AND entity = ".((int) $obj->entity);
430 $sql2 .=
" AND value <> 0";
431 $resql2 = $db->query($sql2);
433 $obj2 = $db->fetch_object($resql2);
434 if ($obj2 && $obj2->nb == 0) {
436 $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).
")";
437 $sqldeleteb =
"DELETE FROM ".MAIN_DB_PREFIX.
"boxes_def WHERE file = '".$db->escape($obj->file).
"' AND entity = ".((int) $obj->entity);
439 if (
GETPOST(
'standard',
'alpha') ==
'confirmed') {
440 $db->query($sqldeletea);
441 $db->query($sqldeleteb);
443 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>';
445 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>';
463 if ($ok &&
GETPOST(
'restore_thirdparties_logos')) {
468 print
'<tr><td colspan="2"><br>*** Restore thirdparties logo<br>';
470 $sql =
"SELECT s.rowid, s.nom as name, s.logo FROM ".MAIN_DB_PREFIX.
"societe as s ORDER BY s.nom";
471 $resql = $db->query(
$sql);
473 $num = $db->num_rows($resql);
477 $obj = $db->fetch_object($resql);
485 $tmp = explode(
'.', $obj->logo);
487 if (isset($tmp[1])) {
492 $filetotest = $dolibarr_main_data_root.
'/societe/logos/'.$name.$ext;
493 $filetotestsmall = $dolibarr_main_data_root.
'/societe/logos/thumbs/'.$name.
'_small'.$ext;
495 print
'Check thirdparty '.$obj->rowid.
' name='.$obj->name.
' logo='.$obj->logo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
497 $filetarget = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/'.$name.$ext;
498 $filetargetsmall = $dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs/'.$name.
'_small'.$ext;
501 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
502 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos');
505 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
506 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
507 dol_copy($filetotest, $filetarget,
'', 0);
513 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
514 dol_mkdir($dolibarr_main_data_root.
'/societe/'.$obj->rowid.
'/logos/thumbs');
516 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
517 if (
GETPOST(
'restore_thirdparties_logos',
'alpha') ==
'confirmed') {
518 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
537 if ($ok &&
GETPOST(
'restore_user_pictures',
'alpha')) {
542 print
'<tr><td colspan="2"><br>*** Restore user pictures<br>';
544 $sql =
"SELECT s.rowid, s.firstname, s.lastname, s.login, s.photo FROM ".MAIN_DB_PREFIX.
"user as s ORDER BY s.rowid";
545 $resql = $db->query(
$sql);
547 $num = $db->num_rows($resql);
551 $obj = $db->fetch_object($resql);
559 $tmp = explode(
'.', $obj->photo);
561 if (isset($tmp[1])) {
566 $filetotest = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/'.$name.$ext;
567 $filetotestsmall = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_small'.$ext;
568 $filetotestmini = $dolibarr_main_data_root.
'/users/'.substr(sprintf(
'%08d', $obj->rowid), -1, 1).
'/'.substr(sprintf(
'%08d', $obj->rowid), -2, 1).
'/thumbs/'.$name.
'_mini'.$ext;
570 print
'Check user '.$obj->rowid.
' lastname='.$obj->lastname.
' firstname='.$obj->firstname.
' photo='.$obj->photo.
' file '.$filetotest.
" exists=".$exists.
"<br>\n";
572 $filetarget = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/'.$name.$ext;
573 $filetargetsmall = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_small'.$ext;
574 $filetargetmini = $dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs/'.$name.
'_mini'.$ext;
578 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
579 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid);
582 print
" -> Copy file ".$filetotest.
" -> ".$filetarget.
"<br>\n";
583 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
584 dol_copy($filetotest, $filetarget,
'', 0);
590 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
591 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
594 print
" -> Copy file ".$filetotestsmall.
" -> ".$filetargetsmall.
"<br>\n";
595 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
596 dol_copy($filetotestsmall, $filetargetsmall,
'', 0);
602 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
603 dol_mkdir($dolibarr_main_data_root.
'/users/'.$obj->rowid.
'/thumbs');
606 print
" -> Copy file ".$filetotestmini.
" -> ".$filetargetmini.
"<br>\n";
607 if (
GETPOST(
'restore_user_pictures',
'alpha') ==
'confirmed') {
608 dol_copy($filetotestmini, $filetargetmini,
'', 0);
626 if ($ok &&
GETPOST(
'rebuild_product_thumbs',
'alpha')) {
628 global $maxwidthsmall, $maxheightsmall, $maxwidthmini, $maxheightmini;
630 print
'<tr><td colspan="2"><br>*** Rebuild product thumbs<br>';
632 $sql =
"SELECT s.rowid, s.ref FROM ".MAIN_DB_PREFIX.
"product as s ORDER BY s.ref";
633 $resql = $db->query(
$sql);
635 $num = $db->num_rows($resql);
639 $obj = $db->fetch_object($resql);
641 if (!empty($obj->ref)) {
642 $files =
dol_dir_list($dolibarr_main_data_root.
'/produit/'.$obj->ref,
'files', 0);
643 foreach ($files as $file) {
646 $imgThumbSmall =
'notbuild';
647 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
649 $imgThumbSmall =
vignette($file[
'fullname'], $maxwidthsmall, $maxheightsmall,
'_small', 50,
"thumbs");
651 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbSmall.
" maxwidthsmall=".$maxwidthsmall.
" maxheightsmall=".$maxheightsmall.
"<br>\n";
652 $imgThumbMini =
'notbuild';
653 if (
GETPOST(
'rebuild_product_thumbs',
'alpha') ==
'confirmed') {
656 $imgThumbMini =
vignette($file[
'fullname'], $maxwidthmini, $maxheightmini,
'_mini', 50,
"thumbs");
658 print
'Check product '.$obj->rowid.
", file ".$file[
'fullname'].
" -> ".$imgThumbMini.
" maxwidthmini=".$maxwidthmini.
" maxheightmini=".$maxheightmini.
"<br>\n";
674 if ($ok &&
GETPOST(
'clean_linked_elements',
'alpha')) {
675 print
'<tr><td colspan="2"><br>*** Check table of linked elements and delete orphelins links</td></tr>';
677 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'commande').
"</td></tr>\n";
680 print
'<tr><td colspan="2">'.checkLinkedElements(
'propal',
'facture').
"</td></tr>\n";
683 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'facture').
"</td></tr>\n";
686 print
'<tr><td colspan="2">'.checkLinkedElements(
'commande',
'shipping').
"</td></tr>\n";
689 print
'<tr><td colspan="2">'.checkLinkedElements(
'shipping',
'delivery').
"</td></tr>\n";
692 print
'<tr><td colspan="2">'.checkLinkedElements(
'order_supplier',
'invoice_supplier').
"</td></tr>\n";
697 if ($ok &&
GETPOST(
'clean_menus',
'alpha')) {
698 print
'<tr><td colspan="2"><br>*** Clean menu entries coming from disabled modules</td></tr>';
700 $sql =
"SELECT rowid, module";
701 $sql .=
" FROM ".MAIN_DB_PREFIX.
"menu as c";
702 $sql .=
" WHERE module IS NOT NULL AND module <> ''";
703 $sql .=
" ORDER BY module";
705 $resql = $db->query(
$sql);
707 $num = $db->num_rows($resql);
711 $obj = $db->fetch_object($resql);
713 $modulecond = $obj->module;
714 $modulecondarray = explode(
'|', $obj->module);
723 foreach ($modulecondarray as $tmpname) {
724 if ($tmpname ==
'margins') {
729 if (!empty($conf->$tmpname)) {
730 $result = $conf->$tmpname->enabled;
737 if (!$moduleok && $modulecond) {
738 print
' - Module condition '.$modulecond.
' seems ko, we delete menu entry.';
739 if (
GETPOST(
'clean_menus') ==
'confirmed') {
740 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"menu WHERE module = '".$db->escape($modulecond).
"'";
741 $resql2 = $db->query($sql2);
746 print
' - <span class="warning">Cleaned</span>';
749 print
' - <span class="warning">Canceled (test mode)</span>';
752 print
' - Module condition '.$modulecond.
' is ok, we do nothing.';
771 print
'<tr><td>No menu entries of disabled menus found</td></tr>';
781 if ($ok &&
GETPOST(
'clean_orphelin_dir',
'alpha')) {
782 $listmodulepart = array(
'company',
'invoice',
'invoice_supplier',
'propal',
'order',
'order_supplier',
'contract',
'tax');
783 foreach ($listmodulepart as $modulepart) {
784 $filearray = array();
785 $upload_dir = isset($conf->$modulepart->dir_output) ? $conf->$modulepart->dir_output :
'';
786 if ($modulepart ==
'company') {
787 $upload_dir = $conf->societe->dir_output;
789 if ($modulepart ==
'invoice') {
790 $upload_dir = $conf->facture->dir_output;
792 if ($modulepart ==
'invoice_supplier') {
793 $upload_dir = $conf->fournisseur->facture->dir_output;
795 if ($modulepart ==
'order') {
796 $upload_dir = $conf->commande->dir_output;
798 if ($modulepart ==
'order_supplier') {
799 $upload_dir = $conf->fournisseur->commande->dir_output;
801 if ($modulepart ==
'contract') {
802 $upload_dir = $conf->contrat->dir_output;
805 if (empty($upload_dir)) {
809 print
'<tr><td colspan="2"><br>*** Clean orphelins files into files '.$upload_dir.
'</td></tr>';
811 $filearray =
dol_dir_list($upload_dir,
"files", 1,
'', array(
'^SPECIMEN\.pdf$',
'^\.',
'(\.meta|_preview.*\.png)$',
'^temp$',
'^payments$',
'^CVS$',
'^thumbs$'),
'', SORT_DESC, 1,
true);
814 if ($modulepart ==
'company') {
815 include_once DOL_DOCUMENT_ROOT.
'/societe/class/societe.class.php';
816 $object_instance =
new Societe($db);
818 if ($modulepart ==
'invoice') {
819 include_once DOL_DOCUMENT_ROOT.
'/compta/facture/class/facture.class.php';
820 $object_instance =
new Facture($db);
821 } elseif ($modulepart ==
'invoice_supplier') {
822 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.facture.class.php';
824 } elseif ($modulepart ==
'propal') {
825 include_once DOL_DOCUMENT_ROOT.
'/comm/propal/class/propal.class.php';
826 $object_instance =
new Propal($db);
827 } elseif ($modulepart ==
'order') {
828 include_once DOL_DOCUMENT_ROOT.
'/commande/class/commande.class.php';
829 $object_instance =
new Commande($db);
830 } elseif ($modulepart ==
'order_supplier') {
831 include_once DOL_DOCUMENT_ROOT.
'/fourn/class/fournisseur.commande.class.php';
833 } elseif ($modulepart ==
'contract') {
834 include_once DOL_DOCUMENT_ROOT.
'/contrat/class/contrat.class.php';
835 $object_instance =
new Contrat($db);
836 } elseif ($modulepart ==
'tax') {
837 include_once DOL_DOCUMENT_ROOT.
'/compta/sociales/class/chargesociales.class.php';
841 foreach ($filearray as $key => $file) {
842 if (!is_dir($file[
'name'])
843 && $file[
'name'] !=
'.'
844 && $file[
'name'] !=
'..'
845 && $file[
'name'] !=
'CVS'
848 $relativefile = preg_replace(
'/'.preg_quote($upload_dir.
'/',
'/').
'/',
'', $file[
'fullname']);
851 $id = 0; $ref =
''; $object_instance->id = 0; $object_instance->ref =
''; $label =
'';
854 if ($modulepart ==
'invoice') {
855 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
857 if ($modulepart ==
'invoice_supplier') {
858 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = empty($reg[1]) ?
'' : $reg[1];
860 if ($modulepart ==
'propal') {
861 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
863 if ($modulepart ==
'order') {
864 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
866 if ($modulepart ==
'order_supplier') {
867 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
869 if ($modulepart ==
'contract') {
870 preg_match(
'/(.*)\/[^\/]+$/', $relativefile, $reg); $ref = $reg[1];
872 if ($modulepart ==
'tax') {
873 preg_match(
'/(\d+)\/[^\/]+$/', $relativefile, $reg); $id = $reg[1];
878 $result = $object_instance->fetch($id, $ref);
882 print
'<tr><td colspan="2">';
883 print
'Delete orphelins file '.$file[
'fullname'].
'<br>';
884 if (
GETPOST(
'clean_orphelin_dir',
'alpha') ==
'confirmed') {
889 } elseif ($result < 0) {
890 print
'Error in '.get_class($object_instance).
'.fetch of id'.$id.
' ref='.$ref.
', result='.$result.
'<br>';
899 if ($ok &&
GETPOST(
'clean_product_stock_batch',
'alpha')) {
900 $methodtofix =
GETPOST(
'methodtofix',
'alpha') ?
GETPOST(
'methodtofix',
'alpha') :
'updatestock';
902 print
'<tr><td colspan="2"><br>*** Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
904 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
905 $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";
906 $sql .=
" WHERE p.rowid = ps.fk_product";
907 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
908 $sql .=
" HAVING (SUM(pb.qty) IS NOT NULL AND reel != SUM(pb.qty)) OR (SUM(pb.qty) IS NULL AND p.tobatch > 0)";
910 $resql = $db->query(
$sql);
912 $num = $db->num_rows($resql);
917 $obj = $db->fetch_object($resql);
918 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)';
921 if ($obj->reel != $obj->reelbatch) {
922 if (empty($obj->tobatch)) {
924 print
' -> Delete qty '.$obj->reelbatch.
' for any lot linked to fk_product_stock='.$obj->psrowid;
925 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"product_batch";
926 $sql2 .=
" WHERE fk_product_stock = ".((int) $obj->psrowid);
929 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
930 $resql2 = $db->query($sql2);
937 if ($methodtofix ==
'updatebatch') {
939 print
' -> Insert qty '.($obj->reel - $obj->reelbatch).
' with lot 000000 linked to fk_product_stock='.$obj->psrowid;
940 $sql2 =
"INSERT INTO ".MAIN_DB_PREFIX.
"product_batch(fk_product_stock, batch, qty)";
941 $sql2 .=
"VALUES(".((int) $obj->psrowid).
", '000000', ".((
float) ($obj->reel - $obj->reelbatch)).
")";
944 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
945 $resql2 = $db->query($sql2);
954 if ($methodtofix ==
'updatestock') {
956 print
' -> Update qty of product_stock with qty = '.($obj->reelbatch ? ((
float) $obj->reelbatch) :
'0').
' for ps.rowid = '.((
int) $obj->psrowid);
957 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"product_stock";
958 $sql2 .=
" SET reel = ".($obj->reelbatch ? ((
float) $obj->reelbatch) :
'0').
" WHERE rowid = ".((
int) $obj->psrowid);
961 if (
GETPOST(
'clean_product_stock_batch') ==
'confirmed') {
966 $resql2 = $db->query($sql2);
969 $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)';
970 $resql3 = $db->query($sql3);
995 print
'<tr><td colspan="2">Nothing to do</td></tr>';
1004 if ($ok &&
GETPOST(
'clean_product_stock_negative_if_batch',
'alpha')) {
1005 print
'<tr><td colspan="2"><br>Clean table product_batch, methodtofix='.$methodtofix.
' (possible values: updatestock or updatebatch)</td></tr>';
1007 $sql =
"SELECT p.rowid, p.ref, p.tobatch, ps.rowid as psrowid, ps.fk_entrepot, ps.reel, SUM(pb.qty) as reelbatch";
1008 $sql .=
" FROM ".MAIN_DB_PREFIX.
"product as p, ".MAIN_DB_PREFIX.
"product_stock as ps, ".MAIN_DB_PREFIX.
"product_batch as pb";
1009 $sql .=
" WHERE p.rowid = ps.fk_product AND ps.rowid = pb.fk_product_stock";
1010 $sql .=
" AND p.tobatch > 0";
1011 $sql .=
" GROUP BY p.rowid, p.ref, p.tobatch, ps.rowid, ps.fk_entrepot, ps.reel";
1012 $sql .=
" HAVING reel != SUM(pb.qty)";
1013 $resql = $db->query(
$sql);
1015 $num = $db->num_rows($resql);
1020 $obj = $db->fetch_object($resql);
1021 print
'<tr><td>'.$obj->rowid.
'-'.$obj->ref.
'-'.$obj->fk_entrepot.
' -> '.$obj->psrowid.
': '.$obj->reel.
' != '.$obj->reelbatch;
1030 if ($ok &&
GETPOST(
'set_empty_time_spent_amount',
'alpha')) {
1031 print
'<tr><td colspan="2"><br>*** Set value of time spent without amount</td></tr>';
1033 $sql =
"SELECT COUNT(ptt.rowid) as nb, u.rowid as user_id, u.login, u.thm as user_thm";
1034 $sql .=
" FROM ".MAIN_DB_PREFIX.
"element_time as ptt, ".MAIN_DB_PREFIX.
"user as u";
1035 $sql .=
" WHERE ptt.fk_user = u.rowid";
1036 $sql .=
" AND ptt.thm IS NULL and u.thm > 0";
1037 $sql .=
" GROUP BY u.rowid, u.login, u.thm";
1039 $resql = $db->query(
$sql);
1041 $num = $db->num_rows($resql);
1046 $obj = $db->fetch_object($resql);
1047 print
'<tr><td>'.$obj->login.
'-'.$obj->user_id.
' ('.$obj->nb.
' lines to fix) -> '.$obj->user_thm;
1051 if (
GETPOST(
'set_empty_time_spent_amount') ==
'confirmed') {
1052 $sql2 =
"UPDATE ".MAIN_DB_PREFIX.
"element_time";
1053 $sql2 .=
" SET thm = ".$obj->user_thm.
" WHERE thm IS NULL AND fk_user = ".((int) $obj->user_id);
1054 $resql2 = $db->query($sql2);
1076 print
'<tr><td>No time spent with empty line on users with a hourly rate defined</td></tr>';
1085 if ($ok &&
GETPOST(
'force_disable_of_modules_not_found',
'alpha')) {
1086 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>';
1088 $arraylistofkey = array(
'hooks',
'js',
'css');
1090 foreach ($arraylistofkey as $key) {
1091 $sql =
"SELECT DISTINCT name, value";
1092 $sql .=
" FROM ".MAIN_DB_PREFIX.
"const as c";
1093 $sql .=
" WHERE name LIKE 'MAIN_MODULE_%_".strtoupper($key).
"'";
1094 $sql .=
" ORDER BY name";
1096 $resql = $db->query(
$sql);
1098 $num = $db->num_rows($resql);
1102 $obj = $db->fetch_object($resql);
1103 $constantname = $obj->name;
1111 if (preg_match(
'/MAIN_MODULE_(.*)_'.strtoupper($key).
'/i', $constantname, $reg)) {
1112 $name = strtolower($reg[1]);
1118 if ($key ==
'hooks') {
1119 $reloffile = $name.
'/class/actions_'.$name.
'.class.php';
1122 $value = $obj->value;
1123 $valuearray = json_decode($value);
1124 $reloffile = $valuearray[0];
1125 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1127 if ($key ==
'css') {
1128 $value = $obj->value;
1129 $valuearray = json_decode($value);
1130 if ($value && (!is_array($valuearray) || count($valuearray) == 0)) {
1131 $valuearray = array();
1132 $valuearray[0] = $value;
1134 $reloffile = preg_replace(
'/^\//',
'', $valuearray[0]);
1149 print
' - File of '.$key.
' ('.$reloffile.
') NOT found, we disable the module.';
1150 if (
GETPOST(
'force_disable_of_modules_not_found') ==
'confirmed') {
1151 $sql2 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"_".strtoupper($key).
"'";
1152 $resql2 = $db->query($sql2);
1157 $sql3 =
"DELETE FROM ".MAIN_DB_PREFIX.
"const WHERE name = 'MAIN_MODULE_".strtoupper($name).
"'";
1158 $resql3 = $db->query($sql3);
1163 print
' - <span class="warning">Cleaned</span>';
1166 print
' - <span class="warning">Canceled (test mode)</span>';
1169 print
' - File of '.$key.
' ('.$reloffile.
') found, we do nothing.';
1189 print
'<tr><td>No active module with missing files found by searching on MAIN_MODULE_(.*)_'.strtoupper($key).
'</td></tr>';
1199 if ($ok &&
GETPOST(
'clean_perm_table',
'alpha')) {
1200 print
'<tr><td colspan="2"><br>*** Clean table user_rights from lines of external modules no more enabled</td></tr>';
1203 foreach ($conf->modules as $key => $val) {
1204 $listofmods .= ($listofmods ?
',' :
'').
"'".$db->escape($val).
"'";
1207 $sql =
"SELECT id, libelle as label, module from ".MAIN_DB_PREFIX.
"rights_def WHERE module NOT IN (".$db->sanitize($listofmods, 1).
") AND id > 100000";
1209 $resql = $db->query(
$sql);
1211 $num = $db->num_rows($resql);
1215 $obj = $db->fetch_object($resql);
1217 print
'<tr><td>Found line with id '.$obj->id.
', label "'.$obj->label.
'" of module "'.$obj->module.
'" to delete';
1218 if (
GETPOST(
'clean_perm_table',
'alpha') ==
'confirmed') {
1219 $sqldelete =
"DELETE FROM ".MAIN_DB_PREFIX.
"rights_def WHERE id = ".((int) $obj->id);
1220 $resqldelete = $db->query($sqldelete);
1221 if (!$resqldelete) {
1231 print
'<tr><td>No lines of a disabled external module (with id > 100000) found into table rights_def</td></tr>';
1241 if ($ok &&
GETPOST(
'force_utf8_on_tables',
'alpha')) {
1242 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>';
1244 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1245 $force_utf8_on_tables =
GETPOST(
'force_utf8_on_tables',
'alpha');
1247 $listoftables = $db->DDLListTablesFull($db->database_name);
1250 if ($force_utf8_on_tables ==
'confirmed') {
1251 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1252 print
'<!-- '.$sql.
' -->';
1253 $resql = $db->query(
$sql);
1256 foreach ($listoftables as $table) {
1258 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1261 if ($table[1] ==
'VIEW') {
1262 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' (Skipped)</td></tr>';
1266 print
'<tr><td colspan="2">';
1268 $sql1 =
"ALTER TABLE ".$table[0].
" ROW_FORMAT=dynamic";
1269 $sql2 =
"ALTER TABLE ".$table[0].
" CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci";
1270 print
'<!-- '.$sql1.
' -->';
1271 print
'<!-- '.$sql2.
' -->';
1272 if ($force_utf8_on_tables ==
'confirmed') {
1273 $resql1 = $db->query($sql1);
1275 $resql2 = $db->query($sql2);
1279 print
' - Done ('.(($resql1 && $resql2) ?
'OK' :
'KO').
')';
1281 print
' - Disabled';
1287 if ($force_utf8_on_tables ==
'confirmed') {
1288 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1289 print
'<!-- '.$sql.
' -->';
1290 $resql = $db->query(
$sql);
1293 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1298 if ($ok &&
GETPOST(
'force_utf8mb4_on_tables',
'alpha')) {
1299 print
'<tr><td colspan="2"><br>*** Force page code and collation of tables into utf8mb4/utf8mb4_unicode_ci (for mysql/mariadb only)</td></tr>';
1301 if ($db->type ==
"mysql" || $db->type ==
"mysqli") {
1302 $force_utf8mb4_on_tables =
GETPOST(
'force_utf8mb4_on_tables',
'alpha');
1304 $listoftables = $db->DDLListTablesFull($db->database_name);
1307 if ($force_utf8mb4_on_tables ==
'confirmed') {
1308 $sql =
'SET FOREIGN_KEY_CHECKS=0';
1309 print
'<!-- '.$sql.
' -->';
1310 $resql = $db->query(
$sql);
1313 foreach ($listoftables as $table) {
1315 if ($conf->db->dolibarr_main_db_encryption != 0 && preg_match(
'/\_const$/', $table[0])) {
1318 if ($table[1] ==
'VIEW') {
1319 print
'<tr><td colspan="2">'.$table[0].
' is a '.$table[1].
' (Skipped)</td></tr>';
1323 print
'<tr><td colspan="2">';
1325 $sql1 =
"ALTER TABLE ".$table[0].
" ROW_FORMAT=dynamic";
1326 $sql2 =
"ALTER TABLE ".$table[0].
" CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci";
1327 print
'<!-- '.$sql1.
' -->';
1328 print
'<!-- '.$sql2.
' -->';
1329 if ($force_utf8mb4_on_tables ==
'confirmed') {
1330 $resql1 = $db->query($sql1);
1332 $resql2 = $db->query($sql2);
1336 print
' - Done ('.(($resql1 && $resql2) ?
'OK' :
'KO').
')';
1338 print
' - Disabled';
1346 if ($force_utf8mb4_on_tables ==
'confirmed') {
1347 $sql =
'SET FOREIGN_KEY_CHECKS=1';
1348 print
'<!-- '.$sql.
' -->';
1349 $resql = $db->query(
$sql);
1352 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1357 if ($ok &&
GETPOST(
'rebuild_sequences',
'alpha')) {
1358 print
'<tr><td colspan="2"><br>*** Force to rebuild sequences (for postgresql only)</td></tr>';
1360 if ($db->type ==
"pgsql") {
1361 $rebuild_sequence =
GETPOST(
'rebuild_sequences',
'alpha');
1363 if ($rebuild_sequence ==
'confirmed') {
1364 $sql =
"SELECT dol_util_rebuild_sequences();";
1365 print
'<!-- '.$sql.
' -->';
1366 $resql = $db->query(
$sql);
1369 print
'<tr><td colspan="2">Not available with database type '.$db->type.
'</td></tr>';
1374 if ($ok &&
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines')) {
1398 $repair_link_dispatch_lines_supplier_order_lines =
GETPOST(
'repair_link_dispatch_lines_supplier_order_lines',
'alpha');
1401 echo
'<tr><th>Repair llx_commande_fournisseur_dispatch.fk_commandefourndet</th></tr>';
1402 echo
'<tr><td>Repair in progress. This may take a while.</td></tr>';
1404 $sql_dispatch =
'SELECT * FROM '.MAIN_DB_PREFIX.
'commande_fournisseur_dispatch WHERE COALESCE(fk_commandefourndet, 0) = 0';
1406 $resql_dispatch = $db->query($sql_dispatch);
1407 $n_processed_rows = 0;
1409 if ($resql_dispatch) {
1410 if ($db->num_rows($resql_dispatch) == 0) {
1411 echo
'<tr><td>Nothing to do.</td></tr>';
1414 while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
1415 $sql_line =
'SELECT line.rowid, line.qty FROM '.MAIN_DB_PREFIX.
'commande_fournisseurdet AS line';
1416 $sql_line .=
' WHERE line.fk_commande = '.((int) $obj_dispatch->fk_commande);
1417 $sql_line .=
' AND line.fk_product = '.((int) $obj_dispatch->fk_product);
1418 $resql_line = $db->query($sql_line);
1424 $remaining_qty = $obj_dispatch->qty;
1425 $first_iteration =
true;
1427 echo
'<tr><td>Unable to find a matching supplier order line for dispatch #'.$obj_dispatch->rowid.
'</td></tr>';
1428 $errors[] = $sql_line;
1429 $n_processed_rows++;
1432 if ($db->num_rows($resql_line) == 0) {
1435 while ($obj_line = $db->fetch_object($resql_line)) {
1436 if (!$remaining_qty) {
1439 if (!$obj_line->rowid) {
1442 $qty_for_line = min($remaining_qty, $obj_line->qty);
1443 if ($first_iteration) {
1444 $sql_attach =
'UPDATE '.MAIN_DB_PREFIX.
'commande_fournisseur_dispatch';
1445 $sql_attach .=
' SET fk_commandefourndet = '.((int) $obj_line->rowid).
', qty = '.((
float) $qty_for_line);
1446 $sql_attach .=
' WHERE rowid = '.((int) $obj_dispatch->rowid);
1447 $first_iteration =
false;
1449 $sql_attach_values = array(
1450 ((
int) $obj_dispatch->fk_commande),
1451 ((
int) $obj_dispatch->fk_product),
1452 ((
int) $obj_line->rowid),
1453 ((
float) $qty_for_line),
1454 ((
int) $obj_dispatch->fk_entrepot),
1455 ((
int) $obj_dispatch->fk_user),
1456 $obj_dispatch->datec ?
"'".$db->idate($db->jdate($obj_dispatch->datec)).
"'" :
'NULL',
1457 $obj_dispatch->comment ?
"'".$db->escape($obj_dispatch->comment).
"'" :
'NULL',
1458 $obj_dispatch->status ? ((
int) $obj_dispatch->status) :
'NULL',
1459 $obj_dispatch->tms ?
"'".$db->idate($db->jdate($obj_dispatch->tms)).
"'" :
'NULL',
1460 $obj_dispatch->batch ?
"'".$db->escape($obj_dispatch->batch).
"'" :
'NULL',
1461 $obj_dispatch->eatby ?
"'".$db->escape($obj_dispatch->eatby).
"'" :
'NULL',
1462 $obj_dispatch->sellby ?
"'".$db->escape($obj_dispatch->sellby).
"'" :
'NULL'
1464 $sql_attach_values = join(
', ', $sql_attach_values);
1466 $sql_attach =
'INSERT INTO '.MAIN_DB_PREFIX.
'commande_fournisseur_dispatch';
1467 $sql_attach .=
' (fk_commande, fk_product, fk_commandefourndet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)';
1468 $sql_attach .=
" VALUES (".$sql_attach_values.
")";
1471 if ($repair_link_dispatch_lines_supplier_order_lines ==
'confirmed') {
1472 $resql_attach = $db->query($sql_attach);
1474 $resql_attach =
true;
1477 if ($resql_attach) {
1478 $remaining_qty -= $qty_for_line;
1480 $errors[] = $sql_attach;
1483 $first_iteration =
false;
1485 $n_processed_rows++;
1488 if (!($n_processed_rows & 0xff)) {
1489 echo
'<tr><td>Processed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1495 echo
'<tr><td>Unable to find any dispatch without an fk_commandefourndet.'.
"</td></tr>\n";
1496 echo $sql_dispatch.
"\n";
1498 echo
'<tr><td>Fixed '.$n_processed_rows.
' rows with '.count($errors).
' errors…'.
"</td></tr>\n";
1499 echo
'<tr><td>DONE.'.
"</td></tr>\n";
1501 if (count($errors)) {
1503 echo
'<tr><td>The transaction was rolled back due to errors: nothing was changed by the script.</td></tr>';
1509 echo
'<tr><td><h3>SQL queries with errors:</h3></tr></td>';
1510 echo
'<tr><td>'.join(
'</td></tr><tr><td>', $errors).
'</td></tr>';
1514 if ($ok &&
GETPOST(
'repair_supplier_order_duplicate_ref')) {
1515 require_once DOL_DOCUMENT_ROOT .
'/fourn/class/fournisseur.commande.class.php';
1516 include_once DOL_DOCUMENT_ROOT .
'/societe/class/societe.class.php';
1523 $sql =
"SELECT * FROM " . MAIN_DB_PREFIX .
"commande_fournisseur";
1524 $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)";
1527 $duplicateSupplierOrders = [];
1528 $resql = $db->query(
$sql);
1530 while ($rawSupplierOrder = $db->fetch_object($resql)) {
1532 $supplierOrder->setVarsFromFetchObj($rawSupplierOrder);
1534 $duplicateSupplierOrders[$rawSupplierOrder->ref] [] = $supplierOrder;
1541 foreach ($duplicateSupplierOrders as $ref => $supplierOrders) {
1543 foreach (array_slice($supplierOrders, 1) as $supplierOrder) {
1546 $soc->fetch($supplierOrder->fourn_id);
1548 $newRef = $supplierOrder->getNextNumRef($soc);
1550 $sql =
"UPDATE " . MAIN_DB_PREFIX .
"commande_fournisseur cf SET cf.ref = '" . $db->escape($newRef) .
"' WHERE cf.rowid = " . (int) $supplierOrder->id;
1568 if (empty($actiondone)) {
1569 print
'<div class="error">'.$langs->trans(
"ErrorWrongParameters").
'</div>';
1572 if ($oneoptionset) {
1573 print
'<div class="center" style="padding-top: 10px"><a href="../index.php?mainmenu=home&leftmenu=home'.(GETPOSTISSET(
"login") ?
'&username='.urlencode(
GETPOST(
"login")) :
'').
'">';
1574 print $langs->trans(
"GoToDolibarr");
1577 print
'<div class="center warning" style="padding-top: 10px">';
1578 print $langs->trans(
"SetAtLeastOneOptionAsUrlParameter");
1585 if ($db->connected) {
1590 if (!$ok && isset($argv[1])) {