2
0
forked from Wavyzz/dolibarr

Compare commits

...

16 Commits

Author SHA1 Message Date
splohmer
87c4ed00a3 FIX not possible to search for billed and not billed supplier orders in the list (#35680)
* FIX not possible to search for billed and not billed supplier orders in the list

as the current implemenation the $billed var can be either 0 or 1 but  cannot be empty if both should be searched. This prevents searching an supplier order through the general search functionality as it finds only not yet billed orders.

* Update list.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2025-10-08 10:39:18 +02:00
Nicolas Domenech
16929b4d89 Fix remove double logo in page subscriptionok (#35672)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2025-10-08 10:32:22 +02:00
Frédéric FRANCE
6c738b6503 fix CI v22 (#35667) 2025-10-07 18:58:38 +02:00
ldestailleur
685119cdde Fix option MAIN_SHOW_TECHNICAL_ID borken on projects 2025-10-07 16:02:54 +02:00
ldestailleur
8e3a7714b8 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2025-10-06 18:00:45 +02:00
ldestailleur
0a914f437a Merge branch '20.0' of git@github.com:Dolibarr/dolibarr.git into 21.0 2025-10-06 18:00:19 +02:00
Frédéric FRANCE
e486707236 ficx backtopage (#35659) 2025-10-06 17:59:11 +02:00
ldestailleur
39d7ffae8d FIX #33741 FIX #35632 2025-10-06 14:05:01 +02:00
John BOTELLA
cecc1831a2 Fix llx header body class (#35653) 2025-10-06 12:34:20 +02:00
Frédéric FRANCE
56fed15f5b fix CI v22 (#35648)
* Update price_parser.class.php

* Update price_parser.class.php

* Update list.php

already set before the loop
2025-10-06 01:33:51 +02:00
Frédéric FRANCE
5342cb87ea remove subtotal from .gitignore (#35647) 2025-10-05 18:16:17 +02:00
PsyCrow
67500e1b99 Update list.php (#35630)
Fix #35629 PHP Warning: Undefined array key "f.total_localtax2"  in linst.php

$totalarray['val']['f.total_localtax2'] not initialized
2025-10-04 13:28:04 +02:00
Alexandre R
d7063122a2 FIX invoices payments on multicurrencies being converted as int (#35622)
* fix invoices payments on multicurrencies being converted as int

* Update paiement.php

---------

Co-authored-by: A.R <alexandre.rivas69@gmail.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
2025-10-03 19:04:49 +02:00
kkhelifa-opendsi
404ad0e876 FIX: substitutions on subject of the sent email reminder of the event (#35621) 2025-10-03 19:01:10 +02:00
Frédéric FRANCE
3b3c5a53d3 fix example captcha (#35620)
* fix example captcha

* Update modCaptchaStandard.class.php
2025-10-03 16:06:54 +02:00
ldestailleur
aef314264c Fix CSS 2025-10-03 13:57:38 +02:00
14 changed files with 100 additions and 99 deletions

1
htdocs/.gitignore vendored
View File

@@ -21,7 +21,6 @@
/cabinetmed*
/webmail*
/conf/conf.php
/subtotal*
/abricot*
/nomenclature*
/of/

View File

@@ -2725,6 +2725,7 @@ class ActionComm extends CommonObject
//Topic
$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->transnoentities('EventReminder'));
$sendTopic = make_substitutions($sendTopic, $substitutionarray);
// Recipient
$recipient = new User($this->db);

View File

@@ -426,9 +426,9 @@ if ($socid > 0) {
*/
if ($isCustomer && !$isSupplier) {
$newcardbutton = dolGetButtonTitle($langs->trans("NewGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=0&backtopage='.$_SERVER["PHP_SELF"].'?id='.$id.'&token='.newToken());
$newcardbutton = dolGetButtonTitle($langs->trans("NewGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$id).'&token='.newToken());
} elseif (!$isCustomer && $isSupplier) {
$newcardbutton = dolGetButtonTitle($langs->trans("NewGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=1&backtopage='.$_SERVER["PHP_SELF"].'?id='.$id.'&token='.newToken());
$newcardbutton = dolGetButtonTitle($langs->trans("NewGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$id).'&token='.newToken());
} else {
$newcardbutton = '';
}
@@ -436,7 +436,7 @@ if ($socid > 0) {
print load_fiche_titre($langs->trans("DiscountStillRemaining"), $newcardbutton);
if ($isCustomer) {
$newcardbutton = dolGetButtonTitle($langs->trans("NewClientGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=0&backtopage='.$_SERVER["PHP_SELF"].'?id='.$id.'&token='.newToken());
$newcardbutton = dolGetButtonTitle($langs->trans("NewClientGlobalDiscount"), '', 'fa fa-plus-circle', $_SERVER['PHP_SELF'].'?action=create_remise&id='.$id.'&discount_type=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?id='.$id).'&token='.newToken());
if ($isSupplier) {
print '<div class="fichecenter">';
print '<div class="fichehalfleft fichehalfleft-lg">';

View File

@@ -4186,7 +4186,7 @@ if ($action == 'create') {
if (getDolGlobalString('INVOICE_USE_SITUATION')) {
print '<div class="listofinvoicetype"><div class="">';
$tmp = '<input type="radio" name="type" id="radio_situation" value="0" disabled> ';
$text = $tmp.'<label>'.$langs->trans("InvoiceSituationAsk").'</label> ';
$text = $tmp.'<label class="opacitymedium">'.$langs->trans("InvoiceSituationAsk").'</label> ';
$desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceFirstSituationDesc").'<br><br>'.$langs->trans("YouMustCreateInvoiceFromThird"), 1, 'help', 'nowraponall', 0, 3, 'firstsituationonsmartphone');
print $desc;
print '</div></div>'."\n";

View File

@@ -179,7 +179,7 @@ if (empty($reshook)) {
}
}
$formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOSTINT($key));
$formquestion[$i++] = array('type' => 'hidden', 'name' => $key, 'value' => GETPOST($key));
}
}

View File

@@ -82,6 +82,7 @@ class modCaptchaStandard extends ModeleCaptcha
global $db, $conf, $langs, $user;
$generator = new modGeneratePassStandard($db, $conf, $langs, $user);
$generator->length = '5';
$example = $generator->getExample();
if (function_exists("imagecreate") && function_exists("imagepng")) {
@@ -89,7 +90,7 @@ class modCaptchaStandard extends ModeleCaptcha
if (!$img) {
return "Problem with GD creation";
}
//$background_color = imagecolorallocate($img, 250, 250, 250);
$background_color = imagecolorallocate($img, 250, 250, 250); // do not comment this line
$ecriture_color = imagecolorallocate($img, 0, 0, 0);
imagestring($img, 4, 15, 8, $example, $ecriture_color);

View File

@@ -134,7 +134,7 @@ $search_multicurrency_montant_ht = GETPOST('search_multicurrency_montant_ht', 'a
$search_multicurrency_montant_tva = GETPOST('search_multicurrency_montant_tva', 'alpha');
$search_multicurrency_montant_ttc = GETPOST('search_multicurrency_montant_ttc', 'alpha');
$optioncss = GETPOST('optioncss', 'alpha');
$billed = GETPOSTINT('billed');
$billed = GETPOST('billed', 'int'); // Value '' must be possible
$search_project_ref = GETPOST('search_project_ref', 'alpha');
$search_btn = GETPOST('button_search', 'alpha');
$search_remove_btn = GETPOST('button_removefilter', 'alpha');

View File

@@ -1550,7 +1550,7 @@ $totalarray['val'] = array();
$totalarray['val']['f.total_ht'] = 0;
$totalarray['val']['f.total_vat'] = 0;
$totalarray['val']['f.total_localtax1'] = 0;
$totalarray['val']['f.total_localtax1'] = 0;
$totalarray['val']['f.total_localtax2'] = 0;
$totalarray['val']['f.total_ttc'] = 0;
$totalarray['val']['totalam'] = 0;
$totalarray['val']['rtp'] = 0;
@@ -1964,9 +1964,6 @@ while ($i < $imaxinloop) {
$totalarray['nbfield']++;
$totalarray['pos'][$totalarray['nbfield']] = 'totalam';
}
if (empty($totalarray['val']['totalam'])) {
$totalarray['val']['totalam'] = 0; // avoid PHP Warning: Undefined array key "totalam" on line 1891
}
$totalarray['val']['totalam'] += $totalpay;
}

View File

@@ -117,13 +117,13 @@ class PriceParser
if (in_array($code, array(9, 14, 19, 20))) { //Errors which have 0 arg
return $langs->trans("ErrorPriceExpression".$code);
} elseif (in_array($code, array(1, 2, 3, 4, 5, 8, 10, 11, 17, 21, 22))) { //Errors which have 1 arg
return $langs->trans("ErrorPriceExpression".$code, $info);
return $langs->trans("ErrorPriceExpression".$code, (string) $info);
} elseif (in_array($code, array(6, 23))) { //Errors which have 2 args
return $langs->trans("ErrorPriceExpression".$code, $info[0], $info[1]);
} elseif (in_array($code, array(7, 12, 13, 15, 16, 18))) { //Internal errors
return $langs->trans("ErrorPriceExpressionInternal", $code);
return $langs->trans("ErrorPriceExpressionInternal", (string) $code);
} else { //Unknown errors
return $langs->trans("ErrorPriceExpressionUnknown", $code);
return $langs->trans("ErrorPriceExpressionUnknown", (string) $code);
}
}

View File

@@ -213,8 +213,8 @@ class MouvementStock extends CommonObject
* @param int|'' $sellby sell-by date. Will be used if lot does not exists yet and will be created.
* @param string $batch batch number
* @param bool $skip_batch If set to true, stock movement is done without impacting batch record
* @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch to use)
* @param int<0,1> $disablestockchangeforsubproduct Disable stock change for sub-products of kit (useful only if product is a subproduct)
* @param int $id_product_batch Id product_batch (when skip_batch is false and we already know which record of product_batch table to use)
* @param int<0,1> $disablestockchangeforsubproduct Disable stock change for sub-products of kit (useful only if product is a kit)
* @param int<0,1> $donotcleanemptylines Do not clean lines in stock table with qty=0 (because we want to have this done by the caller)
* @param bool $force_update_batch Allows to add batch stock movement even if $product doesn't use batch anymore
* @return int Return integer <0 if KO, 0 if fk_product is null or product id does not exists, >0 if OK
@@ -966,7 +966,6 @@ class MouvementStock extends CommonObject
$result = -1;
}
$fk_product_stock = 0;
if ($result >= 0) {
// No error
if ($pdluo->id > 0) { // product_batch record found
@@ -1170,7 +1169,7 @@ class MouvementStock extends CommonObject
*/
public function getNomUrl($withpicto = 0, $option = '', $notooltip = 0, $maxlen = 24, $morecss = '')
{
global $langs, $conf, $db;
global $langs;
$result = '';
@@ -1263,7 +1262,7 @@ class MouvementStock extends CommonObject
*/
public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
{
global $conf, $user, $langs;
global $langs;
$langs->load("stocks");
$outputlangs->load("products");
@@ -1330,27 +1329,40 @@ class MouvementStock extends CommonObject
}
/**
* reverse movement for object by updating infos
* Reverse movement for object by updating infos
*
* @return int 1 if OK,-1 if KO
*/
public function reverseMouvement()
public function reverseMovement()
{
$formattedDate = "REVERTMV" .dol_print_date($this->datem, '%Y%m%d%His');
if ($this->label == 'Annulation movement ID'.$this->id) {
return -1;
}
global $user;
$formattedDate = "REVERT-" .($this->inventorycode ? $this->inventorycode : dol_print_date($this->datem, '%Y%m%d%His'));
if ($this->inventorycode == $formattedDate) {
return -1;
}
$sql = "UPDATE ".$this->db->prefix()."stock_mouvement SET";
$sql .= " label = 'Annulation movement ID ".((int) $this->id)."',";
$sql .= "inventorycode = '".($formattedDate)."'";
$sql .= " WHERE rowid = ".((int) $this->id);
$newlabel = 'Revert '.$this->label;
// type is 0=input (stock increase by a stock transfer), 1=output (stock decrease by a stock transfer), 2=output (stock decrease), 3=input (stock increase)
// Note that qty should be > 0 with 0 or 3, < 0 with 1 or 2.
if ($this->type == 0) {
$newtype = 1;
} elseif ($this->type == 1) {
$newtype = 0;
} elseif ($this->type == 2) {
$newtype = 3;
} elseif ($this->type == 3) {
$newtype = 2;
} else {
return -1;
}
$newqty = - $this->qty;
$resql = $this->db->query($sql);
$this->db->begin();
if ($resql) {
$result = $this->_create($user, $this->product_id, $this->warehouse_id, $newqty, $newtype, 0, $newlabel, $formattedDate, '', 0, 0, $this->batch);
if ($result > 0) {
$this->db->commit();
return 1;
} else {

View File

@@ -619,41 +619,48 @@ if ($action == "transfert_stock" && $permissiontoadd && !$cancel) {
if ($action == 'confirm_reverse' && $confirm == "yes" && $permissiontoadd) {
$toselect = array_map('intval', $toselect);
$db->begin();
$sql = "SELECT rowid, label, inventorycode, datem";
$sql .= " FROM ".MAIN_DB_PREFIX."stock_mouvement";
$sql .= " WHERE rowid IN (";
foreach ($toselect as $id) {
$sql .= ((int) $id).",";
}
$sql = rtrim($sql, ',');
$sql .= ")";
$sql .= " WHERE rowid IN (".$db->sanitize(implode(',', $toselect)).")";
$resql = $db->query($sql);
if ($resql) {
$num = $db->num_rows($resql);
$i = 0;
$hasSuccess = false;
$hasError = false;
$error =0;
while ($i < $num) {
$obj = $db->fetch_object($resql);
$object->fetch($obj->rowid);
$reverse = $object->reverseMouvement();
$object->id = 0;
$object->fetch($obj->rowid); // $object is MouvementStock
// TODO Add a protection to disallow reversion if type of movement is not the same value for all selected lines
// Create the reverse movement
$reverse = $object->reverseMovement();
if ($reverse < 0) {
$hasError = true;
} else {
$hasSuccess = true;
setEventMessages($object->error, $object->errors, 'errors');
$error++;
break;
}
$i++;
}
if ($hasError) {
setEventMessages($langs->trans("WarningAlreadyReverse", $langs->transnoentities($idAlreadyReverse)), null, 'warnings');
}
if ($hasSuccess) {
setEventMessages($langs->trans("ReverseConfirmed"), null);
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
} else {
setEventMessages($db->lasterror(), null, 'errors');
$error++;
}
if (!$error) {
setEventMessages($langs->trans("ReverseConfirmed"), null);
$db->commit();
} else {
$db->rollback();
}
header("Location: ".$_SERVER["PHP_SELF"]);
exit;
}
/*

View File

@@ -106,6 +106,7 @@ $pagenext = $page + 1;
$search_all = GETPOST('search_all', 'alphanohtml');
$search_entity = GETPOSTINT('search_entity');
$search_id = GETPOST("search_id", 'alpha');
$search_ref = GETPOST("search_ref", 'alpha');
$search_label = GETPOST("search_label", 'alpha');
$search_societe = GETPOST("search_societe", 'alpha');
@@ -392,6 +393,7 @@ if (empty($reshook)) {
// Purge search criteria
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
$search_all = '';
$search_id = "";
$search_ref = "";
$search_label = "";
$search_societe = "";
@@ -629,6 +631,9 @@ if (!$user->hasRight('projet', 'all', 'lire')) {
if ($socid > 0) {
$sql .= " AND (p.fk_soc = ".((int) $socid).")"; // This filter if when we use a hard coded filter on company on url (not related to filter for external users)
}
if ($search_id) {
$sql .= natural_search('p.rowid', $search_id, 1);
}
if ($search_ref) {
$sql .= natural_search('p.ref', $search_ref);
}
@@ -1054,6 +1059,9 @@ if (!empty($search_category_array)) {
$param .= '&search_categegory_project_list[]='.urlencode($tmpval);
}
}
if ($search_id != '') {
$param .= '&search_id='.urlencode($search_id);
}
if ($search_ref != '') {
$param .= '&search_ref='.urlencode($search_ref);
}
@@ -1300,10 +1308,16 @@ if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print $searchpicto;
print '</td>';
}
// Project ID
if (!empty($arrayfields['p.rowid']['checked'])) {
print '<td class="liste_titre">';
print '<input type="text" class="flat width50" name="search_id" value="'.dol_escape_htmltag($search_id).'">';
print '</td>';
}
// Project ref
if (!empty($arrayfields['p.ref']['checked'])) {
print '<td class="liste_titre">';
print '<input type="text" class="flat" name="search_ref" value="'.dol_escape_htmltag($search_ref).'" size="6">';
print '<input type="text" class="flat width75" name="search_ref" value="'.dol_escape_htmltag($search_ref).'">';
print '</td>';
}
// Project label
@@ -1514,6 +1528,10 @@ if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
if (!empty($arrayfields['p.rowid']['checked'])) {
print_liste_field_titre($arrayfields['p.rowid']['label'], $_SERVER["PHP_SELF"], "p.rowid", "", $param, "", $sortfield, $sortorder);
$totalarray['nbfield']++;
}
if (!empty($arrayfields['p.ref']['checked'])) {
print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER["PHP_SELF"], "p.ref", "", $param, "", $sortfield, $sortorder);
$totalarray['nbfield']++;
@@ -1917,7 +1935,16 @@ while ($i < $imaxinloop) {
$totalarray['nbfield']++;
}
}
// Project url
// Project ID
if (!empty($arrayfields['p.rowid']['checked'])) {
print '<td class="nowraponall">';
print $object->id;
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
// Project ref url
if (!empty($arrayfields['p.ref']['checked'])) {
print '<td class="nowraponall tdoverflowmax200">';
print $object->getNomUrl(1, (!empty(GETPOSTINT('search_usage_event_organization')) ? 'eventorganization' : ''));

View File

@@ -182,53 +182,10 @@ $conf->dol_hide_leftmenu = 1;
llxHeaderSubscriptionOk($langs->trans("PaymentForm"));
// Show message
print '<span id="dolpaymentspan"></span>'."\n";
print '<div id="dolpaymentdiv" class="center">'."\n";
// Show logo (search order: logo defined by PAYMENT_LOGO_suffix, then PAYMENT_LOGO, then small company logo, large company logo, theme logo, common logo)
// Define logo and logosmall
$logosmall = $mysoc->logo_small;
$logo = $mysoc->logo;
$paramlogo = 'ONLINE_PAYMENT_LOGO_'.$suffix;
if (getDolGlobalString($paramlogo)) {
$logosmall = getDolGlobalString($paramlogo);
} elseif (getDolGlobalString('ONLINE_PAYMENT_LOGO')) {
$logosmall = getDolGlobalString('ONLINE_PAYMENT_LOGO');
}
//print '<!-- Show logo (logosmall='.$logosmall.' logo='.$logo.') -->'."\n";
// Define urllogo
$urllogo = '';
$urllogofull = '';
if (!empty($logosmall) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$logosmall)) {
$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/thumbs/'.$logosmall);
$urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/thumbs/'.$logosmall);
} elseif (!empty($logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$logo)) {
$urllogo = DOL_URL_ROOT.'/viewimage.php?modulepart=mycompany&amp;entity='.$conf->entity.'&amp;file='.urlencode('logos/'.$logo);
$urllogofull = $dolibarr_main_url_root.'/viewimage.php?modulepart=mycompany&entity='.$conf->entity.'&file='.urlencode('logos/'.$logo);
}
// Output html code for logo
if ($urllogo) {
print '<div class="backgreypublicpayment">';
print '<div class="logopublicpayment">';
print '<img id="dolpaymentlogo" src="'.$urllogo.'"';
print '>';
print '</div>';
if (!getDolGlobalString('MAIN_HIDE_POWERED_BY')) {
print '<div class="poweredbypublicpayment opacitymedium right"><a class="poweredbyhref" href="https://www.dolibarr.org?utm_medium=website&utm_source=poweredby" target="dolibarr" rel="noopener">'.$langs->trans("PoweredBy").'<br><img class="poweredbyimg" src="'.DOL_URL_ROOT.'/theme/dolibarr_logo.svg" width="80px"></a></div>';
}
print '</div>';
}
if (getDolGlobalString('EVENTORGANIZATION_IMAGE_PUBLIC_INTERFACE')) {
print '<div class="backimagepubliceventorganizationsubscription">';
print '<img id="idEVENTORGANIZATION_IMAGE_PUBLIC_INTERFACE" src="' . getDolGlobalString('EVENTORGANIZATION_IMAGE_PUBLIC_INTERFACE').'">';
print '</div>';
}
print '<br><br><br>';
print $langs->trans("SubscriptionOk");

View File

@@ -571,7 +571,7 @@ if ($num == 1 && getDolGlobalString('MAIN_SEARCH_DIRECT_OPEN_IF_ONLY_ONE') && $s
// Output page
// --------------------------------------------------------------------
llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist mod-product page-list');
llxHeader('', $title, $help_url, '', 0, 0, $morejs, $morecss, '', 'bodyforlist mod-user page-list');
$arrayofselected = is_array($toselect) ? $toselect : array();