Compare commits

..

68 Commits

Author SHA1 Message Date
Laurent Destailleur
1c367a59d3 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-12-03 21:39:57 +01:00
Laurent Destailleur
9392e0a9b6 CSS 2025-12-03 21:39:31 +01:00
Laurent Destailleur
3f0ec8dc78 Fix setup margin 2025-12-03 18:39:34 +01:00
Laurent Destailleur
caf65afa7e WIP LNE 2025-12-03 18:19:06 +01:00
Laurent Destailleur
7847408006 WIP LNE 2025-12-03 15:40:42 +01:00
Laurent Destailleur
a4114d61be Fix replace DISTINCT 2025-12-03 12:35:09 +01:00
Laurent Destailleur
e2595b5117 Fix LNE 2025-12-02 22:37:49 +01:00
Laurent Destailleur
793d846d94 Debug v23 2025-12-02 21:40:15 +01:00
Laurent Destailleur
10b087e209 Fix yearly events and duplicate recurring events 2025-12-02 21:33:09 +01:00
Laurent Destailleur
e60de6525b WIP Loi finance 2025-12-02 20:29:20 +01:00
Laurent Destailleur
5bcd5db58f Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into develop 2025-12-02 15:11:40 +01:00
Laurent Destailleur
7828311250 Fix export pb in br 2025-12-02 15:04:14 +01:00
Laurent Destailleur
efd58a5f48 Merge branch '22.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2025-12-02 14:54:22 +01:00
Laurent Destailleur
6fbc380e52 FIX Export of extrafield in organized events 2025-12-02 14:54:10 +01:00
Laurent Destailleur
307eaf0321 Trans 2025-12-02 14:07:24 +01:00
Laurent Destailleur
14c949c8c9 Merge pull request #36408 from JonBendtsen/security.lib.php_checkUserAccessToObject_moduleEnabled_0permissions
Qual: DENY access to Thirdparty when module is enabled, but no permissions at all
2025-12-02 10:46:46 +01:00
Laurent Destailleur
d8a4e774bd Debug v23 2025-12-01 21:19:51 +01:00
Laurent Destailleur
2487e7ca5c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-12-01 18:56:50 +01:00
Laurent Destailleur
36fc03aa49 FIX must not allow deletion of invoice if printed or sent by email. 2025-12-01 18:56:18 +01:00
Laurent Destailleur
759c4ba5a9 Merge pull request #36496 from ATM-NicolasV/FIX/FAMILY_VARCHAR
Modification of the family VARCHAR field to VARCHAR(64), causing the failure of module re-activation.
2025-12-01 16:48:29 +01:00
atm-nicolasV
6b6a4163b8 Modification of the family VARCHAR field to VARCHAR(64), causing the failure of module re-activation. 2025-12-01 15:56:29 +01:00
Laurent Destailleur
8980392d8c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-12-01 15:40:57 +01:00
Laurent Destailleur
967865dfe5 CSS 2025-12-01 15:40:42 +01:00
Laurent Destailleur
854adf45f7 Merge pull request #36487 from le-reparateur/patch-4
Add default supplier type handling in card.php in creation mode
2025-12-01 15:24:07 +01:00
Laurent Destailleur
14eab317ef Fix formatting and add new line in card.php 2025-12-01 14:08:11 +01:00
Laurent Destailleur
ca30a6d692 Update card.php 2025-12-01 14:07:28 +01:00
Laurent Destailleur
f40e88d67a Merge pull request #36477 from atm-jonathan/FIX_TICKET_RANDOM_ID_ENTROPY
FIX: ticket module - use random_int() for secure ID generation instea…
2025-12-01 13:55:47 +01:00
Laurent Destailleur
153d750d9c Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
2025-12-01 13:55:35 +01:00
Laurent Destailleur
41fc03c63b Fix: Do not transform [__XXX__] string when
MAIN_RESTRICTHTML_ONLY_VALID_HTML is on.
2025-12-01 13:54:27 +01:00
Laurent Destailleur
47aa1b4001 Update ticket.lib.php 2025-12-01 13:20:45 +01:00
Laurent Destailleur
a96727726e Merge pull request #36488 from BenjaminFlr/35411
FIX(tasks): dates in ganttview
2025-12-01 13:14:03 +01:00
Laurent Destailleur
9cd4c05f5b Merge pull request #36486 from JonBendtsen/API_Timespent_Service_Field_33899
FIX: API task getTimeSpent to actually return data
2025-12-01 13:13:03 +01:00
Laurent Destailleur
ebacc05fe3 Comment 2025-12-01 13:09:18 +01:00
Laurent Destailleur
db6c1cd87f Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-12-01 11:43:22 +01:00
Laurent Destailleur
ab3204a88a Debug v23 2025-12-01 11:42:20 +01:00
Laurent Destailleur
edb73dcaf3 Comment 2025-12-01 11:11:16 +01:00
Laurent Destailleur
b83a13656f Add new phpunit tests 2025-11-30 18:37:58 +01:00
Laurent Destailleur
e932bc0722 Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop 2025-11-30 14:48:55 +01:00
Laurent Destailleur
2eee5bf2a1 CSS 2025-11-30 14:48:33 +01:00
Benjamin Falière
819453b546 FIX (tasks): dates in gantt view 2025-11-30 13:21:13 +01:00
Francis
7b2ceaf177 Add default supplier type handling in card.php in creation mode 2025-11-30 12:11:16 +01:00
Jon Bendtsen
9801f022f9 PHPStan fix 2025-11-30 12:09:08 +01:00
Jon Bendtsen
f7fee10e23 1 more pre-commit check fix 2025-11-30 12:03:57 +01:00
Francis
190da9cb8c Add default supplier type handling in card.php in creation mode
Hi
By default supplier is a professional in creation mode.
2025-11-30 12:01:46 +01:00
Jon Bendtsen
579f1ab1f7 actual pre-commit fix 2025-11-30 11:59:59 +01:00
Jon Bendtsen
bd31e922c8 letting API TASK PUT timespent update the product 2025-11-30 11:59:47 +01:00
Jon Bendtsen
6676171146 fix pre-commit CI check 2025-11-30 11:35:39 +01:00
Jon Bendtsen
58afc38ec4 API POST can now include a product_id 2025-11-30 11:30:01 +01:00
Jon Bendtsen
9a47931329 FIX: API task getTimeSpent to actually return data 2025-11-30 11:04:34 +01:00
Laurent Destailleur
dbd98af0c3 Merge pull request #36485 from JonBendtsen/API_Timespent_Service_Field_33899
FIX #33899 API Timespent Service Field
2025-11-30 10:25:51 +01:00
Jon Bendtsen
18d8cfd510 making a more general fix for checking access to projet_task 2025-11-30 09:35:05 +01:00
Jon Bendtsen
9b0732dd49 FIX: #33899 API Timespent Service Field 2025-11-30 00:02:34 +01:00
Laurent Destailleur
f255dba783 Merge pull request #36481 from BenjaminFlr/accessibility
ENH: Accessibility on modulebuilder setup page
2025-11-29 19:16:09 +01:00
Laurent Destailleur
f4475746c3 Update supported versions for security reports 2025-11-29 16:54:56 +01:00
Laurent Destailleur
62ebfd6f5e Clarify supported versions for security reports 2025-11-29 16:53:58 +01:00
Benjamin Falière
5932aaa9db ENH: Accessibility on modulebuilder setup page
Add label for input fields
2025-11-29 16:39:06 +01:00
atm-jonathan
4a96baed9b FIX: ticket module - use random_int() for secure ID generation instead of microtime 2025-11-29 15:20:15 +01:00
Laurent Destailleur
83fe760c0f Merge pull request #36474 from Dolibarr/phpstan-baseline
PHPStan > Update baseline
2025-11-29 14:50:27 +01:00
Laurent Destailleur
2dcdf773d0 Merge pull request #36400 from atm-jonathan/FIX/ADD_NOCRFCHECK_TO_PASSWORD_FORGOTTEN
Fix: Allow password reset link when CSRF protection is strict
2025-11-26 22:43:31 +01:00
Laurent Destailleur
f1971e1d14 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2025-11-26 22:11:31 +01:00
Laurent Destailleur
5103e2d846 Merge branch '21.0' of git@github.com:Dolibarr/dolibarr.git into 22.0 2025-11-26 22:11:31 +01:00
Laurent Destailleur
9e44c0a5c9 Fix CI 2025-11-26 22:11:09 +01:00
atm-jonathan
b2bb2fea1b Fix: use main.inc.php whitelist instead of defining NOCSRFCHECK locally 2025-11-26 11:11:56 +01:00
Jon Bendtsen
5a5764d73c remove whitespace 2025-11-25 19:28:34 +01:00
Laurent Destailleur
e9a8a4efca Update security.lib.php 2025-11-25 18:50:47 +01:00
Jon Bendtsen
3f90e51792 fix too many parentasies 2025-11-25 18:50:47 +01:00
Jon Bendtsen
966a69bab0 Qual: DENY access to Thirdparty when module is enabled, but no permissions at all 2025-11-25 18:50:47 +01:00
x
b4b202cb18 add nocrfcheck 2025-11-24 15:06:34 +01:00
54 changed files with 904 additions and 364 deletions

View File

