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

This commit is contained in:
Laurent Destailleur (aka Eldy) 2025-02-12 15:50:23 +01:00
commit 863248b618
10 changed files with 141 additions and 37 deletions

View File

@ -469,6 +469,12 @@ if ($filtert > 0 || $usergroup > 0) {
if ($usergroup > 0) {
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."usergroup_user as ugu ON ugu.fk_user = ar.fk_element";
}
// Add table from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListFrom', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint;
$sql .= " WHERE a.entity IN (".getEntity('agenda').")";
// Condition on actioncode
if (!empty($actioncode)) {

View File

@ -2554,6 +2554,9 @@ class Facture extends CommonInvoice
if (isset($this->retained_warranty)) {
$this->retained_warranty = (float) $this->retained_warranty;
}
if (!isset($this->fk_user_author) && isset($this->user_author) ) {
$this->fk_user_author = $this->user_author;
}
// Check parameters
// Put here code to add control on parameters values
@ -2581,6 +2584,7 @@ class Facture extends CommonInvoice
$sql .= " total_ttc=".(isset($this->total_ttc) ? (float) $this->total_ttc : "null").",";
$sql .= " revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp != '') ? (float) $this->revenuestamp : "null").",";
$sql .= " fk_statut=".(isset($this->status) ? (int) $this->status : "null").",";
$sql .= " fk_user_author=".(isset($this->fk_user_author) ? ((int) $this->fk_user_author) : "null").",";
$sql .= " fk_user_valid=".(isset($this->fk_user_valid) ? (int) $this->fk_user_valid : "null").",";
$sql .= " fk_facture_source=".(isset($this->fk_facture_source) ? (int) $this->fk_facture_source : "null").",";
$sql .= " fk_projet=".(isset($this->fk_project) ? (int) $this->fk_project : "null").",";
@ -3324,10 +3328,17 @@ class Facture extends CommonInvoice
}
}
if ($key == 'TVA_INTRA') {
// Check for mandatory
if (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY') && ($this->thirdparty->tva_assuj) && empty($this->thirdparty->tva_intra)) {
// Check for mandatory vat number
if (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY') == 'eeconly') {
if (($this->thirdparty->tva_assuj) && empty($this->thirdparty->tva_intra) && $this->thirdparty->isInEEC()) {
$langs->load("errors");
$this->error = $langs->trans('ErrorProdIdIsMandatoryForEuThirdparties', $langs->transnoentitiesnoconv('VATIntra')).' ('.$langs->transnoentitiesnoconv("ForbiddenBySetupRules").') ['.$langs->trans('Company').' : '.$this->thirdparty->name.']';
dol_syslog(__METHOD__.' '.$this->error, LOG_ERR);
return -1;
}
} elseif (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY') && ($this->thirdparty->tva_assuj) && empty($this->thirdparty->tva_intra)) {
$langs->load("errors");
$this->error = $langs->trans('ErrorProdIdIsMandatory', $langs->trans('VATIntra')).' ('.$langs->trans("ForbiddenBySetupRules").') ['.$langs->trans('Company').' : '.$this->thirdparty->name.']';
$this->error = $langs->trans('ErrorProdIdIsMandatory', $langs->transnoentitiesnoconv('VATIntra')).' ('.$langs->transnoentitiesnoconv("ForbiddenBySetupRules").') ['.$langs->trans('Company').' : '.$this->thirdparty->name.']';
dol_syslog(__METHOD__.' '.$this->error, LOG_ERR);
return -1;
}

View File

@ -785,13 +785,16 @@ if ($object->id > 0 || !empty($object->ref)) {
print '</td>'; // Dispatch column
print '<td></td>'; // Warehouse column
$sql = "SELECT ed.rowid, ed.qty, ed.fk_entrepot,";
$sql .= " eb.batch, eb.eatby, eb.sellby, cd.fk_product";
$sql .= " FROM ".MAIN_DB_PREFIX."expeditiondet as ed";
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet";
$sql .= " JOIN ".MAIN_DB_PREFIX."commandedet as cd on ed.fk_elementdet = cd.rowid";
$sql .= " WHERE ed.fk_elementdet =".(int) $objp->rowid;
$sql .= " AND ed.fk_expedition =".(int) $object->id;
$sql = "SELECT ed.rowid";
$sql .= ", cd.fk_product";
$sql .= ", ".$db->ifsql('eb.rowid IS NULL', 'ed.qty', 'eb.qty')." as qty";
$sql .= ", ed.fk_entrepot";
$sql .= ", eb.batch, eb.eatby, eb.sellby";
$sql .= " FROM ".$db->prefix()."expeditiondet as ed";
$sql .= " LEFT JOIN ".$db->prefix()."expeditiondet_batch as eb on ed.rowid = eb.fk_expeditiondet";
$sql .= " INNER JOIN ".$db->prefix()."commandedet as cd on ed.fk_origin_line = cd.rowid";
$sql .= " WHERE ed.fk_origin_line = ".(int) $objp->rowid;
$sql .= " AND ed.fk_expedition = ".(int) $object->id;
$sql .= " ORDER BY ed.rowid, ed.fk_elementdet";
$resultsql = $db->query($sql);

View File

@ -737,6 +737,7 @@ if (empty($reshook)) {
unset($_POST['date_end_fill']);
unset($_POST['situations']);
unset($_POST['progress']);
unset($_POST['fourn_ref']);
} else {
setEventMessages($object->error, $object->errors, 'errors');
}
@ -879,6 +880,7 @@ if (empty($reshook)) {
unset($_POST['date_endyear']);
unset($_POST['situations']);
unset($_POST['progress']);
unset($_POST['fourn_ref']);
} else {
setEventMessages($object->error, $object->errors, 'errors');
}

View File

@ -412,6 +412,7 @@ SaleExport=Export sale
SaleEEC=Sale in EEC
SaleEECWithVAT=Sale in EEC with a VAT not null, so we suppose this is NOT an intracommunautary sale and the suggested account is the standard product account.
SaleEECWithoutVATNumber=Sale in EEC with no VAT but the VAT ID of third party is not defined. We fall back on the account for standard sales. You can fix the VAT ID of the third party, or change the product account suggested for binding if needed.
AnySale=Any sale
ForbiddenTransactionAlreadyExported=Forbidden: The transaction has been validated and/or exported.
ForbiddenTransactionAlreadyValidated=Forbidden: The transaction has been validated.
DataMustHaveBeenTransferredInAccounting=The transfer of data in accounting must have been done

View File

@ -31,6 +31,7 @@ ErrorFromToAccountsMustDiffers=Source and targets bank accounts must be differen
ErrorBadThirdPartyName=Bad value for third-party name
ForbiddenBySetupRules=Forbidden by setup rules
ErrorProdIdIsMandatory=The %s is mandatory
ErrorProdIdIsMandatoryForEuThirdparties=The %s is mandatory for customers in EEC
ErrorAccountancyCodeCustomerIsMandatory=The accountancy code of customer %s is mandatory
ErrorAccountancyCodeSupplierIsMandatory=The accountancy code of supplier %s is mandatory
ErrorBadCustomerCodeSyntax=Bad syntax for customer code

View File

@ -5561,8 +5561,6 @@ class Product extends CommonObject
*/
public function getChildsArbo($id, $firstlevelonly = 0, $level = 1, $parents = array())
{
global $alreadyfound;
if (empty($id)) {
return array();
}
@ -5579,9 +5577,6 @@ class Product extends CommonObject
dol_syslog(get_class($this).'::getChildsArbo id='.$id.' level='.$level. ' parents='.(is_array($parents) ? implode(',', $parents) : $parents), LOG_DEBUG);
if ($level == 1) {
$alreadyfound = array($id => 1); // We init array of found object to start of tree, so if we found it later (should not happened), we stop immediately
}
// Protection against infinite loop
if ($level > 30) {
return array();
@ -5590,14 +5585,16 @@ class Product extends CommonObject
$res = $this->db->query($sql);
if ($res) {
$prods = array();
if ($this->db->num_rows($res) > 0) {
$parents[] = $id;
}
while ($rec = $this->db->fetch_array($res)) {
if (!empty($alreadyfound[$rec['rowid']])) {
if (in_array($rec['id'], $parents)) {
dol_syslog(get_class($this).'::getChildsArbo the product id='.$rec['rowid'].' was already found at a higher level in tree. We discard to avoid infinite loop', LOG_WARNING);
if (in_array($rec['id'], $parents)) {
continue; // We discard this child if it is already found at a higher level in tree in the same branch.
}
continue; // We discard this child if it is already found at a higher level in tree in the same branch.
}
$alreadyfound[$rec['rowid']] = 1;
$prods[$rec['rowid']] = array(
0 => $rec['rowid'],
1 => $rec['qty'],
@ -5611,7 +5608,6 @@ class Product extends CommonObject
//$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty'],2=>$rec['fk_product_type']);
//$prods[$this->db->escape($rec['label'])]= array(0=>$rec['id'],1=>$rec['qty']);
if (empty($firstlevelonly)) {
$parents[] = $rec['rowid'];
$listofchilds = $this->getChildsArbo($rec['rowid'], 0, $level + 1, $parents);
foreach ($listofchilds as $keyChild => $valueChild) {
$prods[$rec['rowid']]['childs'][$keyChild] = $valueChild;

View File

@ -978,7 +978,7 @@ if (getDolGlobalString('MEMBER_SKIP_TABLE') || getDolGlobalString('MEMBER_NEWFOR
}
}
//htmlPrintOnlineFooter($mysoc, $langs);
llxFooterVierge();
$db->close();

View File

@ -185,6 +185,62 @@ $hookmanager->initHooks(array('onlinesign'));
$error = 0;
/**
* Show header for online signature
*
* @param string $title Title
* @param string $head Head array
* @param int $disablejs More content into html header
* @param int $disablehead More content into html header
* @param string[]|string $arrayofjs Array of complementary js files
* @param string[]|string $arrayofcss Array of complementary css files
* @return void
*/
function llxHeaderVierge($title, $head = "", $disablejs = 0, $disablehead = 0, $arrayofjs = [], $arrayofcss = [])
{
global $conf, $langs, $mysoc;
top_htmlhead($head, $title, $disablejs, $disablehead, $arrayofjs, $arrayofcss); // Show html headers
print '<body id="mainbody" class="publicnewmemberform">';
// Define urllogo
$urllogo = DOL_URL_ROOT.'/theme/common/login_logo.png';
if (!empty($mysoc->logo_small) && is_readable($conf->mycompany->dir_output.'/logos/thumbs/'.$mysoc->logo_small)) {
$urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/thumbs/'.$mysoc->logo_small);
} elseif (!empty($mysoc->logo) && is_readable($conf->mycompany->dir_output.'/logos/'.$mysoc->logo)) {
$urllogo = DOL_URL_ROOT.'/viewimage.php?cache=1&amp;modulepart=mycompany&amp;file='.urlencode('logos/'.$mysoc->logo);
} elseif (is_readable(DOL_DOCUMENT_ROOT.'/theme/dolibarr_logo.svg')) {
$urllogo = DOL_URL_ROOT.'/theme/dolibarr_logo.svg';
}
print '<header class="center">';
// Output html code for logo
if ($urllogo) {
print '<div class="backgreypublicpayment">';
print '<div class="logopublicpayment">';
print '<img id="dolpaymentlogo" src="'.$urllogo.'">';
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('MEMBER_IMAGE_PUBLIC_REGISTRATION')) {
print '<div class="backimagepublicregistration">';
print '<img id="idEVENTORGANIZATION_IMAGE_PUBLIC_INTERFACE" src="' . getDolGlobalString('MEMBER_IMAGE_PUBLIC_REGISTRATION').'">';
print '</div>';
}
print '</header>';
print '<div class="divmainbodylarge">';
}
/*
* Actions
@ -233,6 +289,7 @@ if ($action == 'confirm_refusepropal' && $confirm == 'yes') { // Test on pemriss
*/
$form = new Form($db);
$head = '';
if (getDolGlobalString('MAIN_SIGN_CSS_URL')) {
$head = '<link rel="stylesheet" type="text/css" href="' . getDolGlobalString('MAIN_SIGN_CSS_URL').'?lang='.$langs->defaultlang.'">'."\n";
@ -241,8 +298,12 @@ if (getDolGlobalString('MAIN_SIGN_CSS_URL')) {
$conf->dol_hide_topmenu = 1;
$conf->dol_hide_leftmenu = 1;
$title = $langs->trans("OnlineSignature");
$replacemainarea = (empty($conf->dol_hide_leftmenu) ? '<div>' : '').'<div>';
llxHeader($head, $langs->trans("OnlineSignature"), '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1);
llxHeader($head, $title, '', '', 0, 0, '', '', '', 'onlinepaymentbody', $replacemainarea, 1);
llxHeaderVierge($title);
if ($action == 'refusepropal') {
print $form->formconfirm($_SERVER["PHP_SELF"].'?ref='.urlencode($ref).'&securekey='.urlencode($SECUREKEY).(isModEnabled('multicompany') ? '&entity='.$entity : ''), $langs->trans('RefusePropal'), $langs->trans('ConfirmRefusePropal', $object->ref), 'confirm_refusepropal', '', '', 1);

View File

@ -43,7 +43,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
* @var User $user
*/
$langs->loadLangs(array("admin", "companies", "other"));
$langs->loadLangs(array("admin", "accountancy", "companies", "other"));
$action = GETPOST('action', 'aZ09');
$value = GETPOST('value', 'alpha');
@ -329,9 +329,11 @@ if ($action == 'setprofidmandatory') {
}
//Activate ProfId invoice mandatory
if ($action == 'setprofidinvoicemandatory') {
if ($action == 'setprofidinvoicemandatory' || $action == 'setprofidinvoicemandatoryeeconly') {
$status = GETPOST('status', 'alpha');
if ($status == '1' && $action == 'setprofidinvoicemandatoryeeconly') {
$status = 'eeconly';
}
$idprof = "SOCIETE_".$value."_INVOICE_MANDATORY";
$result = dolibarr_set_const($db, $idprof, $status, 'chaine', 0, '', $conf->entity);
if ($result <= 0) {
@ -777,31 +779,52 @@ print '<td colspan="2">'.$langs->trans('VATIntra')."</td>\n";
$key = 'VAT_INTRA';
if (getDolGlobalString('SOCIETE_VAT_INTRA_UNIQUE')) {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofid&token='.newToken().'&value='.$key.'&status=0">';
print img_picto($langs->trans("Activated"), 'switch_on');
print img_picto($langs->trans("Activated"), 'switch_on', 'class="valignmiddle"');
print '</a></td>';
} else {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofid&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print img_picto($langs->trans("Disabled"), 'switch_off', 'class="valignmiddle"');
print '</a></td>';
}
if (getDolGlobalString('SOCIETE_VAT_INTRA_MANDATORY')) {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidmandatory&token='.newToken().'&value='.$key.'&status=0">';
print img_picto($langs->trans("Activated"), 'switch_on');
print img_picto($langs->trans("Activated"), 'switch_on', 'class="valignmiddle"');
print '</a></td>';
} else {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidmandatory&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print img_picto($langs->trans("Disabled"), 'switch_off', 'class="valignmiddle"');
print '</a></td>';
}
if (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY')) {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatory&token='.newToken().'&value='.$key.'&status=0">';
print img_picto($langs->trans("Activated"), 'switch_on');
print '</a></td>';
print '<td class="center">';
if (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY') == 'eeconly') {
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatoryeeconly&token='.newToken().'&value='.$key.'&status=0">';
print img_picto($langs->trans("Activated"), 'switch_on', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("SaleEEC").'<br>';
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatory&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Activated"), 'switch_off', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("AnySale");
} elseif (getDolGlobalString('SOCIETE_VAT_INTRA_INVOICE_MANDATORY')) {
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatoryeeconly&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Activated"), 'switch_off', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("SaleEEC").'<br>';
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatory&token='.newToken().'&value='.$key.'&status=0">';
print img_picto($langs->trans("Activated"), 'switch_on', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("AnySale");
} else {
print '<td class="center"><a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatory&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Disabled"), 'switch_off');
print '</a></td>';
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatoryeeconly&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Disabled"), 'switch_off', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("SaleEEC").'<br>';
print '<a class="reposition" href="'.$_SERVER['PHP_SELF'].'?action=setprofidinvoicemandatory&token='.newToken().'&value='.$key.'&status=1">';
print img_picto($langs->trans("Disabled"), 'switch_off', 'class="valignmiddle paddingrightonly"');
print '</a>';
print $langs->trans("AnySale");
}
print '</td>';
print "</tr>\n";
print "</table>\n";