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

This commit is contained in:
Laurent Destailleur 2026-01-26 19:35:29 +01:00
commit 5efcd7652f
30 changed files with 298 additions and 197 deletions

View file

@ -230,7 +230,7 @@ class AccountancyExport
);
global $hookmanager;
$code = $formatcode[$type];
$code = $formatcode[$type] ?? '';
$parameters = array('type' => $type);
$reshook = $hookmanager->executeHooks('getFormatCode', $parameters, $code);

View file

@ -1,11 +1,11 @@
<?php
/* Copyright (C) 2014-2017 Olivier Geffroy <jeff@jeffinfo.com>
* Copyright (C) 2015-2025 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2015-2020 Florian Henry <florian.henry@open-concept.pro>
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
* Copyright (C) 2025 Nicolas Barrouillet <nicolas@pragma-tech.fr>
* Copyright (C) 2024 Jose MARTINEZ <jose.martinez@pichinov.com>
* Copyright (C) 2025 Nicolas Barrouillet <nicolas@pragma-tech.fr>
*
* 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
@ -3761,7 +3761,7 @@ class BookKeeping extends CommonObject
$newBookKeeping->sens = 'D';
}
$newBookKeeping->label_operation = "Extourne " . $bookKeeping->piece_num . " - " . $bookKeeping->numero_compte . " - " . date('d/m/Y', dol_now()) . " - " . $i;
$newBookKeeping->label_operation = $langs->trans("ReturnAccount") . " " . $bookKeeping->piece_num . " - " . $bookKeeping->numero_compte . " - " . date('d/m/Y', dol_now()) . " - " . $i;
$newBookKeeping->numero_compte = $bookKeeping->numero_compte;
$newBookKeeping->label_compte = $bookKeeping->label_compte;
@ -3777,14 +3777,14 @@ class BookKeeping extends CommonObject
}
$createResult = $newBookKeeping->create($user);
if ($createResult > 0) {
if ($createResult >= 0) {
$newBookKeeping->piece_num = $pieceNumNext;
$newBookKeeping->fk_doc = $bookKeeping->fk_doc;
$newBookKeeping->fk_docdet = $bookKeeping->fk_docdet;
$result = $newBookKeeping->update($user);
$newBookKeeping->update($user);
setEventMessages($langs->trans("SuccessReturnedAccount", $bookKeeping->piece_num), null, 'mesgs');
} else {
setEventMessages($langs->trans("ErrorWhileCreating", $newBookKeeping->error), null, 'errors');
setEventMessages($langs->trans("ErrorWhileCreating", $newBookKeeping->error), $newBookKeeping->errors, 'errors');
$error++;
}
}

View file

@ -132,12 +132,14 @@ if (isModEnabled('accounting')) {
print load_fiche_titre($langs->trans("AccountancyArea"), empty($resultboxes['selectboxlist']) ? '' : $resultboxes['selectboxlist'], 'accountancy', 0, '', '', $showtutorial);
/*
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
$messagewarning = $langs->trans("SorryThisModuleIsNotCompatibleWithTheExperimentalFeatureOfSituationInvoices");
$messagewarning .= ' '.$langs->trans("WarningExperimentalFeatureInvoiceSituationNeedToUpgradeToProgressiveMode", 'https://partners.dolibarr.org');
print info_admin($messagewarning);
print "<br>";
}
*/
if (!$helpisexpanded && empty($resultboxes['boxlista']) && empty($resultboxes['boxlistb'])) {
print '<div class="opacitymedium idfaq2"><br>'.$langs->trans("ClickOnUseTutorialForHelp", $langs->transnoentities("ShowTutorial"))."</div>\n";

View file

@ -1183,7 +1183,7 @@ class AdherentType extends CommonObject
//$return .= '<input id="cb'.$this->id.'" class="flat checkforselect fright" type="checkbox" name="toselect[]" value="'.$this->id.'"'.($selected ? ' checked="checked"' : '').'>';
if ($user->hasRight('adherent', 'configurer')) {
$return .= '<span class="right paddingleft"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.urlencode($this->ref).'">'.img_edit().'</a></span>';
$return .= '<span class="right paddingleft"><a class="editfielda showonhover" href="'.$_SERVER["PHP_SELF"].'?action=edit&rowid='.urlencode($this->ref).'">'.img_edit().'</a></span>';
} else {
$return .= '<span class="right">&nbsp;</span>';
}

View file

@ -459,7 +459,9 @@ print '<td class="liste_titre"></td>';
print '</tr>';
// Activate FileCache (so content of file boxes are stored into a cache file int boxes/temp for 3600 seconds)
print '<tr class="oddeven"><td>'.$langs->trans("EnableFileCache").'</td><td>';
print '<tr class="oddeven"><td>'.$langs->trans("EnableFileCache");
print ' <span class="opacitymedium">('.getDolGlobalInt('MAIN_ACTIVATE_FILECACHE_DELAY', 900)." ".$langs->trans("seconds").")</span>";
print '</td><td>';
if ($conf->use_javascript_ajax) {
print ajax_constantonoff('MAIN_ACTIVATE_FILECACHE', array(), null, 0, 0, 0, 2, 0, 1);
} else {

View file

@ -1,10 +1,11 @@
<?php
/* Copyright (C) 2006-2014 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
/* Copyright (C) 2006-2014 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2011 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2021 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Anthony Berton <anthony.berton@bb2a.fr>
*
* 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
@ -151,7 +152,7 @@ if ($what == 'mysql') {
}
if (!$errormsg && $cmddump) {
dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'SYSTEMTOOLS_MYSQLDUMP', $cmddump, 'chaine', 0, '', 0);
}
if (!$errormsg) {
@ -191,7 +192,7 @@ if ($what == 'postgresql') {
} */
if (!$errormsg && $cmddump) {
dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump, 'chaine', 0, '', $conf->entity);
dolibarr_set_const($db, 'SYSTEMTOOLS_POSTGRESQLDUMP', $cmddump, 'chaine', 0, '', 0);
}
if (!$errormsg) {

View file

@ -2045,7 +2045,7 @@ class Categorie extends CommonObject
* Return an array with all photos inside the directory
*
* @param string $dir Dir to scan
* @param int $nbmax Nombre maximum de photos (0=pas de max)
* @param int $nbmax Maximum number of photos (0=no max)
* @return array<int,array{photo:string,photo_vignette:string}> Table with images
*/
public function liste_photos($dir, $nbmax = 0)

View file

@ -20,6 +20,7 @@
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2025 Benjamin Falière <benjamin@faliere.com>
* Copyright (C) 2025 Anthony Berton <anthony.berton@bb2a.fr>
*
* 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
@ -161,6 +162,8 @@ if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->tabl
}
$price_base_type = null;
$shipping_method_id = null;
$warehouse_id = -1;
// Security check
if (!empty($user->socid)) {
@ -2295,7 +2298,7 @@ if ($action == 'create') {
$cond_reglement_id = (!empty($objectsrc->cond_reglement_id) ? $objectsrc->cond_reglement_id : (!empty($soc->cond_reglement_id) ? $soc->cond_reglement_id : 0));
$mode_reglement_id = (!empty($objectsrc->mode_reglement_id) ? $objectsrc->mode_reglement_id : (!empty($soc->mode_reglement_id) ? $soc->mode_reglement_id : 0));
$warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : 0));
$warehouse_id = (!empty($objectsrc->warehouse_id) ? $objectsrc->warehouse_id : (!empty($soc->warehouse_id) ? $soc->warehouse_id : -1));
// Replicate extrafields
$objectsrc->fetch_optionals();
@ -2319,7 +2322,7 @@ if ($action == 'create') {
$mode_reglement_id = empty($soc->mode_reglement_id) ? $mode_reglement_id : $soc->mode_reglement_id;
$fk_account = empty($soc->fk_account) ? $fk_account : $soc->fk_account;
$shipping_method_id = $soc->shipping_method_id;
$warehouse_id = $soc->fk_warehouse;
$warehouse_id = !empty($soc->fk_warehouse) ? $soc->fk_warehouse : $warehouse_id;
$remise_percent = $soc->remise_percent;
if (isModEnabled("multicurrency") && !empty($soc->multicurrency_code)) {
@ -2347,7 +2350,7 @@ if ($action == 'create') {
if ($soc->fk_warehouse > 0) {
$warehouse_id = $soc->fk_warehouse;
}
if (isModEnabled('stock') && empty($warehouse_id) && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
if (isModEnabled('stock') && $warehouse_id < 0 && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_PROPAL')) {
if (empty($object->warehouse_id) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
$warehouse_id = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE');
}
@ -2390,9 +2393,11 @@ if ($action == 'create') {
// Third party
print '<tr class="field_socid">';
print '<td class="titlefieldcreate fieldrequired">' . $langs->trans('Customer') . '</td>';
$shipping_method_id = 0;
$warehouse_id = 0;
if ($socid > 0) {
print '<td class="valuefieldcreate">';
print $soc->getNomUrl(1, 'customer');
@ -2401,7 +2406,6 @@ if ($action == 'create') {
if (getDolGlobalString('SOCIETE_ASK_FOR_SHIPPING_METHOD') && !empty($soc->shipping_method_id)) {
$shipping_method_id = $soc->shipping_method_id;
}
//$warehouse_id = $soc->warehouse_id;
} else {
print '<td class="valuefieldcreate">';
$filter = '((s.client:IN:1,2,3) AND (s.status:=:1))';

View file

@ -1286,7 +1286,7 @@ if (isModEnabled('stock') && getDolGlobalString('WAREHOUSE_ASK_WAREHOUSE_DURING_
$formproduct = new FormProduct($db);
$moreforfilter .= '<div class="divsearchfield">';
$tmptitle = $langs->trans('Warehouse');
$moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', 1, 0, 0, $tmptitle, 0, 0, array(), 'maxwidth250 widthcentpercentminusx');
$moreforfilter .= img_picto($tmptitle, 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($search_warehouse, 'search_warehouse', '', $tmptitle, 0, 0, '', 0, 0, array(), 'maxwidth250 widthcentpercentminusx');
$moreforfilter .= '</div>';
}
$parameters = array();

View file

@ -309,16 +309,19 @@ if ($modecompta == 'BOOKKEEPING') {
if ($showaccountdetail == 'no') {
$sql .= ", f.thirdparty_code as name";
}
$sql .= " FROM ".MAIN_DB_PREFIX."accounting_bookkeeping as f";
$sql .= ", ".MAIN_DB_PREFIX."accounting_account as aa";
$sql .= " WHERE f.numero_compte = aa.account_number";
$sql .= " FROM ".$db->prefix()."accounting_bookkeeping as f";
$sql .= " INNER JOIN ".$db->prefix()."accounting_account as aa";
$sql .= " ON aa.account_number = f.numero_compte";
$sql .= " AND aa.entity = f.entity"; // Security prevents duplicate.
$sql .= " WHERE 1=1";
$sql .= " AND ".$predefinedgroupwhere;
$sql .= " AND fk_pcg_version = '".$db->escape($charofaccountstring)."'";
$sql .= " AND aa.fk_pcg_version = '".$db->escape($charofaccountstring)."'";
$sql .= " AND f.entity = ".$conf->entity;
if (!empty($date_start) && !empty($date_end)) {
$sql .= " AND f.doc_date >= '".$db->idate($date_start)."' AND f.doc_date <= '".$db->idate($date_end)."'";
$sql .= " AND f.doc_date >= '".$db->idate($date_start)."'";
$sql .= " AND f.doc_date <= '".$db->idate($date_end)."'";
}
$sql .= " GROUP BY pcg_type";
$sql .= " GROUP BY aa.pcg_type";
if ($showaccountdetail == 'no') {
$sql .= ", name, socid"; // group by "accounting group" (INCOME/EXPENSE), then "customer".
}

View file

@ -1416,8 +1416,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
if (getDolGlobalString('THIRDPARTY_ENABLE_PROSPECTION_ON_ALTERNATIVE_ADRESSES')) {
if ($object->thirdparty->client == 2 || $object->thirdparty->client == 3) {
// Level of prospect
print '<tr><td class="titlefield">';
print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
print '<tr><td class="">';
print '<table class="nobordernopadding centpercent"><tr><td class="nowrap">';
print $langs->trans('ProspectLevel');
print '<td>';
if ($action != 'editlevel' && $user->hasRight('societe', 'contact', 'creer')) {
@ -1453,7 +1453,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Categories
if (isModEnabled('category') && $user->hasRight('categorie', 'lire')) {
print '<tr><td class="titlefield">'.$langs->trans("Categories").'</td>';
print '<tr><td class="">'.$langs->trans("Categories").'</td>';
print '<td>';
print $form->showCategories($object->id, Categorie::TYPE_CONTACT, 1);
print '</td></tr>';
@ -1461,7 +1461,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
// Contact by default for
if (!empty($object->socid)) {
print '<tr><td class="titlefield">'.$langs->trans("ContactByDefaultFor").'</td>';
print '<tr><td class="">'.$langs->trans("ContactByDefaultFor").'</td>';
print '<td>';
print $formcompany->showRoles("roles", $object, 'view', $object->roles, '');
print '</td></tr>';
@ -1474,13 +1474,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
$object->load_ref_elements();
if (isModEnabled("propal")) {
print '<tr><td class="titlefield tdoverflow">'.$langs->trans("ContactForProposals").'</td><td>';
print '<tr><td class="">'.$langs->trans("ContactForProposals").'</td><td>';
print $object->ref_propal ? $object->ref_propal : '<span class="opacitymedium">'.$langs->trans("NoContactForAnyProposal").'<span>';
print '</td></tr>';
}
if (isModEnabled('order') || isModEnabled("shipping")) {
print '<tr><td class="titlefield tdoverflow">';
print '<tr><td class="">';
if (isModEnabled("shipping")) {
print $langs->trans("ContactForOrdersOrShipments");
} else {
@ -1496,13 +1496,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
}
if (isModEnabled('contract')) {
print '<tr><td class="tdoverflow">'.$langs->trans("ContactForContracts").'</td><td>';
print '<tr><td class="">'.$langs->trans("ContactForContracts").'</td><td>';
print $object->ref_contrat ? $object->ref_contrat : '<span class="opacitymedium">'.$langs->trans("NoContactForAnyContract").'</span>';
print '</td></tr>';
}
if (isModEnabled('invoice')) {
print '<tr><td class="tdoverflow">'.$langs->trans("ContactForInvoices").'</td><td>';
print '<tr><td class="">'.$langs->trans("ContactForInvoices").'</td><td>';
print $object->ref_facturation ? $object->ref_facturation : '<span class="opacitymedium">'.$langs->trans("NoContactForAnyInvoice").'</span>';
print '</td></tr>';
}
@ -1527,6 +1527,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
print dol_get_fiche_end();
/*
* Action bar
*/

View file

@ -265,7 +265,7 @@ class ModeleBoxes // Can't be abstract as it is instantiated to build "empty" bo
$MAXLENGTHBOX = 0; // When set to 0: no length limit
$cachetime = 900; // 900 : 15mn
$cachetime = getDolGlobalInt('MAIN_ACTIVATE_FILECACHE_DELAY', 900); // 900 : 15mn
$cachedir = DOL_DATA_ROOT.'/users/temp/widgets';
$fileid = get_class($this).'id-'.$this->box_id.'-e'.$conf->entity.'-u'.$user->id.'-s'.$user->socid.'.cache';
$filename = '/box-'.$fileid;

View file

@ -5807,6 +5807,8 @@ abstract class CommonObject
$this->tpl['strike'] = 0;
if ($restrictlist == 'services' && $line->product_type != Product::TYPE_SERVICE) {
$this->tpl['strike'] = 1;
} elseif ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
$this->tpl['strike'] = 1;
}
// Output template part (modules that overwrite templates must declare this into descriptor)

View file

@ -3,6 +3,7 @@
* Copyright (C) 2016 Christophe Battarel <christophe@altairis.fr>
* Copyright (C) 2019-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 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
@ -285,5 +286,6 @@ function llxHeaderTicket($title, $head = "", $disablejs = 0, $disablehead = 0, $
print '<body id="mainbody" class="publicnewticketform">';
print '<div class="publicnewticketform2 centpercent" style="min-height: 100%;">';
htmlPrintOnlineHeader($mysoc, $langs, (getDolGlobalInt('TICKET_SHOW_COMPANY_LOGO') ? getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/index.php?entity='.$conf->entity, 1)) : '0'), getDolGlobalString('TICKET_PUBLIC_INTERFACE_TOPIC', $langs->trans("TicketSystem")), 'TICKET_IMAGE_PUBLIC_INTERFACE');
}

View file

@ -151,7 +151,7 @@ class doc_generic_contract_odt extends ModelePDFContract
$texte .= getDolGlobalString('CONTRACT_ADDON_PDF_ODT_PATH');
$texte .= '</textarea>';
$texte .= '</div><div style="display: inline-block; vertical-align: middle;">';
$texte .= '<input type="submit" class="button reposition smallpaddingimp" value="'.dol_escape_htmltag($langs->trans("Upload")).'" name="upload">';
$texte .= '<input type="submit" class="button reposition smallpaddingimp" name="modify" value="'.dol_escape_htmltag($langs->trans("Modify")).'">';
$texte .= '<br></div></div>';
// Scan directories
@ -159,7 +159,7 @@ class doc_generic_contract_odt extends ModelePDFContract
if (getDolGlobalString('CONTRACT_ADDON_PDF_ODT_PATH')) {
$texte .= $langs->trans("NumberOfModelFilesFound").': <b>';
//$texte.=$nbofiles?'<a id="a_'.get_class($this).'" href="#">':'';
$texte .= count($listoffiles);
$texte .= $nbofiles;
//$texte.=$nbofiles?'</a>':'';
$texte .= '</b>';
}

View file

@ -639,7 +639,8 @@ class modProduct extends DolibarrModules
'p.recuperableonly' => '^[0|1]$',
);
if (isModEnabled('stock')) {//if Stock module enabled
// Complete if Stock module enabled
if (isModEnabled('stock')) {
$this->import_fields_array[$r] = array_merge($this->import_fields_array[$r], array(
'p.fk_default_warehouse' => 'DefaultWarehouse',
'p.tobatch' => 'ManageLotSerial',
@ -994,7 +995,11 @@ class modProduct extends DolibarrModules
// End add extra fields
$this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'product_price'); // aliastable.field => ('user->id' or 'lastrowid-'.tableparent)
$this->import_regex_array[$r] = array('pr.datec' => '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$', 'pr.recuperableonly' => '^[0|1]$');
$this->import_regex_array[$r] = array(
'pr.datec' => '^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]$',
'pr.recuperableonly' => '^[0|1]$'
);
$this->import_convertvalue_array[$r] = array(
'pr.fk_product' => array('rule' => 'fetchidfromref', 'classfile' => '/product/class/product.class.php', 'class' => 'Product', 'method' => 'fetch', 'element' => 'Product')
);

View file

@ -29,12 +29,6 @@
// Load Dolibarr environment
require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/donation.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
/**
* @var Conf $conf
* @var DoliDB $db
@ -44,6 +38,11 @@ require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
*
* @var string $dolibarr_main_url_root
*/
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/donation.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/don/class/don.class.php';
// Load translation files required by the page
$langs->loadLangs(array("admin", "donations"));
@ -120,7 +119,7 @@ print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
print '<input type="hidden" name="action" value="update">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print dol_get_fiche_head($head, 'website', $langs->trans("Donations"), -1, 'user');
print dol_get_fiche_head($head, 'website', $langs->trans("Donations"), -1, 'payment');
if ($conf->use_javascript_ajax) {
print "\n".'<script type="text/javascript">';

View file

@ -316,7 +316,7 @@ if (empty($reshook)) {
}
if ($objecttmp->id > 0) {
$res = $objecttmp->add_object_linked($objecttmp->origin, $id_sending);
$res = $objecttmp->add_object_linked($objecttmp->origin_type, $id_sending);
if ($res == 0) {
$errors[] = $expd->ref.' : '.$langs->trans($objecttmp->errors[0]);

View file

@ -1604,14 +1604,18 @@ if (empty($reshook)) {
$num = count($lines);
for ($i = 0; $i < $num; $i++) {
if ((empty($lines[$i]->subprice) || $lines[$i]->qty <= 0 || !in_array($lines[$i]->id, $selectedLines)) && $lines[$i]->product_type != 9) {
if (
empty($lines[$i]->subprice)
|| $lines[$i]->qty < 0
|| !in_array($lines[$i]->id, $selectedLines)
|| $lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE
) {
continue;
}
$label = (!empty($lines[$i]->label) ? $lines[$i]->label : '');
$desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : '');
$product_type = (!empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0);
// Reset fk_parent_line for no child products and special product
if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
$fk_parent_line = 0;
@ -2209,7 +2213,7 @@ if ($action == 'create') {
$formconfirm = '';
// Confirmation de la suppression de la commande
// Confirmation of deletion of order
if ($action == 'delete') {
$arrayAjouts = array();
$heightModal = 0;

View file

@ -114,11 +114,13 @@ if (getDolGlobalString('MAIN_MOTD')) {
*/
// Specific warning to propose to upgrade invoice situation to progressive mode
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) { // Note that we must also be in v22 or +, but this is the case now in this branch
/*
if (getDolGlobalInt('INVOICE_USE_SITUATION') == 1) {
$langs->loadLangs(array("admin"));
print info_admin($langs->trans("WarningExperimentalFeatureInvoiceSituationNeedToUpgradeToProgressiveMode", 'https://partners.dolibarr.org'));
//print "<br>";
}
*/
/*
* Show security warnings

View file

@ -1,14 +1,15 @@
-- Copyright (C) 2001-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
-- Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
-- Copyright (C) 2004 Guillaume Delecourt <guillaume.delecourt@opensides.be>
-- Copyright (C) 2005-2025 Regis Houssin <regis.houssin@inodbox.com>
-- Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
-- Copyright (C) 2010-2016 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2012 Sebastian Neuwert <sebastian.neuwert@modula71.de>
-- Copyright (C) 2012 Ricardo Schluter <info@ripasch.nl>
-- Copyright (C) 2022 Miro Sertić <miro.sertic0606@gmail.com>
-- Copyright (C) 2001-2004 Rodolphe Quiedeville <rodolphe@quiedeville.org>
-- Copyright (C) 2003 Jean-Louis Bergamo <jlb@j1b.org>
-- Copyright (C) 2004-2011 Laurent Destailleur <eldy@users.sourceforge.net>
-- Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
-- Copyright (C) 2004 Guillaume Delecourt <guillaume.delecourt@opensides.be>
-- Copyright (C) 2005-2025 Regis Houssin <regis.houssin@inodbox.com>
-- Copyright (C) 2007 Patrick Raguin <patrick.raguin@gmail.com>
-- Copyright (C) 2010-2016 Juanjo Menent <jmenent@2byte.es>
-- Copyright (C) 2012 Sebastian Neuwert <sebastian.neuwert@modula71.de>
-- Copyright (C) 2012 Ricardo Schluter <info@ripasch.nl>
-- Copyright (C) 2022 Miro Sertić <miro.sertic0606@gmail.com>
-- Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.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
@ -188,7 +189,8 @@ insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (8
-- ITALY (id country=3)
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '0','0','VAT rate 0',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '10','0','VAT rate - reduced',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '10','0','VAT rate - reduced 1',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '5','0','VAT rate - reduced 2',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '4','0','VAT rate - super-reduced',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (3, '22','0','VAT rate - standard',1,__ENTITY__);
@ -235,9 +237,8 @@ insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (1
-- NEDERLAND (id country=17)
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '0','0','0 BTW tarief', 1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '6','0','Verlaagd BTW tarief', 1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '19','0','Algemeen BTW tarief',1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '21','0','Algemeen BTW tarief (vanaf 1 oktober 2012)',0,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '9','0','Verlaagd BTW tarief', 1,__ENTITY__);
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (17, '21','0','Algemeen BTW tarief',0,__ENTITY__);
-- NEW CALEDONIA (id country=165)
insert into llx_c_tva(fk_pays,taux,recuperableonly,note,active,entity) values (165, '0','0','VAT rate 0', 1,__ENTITY__);

View file

@ -3261,121 +3261,123 @@ function left_menu($menu_array_before, $helppagename = '', $notused = '', $menu_
}
// Dolibarr version + help + bug report link
print "\n";
print "<!-- Begin Help Block-->\n";
print '<div id="blockvmenuhelp" class="blockvmenuhelp">'."\n";
if (getDolGlobalString('MAIN_SHOW_VERSION') || getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) {
print "\n";
print "<!-- Begin Help Block-->\n";
print '<div id="blockvmenuhelp" class="blockvmenuhelp">'."\n";
// Version
if (getDolGlobalString('MAIN_SHOW_VERSION')) { // Version is already on help picto and on login page.
$doliurl = 'https://www.dolibarr.org';
//local communities
if (preg_match('/fr/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.fr';
}
if (preg_match('/es/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.es';
}
if (preg_match('/de/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.de';
}
if (preg_match('/it/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.it';
}
if (preg_match('/gr/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.gr';
// Version
if (getDolGlobalString('MAIN_SHOW_VERSION')) { // Version is already on help picto and on login page.
$doliurl = 'https://www.dolibarr.org';
//local communities
if (preg_match('/fr/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.fr';
}
if (preg_match('/es/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.es';
}
if (preg_match('/de/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.de';
}
if (preg_match('/it/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.it';
}
if (preg_match('/gr/i', $langs->defaultlang)) {
$doliurl = 'https://www.dolibarr.gr';
}
$appli = constant('DOL_APPLICATION_TITLE');
$applicustom = getDolGlobalString('MAIN_APPLICATION_TITLE');
if ($applicustom) {
$appli = (preg_match('/^\+/', $applicustom) ? $appli : '').$applicustom;
} else {
$appli .= " ".DOL_VERSION;
}
// Clean doliurl if we use a custom application name
if ($applicustom) {
$doliurl = '';
}
print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">';
if ($doliurl) {
print '<a class="help" target="_blank" rel="noopener noreferrer" href="'.$doliurl.'">';
} else {
print '<span class="help">';
}
print $appli;
if ($doliurl) {
print '</a>';
} else {
print '</span>';
}
print '</div>'."\n";
}
$appli = constant('DOL_APPLICATION_TITLE');
$applicustom = getDolGlobalString('MAIN_APPLICATION_TITLE');
if ($applicustom) {
$appli = (preg_match('/^\+/', $applicustom) ? $appli : '').$applicustom;
} else {
$appli .= " ".DOL_VERSION;
// Link to bugtrack
if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK') == 'github') {
$bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new?labels=Bug';
$bugbaseurl .= '&title=';
$bugbaseurl .= urlencode("Bug: ");
$bugbaseurl .= '&body=';
$bugbaseurl .= urlencode("# Instructions\n");
$bugbaseurl .= urlencode("*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*\n");
$bugbaseurl .= urlencode("*Please:*\n");
$bugbaseurl .= urlencode("- *replace the bracket enclosed texts with meaningful information*\n");
$bugbaseurl .= urlencode("- *remove any unused sub-section*\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("# Bug\n");
$bugbaseurl .= urlencode("[*Short description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Environment\n");
$bugbaseurl .= urlencode("- **Version**: ".DOL_VERSION."\n");
$bugbaseurl .= urlencode("- **OS**: ".php_uname('s')."\n");
$bugbaseurl .= urlencode("- **Web server**: ".$_SERVER["SERVER_SOFTWARE"]."\n");
$bugbaseurl .= urlencode("- **PHP**: ".php_sapi_name().' '.phpversion()."\n");
$bugbaseurl .= urlencode("- **Database**: ".$db::LABEL.' '.$db->getVersion()."\n");
$bugbaseurl .= urlencode("- **URL(s)**: ".$_SERVER["REQUEST_URI"]."\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Expected and actual behavior\n");
$bugbaseurl .= urlencode("[*Verbose description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Steps to reproduce the behavior\n");
$bugbaseurl .= urlencode("[*Verbose description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging information…)\n");
$bugbaseurl .= urlencode("[*Files*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Report\n");
} elseif (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) {
$bugbaseurl = getDolGlobalString('MAIN_BUGTRACK_ENABLELINK');
} else {
$bugbaseurl = "";
}
// Execute hook printBugtrackInfo
$parameters = array('bugbaseurl' => $bugbaseurl);
$reshook = $hookmanager->executeHooks('printBugtrackInfo', $parameters); // Note that $action and $object may have been modified by some hooks
if (empty($reshook)) {
$bugbaseurl .= $hookmanager->resPrint;
} else {
$bugbaseurl = $hookmanager->resPrint;
}
print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">';
print '<a class="help" target="_blank" rel="noopener noreferrer" href="'.$bugbaseurl.'"><i class="fas fa-bug"></i> '.$langs->trans("FindBug").'</a>';
print '</div>';
}
// Clean doliurl if we use a custom application name
if ($applicustom) {
$doliurl = '';
}
print '<div id="blockvmenuhelpapp" class="blockvmenuhelp">';
if ($doliurl) {
print '<a class="help" target="_blank" rel="noopener noreferrer" href="'.$doliurl.'">';
} else {
print '<span class="help">';
}
print $appli;
if ($doliurl) {
print '</a>';
} else {
print '</span>';
}
print '</div>'."\n";
print "</div>\n";
print "<!-- End Help Block-->\n";
print "\n";
}
// Link to bugtrack
if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) {
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
if (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK') == 'github') {
$bugbaseurl = 'https://github.com/Dolibarr/dolibarr/issues/new?labels=Bug';
$bugbaseurl .= '&title=';
$bugbaseurl .= urlencode("Bug: ");
$bugbaseurl .= '&body=';
$bugbaseurl .= urlencode("# Instructions\n");
$bugbaseurl .= urlencode("*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.*\n");
$bugbaseurl .= urlencode("*Please:*\n");
$bugbaseurl .= urlencode("- *replace the bracket enclosed texts with meaningful information*\n");
$bugbaseurl .= urlencode("- *remove any unused sub-section*\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("# Bug\n");
$bugbaseurl .= urlencode("[*Short description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Environment\n");
$bugbaseurl .= urlencode("- **Version**: ".DOL_VERSION."\n");
$bugbaseurl .= urlencode("- **OS**: ".php_uname('s')."\n");
$bugbaseurl .= urlencode("- **Web server**: ".$_SERVER["SERVER_SOFTWARE"]."\n");
$bugbaseurl .= urlencode("- **PHP**: ".php_sapi_name().' '.phpversion()."\n");
$bugbaseurl .= urlencode("- **Database**: ".$db::LABEL.' '.$db->getVersion()."\n");
$bugbaseurl .= urlencode("- **URL(s)**: ".$_SERVER["REQUEST_URI"]."\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Expected and actual behavior\n");
$bugbaseurl .= urlencode("[*Verbose description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Steps to reproduce the behavior\n");
$bugbaseurl .= urlencode("[*Verbose description*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging information…)\n");
$bugbaseurl .= urlencode("[*Files*]\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("\n");
$bugbaseurl .= urlencode("## Report\n");
} elseif (getDolGlobalString('MAIN_BUGTRACK_ENABLELINK')) {
$bugbaseurl = getDolGlobalString('MAIN_BUGTRACK_ENABLELINK');
} else {
$bugbaseurl = "";
}
// Execute hook printBugtrackInfo
$parameters = array('bugbaseurl' => $bugbaseurl);
$reshook = $hookmanager->executeHooks('printBugtrackInfo', $parameters); // Note that $action and $object may have been modified by some hooks
if (empty($reshook)) {
$bugbaseurl .= $hookmanager->resPrint;
} else {
$bugbaseurl = $hookmanager->resPrint;
}
print '<div id="blockvmenuhelpbugreport" class="blockvmenuhelp">';
print '<a class="help" target="_blank" rel="noopener noreferrer" href="'.$bugbaseurl.'"><i class="fas fa-bug"></i> '.$langs->trans("FindBug").'</a>';
print '</div>';
}
print "</div>\n";
print "<!-- End Help Block-->\n";
print "\n";
print "</div>\n";
print "<!-- End left menu -->\n";
print "\n";

View file

@ -656,7 +656,6 @@ if (isModEnabled("supplier_order") || isModEnabled("supplier_invoice")) {
print '<td>'.$form->textwithpicto($langs->trans("UseProductSupplierPackaging", $langs->transnoentities("PackagingForThisProduct")), $langs->trans("PackagingForThisProductDesc")).'</td>';
print '<td align="right">';
print ajax_constantonoff("PRODUCT_USE_SUPPLIER_PACKAGING", array(), $conf->entity, 0, 0, 0, 0);
//print $form->selectyesno("activate_useProdSupplierPackaging", (!empty($conf->global->PRODUCT_USE_SUPPLIER_PACKAGING) ? $conf->global->PRODUCT_USE_SUPPLIER_PACKAGING : 0), 1);
print '</td>';
print '</tr>';

View file

@ -333,6 +333,7 @@ class MouvementStock extends CommonObject
if (getDolGlobalInt('PRODUIT_SOUSPRODUITS')) {
$productChildrenNb = $product->hasFatherOrChild(1);
}
if ($product->isStockManaged() && ($productChildrenNb == 0 || getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE'))) { // For kit parent, we disable stock move, except if option PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE is set. For this option on, code must be completed to finish implementation, for example to have kit supported in shipments.
$movestock = 1;
}

View file

@ -11,6 +11,7 @@
* Copyright (C) 2023-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Günter Lukas <github@gl.co.at>
* Copyright (C) 2026 Joachim Kueter <git-jk@bloxera.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
@ -198,6 +199,17 @@ $hookmanager->initHooks(array('projectOverview'));
//if ($user->socid > 0) $socid = $user->socid; // For external user, no check is done on company because readability is managed by public status of project and assignment.
$result = restrictedArea($user, 'projet', $object->id, 'projet&project');
// Check if user has access to any financial module (not just project time)
$canSeeFinancials = (
(isModEnabled('invoice') && $user->hasRight('facture', 'lire'))
|| (isModEnabled('supplier_invoice') && ($user->hasRight('fournisseur', 'facture', 'lire') || $user->hasRight('supplier_invoice', 'lire')))
|| (isModEnabled('salaries') && $user->hasRight('salaries', 'read'))
|| (isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'))
|| (isModEnabled('don') && $user->hasRight('don', 'lire'))
|| (isModEnabled('tax') && $user->hasRight('tax', 'charges', 'lire'))
|| (isModEnabled('bank') && $user->hasRight('banque', 'lire'))
);
$total_duration = 0;
$total_ttc_by_line = 0;
$total_ht_by_line = 0;
@ -723,7 +735,7 @@ $listofreferent = array(
'margin' => 'minus',
'table' => 'projet_task',
'datefieldname' => 'element_date',
'disableamount' => 0,
'disableamount' => ($canSeeFinancials ? 0 : 1),
'urlnew' => DOL_URL_ROOT.'/projet/tasks/time.php?withproject=1&action=createtime&projectid='.$id.'&backtopage='.urlencode($_SERVER['PHP_SELF'].'?id='.$id),
'buttonnew' => 'AddTimeSpent',
'testnew' => $user->hasRight('project', 'creer'),
@ -935,6 +947,10 @@ foreach ($listofreferent as $key => $value) {
$tablename = $value['table'];
$datefieldname = $value['datefieldname'];
$qualified = $value['test'];
// Hide project_task amounts in profit section for users without financial access
if ($key === 'project_task' && !$canSeeFinancials) {
$qualified = false;
}
$margin = empty($value['margin']) ? 0 : $value['margin'];
$project_field = empty($value['project_field']) ? '' : $value['project_field'];
if ($qualified) { // If this element must be included into profit summary table ($margin is '', 'minus' or 'add')

View file

@ -10,6 +10,7 @@
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Vincent de Grandpré <vincent@de-grandpre.quebec>
* Copyright (C) 2024 Solution Libre SAS <contact@solution-libre.fr>
* Copyright (C) 2026 Joachim Kueter <git-jk@bloxera.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
@ -1893,7 +1894,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
if (isModEnabled("service") && !empty($projectstatic->thirdparty) && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
print '<td class="nowraponall">';
print img_picto('', 'service');
print $form->select_produits((GETPOSTISSET('fk_product') ? GETPOSTINT("fk_product") : ''), 'fk_product', 1, 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1);
print $form->select_produits((GETPOSTISSET('fk_product') ? GETPOSTINT("fk_product") : ''), 'fk_product', 1, 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', ($user->hasRight('produit', 'lire') ? 0 : 1), '', null, 1);
print '</td>';
}
}
@ -2462,7 +2463,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '<td class="nowraponall">';
if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
print img_picto('', 'service');
print $form->select_produits($task_time->fk_product, 'fk_product', 1, 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500', 0, '', null, 1);
print $form->select_produits($task_time->fk_product, 'fk_product', 1, 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500', ($user->hasRight('produit', 'lire') ? 0 : 1), '', null, 1);
} elseif (!empty($task_time->fk_product)) {
$product = new Product($db);
$resultFetch = $product->fetch($task_time->fk_product);
@ -2517,19 +2518,23 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
if ($task_time->invoice_id) {
$result = $tmpinvoice->fetch($task_time->invoice_id);
if ($result > 0) {
if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
print $formproject->selectInvoiceAndLine($task_time->invoice_id, $task_time->invoice_line_id, 'invoiceid', 'invoicelineid', 'maxwidth500', array('p.rowid' => $projectstatic->id));
} else {
print $tmpinvoice->getNomUrl(1);
if (!empty($task_time->invoice_line_id)) {
$invoiceLine = new FactureLigne($db);
$invoiceLine->fetch($task_time->invoice_line_id);
if (!empty($invoiceLine->id)) {
print '<br><span class="small opacitymedium">'.$langs->trans('Qty').':'.$invoiceLine->qty;
print ' '.$langs->trans('TotalHT').':'.price($invoiceLine->total_ht);
print '</span>';
if ($user->hasRight('facture', 'lire')) {
if ($action == 'editline' && GETPOSTINT('lineid') == $task_time->rowid) {
print $formproject->selectInvoiceAndLine($task_time->invoice_id, $task_time->invoice_line_id, 'invoiceid', 'invoicelineid', 'maxwidth500', array('p.rowid' => $projectstatic->id));
} else {
print $tmpinvoice->getNomUrl(1);
if (!empty($task_time->invoice_line_id)) {
$invoiceLine = new FactureLigne($db);
$invoiceLine->fetch($task_time->invoice_line_id);
if (!empty($invoiceLine->id)) {
print '<br><span class="small opacitymedium">'.$langs->trans('Qty').':'.$invoiceLine->qty;
print ' '.$langs->trans('TotalHT').':'.price($invoiceLine->total_ht);
print '</span>';
}
}
}
} else {
print $langs->trans("Yes");
}
}
$invoiced = true;

View file

@ -14,6 +14,7 @@
* Copyright (C) 2022-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Nick Fragoulis
* Copyright (C) 2026 Mathieu Moulin <mathieu@iprospective.fr>
*
* 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

View file

@ -96,6 +96,9 @@ $MAXPRODUCT = getDolGlobalInt('TAKEPOS_NB_MAXPRODUCT', $maxproductbydefaultforth
$term = empty($_SESSION['takeposterminal']) ? 1 : $_SESSION['takeposterminal'];
$socid = getDolGlobalInt('CASHDESK_ID_THIRDPARTY' . $term);
/*
$constforcompanyid = 'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"];
$soc = new Societe($db);
@ -362,8 +365,15 @@ function LoadProducts(position, issubcat) {
if (maxproduct >= 1) {
limit = maxproduct - 1;
}
// Get socid
let socid = jQuery('#thirdpartyid').val();
if ((socid === undefined || socid === "") && parseInt("<?php echo dol_escape_js($socid) ?>") > 0) {
socid = parseInt("<?php echo dol_escape_js($socid); ?>");
}
// Only show products for sale (tosell=1)
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&thirdpartyid=' + jQuery('#thirdpartyid').val() + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset=0', function(data) {
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&thirdpartyid=' + socid + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset=0', function(data) {
/* Fill thumbs from ishow to end max of products with products loaded into data array */
console.log("Call ajax.php (in LoadProducts) to get Products of category "+currentcat+" then loop on result to fill image thumbs");
console.log("Found "+data.length+" record");
@ -487,10 +497,18 @@ function MoreProducts(moreorless) {
if (maxproduct >= 1) {
limit = maxproduct-1;
}
var nb_cat_shown = $('.div5 div.wrapper2[data-iscat=1]').length;
var offset = <?php echo($MAXPRODUCT - 2); ?> * pageproducts - nb_cat_shown;
var offset = <?php echo ($MAXPRODUCT - 2); ?> * pageproducts - nb_cat_shown;
// Get socid
let socid = jQuery('#thirdpartyid').val();
if ((socid === undefined || socid === "") && parseInt("<?php echo dol_escape_js($socid) ?>") > 0) {
socid = parseInt("<?php echo dol_escape_js($socid); ?>");
}
// Only show products for sale (tosell=1)
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&thirdpartyid=' + jQuery('#thirdpartyid').val() + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) {
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&thirdpartyid=' + socid + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) {
console.log("Call ajax.php (in MoreProducts) to get Products of category "+currentcat);
if (typeof (data[0]) == "undefined" && moreorless=="more"){ // Return if no more pages
@ -772,7 +790,14 @@ function Search2(keyCodeForEnter, moreorless) {
pageproducts = 0;
jQuery(".wrapper2 .catwatermark").hide();
var nbsearchresults = 0;
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=search&token=<?php echo newToken();?>&search_term=' + search_term + '&thirdpartyid=' + jQuery('#thirdpartyid').val() + '&search_start=' + search_start + '&search_limit=' + search_limit, function (data) {
// Only show products for sale (tosell=1)
let socid = jQuery('#thirdpartyid').val();
if ((socid === undefined || socid === "") && parseInt("<?php echo dol_escape_js($socid) ?>") > 0) {
socid = parseInt("<?php echo dol_escape_js($socid); ?>");
}
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=search&token=<?php echo newToken();?>&search_term=' + search_term + '&thirdpartyid=' + socid + '&search_start=' + search_start + '&search_limit=' + search_limit, function (data) {
for (i = 0; i < <?php echo $MAXPRODUCT ?>; i++) {
if (typeof (data[i]) == "undefined") {
$("#prowatermark" + i).html("");

View file

@ -1889,7 +1889,16 @@ select.flat.selectlimit {
margin-top: 25px !important;
}
.navselectiondate {
width: 250px;
min-width: 250px;
}
.showonhover:hover *::before {
visibility: visible !important;
display: inline-block !important;
}
.showonhover:not(:hover) *::before {
visibility: hidden;
display: inline-block !important;
}
/* Styles for amount on card */
@ -2608,6 +2617,7 @@ td.showDragHandle {
display: table-cell;
<?php } ?>
border-<?php echo $right; ?>: 1px solid #ECECEC;
border-bottom: 1px solid #ECECEC;
box-shadow: 3px 0 6px -2px #eee;
background: var(--colorbackvmenu1);
transition: left 0.5s ease;

View file

@ -2014,6 +2014,10 @@ select.flat.selectlimit {
.tablelistofcalendars {
margin-top: 25px !important;
}
.navselectiondate {
min-width: 250px;
}
.amountalreadypaid {
white-space: nowrap;
}
@ -2063,6 +2067,16 @@ select.flat.selectlimit {
border-radius: 5px;
}
.showonhover:hover *::before {
visibility: visible !important;
display: inline-block !important;
}
.showonhover:not(:hover) *::before {
visibility: hidden;
display: inline-block !important;
}
.savingdocmask {
margin-top: 6px;
margin-bottom: 12px;