Debug import wizard

This commit is contained in:
Laurent Destailleur 2022-05-19 20:18:18 +02:00
parent 4b996f79a9
commit 2d16af1d31
4 changed files with 287 additions and 36 deletions

174
ChangeLog
View File

@ -10,20 +10,176 @@ For users:
---------------
NEW: PHP 8.1 compatibility
NEW: Support for recurring purchase invoices.
NEW: #20292 Include German public holidays
NEW: #17123 added ExtraFields for Stock Mouvement
NEW: #20609 : new massaction to assign a sale representatives on a selection of thirdparties
NEW: #20653 edit discount pourcentage for all lines in one shot
NEW: Accept 'auto' for ref of object on import of purchase order/proposal
NEW: Accountancy - Add more filters and info on page to bind accounting accounts
NEW: Accountancy - Add subledger account when we generate a transaction with a deposit invoice
NEW: Accountancy - Add a massaction to preselect an account (customer and supplier list)
NEW: ACE Editor is restored at same cursor position after a save.
NEW: Add "addMoreActionsButtons" hook to subscription form
NEW: Add an option in GUI to show a Quick add button into top menu bar
NEW: Module Recruitment - Add a public page with all list of open job positions.
NEW: Module Recruitment - Add a tab with list of application on the jobposition file.
NEW: Add a workflow to auto link contract on a ticket
NEW: Add column date of Signature on proposal list
NEW: Add column template invoice in invoice list
NEW: Add column "Total HT" to products array on document creation card
NEW: ADD configuration for text color of button action
NEW: Add constant to hide categories in TakePos
NEW: Add constant to show category description in TakePos
NEW: Add constant to show only the products in stock in TakePos
NEW: Add entity filter in exports
NEW: Show the event block on recurring invoices #20870
NEW: Add filter "opportunity status" on statistics of projects.
NEW: Add firstname, lastname and max number of attendees for module "Event Organization"
NEW: add margin info in proposal and order list
NEW: Add massaction "Edit Extrafield" for Product
NEW: Add more fields to detect duplicate during import of thirdparties
NEW: Add option to foce delivery on email for purchase order receipt to yes
NEW: Add param boder table for md theme
NEW: Add param color button action
NEW: Add possibility to create contract from invoice
NEW: Add possibility with constant MAIN_LOGIN_BADCHARUNAUTHORIZED to define bad character unauthorized into login name
NEW: Add private and public notes on tax files.
NEW: Add status "Obsolete" to KM articles
NEW: Add substitutions "user numbers"
NEW: Add the possibility to add sub-BOMs to BOM
NEW: allow a ticket to be automatically marked as read when created from backend.
NEW: allow cut&paste as real numeric value to excel
NEW: A public form to send a message and create a lead is available
NEW: automatically set totally received status in reception
NEW: Auto set invoice paid when adding credit not and remain to pay is 0
NEW: Availibility dictionnary has a new column unit and number
NEW: barcode rule to insert product in takepos
NEW: Can change value of AWP during the inventory
NEW: Can enter price with tax for predefined products on purchase objects
NEW: Can filter on a thirdparty on product statistics
NEW: Can removed doc templates from setup page of thirdparty
NEW: Can set the parent company during the creation of thirdparty (action=add of societe/card.php)
NEW: Can use ! to make a search that exclude a string
NEW: Change in theme colors does not need to use the refresh button
NEW: clean values and amount in FEC import
NEW: const MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND for mailing mass action
NEW: Contact filter project list
NEW: Create contract from invoice
NEW: create third-party with contact if not found on public ticket
NEW: Default value for MAIN_SECURITY_CSRF_WITH_TOKEN is now 2 (GET are also protected agains CSRF attacks)
NEW: deposit payment terms: add field into dictionary admin page to define default percentage of deposit.
NEW: Dictionaries - add possibility to manage countries in EEC
NEW: display errors in a message box after generating documents
NEW: Display physical and virtual stock of the products when creating OF from a BOM
NEW: Display product ref in "Object link" product tab for BOM
NEW: Enhance the import. Can use 'auto' for the ref (import of orders)
NEW: Events on Proposal to Return to Draft
NEW: Page to list expense report payments
NEW: JS inventory autocalc input
NEW: language support for more emailing target selectors
NEW: leave requests: add field into type dictionary to block request if balance is negative
NEW: MAIN_MAIL_AUTOCOPY_TO can accept several email and special keys
NEW: MAIN_SEARCH_CAT_OR_BY_DEFAULT const for search by category
NEW: Mass action "Close shipments"
NEW: Module website now supports the multicompany module
NEW: More mode for THEME_TOPMENU_DISABLE_IMAGE (2, 3, ...)
NEW: Add option to move checkbox column as first column on Thirdparty list (only few screens)
NEW: Add tabs for nets Bom
NEW: on redirect of page in website module, GET parameters are kept.
NEW: optional display warning icons on ticket list
NEW: option to default check "notify tier at creation" in ticket module
NEW: option update prices on proposal cloning
NEW: payment conditions enabling semi-automatic deposit creation (Issue #18439)
NEW: possibility to consume multiple batch
NEW: Reverse movement product consumption
NEW: Send email to the supplier order contact
NEW: New permission to report time on timesheet.
NEW: SEPA XML - option to place payment Type Info at Credit transfer Transaction level
NEW: Show number of votes into the label of tab "Results" of a survey
NEW: Show product reference in Takepos
NEW: Some core tables are created only at module activation
NEW: split consumption line on MO
NEW: stock filter in reassort lists
NEW: stock limit in stock export CSV
NEW: Sub-bom are availables
NEW: Supplier order - Show ref supplier of reception in linked object block
NEW: support user_modif in order
NEW: TakePos - pagination on search results
NEW: The backup tools has an "lowmemory" option for mysqldump on large database
NEW: The 'reposition' class works on ajax constantonoff that make redirects
NEW: Thirdparty - Add rules "customer accountancy code" is mandatory to validate invoice
NEW: thumbnail field in product list
NEW: total mark rate in list
NEW: uncheck "send message" by default on a ticket when private messages has been checked
NEW: VAT Report by month - Show detail by rate and also by code
NEW: Ticket triggers: allow to automatically send messages on new tickets
NEW: Accountancy - Add hidden feature for accounting reconciliation
NEW: Can store the session into database (instead of beeing managed by PHP)
Modules
NEW: Module Partnership Management
NEW: Experimental module Event Organization Management
NEW: Experimental module Workstations Management
NEW: Experimental module Partnership Management
For developers:
---------------
NEW: A lot of addition of hooks.
For developers or integrators:
------------------------------
NEW: dol_uncompress() supports more extensions (.gz, .bz2, .zstd). Only .zip was supported before.
NEW: Implement a generic method for Kaban views
NEW: Upgrade chartjs library to 3.7.1
NEW: update rank line is possible on API for customer invoices, sales orders and supplier invoice
NEW: stripe element with more gateways
NEW: solde() function evolution to be able to get solde until a chosen date
NEW: Suggest a way to run upgrade per entities.
NEW: Support html content for multiselect component.
NEW: ModuleBuilder - Add tabs view in module builder
NEW: ModuleBuilder - More feature that can be modifed after module generation
NEW: Hook getNomUrl available everywhere in tooltip of ref links
NEW: Identification of tr is possible with by attribute data-id on some pages
NEW: Import with select boxes V2
NEW: Can update rank of invoice, proposal and order lines with API update
NEW: Can use current entity filter on 'chkbxlst'
NEW: Creation of the function select_bom() used to display bom select list
NEW: add printFieldListWhere hook in product reassort card
NEW: Add trigger and event on completely received status change
NEW: Add utility function send backup by mail
NEW: add WordPress OAuth to save a token (not SSO)
NEW: A module can embed a sql script run at each Dolibarr upgrade
NEW: API Proposals - Add POST lines
NEW: API REST filter states by country
NEW: Add option INVOICEREC_SET_AUTOFILL_DATE_START/END
NEW: Add option MAIN_API_DEBUG to save API logs into a file
NEW: Add param to keep the robot=index meta tag on public pages
NEW: Add method hintindex() in database handlers.
NEW: add modifications for new function "$db->prefix()"
NEW: addMoreActionsButtonsList hook for button in list
NEW: Add API to get a template invoice
NEW: Standardize a lot of code.
NEW: #20736 Allow extrafields SQL filters on REST API product lookup
NEW: #19294 implement detailed timespent in task of project API
NEW: Add a protection into PHPunit to avoid to forget a var_dump
NEW: Add datem and type parameters to API to create movements
NEW: Add hidden option on contract PDF line to hide qty and price
NEW: Option MAIL_MASS_ACTION_ADD_LAST_IF_MAIN_DOC_NOT_FOUND to send last document in mass mailing action
NEW: Add hooks: selectContactListWhere hook, selectThirdpartyListWhere hook
NEW: TakePos - add hooks complete product display
NEW: TakePos - add hooks for cart display
NEW: TakePos - add hooks to complete ajax return array
NEW: Add hook before the public ticket list
NEW: Add hook doaction in takepos invoice
NEW: Add Hook for Notif
NEW: Add hook for more buttons
NEW: Add hook printFieldListWhere in "show_contacts" function
NEW: Add hook printFieldWhere in load_state_board function
NEW: Add hooks contact tab badge and hooks parameter for avoid conflicts
NEW: Add hook selectProductsListWhere in select_produits_list function
NEW: Add hooks in commercial index
NEW: Add hooks in customers and products boxes
NEW: Add hooks in thirdparty index page
NEW: Add hooks on project task time page
NEW: Add hooks on salaries and sociales card
NEW: Add hooks select product list and select thirdparty list function
NEW: Add hook to getSellPrice function
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:

View File

@ -10141,9 +10141,6 @@ class Form
window.parent.jQuery(\'#idfordialog'.$dol_openinpopup.'\').dialog(\'close\');
});';
$retstring .= '</script>';
// TODO @LDR for the save button, in action "add", set parent var to return data and close the window
//$retstring .= '<a onclick="javascript:$(\'#varforreturndialogid'.$dol_openinpopup.'\', window.parent.document).text(\'setid\');">setid</a> ';
//$retstring .= '<a onclick="javascript:$(\'#varforreturndialoglabel'.$dol_openinpopup.'\', window.parent.document).text(\'setlabel\');">setlabel</a>';
}
return $retstring;

