From fa29415e6a16d5bab7afc9a9c342d75cfc6f07c3 Mon Sep 17 00:00:00 2001 From: Florian Mortgat Date: Thu, 22 Aug 2019 14:06:18 +0200 Subject: [PATCH] Moved repair payload from a specific script to install/repair.php --- ..._commande_fournisseur_dispatch_3.6-9.0.php | 160 ------------------ htdocs/install/repair.php | 125 ++++++++++++++ 2 files changed, 125 insertions(+), 160 deletions(-) delete mode 100644 htdocs/fourn/commande/script/repair_llx_commande_fournisseur_dispatch_3.6-9.0.php diff --git a/htdocs/fourn/commande/script/repair_llx_commande_fournisseur_dispatch_3.6-9.0.php b/htdocs/fourn/commande/script/repair_llx_commande_fournisseur_dispatch_3.6-9.0.php deleted file mode 100644 index 95cf50aabbf..00000000000 --- a/htdocs/fourn/commande/script/repair_llx_commande_fournisseur_dispatch_3.6-9.0.php +++ /dev/null @@ -1,160 +0,0 @@ - - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * This script is meant to be run when upgrading from a dolibarr version < 3.8 - * to a newer version. - * - * Version 3.8 introduces a new column in llx_commande_fournisseur_dispatch, which - * matches the dispatch to a specific supplier order line (so that if there are - * several with the same product, the user can specifically tell which products of - * which line were dispatched where). - * - * However when migrating, the new column has a default value of 0, which means that - * old supplier orders whose lines were dispatched using the old dolibarr version - * have unspecific dispatch lines, which are not taken into account by the new version, - * thus making the order look like it was never dispatched at all. - * - * This scripts sets this foreign key to the first matching supplier order line whose - * product (and supplier order of course) are the same as the dispatch’s. - * - * If the dispatched quantity is more than indicated on the order line (this happens if - * there are several order lines for the same product), it creates new dispatch lines - * pointing to the other order lines accordingly, until all the dispatched quantity is - * accounted for. - */ - -// Dolibarr environment -$path_dir = '../../'; -$main_inc_file = 'main.inc.php'; -while ((false == (@include $path_dir . $main_inc_file)) && 3*10 > strlen($path_dir)) { - $path_dir = '../' . $path_dir; - if (strlen($path_dir) > 20) { - echo 'Error: unable to include "' . $main_inc_file . '" from any of the parent directories.'; - exit; - } -} - -// Access control -if (!$user->admin) { - accessforbidden(); -} - -echo '

Repair llx_commande_fournisseur_dispatch.fk_commandefourndet

'; -echo '

Repair in progress. This may take a while.