@@ -5,7 +5,7 @@ This file contains some policies about the security reports on Dolibarr ERP CRM
## Supported Versions for security reports ## Supported Versions for security reports
Security report are valid only on current stable version (see https://dolibarr.org web site to get current stable version) or on development version (branch "develop" on https://github.com/Dolibarr/dolibarr). Security report are valid only on any current stable version for the last 5 major versions (see https://dolibarr.org web site to get current stable version) or on development version (branch "develop" on https://github.com/Dolibarr/dolibarr).
## Reporting a Vulnerability ## Reporting a Vulnerability

View File

@@ -145,8 +145,6 @@ Barcode
BarcodeDesc BarcodeDesc
BarcodeStickersMask BarcodeStickersMask
BillOfMaterialsLine BillOfMaterialsLine
BlockLogNeedAmountsValue
BlockLogNeedElement
BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote BlockedLogAuthorityNeededToStoreYouFingerprintsInNonAlterableRemote
BlockedLogAuthorityUrl BlockedLogAuthorityUrl
BlockedLogSetup BlockedLogSetup

View File

@@ -30,12 +30,6 @@
// Load Dolibarr environment // Load Dolibarr environment
require '../main.inc.php'; require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/defaultvalues.class.php';
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -43,6 +37,11 @@ require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
* @var Translate $langs * @var Translate $langs
* @var User $user * @var User $user
*/ */
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/agenda.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/defaultvalues.class.php';
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
if (!$user->admin) { if (!$user->admin) {
accessforbidden(); accessforbidden();

View File

@@ -524,9 +524,6 @@ if (empty($reshook)) {
} }
// Rename some POST variables into a generic name // Rename some POST variables into a generic name
if ($field == 'fk_user' && !(GETPOSTINT('fk_user') > 0)) {
$_POST['fk_user'] = '';
}
if ($field == 'topic') { if ($field == 'topic') {
$_POST['topic'] = GETPOST('topic-'.$rowid); $_POST['topic'] = GETPOST('topic-'.$rowid);
} }
@@ -548,7 +545,7 @@ if (empty($reshook)) {
} }
$sql .= $field."="; $sql .= $field."=";
if (GETPOST($keycode) == '' || (!in_array($keycode, array('langcode', 'position', 'private', 'defaultfortype')) && !GETPOST($keycode))) { if ((GETPOST($keycode) == '' && in_array($keycode, array('langcode'))) || (!in_array($keycode, array('langcode', 'position', 'private', 'defaultfortype')) && !GETPOST($keycode))) {
$sql .= "null"; // langcode,... must be '' if not defined so the unique key that include lang will work $sql .= "null"; // langcode,... must be '' if not defined so the unique key that include lang will work
} elseif (GETPOST($keycode) == '0' && $keycode == 'langcode') { } elseif (GETPOST($keycode) == '0' && $keycode == 'langcode') {
$sql .= "''"; // langcode must be '' if not defined so the unique key that include lang will work $sql .= "''"; // langcode must be '' if not defined so the unique key that include lang will work
@@ -560,7 +557,9 @@ if (empty($reshook)) {
} }
} elseif ($keycode == 'content') { } elseif ($keycode == 'content') {
$sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'"; $sql .= "'".$db->escape(GETPOST($keycode, 'restricthtml'))."'";
} elseif (in_array($keycode, array('joinfiles', 'defaultfortype', 'private', 'position'))) { } elseif ($keycode == 'position') {
$sql .= (GETPOSTINT($keycode) > 0 ? GETPOSTINT($keycode) : 1);
} elseif (in_array($keycode, array('joinfiles', 'defaultfortype', 'private'))) {
$sql .= GETPOSTINT($keycode); $sql .= GETPOSTINT($keycode);
} else { } else {
$sql .= "'".$db->escape(GETPOST($keycode, 'alphanohtml'))."'"; $sql .= "'".$db->escape(GETPOST($keycode, 'alphanohtml'))."'";
@@ -572,10 +571,10 @@ if (empty($reshook)) {
if (!$user->admin) { // A non admin user can only edit its own template if (!$user->admin) { // A non admin user can only edit its own template
$sql .= " AND fk_user = ".((int) $user->id); $sql .= " AND fk_user = ".((int) $user->id);
} }
//print $sql;exit;
dol_syslog("actionmodify", LOG_DEBUG); dol_syslog("actionmodify", LOG_DEBUG);
//print $sql; //print $sql; exit;
$resql = $db->query($sql); $resql = $db->query($sql);
if (!$resql) { if (!$resql) {
$error++; $error++;
@@ -731,7 +730,6 @@ $reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters,
$param .= $hookmanager->resPrint; $param .= $hookmanager->resPrint;
$linkback = '';
$titlepicto = 'title_setup'; $titlepicto = 'title_setup';
@@ -1164,7 +1162,8 @@ if ($num) {
if ($obj) { if ($obj) {
if (($action == 'edit' || $action == 'preview') && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) { if (($action == 'edit' || $action == 'preview') && ($rowid == (!empty($obj->rowid) ? $obj->rowid : $obj->code))) {
print '<tr class="nohover oddeven" id="rowid-'.$obj->rowid.'">'; // TODO Move this 2 lines into a popup
print '<tr class="nohover oddeven noborderbottom" id="rowid-'.$obj->rowid.'" name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'">';
$tmpaction = 'edit'; $tmpaction = 'edit';
if ($action == 'edit') { if ($action == 'edit') {
@@ -1180,16 +1179,6 @@ if ($num) {
$colspan = 0; $colspan = 0;
print '<tr><td colspan="12">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
if ($action == 'edit') {
print '<input type="submit" class="button buttongen button-save" name="actionmodify" value="'.$langs->trans("Save").'">';
}
print '<input type="submit" class="button buttongen button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '</td></tr>';
// Action column // Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="center">'; print '<td class="center">';
@@ -1203,20 +1192,16 @@ if ($num) {
// Action column // Action column
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) { if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="center">'; print '<td class="center">';
print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
if ($action == 'edit') {
print '<input type="submit" class="button buttongen button-save" name="actionmodify" value="'.$langs->trans("Modify").'">';
}
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
print '<input type="submit" class="button buttongen button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '</td>'; print '</td>';
$colspan++; $colspan++;
} }
print "</tr>\n"; print "</tr>\n";
print '<tr class="oddeven nohover" id="tr-aaa-'.$rowid.'">'; print '<tr class="oddeven nohover" id="tr-aaa-'.$rowid.'">';
print '<td colspan="'.$colspan.'" class="" style="padding-left: 20px; padding-right: 20px;">'; if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="center"></td>';
}
print '<td colspan="'.($colspan - 1).'" class="" style="padding-left: 20px; padding-right: 20px;">';
$fieldsforcontent = array('topic', 'email_from','joinfiles', 'content'); $fieldsforcontent = array('topic', 'email_from','joinfiles', 'content');
if (getDolGlobalString('MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES')) { if (getDolGlobalString('MAIN_EMAIL_TEMPLATES_FOR_OBJECT_LINES')) {
@@ -1259,7 +1244,7 @@ if ($num) {
if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) { if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) {
$okforextended = false; $okforextended = false;
} }
$doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 500, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '90%', ($action != 'edit' ? 1 : 0)); $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 450, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '80%', ($action != 'edit' ? 1 : 0));
print $doleditor->Create(1); print $doleditor->Create(1);
} }
if ($tmpfieldlist == 'content_lines') { if ($tmpfieldlist == 'content_lines') {
@@ -1269,16 +1254,27 @@ if ($num) {
if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) { if (!getDolGlobalString('FCKEDITOR_ENABLE_MAIL')) {
$okforextended = false; $okforextended = false;
} }
$doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 140, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '90%'); $doleditor = new DolEditor($tmpfieldlist.'-'.$rowid, (!empty($obj->{$tmpfieldlist}) ? $obj->{$tmpfieldlist} : ''), '', 140, 'dolibarr_mailings', 'In', false, $acceptlocallinktomedia, $okforextended, ROWS_6, '80%');
print $doleditor->Create(1); print $doleditor->Create(1);
} }
print '</div>'; print '</div>';
} }
} }
print '</div>'; print '</div>';
print '<center><input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">';
if ($action == 'edit') {
print '<input type="submit" class="button buttongen button-save" name="actionmodify" value="'.$langs->trans("Save").'">';
}
print '<input type="submit" class="button buttongen button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '</center>';
print '</td>'; print '</td>';
print "</tr>\n"; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="center"></td>';
}
print '</tr>';
$nbqualified++; $nbqualified++;
} else { } else {
@@ -1509,7 +1505,7 @@ function fieldList($fieldlist, $obj = null, $tabname = '', $context = '')
} elseif ($value == 'fk_user') { } elseif ($value == 'fk_user') {
print '<td>'; print '<td>';
if ($user->admin && $context != 'preview') { if ($user->admin && $context != 'preview') {
print $form->select_dolusers(GETPOSTISSET('fk_user') ? GETPOSTINT('fk_user') : (empty($obj->$value) ? '' : $obj->$value), 'fk_user', 1, array(), 0, ($user->admin ? '' : 'hierarchyme'), array(), '0', 0, 0, '', 0, '', 'minwidth75 maxwidth100'); print $form->select_dolusers(GETPOSTISSET('fk_user') ? GETPOSTINT('fk_user') : (empty($obj->$value) ? '' : $obj->$value), 'fk_user', $langs->trans("Owner"), array(), 0, ($user->admin ? '' : 'hierarchyme'), array(), '0', 0, 0, '', 0, '', 'minwidth75 maxwidth100');
} else { } else {
if ($context == 'add') { // I am not admin and we show the add form if ($context == 'add') { // I am not admin and we show the add form
print $user->getNomUrl(-1); // Me print $user->getNomUrl(-1); // Me
@@ -1536,7 +1532,7 @@ function fieldList($fieldlist, $obj = null, $tabname = '', $context = '')
if ($context == 'edit') { if ($context == 'edit') {
$selectedlang = $obj->lang; $selectedlang = $obj->lang;
} }
print $formadmin->select_language($selectedlang, 'langcode', 0, array(), 1, 0, 0, 'maxwidth100'); print $formadmin->select_language($selectedlang, 'langcode', 0, array(), $langs->trans("Language"), 0, 0, 'maxwidth100');
} else { } else {
if (!empty($obj->lang)) { if (!empty($obj->lang)) {
print $obj->lang.' - '.$langs->trans('Language_'.$obj->lang); print $obj->lang.' - '.$langs->trans('Language_'.$obj->lang);

View File

@@ -34,10 +34,6 @@ if (!defined('NOTOKENRENEWAL')) {
// Load Dolibarr environment // Load Dolibarr environment
require '../main.inc.php'; require '../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -45,6 +41,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
* @var Translate $langs * @var Translate $langs
* @var User $user * @var User $user
*/ */
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
// Load translation files required by the page // Load translation files required by the page
$langs->loadLangs(array('errors', 'admin', 'modulebuilder', 'exports')); $langs->loadLangs(array('errors', 'admin', 'modulebuilder', 'exports'));
@@ -268,7 +267,7 @@ $head = modulehelp_prepare_head($objMod);
// Check filters // Check filters
$modulename = $objMod->getName(); $modulename = $objMod->getName();
$moduledesc = $objMod->getDesc(); $moduledesc = $objMod->getDesc(1);
$moduleauthor = $objMod->getPublisher(); $moduleauthor = $objMod->getPublisher();
$moduledir = strtolower(preg_replace('/^mod/i', '', get_class($objMod))); $moduledir = strtolower(preg_replace('/^mod/i', '', get_class($objMod)));

View File

@@ -747,25 +747,9 @@ class Asset extends CommonObject
return -1; return -1;
} }
// Old request with 'WITH' $sql = "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht,";
/* $sql .= " " . $this->db->ifsql('EXISTS (SELECT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as ab WHERE ab.doc_type = \'asset\' AND ab.fk_docdet = ad.rowid)', '1', '0') . " AS bookkeeping";
$sql = "WITH in_accounting_bookkeeping(fk_docdet) AS (";
$sql .= " SELECT DISTINCT fk_docdet";
$sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping";
$sql .= " WHERE doc_type = 'asset'";
$sql .= ")";
$sql .= "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht";
$sql .= ", " . $this->db->ifsql('iab.fk_docdet IS NOT NULL', 1, 0) . " AS bookkeeping";
$sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad"; $sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
$sql .= " LEFT JOIN in_accounting_bookkeeping as iab ON iab.fk_docdet = ad.rowid";
$sql .= " WHERE ad.fk_asset = " . (int) $this->id;
$sql .= " ORDER BY ad.depreciation_date ASC";
*/
$sql = "SELECT ad.rowid, ad.depreciation_mode, ad.ref, ad.depreciation_date, ad.depreciation_ht, ad.cumulative_depreciation_ht";
$sql .= ", " . $this->db->ifsql('iab.fk_docdet IS NOT NULL', '1', '0') . " AS bookkeeping";
$sql .= " FROM " . MAIN_DB_PREFIX . "asset_depreciation AS ad";
$sql .= " LEFT JOIN (SELECT DISTINCT fk_docdet FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping WHERE doc_type = 'asset') AS iab ON iab.fk_docdet = ad.rowid";
$sql .= " WHERE ad.fk_asset = " . (int) $this->id; $sql .= " WHERE ad.fk_asset = " . (int) $this->id;
$sql .= " ORDER BY ad.depreciation_date ASC"; $sql .= " ORDER BY ad.depreciation_date ASC";

View File

@@ -4,7 +4,7 @@ BLOCKED LOG
## Feature ## Feature
This module tracks, in real time, some events into a non reversible log (that you can't modify once recorded) into a block chain. This module tracks, in real time, some events into a non reversible log (that you can't modify once recorded) into a block chain.
This module provides compatibility with requirements of laws of some countries (like France with the law Finance 2016 - Norme NF525). This module provides compatibility with requirements of laws of some countries (like France with the Law Finance or Spain with VeriFactu).
**The tracked events are:** **The tracked events are:**
@@ -17,6 +17,3 @@ You can also read and search into this dedicated log.
All record in the log are linked with the previous one in a blockchain, and content of the record is part of the All record in the log are linked with the previous one in a blockchain, and content of the record is part of the
signature included into the link, so, once the module is activated, it is no more possible to erase or modify a record without corrupting all the chain. signature included into the link, so, once the module is activated, it is no more possible to erase or modify a record without corrupting all the chain.

View File

@@ -30,6 +30,7 @@ require '../../main.inc.php';
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
* @var HookManager $hookmanager * @var HookManager $hookmanager
* @var Societe $mysoc
* @var Translate $langs * @var Translate $langs
* @var User $user * @var User $user
*/ */
@@ -90,26 +91,39 @@ $form = new Form($db);
$block_static = new BlockedLog($db); $block_static = new BlockedLog($db);
$block_static->loadTrackedEvents(); $block_static->loadTrackedEvents();
$title = $langs->trans("BlockedLogSetup"); $title = $langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog');
$help_url="EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable"; $help_url="EN:Module_Unalterable_Archives_-_Logs|FR:Module_Archives_-_Logs_Inaltérable";
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-blockedlog page-admin_blockedlog'); llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-blockedlog page-admin_blockedlog');
$linkback = ''; $linkback = '';
if ($withtab) { if ($withtab) {
$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php').'">'.$langs->trans("BackToModuleList").'</a>'; $linkback = '<a href="'.dolBuildUrl($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
} }
print load_fiche_titre($langs->trans("ModuleSetup").' '.$langs->trans('BlockedLog'), $linkback, 'blockedlog'); $morehtmlcenter = '';
$registrationnumber = getHashUniqueIdOfRegistration();
$texttop = '<small class="opacitymedium">'.$langs->trans("RegistrationNumber").':</small> <small>'.dol_trunc($registrationnumber, 10).'</small>';
print load_fiche_titre($title, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter);
if ($withtab) { if ($withtab) {
$head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha')); $head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha'));
print dol_get_fiche_head($head, 'blockedlog', '', -1); print dol_get_fiche_head($head, 'blockedlog', '', -1);
} }
print $texttop;
print '<br><br>';
print '<span class="opacitymedium">'.$langs->trans("BlockedLogDesc")."</span><br>\n"; print '<span class="opacitymedium">'.$langs->trans("BlockedLogDesc")."</span><br>\n";
if ($mysoc->country_code == 'FR') {
$htmltext = $langs->trans("UnalterableLogTool1FR").'<br>';
}
print info_admin($htmltext, 0, 0, 'warning');
print '<br>'; print '<br>';
print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table

View File

@@ -54,7 +54,7 @@ $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : get
$backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page $backtopage = GETPOST('backtopage', 'alpha'); // Go back to a dedicated page
$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print') $optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
$hmacexportkey = GETPOST('hmacexportkey', 'password'); //$hmacexportkey = GETPOST('hmacexportkey', 'password');
$search_showonlyerrors = GETPOSTINT('search_showonlyerrors'); $search_showonlyerrors = GETPOSTINT('search_showonlyerrors');
if ($search_showonlyerrors < 0) { if ($search_showonlyerrors < 0) {
@@ -179,10 +179,12 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Year")), null, "errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Year")), null, "errors");
$error++; $error++;
} }
/*
if (empty($hmacexportkey)) { if (empty($hmacexportkey)) {
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Password")), null, "errors"); setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Password")), null, "errors");
$error++; $error++;
} }
*/
$dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1); $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1);
$datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12); $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12);
@@ -256,14 +258,17 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
$sql .= " FROM ".MAIN_DB_PREFIX."blockedlog"; $sql .= " FROM ".MAIN_DB_PREFIX."blockedlog";
$sql .= " WHERE entity = ".((int) $conf->entity); $sql .= " WHERE entity = ".((int) $conf->entity);
if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) { if (GETPOSTINT('monthtoexport') > 0 || GETPOSTINT('yeartoexport') > 0) {
$dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 1); $dates = dol_get_first_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') > 0 ? GETPOSTINT('monthtoexport') : 1);
$datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') ? GETPOSTINT('monthtoexport') : 12); $datee = dol_get_last_day(GETPOSTINT('yeartoexport'), GETPOSTINT('monthtoexport') > 0 ? GETPOSTINT('monthtoexport') : 12);
$sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'"; $sql .= " AND date_creation BETWEEN '".$db->idate($dates)."' AND '".$db->idate($datee)."'";
} }
$sql .= " ORDER BY rowid ASC"; // Required so later we can use the parameter $previoushash of checkSignature() $sql .= " ORDER BY rowid ASC"; // Required so later we can use the parameter $previoushash of checkSignature()
$resql = $db->query($sql); $resql = $db->query($sql);
if ($resql) { if ($resql) {
$registrationnumber = getHashUniqueIdOfRegistration();
$secretkey = $registrationnumber;
$yearmonthtoexport = GETPOSTINT('yeartoexport').(GETPOSTINT('monthtoexport') > 0 ? sprintf("%02d", GETPOSTINT('monthtoexport')) : ''); $yearmonthtoexport = GETPOSTINT('yeartoexport').(GETPOSTINT('monthtoexport') > 0 ? sprintf("%02d", GETPOSTINT('monthtoexport')) : '');
$yearmonthdateofexport = dol_print_date(dol_now(), 'dayhourlog', 'gmt'); $yearmonthdateofexport = dol_print_date(dol_now(), 'dayhourlog', 'gmt');
@@ -275,7 +280,7 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
$fh = fopen($tmpfile, 'w'); $fh = fopen($tmpfile, 'w');
// Print line with title // Print line with title
fwrite($fh, "BEGIN - date=".$yearmonthdateofexport fwrite($fh, "BEGIN - date=".$yearmonthdateofexport." - period=".$yearmonthtoexport
.';'.$langs->transnoentities('Id') .';'.$langs->transnoentities('Id')
.';'.$langs->transnoentities('DateCreation') .';'.$langs->transnoentities('DateCreation')
.';'.$langs->transnoentities('Action') .';'.$langs->transnoentities('Action')
@@ -290,6 +295,7 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
.';'.$langs->transnoentities('Fingerprint') .';'.$langs->transnoentities('Fingerprint')
.';'.$langs->transnoentities('Status') .';'.$langs->transnoentities('Status')
.';'.$langs->transnoentities('FingerprintExport') .';'.$langs->transnoentities('FingerprintExport')
//.';'.$langs->transnoentities('FingerprintExportHMAC')
."\n"); ."\n");
$loweridinerror = 0; $loweridinerror = 0;
@@ -355,6 +361,7 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
} }
$signatureexport = 'TODO'; $signatureexport = 'TODO';
$signatureexporthmac = 'TODO';
fwrite($fh, fwrite($fh,
';'.$block_static->id ';'.$block_static->id
@@ -370,7 +377,8 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
.';"'.str_replace('"', '""', $block_static->object_version).'";"' .';"'.str_replace('"', '""', $block_static->object_version).'";"'
.str_replace('"', '""', $block_static->signature).'";"' .str_replace('"', '""', $block_static->signature).'";"'
.str_replace('"', '""', $statusofrecord).'";"' .str_replace('"', '""', $statusofrecord).'";"'
.str_replace('"', '""', $signatureexport).'"' .str_replace('"', '""', $signatureexport).'";'
//.str_replace('"', '""', $signatureexporthmac).'"'
//.';'.$statusofrecordnote //.';'.$statusofrecordnote
."\n"); ."\n");
@@ -384,11 +392,11 @@ if (GETPOST('action') == 'export' && $user->hasRight('blockedlog', 'read')) { /
// Calculate the md5 of the file (the last line has a return line) // Calculate the md5 of the file (the last line has a return line)
$algo = 'sha256'; $algo = 'sha256';
$secretkey = 'TODOASKBEFOREEXPORT'; $sha256 = hash_file($algo, $tmpfile);
$hmacsha256 = hash_hmac_file($algo, $tmpfile, $secretkey); $hmacsha256 = hash_hmac_file($algo, $tmpfile, $secretkey);
// Now add a signature to check integrity at end of file // Now add a signature to check integrity at end of file
file_put_contents($tmpfile, 'END - hmac_sha256='.$hmacsha256, FILE_APPEND); file_put_contents($tmpfile, 'END - sha256='.$sha256.' - hmac_sha256='.$hmacsha256, FILE_APPEND);
setEventMessages($langs->trans("FileGenerated"), null); setEventMessages($langs->trans("FileGenerated"), null);
} else { } else {
@@ -426,19 +434,26 @@ if (!is_array($blocks)) {
$linkback = ''; $linkback = '';
if (GETPOST('withtab', 'alpha')) { if (GETPOST('withtab', 'alpha')) {
$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php').'">'.$langs->trans("BackToModuleList").'</a>'; $linkback = '<a href="'.dolBuildUrl($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
} }
print load_fiche_titre($title, $linkback, 'blockedlog'); $morehtmlcenter = '';
$registrationnumber = getHashUniqueIdOfRegistration();
$texttop = '<small class="opacitymedium">'.$langs->trans("RegistrationNumber").':</small> <small>'.dol_trunc($registrationnumber, 10).'</small>';
print load_fiche_titre($title, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter);
$head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha')); $head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha'));
print dol_get_fiche_head($head, 'archives', '', -1); print dol_get_fiche_head($head, 'archives', '', -1);
print $texttop;
print '<br><br>';
print '<div class="opacitymedium hideonsmartphone justify">'; print '<div class="opacitymedium hideonsmartphone justify">';
print $langs->trans("ArchivesDesc")."<br>"; print $langs->trans("ArchivesDesc")."<br>";
print "<br>\n";
print "</div>\n"; print "</div>\n";
@@ -451,7 +466,7 @@ if ($mysoc->country_code == 'FR') {
//$htmltext .= $langs->trans("UnalterableLogTool1"); //$htmltext .= $langs->trans("UnalterableLogTool1");
//$htmltext .= $langs->trans("UnalterableLogTool3")."<br>"; //$htmltext .= $langs->trans("UnalterableLogTool3")."<br>";
print info_admin($htmltext); print info_admin($htmltext, 0, 0, 'warning');
print '<br>'; print '<br>';
@@ -533,7 +548,8 @@ print '<input type="text" name="yeartoexport" class="valignmiddle maxwidth75imp"
print ' '; print ' ';
print '<input type="text" name="hmacexportkey" class="valignmiddle minwidth150imp maxwidth300imp" required value="'.GETPOST('hmacexportkey').'" placeholder="'.$langs->trans("Password").'">'; // Disabled, we will use the getHashUniqueIdOfRegistration() as secret HMAC
//print '<input type="text" name="hmacexportkey" class="valignmiddle minwidth150imp maxwidth300imp" required value="'.GETPOST('hmacexportkey').'" placeholder="'.$langs->trans("Password").'">';
print ' '; print ' ';

View File

@@ -396,15 +396,23 @@ if (!is_array($blocks)) {
$linkback = ''; $linkback = '';
if (GETPOST('withtab', 'alpha')) { if (GETPOST('withtab', 'alpha')) {
$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php').'">'.$langs->trans("BackToModuleList").'</a>'; $linkback = '<a href="'.dolBuildUrl($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php', ['restore_lastsearch_values' => 1]).'">'.img_picto($langs->trans("BackToModuleList"), 'back', 'class="pictofixedwidth"').'<span class="hideonsmartphone">'.$langs->trans("BackToModuleList").'</span></a>';
} }
print load_fiche_titre($title, $linkback, 'blockedlog'); $morehtmlcenter = '';
$registrationnumber = getHashUniqueIdOfRegistration();
$texttop = '<small class="opacitymedium">'.$langs->trans("RegistrationNumber").':</small> <small>'.dol_trunc($registrationnumber, 10).'</small>';
print load_fiche_titre($title, $linkback, 'blockedlog', 0, '', '', $morehtmlcenter);
$head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha')); $head = blockedlogadmin_prepare_head(GETPOST('withtab', 'alpha'));
print dol_get_fiche_head($head, 'fingerprints', '', -1); print dol_get_fiche_head($head, 'fingerprints', '', -1);
print $texttop;
print '<br><br>';
print '<div class="opacitymedium hideonsmartphone justify">'; print '<div class="opacitymedium hideonsmartphone justify">';
print $langs->trans("FingerprintsDesc")."<br>"; print $langs->trans("FingerprintsDesc")."<br>";
@@ -418,7 +426,7 @@ $htmltext = '';
$htmltext .= $langs->trans("UnalterableLogTool2", $langs->transnoentitiesnoconv("Archives"))."<br>"; $htmltext .= $langs->trans("UnalterableLogTool2", $langs->transnoentitiesnoconv("Archives"))."<br>";
$htmltext .= $langs->trans("UnalterableLogTool3")."<br>"; $htmltext .= $langs->trans("UnalterableLogTool3")."<br>";
print info_admin($htmltext); print info_admin($htmltext, 0, 0, 'warning');
print '<br>'; print '<br>';

View File

@@ -129,6 +129,8 @@ function formatObject($objtoshow, $prefix)
'pos_source' => "POSTerminal", 'pos_source' => "POSTerminal",
'posmodule' => 'POSModule', 'posmodule' => 'POSModule',
'posnumber' => 'POSTerminal', 'posnumber' => 'POSTerminal',
'pos_print_counter' => "NumberOfPrints",
'email_sent_counter' => "NumberOfEmailsSent",
'managers' => 'Managers', 'managers' => 'Managers',
'type_code' => 'PaymentMode', 'type_code' => 'PaymentMode',
'datec' => 'DateCreation', 'datec' => 'DateCreation',
@@ -153,11 +155,13 @@ function formatObject($objtoshow, $prefix)
'tva_tx' => 'VatRate', 'tva_tx' => 'VatRate',
'localtax1_tx' => 'Localtax1Rate', 'localtax1_tx' => 'Localtax1Rate',
'localtax2_tx' => 'Localtax2Rate', 'localtax2_tx' => 'Localtax2Rate',
'vat_src_code' => 'VatCode',
'multicurrency_code' => 'Currency', 'multicurrency_code' => 'Currency',
'qty' => 'Quantity', 'qty' => 'Quantity',
'nom' => 'Name', 'nom' => 'Name',
'name' => 'Name', 'name' => 'Name',
'email' => 'Email', 'email' => 'Email',
'state_code' => 'State',
'revenuestamp' => 'RevenueStamp', 'revenuestamp' => 'RevenueStamp',
'code_client' => 'CustomerCode', 'code_client' => 'CustomerCode',
'capital' => 'Capital', 'capital' => 'Capital',
@@ -167,9 +171,10 @@ function formatObject($objtoshow, $prefix)
'localtax2_value' => 'LocalTax2DefaultValue', 'localtax2_value' => 'LocalTax2DefaultValue',
'subprice' => 'UnitPrice', 'subprice' => 'UnitPrice',
'product_type' => 'ProductType', 'product_type' => 'ProductType',
'product_label' => 'ProductLabel',
'type' => 'InvoiceType', 'type' => 'InvoiceType',
'info_bits' => 'TVA NPR or NOT', 'info_bits' => 'TVA NPR or NOT',
'special_code' => 'Special line (WEEE line, option, id of module...)' 'special_code' => 'Special line (WEEE line, option, id of module...)',
); );
if (is_object($newobjtoshow) || is_array($newobjtoshow)) { if (is_object($newobjtoshow) || is_array($newobjtoshow)) {

View File

@@ -193,7 +193,7 @@ class BlockedLog
$sep = 0; $sep = 0;
// Customer Invoice/Facture / Payment // Customer Invoice/Facture / Payment (For most VAT antifraud laws)
if (isModEnabled('invoice')) { if (isModEnabled('invoice')) {
$sep++; $sep++;
$this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("Invoices").' | '.$langs->trans("Payments").'</span>', 'disabled' => 1); $this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("Invoices").' | '.$langs->trans("Payments").'</span>', 'disabled' => 1);
@@ -221,7 +221,7 @@ class BlockedLog
*/ */
// Donation // Donation
if (isModEnabled('don')) { if (isModEnabled('don') && getDolGlobalString('BLOCKEDLOG_ENABLE_DONATION')) { // For countries that need unalterable logs for donations
if (!empty($this->trackedevents)) { if (!empty($this->trackedevents)) {
$sep++; $sep++;
$this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("Donations").' | '.$langs->trans("Payments").'</span>', 'disabled' => 1); $this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("Donations").' | '.$langs->trans("Payments").'</span>', 'disabled' => 1);
@@ -244,7 +244,7 @@ class BlockedLog
*/ */
// Members // Members
if (isModEnabled('member')) { if (isModEnabled('member') && getDolGlobalString('BLOCKEDLOG_ENABLE_MEMBER')) { // For countries that need unalterable logs for membership management
if (!empty($this->trackedevents)) { if (!empty($this->trackedevents)) {
$sep++; $sep++;
$this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("MenuMembers").'</span>', 'disabled' => 1); $this->trackedevents['separator_'.$sep] = array('id' => 'separator_'.$sep, 'label' => '----------', 'labelhtml' => '<span class="opacitymedium">----- '.$langs->trans("MenuMembers").'</span>', 'disabled' => 1);
@@ -256,6 +256,7 @@ class BlockedLog
} }
// Bank // Bank
/*
if (isModEnabled("bank")) { if (isModEnabled("bank")) {
if (!empty($this->trackedevents)) { if (!empty($this->trackedevents)) {
$sep++; $sep++;
@@ -266,6 +267,7 @@ class BlockedLog
$this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = array('id' => 'PAYMENT_VARIOUS_MODIFY', 'label' => 'logPAYMENT_VARIOUS_MODIFY', 'labelhtml' => img_picto('', 'bank', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_VARIOUS_MODIFY')); $this->trackedevents['PAYMENT_VARIOUS_MODIFY'] = array('id' => 'PAYMENT_VARIOUS_MODIFY', 'label' => 'logPAYMENT_VARIOUS_MODIFY', 'labelhtml' => img_picto('', 'bank', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_VARIOUS_MODIFY'));
$this->trackedevents['PAYMENT_VARIOUS_DELETE'] = array('id' => 'PAYMENT_VARIOUS_DELETE', 'label' => 'logPAYMENT_VARIOUS_DELETE', 'labelhtml' => img_picto('', 'bank', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_VARIOUS_DELETE')); $this->trackedevents['PAYMENT_VARIOUS_DELETE'] = array('id' => 'PAYMENT_VARIOUS_DELETE', 'label' => 'logPAYMENT_VARIOUS_DELETE', 'labelhtml' => img_picto('', 'bank', 'class="pictofixedwidth").').$langs->trans('logPAYMENT_VARIOUS_DELETE'));
} }
*/
// Cash register closing // Cash register closing
// $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all external POS modules // $conf->global->BANK_ENABLE_POS_CASHCONTROL must be set to 1 by all external POS modules
@@ -279,7 +281,7 @@ class BlockedLog
$this->trackedevents['CASHCONTROL_VALIDATE'] = array('id' => 'CASHCONTROL_VALIDATE', 'label' => 'logCASHCONTROL_VALIDATE', 'labelhtml' => img_picto('', 'pos', 'class="pictofixedwidth").').$langs->trans('logCASHCONTROL_VALIDATE')); $this->trackedevents['CASHCONTROL_VALIDATE'] = array('id' => 'CASHCONTROL_VALIDATE', 'label' => 'logCASHCONTROL_VALIDATE', 'labelhtml' => img_picto('', 'pos', 'class="pictofixedwidth").').$langs->trans('logCASHCONTROL_VALIDATE'));
} }
// Add more action to track from a conf variable // Add more action to track from a conf variable. For the case we want to track other actions into the unalterable log.
// For example: STOCK_MOVEMENT, ... // For example: STOCK_MOVEMENT, ...
if (getDolGlobalString('BLOCKEDLOG_ADD_ACTIONS_SUPPORTED')) { if (getDolGlobalString('BLOCKEDLOG_ADD_ACTIONS_SUPPORTED')) {
if (!empty($this->trackedevents)) { if (!empty($this->trackedevents)) {
@@ -515,7 +517,8 @@ class BlockedLog
'table_element', 'fields', 'table_element', 'fields',
'ref_previous', 'ref_next', 'ref_previous', 'ref_next',
'origin', 'origin_id', 'origin', 'origin_id',
'oldcopy', 'picto', 'error', 'errors', 'model_pdf', 'modelpdf', 'last_main_doc', 'civility_id', 'contact', 'contact_id', 'oldcopy', 'picto', 'error', 'errors',
'model_pdf', 'modelpdf', 'last_main_doc', 'civility_id', 'contact', 'contact_id',
'table_element_line', 'ismultientitymanaged', 'isextrafieldmanaged', 'table_element_line', 'ismultientitymanaged', 'isextrafieldmanaged',
'array_languages', 'array_languages',
'childtables', 'childtables',
@@ -554,17 +557,32 @@ class BlockedLog
// List of fields qualified // List of fields qualified
if (!in_array($key, array( if (!in_array($key, array(
'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode', 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
'tva_intra', 'tva_assuj', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' 'tva_intra', 'tva_assuj', 'localtax1_assuj', 'localtax2_assuj', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
))) { ))) {
continue; // Discard if not into this dedicated list continue; // Discard if not into this dedicated list
} }
if (!is_object($value) && !is_null($value) && $value !== '') {
$valuequalifiedforstorage = false;
if (!is_object($value)) {
if (empty($value) && in_array($key, array('country_code', 'idprof1', 'idprof2', 'tva_intra'))) {
$valuequalifiedforstorage = true; // We accept '' value for some fields
$value = (string) $value;
}
if (!is_null($value) && empty($value) && in_array($key, array('tva_assuj', 'localtax1_assuj', 'localtax2_assuj'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($value) && (string) $value !== '') {
$valuequalifiedforstorage = true;
}
}
if ($valuequalifiedforstorage) {
$this->object_data->thirdparty->$key = $value; $this->object_data->thirdparty->$key = $value;
} }
} }
} }
// Add company info // Add my company info
if (!empty($mysoc)) { if (!empty($mysoc)) {
$this->object_data->mycompany = new stdClass(); $this->object_data->mycompany = new stdClass();
@@ -572,14 +590,29 @@ class BlockedLog
if (in_array($key, $arrayoffieldstoexclude)) { if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties continue; // Discard some properties
} }
// List of fields qualified // List of fields qualified to keep
if (!in_array($key, array( if (!in_array($key, array(
'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode', 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
'tva_assuj', 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' 'tva_assuj', 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
))) { ))) {
continue; // Discard if not into this dedicated list continue; // Discard if not into this dedicated list
} }
if (!is_object($value) && !is_null($value) && $value !== '') {
$valuequalifiedforstorage = false;
if (!is_object($value)) {
if (empty($value) && in_array($key, array('country_code', 'idprof1', 'idprof2', 'tva_intra'))) {
$valuequalifiedforstorage = true; // We accept '' value for some fields
$value = (string) $value;
}
if (!is_null($value) && empty($value) && in_array($key, array('tva_assuj'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($value) && (string) $value !== '') {
$valuequalifiedforstorage = true;
}
}
if ($valuequalifiedforstorage) {
$this->object_data->mycompany->$key = $value; $this->object_data->mycompany->$key = $value;
} }
} }
@@ -600,10 +633,14 @@ class BlockedLog
} }
// List of fields qualified // List of fields qualified
if (!in_array($key, array( if (!in_array($key, array(
'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'datev', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public', 'lines', 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'datev', 'type',
'module_source', 'pos_source' //'vat_src_code', 'tva_tx', 'localtax1_tx', 'localtax2_tx', There is no rate at full doc level
'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2',
'revenuestamp', 'datepointoftax', 'note_public',
'lines',
'module_source', 'pos_source', 'pos_print_counter', 'email_sent_counter'
))) { ))) {
continue; // Discard if not into a dedicated list continue; // Discarded if not into the dedicated list
} }
if ($key == 'lines') { if ($key == 'lines') {
$lineid = 0; $lineid = 0;
@@ -612,8 +649,7 @@ class BlockedLog
foreach ($tmpline as $keyline => $valueline) { foreach ($tmpline as $keyline => $valueline) {
if (!in_array($keyline, array( if (!in_array($keyline, array(
'ref', 'product_type', 'product_label', 'ref', 'product_type', 'product_label',
'qty', 'qty', 'subprice',
'subprice',
'vat_src_code', 'tva_tx', 'localtax1_tx', 'localtax2_tx', 'vat_src_code', 'tva_tx', 'localtax1_tx', 'localtax2_tx',
'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2', 'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2',
'multicurrency_code', 'multicurrency_total_ht', 'multicurrency_total_tva', 'multicurrency_total_ttc', 'multicurrency_code', 'multicurrency_total_ht', 'multicurrency_total_tva', 'multicurrency_total_ttc',
@@ -626,15 +662,45 @@ class BlockedLog
$this->object_data->invoiceline[$lineid] = new stdClass(); $this->object_data->invoiceline[$lineid] = new stdClass();
} }
if (!is_object($valueline) && !is_null($valueline) && $valueline !== '') { $valuequalifiedforstorage = false;
if (!is_object($valueline)) {
if (!is_null($valueline) && empty($valueline) && in_array($key, array('tva_tx', 'localtax1_tx', 'localtax2_tx', 'total_ht', 'total_tva', 'total_ttc', 'total_localtax1', 'total_localtax2'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($valueline) && (string) $valueline !== '') {
$valuequalifiedforstorage = true;
}
}
if ($keyline == 'product_label' && empty($valueline)) {
$valueline = dol_trunc(dolGetFirstLineOfText($tmpline->desc)); // Fallback on description if label is empty
$valuequalifiedforstorage = true;
}
if ($valuequalifiedforstorage) {
$this->object_data->invoiceline[$lineid]->$keyline = $valueline; $this->object_data->invoiceline[$lineid]->$keyline = $valueline;
} }
} }
} }
} elseif (!is_object($value) && !is_null($value) && $value !== '') { } else {
$valuequalifiedforstorage = false;
if (!is_object($value)) {
if (empty($value) && in_array($key, array('pos_source', 'module_source'))) {
$valuequalifiedforstorage = true; // We accept '' value for some fields
$value = (string) $value;
}
if (!is_null($value) && empty($value) && in_array($key, array('total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'pos_print_counter', 'email_sent_counter'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($value) && (string) $value !== '') {
$valuequalifiedforstorage = true;
}
}
if ($valuequalifiedforstorage) {
$this->object_data->$key = $value; $this->object_data->$key = $value;
} }
} }
}
if (!empty($object->newref)) { if (!empty($object->newref)) {
$this->object_data->ref = $object->newref; $this->object_data->ref = $object->newref;
@@ -651,7 +717,22 @@ class BlockedLog
))) { ))) {
continue; // Discard if not into a dedicated list continue; // Discard if not into a dedicated list
} }
if (!is_object($value) && !is_null($value) && $value !== '') {
$valuequalifiedforstorage = false;
if (!is_object($value)) {
if (empty($value) && in_array($key, array('pos_source', 'module_source'))) {
$valuequalifiedforstorage = true; // We accept '' value for some fields
$value = (string) $value;
}
if (!is_null($value) && empty($value) && in_array($key, array('total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'pos_print_counter', 'email_sent_counter'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($value) && (string) $value !== '') {
$valuequalifiedforstorage = true;
}
}
if ($valuequalifiedforstorage) {
$this->object_data->$key = $value; $this->object_data->$key = $value;
} }
} }
@@ -679,7 +760,7 @@ class BlockedLog
$totalamount = 0; $totalamount = 0;
// Loop on each invoice payment amount (payment_part) // Loop on each invoice payment amount (the payment_part)
if (is_array($object->amounts) && !empty($object->amounts)) { if (is_array($object->amounts) && !empty($object->amounts)) {
$paymentpartnumber = 0; $paymentpartnumber = 0;
foreach ($object->amounts as $objid => $amount) { foreach ($object->amounts as $objid => $amount) {
@@ -738,7 +819,7 @@ class BlockedLog
if (in_array($key, $arrayoffieldstoexclude)) { if (in_array($key, $arrayoffieldstoexclude)) {
continue; // Discard some properties continue; // Discard some properties
} }
// List of fields qualified // List of thirdparty fields qualified
if (!in_array($key, array( if (!in_array($key, array(
'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode', 'name', 'name_alias', 'ref_ext', 'address', 'zip', 'town', 'state_code', 'country_code', 'idprof1', 'idprof2', 'idprof3', 'idprof4', 'idprof5', 'idprof6', 'phone', 'fax', 'email', 'barcode',
'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur' 'tva_intra', 'localtax1_assuj', 'localtax1_value', 'localtax2_assuj', 'localtax2_value', 'managers', 'capital', 'typent_code', 'forme_juridique_code', 'code_client', 'code_fournisseur'
@@ -754,6 +835,8 @@ class BlockedLog
// Init object to avoid warnings // Init object to avoid warnings
if ($this->element == 'payment_donation') { if ($this->element == 'payment_donation') {
$paymentpart->donation = new stdClass(); $paymentpart->donation = new stdClass();
} elseif ($this->element == 'payment_various') {
$paymentpart->various = new stdClass();
} else { } else {
$paymentpart->invoice = new stdClass(); $paymentpart->invoice = new stdClass();
} }
@@ -765,11 +848,27 @@ class BlockedLog
} }
// List of fields qualified // List of fields qualified
if (!in_array($key, array( if (!in_array($key, array(
'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public' 'ref', 'ref_client', 'ref_supplier', 'date', 'datef', 'type', 'total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'revenuestamp', 'datepointoftax', 'note_public',
'pos_source', 'module_source', 'pos_print_counter', 'email_sent_counter'
))) { ))) {
continue; // Discard if not into a dedicated list continue; // Discard if not into a dedicated list
} }
if (!is_object($value) && !is_null($value) && $value !== '') {
$valuequalifiedforstorage = false;
if (!is_object($value)) {
if (empty($value) && in_array($key, array('pos_source', 'module_source'))) {
$valuequalifiedforstorage = true; // We accept '' value for some fields
$value = (string) $value;
}
if (!is_null($value) && empty($value) && in_array($key, array('total_ht', 'total_tva', 'total_ttc', 'localtax1', 'localtax2', 'pos_print_counter', 'email_sent_counter'))) {
$valuequalifiedforstorage = true; // We accept zero value for amounts
}
if (!is_null($value) && (string) $value !== '') {
$valuequalifiedforstorage = true;
}
}
if ($valuequalifiedforstorage) {
if ($this->element == 'payment_donation') { if ($this->element == 'payment_donation') {
$paymentpart->donation->$key = $value; $paymentpart->donation->$key = $value;
} elseif ($this->element == 'payment_various') { } elseif ($this->element == 'payment_various') {
@@ -990,19 +1089,29 @@ class BlockedLog
// Check parameters/properties // Check parameters/properties
if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled) if (!isset($this->amounts)) { // amount can be 0 for some events (like when module is disabled)
$this->error = $langs->trans("BlockLogNeedAmountsValue"); $langs->load("errors");
$this->error = $langs->trans("ErrorBlockLogNeedAmountsValue");
dol_syslog($this->error, LOG_WARNING); dol_syslog($this->error, LOG_WARNING);
return -1; return -1;
} }
if (empty($this->element)) { if (empty($this->element)) {
$this->error = $langs->trans("BlockLogNeedElement"); $langs->load("errors");
$this->error = $langs->trans("ErrorBlockLogNeedElement");
dol_syslog($this->error, LOG_WARNING);
return -2;
}
if (empty($this->object_data)) {
$langs->load("errors");
$this->error = $langs->trans("ErrorBlockLogNeedObject");
dol_syslog($this->error, LOG_WARNING); dol_syslog($this->error, LOG_WARNING);
return -2; return -2;
} }
if (empty($this->action)) { if (empty($this->action)) {
$this->error = $langs->trans("BadParameterWhenCallingCreateOfBlockedLog"); $langs->load("errors");
$this->error = $langs->trans("ErrorBadParameterWhenCallingCreateOfBlockedLog");
dol_syslog($this->error, LOG_WARNING); dol_syslog($this->error, LOG_WARNING);
return -3; return -3;
} }

View File

@@ -82,7 +82,7 @@ function blockedlogadmin_prepare_head($withtabsetup)
* *
* @return boolean True or false * @return boolean True or false
*/ */
function isRegistrationRecorded() function isRegistrationDataSaved()
{ {
global $mysoc; global $mysoc;
@@ -105,24 +105,41 @@ function isRegistrationRecorded()
return true; return true;
} }
/** /**
* Return if the version is a candidate version to get the LNE certification and if the prerequisites are OK. * Return a hash unique identifier of the registration
* The difference between isALNEQualifiedVersion() and isALNERunningVersion() is that this one just check if it has a sense or not to
* activate the restrictions (it is not a strict check) and the second one is a strict check to say restrictions must be enabled and can't be disabled.
* *
* @return string Hash unique ID (used to idenfiy the registration without disclosing personal data)
*/
function getHashUniqueIdOfRegistration()
{
global $conf;
return dol_hash('dolibarr'.$conf->file->instance_unique_id, 'sha256', 1);
}
/**
* Return if the version is a candidate version to get the LNE certification and if the prerequisites are OK in production to be switched to LNE certified mode.
* The difference with isALNERunningVersion() is that isALNEQualifiedVersion() just checks if it has a sense or not to activate
* the restrictions (it is not a check to say if we are or not in a mode with restrictions activated, but if we are in a context that has a sense to activate them).
* It can be used to show warnings or alerts to end users.
*
* @param int<0,1> $ignoredev Set this to 1 to ignore the fact the version is an alpha or beta version
* @param int<0,1> $ignoremodule Set this to 1 to not take into account if module BlockedLog is on, so function can be used during module activation.
* @return boolean True or false * @return boolean True or false
*/ */
function isALNEQualifiedVersion() function isALNEQualifiedVersion($ignoredev = 0, $ignoremodule = 0)
{ {
global $mysoc; global $mysoc;
// For Debug help: Constant set by developer to force all LNE restrictions even if country is not France so we can test them on any dev instance. // For Debug help: Constant set by developer to force all LNE restrictions even if country is not France so we can test them on any dev instance.
// Note that you can force, with this option, to enabling of the LNE restrictions but you can't force the disabling of the LNE restriction. // Note that you can force, with this option, the enabling of the LNE restrictions, but there is no way to force the disabling of the LNE restriction.
if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2) { if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2) {
return true; return true;
} }
if (preg_match('/\-/', DOL_VERSION)) { // This is not a stable version if (!$ignoredev && preg_match('/\-/', DOL_VERSION)) { // This is not a stable version
return false; return false;
} }
if ($mysoc->country_code != 'FR') { if ($mysoc->country_code != 'FR') {
@@ -131,7 +148,7 @@ function isALNEQualifiedVersion()
if (!defined('CERTIF_LNE') || (int) constant('CERTIF_LNE') === 0) { if (!defined('CERTIF_LNE') || (int) constant('CERTIF_LNE') === 0) {
return false; return false;
} }
if (!isModEnabled('blockedlog')) { if (!$ignoremodule && !isModEnabled('blockedlog')) {
return false; return false;
} }
@@ -140,16 +157,15 @@ function isALNEQualifiedVersion()
/** /**
* Return if the application is executed with the LNE features on. * Return if the application is executed with the LNE requirements on.
* This function is used to disabled some features like disabling custom receipts, or showing the mandatory information "Certified LNE" * This function can be used to disable some features like custom receipts, or to enable others like showing the information "Certified LNE".
* on tickets when it is not true.
* *
* @return boolean True or false * @return boolean True or false
*/ */
function isALNERunningVersion() function isALNERunningVersion()
{ {
// For Debug help: Constant set by developer to force all LNE restrictions even if country is not France so we can test them on any dev instance. // For Debug help: Constant set by developer to force all LNE restrictions even if country is not France so we can test them on any dev instance.
// Note that you can force, with this option, to enabling of the LNE restrictions but you can't force the disabling of the LNE restriction. // Note that you can force, with this option, the enabling of the LNE restrictions, but there is no way to force the disabling of the LNE restriction.
if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2) { if (defined('CERTIF_LNE') && (int) constant('CERTIF_LNE') === 2) {
return true; return true;
} }

View File

@@ -541,22 +541,29 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
if (!$error) { if (!$error) {
$db->begin(); $db->begin();
$dayinyear = dol_print_date($object->datep, '%m%d');
$dayinmonth = dol_print_date($object->datep, '%d'); $dayinmonth = dol_print_date($object->datep, '%d');
$dayinweek = dol_print_date($object->datep, '%w'); $dayinweek = dol_print_date($object->datep, '%w');
$selectedrecurrulefreq = 'no'; $selectedrecurrulefreq = 'no';
$selectedrecurrulebyyearmonthday = '';
$selectedrecurrulebymonthday = ''; $selectedrecurrulebymonthday = '';
$selectedrecurrulebyday = ''; $selectedrecurrulebyday = '';
$object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : ""; $object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : "";
$object->recurrule .= (GETPOST('recurrulefreq', 'alpha') == 'YEARLY') ? "_BYYEARMONTHDAY".((int) $dayinyear) : "";
$object->recurrule .= (GETPOST('recurrulefreq', 'alpha') == 'MONTHLY') ? "_BYMONTHDAY".((int) $dayinmonth) : ""; $object->recurrule .= (GETPOST('recurrulefreq', 'alpha') == 'MONTHLY') ? "_BYMONTHDAY".((int) $dayinmonth) : "";
$object->recurrule .= (GETPOST('recurrulefreq', 'alpha') == 'WEEKLY') ? "_BYDAY".((int) $dayinweek) : ""; $object->recurrule .= (GETPOST('recurrulefreq', 'alpha') == 'WEEKLY') ? "_BYDAY".((int) $dayinweek) : "";
$reg1 = []; $reg1 = [];
$reg2 = []; $reg2 = [];
$reg3 = []; $reg3 = [];
$reg4 = [];
if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg1)) { if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg1)) {
$selectedrecurrulefreq = $reg1[1]; $selectedrecurrulefreq = $reg1[1];
} }
if ($object->recurrule && preg_match('/FREQ=YEARLY.*BYYEARMONTHDAY(\d+)/i', $object->recurrule, $reg4)) {
$selectedrecurrulebyyearmonthday = (int) $reg4[1];
}
if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg2)) { if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg2)) {
$selectedrecurrulebymonthday = (int) $reg2[1]; $selectedrecurrulebymonthday = (int) $reg2[1];
} }
@@ -689,10 +696,9 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
if ($res <= 0) { if ($res <= 0) {
// If error // If error
$db->rollback();
$langs->load("errors"); $langs->load("errors");
$error = $langs->trans('ErrorReminderActionCommCreation'); $error++;
setEventMessages($error, null, 'errors'); setEventMessages($langs->trans('ErrorReminderActionCommCreation'), null, 'errors');
$action = 'create'; $action = 'create';
$donotclearsession = 1; $donotclearsession = 1;
break; break;
@@ -707,13 +713,6 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
*/ */
$moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1';
if ($error) {
$db->rollback();
} else {
$db->commit();
}
// if (!empty($backtopage)) { // if (!empty($backtopage)) {
// dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); // dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
// header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); // header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
@@ -725,23 +724,24 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
// exit; // exit;
} else { } else {
// If error // If error
$db->rollback();
$langs->load("errors"); $langs->load("errors");
$error = $langs->trans($object->error); $error++;
setEventMessages($error, null, 'errors'); setEventMessages($langs->trans($object->error), null, 'errors');
$action = 'create'; $action = 'create';
$donotclearsession = 1; $donotclearsession = 1;
} }
} else { } else {
$db->rollback(); $error++;
setEventMessages($object->error, $object->errors, 'errors'); setEventMessages($object->error, $object->errors, 'errors');
$action = 'create'; $action = 'create';
$donotclearsession = 1; $donotclearsession = 1;
} }
// Manage other events in case of recurring event
if (!$error && $eventisrecurring) { if (!$error && $eventisrecurring) {
$dayoffset = 0; $dayoffset = 0;
$monthoffset = 0; $monthoffset = 0;
$yearoffset = 0;
// We set first date of recurrence and offsets // We set first date of recurrence and offsets
if ($selectedrecurrulefreq == 'WEEKLY' && !empty($selectedrecurrulebyday)) { if ($selectedrecurrulefreq == 'WEEKLY' && !empty($selectedrecurrulebyday)) {
$firstdatearray = dol_get_first_day_week(GETPOSTINT("apday"), GETPOSTINT("apmonth"), GETPOSTINT("apyear")); $firstdatearray = dol_get_first_day_week(GETPOSTINT("apday"), GETPOSTINT("apmonth"), GETPOSTINT("apyear"));
@@ -749,12 +749,21 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$datep = dol_time_plus_duree($datep, $selectedrecurrulebyday + 6, 'd');//We begin the week after $datep = dol_time_plus_duree($datep, $selectedrecurrulebyday + 6, 'd');//We begin the week after
$dayoffset = 7; $dayoffset = 7;
$monthoffset = 0; $monthoffset = 0;
$yearoffset = 0;
} elseif ($selectedrecurrulefreq == 'MONTHLY' && !empty($selectedrecurrulebymonthday)) { } elseif ($selectedrecurrulefreq == 'MONTHLY' && !empty($selectedrecurrulebymonthday)) {
$firstday = $selectedrecurrulebymonthday; $firstday = $selectedrecurrulebymonthday;
$firstmonth = GETPOST("apday") > $selectedrecurrulebymonthday ? GETPOSTINT("apmonth") + 1 : GETPOSTINT("apmonth");//We begin the week after $firstmonth = GETPOST("apday") > $selectedrecurrulebymonthday ? GETPOSTINT("apmonth") + 1 : GETPOSTINT("apmonth");//We begin the month after
$datep = dol_mktime($fulldayevent ? 0 : GETPOSTINT("aphour"), $fulldayevent ? 0 : GETPOSTINT("apmin"), $fulldayevent ? 0 : GETPOSTINT("apsec"), $firstmonth, $firstday, GETPOSTINT("apyear"), $tzforfullday ? $tzforfullday : 'tzuserrel'); $datep = dol_mktime($fulldayevent ? 0 : GETPOSTINT("aphour"), $fulldayevent ? 0 : GETPOSTINT("apmin"), $fulldayevent ? 0 : GETPOSTINT("apsec"), $firstmonth, $firstday, GETPOSTINT("apyear"), $tzforfullday ? $tzforfullday : 'tzuserrel');
$datep = dol_time_plus_duree($datep, 1, 'm');//We begin the month after
$dayoffset = 0; $dayoffset = 0;
$monthoffset = 1; $monthoffset = 1;
$yearoffset = 0;
} elseif ($selectedrecurrulefreq == 'YEARLY' && !empty($selectedrecurrulebyyearmonthday)) {
$datep = dol_mktime($fulldayevent ? 0 : GETPOSTINT("aphour"), $fulldayevent ? 0 : GETPOSTINT("apmin"), $fulldayevent ? 0 : GETPOSTINT("apsec"), GETPOSTINT("apmonth"), GETPOSTINT("apday"), GETPOSTINT("apyear"), $tzforfullday ? $tzforfullday : 'tzuserrel');
$datep = dol_time_plus_duree($datep, 1, 'y');//We begin the year after
$dayoffset = 0;
$monthoffset = 0;
$yearoffset = 1;
} else { } else {
$error++; $error++;
} }
@@ -809,10 +818,9 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
if ($res <= 0) { if ($res <= 0) {
// If error // If error
$db->rollback(); $error++;
$langs->load("errors"); $langs->load("errors");
$error = $langs->trans('ErrorReminderActionCommCreation'); setEventMessages($langs->trans('ErrorReminderActionCommCreation'), null, 'errors');
setEventMessages($error, null, 'errors');
$action = 'create'; $action = 'create';
$donotclearsession = 1; $donotclearsession = 1;
break; break;
@@ -826,15 +834,9 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid; $moreparam .= ($moreparam ? '&' : '').'search_filtert='.$object->userownerid;
*/ */
$moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1'; $moreparam .= ($moreparam ? '&' : '').'disabledefaultvalues=1';
if ($error) {
$db->rollback();
} else {
$db->commit();
}
} else { } else {
// If error // If error
$db->rollback(); $error++;
$langs->load("errors"); $langs->load("errors");
$error = $langs->trans($finalobject->error); $error = $langs->trans($finalobject->error);
setEventMessages($error, null, 'errors'); setEventMessages($error, null, 'errors');
@@ -842,7 +844,7 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
$donotclearsession = 1; $donotclearsession = 1;
} }
} else { } else {
$db->rollback(); $error++;
setEventMessages($finalobject->error, $finalobject->errors, 'errors'); setEventMessages($finalobject->error, $finalobject->errors, 'errors');
$action = 'create'; $action = 'create';
$donotclearsession = 1; $donotclearsession = 1;
@@ -856,10 +858,19 @@ if (empty($reshook) && $action == 'add' && $usercancreate) {
// increment date for recurrent events // increment date for recurrent events
$datep = dol_time_plus_duree($datep, $dayoffset, 'd'); $datep = dol_time_plus_duree($datep, $dayoffset, 'd');
$datep = dol_time_plus_duree($datep, $monthoffset, 'm'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder $datep = dol_time_plus_duree($datep, $monthoffset, 'm'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder
$datep = dol_time_plus_duree($datep, $yearoffset, 'y'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder
$datef = dol_time_plus_duree($datef, $dayoffset, 'd'); $datef = dol_time_plus_duree($datef, $dayoffset, 'd');
$datef = dol_time_plus_duree($datef, $monthoffset, 'm'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder $datef = dol_time_plus_duree($datef, $monthoffset, 'm'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder
$datef = dol_time_plus_duree($datef, $yearoffset, 'y'); // @phan-suppress-current-line PhanPluginSuspiciousParamOrder
} }
} }
if ($error) {
$db->rollback();
} else {
$db->commit();
}
if (!empty($backtopage) && !$error) { if (!empty($backtopage) && !$error) {
dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); dol_syslog("Back to ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : '')); header("Location: ".$backtopage.($moreparam ? (preg_match('/\?/', $backtopage) ? '&'.$moreparam : '?'.$moreparam) : ''));
@@ -1335,6 +1346,7 @@ $formproject = new FormProjets($db);
$arrayrecurrulefreq = array( $arrayrecurrulefreq = array(
'no' => $langs->trans("OnceOnly"), 'no' => $langs->trans("OnceOnly"),
'YEARLY' => $langs->trans("EveryYear"),
'MONTHLY' => $langs->trans("EveryMonth"), 'MONTHLY' => $langs->trans("EveryMonth"),
'WEEKLY' => $langs->trans("EveryWeek") 'WEEKLY' => $langs->trans("EveryWeek")
// 'DAILY'=>$langs->trans("EveryDay") // 'DAILY'=>$langs->trans("EveryDay")
@@ -1521,9 +1533,11 @@ if ($action == 'create') {
print '<input type="hidden" name="recurid" value="'.(empty($object->recurid) ? '' : $object->recurid).'">'; print '<input type="hidden" name="recurid" value="'.(empty($object->recurid) ? '' : $object->recurid).'">';
$selectedrecurrulefreq = 'no'; $selectedrecurrulefreq = 'no';
$selectedrecurrulebyyearmonthday = '';
$selectedrecurrulebymonthday = ''; $selectedrecurrulebymonthday = '';
$selectedrecurrulebyday = ''; $selectedrecurrulebyday = '';
$object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : ""; $object->recurrule = GETPOSTISSET('recurrulefreq') ? "FREQ=".GETPOST('recurrulefreq', 'alpha') : "";
$object->recurrule .= GETPOSTISSET('BYYEARMONTHDAY') ? "_BYYEARMONTHDAY".GETPOST('BYYEARMONTHDAY', 'alpha') : "";
$object->recurrule .= GETPOSTISSET('BYMONTHDAY') ? "_BYMONTHDAY".GETPOST('BYMONTHDAY', 'alpha') : ""; $object->recurrule .= GETPOSTISSET('BYMONTHDAY') ? "_BYMONTHDAY".GETPOST('BYMONTHDAY', 'alpha') : "";
$object->recurrule .= GETPOSTISSET('BYDAY') ? "_BYDAY".GETPOST('BYDAY', 'alpha') : ""; $object->recurrule .= GETPOSTISSET('BYDAY') ? "_BYDAY".GETPOST('BYDAY', 'alpha') : "";
@@ -1532,6 +1546,9 @@ if ($action == 'create') {
if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg)) { if ($object->recurrule && preg_match('/FREQ=([A-Z]+)/i', $object->recurrule, $reg)) {
$selectedrecurrulefreq = $reg[1]; $selectedrecurrulefreq = $reg[1];
} }
if ($object->recurrule && preg_match('/FREQ=YEARLY.*BYYEARMONTHDAY(\d+)/i', $object->recurrule, $reg)) {
$selectedrecurrulebyyearmonthday = (int) $reg[1];
}
if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg)) { if ($object->recurrule && preg_match('/FREQ=MONTHLY.*BYMONTHDAY(\d+)/i', $object->recurrule, $reg)) {
$selectedrecurrulebymonthday = (int) $reg[1]; $selectedrecurrulebymonthday = (int) $reg[1];
} }
@@ -1571,16 +1588,25 @@ if ($action == 'create') {
console.log("reg1: " + "<?php echo $selectedrecurrulefreq; ?>"); console.log("reg1: " + "<?php echo $selectedrecurrulefreq; ?>");
console.log("reg2: " + "<?php echo $selectedrecurrulebymonthday; ?>"); console.log("reg2: " + "<?php echo $selectedrecurrulebymonthday; ?>");
console.log("reg3: " + "<?php echo $selectedrecurrulebyday; ?>"); console.log("reg3: " + "<?php echo $selectedrecurrulebyday; ?>");
console.log("reg4: " + "<?php echo $selectedrecurrulebyyearmonthday; ?>");
console.log("selectedrulefreq: " + "<?php echo $selectedrecurrulefreq; ?>"); console.log("selectedrulefreq: " + "<?php echo $selectedrecurrulefreq; ?>");
if (jQuery("#recurrulefreq").val() == 'MONTHLY') { if (jQuery("#recurrulefreq").val() == 'YEARLY') {
/* jQuery(".repeateventBYYEARMONTHDAY").css("display", "inline-block"); */ /* use this instead of show because we want inline-block and not block */
jQuery(".repeateventlimitdate").css("display", "inline-block");
jQuery(".repeateventBYMONTHDAY").hide();
jQuery(".repeateventBYDAY").hide();
} else if (jQuery("#recurrulefreq").val() == 'MONTHLY') {
/* jQuery(".repeateventBYMONTHDAY").css("display", "inline-block"); */ /* use this instead of show because we want inline-block and not block */ /* jQuery(".repeateventBYMONTHDAY").css("display", "inline-block"); */ /* use this instead of show because we want inline-block and not block */
jQuery(".repeateventlimitdate").css("display", "inline-block"); jQuery(".repeateventlimitdate").css("display", "inline-block");
jQuery(".repeateventBYYEARMONTHDAY").hide();
jQuery(".repeateventBYDAY").hide(); jQuery(".repeateventBYDAY").hide();
} else if (jQuery("#recurrulefreq").val() == 'WEEKLY') { } else if (jQuery("#recurrulefreq").val() == 'WEEKLY') {
jQuery(".repeateventBYYEARMONTHDAY").hide();
jQuery(".repeateventBYMONTHDAY").hide(); jQuery(".repeateventBYMONTHDAY").hide();
/* jQuery(".repeateventBYDAY").css("display", "inline-block"); */ /* use this instead of show because we want inline-block and not block */ /* jQuery(".repeateventBYDAY").css("display", "inline-block"); */ /* use this instead of show because we want inline-block and not block */
jQuery(".repeateventlimitdate").css("display", "inline-block"); jQuery(".repeateventlimitdate").css("display", "inline-block");
} else { } else {
jQuery(".repeateventBYYEARMONTHDAY").hide();
jQuery(".repeateventBYMONTHDAY").hide(); jQuery(".repeateventBYMONTHDAY").hide();
jQuery(".repeateventBYDAY").hide(); jQuery(".repeateventBYDAY").hide();
jQuery(".repeateventlimitdate").hide(); jQuery(".repeateventlimitdate").hide();
@@ -1616,7 +1642,7 @@ if ($action == 'create') {
print '<table class="border centpercent nobottom">'; print '<table class="border centpercent nobottom">';
// Assigned to user // Assigned to user
print '<tr><td class="tdtop nowrap titlefieldcreate"><span>'.$langs->trans("ActionAffectedTo").'</span></td><td>'; print '<tr><td class="nowrap titlefieldcreate"><span>'.$langs->trans("ActionAffectedTo").'</span></td><td>';
$listofuserid = []; $listofuserid = [];
$listofcontactid = []; $listofcontactid = [];
$listofotherid = []; $listofotherid = [];
@@ -2248,7 +2274,7 @@ if ($id > 0 && $action != 'create') {
$listofcontactid = $object->socpeopleassigned; // Contact assigned $listofcontactid = $object->socpeopleassigned; // Contact assigned
$listofotherid = $object->otherassigned; // Other undefined email (not used yet) $listofotherid = $object->otherassigned; // Other undefined email (not used yet)
print '<tr><td class="tdtop nowrap fieldrequired">'.$langs->trans("ActionAssignedTo").'</td><td>'; print '<tr><td class="nowrap fieldrequired">'.$langs->trans("ActionAssignedTo").'</td><td>';
print '<div class="assignedtouser">'; print '<div class="assignedtouser">';
print $form->select_dolusers_forevent(($action == 'create' ? 'add' : 'update'), 'assignedtouser', 1, [], 0, '', [], '0', 0, 0, 'u.statut:<>:0', 1, $listofuserid, $listofcontactid, $listofotherid, (int) $caneditdateorowner); print $form->select_dolusers_forevent(($action == 'create' ? 'add' : 'update'), 'assignedtouser', 1, [], 0, '', [], '0', 0, 0, 'u.statut:<>:0', 1, $listofuserid, $listofcontactid, $listofotherid, (int) $caneditdateorowner);
print '</div>'; print '</div>';
@@ -2723,6 +2749,9 @@ if ($id > 0 && $action != 'create') {
if (preg_match('/FREQ=MONTHLY_BYMONTHDAY(\d+)/', $object->recurrule, $reg)) { if (preg_match('/FREQ=MONTHLY_BYMONTHDAY(\d+)/', $object->recurrule, $reg)) {
print $langs->trans("EveryMonth").' <span class="opacitymedium small">('.$langs->trans("DayOfMonth").' '.$reg[1].' - '.$langs->trans("Until").' '.dol_print_date($object->recurdateend, 'day').')</span>'; print $langs->trans("EveryMonth").' <span class="opacitymedium small">('.$langs->trans("DayOfMonth").' '.$reg[1].' - '.$langs->trans("Until").' '.dol_print_date($object->recurdateend, 'day').')</span>';
} }
if (preg_match('/FREQ=YEARLY_BYYEARMONTHDAY(\d+)/', $object->recurrule, $reg)) {
print $langs->trans("EveryYear").' <span class="opacitymedium small">('.$langs->trans("DayOfYear").' '.$reg[1].' - '.$langs->trans("Until").' '.dol_print_date($object->recurdateend, 'day').')</span>';
}
print '</td></tr>'; print '</td></tr>';
} }

View File

@@ -6144,7 +6144,7 @@ if ($action == 'create') {
print $invoice->getNomUrl(0); print $invoice->getNomUrl(0);
print '</span>'; print '</span>';
print '</td>'; print '</td>';
// Delete // Delete discount
print '<td class="right">'; print '<td class="right">';
print '<a href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=unlinkdiscount&token='.newToken().'&discountid='.$obj->rowid.'">'; print '<a href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&action=unlinkdiscount&token='.newToken().'&discountid='.$obj->rowid.'">';
print img_picto($langs->transnoentitiesnoconv("RemoveDiscount"), 'unlink'); print img_picto($langs->transnoentitiesnoconv("RemoveDiscount"), 'unlink');
@@ -6788,8 +6788,13 @@ if ($action == 'create') {
// Delete // Delete
$isErasable = $object->is_erasable(); $isErasable = $object->is_erasable();
$htmltooltip = ''; $htmltooltip = '';
if ($isErasable == -4) { if ($isErasable == -6) {
$htmltooltip = $langs->trans('DisabledBecauseAlreadySentByEmail');
} elseif ($isErasable == -5) {
$htmltooltip = $langs->trans('DisabledBecauseAlreadyPrintedOnce');
} elseif ($isErasable == -4) {
$htmltooltip = $langs->trans('DisabledBecausePayments'); $htmltooltip = $langs->trans('DisabledBecausePayments');
} elseif ($isErasable == -3) { } elseif ($isErasable == -3) {
$htmltooltip = $langs->trans('DisabledBecauseNotLastSituationInvoice'); $htmltooltip = $langs->trans('DisabledBecauseNotLastSituationInvoice');

View File

@@ -171,6 +171,11 @@ class Facture extends CommonInvoice
*/ */
public $pos_print_counter = 0; public $pos_print_counter = 0;
/**
* @var int counter used to track how many times the invoice was sent by email
*/
public $email_sent_counter = 0;
/** /**
* @var int id of template invoice when generated from a template invoice * @var int id of template invoice when generated from a template invoice
*/ */
@@ -5583,7 +5588,8 @@ class Facture extends CommonInvoice
$this->fk_incoterms = 0; $this->fk_incoterms = 0;
$this->location_incoterms = ''; $this->location_incoterms = '';
$this->pos_print_counter = 3; // Already printed 3 times $this->pos_print_counter = 0; // Already printed 0 times
$this->email_sent_counter = 0; // Already sent by email 0 times
$this->status = 0; $this->status = 0;

View File

@@ -697,9 +697,11 @@ abstract class CommonInvoice extends CommonObject
* If invoice is draft and has a temporary ref -> yes (1) * If invoice is draft and has a temporary ref -> yes (1)
* If hidden option INVOICE_CAN_NEVER_BE_REMOVED is 1 -> no (0) * If hidden option INVOICE_CAN_NEVER_BE_REMOVED is 1 -> no (0)
* If invoice is transferred in bookkeeping -> no (-1) * If invoice is transferred in bookkeeping -> no (-1)
* If invoice has a definitive ref, is not last in ref and INVOICE_CAN_ALWAYS_BE_REMOVED off -> no (-2) * If invoice has a definitive ref, is not last in ref -> no (-2)
* If invoice has a definitive ref, is not last in a situation cycle and INVOICE_CAN_ALWAYS_BE_REMOVED off -> no (-3) * If invoice has a definitive ref, is not last in a situation cycle -> no (-3)
* If there is one payment and INVOICE_CAN_ALWAYS_BE_REMOVED off -> no (-4) * If there is one payment -> no (-4)
* If already sent by email -> no (-5)
* If already printed -> no (-6)
* Otherwise -> yes (2) * Otherwise -> yes (2)
* *
* @return int Return integer <=0 if no, >0 if yes * @return int Return integer <=0 if no, >0 if yes
@@ -721,6 +723,20 @@ abstract class CommonInvoice extends CommonObject
// If not a draft invoice and not temporary invoice // If not a draft invoice and not temporary invoice
if ($tmppart !== 'PROV') { if ($tmppart !== 'PROV') {
if ($this instanceOf Facture) {
/* @var Facture $this */
// If sent by email, we refuse
if ((int) $this->email_sent_counter > 0) {
return -5;
}
// If printed, we refuse
if ((int) $this->pos_print_counter > 0) {
return -6;
}
}
// If in accountancy, we refuse
$ventilExportCompta = $this->getVentilExportCompta(); $ventilExportCompta = $this->getVentilExportCompta();
if ($ventilExportCompta != 0) { if ($ventilExportCompta != 0) {
return -1; return -1;
@@ -729,32 +745,32 @@ abstract class CommonInvoice extends CommonObject
// Get last number of validated invoice // Get last number of validated invoice
if ($this->element != 'invoice_supplier') { if ($this->element != 'invoice_supplier') {
if (empty($this->thirdparty)) { if (empty($this->thirdparty)) {
$this->fetch_thirdparty(); // We need to have this->thirdparty defined, in case of numbering rule use tags that depend on thirdparty (like {t} tag). $this->fetch_thirdparty(); // We need to have this->thirdparty defined, in case of the numbering rule uses tags that depend on thirdparty (like {t} tag).
} }
$maxref = $this->getNextNumRef($this->thirdparty, 'last'); $maxref = $this->getNextNumRef($this->thirdparty, 'last');
// If there is no invoice into the reset range and not already transferred in accounting, we can delete // If invoice to delete is not the last one, we refuse
// If invoice to delete is last one and not already transferred, we can delete if ($maxref != '' && $maxref != $this->ref) {
if (!getDolGlobalString('INVOICE_CAN_ALWAYS_BE_REMOVED') && $maxref != '' && $maxref != $this->ref) {
return -2; return -2;
} }
// TODO If there is payment in bookkeeping, check the payment is not dispatched in accounting and return -2. // TODO If there is payment in bookkeeping, check the payment is not dispatched in accounting and return -2.
// ... // ...
if (!getDolGlobalString('INVOICE_CAN_ALWAYS_BE_REMOVED') && $this->situation_cycle_ref && method_exists($this, 'is_last_in_cycle')) { // If invoice is situation type, we refuse it it is not the last in situation cycle
if (!getDolGlobalString('INVOICE_SITUATION_CAN_BE_REMOVED_EVEN_IF_NOT_LAST') && $this->situation_cycle_ref && method_exists($this, 'is_last_in_cycle')) {
$last = $this->is_last_in_cycle(); $last = $this->is_last_in_cycle();
if (!$last) { if (!$last) {
return -3; return -3;
} }
} }
} }
}
// Test if there is at least one payment. If yes, refuse to delete. // Test if there is at least one payment. If yes, we refuse to delete.
if (!getDolGlobalString('INVOICE_CAN_ALWAYS_BE_REMOVED') && $this->getSommePaiement() > 0) { if ($this->getSommePaiement() > 0) {
return -4; return -4;
} }
}
return 2; return 2;
} }

View File

@@ -842,7 +842,9 @@ class FormFile
$out .= '<input type="hidden" name="page_y" value="">'; $out .= '<input type="hidden" name="page_y" value="">';
$out .= '<input type="hidden" name="token" value="'.newToken().'">'; $out .= '<input type="hidden" name="token" value="'.newToken().'">';
if ($titletoshow) {
$out .= load_fiche_titre($titletoshow, '', ''); $out .= load_fiche_titre($titletoshow, '', '');
}
$out .= '<div class="div-table-responsive-no-min">'; $out .= '<div class="div-table-responsive-no-min">';
$out .= '<table class="liste formdoc noborder centpercent">'; $out .= '<table class="liste formdoc noborder centpercent">';

View File

@@ -103,6 +103,7 @@ class TimeSpent extends CommonObject
*/ */
public $fields = array( public $fields = array(
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"), 'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
'ref_ext' => array('type' => 'varchar(255)', 'label' => 'RefExt', 'enabled' => 1, 'visible' => 0, 'position' => 20),
'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 17, 'notnull' => 0, 'visible' => -2,), 'tms' => array('type' => 'timestamp', 'label' => 'DateModification', 'enabled' => 1, 'position' => 17, 'notnull' => 0, 'visible' => -2,),
'import_key' => array('type' => 'varchar(14)', 'label' => 'import_key', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1,), 'import_key' => array('type' => 'varchar(14)', 'label' => 'import_key', 'enabled' => 1, 'position' => 15, 'notnull' => 0, 'visible' => -1,),
'fk_element' => array('type' => 'integer', 'label' => 'fk_element', 'enabled' => 1, 'position' => 2, 'notnull' => 1, 'visible' => -1,), 'fk_element' => array('type' => 'integer', 'label' => 'fk_element', 'enabled' => 1, 'position' => 2, 'notnull' => 1, 'visible' => -1,),

View File

@@ -4514,8 +4514,8 @@ function dol_print_socialnetworks($value, $contactid, $socid, $type, $dictsocial
$link = str_replace('{socialid}', $value, getDolGlobalString($networkconstname)); $link = str_replace('{socialid}', $value, getDolGlobalString($networkconstname));
$valuetoshow = $value; $valuetoshow = $value;
if (preg_match('/^https?:\/\//i', $link)) { if (preg_match('/^https?:\/\//i', $link)) {
$valuetoshow = preg_replace('/https:\/\/www\.linkedin\./', 'linkedin.', $valuetoshow); $valuetoshow = preg_replace('/https:\/\/www\.linkedin\.com\/?/', '', $valuetoshow);
//$valuetoshow = preg_replace('/www\.twitter\./', 'twitter.', $valuetoshow); //$valuetoshow = preg_replace('/www\.twitter\.com\/?/', '', $valuetoshow);
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 0) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($valuetoshow) . '</a>'; $htmllink .= '<a href="' . dol_sanitizeUrl($link, 0) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($valuetoshow) . '</a>';
} elseif ($link) { } elseif ($link) {
$htmllink .= '<a href="' . dol_sanitizeUrl($link, 1) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($valuetoshow) . '</a>'; $htmllink .= '<a href="' . dol_sanitizeUrl($link, 1) . '" target="_blank" rel="noopener noreferrer">' . dol_escape_htmltag($valuetoshow) . '</a>';
@@ -7124,7 +7124,7 @@ function print_fiche_titre($title, $mesg = '', $picto = 'generic', $pictoisfullp
/** /**
* Load a title with picto * Load a title with picto
* *
* @param string $title Title to show (HTML sanitized content). Can be a string with a <br> as a substring. * @param string $title Title to show (HTML sanitized content). Can be a string with a <br> as a second string shown under the fmain title.
* @param string $morehtmlright Added message to show on right * @param string $morehtmlright Added message to show on right
* @param string $picto Icon to use before title (should be a 32x32 transparent png file) * @param string $picto Icon to use before title (should be a 32x32 transparent png file)
* @param int<0,1> $pictoisfullpath 1=Icon name is a full absolute url of image * @param int<0,1> $pictoisfullpath 1=Icon name is a full absolute url of image
@@ -9392,19 +9392,41 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = '
//$out = '<html><head><meta charset="utf-8"></head><body><div class="tricktoremove">'.dol_nl2br($out).'</div></body></html>'; //$out = '<html><head><meta charset="utf-8"></head><body><div class="tricktoremove">'.dol_nl2br($out).'</div></body></html>';
} }
// Note: <a href="https://[__aaa__]/aaa.html"> is transformed into <a href="https://[__aaa__]/aaa.html">
// We don't want that, so we protect [__xxx__] by replacing [ and ] before loadHTML and restore them after saveHTML
$out = preg_replace_callback(
'/\[__([0-9a-zA-Z_]+)__\]/',
/**
* @param array<int,string> $m Array of matches
* @return string Translated string for the key
*/
function ($m) {
return 'BRACKETSTART__' . $m[1] . '__BRACKETEND'; },
$out);
$dom->loadHTML($out, LIBXML_HTML_NODEFDTD | LIBXML_ERR_NONE | LIBXML_HTML_NOIMPLIED | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NOXMLDECL); $dom->loadHTML($out, LIBXML_HTML_NODEFDTD | LIBXML_ERR_NONE | LIBXML_HTML_NOIMPLIED | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NOXMLDECL);
$dom->encoding = 'UTF-8'; $dom->encoding = 'UTF-8';
$out = trim($dom->saveHTML()); $out = trim($dom->saveHTML());
// Restore [ and ] that were protected before loadHTML
$out = preg_replace_callback(
'/BRACKETSTART__([0-9a-zA-Z_]+)__BRACKETEND/',
/**
* @param array<int,string> $m Array of matches
* @return string Translated string for the key
*/
function ($m) {
return '[__' . $m[1] . '__]'; },
$out);
// Remove the trick added to solve pb with text in utf8 and text without parent tag // Remove the trick added to solve pb with text in utf8 and text without parent tag
//$out = preg_replace('/^'.preg_quote('<?xml encoding="UTF-8">', '/').'/', '', $out); //$out = preg_replace('/^'.preg_quote('<?xml encoding="UTF-8">', '/').'/', '', $out);
$out = preg_replace('/^' . preg_quote('<html><head><', '/') . '[^<>]+' . preg_quote('></head><body><div class="tricktoremove">', '/') . '/', '', $out); $out = preg_replace('/^' . preg_quote('<html><head><', '/') . '[^<>]+' . preg_quote('></head><body><div class="tricktoremove">', '/') . '/', '', $out);
$out = preg_replace('/' . preg_quote('</div></body></html>', '/') . '$/', '', trim($out)); $out = preg_replace('/' . preg_quote('</div></body></html>', '/') . '$/', '', trim($out));
//$out = preg_replace('/^<\?xml encoding="UTF-8"><div class="tricktoremove">/', '', $out); //$out = preg_replace('/^<\?xml encoding="UTF-8"><div class="tricktoremove">/', '', $out);
//$out = preg_replace('/<\/div>$/', '', $out); //$out = preg_replace('/<\/div>$/', '', $out);
// var_dump('rrrrrrrrrrrrrrrrrrrrrrrrrrrrr'.$out);
if (!$outishtml) { // If $out was not HTML content we made before a dol_nl2br so we must do the opposite operation now if (!$outishtml) { // If $out was not HTML content we made before a dol_nl2br so we must do the opposite operation now
$out = str_replace('<br>', '', $out); $out = str_replace('<br>', '', $out);

View File

@@ -1004,6 +1004,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
} }
if ($feature == 'task' || $feature == 'projet_task') { if ($feature == 'task' || $feature == 'projet_task') {
$feature = 'project_task'; $feature = 'project_task';
$dbtablename = 'projet_task';
} }
if ($feature == 'eventorganization') { if ($feature == 'eventorganization') {
$feature = 'agenda'; $feature = 'agenda';
@@ -1080,6 +1081,9 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
if ($user->socid != $objectid) { if ($user->socid != $objectid) {
return false; return false;
} }
} elseif (isModEnabled('societe') && !$user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir')) {
dol_syslog("security.lib.php::checkUserAccessToObject Deny access due: (isModEnabled('societe') && !user->hasRight('societe', 'lire') && !user->hasRight('societe', 'client', 'voir'))", LOG_DEBUG);
return false;
} elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) { } elseif (isModEnabled("societe") && ($user->hasRight('societe', 'lire') && !$user->hasRight('societe', 'client', 'voir'))) {
// If internal user: Check permission for internal users that are restricted on their objects // If internal user: Check permission for internal users that are restricted on their objects
$sql = "SELECT COUNT(sc.fk_soc) as nb"; $sql = "SELECT COUNT(sc.fk_soc) as nb";
@@ -1264,7 +1268,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
// the user can't view any evaluations // the user can't view any evaluations
return false; return false;
} }
// the user can only their own evaluations or their subordinates' // the user can only see their own evaluations or their subordinates'
return in_array($useridtocheck, $childids); return in_array($useridtocheck, $childids);
} }
} }
@@ -1286,12 +1290,13 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
return false; return false;
} }
} else { } else {
dol_syslog("Bad forged sql in checkUserAccessToObject", LOG_WARNING); dol_syslog("Bad forged sql in security.lib.php::checkUserAccessToObject", LOG_WARNING);
return false; return false;
} }
} }
} }
dol_syslog("security.lib.php::checkUserAccessToObject::return True", LOG_DEBUG);
return true; return true;
} }

View File

@@ -226,9 +226,16 @@ function generate_random_id($car = 16)
{ {
$string = ""; $string = "";
$chaine = "abcdefghijklmnopqrstuvwxyz123456789"; $chaine = "abcdefghijklmnopqrstuvwxyz123456789";
mt_srand((int) ((float) microtime() * 1000000)); $max = strlen($chaine) - 1;
for ($i = 0; $i < $car; $i++) { for ($i = 0; $i < $car; $i++) {
$string .= $chaine[mt_rand() % strlen($chaine)]; try {
$key = random_int(0, $max);
} catch (\Exception $e) {
// Fallback. We let PHP makes the seed automatically (no manual mt_srand)
$key = mt_rand(0, $max);
}
$string .= $chaine[$key];
} }
return $string; return $string;
} }

View File

@@ -782,9 +782,10 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it
/** /**
* Gives the translated module description if translation exists in admin.lang or the default module description * Gives the translated module description if translation exists in admin.lang or the default module description
* *
* @param int<0,1> $foruseinpopupdesc If 1, we return a short description for use into popup window
* @return string Translated module description * @return string Translated module description
*/ */
public function getDesc() public function getDesc($foruseinpopupdesc = 0)
{ {
global $langs; global $langs;
$langs->load("admin"); $langs->load("admin");

View File

@@ -23,6 +23,8 @@
* \brief Description and activation file for the module BlockedLog * \brief Description and activation file for the module BlockedLog
*/ */
include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
/** /**
* Class to describe a BlockedLog module * Class to describe a BlockedLog module
@@ -51,6 +53,7 @@ class modBlockedLog extends DolibarrModules
// Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module) // Module label (no space allowed), used if translation string 'ModuleXXXName' not found (where XXX is value of numeric property 'numero' of module)
$this->name = preg_replace('/^mod/i', '', get_class($this)); $this->name = preg_replace('/^mod/i', '', get_class($this));
$this->description = "Enable a log on some business events into an unalterable log. This module may be mandatory for some countries."; $this->description = "Enable a log on some business events into an unalterable log. This module may be mandatory for some countries.";
// Possible values for version are: 'development', 'experimental', 'dolibarr' or version // Possible values for version are: 'development', 'experimental', 'dolibarr' or version
$this->version = 'dolibarr'; $this->version = 'dolibarr';
// Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase) // Key used in llx_const table to save module status enabled/disabled (where MYMODULE is value of property name of module in uppercase)
@@ -173,6 +176,15 @@ class modBlockedLog extends DolibarrModules
include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
// Check that the HTTPS is forced
global $dolibarr_main_force_https;
if (isALNEQualifiedVersion(0, 1) && empty($dolibarr_main_force_https)) {
$this->error = 'Error: The HTTPS must be forced by setting the $dolibarr_main_force_https into Dolibarr conf/conf.php file to allow the use of this module in France.';
return 0;
}
// Create HMAC if it does not exists yet // Create HMAC if it does not exists yet
$hmac_encoded_secret_key = getDolGlobalString('BLOCKEDLOG_HMAC_KEY'); $hmac_encoded_secret_key = getDolGlobalString('BLOCKEDLOG_HMAC_KEY');
if (empty($hmac_encoded_secret_key)) { if (empty($hmac_encoded_secret_key)) {
@@ -291,4 +303,30 @@ class modBlockedLog extends DolibarrModules
return $this->_remove($sql, $options); return $this->_remove($sql, $options);
} }
/**
* Overwrite the common getDesc() method
*
* @param int<0,1> $foruseinpopupdesc If 1, we return a short description for use into popup window
* @return string Translated module description
*/
public function getDesc($foruseinpopupdesc = 0)
{
global $langs;
$langs->load("admin");
// If module description translation exists
$s = $langs->transnoentitiesnoconv("Module".$this->numero."Desc");
if ($foruseinpopupdesc) {
$langs->load("blockedlog");
$s .= '<br><br>';
if (isALNEQualifiedVersion(1, 1)) {
$s .= info_admin($langs->trans("UnalterableLogTool1FR"), 0, 0, 'warning');
}
}
return $s;
}
} }

View File

@@ -340,18 +340,18 @@ class modEventOrganization extends DolibarrModules
$this->export_TypeFields_array[$r]['t.fk_soc'] = 'Numeric'; $this->export_TypeFields_array[$r]['t.fk_soc'] = 'Numeric';
//$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text';
//unset($this->export_fields_array[$r]['t.fieldtoremove']); //unset($this->export_fields_array[$r]['t.fieldtoremove']);
$keyforselect = 'conferenceorboothattendee'; $keyforselect = 'eventorganization_conferenceorboothattendee'; // The value in column elementtype of llx_extrafields table
$keyforaliasextra = 'extra'; $keyforaliasextra = 'extra';
$keyforelement = 'conferenceorboothattendee'; $keyforelement = 'conferenceorboothattendee'; // The value of key for icon and class
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
//$this->export_dependencies_array[$r] = array('aaaline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields) //$this->export_dependencies_array[$r] = array('aaaline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields)
//$this->export_special_array[$r] = array('t.field'=>'...'); //$this->export_special_array[$r] = array('t.field'=>'...');
//$this->export_examplevalues_array[$r] = array('t.field'=>'Example'); //$this->export_examplevalues_array[$r] = array('t.field'=>'Example');
//$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp'); //$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp');
$this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_start[$r] = 'SELECT DISTINCT ';
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'eventorganization_conferenceorboothattendee as t, '.MAIN_DB_PREFIX.'projet as p'; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'eventorganization_conferenceorboothattendee as t';
$this->export_sql_end[$r] .= ' WHERE t.fk_project = p.rowid'; $this->export_sql_end[$r] .= ' INNER JOIN '.MAIN_DB_PREFIX.'projet as p ON t.fk_project = p.rowid AND p.entity IN ('.getEntity('conferenceorboothattendee').')';
$this->export_sql_end[$r] .= ' AND p.entity IN ('.getEntity('conferenceorboothattendee').')'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'eventorganization_conferenceorboothattendee_extrafields as extra on t.rowid = extra.fk_object';
$r++; $r++;
/* END MODULEBUILDER EXPORT CONFERENCEORBOOTHATTENDEES */ /* END MODULEBUILDER EXPORT CONFERENCEORBOOTHATTENDEES */
@@ -389,7 +389,7 @@ class modEventOrganization extends DolibarrModules
$this->export_TypeFields_array[$r]['s.nom'] = 'Text'; $this->export_TypeFields_array[$r]['s.nom'] = 'Text';
//$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text'; //$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text';
//unset($this->export_fields_array[$r]['t.fieldtoremove']); //unset($this->export_fields_array[$r]['t.fieldtoremove']);
$keyforselect = 'conferenceorbooth'; $keyforselect = 'actioncomm'; // The value in column elementtype of llx_extrafields table
$keyforaliasextra = 'extra'; $keyforaliasextra = 'extra';
$keyforelement = 'conferenceorbooth'; $keyforelement = 'conferenceorbooth';
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php'; include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
@@ -397,16 +397,13 @@ class modEventOrganization extends DolibarrModules
//$this->export_special_array[$r] = array('t.field'=>'...'); //$this->export_special_array[$r] = array('t.field'=>'...');
//$this->export_examplevalues_array[$r] = array('t.field'=>'Example'); //$this->export_examplevalues_array[$r] = array('t.field'=>'Example');
//$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp'); //$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp');
$this->export_sql_start[$r] = 'SELECT DISTINCT '; $this->export_sql_start[$r] = "SELECT DISTINCT ";
$this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'actioncomm as t'; $this->export_sql_end[$r] = ' FROM '.MAIN_DB_PREFIX.'actioncomm as t';
$this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON t.fk_soc = s.rowid,'; $this->export_sql_end[$r] .= ' INNER JOIN '.MAIN_DB_PREFIX.'projet as p ON t.fk_project = p.rowid AND p.usage_organize_event = 1 AND p.entity IN ('.getEntity('conferenceorboothattendee').')';
$this->export_sql_end[$r] .= ' '.MAIN_DB_PREFIX.'projet as p,'; $this->export_sql_end[$r] .= ' INNER JOIN '.MAIN_DB_PREFIX.'c_actioncomm as ca ON ca.id = t.fk_action';
$this->export_sql_end[$r] .= ' '.MAIN_DB_PREFIX.'c_actioncomm as ca'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'societe as s ON t.fk_soc = s.rowid';
$this->export_sql_end[$r] .= ' WHERE t.fk_project = p.rowid'; $this->export_sql_end[$r] .= ' LEFT JOIN '.MAIN_DB_PREFIX.'actioncomm_extrafields as extra on t.id = extra.fk_object';
$this->export_sql_end[$r] .= ' AND ca.id = t.fk_action'; $this->export_sql_end[$r] .= " WHERE t.code LIKE 'AC_EO_%'";
$this->export_sql_end[$r] .= " AND t.code LIKE 'AC_EO_%'";
$this->export_sql_end[$r] .= ' AND p.usage_organize_event = 1';
$this->export_sql_end[$r] .= ' AND p.entity IN ('.getEntity('conferenceorboothattendee').')';
$r++; $r++;
/* END MODULEBUILDER EXPORT CONFERENCEORBOOTH */ /* END MODULEBUILDER EXPORT CONFERENCEORBOOTH */

View File

@@ -144,6 +144,7 @@ $entitytolang = array(
'bomline' => 'BOMLine', 'bomline' => 'BOMLine',
'mrp' => 'ManufacturingOrder', 'mrp' => 'ManufacturingOrder',
'mrp_line' => 'ManufacturingOrderLine', 'mrp_line' => 'ManufacturingOrderLine',
'conferenceorbooth' => 'ConferenceOrBooth',
'conferenceorboothattendee' => 'Attendee', 'conferenceorboothattendee' => 'Attendee',
'inventory' => 'Inventory', 'inventory' => 'Inventory',
'inventory_line' => 'InventoryLine' 'inventory_line' => 'InventoryLine'
@@ -1023,6 +1024,7 @@ if ($step == 4 && $datatoexport) {
// Select request if all fields are selected // Select request if all fields are selected
$sqlmaxforexport = $objexport->build_sql(0, array(), array()); $sqlmaxforexport = $objexport->build_sql(0, array(), array());
print '<br>';
print '<div class="marginbottomonly"><span class="opacitymedium">'.$langs->trans("ChooseFieldsOrdersAndTitle").'</span></div>'; print '<div class="marginbottomonly"><span class="opacitymedium">'.$langs->trans("ChooseFieldsOrdersAndTitle").'</span></div>';
print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
@@ -1353,15 +1355,16 @@ if ($step == 5 && $datatoexport) {
} }
$htmltabloflibs .= '</table><br>'; $htmltabloflibs .= '</table><br>';
print '<br>';
print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NowClickToGenerateToBuildExportFile"), $htmltabloflibs, 1, 'help', '', 0, 2, 'helphonformat').'</span>'; print '<span class="opacitymedium">'.$form->textwithpicto($langs->trans("NowClickToGenerateToBuildExportFile"), $htmltabloflibs, 1, 'help', '', 0, 2, 'helphonformat').'</span>';
//print $htmltabloflibs; //print $htmltabloflibs;
print '<br>';
print '</div>'; print '</div>';
if ($sqlusedforexport && $user->admin) { if ($sqlusedforexport && $user->admin) {
print info_admin($langs->trans("SQLUsedForExport").':<br> '.$sqlusedforexport, 0, 0, '1', '', 'TechnicalInformation'); print info_admin($langs->trans("SQLUsedForExport").':<br> '.$sqlusedforexport, 0, 0, '1', '', 'TechnicalInformation').'<br>';
print '<br>';
} }

View File

@@ -3679,9 +3679,9 @@ if ($action == 'create') {
$s = '<span class="hideonsmartphone opacitymedium">' . $langs->trans("ReCalculate") . ' </span>'; $s = '<span class="hideonsmartphone opacitymedium">' . $langs->trans("ReCalculate") . ' </span>';
$s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=totalofround">' . $langs->trans("Mode1") . '</a>'; $s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=totalofround">' . $langs->trans("Mode1") . '</a>';
$s .= ' / '; $s .= ' / ';
$s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=roundoftotal">' . $langs->trans("Mode2") . '</a>'; $s .= '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=calculate&token='.newToken().'&calculationrule=roundoftotal">' . ($conf->dol_optimize_smallscreen ? "2" : $langs->trans("Mode2")) . '</a>';
print '<div class="inline-block">'; print '<div class="inline-block">';
print $form->textwithtooltip($s, $langs->trans("CalculationRuleDesc", $calculationrulenum) . '<br>' . $langs->trans("CalculationRuleDescSupplier"), 2, 1, img_picto('', 'help'), '', 3, '', 0, 'recalculate'); print $form->textwithtooltip($s, $langs->trans("CalculationRuleDesc", $calculationrulenum) . '<br>' . $langs->trans("CalculationRuleDescSupplier"), 2, 1, img_picto('', 'help', 'class="paddingleft paddingright"'), '', 3, '', 0, 'recalculate');
print '&nbsp; &nbsp; &nbsp; &nbsp;'; print '&nbsp; &nbsp; &nbsp; &nbsp;';
print '</div>'; print '</div>';
} }
@@ -3817,7 +3817,7 @@ if ($action == 'create') {
$bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1); $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1);
} }
print '<td class="right">'; print '<td class="right nowraponall">';
if ($objp->baid > 0) { if ($objp->baid > 0) {
print $bankaccountstatic->getNomUrl(1, 'transactions'); print $bankaccountstatic->getNomUrl(1, 'transactions');
} }

View File

@@ -205,7 +205,7 @@ DELETE FROM llx_user_rights WHERE fk_id IN (SELECT id FROM llx_rights_def WHERE
DELETE FROM llx_usergroup_rights WHERE fk_id IN (SELECT id FROM llx_rights_def WHERE module = 'eventorganization'); DELETE FROM llx_usergroup_rights WHERE fk_id IN (SELECT id FROM llx_rights_def WHERE module = 'eventorganization');
DELETE FROM llx_rights_def WHERE module = 'eventorganization'; DELETE FROM llx_rights_def WHERE module = 'eventorganization';
ALTER TABLE llx_rights_def ADD COLUMN family VARCHAR(16) AFTER module_position; ALTER TABLE llx_rights_def ADD COLUMN family VARCHAR(64) AFTER module_position;
-- Reorder some permission -- Reorder some permission
UPDATE llx_rights_def SET module_position = 64 WHERE module = 'intracommreport' AND module_position <> 64; UPDATE llx_rights_def SET module_position = 64 WHERE module = 'intracommreport' AND module_position <> 64;

View File

@@ -25,7 +25,7 @@ create table llx_rights_def
module varchar(64), module varchar(64),
module_origin varchar(64), -- if the permission is for a module but provided by another module, we add here the name of the module that provides the permission module_origin varchar(64), -- if the permission is for a module but provided by another module, we add here the name of the module that provides the permission
module_position integer DEFAULT 0 NOT NULL, module_position integer DEFAULT 0 NOT NULL,
family varchar(16) NULL, family varchar(64) NULL,
family_position integer DEFAULT 0 NOT NULL, family_position integer DEFAULT 0 NOT NULL,
perms varchar(50), perms varchar(50),
subperms varchar(50), subperms varchar(50),

View File

@@ -171,8 +171,10 @@ OnceOnly=Once only
EveryDay=Every day EveryDay=Every day
EveryWeek=Every week EveryWeek=Every week
EveryMonth=Every month EveryMonth=Every month
EveryYear=Every year
DayOfMonth=Day of month DayOfMonth=Day of month
DayOfWeek=Day of week DayOfWeek=Day of week
DayOfYear=Day of year
DateStartPlusOne=Date start + 1 hour DateStartPlusOne=Date start + 1 hour
SetAllEventsToTodo=Set all events to todo SetAllEventsToTodo=Set all events to todo
SetAllEventsToInProgress=Set all events to in progress SetAllEventsToInProgress=Set all events to in progress

View File

@@ -14,7 +14,9 @@ BillsStatisticsSuppliers=Vendors invoices statistics
DisabledBecauseDispatchedInBookkeeping=Disabled because invoice was dispatched into bookkeeping DisabledBecauseDispatchedInBookkeeping=Disabled because invoice was dispatched into bookkeeping
DisabledBecauseNotLastInvoice=Disabled because invoice is not erasable. Some invoices were recorded after this one and it will create holes in the counter. DisabledBecauseNotLastInvoice=Disabled because invoice is not erasable. Some invoices were recorded after this one and it will create holes in the counter.
DisabledBecauseNotLastSituationInvoice=Disabled because invoice is not erasable. This invoice is not the last one in situation invoice cycle. DisabledBecauseNotLastSituationInvoice=Disabled because invoice is not erasable. This invoice is not the last one in situation invoice cycle.
DisabledBecauseNotErasable=Disabled because cannot be erased DisabledBecauseAlreadyPrintedOnce=Disabled because invoice has already been printed at least once
DisabledBecauseAlreadySentByEmail=Disabled because invoice has already been sent by email at least once
DisabledBecauseNotErasable=Disabled because cannot be erased (unknown reason)
InvoiceStandard=Standard invoice InvoiceStandard=Standard invoice
InvoiceStandardAsk=Standard invoice InvoiceStandardAsk=Standard invoice
InvoiceStandardDesc=This kind of invoice is the common invoice. InvoiceStandardDesc=This kind of invoice is the common invoice.

View File

@@ -4,7 +4,7 @@ Fingerprints=Archived events and fingerprints
FingerprintsDesc=This is the tool to browse or extract the unalterable logs. Unalterable logs are generated and store into a dedicated table of the systel, in real time when a business event appears. FingerprintsDesc=This is the tool to browse or extract the unalterable logs. Unalterable logs are generated and store into a dedicated table of the systel, in real time when a business event appears.
ArchivesDesc=You can use this tool to export Unalterable Logs into archive files. They are kept into the system but you should download and copy them into external supports. ArchivesDesc=You can use this tool to export Unalterable Logs into archive files. They are kept into the system but you should download and copy them into external supports.
UnalterableLogTool1=The law of some countries (like in France when doing B2C), ask that you do it on a regular basis. UnalterableLogTool1=The law of some countries (like in France when doing B2C), ask that you do it on a regular basis.
UnalterableLogTool1FR=In france, you MUST do it at least, once every year, we recommand to do it once per month. UnalterableLogTool1FR=In France, you MUST generate archives of the unalterable logs, at least, once every year. We recommand to do it once per month. Also, you MUST keep these archives for at least 7 years. According to the law, It is the user's responsibility to store their archives on media that guarantee their preservation, including in the event of hardware failure, so we recommand to store them on at least 2 different physical supports.
UnalterableLogTool2=This unalterable Logs contains the history of unalterable data. It is the responsibility of the application user to ensure system backups, in order to comply with legal obligations. If you decide to secure your unalterable logs by exporting and storing archives files instead of a full database backup (tab <b>%s</b>), it is recommended to store the exported archive files in different places (Secured cloud, External USB drive, ...). UnalterableLogTool2=This unalterable Logs contains the history of unalterable data. It is the responsibility of the application user to ensure system backups, in order to comply with legal obligations. If you decide to secure your unalterable logs by exporting and storing archives files instead of a full database backup (tab <b>%s</b>), it is recommended to store the exported archive files in different places (Secured cloud, External USB drive, ...).
UnalterableLogTool3=Note that, there is no feature to purge this log and every change tried to be done directly into this log (by a hacker for example) will be reported with a non-valid fingerprint. UnalterableLogTool3=Note that, there is no feature to purge this log and every change tried to be done directly into this log (by a hacker for example) will be reported with a non-valid fingerprint.
FingerprintsDesc2=If you really need to purge this table because you used your application for a demo/test purpose and want to clean your data to start your production, you can ask your reseller or integrator to reset your database (all your data will be removed). FingerprintsDesc2=If you really need to purge this table because you used your application for a demo/test purpose and want to clean your data to start your production, you can ask your reseller or integrator to reset your database (all your data will be removed).
@@ -24,6 +24,7 @@ BlockedlogInfoDialog=Log Details
ListOfTrackedEvents=List of tracked events ListOfTrackedEvents=List of tracked events
Fingerprint=Fingerprint Fingerprint=Fingerprint
FingerprintExport=Fingerprint export FingerprintExport=Fingerprint export
FingerprintExportHMAC=Fingerprint export HMAC
DownloadLogCSV=Export unalterable logs (CSV) DownloadLogCSV=Export unalterable logs (CSV)
DataOfArchivedEvent=Complete data of archived event DataOfArchivedEvent=Complete data of archived event
DataOfArchivedEventHelp=This field contains the complementary data that was archived on real time. Even if some parent business event could have been canceled or modified, the data stored here is the original data, and it can't be modified. DataOfArchivedEventHelp=This field contains the complementary data that was archived on real time. Even if some parent business event could have been canceled or modified, the data stored here is the original data, and it can't be modified.
@@ -50,6 +51,10 @@ TypeOfEvent=Type of event
TotalForAction=Total for event %s TotalForAction=Total for event %s
SecretKey=Secret key SecretKey=Secret key
ErrorPeriodMustBePastToAllowExport=Export into archives is allowed only if period is completely past ErrorPeriodMustBePastToAllowExport=Export into archives is allowed only if period is completely past
RegistrationNumber=Registration number
NumberOfPrints=Number of prints
NumberOfEmailsSent=Number of emails sent
VatCode=Vat code
## logTypes ## logTypes
logBILL_DELETE=Customer invoice logically deleted logBILL_DELETE=Customer invoice logically deleted

View File

@@ -369,6 +369,10 @@ ErrorPaymentAmountMustNotBeNull=Error, payment amount must be defined and not ze
ErrorOneLineContainsADisactivatedProduct=Error, at least one product is not or no more on sale or for purchase ErrorOneLineContainsADisactivatedProduct=Error, at least one product is not or no more on sale or for purchase
ErrorCalendarIsNotYetOpenOrHasBeenClosed=This calendar is not yet open or has been closed ErrorCalendarIsNotYetOpenOrHasBeenClosed=This calendar is not yet open or has been closed
ErrorFieldClassNotFoundForClassName=The class "%s" managing the field type "%s" is not found. ErrorFieldClassNotFoundForClassName=The class "%s" managing the field type "%s" is not found.
ErrorBlockLogNeedAmountsValue=The unalterbale log object needs amounts values to be set
ErrorBlockLogNeedElement=The unalterbale log object needs element type to be set
ErrorBlockLogNeedObject=The unalterbale log object needs object to be set
ErrorBadParameterWhenCallingCreateOfBlockedLog=Bad parameter when calling create of blocked log
# Warnings # Warnings
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup. WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.

View File

@@ -1401,3 +1401,4 @@ AllProjectContacts=All project contacts
ToPay=Pay ToPay=Pay
StarsFieldValue=%s stars StarsFieldValue=%s stars
Archives=Archives Archives=Archives
LastMainDoc=Last generated document

View File

@@ -350,7 +350,7 @@ if ((!defined('NOCSRFCHECK') && empty($dolibarr_nocsrfcheck) && getDolGlobalInt(
if ((GETPOSTISSET('massaction') || $tmpaction) && getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 3) { if ((GETPOSTISSET('massaction') || $tmpaction) && getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 3) {
// All GET actions (except the listed exceptions that are usually post for pre-actions and not real action) and mass actions are processed as sensitive. // All GET actions (except the listed exceptions that are usually post for pre-actions and not real action) and mass actions are processed as sensitive.
// We exclude some action that are not sensitive so legitimate // We exclude some action that are not sensitive so legitimate
if (GETPOSTISSET('massaction') || (strpos($tmpaction, 'display') !== 0 && !in_array($tmpaction, array('create', 'create2', 'createsite', 'createcard', 'edit', 'editcontract', 'editvalidator', 'file_manager', 'presend', 'presend_addmessage', 'preview', 'reconcile', 'specimen')))) { if (GETPOSTISSET('massaction') || (strpos($tmpaction, 'display') !== 0 && !in_array($tmpaction, array('create', 'create2', 'createsite', 'createcard', 'edit', 'editcontract', 'editvalidator', 'file_manager', 'presend', 'presend_addmessage', 'preview', 'reconcile', 'specimen', 'validatenewpassword')))) {
$sensitiveget = true; $sensitiveget = true;
} }
} elseif (getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 2) { } elseif (getDolGlobalInt('MAIN_SECURITY_CSRF_WITH_TOKEN') >= 2) {
@@ -3731,18 +3731,18 @@ if (!function_exists("llxFooter")) {
$forceping = GETPOSTINT('forceping'); $forceping = GETPOSTINT('forceping');
if (($_SERVER["PHP_SELF"] == DOL_URL_ROOT.'/index.php') || $forceping) { if (($_SERVER["PHP_SELF"] == DOL_URL_ROOT.'/index.php') || $forceping) {
$hash_unique_id = dol_hash('dolibarr'.$conf->file->instance_unique_id, 'sha256'); // Note: if the global salt changes, this hash changes too so ping may be counted twice. We don't mind. It is for statistics purpose only. $hash_unique_id_ping = dol_hash('dolibarr'.$conf->file->instance_unique_id, 'sha256', 1);
$constanttosavelastko = 'MAIN_LAST_PING_KO_DATE'; $constanttosavelastko = 'MAIN_LAST_PING_KO_DATE';
$constanttosavefirstok = 'MAIN_FIRST_PING_OK_DATE'; $constanttosavefirstok = 'MAIN_FIRST_PING_OK_DATE';
$constanttosavefirstokid = 'MAIN_FIRST_PING_OK_ID'; $constanttosavefirstokid = 'MAIN_FIRST_PING_OK_ID';
if (!getDolGlobalString($constanttosavefirstok) if (!getDolGlobalString($constanttosavefirstok)
|| (!empty($conf->file->instance_unique_id) && (($hash_unique_id.' - '.DOL_VERSION) != getDolGlobalString($constanttosavefirstokid)) && (getDolGlobalString($constanttosavefirstokid) != 'disabled')) || (!empty($conf->file->instance_unique_id) && (($hash_unique_id_ping.' - '.DOL_VERSION) != getDolGlobalString($constanttosavefirstokid)) && (getDolGlobalString($constanttosavefirstokid) != 'disabled'))
|| $forceping) { || $forceping) {
// No ping done if we are into an alpha version // No ping done if we are into an alpha version
if (strpos('alpha', DOL_VERSION) > 0 && !$forceping) { if (strpos('alpha', DOL_VERSION) > 0 && !$forceping) {
print "\n<!-- NO JS CODE TO ENABLE the anonymous Ping. It is an alpha version -->\n"; print "\n<!-- NO JS CODE TO ENABLE the anonymous Ping. It is an alpha version -->\n";
} elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id]) || $forceping) { // Cookie is set when we uncheck the checkbox in the installation wizard. } elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id_ping]) || $forceping) { // Cookie is set when we uncheck the checkbox in the installation wizard.
// Output code for ping // Output code for ping
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
@@ -3760,28 +3760,29 @@ if (!function_exists("llxFooter")) {
} }
} }
// Add code to force the registration if not yet done but ready (in case past submission failed) // Add code to force the registration of the use of the BlockedLog module if not yet done but ready (in case past submission failed)
// You can use &forceregistration=1 in parameters to force the call if the call was already sent. // You can use &forceregistration=1 in parameters to force also the recall if the call was already sent.
$forceregistration = GETPOSTINT('forceregistration'); $forceregistration = GETPOSTINT('forceregistration');
if (isModEnabled('blockedlog') && (($_SERVER["PHP_SELF"] == DOL_URL_ROOT.'/index.php') || $forceregistration)) { if (isModEnabled('blockedlog') && (($_SERVER["PHP_SELF"] == DOL_URL_ROOT.'/index.php') || $forceregistration)) {
include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php'; include_once DOL_DOCUMENT_ROOT.'/blockedlog/lib/blockedlog.lib.php';
if (!isALNEQualifiedVersion()) { if (!isALNEQualifiedVersion()) {
print "\n<!-- NO JS CODE TO ENABLE the registration. Not a LNE qualified version -->\n"; print "\n<!-- NO JS CODE TO ENABLE the registration. Not a LNE qualified version -->\n";
} elseif (!isRegistrationRecorded()) { } elseif (!isRegistrationDataSaved()) {
print "\n<!-- NO JS CODE TO ENABLE the registration. Registration data not saved -->\n"; print "\n<!-- NO JS CODE TO ENABLE the registration. Registration data not saved -->\n";
} else { } else {
$hash_unique_id = dol_hash('dolibarr'.$conf->file->instance_unique_id, 'sha256'); // Note: if the global salt changes, this hash changes too so ping may be counted twice. We don't mind. It is for statistics purpose only. $hash_unique_id_registration = dol_hash('dolibarr'.$conf->file->instance_unique_id, 'sha256', 1); // Same than getHashUniqueIdOfRegistration()
$constanttosavelastko = 'MAIN_LAST_REGISTRATION_KO_DATE'; $constanttosavelastko = 'MAIN_LAST_REGISTRATION_KO_DATE';
$constanttosavefirstok = 'MAIN_FIRST_REGISTRATION_OK_DATE'; $constanttosavefirstok = 'MAIN_FIRST_REGISTRATION_OK_DATE';
$constanttosavefirstokid = 'MAIN_FIRST_REGISTRATION_OK_ID'; $constanttosavefirstokid = 'MAIN_FIRST_REGISTRATION_OK_ID';
if (!getDolGlobalString($constanttosavefirstok) if (!getDolGlobalString($constanttosavefirstok)
|| (!empty($conf->file->instance_unique_id) && ($hash_unique_id.' - '.DOL_VERSION != getDolGlobalString($constanttosavefirstokid)) && (getDolGlobalString($constanttosavefirstokid) != 'disabled')) || (!empty($conf->file->instance_unique_id) && ($hash_unique_id_registration.' - '.DOL_VERSION != getDolGlobalString($constanttosavefirstokid)) && (getDolGlobalString($constanttosavefirstokid) != 'disabled'))
|| $forceregistration) { || $forceregistration) {
// No ping done if we are into an alpha version // No registration done if we are into an alpha or beta version
if (strpos('alpha', DOL_VERSION) > 0 && !$forceregistration) { if ((strpos('alpha', DOL_VERSION) > 0 || strpos('beta', DOL_VERSION) > 0) && !$forceregistration) {
print "\n<!-- NO JS CODE TO ENABLE the registration. It is an alpha version -->\n"; print "\n<!-- NO JS CODE TO ENABLE the registration. It is an alpha or beta version -->\n";
} elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id]) || $forceregistration) { // Cookie is set when we uncheck the checkbox in the installation wizard. } elseif (empty($_COOKIE['DOLINSTALLNOPING_'.$hash_unique_id_registration]) || $forceregistration) { // Cookie is set when we uncheck the checkbox in the installation wizard.
// Output code for ping // Output code for ping
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';

View File

@@ -23,13 +23,7 @@
* \brief Page to setup margin module * \brief Page to setup margin module
*/ */
include '../../main.inc.php'; require_once '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/margin/lib/margins.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -37,6 +31,10 @@ require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
* @var Translate $langs * @var Translate $langs
* @var User $user * @var User $user
*/ */
require_once DOL_DOCUMENT_ROOT.'/margin/lib/margins.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
require_once DOL_DOCUMENT_ROOT."/compta/facture/class/facture.class.php";
$langs->loadLangs(array("admin", "bills", "margins", "stocks")); $langs->loadLangs(array("admin", "bills", "margins", "stocks"));
@@ -72,29 +70,25 @@ if (preg_match('/del_([a-z0-9_\-]+)/i', $action, $reg)) {
} }
} }
if ($action == 'remises') { if ($action == 'update') {
if (dolibarr_set_const($db, 'MARGIN_METHODE_FOR_DISCOUNT', GETPOST('MARGIN_METHODE_FOR_DISCOUNT'), 'chaine', 0, '', $conf->entity) > 0) { $error = 0;
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs'); if (dolibarr_set_const($db, 'MARGIN_METHODE_FOR_DISCOUNT', GETPOST('MARGIN_METHODE_FOR_DISCOUNT'), 'chaine', 0, '', $conf->entity) <= 0) {
} else {
dol_print_error($db); dol_print_error($db);
} }
if (dolibarr_set_const($db, 'MARGIN_TYPE', GETPOST('MARGIN_TYPE'), 'chaine', 0, '', $conf->entity) <= 0) {
dol_print_error($db);
}
if (dolibarr_set_const($db, 'AGENT_CONTACT_TYPE', GETPOST('AGENT_CONTACT_TYPE'), 'chaine', 0, '', $conf->entity) <= 0) {
dol_print_error($db);
}
if (!$error) {
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
}
} }
if ($action == 'typemarges') {
if (dolibarr_set_const($db, 'MARGIN_TYPE', GETPOST('MARGIN_TYPE'), 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
} else {
dol_print_error($db);
}
}
if ($action == 'contact') {
if (dolibarr_set_const($db, 'AGENT_CONTACT_TYPE', GETPOST('AGENT_CONTACT_TYPE'), 'chaine', 0, '', $conf->entity) > 0) {
setEventMessages($langs->trans("RecordModifiedSuccessfully"), null, 'mesgs');
} else {
dol_print_error($db);
}
}
/* /*
* View * View
@@ -113,53 +107,49 @@ $head = marges_admin_prepare_head();
print dol_get_fiche_head($head, 'parameters', $langs->trans("Margins"), -1, 'margin'); print dol_get_fiche_head($head, 'parameters', $langs->trans("Margins"), -1, 'margin');
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="update">';
print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
print '<table class="noborder centpercent">'; print '<table class="noborder centpercent">';
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print '<td width=300>'.$langs->trans("MemberMainOptions").'</td>'; print '<td colspan="3">'.$langs->trans("MemberMainOptions").'</td>';
print '<td colspan="2">'.$langs->trans("Value").'</td>'."\n";
print '<td class="left">'.$langs->trans("Description").'</td>'."\n";
print '</tr>'; print '</tr>';
// GLOBAL DISCOUNT MANAGEMENT // GLOBAL DISCOUNT MANAGEMENT
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print "<input type=\"hidden\" name=\"action\" value=\"typemarges\">";
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("MARGIN_TYPE").'</td>'; print '<td>'.$langs->trans("MARGIN_TYPE").'</td>';
print '<td>'; print '<td class="minwidth150">';
print ' <input type="radio" name="MARGIN_TYPE" value="1" '; print ' <input type="radio" name="MARGIN_TYPE" id="MARGIN_TYPE1" value="1" ';
if (getDolGlobalString('MARGIN_TYPE') == '1') { if (getDolGlobalString('MARGIN_TYPE') == '1') {
print 'checked '; print 'checked ';
} }
print '/> '; print '/> ';
print $langs->trans('MargeType1'); print '<label for="MARGIN_TYPE1">'.$langs->trans('MargeType1').'</label>';
print '<br>'; print '<br>';
print ' <input type="radio" name="MARGIN_TYPE" value="pmp" '; print ' <input type="radio" name="MARGIN_TYPE" id="MARGIN_TYPE2" value="pmp" ';
if (getDolGlobalString('MARGIN_TYPE') == 'pmp') { if (getDolGlobalString('MARGIN_TYPE') == 'pmp') {
print 'checked '; print 'checked ';
} }
print '/> '; print '/> ';
print $langs->trans('MargeType2'); print '<label for="MARGIN_TYPE2">'.$langs->trans('MargeType2').'</label>';
print '<br>'; print '<br>';
print ' <input type="radio" name="MARGIN_TYPE" value="costprice" '; print ' <input type="radio" name="MARGIN_TYPE" id="MARGIN_TYPE3" value="costprice" ';
if (getDolGlobalString('MARGIN_TYPE') == 'costprice') { if (getDolGlobalString('MARGIN_TYPE') == 'costprice') {
print 'checked '; print 'checked ';
} }
print '/> '; print '/> ';
print $langs->trans('MargeType3'); print '<label for="MARGIN_TYPE3">'.$langs->trans('MargeType3').'</label>';
print '</td>'; print '</td>';
print '<td>'; print '<td class="minwidth200"><span class="small">'.$langs->trans('MarginTypeDesc').'</span>';
print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'" class="button">';
print '</td>';
print '<td>'.$langs->trans('MarginTypeDesc');
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '</form>';
// DISPLAY MARGIN RATES // DISPLAY MARGIN RATES
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("DisplayMarginRates").'</td>'; print '<td>'.$langs->trans("DisplayMarginRates").'</td>';
print '<td colspan="2">'; print '<td>';
if (!empty($conf->use_javascript_ajax)) { if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('DISPLAY_MARGIN_RATES'); print ajax_constantonoff('DISPLAY_MARGIN_RATES');
} else { } else {
@@ -170,13 +160,13 @@ if (!empty($conf->use_javascript_ajax)) {
} }
} }
print '</td>'; print '</td>';
print '<td>'.$langs->trans('MarginRate').' = '.$langs->trans('Margin').' / '.$langs->trans('BuyingPrice').'</td>'; print '<td><span class="small">'.$langs->trans('MarginRate').' = '.$langs->trans('Margin').' / '.$langs->trans('BuyingPrice').'</span></td>';
print '</tr>'; print '</tr>';
// DISPLAY MARK RATES // DISPLAY MARK RATES
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("DisplayMarkRates").'</td>'; print '<td>'.$langs->trans("DisplayMarkRates").'</td>';
print '<td colspan="2">'; print '<td>';
if (!empty($conf->use_javascript_ajax)) { if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('DISPLAY_MARK_RATES'); print ajax_constantonoff('DISPLAY_MARK_RATES');
} else { } else {
@@ -187,13 +177,13 @@ if (!empty($conf->use_javascript_ajax)) {
} }
} }
print '</td>'; print '</td>';
print '<td>'.$langs->trans('MarkRate').' = '.$langs->trans('Margin').' / '.$langs->trans('SellingPrice').'</td>'; print '<td><span class="small">'.$langs->trans('MarkRate').' = '.$langs->trans('Margin').' / '.$langs->trans('SellingPrice').'</span></td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("ForceBuyingPriceIfNull").'</td>'; print '<td>'.$langs->trans("ForceBuyingPriceIfNull").'</td>';
print '<td colspan="2">'; print '<td>';
if (!empty($conf->use_javascript_ajax)) { if (!empty($conf->use_javascript_ajax)) {
print ajax_constantonoff('ForceBuyingPriceIfNull'); print ajax_constantonoff('ForceBuyingPriceIfNull');
} else { } else {
@@ -204,7 +194,7 @@ if (!empty($conf->use_javascript_ajax)) {
} }
} }
print '</td>'; print '</td>';
print '<td>'.$langs->trans('ForceBuyingPriceIfNullDetails').'</td>'; print '<td><span class="small">'.$langs->trans('ForceBuyingPriceIfNullDetails').'</span></td>';
print '</tr>'; print '</tr>';
// GLOBAL DISCOUNT MANAGEMENT // GLOBAL DISCOUNT MANAGEMENT
@@ -215,25 +205,15 @@ $methods = array(
); );
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="remises">';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("MARGIN_METHODE_FOR_DISCOUNT").'</td>'; print '<td>'.$langs->trans("MARGIN_METHODE_FOR_DISCOUNT").'</td>';
print '<td class="left">'; print '<td class="left">';
print Form::selectarray('MARGIN_METHODE_FOR_DISCOUNT', $methods, getDolGlobalString('MARGIN_METHODE_FOR_DISCOUNT')); print Form::selectarray('MARGIN_METHODE_FOR_DISCOUNT', $methods, getDolGlobalString('MARGIN_METHODE_FOR_DISCOUNT'));
print '</td>'; print '</td>';
print '<td>'; print '<td><span class="small">'.$langs->trans('MARGIN_METHODE_FOR_DISCOUNT_DETAILS').'</span></td>';
print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
print '</td>';
print '<td>'.$langs->trans('MARGIN_METHODE_FOR_DISCOUNT_DETAILS').'</td>';
print '</tr>'; print '</tr>';
print '</form>';
// INTERNAL CONTACT TYPE USED AS COMMERCIAL AGENT // INTERNAL CONTACT TYPE USED AS COMMERCIAL AGENT
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
print '<input type="hidden" name="token" value="'.newToken().'">';
print '<input type="hidden" name="action" value="contact">';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("AgentContactType").'</td>'; print '<td>'.$langs->trans("AgentContactType").'</td>';
print '<td class="left">'; print '<td class="left">';
@@ -241,14 +221,15 @@ $formcompany = new FormCompany($db);
$facture = new Facture($db); $facture = new Facture($db);
print $formcompany->selectTypeContact($facture, getDolGlobalString('AGENT_CONTACT_TYPE'), "AGENT_CONTACT_TYPE", "internal", "code", 1, "maxwidth250"); print $formcompany->selectTypeContact($facture, getDolGlobalString('AGENT_CONTACT_TYPE'), "AGENT_CONTACT_TYPE", "internal", "code", 1, "maxwidth250");
print '</td>'; print '</td>';
print '<td>'; print '<td><span class="small">'.$langs->trans('AgentContactTypeDetails').'</span></td>';
print '<input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'">';
print '</td>';
print '<td>'.$langs->trans('AgentContactTypeDetails').'</td>';
print '</tr>'; print '</tr>';
print '</form>';
print '</table>'; print '</table>';
print '</div>';
print '<center><input type="submit" class="button button-edit" value="'.$langs->trans("Modify").'" class="button"></center>';
print '</form>';
print dol_get_fiche_end(); print dol_get_fiche_end();

View File

@@ -1,6 +1,7 @@
<?php <?php
/* Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com> /* Copyright (C) 2018 Nicolas ZABOURI <info@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr> * Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Benjamin Falière <benjamin@faliere.com>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -144,61 +145,61 @@ if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
} }
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificEditorName").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_EDITOR_NAME" class="block">'.$langs->trans("UseSpecificEditorName").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_SPECIFIC_EDITOR_NAME" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_NAME').'">'; print '<input id="MODULEBUILDER_SPECIFIC_EDITOR_NAME" type="text" name="MODULEBUILDER_SPECIFIC_EDITOR_NAME" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_NAME').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificEditorURL").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_EDITOR_URL" class="block">'.$langs->trans("UseSpecificEditorURL").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_SPECIFIC_EDITOR_URL" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_URL').'">'; print '<input id="MODULEBUILDER_SPECIFIC_EDITOR_URL" type="text" name="MODULEBUILDER_SPECIFIC_EDITOR_URL" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_EDITOR_URL').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) { if (getDolGlobalInt('MAIN_FEATURES_LEVEL') >= 2) {
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificFamily").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_FAMILY" class="block">'.$langs->trans("UseSpecificFamily").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_SPECIFIC_FAMILY" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_FAMILY').'">'; print '<input id="MODULEBUILDER_SPECIFIC_FAMILY" type="text" name="MODULEBUILDER_SPECIFIC_FAMILY" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_FAMILY').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificAuthor").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_AUTHOR" class="block">'.$langs->trans("UseSpecificAuthor").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_SPECIFIC_AUTHOR" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR').'">'; print '<input id="MODULEBUILDER_SPECIFIC_AUTHOR" type="text" name="MODULEBUILDER_SPECIFIC_AUTHOR" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_AUTHOR').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificVersion").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_VERSION" class="block">'.$langs->trans("UseSpecificVersion").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_SPECIFIC_VERSION" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_VERSION').'">'; print '<input id="MODULEBUILDER_SPECIFIC_VERSION" type="text" name="MODULEBUILDER_SPECIFIC_VERSION" value="'.getDolGlobalString('MODULEBUILDER_SPECIFIC_VERSION').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
} }
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("UseSpecificReadme").'</td>'; print '<td><label for="MODULEBUILDER_SPECIFIC_README" class="block">'.$langs->trans("UseSpecificReadme").'</label></td>';
print '<td>'; print '<td>';
print '<textarea class="centpercent" rows="20" name="MODULEBUILDER_SPECIFIC_README">'.getDolGlobalString('MODULEBUILDER_SPECIFIC_README').'</textarea>'; print '<textarea id="MODULEBUILDER_SPECIFIC_README" class="centpercent" rows="20" name="MODULEBUILDER_SPECIFIC_README">'.getDolGlobalString('MODULEBUILDER_SPECIFIC_README').'</textarea>';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("AsciiToHtmlConverter").'</td>'; print '<td><label for="MODULEBUILDER_ASCIIDOCTOR" class="block">'.$langs->trans("AsciiToHtmlConverter").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_ASCIIDOCTOR" value="'.getDolGlobalString('MODULEBUILDER_ASCIIDOCTOR').'">'; print '<input id="MODULEBUILDER_ASCIIDOCTOR" type="text" name="MODULEBUILDER_ASCIIDOCTOR" value="'.getDolGlobalString('MODULEBUILDER_ASCIIDOCTOR').'">';
print ' '.$langs->trans("Example").': asciidoc, asciidoctor'; print ' '.$langs->trans("Example").': asciidoc, asciidoctor';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td>'.$langs->trans("AsciiToPdfConverter").'</td>'; print '<td><label for="MODULEBUILDER_ASCIIDOCTORPDF" class="block">'.$langs->trans("AsciiToPdfConverter").'</label></td>';
print '<td>'; print '<td>';
print '<input type="text" name="MODULEBUILDER_ASCIIDOCTORPDF" value="'.getDolGlobalString('MODULEBUILDER_ASCIIDOCTORPDF').'">'; print '<input id="MODULEBUILDER_ASCIIDOCTORPDF" type="text" name="MODULEBUILDER_ASCIIDOCTORPDF" value="'.getDolGlobalString('MODULEBUILDER_ASCIIDOCTORPDF').'">';
print ' '.$langs->trans("Example").': asciidoctor-pdf'; print ' '.$langs->trans("Example").': asciidoctor-pdf';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';

View File

@@ -23,7 +23,7 @@ use Luracast\Restler\RestException;
require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php'; require_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/timespent.class.php';
/** /**
* API class for projects * API class for projects
@@ -291,11 +291,14 @@ class Tasks extends DolibarrApi
if (!DolibarrApi::_checkAccessToResource('tasks', $this->task->id)) { if (!DolibarrApi::_checkAccessToResource('tasks', $this->task->id)) {
throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); throw new RestException(403, 'Access not allowed for login ' . DolibarrApiAccess::$user->login);
} }
$this->task->fetchTimeSpentOnTask(); $this->task->fetchTimeSpentOnTask();
$result = array(); $result = array();
foreach ($this->task->lines as $line) { foreach ($this->task->lines as $line) {
array_push($result, $this->_cleanObjectDatas($line)); array_push($result, $this->_cleanObjectDatas($line));
} }
return $result; return $result;
} }
@@ -561,6 +564,44 @@ class Tasks extends DolibarrApi
); );
} }
/**
* Get time spent of a task
*
* @param int $id Id of task
* @param int $timespent_id Id of timespent
*
* @url GET {id}/getTimeSpent/{timespent_id}
*
* @return TimeSpent
*
* @throws RestException
*/
public function getTimeSpentByID($id, $timespent_id)
{
dol_syslog("API Rest request::getTimeSpent", LOG_DEBUG);
if (! DolibarrApiAccess::$user->hasRight('projet', 'lire')) {
throw new RestException(403);
}
$taskresult = $this->task->fetch($id);
if (!$taskresult ) {
throw new RestException(404, 'Task with id='.$id.' not found');
}
if (!DolibarrApi::_checkAccessToResource('task', $this->task->id)) {
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
$timespent = new TimeSpent($this->db);
$timeresult = $timespent->fetch($timespent_id);
if (!$timeresult ) {
throw new RestException(404, 'Timespent with id='.$timespent_id.' not found');
}
if (!DolibarrApi::_checkAccessToResource('time', $timespent->id)) {
throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
return $this->_cleanTimeSpentObjectDatas($timespent);
}
/** /**
* Add time spent to a task of a project. * Add time spent to a task of a project.
@@ -568,9 +609,9 @@ class Tasks extends DolibarrApi
* { "date": "2016-12-31 23:15:00", "duration": 1800, "user_id": 1, "note": "My time test" } * { "date": "2016-12-31 23:15:00", "duration": 1800, "user_id": 1, "note": "My time test" }
* *
* @param int $id Task ID * @param int $id Task ID
* @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) * @param datetime|string $date Date (YYYY-MM-DD HH:MI:SS in GMT)
* @phan-param string $date
* @param int $duration Duration in seconds (3600 = 1h) * @param int $duration Duration in seconds (3600 = 1h)
* @param int $product_id The product id that is used, default is null
* @param int $user_id User (Use 0 for connected user) * @param int $user_id User (Use 0 for connected user)
* @param string $note Note * @param string $note Note
* @param int|null $progress Progress percentage (0-100). If null, progress is not updated * @param int|null $progress Progress percentage (0-100). If null, progress is not updated
@@ -582,7 +623,7 @@ class Tasks extends DolibarrApi
* @phan-return array{success:array{code:int,message:string}} * @phan-return array{success:array{code:int,message:string}}
* @phpstan-return array{success:array{code:int,message:string}} * @phpstan-return array{success:array{code:int,message:string}}
*/ */
public function addTimeSpent($id, $date, $duration, $user_id = 0, $note = '', $progress = null) public function addTimeSpent($id, $date, $duration, $product_id = null, $user_id = 0, $note = '', $progress = null)
{ {
if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) {
throw new RestException(403); throw new RestException(403);
@@ -602,10 +643,12 @@ class Tasks extends DolibarrApi
} }
$newdate = dol_stringtotime($date, 1); $newdate = dol_stringtotime($date, 1);
$this->task->timespent_date = $newdate; $this->task->timespent_date = $newdate;
$this->task->timespent_datehour = $newdate; $this->task->timespent_datehour = $newdate;
$this->task->timespent_withhour = 1; $this->task->timespent_withhour = 1;
$this->task->timespent_duration = $duration; $this->task->timespent_duration = $duration;
$this->task->timespent_fk_product = $product_id;
$this->task->timespent_fk_user = $uid; $this->task->timespent_fk_user = $uid;
$this->task->timespent_note = $note; $this->task->timespent_note = $note;
if (!empty($this->task->progress)) if (!empty($this->task->progress))
@@ -637,6 +680,7 @@ class Tasks extends DolibarrApi
* @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT) * @param datetime $date Date (YYYY-MM-DD HH:MI:SS in GMT)
* @phan-param string $date * @phan-param string $date
* @param int $duration Duration in seconds (3600 = 1h) * @param int $duration Duration in seconds (3600 = 1h)
* @param int $product_id The product id that is used, default is null
* @param int $user_id User (Use 0 for connected user) * @param int $user_id User (Use 0 for connected user)
* @param string $note Note * @param string $note Note
* *
@@ -646,7 +690,7 @@ class Tasks extends DolibarrApi
* @phan-return array{success:array{code:int,message:string}} * @phan-return array{success:array{code:int,message:string}}
* @phpstan-return array{success:array{code:int,message:string}} * @phpstan-return array{success:array{code:int,message:string}}
*/ */
public function putTimeSpent($id, $timespent_id, $date, $duration, $user_id = 0, $note = '') public function putTimeSpent($id, $timespent_id, $date, $duration, $product_id = null, $user_id = 0, $note = '')
{ {
if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) { if (!DolibarrApiAccess::$user->hasRight('projet', 'creer')) {
throw new RestException(403); throw new RestException(403);
@@ -662,6 +706,7 @@ class Tasks extends DolibarrApi
$this->task->timespent_datehour = $newdate; $this->task->timespent_datehour = $newdate;
$this->task->timespent_withhour = 1; $this->task->timespent_withhour = 1;
$this->task->timespent_duration = $duration; $this->task->timespent_duration = $duration;
$this->task->timespent_fk_product = $product_id;
$this->task->timespent_fk_user = $user_id ?? DolibarrApiAccess::$user->id; $this->task->timespent_fk_user = $user_id ?? DolibarrApiAccess::$user->id;
$this->task->timespent_note = $note; $this->task->timespent_note = $note;
@@ -725,8 +770,9 @@ class Tasks extends DolibarrApi
* *
* @return void * @return void
*/ */
protected function timespentRecordChecks($id, $timespent_id) private function timespentRecordChecks($id, $timespent_id)
{ {
dol_syslog("API Rest request::timespentRecordChecks", LOG_DEBUG);
if ($this->task->fetch($id) <= 0) { if ($this->task->fetch($id) <= 0) {
throw new RestException(404, 'Task not found'); throw new RestException(404, 'Task not found');
} }
@@ -791,6 +837,132 @@ class Tasks extends DolibarrApi
return $object; return $object;
} }
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
/**
* Clean sensitive object data
* @phpstan-template T of Object
*
* @param Object $object Object to clean
* @return Object Object with cleaned properties
*
* @phpstan-param T $object
* @phpstan-return T
*/
protected function _cleanTimeSpentObjectDatas($object)
{
if (!$object->note_private) {
$object->note_private = $object->note;
// unsure if we should use note_private or note_public, but note_private should be more secure
}
$saving_fk_element = $object->fk_element;
// because calling parent::_cleanObjectDatas clears fk_element
// phpcs:enable
$object = parent::_cleanObjectDatas($object);
unset($object->barcode_type);
unset($object->barcode_type_code);
unset($object->barcode_type_label);
unset($object->barcode_type_coder);
unset($object->cond_reglement_id);
unset($object->cond_reglement);
unset($object->fk_delivery_address);
unset($object->shipping_method_id);
unset($object->fk_account);
unset($object->fk_incoterms);
unset($object->label_incoterms);
unset($object->location_incoterms);
unset($object->name);
unset($object->lastname);
unset($object->firstname);
unset($object->civility_id);
unset($object->mode_reglement_id);
unset($object->country);
unset($object->country_id);
unset($object->country_code);
unset($object->weekWorkLoad);
unset($object->weekWorkLoad);
unset($object->actiontypecode);
unset($object->array_languages);
unset($object->array_options);
unset($object->canvas);
unset($object->civility_code);
unset($object->cond_reglement_supplier_id);
unset($object->contact_id);
unset($object->contacts_ids);
unset($object->contacts_ids_internal);
unset($object->date_cloture);
unset($object->date_validation);
unset($object->demand_reason_id);
unset($object->deposit_percent);
unset($object->entity);
unset($object->extraparams);
unset($object->fk_multicurrency);
unset($object->fk_project);
unset($object->fk_user_creat);
unset($object->fk_user_modif);
unset($object->last_main_doc);
unset($object->lines);
unset($object->linkedObjectsIds);
unset($object->module);
unset($object->multicurrency_code);
unset($object->multicurrency_total_ht);
unset($object->multicurrency_total_localtax1);
unset($object->multicurrency_total_localtax2);
unset($object->multicurrency_total_ttc);
unset($object->multicurrency_total_tva);
unset($object->multicurrency_tx);
unset($object->note_public);
unset($object->origin_id);
unset($object->origin_type);
unset($object->product);
unset($object->ref);
unset($object->region_id);
unset($object->retained_warranty_fk_cond_reglement);
unset($object->rowid);
unset($object->shipping_method);
unset($object->specimen);
unset($object->state_id);
unset($object->status);
unset($object->statut);
unset($object->totalpaid);
unset($object->transport_mode_id);
unset($object->user);
unset($object->user_author);
unset($object->user_closing_id);
unset($object->user_creation);
unset($object->user_creation_id);
unset($object->user_modification);
unset($object->user_modification_id);
unset($object->user_valid);
unset($object->user_validation);
unset($object->user_validation_id);
unset($object->warehouse_id);
unset($object->total_ht);
unset($object->total_tva);
unset($object->total_localtax1);
unset($object->total_localtax2);
unset($object->total_ttc);
unset($object->comments);
if (!$object->date_creation) {
$object->date_creation = $object->datec;
}
if (!$object->date_modification) {
$object->date_modification = $object->tms;
}
if (!$object->fk_element) {
$object->fk_element = $saving_fk_element;
// because calling parent::_cleanObjectDatas clears fk_element
}
return $object;
}
/** /**
* Validate fields before create or update object * Validate fields before create or update object
* *

View File

@@ -1754,6 +1754,7 @@ class Task extends CommonObjectLine
$sql .= " ptt.element_date_withhour as task_date_withhour,"; $sql .= " ptt.element_date_withhour as task_date_withhour,";
$sql .= " ptt.element_duration as task_duration,"; $sql .= " ptt.element_duration as task_duration,";
$sql .= " ptt.fk_user,"; $sql .= " ptt.fk_user,";
$sql .= " ptt.fk_product,";
$sql .= " ptt.note,"; $sql .= " ptt.note,";
$sql .= " ptt.thm,"; $sql .= " ptt.thm,";
$sql .= " pt.rowid as task_id,"; $sql .= " pt.rowid as task_id,";
@@ -1805,6 +1806,7 @@ class Task extends CommonObjectLine
$newobj->timespent_line_withhour = $obj->task_date_withhour; $newobj->timespent_line_withhour = $obj->task_date_withhour;
$newobj->timespent_line_duration = $obj->task_duration; $newobj->timespent_line_duration = $obj->task_duration;
$newobj->timespent_line_fk_user = $obj->fk_user; $newobj->timespent_line_fk_user = $obj->fk_user;
$newobj->timespent_line_fk_product = $obj->fk_product;
$newobj->timespent_line_thm = $obj->thm; // hourly rate $newobj->timespent_line_thm = $obj->thm; // hourly rate
$newobj->timespent_line_note = $obj->note; $newobj->timespent_line_note = $obj->note;

View File

@@ -2509,7 +2509,7 @@ if (preg_match('/^dopayment/', $action)) { // If we chose/clicked on the payme
print '<div class="form-row '.(getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2 ? 'center' : 'left').'">'; print '<div class="form-row '.(getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 2 ? 'center' : 'left').'">';
if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) { if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {
print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>'; print '<label for="card-element">'.$langs->trans("CreditOrDebitCard").'</label>';
print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" autofocus required>'; print '<br><input id="cardholder-name" class="marginbottomonly" name="cardholder-name" value="" type="text" placeholder="'.$langs->trans("CardOwner").'" autocomplete="off" spellcheck="false" autofocus required>';
} }
if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) { if (getDolGlobalInt('STRIPE_USE_INTENT_WITH_AUTOMATIC_CONFIRMATION') == 1) {

View File

@@ -58,14 +58,6 @@ if (is_numeric($entity)) {
// Load Dolibarr environment // Load Dolibarr environment
require '../../main.inc.php'; require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
if (isModEnabled('paypal')) {
require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
}
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -76,6 +68,13 @@ if (isModEnabled('paypal')) {
* *
* @var string $dolibarr_main_url_root * @var string $dolibarr_main_url_root
*/ */
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php';
if (isModEnabled('paypal')) {
require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypal.lib.php';
require_once DOL_DOCUMENT_ROOT.'/paypal/lib/paypalfunctions.lib.php';
}
// Hook to be used by external payment modules (ie Payzen, ...) // Hook to be used by external payment modules (ie Payzen, ...)
$hookmanager = new HookManager($db); $hookmanager = new HookManager($db);

View File

@@ -37,10 +37,6 @@ if (!defined('NOBROWSERNOTIF')) {
// Load Dolibarr environment // Load Dolibarr environment
require '../../main.inc.php'; require '../../main.inc.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/vcard.class.php';
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -49,6 +45,9 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/vcard.class.php';
* @var Translate $langs * @var Translate $langs
* @var string $dolibarr_main_url_root * @var string $dolibarr_main_url_root
*/ */
require_once DOL_DOCUMENT_ROOT.'/core/lib/security.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/vcard.class.php';
// Load translation files required by the page // Load translation files required by the page
$langs->loadLangs(array("companies", "other", "recruitment")); $langs->loadLangs(array("companies", "other", "recruitment"));

View File

@@ -1004,7 +1004,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($canvasdisplayactio
* Creation * Creation
*/ */
$private = GETPOSTINT("private"); $private = GETPOSTINT("private");
if (getDolGlobalString('THIRDPARTY_DEFAULT_CREATE_CONTACT') && !GETPOSTISSET('private')) { if (getDolGlobalString('THIRDPARTY_DEFAULT_CREATE_CONTACT') && !GETPOSTISSET('private') && GETPOST("type", 'aZ') != 'f') {
$private = 1; $private = 1;
} }
if (empty($private)) { if (empty($private)) {

View File

@@ -29,12 +29,6 @@
// Load Dolibarr environment // Load Dolibarr environment
require "../main.inc.php"; require "../main.inc.php";
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
/** /**
* @var Conf $conf * @var Conf $conf
* @var DoliDB $db * @var DoliDB $db
@@ -42,6 +36,10 @@ require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
* @var Translate $langs * @var Translate $langs
* @var User $user * @var User $user
*/ */
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.class.php';
// Load translation files required by the page // Load translation files required by the page
$langs->loadLangs(array("companies", "bills", "orders", "suppliers", "propal", "interventions", "contracts", "products")); $langs->loadLangs(array("companies", "bills", "orders", "suppliers", "propal", "interventions", "contracts", "products"));
@@ -508,7 +506,7 @@ if ($sql_select) {
// Filters // Filters
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print '<th class="liste_titre">'; print '<th class="liste_titre">';
print '<input class="flat" type="text" name="sref" size="8" value="'.$sref.'">'; print '<input class="flat width75" type="text" name="sref" value="'.$sref.'">';
print '</th>'; print '</th>';
print '<th class="liste_titre nowrap center valignmiddle">'; // date print '<th class="liste_titre nowrap center valignmiddle">'; // date
print $formother->select_month($month ? (string) $month : '-1', 'month', 1, 0, 'valignmiddle'); print $formother->select_month($month ? (string) $month : '-1', 'month', 1, 0, 'valignmiddle');
@@ -573,7 +571,7 @@ if ($sql_select) {
} }
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td class="nobordernopadding nowrap" width="100">'; print '<td class="nobordernopadding nowraponall">';
print $documentstatic->getNomUrl(1); print $documentstatic->getNomUrl(1);
print '</td>'; print '</td>';
print '<td class="center" width="80">'.dol_print_date($db->jdate($objp->dateprint), 'day').'</td>'; print '<td class="center" width="80">'.dol_print_date($db->jdate($objp->dateprint), 'day').'</td>';

View File

@@ -4441,7 +4441,7 @@ td.border, div.tagtable div div.border {
.nobordertop, .nobordertop tr:first-of-type td { .nobordertop, .nobordertop tr:first-of-type td {
border-top: none !important; border-top: none !important;
} }
.noborderbottom, .noborderbottom tr:last-of-type td { .noborderbottom, tr.noborderbottom td, .noborderbottom tr:last-of-type td {
border-bottom: none !important; border-bottom: none !important;
} }
.bordertop { .bordertop {

View File

@@ -4489,7 +4489,7 @@ td.border, div.tagtable div div.border {
.nobordertop, .nobordertop tr:first-of-type td { .nobordertop, .nobordertop tr:first-of-type td {
border-top: none !important; border-top: none !important;
} }
.noborderbottom, .noborderbottom tr:last-of-type td { .noborderbottom, tr.noborderbottom td, .noborderbottom tr:last-of-type td {
border-bottom: none !important; border-bottom: none !important;
} }
.bordertop { .bordertop {

View File

@@ -42,6 +42,6 @@ define('DOL_MAJOR_VERSION', '23');
define('DOL_VERSION', constant('DOL_MAJOR_VERSION').'.'.constant('DOL_MINOR_VERSION')); define('DOL_VERSION', constant('DOL_MAJOR_VERSION').'.'.constant('DOL_MINOR_VERSION'));
// DOL_VERSION is now a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c // DOL_VERSION is now a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
if (!defined('CERTIF_LNE')) { // Set to 1 if the beta version is a just a candidate for certification (not yet certified) or if the stable version has been certified.
define('CERTIF_LNE', '1'); // Set to 1 if the beta version is a candidate for certification or if the stable version has been certified. Use 2 for debug to force LNE features. // Use 2 to force LNE featuresfro debug purposes
} define('CERTIF_LNE', '1');

View File

@@ -253,6 +253,9 @@ class AllTests
require_once dirname(__FILE__).'/AssetModelTest.php'; require_once dirname(__FILE__).'/AssetModelTest.php';
$suite->addTestSuite('AssetModelTest'); $suite->addTestSuite('AssetModelTest');
require_once dirname(__FILE__).'/BlockedLogAndLNETest.php';
$suite->addTestSuite('BlockedLogAndLNETest');
// Rest // Rest
require_once dirname(__FILE__).'/RestAPIUserTest.php'; require_once dirname(__FILE__).'/RestAPIUserTest.php';
$suite->addTestSuite('RestAPIUserTest'); $suite->addTestSuite('RestAPIUserTest');

View File

@@ -0,0 +1,85 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
* Copyright (C) ---Put here your own copyright and developer email---
* Copyright (C) 2024 Frédéric France <frederic.france@free.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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file test/unit/BlockedLogAndLNETest.php
* \ingroup core
* \brief PHPUnit test for the BlockedLog and LNE class.
*/
global $conf,$user,$langs,$db;
//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver
//require_once 'PHPUnit/Autoload.php';
require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
require_once dirname(__FILE__).'/../../htdocs/compta/facture/class/facture.class.php';
require_once dirname(__FILE__).'/../../htdocs/blockedlog/class/blockedlog.class.php';
require_once dirname(__FILE__).'/CommonClassTest.class.php';
if (empty($user->id)) {
print "Load permissions for admin user nb 1\n";
$user->fetch(1);
$user->loadRights();
}
$conf->global->MAIN_DISABLE_ALL_MAILS = 1;
$langs->load("main");
/**
* Class for PHPUnit tests
*
* @backupGlobals disabled
* @backupStaticAttributes enabled
* @remarks backupGlobals must be disabled to have db,conf,user and lang not erased.
*/
class BlockedLogAndLNETest extends CommonClassTest
{
/**
* testBlockedLogAndLNETest
*
* @return int
*/
public function testBlockedLogAndLNETest()
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
$localobject = new BlockedLog($db);
$localobject->action = 'TEST';
$element = new Facture($db);
$element->initAsSpecimen();
$localobject->element = $element->element;
$localobject->object_data = $element;
$result = $localobject->create($user);
print __METHOD__." result=".$result."\n";
$this->assertLessThan($result, 0);
return $result;
}
// TODO Add more tests
}

View File

@@ -91,6 +91,13 @@ class NumberingModulesTest extends CommonClassTest
print __METHOD__." is_erasable=".$result."\n"; print __METHOD__." is_erasable=".$result."\n";
$this->assertGreaterThanOrEqual(1, $result, 'Test for is_erasable, 1st invoice'); // Can be deleted $this->assertGreaterThanOrEqual(1, $result, 'Test for is_erasable, 1st invoice'); // Can be deleted
// We emulate print on invoice 3 times
$localobject->pos_print_counter = 3;
$result = $localobject->is_erasable();
print __METHOD__." is_erasable=".$result."\n";
$this->assertGreaterThanOrEqual(-6, $result, 'Test for is_erasable, 1st invoice already printed'); // Can be deleted
$localobject2 = new Facture($db); $localobject2 = new Facture($db);
$localobject2->initAsSpecimen(); $localobject2->initAsSpecimen();
$localobject2->fetch_thirdparty(); $localobject2->fetch_thirdparty();

View File

@@ -129,7 +129,6 @@ class SecurityGETPOSTTest extends CommonClassTest
$_GET["param20"] = '<link rel="dns-prefetch" href="//cdnjs.cloudflare.com" />'; $_GET["param20"] = '<link rel="dns-prefetch" href="//cdnjs.cloudflare.com" />';
$result = GETPOST('id', 'int'); // Must return nothing $result = GETPOST('id', 'int'); // Must return nothing
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('', $result); $this->assertEquals('', $result);
@@ -316,6 +315,7 @@ class SecurityGETPOSTTest extends CommonClassTest
$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1;
$conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 0; $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 0;
//$_POST["param0"] = 'A real string with <a href="rrr" title="aabb">aaa</a> and " inside content'; //$_POST["param0"] = 'A real string with <a href="rrr" title="aabb">aaa</a> and " inside content';
$result = GETPOST("param0", 'restricthtml'); $result = GETPOST("param0", 'restricthtml');
$resultexpected = 'A real string with <a href="rrr" title=\'aa"bb\'>aaa</a> and " and \' and &amp; inside content'; $resultexpected = 'A real string with <a href="rrr" title=\'aa"bb\'>aaa</a> and " and \' and &amp; inside content';
@@ -337,6 +337,11 @@ class SecurityGETPOSTTest extends CommonClassTest
//$this->assertEquals('InvalidHTMLStringCantBeCleaned', $result, 'Test 15b'); // With some PHP and libxml version, we got this result when parsing invalid HTML, but ... //$this->assertEquals('InvalidHTMLStringCantBeCleaned', $result, 'Test 15b'); // With some PHP and libxml version, we got this result when parsing invalid HTML, but ...
//$this->assertEquals('"c:\this is a path~1\aaan 110;" abcdef', $result); // ... on other PHP and libxml versions, we got a HTML that has been cleaned //$this->assertEquals('"c:\this is a path~1\aaan 110;" abcdef', $result); // ... on other PHP and libxml versions, we got a HTML that has been cleaned
$_POST["pagecontentwithaconstantvarinurl"] = '<a href="https://[__aaa__]/aaa.html">https://[__aaa__]/aaa.html</a>';
$result = GETPOST("pagecontentwithaconstantvarinurl", 'restricthtml');
print __METHOD__." result=".$result."\n";
$this->assertEquals('<a href="https://[__aaa__]/aaa.html">https://[__aaa__]/aaa.html</a>', $result, 'Test on HTML content with url with constant');
// Test with restricthtml + MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY only to test disabling of bad attributes // Test with restricthtml + MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY only to test disabling of bad attributes
@@ -456,6 +461,7 @@ class SecurityGETPOSTTest extends CommonClassTest
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('x3aalert(1)', $result, 'Test for backtopage param'); $this->assertEquals('x3aalert(1)', $result, 'Test for backtopage param');
// Test with restricthtml + MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT to test limit of external links
$conf->global->MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT = 3; $conf->global->MAIN_SECURITY_MAX_IMG_IN_HTML_CONTENT = 3;
$_POST["pagecontentwithlinks"] = '<img src="aaa"><img src="bbb"><img src="/ccc"><span style="background: url(/ddd)"></span>'; $_POST["pagecontentwithlinks"] = '<img src="aaa"><img src="bbb"><img src="/ccc"><span style="background: url(/ddd)"></span>';
@@ -498,7 +504,6 @@ class SecurityGETPOSTTest extends CommonClassTest
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertEquals('ErrorHTMLExternalLinksNotAllowed (Example: http://ddd)', $result, 'Test on MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 1 (no links to http allowed)'); $this->assertEquals('ErrorHTMLExternalLinksNotAllowed (Example: http://ddd)', $result, 'Test on MAIN_DISALLOW_URL_INTO_DESCRIPTIONS = 1 (no links to http allowed)');
// Test substitution in GET url // Test substitution in GET url
$user->fk_user = 999; $user->fk_user = 999;
$mysoc->country_id = 1; $mysoc->country_id = 1;