View File

@ -317,6 +317,7 @@ if ($step == 4 && $action == 'select_model') {
}
}
$_SESSION["dol_array_match_file_to_database"] = $serialized_array_match_file_to_database;
$_SESSION['dol_array_match_file_to_database_select'] = $_SESSION["dol_array_match_file_to_database"];
}
}
if ($action == 'saveselectorder') {
@ -745,6 +746,7 @@ if ($step == 3 && $datatoimport) {
// STEP 4: Page to make matching between source file and database fields
if ($step == 4 && $datatoimport) {
//var_dump($_SESSION["dol_array_match_file_to_database_select"]);
$serialized_array_match_file_to_database = isset($_SESSION["dol_array_match_file_to_database_select"]) ? $_SESSION["dol_array_match_file_to_database_select"] : '';
$array_match_file_to_database = array();
$fieldsarray = explode(',', $serialized_array_match_file_to_database);
@ -793,7 +795,7 @@ if ($step == 4 && $datatoimport) {
$i = 1;
foreach ($arrayrecord as $key => $val) {
if ($val["type"] != -1) {
$fieldssource[$i]['example1'] = dol_trunc($val['val'], 24);
$fieldssource[$i]['example1'] = dol_trunc($val['val'], 128);
$i++;
}
}
@ -805,6 +807,11 @@ if ($step == 4 && $datatoimport) {
$minpos = min(count($fieldssource), count($fieldstarget));
//var_dump($array_match_file_to_database);
$initialloadofstep4 = false;
if (empty($_SESSION['dol_array_match_file_to_database_select'])) {
$initialloadofstep4 = true;
}
// Is it a first time in page (if yes, we must initialize array_match_file_to_database)
if (count($array_match_file_to_database) == 0) {
// This is first input in screen, we need to define
@ -837,6 +844,7 @@ if ($step == 4 && $datatoimport) {
}
$array_match_database_to_file = array_flip($array_match_file_to_database);
$fieldstarget_tmp = array();
$arraykeysfieldtarget = array_keys($fieldstarget);
$position = 0;
@ -876,6 +884,7 @@ if ($step == 4 && $datatoimport) {
//print $serialized_array_match_file_to_database;
//print $_SESSION["dol_array_match_file_to_database"];
//print $_SESSION["dol_array_match_file_to_database_select"];
//var_dump($array_match_file_to_database);exit;
// Now $array_match_file_to_database contains fieldnb(1,2,3...)=>fielddatabase(key in $array_match_file_to_database)
@ -903,7 +912,7 @@ if ($step == 4 && $datatoimport) {
print '<div class="underbanner clearboth"></div>';
print '<div class="fichecenter">';
print '<table width="100%" class="border tableforfield">';
print '<table class="centpercent border tableforfield">';
// Module
print '<tr><td class="titlefieldcreate">'.$langs->trans("Module").'</td>';
@ -1029,6 +1038,7 @@ if ($step == 4 && $datatoimport) {
print '<div id="left" class="connectedSortable">'."\n";
// List of source fields
$var = false;
$lefti = 1;
foreach ($fieldssource as $key => $val) {
show_elem($fieldssource, $key, $val, $var); // key is field number in source file
@ -1049,7 +1059,7 @@ if ($step == 4 && $datatoimport) {
print '</td><td width="50%" class="nopaddingrightimp">';
// List of target fields
// Set the list of all possible target fields in Dolibarr.
$optionsnotused = "";
$optionsall = array();
foreach ($fieldstarget as $code => $line) {
@ -1062,15 +1072,27 @@ if ($step == 4 && $datatoimport) {
if (!$line["imported"]) {
$optionsnotused .= $text;
}
$optionsall[$code] = array('label'=>$langs->trans($line["label"]), 'required'=>(empty($line["required"]) ? 0 : 1));
$optionsall[$code] = array('label'=>$langs->trans($line["label"]), 'required'=>(empty($line["required"]) ? 0 : 1), 'position'=>$line['position']);
}
// $optionsall is an array of all possible fields. key=>array('label'=>..., 'xxx')
$height = '32px'; //needs px for css height attribute below
$i = 0;
$mandatoryfieldshavesource = true;
//var_dump($fieldstarget);
//var_dump($optionsall);
//exit;
/*
var_dump($_SESSION['dol_array_match_file_to_database']);
var_dump($_SESSION['dol_array_match_file_to_database_select']);
var_dump($optionsall);
var_dump($fieldssource);
var_dump($fieldstarget);
*/
print '<table class="nobordernopadding centpercent tableimport">';
foreach ($fieldstarget as $code => $line) {
foreach ($fieldssource as $code => $line) { // $fieldssource is an array code=column num, line=content on first line for column in source file.
if ($i == $minpos) {
break;
}
@ -1085,8 +1107,17 @@ if ($step == 4 && $datatoimport) {
//print '<td class="nowraponall" style="font-weight: normal">=> '.img_object('', $entityicon).' '.$langs->trans($entitylang).'</td>';
print '<td class="nowraponall" style="font-weight: normal">=> </td>';
print '<td class="nowraponall" style="font-weight: normal">';
$modetoautofillmapping = 'session'; // Use setup in session
if ($initialloadofstep4) {
$modetoautofillmapping = 'guess';
}
//var_dump($_SESSION['dol_array_match_file_to_database_select']);
//var_dump($modetoautofillmapping);
//var_dump($_SESSION['dol_array_match_file_to_database']);
//var_dump($modetoautofillmapping);
print '<select id="selectorderimport_'.($i+1).'" class="targetselectchange minwidth300" name="select_'.$line["label"].'">';
if ($line["imported"]) {
print '<option value="-1">&nbsp;</option>';
@ -1095,14 +1126,50 @@ if ($step == 4 && $datatoimport) {
}
$j = 0;
foreach ($optionsall as $code => $val) {
$label = $val['required'] ? '<strong>' : '';
$label .= $val['label'];
$label .= $val['required'] ? '*</strong>' : '';
foreach ($optionsall as $tmpcode => $tmpval) { // Loop on each entry to add into each combo list.
$label = $tmpval['required'] ? '<strong>' : '';
$label .= $tmpval['label'];
$label .= $tmpval['required'] ? '*</strong>' : '';
print '<option value="'.$code.'"';
if ($j == $i) {
print ' selected';
// If we must guess how to fill the preselected value, and we can't because input value are not string
if ($modetoautofillmapping == 'guess' && $j == 0 && is_numeric($tmpval)) {
$modetoautofillmapping = 'orderoftargets';
}
print '<option value="'.$tmpcode.'"';
if ($modetoautofillmapping == 'orderoftargets') {
// The mode where we fill the preselected value of combo one by one in order of available targets fields in the declaration in descriptor file.
if ($j == $i) {
print ' selected';
}
} elseif ($modetoautofillmapping == 'guess') {
// The mode where we try to guess which value to preselect from the name in first column of source file.
$regs = array();
if (preg_match('/^(.+)\((.+)\)$/', $line['example1'], $regs)) {
$tmpstring1 = $regs[1];
$tmpstring2 = $regs[2];
} else {
$tmpstring1 = $line['example1'];
$tmpstring2 = '';
}
$tmpstring1 = str_replace('*', '', trim($tmpstring1));
$tmpstring2 = str_replace('*', '', trim($tmpstring2));
if ($tmpstring1 && ($tmpstring1 == $tmpcode || $tmpstring1 == $tmpval)) {
print ' selected';
// TODO Check that $tmpcode not already selected
} elseif ($tmpstring2 && ($tmpstring2 == $tmpcode || $tmpstring2 == $tmpval)) {
print ' selected';
// TODO Check that $tmpcode not already selected
}
} elseif ($modetoautofillmapping == 'session' && !empty($_SESSION['dol_array_match_file_to_database_select'])) {
$tmpselectioninsession = dolExplodeIntoArray($_SESSION['dol_array_match_file_to_database_select'], ',', '=');
//var_dump($code);
//var_dump($tmpselectioninsession);
//if ($tmpselectioninsession[$j] == $code) {
if ($tmpselectioninsession[($i+1)] == $tmpcode) {
print ' selected';
}
print ' data-debug="'.$tmpcode.'-'.$code.'-'.$j.'-'.$tmpselectioninsession[($i+1)].'"';
}
print ' data-html="'.dol_escape_htmltag($label).'"';
print '>';
@ -1122,7 +1189,7 @@ if ($step == 4 && $datatoimport) {
$htmltext .= $langs->trans("DataComeFromNoWhere").'<br>';
} else {
if (empty($objimport->array_import_convertvalue[0][$code])) { // If source file does not need convertion
$filecolumntoshow = $i + 1;
$filecolumntoshow = num2Alpha($i);
$htmltext .= $langs->trans("DataComeFromFileFieldNb", $filecolumntoshow).'<br>';
} else {
if ($objimport->array_import_convertvalue[0][$code]['rule'] == 'fetchidfromref') {
@ -1246,25 +1313,28 @@ if ($step == 4 && $datatoimport) {
// - Then we set to disabled all fields that are selected
print 'function setOptionsToDisabled() {'."\n";
print ' console.log("Remove the disabled flag everywhere");'."\n";
print ' $(".targetselectchange").not($( this )).find(\'option\').prop("disabled", false);'."\n";
print ' $("select.targetselectchange").not($( this )).find(\'option\').prop("disabled", false);'."\n"; // Enable all options
print ' arrayofselectedvalues = [];'."\n";
print ' $(".targetselectchange").each(function(){'."\n";
print ' $("select.targetselectchange").each(function(){'."\n";
print ' id = $(this).attr(\'id\')'."\n";
print ' value = $(this).val()'."\n";
print ' console.log("a selected value has been found for component "+id+" = "+value);'."\n";
print ' arrayofselectedvalues.push(value);'."\n";
print ' });'."\n";
print ' console.log("List of all selected values");'."\n";
print ' console.log(arrayofselectedvalues);'."\n";
print ' console.log("Set the disabled flag for every entry in arrayofselectedvalues");'."\n";
print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n";
print ' console.log("Set the option to disabled for every entry that is currently selected (so into arrayofselectedvalues)");'."\n";
print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n"; // Loop on each selected value
print ' if (value != -1) {'."\n";
print ' console.log("Process key="+key+" value="+value);'."\n";
print ' $(".targetselectchange").find(\'option[value="\'+value+\'"]\').prop("disabled", true);'."\n";
print ' console.log("Process key="+key+" value="+value+" to disable.");'."\n";
print ' $("select.targetselectchange").find(\'option[value="\'+value+\'"]:not(:selected)\').prop("disabled", true);'."\n"; // Set to disabled except if currently selected
print ' }'."\n";
print ' });'."\n";
print '};'."\n";
// Function to save the selection
// Function to save the selection in database
print 'function saveSelection() {'."\n";
print ' console.log(arrayofselectedvalues);'."\n";
print ' arrayselectedfields = [];'."\n";
print ' arrayselectedfields.push("0");'."\n";
print ' $.each( arrayofselectedvalues, function( key, value ) {'."\n";
@ -2255,14 +2325,14 @@ function show_elem($fieldssource, $pos, $key, $var, $nostyle = '')
print '<td class="nocellnopadding" width="16" style="font-weight: normal">';
// The image must have the class 'boxhandle' beause it's value used in DOM draggable objects to define the area used to catch the full object
//print img_picto($langs->trans("MoveField", $pos), 'grip_title', 'class="boxhandle" style="cursor:move;"');
print img_picto($langs->trans("Field").' '.$pos, 'file', 'class="pictofixedwith"');
print img_picto($langs->trans("Column").' '.num2Alpha($pos - 1), 'file', 'class="pictofixedwith"');
print '</td>';
if (isset($fieldssource[$pos]['imported']) && $fieldssource[$pos]['imported'] == false) {
print '<td class="nowraponall boxtdunused" style="font-weight: normal">';
} else {
print '<td class="nowraponall" style="font-weight: normal">';
}
print $langs->trans("Field").' '.$pos;
print $langs->trans("Column").' '.num2Alpha($pos - 1).' (#'.$pos.')';
if (empty($fieldssource[$pos]['example1'])) {
$example = $fieldssource[$pos]['label'];
} else {
@ -2287,6 +2357,20 @@ function show_elem($fieldssource, $pos, $key, $var, $nostyle = '')
}
/**
* Return a numeric into an Excel like column number
*
* @param string $n Numeric value
* @return string Column in Excel format
*/
function num2Alpha($n)
{
for ($r = ""; $n >= 0; $n = intval($n / 26) - 1)
$r = chr($n%26 + 0x41) . $r;
return $r;
}
/**
* Return not used field number
*

View File

@ -706,7 +706,21 @@ if (empty($reshook)) {
// TODO @LDR
if ($dol_openinpopup && $backtopagejsfields) {
print 'TODO Set js var of parent with id, then close popup.';
// TODO @LDR for the save button, in action "add", set parent var to return data and close the window
//$retstring .= '<a onclick="javascript:$(\'#varforreturndialogid'.$dol_openinpopup.'\', window.parent.document).text(\'setid\');">setid</a> ';
//$retstring .= '<a onclick="javascript:$(\'#varforreturndialoglabel'.$dol_openinpopup.'\', window.parent.document).text(\'setlabel\');">setlabel</a>';
$retstring = '';
$retstring .= '<script>';
$retstring .= 'jQuery(document).ready() {
console.log(\'We execute action to create. We save id and go back - '.$dol_openinpopup.'\');
console.log(\'id = '.$object->id.'\');
$(\'#varforreturndialogid'.$dol_openinpopup.'\', window.parent.document).text(\'newid\');
$(\'#varforreturndialoglabel'.$dol_openinpopup.'\', window.parent.document).text(\'newlabel\');
//window.parent.jQuery(\'#idfordialog'.$dol_openinpopup.'\').dialog(\'close\');
});';
$retstring .= '</script>';
$retstring .= 'Set js var of parent with id of object created then close popup.';
print $retstring;
exit;
} else {
header("Location: ".$url);