Quellcode durchsuchen

Debug import wizard

Laurent Destailleur vor 3 Jahren
Ursprung
Commit
2d16af1d31
4 geänderte Dateien mit 288 neuen und 37 gelöschten Zeilen
  1. 165 9
      ChangeLog
  2. 0 3
      htdocs/core/class/html.form.class.php
  3. 108 24
      htdocs/imports/import.php
  4. 15 1
      htdocs/societe/card.php

+ 165 - 9
ChangeLog

@@ -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:

+ 0 - 3
htdocs/core/class/html.form.class.php

@@ -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;

+ 108 - 24
htdocs/imports/import.php

@@ -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>' : '';
-
-			print '<option value="'.$code.'"';
-			if ($j == $i) {
-				print ' selected';
+		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>' : '';
+
+			// 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
  *

+ 15 - 1
htdocs/societe/card.php

@@ -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);