2
0
forked from Wavyzz/dolibarr

Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
ldestailleur
2025-05-12 09:27:58 +02:00
7 changed files with 91 additions and 33 deletions

View File

@@ -452,6 +452,7 @@ if ($resql) {
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_system as a";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_country as c ON a.fk_country = c.rowid AND c.active = 1";
$sql .= " WHERE a.active = 1";
$sql .= " ORDER BY c.code, a.pcg_version";
dol_syslog("accountancy/admin/account.php sql=".$sql);
@@ -463,9 +464,11 @@ if ($resql) {
while ($i < $numbis) {
$obj = $db->fetch_object($resqlchart);
if ($obj) {
print '<option value="'.$obj->rowid.'"';
$labeltoshow = $obj->country_code.' - '.$obj->pcg_version.' - '.$obj->label;
$htmltoshow = picto_from_langcode($obj->country_code).' '.$obj->country_code.' - '.$obj->pcg_version.' - '.$obj->label;
print '<option value="'.$obj->rowid.'" data-html="'.dolPrintHTMLForAttribute($htmltoshow).'"';
print ($pcgver == $obj->rowid) ? ' selected' : '';
print '>'.$obj->pcg_version.' - '.$obj->label.' - ('.$obj->country_code.')</option>';
print '>'.$labeltoshow.'</option>';
}
$i++;
}

View File

@@ -940,7 +940,7 @@ class Form
public function select_country($selected = '', $htmlname = 'country_id', $htmloption = '', $maxlength = 0, $morecss = 'minwidth300', $usecodeaskey = '', $showempty = 1, $disablefavorites = 0, $addspecialentries = 0, $exclude_country_code = array(), $hideflags = 0, $forcecombo = 0)
{
// phpcs:enable
global $conf, $langs, $mysoc;
global $langs, $mysoc;
$langs->load("dict");
@@ -9472,13 +9472,13 @@ class Form
* @param int<0,1> $translate Translate and encode value
* @param int|string $width Force width of select box. May be used only when using jquery couch. Example: 250, '95%'
* @param string $moreattrib Add more options on select component. Example: 'disabled'
* @param string $elemtype Type of element we show ('category', ...). Will execute a formatting function on it. To use in readonly mode if js component support HTML formatting.
* @param string $nu Not used
* @param string $placeholder String to use as placeholder
* @param int<-1,1> $addjscombo Add js combo
* @return string HTML multiselect string
* @see selectarray(), selectArrayAjax(), selectArrayFilter()
*/
public static function multiselectarray($htmlname, $array, $selected = array(), $key_in_label = 0, $value_as_key = 0, $morecss = '', $translate = 0, $width = 0, $moreattrib = '', $elemtype = '', $placeholder = '', $addjscombo = -1)
public static function multiselectarray($htmlname, $array, $selected = array(), $key_in_label = 0, $value_as_key = 0, $morecss = '', $translate = 0, $width = 0, $moreattrib = '', $nu = '', $placeholder = '', $addjscombo = -1)
{
global $conf, $langs;
$out = '';
@@ -9498,6 +9498,8 @@ class Form
}
}
$out .= '<span class="multiselectarray'.$htmlname.'">';
// We need a hidden field because when using the multiselect, if we unselect all, there is no
// variable submitted at all, so no way to make a difference between variable not submitted and variable
// submitted to nothing.
@@ -9544,35 +9546,38 @@ class Form
}
$out .= '</select>' . "\n";
$out .= '</span>';
// Add code for jquery to use multiselect
if (!empty($conf->use_javascript_ajax) && getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') || defined('REQUIRE_JQUERY_MULTISELECT')) {
$out .= "\n" . '<!-- JS CODE TO ENABLE select for id ' . $htmlname . ', addjscombo=' . $addjscombo . ' -->';
$out .= "\n" . '<script nonce="' . getNonce() . '">' . "\n";
if ($addjscombo == 1) {
$tmpplugin = !getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : $conf->global->MAIN_USE_JQUERY_MULTISELECT;
$out .= 'function formatResult(record, container) {' . "\n";
$tmpplugin = getDolGlobalString('MAIN_USE_JQUERY_MULTISELECT', (defined('REQUIRE_JQUERY_MULTISELECT') ? constant('REQUIRE_JQUERY_MULTISELECT') : 'select2'));
// If property data-html set, we decode html entities and use this.
// Note that HTML content must have been sanitized from js with dol_escape_htmltag(xxx, 0, 0, '', 0, 1) when building the select option.
// TODO Move this into common js ?
$out .= 'function formatResult(record, container) {' . "\n";
$out .= ' if ($(record.element).attr("data-html") != undefined && typeof htmlEntityDecodeJs === "function") {';
//$out .= ' console.log("aaa");';
$out .= ' return htmlEntityDecodeJs($(record.element).attr("data-html"));';
$out .= ' }'."\n";
$out .= ' return record.text;';
$out .= '}' . "\n";
$out .= 'function formatSelection(record) {' . "\n";
if ($elemtype == 'category') {
$out .= 'return \'<span><img src="' . DOL_URL_ROOT . '/theme/eldy/img/object_category.png"> \'+record.text+\'</span>\';';
} else {
$out .= 'return record.text;';
}
$out .= ' return record.text;';
$out .= '}' . "\n";
// Load the select2 enhancer
//$out .= 'console.log(\'addjscombo=1 for htmlname=' . dol_escape_js($htmlname) . '\');';
$out .= '$(document).ready(function () {
$(\'#' . dol_escape_js($htmlname) . '\').' . $tmpplugin . '({';
if ($placeholder) {
$out .= '
placeholder: {
id: \'-1\',
text: \'' . dol_escape_js($placeholder) . '\'
text: \''.dol_escape_js($placeholder).'\'
},';
}
$out .= ' dir: \'ltr\',
@@ -9580,7 +9585,7 @@ class Form
dropdownCssClass: \'' . dol_escape_js($morecss) . '\', /* Line to add class on the new <span class="select2-selection...> tag (ok with multiselect). Need full version of select2. */
// Specify format function for dropdown item
formatResult: formatResult,
templateResult: formatResult, /* For 4.0 */
templateResult: formatResult, /* For 4.0 */
escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
// Specify format function for selected item
formatSelection: formatSelection,
@@ -9588,7 +9593,7 @@ class Form
language: (typeof select2arrayoflanguage === \'undefined\') ? \'en\' : select2arrayoflanguage
});
/* Add also morecss to the css .select2 that is after the #htmlname, for component that are show dynamically after load, because select2 set
/* Add also morecss to the css .select2 that is after the #htmlname, for component that are shown dynamically after load, because select2 set
the size only if component is not hidden by default on load */
$(\'#' . dol_escape_js($htmlname) . ' + .select2\').addClass(\'' . dol_escape_js($morecss) . '\');
});' . "\n";

View File

@@ -2753,12 +2753,12 @@ function dolButtonToOpenExportDialog($name, $label, $buttonstring, $exportSiteNa
* @param string $disabled Disabled text
* @param string $morecss More CSS
* @param string $jsonopen Some JS code to execute on click/open of popup
* @param string $backtopagejsfields The back to page must be managed using javascript instead of a redirect.
* @param string $jsonclose Some JS code to execute on close of popup
* Value is 'keyforpopupid:Name_of_html_component_to_set_with id,Name_of_html_component_to_set_with_label'
* @param string $accesskey A key to use shortcut
* @return string HTML component with button
*/
function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $jsonopen = '', $backtopagejsfields = '', $accesskey = '')
function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $disabled = '', $morecss = 'classlink button bordertransp', $jsonopen = '', $jsonclose = '', $accesskey = '')
{
global $conf;
@@ -2770,23 +2770,26 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di
$out = '';
/* canceled
$backtopagejsfieldsid = '';
$backtopagejsfieldslabel = '';
$backtopagejsfieldshtml = '';
if ($backtopagejsfields) {
$tmpbacktopagejsfields = explode(':', $backtopagejsfields);
if (empty($tmpbacktopagejsfields[1])) { // If the part 'keyforpopupid:' is missing, we add $name for it.
$backtopagejsfields = $name.":".$backtopagejsfields;
$tmp2backtopagejsfields = explode(',', $tmpbacktopagejsfields[0]);
} else {
$tmp2backtopagejsfields = explode(',', $tmpbacktopagejsfields[1]);
}
$backtopagejsfieldsid = empty($tmp2backtopagejsfields[0]) ? '' : $tmp2backtopagejsfields[0];
$backtopagejsfieldslabel = empty($tmp2backtopagejsfields[1]) ? '' : $tmp2backtopagejsfields[1];
$backtopagejsfieldshtml = empty($tmp2backtopagejsfields[2]) ? '' : $tmp2backtopagejsfields[2];
$url .= '&backtopagejsfields='.urlencode($backtopagejsfields);
}
*/
//print '<input type="submit" class="button bordertransp"'.$disabled.' value="'.dol_escape_htmltag($langs->trans("MediaFiles")).'" name="file_manager">';
$out .= '<!-- a link for button to open url into a dialog popup with backtopagejsfields = '.$backtopagejsfields.' -->';
$out .= '<!-- a link for button to open url into a dialog popup -->';
$out .= '<a '.($accesskey ? ' accesskey="'.$accesskey.'"' : '').' class="cursorpointer reposition button_'.$name.($morecss ? ' '.$morecss : '').'"'.$disabled.' title="'.dol_escape_htmltag($label).'"';
if (empty($conf->use_javascript_ajax)) {
$out .= ' href="'.DOL_URL_ROOT.$url.'" target="_blank"';
@@ -2798,12 +2801,15 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di
$out .= '>'.$buttonstring.'</a>';
if (!empty($conf->use_javascript_ajax)) {
// Add code to open url using the popup. Add also hidden field to retrieve the returned variables
// Add code to open url using the popup.
$out .= '<!-- code to open popup and variables to retrieve returned variables -->';
$out .= '<div id="idfordialog'.$name.'" class="hidden">'.(getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for dialog' : '').'</div>';
/* canceled
// Add also hidden field to retrieve the returned variables
$out .= '<div id="varforreturndialogid'.$name.'" class="hidden">'.(getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for returned id' : '').'</div>';
$out .= '<div id="varforreturndialoglabel'.$name.'" class="hidden">'.(getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for returned label' : '').'</div>';
$out .= '<div id="varforreturndialoghtml'.$name.'" class="hidden">'.(getDolGlobalInt('MAIN_OPTIMIZEFORTEXTBROWSER') < 2 ? 'div for returned html' : '').'</div>';
*/
$out .= '<!-- Add js code to open dialog popup on dialog -->';
$out .= '<script nonce="'.getNonce().'" type="text/javascript">
jQuery(document).ready(function () {
@@ -2821,15 +2827,24 @@ function dolButtonToOpenUrlInDialogPopup($name, $label, $buttonstring, $url, $di
console.log("open popup name='.$name.', backtopagejsfields='.$backtopagejsfields.'");
},
close: function (event, ui) {
console.log("Popup is closed.");
/* to remove
var returnedid = jQuery("#varforreturndialogid'.$name.'").text();
var returnedlabel = jQuery("#varforreturndialoglabel'.$name.'").text();
console.log("popup has been closed. returnedid (js var defined into parent page)="+returnedid+" returnedlabel="+returnedlabel);
var returnedhtml = jQuery("#varforreturndialoghtml'.$name.'").text();
console.log("popup has been closed.");
console.log("returnedid="+returnedid+", returnedlabel="+returnedlabel+", returnedhtml="+returnedhtml+". We save this value into main page.");
if (returnedid != "" && returnedid != "div for returned id") {
jQuery("#'.(empty($backtopagejsfieldsid) ? "none" : $backtopagejsfieldsid).'").val(returnedid);
}
if (returnedlabel != "" && returnedlabel != "div for returned label") {
jQuery("#'.(empty($backtopagejsfieldslabel) ? "none" : $backtopagejsfieldslabel).'").val(returnedlabel);
}
if (returnedhtml != "" && returnedhtml != "div for returned html") {
jQuery("#'.(empty($backtopagejsfieldshtml) ? "none" : $backtopagejsfieldshtml).'").val(returnedlabel);
}
*/
'.(empty($jsonclose) ? '' : $jsonclose.';').'
}
});

View File

@@ -357,9 +357,9 @@ if ($nolinesbefore) {
$newbutton = '<span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("NewProduct").'"></span>';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
// @FIXME Not working yet
$tmpbacktopagejsfields = 'addproduct:id,search_id';
$jsonclode = 'jsRefreshProductCombo';
// @phan-suppress-next-line PhanPluginSuspiciousParamOrder
print dolButtonToOpenUrlInDialogPopup('addproduct', $langs->transnoentitiesnoconv('AddProduct'), $newbutton, $url, '', '', $tmpbacktopagejsfields);
print dolButtonToOpenUrlInDialogPopup('addproduct', $langs->transnoentitiesnoconv('AddProduct'), $newbutton, $url, '', '', $jsonclode);
} else {
print '<a href="'.DOL_URL_ROOT.'/product/card.php?action=create&type=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id).'" title="'.dol_escape_htmltag($langs->trans("NewProduct")).'"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a>';
}
@@ -369,9 +369,9 @@ if ($nolinesbefore) {
$newbutton = '<span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("NewService").'"></span>';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
// @FIXME Not working yet
$tmpbacktopagejsfields = 'addproduct:id,search_id';
$jsonclode = 'jsRefreshServiceCombo';
// @phan-suppress-next-line PhanPluginSuspiciousParamOrder
print dolButtonToOpenUrlInDialogPopup('addproduct', $langs->transnoentitiesnoconv('AddService'), $newbutton, $url, '', '', $tmpbacktopagejsfields);
print dolButtonToOpenUrlInDialogPopup('addproduct', $langs->transnoentitiesnoconv('AddService'), $newbutton, $url, '', '', $jsonclode);
} else {
print '<a href="'.DOL_URL_ROOT.'/product/card.php?action=create&type=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$object->id).'" title="'.dol_escape_htmltag($langs->trans("NewService")).'"><span class="fa fa-plus-circle valignmiddle paddingleft"></span></a>';
}

View File

@@ -2433,7 +2433,8 @@ function top_menu_user($hideloginname = 0, $urllogout = '')
// Defined the links for bottom of card
$profilLink = '<a accesskey="u" href="'.DOL_URL_ROOT.'/user/card.php?id='.$user->id.'" class="button-top-menu-dropdown" title="'.dol_escape_htmltag($langs->trans("YourUserFile").' ('.$stringforfirstkey.' u)').'"><i class="fa fa-user"></i> '.$langs->trans("Card").'</a>';
$urltovirtualcard = '/user/virtualcard.php?id='.((int) $user->id);
$virtuelcardLink = dolButtonToOpenUrlInDialogPopup('publicvirtualcardmenu', $langs->transnoentitiesnoconv("PublicVirtualCardUrl").(is_object($user) ? ' - '.$user->getFullName($langs) : '').' ('.$stringforfirstkey.' v)', img_picto($langs->trans("PublicVirtualCardUrl").' ('.$stringforfirstkey.' v)', 'card', ''), $urltovirtualcard, '', 'button-top-menu-dropdown marginleftonly nohover', "closeTopMenuLoginDropdown()", '', 'v');
$jsonopen = "closeTopMenuLoginDropdown()";
$virtuelcardLink = dolButtonToOpenUrlInDialogPopup('publicvirtualcardmenu', $langs->transnoentitiesnoconv("PublicVirtualCardUrl").(is_object($user) ? ' - '.$user->getFullName($langs) : '').' ('.$stringforfirstkey.' v)', img_picto($langs->trans("PublicVirtualCardUrl").' ('.$stringforfirstkey.' v)', 'card', ''), $urltovirtualcard, '', 'button-top-menu-dropdown marginleftonly nohover', $jsonopen, '', 'v');
$logoutLink = '<a accesskey="l" href="'.$urllogout.'" class="button-top-menu-dropdown" title="'.dol_escape_htmltag($langs->trans("Logout").' ('.$stringforfirstkey.' l)').'"><i class="fa fa-sign-out-alt pictofixedwidth"></i><span class="hideonsmartphone">'.$langs->trans("Logout").'</span></a>';
$profilName = $user->getFullName($langs).' ('.$user->login.')';

View File

@@ -165,7 +165,6 @@ if (isModEnabled('multicompany') && !empty($conf->stripeconnect->enabled) && is_
$ret = $mc->switchEntity($key);
}
// list of action
$stripe = new Stripe($db);
// Subject
@@ -180,6 +179,10 @@ dol_syslog("***** Stripe IPN was called with event->type=".$event->type." servic
dol_syslog("***** Stripe IPN was called with event->type=".$event->type." service=".$service, LOG_DEBUG, 0, '_payment');
// Add a delay to be sure that any Stripe action from webhooks are executed after interactive actions
sleep(2);
if ($event->type == 'payout.created' && getDolGlobalString('STRIPE_AUTO_RECORD_PAYOUT')) {
// When a payout is created by Stripe to transfer money to your account
dol_syslog("object = ".var_export($event->data, true));

View File

@@ -2405,7 +2405,12 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
print '</td>';
print '</tr>';
print '<tr><td>'.$form->editfieldkey('CustomerCode', 'customer_code', '', $object, 0).'</td><td colspan="3">';
$colspan = 0;
if ($conf->browser->layout == 'phone') {
$colspan = 3;
}
print '<tr><td>'.$form->editfieldkey('CustomerCode', 'customer_code', '', $object, 0).'</td><td'.($colspan ? ' colspan="'.$colspan.'"': '').'>';
print '<table class="nobordernopadding"><tr><td>';
$tmpcode = $object->code_client ?? '';
if (empty($tmpcode) && !empty($modCodeClient->code_auto)) {
@@ -2422,7 +2427,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
print '</tr><tr>';
}
print '<td>'.$form->editfieldkey('SupplierCode', 'supplier_code', '', $object, 0).'</td><td colspan="3">';
print '<td>'.$form->editfieldkey('SupplierCode', 'supplier_code', '', $object, 0).'</td><td'.($colspan ? ' colspan="'.$colspan.'"': '').'>';
if ((isModEnabled("fournisseur") && $user->hasRight('fournisseur', 'lire') && !getDolGlobalString('MAIN_USE_NEW_SUPPLIERMOD')) || (isModEnabled("supplier_order") && $user->hasRight('supplier_order', 'lire')) || (isModEnabled("supplier_invoice") && $user->hasRight('supplier_invoice', 'lire'))) {
print '<table class="nobordernopadding"><tr><td>';
@@ -2753,7 +2758,32 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
foreach ($cats as $cat) {
$arrayselected[] = $cat->id;
}
print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('custcats', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
print img_picto('', 'category', 'class="pictofixedwidth"');
$htmlname = 'custcats';
print $form->multiselectarray($htmlname, $cate_arbo, $arrayselected, 0, 0, 'minwidth100 widthcentpercentminusxx', 0, 0);
if (getDolGlobalString('CATEGORY_EDIT_IN_POPUP_NOT_IN_MENU')) {
// Add html code to add the edit button and go back
$jsonclose = 'doJsCodeAfterPopupClose'.$htmlname.'()';
$s = dolButtonToOpenUrlInDialogPopup($htmlname, $langs->transnoentitiesnoconv("Tags"), img_picto('', 'add', 'class="editfielda"'), '/categories/categorie_list.php?type='.Categorie::TYPE_CUSTOMER, '', '', '', $jsonclose);
print $s;
// Add js code to add the edit button and go back
print '<script>function doJsCodeAfterPopupClose'.$htmlname.'() {
console.log("doJsCodeAfterPopupClose'.$htmlname.' has been called, we refresh the combo content + refresh select2...");
// Call an ajax to reload values and update the select
// $("#'.dol_escape_js($htmlname).'").append(new Option("Option 4", "4"));
// Refresh select2 to take account of new values (enough for small change)
$("#'.dol_escape_js($htmlname).'").trigger("change");
// Alternative if change in select is complex
/*
$("#'.dol_escape_js($htmlname).'").select2("destroy");
$("#'.dol_escape_js($htmlname).'").select2();
*/
}</script>';
}
print "</td></tr>";
// Supplier
@@ -2767,7 +2797,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
foreach ($cats as $cat) {
$arrayselected[] = $cat->id;
}
print img_picto('', 'category', 'class="pictofixedwidth"').$form->multiselectarray('suppcats', $cate_arbo, $arrayselected, 0, 0, 'quatrevingtpercent widthcentpercentminusx', 0, 0);
print img_picto('', 'category', 'class="pictofixedwidth"');
print $form->multiselectarray('suppcats', $cate_arbo, $arrayselected, 0, 0, 'minwidth100 widthcentpercentminusxx', 0, 0);
print "</td></tr>";
}
}