mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-02-13 11:15:21 +01:00
Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
* Copyright (C) 2024 Josep Lluís Amador Teruel <joseplluis@lliuretic.cat>
|
||||
* Copyright (C) 2024 Benoît PASCAL <contact@p-ben.com>
|
||||
* Copyright (C) 2025 Vincent Maury <vmaury@timgroup.fr>
|
||||
* Copyright (C) 2026 Benjamin Falière <benjamin@faliere.com>
|
||||
*
|
||||
* 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
|
||||
@@ -16723,10 +16724,11 @@ function show_actions_messaging($conf, $langs, $db, $filterobj, $objcon = null,
|
||||
}
|
||||
|
||||
$libelle = '';
|
||||
if (!empty($actionstatic->code) && preg_match('/^TICKET_MSG/', $actionstatic->code)) {
|
||||
|
||||
if (!empty($actionstatic->code) && preg_match('/^TICKET_MSG_PRIVATE/', $actionstatic->code)) {
|
||||
$out .= $langs->trans('TicketNewMessage').' <em>('.$langs->trans('Private').')</em>';
|
||||
} elseif (!empty($actionstatic->code) && preg_match('/^TICKET_MSG/', $actionstatic->code)) {
|
||||
$out .= $langs->trans('TicketNewMessage');
|
||||
} elseif (!empty($actionstatic->code) && preg_match('/^TICKET_MSG_PRIVATE/', $actionstatic->code)) {
|
||||
$out .= $langs->trans('TicketNewMessage') . ' <em>(' . $langs->trans('Private') . ')</em>';
|
||||
} elseif (isset($histo[$key]['type'])) {
|
||||
if ($histo[$key]['type'] == 'action') {
|
||||
$transcode = $langs->transnoentitiesnoconv("Action" . $histo[$key]['acode']);
|
||||
|
||||
@@ -2658,7 +2658,7 @@ function getModuleDirForApiClass($moduleobject)
|
||||
$moduledirforclass = 'api';
|
||||
} elseif (in_array($moduleobject, ['contact', 'contacts', 'customer', 'thirdparty', 'thirdparties'])) {
|
||||
$moduledirforclass = 'societe';
|
||||
} elseif ($moduleobject == 'propale' || $moduleobject == 'proposals') {
|
||||
} elseif ($moduleobject == 'propal' || $moduleobject == 'propale' || $moduleobject == 'proposals') {
|
||||
$moduledirforclass = 'comm/propal';
|
||||
} elseif ($moduleobject == 'agenda' || $moduleobject == 'agendaevents') {
|
||||
$moduledirforclass = 'comm/action';
|
||||
|
||||
@@ -737,6 +737,11 @@ class pdf_espadon extends ModelePdfExpedition
|
||||
$nexY = max($pdf->GetY(), $nexY);
|
||||
}
|
||||
|
||||
if ($this->getColumnStatus('totalexcltax') && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
|
||||
$this->printStdColumnContent($pdf, $curY, 'totalexcltax', price($object->lines[$i]->total_ht, 0, $outputlangs));
|
||||
$nexY = max($pdf->GetY(), $nexY);
|
||||
}
|
||||
|
||||
// Extrafields
|
||||
if (!empty($object->lines[$i]->array_options) && $object->lines[$i]->special_code != SUBTOTALS_SPECIAL_CODE) {
|
||||
foreach ($object->lines[$i]->array_options as $extrafieldColKey => $extrafieldValue) {
|
||||
@@ -954,8 +959,8 @@ class pdf_espadon extends ModelePdfExpedition
|
||||
$this->printStdColumnContent($pdf, $tab2_top, 'qty_shipped', $totalToShip);
|
||||
}
|
||||
|
||||
if ($this->getColumnStatus('subprice')) {
|
||||
$this->printStdColumnContent($pdf, $tab2_top, 'subprice', price($object->total_ht, 0, $outputlangs));
|
||||
if ($this->getColumnStatus('totalexcltax')) {
|
||||
$this->printStdColumnContent($pdf, $tab2_top, 'totalexcltax', price($object->total_ht, 0, $outputlangs));
|
||||
}
|
||||
|
||||
$pdf->SetTextColor(0, 0, 0);
|
||||
|
||||
@@ -1959,7 +1959,7 @@ if ($action == 'create' && $usercancreate) {
|
||||
if ($res < 0) {
|
||||
dol_print_error($db, $product->error, $product->errors);
|
||||
}
|
||||
if (getDolGlobalInt('PRODUIT_SOUSPRODUITS')) {
|
||||
if (getDolGlobalInt('PRODUIT_SOUSPRODUITS') && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
|
||||
$productChildrenNb = $product->hasFatherOrChild(1);
|
||||
}
|
||||
if ($productChildrenNb > 0) {
|
||||
@@ -2168,13 +2168,13 @@ if ($action == 'create' && $usercancreate) {
|
||||
$subj = 0;
|
||||
// Define nb of lines suggested for this order line
|
||||
$nbofsuggested = 0;
|
||||
if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
||||
if (is_object($product->stock_warehouse[$warehouse_id]) && !empty($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
||||
foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) {
|
||||
$nbofsuggested++;
|
||||
}
|
||||
}
|
||||
print '<input name="idl' . $indiceAsked . '" type="hidden" value="' . $line->id . '">';
|
||||
if (is_object($product->stock_warehouse[$warehouse_id]) && count($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
||||
print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
|
||||
if (is_object($product->stock_warehouse[$warehouse_id]) && !empty($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
||||
foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) { // $dbatch is instance of Productbatch
|
||||
//var_dump($dbatch);
|
||||
$batchStock = +$dbatch->qty; // To get a numeric
|
||||
@@ -2414,7 +2414,7 @@ if ($action == 'create' && $usercancreate) {
|
||||
// Define nb of lines suggested for this order line
|
||||
$nbofsuggested = 0;
|
||||
foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) {
|
||||
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (count($stock_warehouse->detail_batch))) {
|
||||
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (!empty($stock_warehouse->detail_batch))) {
|
||||
$nbofsuggested += count($stock_warehouse->detail_batch);
|
||||
}
|
||||
}
|
||||
@@ -2427,7 +2427,7 @@ if ($action == 'create' && $usercancreate) {
|
||||
}
|
||||
|
||||
$tmpwarehouseObject->fetch($warehouse_id);
|
||||
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (count($stock_warehouse->detail_batch))) {
|
||||
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (!empty($stock_warehouse->detail_batch))) {
|
||||
foreach ($stock_warehouse->detail_batch as $dbatch) {
|
||||
$batchStock = +$dbatch->qty; // To get a numeric
|
||||
if (isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) {
|
||||
|
||||
@@ -569,9 +569,9 @@ class Expedition extends CommonObject
|
||||
if (empty($line->product_type) || getDolGlobalString('STOCK_SUPPORTS_SERVICES') || getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
||||
$line_id = 0;
|
||||
if (!isset($kits_id_cached[$line->fk_product])) {
|
||||
if (!isset($line->detail_batch) || isset($kits_list[$line->fk_product])) { // no batch management or is kit
|
||||
if (!isset($line->detail_batch) || (isset($kits_list[$line->fk_product]) && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) { // no batch management or is kit
|
||||
$qty = isset($kits_list[$line->fk_product]) ? $kits_list[$line->fk_product]['total_qty'] : $line->qty;
|
||||
$warehouse_id = isset($kits_list[$line->fk_product]) ? 0 : $line->entrepot_id;
|
||||
$warehouse_id = (isset($kits_list[$line->fk_product]) && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) ? 0 : $line->entrepot_id;
|
||||
$line_id = $this->create_line($warehouse_id, $line->origin_line_id, $qty, $line->rang, $line->array_options, 0, $line->fk_product);
|
||||
if ($line_id <= 0) {
|
||||
$error++;
|
||||
@@ -589,7 +589,7 @@ class Expedition extends CommonObject
|
||||
}
|
||||
|
||||
// virtual products
|
||||
if (isset($kits_list[$line->fk_product])) {
|
||||
if (isset($kits_list[$line->fk_product]) && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
|
||||
$prods_arbo = $kits_list[$line->fk_product]['arbo'];
|
||||
$total_qty = $kits_list[$line->fk_product]['total_qty'];
|
||||
|
||||
@@ -650,7 +650,7 @@ class Expedition extends CommonObject
|
||||
|
||||
// create line for a child of virtual product
|
||||
if (!isset($sub_kits_id_cached[$product_child_id]) || $warehouse_id > 0) {
|
||||
$line_id = $this->create_line($warehouse_id, 0, $product_child_qty, $line->rang, $line->array_options, $parent_line_id, $product_child_id);
|
||||
$line_id = $this->create_line($warehouse_id, ($parent_line_id ? 0 : $line->origin_line_id), $product_child_qty, $line->rang, $line->array_options, $parent_line_id, $product_child_id);
|
||||
if ($line_id <= 0) {
|
||||
$error++;
|
||||
dol_syslog(__METHOD__ . ' : ' . $this->errorsToString(), LOG_ERR);
|
||||
@@ -1749,7 +1749,7 @@ class Expedition extends CommonObject
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
$line_id = (int) $obj->expeditiondet_id;
|
||||
|
||||
if ($can_update_stock && empty($obj->iskit) && !empty($obj->incdec)) {
|
||||
if ($can_update_stock && (empty($obj->iskit) || getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
|
||||
$mouvS = new MouvementStock($this->db);
|
||||
// we do not log origin because it will be deleted
|
||||
$mouvS->origin = '';
|
||||
@@ -1954,7 +1954,7 @@ class Expedition extends CommonObject
|
||||
$obj = $this->db->fetch_object($resql);
|
||||
$line_id = (int) $obj->expeditiondet_id;
|
||||
|
||||
if ($can_update_stock && empty($obj->iskit) && !empty($obj->incdec)) {
|
||||
if ($can_update_stock && (empty($obj->iskit) || getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) && !empty($obj->incdec)) {
|
||||
$mouvS = new MouvementStock($this->db);
|
||||
// we do not log origin because it will be deleted
|
||||
$mouvS->origin = '';
|
||||
|
||||
@@ -913,7 +913,9 @@ if ($object->id > 0 || !empty($object->ref)) {
|
||||
$resql_child = $db->query($sql_child);
|
||||
if ($resql_child) {
|
||||
if ($child_obj = $db->fetch_object($resql_child)) {
|
||||
$line_obj->iskit = (int) $child_obj->iskit;
|
||||
if (!getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
|
||||
$line_obj->iskit = (int) $child_obj->iskit;
|
||||
}
|
||||
if ($can_manage_stock) {
|
||||
$line_obj->incdec = (int) $child_obj->incdec; // reset value to 0 or 1 if stock can be managed
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ class Odf
|
||||
* Class constructor
|
||||
*
|
||||
* @param string $filename The name of the odt file
|
||||
* @param array $config Array of config data
|
||||
* @param array $config Array of config data
|
||||
* @throws OdfException
|
||||
*/
|
||||
public function __construct($filename, $config = array())
|
||||
@@ -957,19 +957,32 @@ IMG;
|
||||
// $result = $utils->executeCLI($command, $outputfile); and replace test on $execmethod.
|
||||
// $retval will be $result['result']
|
||||
// $errorstring will be $result['output']
|
||||
|
||||
// Protect parentheses from being double-escaped by escapeshellcmd().
|
||||
// The $command is already built with escapeshellarg() for all arguments,
|
||||
// but escapeshellcmd() escapes parentheses inside quoted strings, breaking
|
||||
// filenames like "(PROV35)_invoice.odt" for draft invoices.
|
||||
// Security: reject if placeholder strings already exist to prevent injection.
|
||||
if (strpos($command, '__PARENTHESIS_OPEN__') !== false || strpos($command, '__PARENTHESIS_CLOSE__') !== false) {
|
||||
dol_syslog(get_class($this).'::exportAsAttachedPDF Invalid characters in command path: '.$command, LOG_WARNING);
|
||||
throw new OdfException('Invalid characters in command path');
|
||||
}
|
||||
$commandprotected = str_replace(array('(', ')'), array('__PARENTHESIS_OPEN__', '__PARENTHESIS_CLOSE__'), $command);
|
||||
$commandescaped = escapeshellcmd($commandprotected);
|
||||
$commandescapedtoexec = str_replace(array('__PARENTHESIS_OPEN__', '__PARENTHESIS_CLOSE__'), array('(', ')'), $commandescaped);
|
||||
|
||||
$retval=0; $output_arr=array();
|
||||
if ($execmethod == 1) {
|
||||
exec(escapeshellcmd($command), $output_arr, $retval);
|
||||
}
|
||||
if ($execmethod == 2) {
|
||||
exec($commandescapedtoexec, $output_arr, $retval);
|
||||
} elseif ($execmethod == 2) {
|
||||
$outputfile = DOL_DATA_ROOT.'/odt2pdf.log';
|
||||
|
||||
$handle = fopen($outputfile, 'w');
|
||||
if ($handle) {
|
||||
dol_syslog(get_class($this)."Run command ".$command, LOG_DEBUG);
|
||||
dol_syslog(get_class($this)."escapeshellcmd(command) = ".escapeshellcmd($command), LOG_DEBUG);
|
||||
dol_syslog(get_class($this)."escapeshellcmd(command) = ".$commandescapedtoexec, LOG_DEBUG);
|
||||
fwrite($handle, $command."\n");
|
||||
$handlein = popen(escapeshellcmd($command), 'r');
|
||||
$handlein = popen($commandescapedtoexec, 'r');
|
||||
while (!feof($handlein)) {
|
||||
$read = fgets($handlein);
|
||||
fwrite($handle, $read);
|
||||
|
||||
Reference in New Issue
Block a user