diff --git a/dev/build/phpstan/phpstan-baseline.neon b/dev/build/phpstan/phpstan-baseline.neon index be42a96344b..9650d6771b0 100644 --- a/dev/build/phpstan/phpstan-baseline.neon +++ b/dev/build/phpstan/phpstan-baseline.neon @@ -9096,12 +9096,6 @@ parameters: count: 1 path: ../../../htdocs/core/class/commonobject.class.php - - - message: '#^Parameter \#17 \$pa_ht of method Commande\:\:updateline\(\) expects int, float given\.$#' - identifier: argument.type - count: 1 - path: ../../../htdocs/core/class/commonobject.class.php - - message: '#^Parameter \#2 \$line of method CommonObject\:\:printObjectLine\(\) expects CommonObjectLine, CommonObject\|stdClass given\.$#' identifier: argument.type @@ -20244,12 +20238,6 @@ parameters: count: 2 path: ../../../htdocs/fourn/commande/dispatch.php - - - message: '#^Variable \$reception might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../../htdocs/fourn/commande/dispatch.php - - message: '#^If condition is always false\.$#' identifier: if.alwaysFalse @@ -28734,12 +28722,6 @@ parameters: count: 16 path: ../../../htdocs/public/webportal/webportal.main.inc.php - - - message: '#^Variable \$logged_partnership might not be defined\.$#' - identifier: variable.undefined - count: 1 - path: ../../../htdocs/public/webportal/webportal.main.inc.php - - message: '#^Negated boolean expression is always false\.$#' identifier: booleanNot.alwaysFalse diff --git a/dev/tools/fixcopyrightheader.php b/dev/tools/fixcopyrightheader.php index bda934bf3b7..423c455f596 100755 --- a/dev/tools/fixcopyrightheader.php +++ b/dev/tools/fixcopyrightheader.php @@ -1,6 +1,6 @@ #!/usr/bin/env php +/* Copyright (C) 2024-2025 MDW * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -125,9 +125,11 @@ function updateCopyrightNotice($filename, $fileType, $name, $email) $matches = array(); if (preg_match($pattern, $lines, $matches)) { $existingYear = $matches['last']; + $startYear = null; if (array_key_exists('start', $matches)) { $startYear = $matches['start']; - } else { + } + if (empty($startYear)) { $startYear = $existingYear; } @@ -135,7 +137,6 @@ function updateCopyrightNotice($filename, $fileType, $name, $email) if ($existingYear !== date('Y')) { // Extend the year range to the current year $updatedNotice = preg_replace('/(?:\d{4}-)?\d{4}\s+/', $startYear . '-' . date('Y') . "\t", $matches[0]); - // Replace the old notice with the updated one in the file file_put_contents($filename, preg_replace($pattern, $updatedNotice, file_get_contents($filename))); return true; // Change detected diff --git a/dev/tools/phan/baseline.txt b/dev/tools/phan/baseline.txt index 524c56158ce..65d97c5a1e7 100644 --- a/dev/tools/phan/baseline.txt +++ b/dev/tools/phan/baseline.txt @@ -11,7 +11,7 @@ return [ // # Issue statistics: // PhanUndeclaredProperty : 560+ occurrences // PhanPossiblyUndeclaredGlobalVariable : 310+ occurrences - // PhanUndeclaredGlobalVariable : 290+ occurrences + // PhanUndeclaredGlobalVariable : 280+ occurrences // PhanTypeMismatchArgumentProbablyReal : 230+ occurrences // PhanPluginUnknownArrayMethodReturnType : 180+ occurrences // PhanTypeMismatchProperty : 130+ occurrences @@ -34,7 +34,7 @@ return [ // PhanPluginSuspiciousParamPosition : 7 occurrences // PhanTypeArraySuspiciousNull : 6 occurrences // PhanParamTooMany : 5 occurrences - // PhanPossiblyNullTypeMismatchProperty : 5 occurrences + // PhanPossiblyNullTypeMismatchProperty : 4 occurrences // PhanEmptyFQSENInClasslike : 3 occurrences // PhanInvalidFQSENInClasslike : 3 occurrences // PhanTypeMismatchReturn : 3 occurrences @@ -310,7 +310,6 @@ return [ 'htdocs/fourn/class/fournisseur.commande.class.php' => ['PhanUndeclaredProperty'], 'htdocs/fourn/commande/card.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchDimAssignment', 'PhanTypeMismatchProperty', 'PhanTypeSuspiciousStringExpression', 'PhanUndeclaredProperty'], 'htdocs/fourn/commande/contact.php' => ['PhanUndeclaredGlobalVariable'], - 'htdocs/fourn/commande/dispatch.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/fourn/commande/document.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/fourn/commande/info.php' => ['PhanUndeclaredGlobalVariable'], 'htdocs/fourn/commande/list.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgumentProbablyReal'], @@ -469,7 +468,7 @@ return [ 'htdocs/public/ticket/create_ticket.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchDimFetchNullable', 'PhanTypeMismatchProperty'], 'htdocs/public/ticket/view.php' => ['PhanPossiblyUndeclaredGlobalVariable', 'PhanTypeMismatchArgumentProbablyReal'], 'htdocs/public/webportal/tpl/menu.tpl.php' => ['PhanUndeclaredProperty'], - 'htdocs/public/webportal/webportal.main.inc.php' => ['PhanPossiblyNullTypeMismatchProperty', 'PhanPossiblyUndeclaredGlobalVariable', 'PhanRedefineFunction'], + 'htdocs/public/webportal/webportal.main.inc.php' => ['PhanRedefineFunction'], 'htdocs/public/website/index.php' => ['PhanRedefineFunction'], 'htdocs/public/website/javascript.js.php' => ['PhanRedefineFunction'], 'htdocs/public/website/styles.css.php' => ['PhanRedefineFunction'], diff --git a/htdocs/accountancy/admin/index.php b/htdocs/accountancy/admin/index.php index 39a52e9621a..0c422f24fc6 100644 --- a/htdocs/accountancy/admin/index.php +++ b/htdocs/accountancy/admin/index.php @@ -1,13 +1,13 @@ - * Copyright (C) 2013-2014 Florian Henry - * Copyright (C) 2013-2024 Alexandre Spangaro - * Copyright (C) 2014-2015 Ari Elbaz (elarifr) - * Copyright (C) 2014 Marcos García - * Copyright (C) 2014 Juanjo Menent - * Copyright (C) 2015 Jean-François Ferry - * Copyright (C) 2017 Laurent Destailleur - * Copyright (C) 2021 Ferran Marcet +/* Copyright (C) 2013-2014 Olivier Geffroy + * Copyright (C) 2013-2014 Florian Henry + * Copyright (C) 2013-2024 Alexandre Spangaro + * Copyright (C) 2014-2015 Ari Elbaz (elarifr) + * Copyright (C) 2014 Marcos García + * Copyright (C) 2014 Juanjo Menent + * Copyright (C) 2015 Jean-François Ferry + * Copyright (C) 2017 Laurent Destailleur + * Copyright (C) 2021 Ferran Marcet * Copyright (C) 2024 Frédéric France * * This program is free software; you can redistribute it and/or modify @@ -329,6 +329,20 @@ if ($action == 'setenablevatreversecharge') { } } +if ($action == 'setenabletabonthirdparty') { + $setenabletabonthirdparty = GETPOSTINT('value'); + $res = dolibarr_set_const($db, "ACCOUNTING_ENABLE_TABONTHIRDPARTY", $setenabletabonthirdparty, 'yesno', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } + + if (!$error) { + setEventMessages($langs->trans("SetupSaved"), null, 'mesgs'); + } else { + setEventMessages($langs->trans("Error"), null, 'mesgs'); + } +} + /* * View @@ -646,6 +660,20 @@ if (getDolGlobalString('ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE')) { } print ''; +print ''; +print ''; +print $form->textwithpicto($langs->trans("ACCOUNTING_ENABLE_TABONTHIRDPARTY"), $langs->trans("ACCOUNTING_ENABLE_TABONTHIRDPARTY_DESC")).''; +if (getDolGlobalString('ACCOUNTING_ENABLE_TABONTHIRDPARTY')) { + print ''; + print img_picto($langs->trans("Activated"), 'switch_on'); + print ''; +} else { + print ''; + print img_picto($langs->trans("Disabled"), 'switch_off'); + print ''; +} +print ''; + print ''; print ''; diff --git a/htdocs/accountancy/bookkeeping/listbyaccount.php b/htdocs/accountancy/bookkeeping/listbyaccount.php index 7834b2a6d0f..17663bf411b 100644 --- a/htdocs/accountancy/bookkeeping/listbyaccount.php +++ b/htdocs/accountancy/bookkeeping/listbyaccount.php @@ -30,6 +30,7 @@ require '../../main.inc.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/lettering.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/bookkeeping.class.php'; require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php'; @@ -51,6 +52,7 @@ $langs->loadLangs(array("accountancy", "compta")); $action = GETPOST('action', 'aZ09'); $socid = GETPOSTINT('socid'); +$mode = (GETPOST('mode', 'alpha') ? GETPOST('mode', 'alpha') : 'customer'); // Only for tab view $massaction = GETPOST('massaction', 'alpha'); $confirm = GETPOST('confirm', 'alpha'); $toselect = GETPOST('toselect', 'array'); @@ -305,6 +307,9 @@ if (empty($reshook)) { $toselect = array(); } + if (!empty($socid)) { + $param = '&socid='.$socid; + } if (!empty($search_date_start)) { $filter['t.doc_date>='] = $search_date_start; $param .= '&search_date_startmonth='.$search_date_startmonth.'&search_date_startday='.$search_date_startday.'&search_date_startyear='.$search_date_startyear; @@ -425,33 +430,6 @@ if (empty($reshook)) { $param = '&type='.$type.$param; } - //if ($action == 'delbookkeepingyearconfirm' && $user->hasRight('accounting', 'mouvements', 'supprimer')_tous) { - // $delmonth = GETPOST('delmonth', 'int'); - // $delyear = GETPOST('delyear', 'int'); - // if ($delyear == -1) { - // $delyear = 0; - // } - // $deljournal = GETPOST('deljournal', 'alpha'); - // if ($deljournal == -1) { - // $deljournal = 0; - // } - // - // if (!empty($delmonth) || !empty($delyear) || !empty($deljournal)) { - // $result = $object->deleteByYearAndJournal($delyear, $deljournal, '', ($delmonth > 0 ? $delmonth : 0)); - // if ($result < 0) { - // setEventMessages($object->error, $object->errors, 'errors'); - // } else { - // setEventMessages("RecordDeleted", null, 'mesgs'); - // } - // - // // Make a redirect to avoid to launch the delete later after a back button - // header("Location: ".$_SERVER["PHP_SELF"].($param ? '?'.$param : '')); - // exit; - // } else { - // setEventMessages("NoRecordDeleted", null, 'warnings'); - // } - //} - // Mass actions $objectclass = 'Bookkeeping'; $objectlabel = 'Bookkeeping'; @@ -617,6 +595,115 @@ $title_page .= ')'; $help_url = 'EN:Module_Double_Entry_Accounting|FR:Module_Comptabilité_en_Partie_Double'; llxHeader('', $title_page, $help_url, '', 0, 0, '', '', '', 'mod-accountancy accountancy-consultation page-'.(($type == 'sub') ? 'sub' : '').'ledger'); +if (!empty($socid)) { + $companystatic = new Societe($db); + $res = $companystatic->fetch($socid); + if ($res > 0) { + $tmpobject = $object; + $object = $companystatic; // $object must be of type Societe when calling societe_prepare_head + $head = societe_prepare_head($companystatic); + $object = $tmpobject; + + print dol_get_fiche_head($head, 'accounting', $langs->trans("ThirdParty"), -1, 'company'); + + $linkback = ''.$langs->trans("BackToList").''; + + dol_banner_tab($companystatic, 'socid', $linkback, ($user->socid ? 0 : 1), 'rowid', 'nom'); + + print '
'; + + print '
'; + print ''; + + // Type Prospect/Customer/Supplier + print ''; + + // Customer code + if ($companystatic->client && !empty($companystatic->code_client)) { + print ''; + print ''; + } + // Supplier code + if ($companystatic->fournisseur && !empty($companystatic->code_fournisseur)) { + print ''; + print ''; + } + + print '
'.$langs->trans('NatureOfThirdParty').''; + print $companystatic->getTypeUrl(1); + print '
'; + print $langs->trans('CustomerCode').''; + print showValueWithClipboardCPButton(dol_escape_htmltag($companystatic->code_client)); + $tmpcheck = $companystatic->check_codeclient(); + if ($tmpcheck != 0 && $tmpcheck != -5) { + print ' ('.$langs->trans("WrongCustomerCode").')'; + } + print '
'; + print $langs->trans('SupplierCode').''; + print showValueWithClipboardCPButton(dol_escape_htmltag($companystatic->code_fournisseur)); + $tmpcheck = $companystatic->check_codefournisseur(); + if ($tmpcheck != 0 && $tmpcheck != -5) { + print ' ('.$langs->trans("WrongSupplierCode").')'; + } + print '
'; + print '
'; + print dol_get_fiche_end(); + + print info_admin($langs->trans("WarningThisPageContainsOnlyEntriesTransferredInAccounting")); + + // Choice of mode (customer / supplier) + if (!empty($conf->dol_use_jmobile)) { + print "\n".'
'."\n"; + } + + if ($companystatic->client && !empty($companystatic->code_compta_client)) { + if ($mode != 'customer') { + if (!empty($companystatic->code_compta_client)) { + $subledger_start_account = $subledger_end_account = $companystatic->code_compta_client; + } else { + $subledger_start_account = $subledger_end_account = ''; + } + print ''; + } else { + print ''; + } + + print $langs->trans("CustomerAccountancyCodeShort"); + if ($mode != 'customer') { + print ''; + } else { + print ''; + } + } + + if ($companystatic->fournisseur && !empty($companystatic->code_compta_fournisseur)) { + if ($mode != 'supplier') { + if (!empty($companystatic->code_compta_fournisseur)) { + $subledger_start_account = $subledger_end_account = $companystatic->code_compta_fournisseur; + } else { + $subledger_start_account = $subledger_end_account = ''; + } + print ''; + } else { + print ''; + } + print $langs->trans("SupplierAccountancyCodeShort"); + if ($mode != 'supplier') { + print ''; + } else { + print ''; + } + } + + if (!empty($conf->dol_use_jmobile)) { + print '
'; + } else { + print '
'; + } + print '
'; + } +} + // List $nbtotalofrecords = ''; if (!getDolGlobalInt('MAIN_DISABLE_FULL_SCANLIST')) { @@ -650,47 +737,6 @@ if (!$error) { $arrayofselected = is_array($toselect) ? $toselect : array(); - -///if ($action == 'delbookkeepingyear') { -// $form_question = array(); -// $delyear = GETPOST('delyear', 'int'); -// $deljournal = GETPOST('deljournal', 'alpha'); -// -// if (empty($delyear)) { -// $delyear = dol_print_date(dol_now(), '%Y'); -// } -// $month_array = array(); -// for ($i = 1; $i <= 12; $i++) { -// $month_array[$i] = $langs->trans("Month".sprintf("%02d", $i)); -// } -// $year_array = $formaccounting->selectyear_accountancy_bookkepping($delyear, 'delyear', 0, 'array'); -// $journal_array = $formaccounting->select_journal($deljournal, 'deljournal', '', 1, 1, 1, '', 0, 1); -// -// $form_question['delmonth'] = array( -// 'name' => 'delmonth', -// 'type' => 'select', -// 'label' => $langs->trans('DelMonth'), -// 'values' => $month_array, -// 'default' => '' -// ); -// $form_question['delyear'] = array( -// 'name' => 'delyear', -// 'type' => 'select', -// 'label' => $langs->trans('DelYear'), -// 'values' => $year_array, -// 'default' => $delyear -// ); -// $form_question['deljournal'] = array( -// 'name' => 'deljournal', -// 'type' => 'other', // We don't use select here, the journal_array is already a select html component -// 'label' => $langs->trans('DelJournal'), -// 'value' => $journal_array, -// 'default' => $deljournal -// ); -// -// $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?'.$param, $langs->trans('DeleteMvt'), $langs->trans('ConfirmDeleteMvt', $langs->transnoentitiesnoconv("RegistrationInAccounting")), 'delbookkeepingyearconfirm', $form_question, '', 1, 300); -//} - // Print form confirm $formconfirm = ''; print $formconfirm; @@ -722,6 +768,9 @@ if ($optioncss != '') { } print ''; print ''; +if (!empty($socid)) { + print ''; +} print ''; print ''; print ''; @@ -735,15 +784,18 @@ if ($reshook < 0) { $newcardbutton = empty($hookmanager->resPrint) ? '' : $hookmanager->resPrint; if (empty($reshook)) { - $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT.'/accountancy/bookkeeping/list.php?'.$param); - if ($type == 'sub') { - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly')); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); - } else { - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); - $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + // Remove button navigation if in thirdparty tab mode + if (empty($socid)) { + $newcardbutton = dolGetButtonTitle($langs->trans('ViewFlatList'), '', 'fa fa-list paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/list.php?' . $param); + if ($type == 'sub') { + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + } else { + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupByAccountAccounting'), '', 'fa fa-stream paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?' . $url_param, '', 1, array('morecss' => 'marginleftonly btnTitleSelected')); + $newcardbutton .= dolGetButtonTitle($langs->trans('GroupBySubAccountAccounting'), '', 'fa fa-align-left vmirror paddingleft imgforviewmode', DOL_URL_ROOT . '/accountancy/bookkeeping/listbyaccount.php?type=sub&' . $url_param, '', 1, array('morecss' => 'marginleftonly')); + } + $newcardbutton .= dolGetButtonTitleSeparator(); } - $newcardbutton .= dolGetButtonTitleSeparator(); $newcardbutton .= dolGetButtonTitle($langs->trans('NewAccountingMvt'), '', 'fa fa-plus-circle paddingleft', DOL_URL_ROOT.'/accountancy/bookkeeping/card.php?action=create'); } @@ -763,17 +815,7 @@ if ($massaction == 'preunletteringauto') { } elseif ($massaction == 'predeletebookkeepingwriting') { print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassDeleteBookkeepingWriting"), $langs->trans("ConfirmMassDeleteBookkeepingWritingQuestion", count($toselect)), "deletebookkeepingwriting", null, '', 0, 200, 500, 1); } -//DeleteMvt=Supprimer des lignes d'opérations de la comptabilité -//DelMonth=Mois à effacer -//DelYear=Année à supprimer -//DelJournal=Journal à supprimer -//ConfirmDeleteMvt=Cette action supprime les lignes des opérations pour l'année/mois et/ou pour le journal sélectionné (au moins un critère est requis). Vous devrez utiliser de nouveau la fonctionnalité '%s' pour retrouver vos écritures dans la comptabilité. -//ConfirmDeleteMvtPartial=Cette action supprime l'écriture de la comptabilité (toutes les lignes opérations liées à une même écriture seront effacées). -//$topicmail = "Information"; -//$modelmail = "accountingbookkeeping"; -//$objecttmp = new BookKeeping($db); -//$trackid = 'bk'.$object->id; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; @@ -789,8 +831,8 @@ if (preg_match('/^asc/i', $sortorder)) { $sortorder = "desc"; } -// Warning to explain why list of record is not consistent with the other list view (missing a lot of lines) -if ($type == 'sub') { +// Warning to explain why the list of record is not consistent with the other list view (missing a lot of lines) +if ($type == 'sub' && !$socid) { print info_admin($langs->trans("WarningRecordWithoutSubledgerAreExcluded")); } @@ -811,17 +853,19 @@ if ($type == 'sub') { } else { $moreforfilter .= $formaccounting->select_account($search_accountancy_code_end, 'search_accountancy_code_end', $langs->trans('to'), array(), 1, 1, 'maxwidth200'); } -$stringforfirstkey = $langs->trans("KeyboardShortcut"); -if ($conf->browser->name == 'chrome') { - $stringforfirstkey .= ' ALT +'; -} elseif ($conf->browser->name == 'firefox') { - $stringforfirstkey .= ' ALT + SHIFT +'; -} else { - $stringforfirstkey .= ' CTL +'; -} -$moreforfilter .= '   '; -$moreforfilter .= '   '; -$moreforfilter .= << SCRIPT; +} $moreforfilter .= ''; $moreforfilter .= ''; -$moreforfilter .= '
'; -$moreforfilter .= $langs->trans('AccountingCategory').': '; -$moreforfilter .= '
'; -$moreforfilter .= $formaccounting->select_accounting_category($search_account_category, 'search_account_category', 1, 0, 0, 0); -$moreforfilter .= '
'; -$moreforfilter .= '
'; +if (empty($socid)) { + $moreforfilter .= '
'; + $moreforfilter .= $langs->trans('AccountingCategory') . ': '; + $moreforfilter .= '
'; + $moreforfilter .= $formaccounting->select_accounting_category($search_account_category, 'search_account_category', 1, 0, 0, 0); + $moreforfilter .= '
'; + $moreforfilter .= '
'; +} $parameters = array(); $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook @@ -1486,13 +1533,6 @@ print $hookmanager->resPrint; print ""; print ''; -// TODO Replace this with mass delete action -//if ($user->hasRight('accounting', 'mouvements, 'supprimer_tous')) { -// print '
'."\n"; -// print ''.$langs->trans("DeleteMvt").''; -// print '
'; -//} - print ''; // End of page diff --git a/htdocs/comm/propal/class/propal.class.php b/htdocs/comm/propal/class/propal.class.php index 3359667e3b2..2d63be548dd 100644 --- a/htdocs/comm/propal/class/propal.class.php +++ b/htdocs/comm/propal/class/propal.class.php @@ -13,7 +13,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2015 Marcos García * Copyright (C) 2018 Nicolas ZABOURI - * Copyright (C) 2018-2024 Frédéric France + * Copyright (C) 2018-2025 Frédéric France * Copyright (C) 2018 Ferran Marcet * Copyright (C) 2022 ATM Consulting * Copyright (C) 2022 OpenDSI @@ -864,7 +864,7 @@ class Propal extends CommonObject * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price - * @param int $pa_ht Price (without tax) of product when it was bought + * @param float $pa_ht Price (without tax) of product when it was bought * @param string $label ??? * @param int $type 0/1=Product/service * @param int|string $date_start Start date of the line diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index e3b381a518a..c67828a8a89 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -11,7 +11,7 @@ * Copyright (C) 2014-2015 Marcos García * Copyright (C) 2018 Nicolas ZABOURI * Copyright (C) 2016-2022 Ferran Marcet - * Copyright (C) 2021-2024 Frédéric France + * Copyright (C) 2021-2025 Frédéric France * Copyright (C) 2022 Gauthier VERDOL * Copyright (C) 2024 MDW * Copyright (C) 2024 William Mead @@ -36,7 +36,7 @@ * \brief class for orders */ -include_once DOL_DOCUMENT_ROOT.'/core/class/commonorder.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/commonorder.class.php'; require_once DOL_DOCUMENT_ROOT.'/commande/class/orderline.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT.'/margin/lib/margins.lib.php'; @@ -461,6 +461,7 @@ class Commande extends CommonOrder } $obj = new $classname(); + /** @var ModeleNumRefCommandes $obj */ '@phan-var-force ModeleNumRefCommandes $obj'; $numref = $obj->getNextValue($soc, $this); @@ -3123,7 +3124,7 @@ class Commande extends CommonOrder * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price - * @param int $pa_ht Price (without tax) of product when it was bought + * @param float $pa_ht Price (without tax) of product when it was bought * @param string $label Label * @param int $special_code Special code (also used by externals modules!) * @param array $array_options extrafields array diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 0d1435fa918..b4e9e4e24da 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -21,7 +21,7 @@ * Copyright (C) 2023 Gauthier VERDOL * Copyright (C) 2023 Nick Fragoulis * Copyright (C) 2024 MDW - * Copyright (C) 2024 Frédéric France + * Copyright (C) 2024-2025 Frédéric France * * 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 @@ -4145,7 +4145,7 @@ class Facture extends CommonInvoice * @param int $fk_parent_line Id of parent line (0 in most cases, used by modules adding sublevels into lines). * @param int $skip_update_total Keep fields total_xxx to 0 (used for special lines by some modules) * @param int $fk_fournprice Id of origin supplier price - * @param int $pa_ht Price (without tax) of product when it was bought + * @param float $pa_ht Price (without tax) of product when it was bought * @param string $label Label of the line (deprecated, do not use) * @param int $special_code Special code (also used by externals modules!) * @param array $array_options extrafields array diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 0f83d2dc1f4..8999641d19a 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -9,7 +9,7 @@ * Copyright (C) 2013 Florian Henry * Copyright (C) 2014-2015 Marcos García * Copyright (C) 2018 Nicolas ZABOURI - * Copyright (C) 2018-2024 Frédéric France + * Copyright (C) 2018-2025 Frédéric France * Copyright (C) 2015-2018 Ferran Marcet * Copyright (C) 2024 William Mead * Copyright (C) 2024 MDW @@ -1701,7 +1701,7 @@ class Contrat extends CommonObject * @param string $price_base_type HT or TTC * @param int $info_bits Bits of type of lines * @param int $fk_fournprice Fourn price id - * @param int $pa_ht Buying price HT + * @param float $pa_ht Buying price HT * @param array $array_options extrafields array * @param string $fk_unit Code of the unit to use. Null to use the default one * @param int $rang Position diff --git a/htdocs/core/class/commondocgenerator.class.php b/htdocs/core/class/commondocgenerator.class.php index 7404c634f77..625d3584382 100644 --- a/htdocs/core/class/commondocgenerator.class.php +++ b/htdocs/core/class/commondocgenerator.class.php @@ -779,6 +779,14 @@ abstract class CommonDocGenerator $resarray[$array_key.'_total_discount_ht'] = ''; } + if ($object->element == 'facture' || $object->element == 'invoice_supplier') { + if ($object->type == 0) { + $resarray[$array_key.'_type_label'] = $outputlangs->transnoentities("PdfInvoiceTitle"); + } else { + $resarray[$array_key.'_type_label'] = (empty($object)) ? '' : $object->getLibType(0); + } + } + // Fetch project information if there is a project assigned to this object if ($object->element != "project" && !empty($object->fk_project) && $object->fk_project > 0) { if (!is_object($object->project)) { diff --git a/htdocs/core/lib/company.lib.php b/htdocs/core/lib/company.lib.php index a4682c21a13..a28d7d61931 100644 --- a/htdocs/core/lib/company.lib.php +++ b/htdocs/core/lib/company.lib.php @@ -141,6 +141,25 @@ function societe_prepare_head(Societe $object) $h++; } + if (isModEnabled('accounting') && getDolGlobalString('ACCOUNTING_ENABLE_TABONTHIRDPARTY') && ($user->hasRight('accounting', 'mouvements', 'lire'))) { + // link to customer account by default + if (!empty($object->code_compta_client)) { + $subledger_start_account = $subledger_end_account = $object->code_compta_client; + $mode = 'customer'; + } elseif (!empty($object->code_compta_fournisseur)) { + $subledger_start_account = $subledger_end_account = $object->code_compta_fournisseur; + $mode = 'supplier'; + } else { + $subledger_start_account = $subledger_end_account = ''; + $mode = 'customer'; + } + + $head[$h][0] = DOL_URL_ROOT.'/accountancy/bookkeeping/listbyaccount.php?socid='.$object->id.'&mode='.$mode.'&type=sub&search_accountancy_code_start='.$subledger_start_account.'&search_accountancy_code_end='.$subledger_end_account; + $head[$h][1] = $langs->trans("Accounting"); + $head[$h][2] = 'accounting'; + $h++; + } + if (isModEnabled('project') && ($user->hasRight('projet', 'lire'))) { $nbProject = 0; // Enable caching of thirdrparty count projects @@ -1402,7 +1421,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserl print ''; // Action column if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + print ''; print $form->showFilterButtons(); print ''; } @@ -1449,7 +1468,7 @@ function show_contacts($conf, $langs, $db, $object, $backtopage = '', $showuserl print $hookmanager->resPrint; // Action column if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { - print ''; + print ''; print $form->showFilterButtons(); print ''; } diff --git a/htdocs/core/tpl/objectline_view.tpl.php b/htdocs/core/tpl/objectline_view.tpl.php index 93bc95c0a12..58ccc4e50ff 100644 --- a/htdocs/core/tpl/objectline_view.tpl.php +++ b/htdocs/core/tpl/objectline_view.tpl.php @@ -126,6 +126,12 @@ $coldisplay = 0;
$line, 'i' =>& $i, 'coldisplay' =>& $coldisplay]; +$reshook = $hookmanager->executeHooks('objectLineView_BeforeProduct', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; + if (($line->info_bits & 2) == 2) { print ''; $txt = ''; @@ -267,8 +273,12 @@ if (($line->info_bits & 2) == 2) { } } + + $parameters = ['line' => $line, 'i' =>& $i, 'coldisplay' =>& $coldisplay]; + $reshook = $hookmanager->executeHooks('objectLineView_BeforeProductExtrafield', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + print $hookmanager->resPrint; // Line extrafield - if (!empty($extrafields)) { + if (!empty($extrafields) && empty($reshook)) { $temps = $line->showOptionals($extrafields, 'view', array(), '', '', 1, 'line'); if (!empty($temps)) { print '
'; @@ -278,17 +288,22 @@ if (($line->info_bits & 2) == 2) { } } -if ($user->hasRight('fournisseur', 'lire') && isset($line->fk_fournprice) && $line->fk_fournprice > 0 && !getDolGlobalString('SUPPLIER_HIDE_SUPPLIER_OBJECTLINES')) { - require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; - $productfourn = new ProductFournisseur($this->db); - $productfourn->fetch_product_fournisseur_price($line->fk_fournprice); - print '
'; - print ''.$langs->trans('Supplier').' : '.$productfourn->getSocNomUrl(1, 'supplier').' - '.$langs->trans('Ref').' : '; - // Supplier ref - if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { // change required right here - print $productfourn->getNomUrl(); - } else { - print $productfourn->ref_supplier; +$parameters = ['line' => $line, 'i' =>& $i, 'coldisplay' =>& $coldisplay]; +$reshook = $hookmanager->executeHooks('objectLineView_ProductSupplier', $parameters, $object, $action); // Note that $action and $object may have been modified by hook +print $hookmanager->resPrint; +if (empty($reshook)) { + if ($user->hasRight('fournisseur', 'lire') && isset($line->fk_fournprice) && $line->fk_fournprice > 0 && !getDolGlobalString('SUPPLIER_HIDE_SUPPLIER_OBJECTLINES')) { + require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php'; + $productfourn = new ProductFournisseur($this->db); + $productfourn->fetch_product_fournisseur_price($line->fk_fournprice); + print '
'; + print ''.$langs->trans('Supplier').' : '.$productfourn->getSocNomUrl(1, 'supplier').' - '.$langs->trans('Ref').' : '; + // Supplier ref + if ($user->hasRight('produit', 'creer') || $user->hasRight('service', 'creer')) { // change required right here + print $productfourn->getNomUrl(); + } else { + print $productfourn->ref_supplier; + } } } diff --git a/htdocs/install/doctemplates/invoices/template_invoice.odt b/htdocs/install/doctemplates/invoices/template_invoice.odt index 925d9f087cd..5d44e1a606c 100644 Binary files a/htdocs/install/doctemplates/invoices/template_invoice.odt and b/htdocs/install/doctemplates/invoices/template_invoice.odt differ diff --git a/htdocs/install/doctemplates/supplier_invoices/template_supplier_invoices.odt b/htdocs/install/doctemplates/supplier_invoices/template_supplier_invoices.odt index 8ece83c989c..b53c0c79f48 100644 Binary files a/htdocs/install/doctemplates/supplier_invoices/template_supplier_invoices.odt and b/htdocs/install/doctemplates/supplier_invoices/template_supplier_invoices.odt differ diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index c4e8cfb2e9f..0334fccd610 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -313,6 +313,7 @@ ClickOnUseTutorialForHelp=Welcome on the section to generate your accountancy. C NotReconciled=Not reconciled WarningRecordWithoutSubledgerAreExcluded=Warning, all lines without subledger account defined are filtered and excluded from this view AccountRemovedFromCurrentChartOfAccount=Accounting account that does not exist in the current chart of accounts +WarningThisPageContainsOnlyEntriesTransferredInAccounting=Warning, this page only contains entries transferred to the accounting system. ## Admin BindingOptions=Options for the transfer in accountancy ApplyMassCategories=Apply mass categories @@ -347,6 +348,8 @@ ACCOUNTING_LETTERING_NBLETTERS_DESC=Some accounting software only accepts a two- OptionsAdvanced=Advanced options ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE=Activate the management of VAT reverse charge on supplier purchases ACCOUNTING_FORCE_ENABLE_VAT_REVERSE_CHARGE_DESC=When this option is enabled, you can define that a supplier or a given vendor invoice must be transferred into accountancy differently: A additional debit and a credit line will generated into the accounting on 2 given accounts from the chart of account defined into the "%s" setup page. +ACCOUNTING_ENABLE_TABONTHIRDPARTY=Activate a tab on third-party cards to view the subsidiary ledger +ACCOUNTING_ENABLE_TABONTHIRDPARTY_DESC=When this option is enabled, a new tab is showing in third-party cards to view and manage accounting for the third-party as to reconcile, print & more ## Export NotExportLettering=Do not export the lettering when generating the file NotifiedExportDate=Flag not yet exported lines as Exported (to modify a line flagged as exported, you will need to delete the whole transaction and re-transfert it into accounting) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 18c3171271b..5c15a78aad6 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1363,19 +1363,19 @@ class Product extends CommonObject $this->note_private = (isset($this->note_private) ? trim($this->note_private) : null); $this->note_public = (isset($this->note_public) ? trim($this->note_public) : null); $this->net_measure = price2num($this->net_measure); - $this->net_measure_units = (empty($this->net_measure_units) ? '' : trim((string) $this->net_measure_units)); + $this->net_measure_units = (is_null($this->net_measure_units) ? '' : trim((string) $this->net_measure_units)); $this->weight = price2num($this->weight); - $this->weight_units = (empty($this->weight_units) ? '' : trim((string) $this->weight_units)); + $this->weight_units = (is_null($this->weight_units) ? '' : trim((string) $this->weight_units)); $this->length = price2num($this->length); - $this->length_units = (empty($this->length_units) ? '' : trim((string) $this->length_units)); + $this->length_units = (is_null($this->length_units) ? '' : trim((string) $this->length_units)); $this->width = price2num($this->width); - $this->width_units = (empty($this->width_units) ? '' : trim((string) $this->width_units)); + $this->width_units = (is_null($this->width_units) ? '' : trim((string) $this->width_units)); $this->height = price2num($this->height); - $this->height_units = (empty($this->height_units) ? '' : trim((string) $this->height_units)); + $this->height_units = (is_null($this->height_units) ? '' : trim((string) $this->height_units)); $this->surface = price2num($this->surface); - $this->surface_units = (empty($this->surface_units) ? '' : trim((string) $this->surface_units)); + $this->surface_units = (is_null($this->surface_units) ? '' : trim((string) $this->surface_units)); $this->volume = price2num($this->volume); - $this->volume_units = (empty($this->volume_units) ? '' : trim((string) $this->volume_units)); + $this->volume_units = (is_null($this->volume_units) ? '' : trim((string) $this->volume_units)); // set unit not defined if (is_numeric($this->length_units)) {