'; - -echo '
';
-
-$sql_dispatch = 'SELECT * FROM ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch WHERE COALESCE(fk_commandefourndet, 0) = 0';
-$db->begin();
-$resql_dispatch = $db->query($sql_dispatch);
-$n_processed_rows = 0;
-$errors = array();
-if ($resql_dispatch) {
-    if ($db->num_rows($resql_dispatch) == 0) {
-        echo 'Nothing to do.'; exit;
-    };
-    while ($obj_dispatch = $db->fetch_object($resql_dispatch)) {
-        $sql_line = 'SELECT line.rowid, line.qty FROM ' . MAIN_DB_PREFIX . 'commande_fournisseurdet AS line'
-            .  ' WHERE line.fk_commande = ' . $obj_dispatch->fk_commande
-            .  ' AND line.fk_product = ' . $obj_dispatch->fk_product;
-        $resql_line = $db->query($sql_line);
-
-        // s’il y a plusieurs lignes avec le même produit sur cette commande fournisseur,
-        // on divise la ligne de dispatch en autant de lignes qu’on en a sur la commande pour le produit
-        // et on met la quantité de la ligne dans la limite du "budget" indiqué par dispatch.qty
-
-        $remaining_qty = $obj_dispatch->qty;
-        $first_iteration = true;
-        if (!$resql_line) {
-            echo 'Unable to find a matching supplier order line for dispatch #' . $obj_dispatch->rowid . "\n";
-            $errors[] = $sql_line;
-            $n_processed_rows++;
-            continue;
-        }
-        if ($db->num_rows($resql_line) == 0) continue;
-        while ($obj_line = $db->fetch_object($resql_line)) {
-            if (!$remaining_qty) break;
-            if (!$obj_line->rowid) {
-                continue;
-            }
-            $qty_for_line = min($remaining_qty, $obj_line->qty);
-            if ($first_iteration) {
-                $sql_attach = 'UPDATE ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch'
-                    . ' SET fk_commandefourndet = ' . $obj_line->rowid . ', qty = ' . $qty_for_line
-                    . ' WHERE rowid = ' . $obj_dispatch->rowid;
-                $first_iteration = false;
-            } else {
-                $sql_attach_values = array(
-                    $obj_dispatch->fk_commande,
-                    $obj_dispatch->fk_product,
-                    $obj_line->rowid,
-                    $qty_for_line,
-                    $obj_dispatch->fk_entrepot,
-                    $obj_dispatch->fk_user,
-                    $obj_dispatch->datec ? '"' . $db->escape($obj_dispatch->datec) . '"' : 'NULL',
-                    $obj_dispatch->comment ? '"' . $db->escape($obj_dispatch->comment) . '"' : 'NULL',
-                    $obj_dispatch->status ?: 'NULL',
-                    $obj_dispatch->tms ? '"' . $db->escape($obj_dispatch->tms) . '"': 'NULL',
-                    $obj_dispatch->batch ?: 'NULL',
-                    $obj_dispatch->eatby ? '"' . $db->escape($obj_dispatch->eatby) . '"': 'NULL',
-                    $obj_dispatch->sellby ? '"' . $db->escape($obj_dispatch->sellby) . '"': 'NULL'
-                );
-                $sql_attach_values = join(', ', $sql_attach_values);
-
-                $sql_attach = 'INSERT INTO ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch'
-                    . ' (fk_commande, fk_product, fk_commandefourndet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)'
-                    . ' VALUES (' . $sql_attach_values . ')';
-            }
-            $resql_attach = $db->query($sql_attach);
-            if ($resql_attach) {
-                $remaining_qty -= $qty_for_line;
-            } else {
-                $errors[] = $sql_attach;
-            }
-            $first_iteration = false;
-        }
-        $n_processed_rows++;
-
-        // report progress every 256th row
-        if (!($n_processed_rows & 0xff)) {
-            echo 'Processed ' . $n_processed_rows . ' rows with ' . count($errors) . ' errors…' . "\n";
-            flush();
-            ob_flush();
-        }
-    }
-} else {
-    echo 'Unable to find any dispatch without an fk_commandefourndet.' . "\n";
-    echo $sql_dispatch . "\n";
-}
-echo 'Fixed ' . $n_processed_rows . ' rows with ' . count($errors) . ' errors…' . "\n";
-echo 'DONE.' . "\n";
-echo '
'; - -if (count($errors)) { - $db->rollback(); - echo 'The transaction was rolled back due to errors: nothing was changed by the script.'; -} else { - $db->commit(); -} -$db->close(); - - -echo '

SQL queries with errors:

'; -echo ''; - diff --git a/htdocs/install/repair.php b/htdocs/install/repair.php index 4d3e28a38d3..b7f3f9eb5b6 100644 --- a/htdocs/install/repair.php +++ b/htdocs/install/repair.php @@ -78,6 +78,7 @@ print 'Option rebuild_product_thumbs (0 or \'test\' or \'confirmed\') is '.(GETP print 'Option force_disable_of_modules_not_found (0 or \'test\' or \'confirmed\') is '.(GETPOST('force_disable_of_modules_not_found','alpha')?GETPOST('force_disable_of_modules_not_found','alpha'):'0').'
'."\n"; print 'Option clean_perm_table (0 or \'test\' or \'confirmed\') is '.(GETPOST('clean_perm_table','alpha')?GETPOST('clean_perm_table','alpha'):'0').'
'."\n"; print 'Option force_utf8_on_tables, for mysql/mariadb only (0 or \'test\' or \'confirmed\') is '.(GETPOST('force_utf8_on_tables','alpha')?GETPOST('force_utf8_on_tables','alpha'):'0').'
'."\n"; +print 'Option repair_link_dispatch_lines_supplier_order_lines, (0 or \'test\' or \'confirmed\') is '.(GETPOST('repair_link_dispatch_lines_supplier_order_lines','alpha')?GETPOST('repair_link_dispatch_lines_supplier_order_lines','alpha'):'0').'
'."\n"; print '
'; print ''; @@ -1122,6 +1123,130 @@ if ($ok && GETPOST('force_utf8_on_tables','alpha')) } } +// +if ($ok && GETPOST('repair_link_dispatch_lines_supplier_order_lines')) { + /* + * This script is meant to be run when upgrading from a dolibarr version < 3.8 + * to a newer version. + * + * Version 3.8 introduces a new column in llx_commande_fournisseur_dispatch, which + * matches the dispatch to a specific supplier order line (so that if there are + * several with the same product, the user can specifically tell which products of + * which line were dispatched where). + * + * However when migrating, the new column has a default value of 0, which means that + * old supplier orders whose lines were dispatched using the old dolibarr version + * have unspecific dispatch lines, which are not taken into account by the new version, + * thus making the order look like it was never dispatched at all. + * + * This scripts sets this foreign key to the first matching supplier order line whose + * product (and supplier order of course) are the same as the dispatch’s. + * + * If the dispatched quantity is more than indicated on the order line (this happens if + * there are several order lines for the same product), it creates new dispatch lines + * pointing to the other order lines accordingly, until all the dispatched quantity is + * accounted for. + */ + echo ''; + echo ''; + + $sql_dispatch = 'SELECT * FROM ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch WHERE COALESCE(fk_commandefourndet, 0) = 0'; + $db->begin(); + $resql_dispatch = $db->query($sql_dispatch); + $n_processed_rows = 0; + $errors = array(); + if ($resql_dispatch) { + if ($db->num_rows($resql_dispatch) == 0) { + echo ''; + exit; + } + while ($obj_dispatch = $db->fetch_object($resql_dispatch)) { + $sql_line = 'SELECT line.rowid, line.qty FROM ' . MAIN_DB_PREFIX . 'commande_fournisseurdet AS line' + . ' WHERE line.fk_commande = ' . $obj_dispatch->fk_commande + . ' AND line.fk_product = ' . $obj_dispatch->fk_product; + $resql_line = $db->query($sql_line); + + // s’il y a plusieurs lignes avec le même produit sur cette commande fournisseur, + // on divise la ligne de dispatch en autant de lignes qu’on en a sur la commande pour le produit + // et on met la quantité de la ligne dans la limite du "budget" indiqué par dispatch.qty + + $remaining_qty = $obj_dispatch->qty; + $first_iteration = true; + if (!$resql_line) { + echo ''; + $errors[] = $sql_line; + $n_processed_rows++; + continue; + } + if ($db->num_rows($resql_line) == 0) continue; + while ($obj_line = $db->fetch_object($resql_line)) { + if (!$remaining_qty) break; + if (!$obj_line->rowid) { + continue; + } + $qty_for_line = min($remaining_qty, $obj_line->qty); + if ($first_iteration) { + $sql_attach = 'UPDATE ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch' + . ' SET fk_commandefourndet = ' . $obj_line->rowid . ', qty = ' . $qty_for_line + . ' WHERE rowid = ' . $obj_dispatch->rowid; + $first_iteration = false; + } else { + $sql_attach_values = array( + $obj_dispatch->fk_commande, + $obj_dispatch->fk_product, + $obj_line->rowid, + $qty_for_line, + $obj_dispatch->fk_entrepot, + $obj_dispatch->fk_user, + $obj_dispatch->datec ? '"' . $db->escape($obj_dispatch->datec) . '"' : 'NULL', + $obj_dispatch->comment ? '"' . $db->escape($obj_dispatch->comment) . '"' : 'NULL', + $obj_dispatch->status ?: 'NULL', + $obj_dispatch->tms ? '"' . $db->escape($obj_dispatch->tms) . '"': 'NULL', + $obj_dispatch->batch ?: 'NULL', + $obj_dispatch->eatby ? '"' . $db->escape($obj_dispatch->eatby) . '"': 'NULL', + $obj_dispatch->sellby ? '"' . $db->escape($obj_dispatch->sellby) . '"': 'NULL' + ); + $sql_attach_values = join(', ', $sql_attach_values); + + $sql_attach = 'INSERT INTO ' . MAIN_DB_PREFIX . 'commande_fournisseur_dispatch' + . ' (fk_commande, fk_product, fk_commandefourndet, qty, fk_entrepot, fk_user, datec, comment, status, tms, batch, eatby, sellby)' + . ' VALUES (' . $sql_attach_values . ')'; + } + $resql_attach = $db->query($sql_attach); + if ($resql_attach) { + $remaining_qty -= $qty_for_line; + } else { + $errors[] = $sql_attach; + } + $first_iteration = false; + } + $n_processed_rows++; + + // report progress every 256th row + if (!($n_processed_rows & 0xff)) { + echo '\n"; + flush(); + ob_flush(); + } + } + } else { + echo '\n"; + echo $sql_dispatch . "\n"; + } + echo '\n"; + echo '\n"; + + if (count($errors)) { + $db->rollback(); + echo ''; + } else { + $db->commit(); + } + $db->close(); + + echo ''; + echo ''; +} print '
Repair llx_commande_fournisseur_dispatch.fk_commandefourndet
Repair in progress. This may take a while.
Nothing to do.
Unable to find a matching supplier order line for dispatch #' . $obj_dispatch->rowid . '
Processed ' . $n_processed_rows . ' rows with ' . count($errors) . ' errors…' . "
Unable to find any dispatch without an fk_commandefourndet.' . "
Fixed ' . $n_processed_rows . ' rows with ' . count($errors) . ' errors…' . "
DONE.' . "
The transaction was rolled back due to errors: nothing was changed by the script.

SQL queries with errors:

' . join('
', $errors) . '
';