From 2e0c3e622107cb5eb40dffb9b27a275e5f3e67a3 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:30:38 +0100 Subject: [PATCH 01/96] Add default reminder email template --- ChangeLog.md | 4 + README.md | 2 + admin/setup.php | 217 ++++++++++++++++---- class/timesheetweek_reminder.class.php | 251 ++++++++++++++++++++++++ core/modules/modTimesheetWeek.class.php | 218 +++++++++++++++++--- langs/en_US/timesheetweek.lang | 23 +++ langs/fr_FR/timesheetweek.lang | 23 +++ 7 files changed, 679 insertions(+), 59 deletions(-) create mode 100644 class/timesheetweek_reminder.class.php diff --git a/ChangeLog.md b/ChangeLog.md index 8cbd24b..36eb6bf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,5 +1,9 @@ # CHANGELOG MODULE TIMESHEETWEEK FOR [DOLIBARR ERP CRM](https://www.dolibarr.org) +## 1.6.0 (20/06/2026) +- Ajoute un rappel hebdomadaire automatique par email configurable (activation, jour, heure, modèle) et une tâche planifiée dédiée avec bouton de test administrateur. + / Adds a configurable automatic weekly email reminder (enablement, day, time, template) plus a dedicated scheduled task and admin test button. + ## 1.5.0 (01/12/2025) - Ajoute une action de masse pour générer un PDF unique fusionnant les feuilles sélectionnées en utilisant le modèle par défaut. / Adds a mass action to generate a single merged PDF for selected timesheets using the default template. diff --git a/README.md b/README.md index 3273f32..364e614 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ TimesheetWeek ajoute une gestion hebdomadaire des feuilles de temps fidèle à l - Redirection automatique vers la feuille existante en cas de tentative de doublon afin d'éviter les saisies multiples. - Suivi des compteurs hebdomadaires de zones et de paniers directement sur les feuilles et recalcul automatique à chaque enregistrement. - Saisie dédiée pour les salariés en forfait jour grâce à des sélecteurs Journée/Matin/Après-midi convertissant automatiquement les heures. +- Rappel hebdomadaire automatique par email configurable (activation, jour, heure, modèle) avec tâche planifiée dédiée et bouton d'envoi de test administrateur. - Affichage des compteurs dans la liste hebdomadaire et ajout du libellé « Zone » sur chaque sélecteur quotidien pour clarifier la saisie. - Ligne de total en bas de la liste hebdomadaire pour additionner heures, zones, paniers et afficher la colonne de date de validation. - Création rapide d'une feuille d'heures via le raccourci « Ajouter » du menu supérieur. @@ -51,6 +52,7 @@ TimesheetWeek delivers weekly timesheet management that follows Dolibarr design - Automatic redirect to the existing timesheet when a duplicate creation is attempted. - Weekly counters for zones and meal allowances with automatic recomputation on each save. - Dedicated input for daily rate employees with Full day/Morning/Afternoon selectors that automatically convert hours. +- Configurable automatic weekly email reminder (enablement, weekday, time, template) with a dedicated scheduled task and admin test send button. - Counter display inside the weekly list plus a « Zone » caption on each daily selector for better input guidance. - Total row at the bottom of the weekly list to sum hours, zones, meals and expose the validation date column. - Quick creation shortcut available from the top-right « Add » menu. diff --git a/admin/setup.php b/admin/setup.php index 1394de5..7d19608 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -22,7 +22,6 @@ */ // EN: Load Dolibarr environment with fallback paths. -// FR: Charge l'environnement Dolibarr en testant les chemins possibles. $res = 0; if (!$res && file_exists(__DIR__.'/../main.inc.php')) { $res = require_once __DIR__.'/../main.inc.php'; @@ -40,34 +39,37 @@ 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/pdf.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; // EN: Load document helper functions required for model toggles. -// FR: Charge les fonctions d'aide aux documents nécessaires aux commutateurs de modèles. require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; dol_include_once('/timesheetweek/lib/timesheetweek.lib.php'); dol_include_once('/timesheetweek/class/timesheetweek.class.php'); +dol_include_once('/timesheetweek/class/timesheetweek_reminder.class.php'); // EN: Load translation files required for the configuration page. -// FR: Charge les fichiers de traduction nécessaires à la page de configuration. $langs->loadLangs(array('admin', 'other', 'timesheetweek@timesheetweek')); // EN: Only administrators can access the setup. -// FR: Seuls les administrateurs peuvent accéder à la configuration. if (empty($user->admin)) { accessforbidden(); } // EN: Read HTTP parameters once so we can re-use them further down. -// FR: Lit les paramètres HTTP une seule fois pour les réutiliser ensuite. $action = GETPOST('action', 'aZ09'); $value = GETPOST('value', 'alphanohtml'); $token = GETPOST('token', 'alphanohtml'); // EN: Capture additional parameters used to reproduce Dolibarr's document model toggles. -// FR: Capture les paramètres additionnels utilisés par les bascules de modèles de document Dolibarr. $docLabel = GETPOST('label', 'alphanohtml'); $scanDir = GETPOST('scan_dir', 'alpha'); +$reminderAction = GETPOST('reminder_action', 'aZ09'); + +if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php')) { + dol_include_once('/core/class/cemailtemplates.class.php'); +} elseif (is_readable(DOL_DOCUMENT_ROOT.'/core/class/emailtemplates.class.php')) { + dol_include_once('/core/class/emailtemplates.class.php'); +} // EN: Helper to enable a PDF model in the database. -// FR: Aide pour activer un modèle PDF dans la base. function timesheetweekEnableDocumentModel($model, $label = '', $scandir = '') { global $db, $conf; @@ -77,7 +79,6 @@ function timesheetweekEnableDocumentModel($model, $label = '', $scandir = '') } // EN: Check if the model already exists for the current entity to avoid duplicates. - // FR: Vérifie si le modèle existe déjà pour l'entité courante afin d'éviter les doublons. $sql = 'SELECT rowid FROM '.MAIN_DB_PREFIX."document_model WHERE nom='".$db->escape($model)."' AND type='timesheetweek' AND entity=".((int) $conf->entity); $resql = $db->query($sql); if (!$resql) { @@ -91,13 +92,11 @@ function timesheetweekEnableDocumentModel($model, $label = '', $scandir = '') $fields = array(); // EN: Refresh label when provided to keep UI messages in sync. - // FR: Met à jour le libellé fourni pour garder l'interface cohérente. if ($label !== '') { $fields[] = "libelle='".$db->escape($label)."'"; } // EN: Refresh directory hint when provided to ease future scans. - // FR: Met à jour le chemin fourni pour faciliter les scans ultérieurs. if ($scandir !== '') { $fields[] = "description='".$db->escape($scandir)."'"; } @@ -122,7 +121,6 @@ function timesheetweekEnableDocumentModel($model, $label = '', $scandir = '') // EN: Helper to disable a PDF model from the database. -// FR: Aide pour désactiver un modèle PDF dans la base. function timesheetweekDisableDocumentModel($model) { if (empty($model)) { @@ -134,7 +132,6 @@ function timesheetweekDisableDocumentModel($model) } // EN: Build the list of numbering modules available for the module. -// FR: Construit la liste des modules de numérotation disponibles pour le module. function timesheetweekListNumberingModules(array $directories, Translate $langs, TimesheetWeek $sample, $selected) { global $db; @@ -143,7 +140,6 @@ function timesheetweekListNumberingModules(array $directories, Translate $langs, foreach ($directories as $reldir) { // EN: Resolve the directory that holds the numbering module classes. - // FR: Résout le répertoire qui contient les classes de numérotation. $dir = dol_buildpath(rtrim($reldir, '/').'/timesheetweek/core/modules/timesheetweek/'); if (!is_dir($dir)) { continue; @@ -210,7 +206,6 @@ function timesheetweekListNumberingModules(array $directories, Translate $langs, } // EN: Build the list of available document models for the module. -// FR: Construit la liste des modèles de documents disponibles pour le module. function timesheetweekListDocumentModels(array $directories, Translate $langs, array $enabled, $default) { global $db; @@ -219,7 +214,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a foreach ($directories as $reldir) { // EN: Resolve the directory that stores the document model definitions. - // FR: Résout le répertoire qui contient les définitions de modèles de document. $dir = dol_buildpath(rtrim($reldir, '/').'/timesheetweek/core/modules/timesheetweek/doc/'); if (!is_dir($dir)) { continue; @@ -275,8 +269,15 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Verify CSRF token when the request changes the configuration. -// FR: Vérifie le jeton CSRF lorsque la requête modifie la configuration. if (in_array($action, array('setmodule', 'setdoc', 'setdocmodel', 'delmodel', 'setquarterday'), true)) { + if (function_exists('dol_verify_token')) { + if (empty($token) || dol_verify_token($token) <= 0) { + accessforbidden(); + } + } +} + +if (in_array($reminderAction, array('savereminder', 'testreminder'), true)) { if (function_exists('dol_verify_token')) { if (empty($token) || dol_verify_token($token) <= 0) { accessforbidden(); @@ -285,7 +286,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Persist the chosen numbering module. -// FR: Enregistre le module de numérotation choisi. if ($action === 'setmodule' && !empty($value)) { $result = dolibarr_set_const($db, 'TIMESHEETWEEK_ADDON', $value, 'chaine', 0, '', $conf->entity); if ($result > 0) { @@ -296,7 +296,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Set the default PDF model while ensuring the model is enabled. -// FR: Définit le modèle PDF par défaut tout en s'assurant qu'il est activé. if ($action === 'setdoc' && !empty($value)) { $res = timesheetweekEnableDocumentModel($value, $docLabel, $scanDir); if ($res > 0) { @@ -310,7 +309,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Activate a PDF model without making it the default. -// FR: Active un modèle PDF sans le définir comme défaut. if ($action === 'setdocmodel' && !empty($value)) { $res = timesheetweekEnableDocumentModel($value, $docLabel, $scanDir); if ($res > 0) { @@ -321,7 +319,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Disable a PDF model and remove the default flag if needed. -// FR: Désactive un modèle PDF et supprime le statut par défaut si nécessaire. if ($action === 'delmodel' && !empty($value)) { $res = timesheetweekDisableDocumentModel($value); if ($res > 0) { @@ -335,12 +332,11 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Enable or disable the quarter-day selector for daily rate contracts. -// FR: Active ou désactive le sélecteur quart de jour pour les contrats au forfait jour. if ($action === 'setquarterday') { - $targetValue = (int) GETPOST('value', 'int'); - if ($targetValue !== 0) { - $targetValue = 1; - } + $targetValue = (int) GETPOST('value', 'int'); + if ($targetValue !== 0) { + $targetValue = 1; + } $res = dolibarr_set_const($db, 'TIMESHEETWEEK_QUARTERDAYFORDAILYCONTRACT', $targetValue, 'chaine', 0, '', $conf->entity); if ($res > 0) { setEventMessages($langs->trans('SetupSaved'), null, 'mesgs'); @@ -349,19 +345,70 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } } +if ($reminderAction === 'savereminder') { +$reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); +$reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); +$reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); + $reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); + + $error = 0; + + if ($reminderWeekdayValue < 1 || $reminderWeekdayValue > 7) { + setEventMessages($langs->trans('TimesheetWeekReminderWeekdayInvalid'), null, 'errors'); + $error++; + } + + if (!preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', $reminderHourValue)) { + setEventMessages($langs->trans('TimesheetWeekReminderHourInvalid'), null, 'errors'); + $error++; + } + + if (!$error) { + $results = array(); + $results[] = dolibarr_set_const($db, 'TIMESHEETWEEK_REMINDER_ENABLED', ($reminderEnabledValue ? 1 : 0), 'chaine', 0, '', $conf->entity); + $results[] = dolibarr_set_const($db, 'TIMESHEETWEEK_REMINDER_WEEKDAY', $reminderWeekdayValue, 'chaine', 0, '', $conf->entity); + $results[] = dolibarr_set_const($db, 'TIMESHEETWEEK_REMINDER_HOUR', $reminderHourValue, 'chaine', 0, '', $conf->entity); + $results[] = dolibarr_set_const($db, 'TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $reminderTemplateValue, 'chaine', 0, '', $conf->entity); + + $hasError = false; + foreach ($results as $resultValue) { + if ($resultValue <= 0) { + $hasError = true; + break; + } + } + + if ($hasError) { + setEventMessages($langs->trans('Error'), null, 'errors'); + } else { + setEventMessages($langs->trans('SetupSaved'), null, 'mesgs'); +} +} +} + + if ($reminderAction === 'testreminder') { + $resultTest = TimesheetweekReminder::sendTest($db, $user); + if ($resultTest > 0) { + setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); + } else { + setEventMessages($langs->trans('TimesheetWeekReminderTestError'), null, 'errors'); + } +} + // EN: Read the selected options so we can highlight them in the UI. -// FR: Lit les options sélectionnées pour les mettre en avant dans l'interface. $selectedNumbering = getDolGlobalString('TIMESHEETWEEK_ADDON', 'mod_timesheetweek_standard'); $defaultPdf = getDolGlobalString('TIMESHEETWEEK_ADDON_PDF', 'standard_timesheetweek'); $useQuarterDaySelector = getDolGlobalInt('TIMESHEETWEEK_QUARTERDAYFORDAILYCONTRACT', 0); +$reminderEnabled = getDolGlobalInt('TIMESHEETWEEK_REMINDER_ENABLED', 0); +$reminderWeekday = getDolGlobalInt('TIMESHEETWEEK_REMINDER_WEEKDAY', 1); +$reminderHour = getDolGlobalString('TIMESHEETWEEK_REMINDER_HOUR', '18:00'); +$reminderTemplateId = getDolGlobalInt('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 0); $directories = array_merge(array('/'), (array) $conf->modules_parts['models']); // EN: Prepare a lightweight object to test numbering module activation. -// FR: Prépare un objet léger pour tester l'activation des modules de numérotation. $sampleTimesheet = new TimesheetWeek($db); // EN: Fetch the enabled document models from the database. -// FR: Récupère les modèles de documents activés depuis la base. $enabledModels = array(); $sql = 'SELECT nom FROM '.MAIN_DB_PREFIX."document_model WHERE type='timesheetweek' AND entity IN (0, ".((int) $conf->entity).')'; $resql = $db->query($sql); @@ -373,10 +420,29 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Build the metadata arrays used by the HTML rendering below. -// FR: Construit les tableaux de métadonnées utilisés par l'affichage HTML ci-dessous. $numberingModules = timesheetweekListNumberingModules($directories, $langs, $sampleTimesheet, $selectedNumbering); $documentModels = timesheetweekListDocumentModels($directories, $langs, $enabledModels, $defaultPdf); $pageToken = function_exists('newToken') ? newToken() : ''; +$form = new Form($db); + +$emailTemplates = array(); +$emailTemplateClass = ''; +if (class_exists('CEmailTemplates')) { + $emailTemplateClass = 'CEmailTemplates'; +} elseif (class_exists('EmailTemplates')) { + $emailTemplateClass = 'EmailTemplates'; +} + +if (!empty($emailTemplateClass)) { + $emailTemplateObject = new $emailTemplateClass($db); + if (method_exists($emailTemplateObject, 'fetchAll')) { + $filters = array('entity' => $conf->entity); + $templatesResult = $emailTemplateObject->fetchAll('', '', 0, 0, $filters); + if (is_array($templatesResult)) { + $emailTemplates = $templatesResult; + } + } +} $title = $langs->trans('ModuleSetup', 'Timesheetweek'); $helpurl = ''; @@ -397,7 +463,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print '
'; // EN: Display the numbering modules with switch-based activation instead of radios. -// FR: Affiche les modules de numérotation avec des commutateurs plutôt qu'avec des radios. print '
'.$langs->trans('TimesheetWeekNumberingHelp').'
'; print '
'; @@ -433,7 +498,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''.(!empty($moduleInfo['example']) ? dol_escape_htmltag($moduleInfo['example']) : ' ').''; // EN: Render the activation toggle that selects the numbering model with CSRF protection. - // FR: Affiche le commutateur d’activation qui sélectionne le modèle de numérotation avec protection CSRF. print ''; if ($moduleInfo['active']) { print img_picto($langs->trans('Enabled'), 'switch_on'); @@ -455,7 +519,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print '
'; // EN: Display the helper switches dedicated to the daily-rate contract workflows. -// FR: Affiche les commutateurs dédiés aux workflows des contrats au forfait jour. print load_fiche_titre($langs->trans('TimesheetWeekDailyRateOptions'), '', 'setup'); print '
'.$langs->trans('TimesheetWeekDailyRateOptionsHelp').'
'; @@ -468,7 +531,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; // EN: Render the switch dedicated to the quarter-day declaration helper. -// FR: Affiche le commutateur dédié à l'aide de déclaration des quarts de jour. print ''; print ''.$langs->trans('TimesheetWeekQuarterDayForDailyContract').''; print ''.$langs->trans('TimesheetWeekQuarterDayForDailyContractHelp').''; @@ -488,6 +550,95 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print '
'; +print load_fiche_titre($langs->trans('TimesheetWeekReminderSectionTitle'), '', 'email'); +print '
'.$langs->trans('TimesheetWeekReminderSectionHelp').'
'; + +print '
'; +print ''; + +print '
'; +print ''; +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +$weekdayOptions = array( +1 => $langs->trans('Monday'), +2 => $langs->trans('Tuesday'), +3 => $langs->trans('Wednesday'), +4 => $langs->trans('Thursday'), +5 => $langs->trans('Friday'), +6 => $langs->trans('Saturday'), +7 => $langs->trans('Sunday'), +); + +print ''; +print ''; +print ''; +print ''; +print ''; + +print ''; +print ''; +print ''; +print ''; +print ''; + +$templateOptions = array(0 => $langs->trans('None')); +foreach ($emailTemplates as $templateItem) { + $templateId = 0; + if (!empty($templateItem->id)) { + $templateId = (int) $templateItem->id; + } elseif (!empty($templateItem->rowid)) { + $templateId = (int) $templateItem->rowid; + } + + if (empty($templateId)) { + continue; + } + + $templateLabel = ''; + if (!empty($templateItem->label)) { + $templateLabel = $templateItem->label; + } elseif (!empty($templateItem->ref)) { + $templateLabel = $templateItem->ref; + } elseif (!empty($templateItem->topic)) { + $templateLabel = $templateItem->topic; + } else { + $templateLabel = '#'.$templateId; + } + + $templateOptions[$templateId] = $templateLabel; +} + +print ''; +print ''; +print ''; +print ''; +print ''; + +print '
'.$langs->trans('Name').''.$langs->trans('Description').''.$langs->trans('Value').'
'.$langs->trans('TimesheetWeekReminderEnabled').''.$langs->trans('TimesheetWeekReminderEnabledHelp').''; +print ''; +print '
'.$langs->trans('TimesheetWeekReminderWeekday').''.$langs->trans('TimesheetWeekReminderWeekdayHelp').''.$form->selectarray('TIMESHEETWEEK_REMINDER_WEEKDAY', $weekdayOptions, $reminderWeekday, 0, 0, 0, '', 0, 0, 0, '', '', 1).'
'.$langs->trans('TimesheetWeekReminderHour').''.$langs->trans('TimesheetWeekReminderHourHelp').'
'.$langs->trans('TimesheetWeekReminderEmailTemplate').''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''.$form->selectarray('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $templateOptions, $reminderTemplateId, 0, 0, 0, '', 0, 0, 0, '', '', 1).'
'; +print '
'; + +print '
'; +print ''; +print ' '; +print ''; +print '
'; +print '
'; + +print '
'; + print load_fiche_titre($langs->trans('TimesheetWeekPDFModels'), '', 'pdf'); print '
'.$langs->trans('TimesheetWeekPDFModelsHelp').'
'; diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php new file mode 100644 index 0000000..763dea0 --- /dev/null +++ b/class/timesheetweek_reminder.class.php @@ -0,0 +1,251 @@ + + * + * 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 . + */ + +if (!defined('NOREQUIREUSER')) { + define('NOREQUIREUSER', 1); +} +if (!defined('NOREQUIREDB')) { + define('NOREQUIREDB', 1); +} +if (!defined('NOREQUIRESOC')) { + define('NOREQUIRESOC', 1); +} +if (!defined('NOREQUIRETRAN')) { + define('NOREQUIRETRAN', 1); +} +if (!defined('NOREQUIRESUBPERMS')) { + define('NOREQUIRESUBPERMS', 1); +} +if (!defined('NOREQUIREMENU')) { + define('NOREQUIREMENU', 1); +} + +require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; +require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; +dol_include_once('/core/class/emailtemplates.class.php'); + +dol_include_once('/timesheetweek/class/timesheetweek.class.php'); + +/** + * EN: Cron helper used to send weekly reminders. + * FR: Assistant cron utilisé pour envoyer les rappels hebdomadaires. + */ +class TimesheetweekReminder +{ + /** + * EN: Run cron job to send weekly reminder emails. + * FR: Exécuter la tâche planifiée pour envoyer les rappels hebdomadaires par email. + * + * @param DoliDB $db Database handler + * @param int $limit Optional limit for recipients + * @param int $forcerun Force execution (1) or use normal scheduling (0) + * @param array $targetUserIds Limit execution to specific user ids when provided + * @return int <0 if KO, >=0 if OK (number of emails sent) + */ + public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds = array()) + { + global $conf, $langs; + + $langs->loadLangs(array('timesheetweek@timesheetweek')); + + dol_syslog(__METHOD__, LOG_DEBUG); + + $reminderEnabledConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_ENABLED', $conf->entity); + $reminderEnabled = !empty($reminderEnabledConst) ? (int) $reminderEnabledConst : 0; + if (empty($reminderEnabled) && empty($forcerun)) { + dol_syslog('TimesheetweekReminder: reminder disabled', LOG_INFO); + return 0; + } + + $reminderWeekdayConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_WEEKDAY', $conf->entity); + $reminderWeekday = !empty($reminderWeekdayConst) ? (int) $reminderWeekdayConst : 1; + if ($reminderWeekday < 1 || $reminderWeekday > 7) { + dol_syslog($langs->trans('TimesheetWeekReminderWeekdayInvalid'), LOG_ERR); + return -1; + } + + $reminderHourConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_HOUR', $conf->entity); + $reminderHour = !empty($reminderHourConst) ? $reminderHourConst : '18:00'; + if (!preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', $reminderHour)) { + dol_syslog($langs->trans('TimesheetWeekReminderHourInvalid'), LOG_ERR); + return -1; + } + + $templateIdConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $conf->entity); + $templateId = !empty($templateIdConst) ? (int) $templateIdConst : 0; + if (empty($templateId)) { + dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); + return 0; + } + + $timezoneCode = !empty($conf->timezone) ? $conf->timezone : 'UTC'; + $now = dol_now(); + $nowArray = dol_getdate($now, true, $timezoneCode); + $currentWeekday = (int) $nowArray['wday']; + $currentWeekdayIso = ($currentWeekday === 0) ? 7 : $currentWeekday; + $currentMinutes = ((int) $nowArray['hours'] * 60) + (int) $nowArray['minutes']; + + list($targetHour, $targetMinute) = explode(':', $reminderHour); + $targetMinutes = ((int) $targetHour * 60) + (int) $targetMinute; + $windowMinutes = 60; + $lowerBound = max(0, $targetMinutes - $windowMinutes); + $upperBound = min(1440, $targetMinutes + $windowMinutes); + + if (empty($forcerun)) { + if ($currentWeekdayIso !== $reminderWeekday) { + dol_syslog('TimesheetweekReminder: not the configured day, skipping execution', LOG_DEBUG); + return 0; + } + if ($currentMinutes < $lowerBound || $currentMinutes > $upperBound) { + dol_syslog('TimesheetweekReminder: outside configured time window, skipping execution', LOG_DEBUG); + return 0; + } + } + + $emailTemplateClass = ''; + if (class_exists('CEmailTemplates')) { + $emailTemplateClass = 'CEmailTemplates'; + } elseif (class_exists('EmailTemplates')) { + $emailTemplateClass = 'EmailTemplates'; + } + + if (empty($emailTemplateClass)) { + dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_ERR); + return -1; + } + + $emailTemplate = new $emailTemplateClass($db); + $templateFetch = $emailTemplate->fetch($templateId); + if ($templateFetch <= 0) { + dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); + return 0; + } + + $subject = !empty($emailTemplate->topic) ? $emailTemplate->topic : $emailTemplate->label; + $body = !empty($emailTemplate->content) ? $emailTemplate->content : ''; + + if (empty($subject) || empty($body)) { + dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); + return 0; + } + + $from = getDolGlobalString('MAIN_MAIL_EMAIL_FROM', ''); + if (empty($from)) { + $from = getDolGlobalString('MAIN_INFO_SOCIETE_MAIL', ''); + } + + $substitutions = getCommonSubstitutionArray($langs, 0, null, null, null); + complete_substitutions_array($substitutions, $langs, null); + + $eligibleRights = array( + 45000301, // read own + 45000302, // read child + 45000303, // read all + 45000304, // write own + 45000305, // write child + 45000306, // write all + 45000310, // validate generic + 45000311, // validate own + 45000312, // validate child + 45000313, // validate all + 45000314, // seal + 45000315, // unseal + ); + + $entityFilter = getEntity('user'); + $sql = 'SELECT DISTINCT u.rowid, u.lastname, u.firstname, u.email'; + $sql .= ' FROM '.MAIN_DB_PREFIX."user AS u"; + $sql .= ' INNER JOIN '.MAIN_DB_PREFIX."user_rights AS ur ON ur.fk_user = u.rowid AND ur.entity IN (".$entityFilter.')'; + $sql .= " WHERE u.statut = 1 AND u.email IS NOT NULL AND u.email <> ''"; + $sql .= ' AND u.entity IN ('.$entityFilter.')'; + $sql .= ' AND ur.fk_id IN ('.implode(',', array_map('intval', $eligibleRights)).')'; + if (!empty($targetUserIds)) { + $sql .= ' AND u.rowid IN ('.implode(',', array_map('intval', $targetUserIds)).')'; + } + $sql .= ' ORDER BY u.rowid ASC'; + if ($limit > 0) { + $sql .= $db->plimit((int) $limit); + } + + $resql = $db->query($sql); + if (!$resql) { + dol_syslog($db->lasterror(), LOG_ERR); + return -1; + } + + $emailsSent = 0; + $errors = 0; + + while ($obj = $db->fetch_object($resql)) { + $recipient = trim($obj->email); + if (empty($recipient)) { + continue; + } + + $user = new User($db); + $fetchUser = $user->fetch($obj->rowid); + if ($fetchUser < 0) { + dol_syslog($user->error, LOG_ERR); + $errors++; + continue; + } + + $userSubstitutions = $substitutions; + $userSubstitutions['__USER_FIRSTNAME__'] = $user->firstname; + $userSubstitutions['__USER_LASTNAME__'] = $user->lastname; + $userSubstitutions['__USER_FULLNAME__'] = dolGetFirstLastname($user->firstname, $user->lastname); + $userSubstitutions['__USER_EMAIL__'] = $recipient; + complete_substitutions_array($userSubstitutions, $langs, null, $user); + + $preparedSubject = make_substitutions($subject, $userSubstitutions); + $preparedBody = make_substitutions($body, $userSubstitutions); + + $mail = new CMailFile($preparedSubject, $recipient, $from, $preparedBody, array(), array(), array(), '', '', 0, 0, '', '', '', 'utf-8'); + $resultSend = $mail->sendfile(); + if ($resultSend) { + $emailsSent++; + dol_syslog($langs->trans('TimesheetWeekReminderSendSuccess', $recipient), LOG_INFO); + } else { + dol_syslog($langs->trans('TimesheetWeekReminderSendFailed', $recipient), LOG_ERR); + $errors++; + } + } + + $db->free($resql); + + if ($errors > 0) { + return -$errors; + } + + return $emailsSent; + } + + /** + * Send a reminder test email to the current user using the configured template. + * + * @param DoliDB $db Database handler + * @param User $user Current user + * @return int <0 if KO, >=0 if OK (number of emails sent) + */ + public static function sendTest($db, User $user) + { + return self::run($db, 1, 1, array((int) $user->id)); + } +} \ No newline at end of file diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index c11dd0c..7a81868 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -309,20 +309,20 @@ public function __construct($db) // unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week /* BEGIN MODULEBUILDER CRON */ $this->cronjobs = array( - // 0 => array( - // 'label' => 'MyJob label', - // 'jobtype' => 'method', - // 'class' => '/timesheetweek/class/timesheetweek.class.php', - // 'objectname' => 'TimesheetWeek', - // 'method' => 'doScheduledJob', - // 'parameters' => '', - // 'comment' => 'Comment', - // 'frequency' => 2, - // 'unitfrequency' => 3600, - // 'status' => 0, - // 'test' => 'isModEnabled("timesheetweek")', - // 'priority' => 50, - // ), + 0 => array( + 'label' => 'TimesheetWeekReminderCronLabel', + 'jobtype' => 'method', + 'class' => '/timesheetweek/class/timesheetweek_reminder.class.php', + 'objectname' => 'TimesheetweekReminder', + 'method' => 'run', + 'parameters' => '', + 'comment' => 'TimesheetWeekReminderCronComment', + 'frequency' => 1, + 'unitfrequency' => 86400, + 'status' => 0, + 'test' => 'isModEnabled("timesheetweek")', + 'priority' => 50, + ), ); /* END MODULEBUILDER CRON */ // Example: $this->cronjobs=array( @@ -867,20 +867,186 @@ public function init($options = '') $params = ActionsTimesheetweek::getMulticompanySharingDefinition(); } - if (!empty($params)) { - // EN: Merge TimesheetWeek definitions with any existing external module configuration. - // FR: Fusionner les définitions TimesheetWeek avec toute configuration de module externe existante. - $externalmodule = array_merge($externalmodule, $params); - - // EN: Persist the refreshed configuration in the Dolibarr constants table. - // FR: Persister la configuration actualisée dans la table des constantes de Dolibarr. - $jsonformat = json_encode($externalmodule); - dolibarr_set_const($this->db, 'MULTICOMPANY_EXTERNAL_MODULES_SHARING', $jsonformat, 'chaine', 0, '', $conf->entity); - } - - return $this->_init($sql, $options); + if (!empty($params)) { + // EN: Merge TimesheetWeek definitions with any existing external module configuration. + // FR: Fusionner les définitions TimesheetWeek avec toute configuration de module externe existante. + $externalmodule = array_merge($externalmodule, $params); + + // EN: Persist the refreshed configuration in the Dolibarr constants table. + // FR: Persister la configuration actualisée dans la table des constantes de Dolibarr. + $jsonformat = json_encode($externalmodule); + dolibarr_set_const($this->db, "MULTICOMPANY_EXTERNAL_MODULES_SHARING", $jsonformat, "chaine", 0, "", $conf->entity); + } + + $resultInit = $this->_init($sql, $options); + if ($resultInit <= 0) { + return $resultInit; + } + + $this->setupReminderEmailTemplate($conf, $langs); + + return $resultInit; + } + + /** + * Ensure the weekly reminder email template exists and set the default constant when missing. + * + * @param Conf $conf + * @param Translate $langs + * @return void + */ + protected function setupReminderEmailTemplate($conf, $langs) + { + global $user; + + $templateId = $this->findReminderTemplateId($conf); + if ($templateId <= 0) { + $templateId = $this->createReminderTemplate($conf, $langs, $user); + } + + if ($templateId > 0 && (int) getDolGlobalInt("TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE") === 0) { + dolibarr_set_const($this->db, "TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE", (int) $templateId, "chaine", 0, "", $conf->entity); + } } + + /** + * Search for the existing weekly reminder template. + * + * @param Conf $conf + * @return int + */ + protected function findReminderTemplateId($conf) + { + $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_email_templates WHERE code = 'TIMESHEETWEEK_REMINDER' AND module = 'timesheetweek' AND entity IN (0, ".((int) $conf->entity).") ORDER BY entity DESC"; + $resql = $this->db->query($sql); + if (!$resql) { + return 0; + } + + $templateId = 0; + if ($obj = $this->db->fetch_object($resql)) { + $templateId = (int) $obj->rowid; + } + + $this->db->free($resql); + + return $templateId; + } + + /** + * Create the default weekly reminder email template. + * + * @param Conf $conf + * @param mixed $langs + * @param User $user + * @return int + */ + protected function createReminderTemplate($conf, $langs, $user) + { + $templateClass = $this->resolveEmailTemplateClass(); + if (empty($templateClass)) { + return 0; + } + + dol_include_once("/core/class/CMailFile.class.php"); + $template = new $templateClass($this->db); + + if (property_exists($template, "entity")) { + $template->entity = 0; + } + if (property_exists($template, "module")) { + $template->module = "timesheetweek"; + } + if (property_exists($template, "type_template") && empty($template->type_template)) { + $template->type_template = "timesheetweek"; + } + if (property_exists($template, "code")) { + $template->code = "TIMESHEETWEEK_REMINDER"; + } + $template->label = $langs->transnoentities("TimesheetWeekReminderTemplateLabel"); + if (property_exists($template, "topic")) { + $template->topic = $langs->transnoentities("TimesheetWeekReminderTemplateSubject"); + } + if (property_exists($template, "subject")) { + $template->subject = $langs->transnoentities("TimesheetWeekReminderTemplateSubject"); + } + if (property_exists($template, "content")) { + $template->content = $langs->transnoentities("TimesheetWeekReminderTemplateBody"); + } + if (property_exists($template, "lang")) { + $template->lang = "fr_FR"; + } + if (property_exists($template, "private")) { + $template->private = 0; + } + if (property_exists($template, "fk_user")) { + $template->fk_user = (int) $user->id; + } + if (property_exists($template, "active")) { + $template->active = 1; + } + if (property_exists($template, "enabled")) { + $template->enabled = 1; + } + if (property_exists($template, "email_from")) { + $template->email_from = ""; + } + if (property_exists($template, "email_to")) { + $template->email_to = ""; + } + if (property_exists($template, "email_cc")) { + $template->email_cc = ""; + } + if (property_exists($template, "email_bcc")) { + $template->email_bcc = ""; + } + if (property_exists($template, "joinfiles")) { + $template->joinfiles = 0; + } + if (property_exists($template, "position")) { + $template->position = 0; + } + + if (method_exists($template, "create")) { + $res = $template->create($user); + if ($res > 0) { + if (!empty($template->id)) { + return (int) $template->id; + } + if (!empty($template->rowid)) { + return (int) $template->rowid; + } + return (int) $this->db->last_insert_id(MAIN_DB_PREFIX."c_email_templates"); + } + } + + return 0; + } + + /** + * Resolve the email template class available in the current Dolibarr version. + * + * @return string + */ + protected function resolveEmailTemplateClass() + { + $templateClass = ""; + if (is_readable(DOL_DOCUMENT_ROOT."/core/class/cemailtemplates.class.php")) { + dol_include_once("/core/class/cemailtemplates.class.php"); + } + if (is_readable(DOL_DOCUMENT_ROOT."/core/class/emailtemplates.class.php")) { + dol_include_once("/core/class/emailtemplates.class.php"); + } + if (class_exists("CEmailTemplates")) { + $templateClass = "CEmailTemplates"; + } elseif (class_exists("EmailTemplates")) { + $templateClass = "EmailTemplates"; + } + + return $templateClass; + } + /** * Function called when module is disabled. * Remove from database constants, boxes and permissions from Dolibarr database. diff --git a/langs/en_US/timesheetweek.lang b/langs/en_US/timesheetweek.lang index abe3a41..fb26c68 100644 --- a/langs/en_US/timesheetweek.lang +++ b/langs/en_US/timesheetweek.lang @@ -27,6 +27,29 @@ TimesheetWeekDailyRateOptions = Daily-rate options TimesheetWeekDailyRateOptionsHelp = Configure the helpers available for daily-rate contracts. TimesheetWeekQuarterDayForDailyContract = Quarter-day selector for daily-rate contracts TimesheetWeekQuarterDayForDailyContractHelp = Allow daily-rate employees to declare quarter days instead of half-days only. +TimesheetWeekReminderSectionTitle = Weekly email reminder +TimesheetWeekReminderSectionHelp = Configure the automatic reminder asking users to fill, validate or send their weekly timesheets. +TimesheetWeekReminderEnabled = Enable automatic reminder +TimesheetWeekReminderEnabledHelp = Turn the weekly reminder on or off. +TimesheetWeekReminderWeekday = Reminder day of week +TimesheetWeekReminderWeekdayHelp = Select which day of the week the reminder should be sent. +TimesheetWeekReminderHour = Reminder time (HH:MM) +TimesheetWeekReminderHourHelp = Time of day when the reminder should be sent. +TimesheetWeekReminderHourInvalid = Please enter a valid time formatted as HH:MM. +TimesheetWeekReminderWeekdayInvalid = Please choose a valid day of the week for the reminder. +TimesheetWeekReminderEmailTemplate = Email template for reminder +TimesheetWeekReminderEmailTemplateHelp = Choose the Dolibarr email template used to send the reminder. +TimesheetWeekReminderCronLabel = Weekly timesheet reminder +TimesheetWeekReminderCronComment = Send weekly reminder emails prompting users to complete their timesheets. +TimesheetWeekReminderTemplateMissing = Reminder email template is not configured. +TimesheetWeekReminderSendFailed = Failed to send the reminder email to %s. +TimesheetWeekReminderSendSuccess = Reminder email successfully sent to %s. +TimesheetWeekReminderSendTest = Send test email +TimesheetWeekReminderTestSuccess = Test reminder email sent (%s) +TimesheetWeekReminderTestError = Unable to send the test reminder email. +TimesheetWeekReminderTemplateLabel = Timesheetweek - Timesheet reminder +TimesheetWeekReminderTemplateSubject = Timesheet submission reminder +TimesheetWeekReminderTemplateBody = Hello __TSW_USER_FIRSTNAME__,\nPlease submit your weekly timesheet before Monday 8:00.\n__TSW_TIMESHEET_NEW_URL__\nRegards, __TSW_DOLIBARR_TITLE__ NewSection=New section TIMESHEETWEEK_MYPARAM1 = My param 1 TIMESHEETWEEK_MYPARAM1Tooltip = My param 1 tooltip diff --git a/langs/fr_FR/timesheetweek.lang b/langs/fr_FR/timesheetweek.lang index e0b0a9b..3c992fa 100644 --- a/langs/fr_FR/timesheetweek.lang +++ b/langs/fr_FR/timesheetweek.lang @@ -27,6 +27,29 @@ TimesheetWeekDailyRateOptions = Options forfait jour TimesheetWeekDailyRateOptionsHelp = Configure les assistants disponibles pour les contrats au forfait jour. TimesheetWeekQuarterDayForDailyContract = Sélecteur quart de jour pour forfait jour TimesheetWeekQuarterDayForDailyContractHelp = Autorise les salariés au forfait jour à déclarer des quarts de jour au lieu des seules demi-journées. +TimesheetWeekReminderSectionTitle = Rappel hebdomadaire par email +TimesheetWeekReminderSectionHelp = Configure le rappel automatique invitant les utilisateurs à saisir, valider ou envoyer leurs feuilles hebdomadaires. +TimesheetWeekReminderEnabled = Activer le rappel automatique +TimesheetWeekReminderEnabledHelp = Active ou désactive l'envoi hebdomadaire du rappel. +TimesheetWeekReminderWeekday = Jour d'envoi du rappel +TimesheetWeekReminderWeekdayHelp = Choisissez le jour de la semaine pour envoyer le rappel. +TimesheetWeekReminderHour = Heure d'envoi (HH:MM) +TimesheetWeekReminderHourHelp = Heure d'envoi du rappel, au format 24 h. +TimesheetWeekReminderHourInvalid = Merci de saisir une heure valide au format HH:MM. +TimesheetWeekReminderWeekdayInvalid = Merci de choisir un jour de semaine valide pour le rappel. +TimesheetWeekReminderEmailTemplate = Modèle d'email pour le rappel +TimesheetWeekReminderEmailTemplateHelp = Sélectionnez le modèle d'email Dolibarr utilisé pour envoyer le rappel. +TimesheetWeekReminderCronLabel = Rappel hebdomadaire des feuilles d'heures +TimesheetWeekReminderCronComment = Envoie un rappel hebdomadaire par email pour inviter les utilisateurs à compléter leurs feuilles d'heures. +TimesheetWeekReminderTemplateMissing = Le modèle d'email de rappel n'est pas configuré. +TimesheetWeekReminderSendFailed = Échec de l'envoi du rappel à %s. +TimesheetWeekReminderSendSuccess = Rappel envoyé avec succès à %s. +TimesheetWeekReminderSendTest = Envoyer un mail de test +TimesheetWeekReminderTestSuccess = Mail de test envoyé (%s) +TimesheetWeekReminderTestError = Échec de l'envoi du mail de test. +TimesheetWeekReminderTemplateLabel = Timesheetweek - Rappel des feuilles d'heures +TimesheetWeekReminderTemplateSubject = Rappel d'envoi des feuilles d'heures +TimesheetWeekReminderTemplateBody = Bonjour __TSW_USER_FIRSTNAME__,\nMerci de soumettre votre feuille d'heures de la semaine pour lundi 8h.\n__TSW_TIMESHEET_NEW_URL__\nBon weekend, __TSW_DOLIBARR_TITLE__ NewSection=Nouvelle section TIMESHEETWEEK_MYPARAM1 = Mon paramètre 1 TIMESHEETWEEK_MYPARAM1Tooltip = Info-bulle de mon paramètre 1 From 6cfed68cbf32af9fd6236694bfa94678b4b5ce24 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:35:51 +0100 Subject: [PATCH 02/96] Comment out NOREQUIREUSER and NOREQUIREMENU checks Commented out the NOREQUIREUSER and NOREQUIREMENU definitions. --- class/timesheetweek_reminder.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 763dea0..0fc06a7 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - +/* if (!defined('NOREQUIREUSER')) { define('NOREQUIREUSER', 1); } @@ -33,7 +33,7 @@ if (!defined('NOREQUIREMENU')) { define('NOREQUIREMENU', 1); } - +*/ require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; @@ -248,4 +248,4 @@ public static function sendTest($db, User $user) { return self::run($db, 1, 1, array((int) $user->id)); } -} \ No newline at end of file +} From 96854603ff673735c1a01119fd704a82b57a3bf5 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 10:37:43 +0100 Subject: [PATCH 03/96] Remove multi-entity management checks from SQL Removed conditional checks for multi-entity management in SQL queries. --- .../timesheetweek/mod_timesheetweek_standard.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/core/modules/timesheetweek/mod_timesheetweek_standard.php b/core/modules/timesheetweek/mod_timesheetweek_standard.php index fe79b79..04e9bfb 100644 --- a/core/modules/timesheetweek/mod_timesheetweek_standard.php +++ b/core/modules/timesheetweek/mod_timesheetweek_standard.php @@ -95,11 +95,6 @@ public function canBeActivated($object) $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql .= " FROM ".$db->prefix()."timesheetweek_timesheetweek"; $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - if ($object->ismultientitymanaged == 1) { - $sql .= " AND entity = ".$conf->entity; - } elseif (!is_numeric($object->ismultientitymanaged)) { // @phan-suppress-current-line PhanPluginEmptyStatementIf - // TODO - } $resql = $db->query($sql); if ($resql) { @@ -133,11 +128,6 @@ public function getNextValue($object) $sql = "SELECT MAX(CAST(SUBSTRING(ref FROM ".$posindice.") AS SIGNED)) as max"; $sql .= " FROM ".$db->prefix()."timesheetweek_timesheetweek"; $sql .= " WHERE ref LIKE '".$db->escape($this->prefix)."____-%'"; - if ($object->ismultientitymanaged == 1) { - $sql .= " AND entity = ".$conf->entity; - } elseif (!is_numeric($object->ismultientitymanaged)) { - // TODO - } $resql = $db->query($sql); if ($resql) { From f4efd58c735418c651c3f1905c0d6c33b48c82e7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:18:44 +0100 Subject: [PATCH 04/96] Improve reminder template compatibility --- class/timesheetweek_reminder.class.php | 6 +- core/modules/modTimesheetWeek.class.php | 109 ++++++++++++++---------- sql/update_all.sql | 4 +- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 0fc06a7..b0de9cb 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -39,7 +39,11 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -dol_include_once('/core/class/emailtemplates.class.php'); +if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php')) { + dol_include_once('/core/class/cemailtemplates.class.php'); +} elseif (is_readable(DOL_DOCUMENT_ROOT.'/core/class/emailtemplates.class.php')) { + dol_include_once('/core/class/emailtemplates.class.php'); +} dol_include_once('/timesheetweek/class/timesheetweek.class.php'); diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 7a81868..60b2ed6 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -915,24 +915,29 @@ protected function setupReminderEmailTemplate($conf, $langs) * @param Conf $conf * @return int */ - protected function findReminderTemplateId($conf) - { - $sql = "SELECT rowid FROM ".MAIN_DB_PREFIX."c_email_templates WHERE code = 'TIMESHEETWEEK_REMINDER' AND module = 'timesheetweek' AND entity IN (0, ".((int) $conf->entity).") ORDER BY entity DESC"; - $resql = $this->db->query($sql); - if (!$resql) { - return 0; - } - - $templateId = 0; - if ($obj = $this->db->fetch_object($resql)) { - $templateId = (int) $obj->rowid; + protected function findReminderTemplateId($conf) + { + $hasCodeColumn = $this->emailTemplateHasCodeColumn(); + $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX."c_email_templates WHERE module = 'timesheetweek' AND entity IN (0, ".((int) $conf->entity).')'; + if ($hasCodeColumn) { + $sql .= " AND code = 'TIMESHEETWEEK_REMINDER'"; + } + $sql .= ' ORDER BY entity DESC'; + $resql = $this->db->query($sql); + if (!$resql) { + return 0; + } + + $templateId = 0; + if ($obj = $this->db->fetch_object($resql)) { + $templateId = (int) $obj->rowid; + } + + $this->db->free($resql); + + return $templateId; } - - $this->db->free($resql); - - return $templateId; - } - + /** * Create the default weekly reminder email template. * @@ -954,17 +959,17 @@ protected function createReminderTemplate($conf, $langs, $user) if (property_exists($template, "entity")) { $template->entity = 0; } - if (property_exists($template, "module")) { - $template->module = "timesheetweek"; - } - if (property_exists($template, "type_template") && empty($template->type_template)) { - $template->type_template = "timesheetweek"; - } - if (property_exists($template, "code")) { - $template->code = "TIMESHEETWEEK_REMINDER"; - } + if (property_exists($template, "module")) { + $template->module = "timesheetweek"; + } + if (property_exists($template, "type_template") && empty($template->type_template)) { + $template->type_template = "timesheetweek"; + } + if ($this->emailTemplateHasCodeColumn() && property_exists($template, "code")) { + $template->code = "TIMESHEETWEEK_REMINDER"; + } - $template->label = $langs->transnoentities("TimesheetWeekReminderTemplateLabel"); + $template->label = $langs->transnoentities("TimesheetWeekReminderTemplateLabel"); if (property_exists($template, "topic")) { $template->topic = $langs->transnoentities("TimesheetWeekReminderTemplateSubject"); } @@ -1029,24 +1034,42 @@ protected function createReminderTemplate($conf, $langs, $user) * * @return string */ - protected function resolveEmailTemplateClass() - { - $templateClass = ""; - if (is_readable(DOL_DOCUMENT_ROOT."/core/class/cemailtemplates.class.php")) { - dol_include_once("/core/class/cemailtemplates.class.php"); - } - if (is_readable(DOL_DOCUMENT_ROOT."/core/class/emailtemplates.class.php")) { - dol_include_once("/core/class/emailtemplates.class.php"); + protected function resolveEmailTemplateClass() + { + $templateClass = ""; + if (is_readable(DOL_DOCUMENT_ROOT."/core/class/cemailtemplates.class.php")) { + dol_include_once("/core/class/cemailtemplates.class.php"); + } + if (is_readable(DOL_DOCUMENT_ROOT."/core/class/emailtemplates.class.php")) { + dol_include_once("/core/class/emailtemplates.class.php"); + } + if (class_exists("CEmailTemplates")) { + $templateClass = "CEmailTemplates"; + } elseif (class_exists("EmailTemplates")) { + $templateClass = "EmailTemplates"; + } + + return $templateClass; } - if (class_exists("CEmailTemplates")) { - $templateClass = "CEmailTemplates"; - } elseif (class_exists("EmailTemplates")) { - $templateClass = "EmailTemplates"; + + /** + * Determine if the email template table exposes the code column. + * + * @return bool + */ + protected function emailTemplateHasCodeColumn() + { + $sql = "SHOW COLUMNS FROM ".MAIN_DB_PREFIX."c_email_templates LIKE 'code'"; + $resql = $this->db->query($sql); + if ($resql) { + $hasColumn = ($this->db->num_rows($resql) > 0); + $this->db->free($resql); + return $hasColumn; + } + + return false; } - - return $templateClass; - } - + /** * Function called when module is disabled. * Remove from database constants, boxes and permissions from Dolibarr database. diff --git a/sql/update_all.sql b/sql/update_all.sql index 102cde8..96f6434 100644 --- a/sql/update_all.sql +++ b/sql/update_all.sql @@ -1,2 +1,2 @@ --- EN: Add the PDF model column to existing tables / FR: Ajoute la colonne de modèle PDF aux tables existantes. -ALTER TABLE llx_timesheet_week ADD COLUMN IF NOT EXISTS model_pdf VARCHAR(255) DEFAULT NULL AFTER status; +-- EN: Add the PDF model column to existing tables. +ALTER TABLE llx_timesheet_week ADD COLUMN model_pdf VARCHAR(255) DEFAULT NULL AFTER status; From 149e6005727672e4c37f5bb406e9ae1282ed2eb9 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 11:52:33 +0100 Subject: [PATCH 05/96] Insert reminder email template via install SQL --- sql/llx_timesheet_week.sql | 109 +++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index 9e47caf..964952e 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -40,6 +40,115 @@ CREATE TABLE IF NOT EXISTS llx_timesheet_week ( FOREIGN KEY (fk_user_valid) REFERENCES llx_user (rowid) ) ENGINE=innodb; + +-- EN: Insert default weekly reminder email template when code column exists +INSERT INTO llx_c_email_templates ( +entity, +private, +module, +type_template, +code, +label, +lang, +position, +active, +enabled, +joinfiles, +email_from, +email_to, +email_cc, +email_bcc, +topic, +subject, +content +) +SELECT +0, +0, +'timesheetweek', +'timesheetweek', +'TIMESHEETWEEK_REMINDER', +'Timesheetweek - Rappel des feuilles d''heures', +'fr_FR', +0, +1, +1, +0, +'', +'', +'', +'', +'Rappel d''envoi des feuilles d''heures', +'Rappel d''envoi des feuilles d''heures', +'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' +WHERE EXISTS ( +SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME = 'code' +) +AND NOT EXISTS ( +SELECT 1 +FROM llx_c_email_templates +WHERE module = 'timesheetweek' +AND entity IN (0, 1) +AND code = 'TIMESHEETWEEK_REMINDER' +); + +-- EN: Insert default weekly reminder email template when code column is missing +INSERT INTO llx_c_email_templates ( +entity, +private, +module, +type_template, +label, +lang, +position, +active, +enabled, +joinfiles, +email_from, +email_to, +email_cc, +email_bcc, +topic, +subject, +content +) +SELECT +0, +0, +'timesheetweek', +'timesheetweek', +'Timesheetweek - Rappel des feuilles d''heures', +'fr_FR', +0, +1, +1, +0, +'', +'', +'', +'', +'Rappel d''envoi des feuilles d''heures', +'Rappel d''envoi des feuilles d''heures', +'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' +WHERE NOT EXISTS ( +SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME = 'code' +) +AND NOT EXISTS ( +SELECT 1 +FROM llx_c_email_templates +WHERE module = 'timesheetweek' +AND entity IN (0, 1) +AND (type_template = 'timesheetweek' OR type_template IS NULL) +); + -- TimesheetWeek - lines CREATE TABLE IF NOT EXISTS llx_timesheet_week_line ( rowid INT AUTO_INCREMENT PRIMARY KEY, From 5e1faccb13ffdf4e4673fd7c6f32f18802e9ec4e Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:00:12 +0100 Subject: [PATCH 06/96] Handle email template columns across schemas --- sql/llx_timesheet_week.sql | 110 ++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 2 deletions(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index 964952e..ab06fdf 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -41,7 +41,7 @@ CREATE TABLE IF NOT EXISTS llx_timesheet_week ( ) ENGINE=innodb; --- EN: Insert default weekly reminder email template when code column exists +-- EN: Insert default weekly reminder email template when full email columns exist with code INSERT INTO llx_c_email_templates ( entity, private, @@ -86,17 +86,71 @@ SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME IN ('code', 'email_cc', 'email_bcc', 'email_from', 'email_to', 'joinfiles') +GROUP BY TABLE_NAME +HAVING COUNT(DISTINCT COLUMN_NAME) = 6 +) +AND NOT EXISTS ( +SELECT 1 +FROM llx_c_email_templates +WHERE module = 'timesheetweek' +AND entity IN (0, 1) +AND code = 'TIMESHEETWEEK_REMINDER' +); + +-- EN: Insert default weekly reminder email template when code exists but simplified email columns +INSERT INTO llx_c_email_templates ( +entity, +private, +module, +type_template, +code, +label, +lang, +position, +active, +enabled, +topic, +subject, +content +) +SELECT +0, +0, +'timesheetweek', +'timesheetweek', +'TIMESHEETWEEK_REMINDER', +'Timesheetweek - Rappel des feuilles d''heures', +'fr_FR', +0, +1, +1, +'Rappel d''envoi des feuilles d''heures', +'Rappel d''envoi des feuilles d''heures', +'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' +WHERE EXISTS ( +SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' AND COLUMN_NAME = 'code' ) AND NOT EXISTS ( SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME = 'email_cc' +) +AND NOT EXISTS ( +SELECT 1 FROM llx_c_email_templates WHERE module = 'timesheetweek' AND entity IN (0, 1) AND code = 'TIMESHEETWEEK_REMINDER' ); --- EN: Insert default weekly reminder email template when code column is missing +-- EN: Insert default weekly reminder email template when full email columns exist without code INSERT INTO llx_c_email_templates ( entity, private, @@ -141,6 +195,58 @@ WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'llx_c_email_templates' AND COLUMN_NAME = 'code' ) +AND EXISTS ( +SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME IN ('email_cc', 'email_bcc', 'email_from', 'email_to', 'joinfiles') +GROUP BY TABLE_NAME +HAVING COUNT(DISTINCT COLUMN_NAME) = 5 +) +AND NOT EXISTS ( +SELECT 1 +FROM llx_c_email_templates +WHERE module = 'timesheetweek' +AND entity IN (0, 1) +AND (type_template = 'timesheetweek' OR type_template IS NULL) +); + +-- EN: Insert default weekly reminder email template when code is missing and email columns are simplified +INSERT INTO llx_c_email_templates ( +entity, +private, +module, +type_template, +label, +lang, +position, +active, +enabled, +topic, +subject, +content +) +SELECT +0, +0, +'timesheetweek', +'timesheetweek', +'Timesheetweek - Rappel des feuilles d''heures', +'fr_FR', +0, +1, +1, +'Rappel d''envoi des feuilles d''heures', +'Rappel d''envoi des feuilles d''heures', +'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' +WHERE NOT EXISTS ( +SELECT 1 +FROM information_schema.COLUMNS +WHERE TABLE_SCHEMA = DATABASE() +AND TABLE_NAME = 'llx_c_email_templates' +AND COLUMN_NAME IN ('code', 'email_cc') +) AND NOT EXISTS ( SELECT 1 FROM llx_c_email_templates From f0f60810ed145b1e0dc3eeb87badb25c771b8a4a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:08:11 +0100 Subject: [PATCH 07/96] Remove comment from llx_timesheet_week.sql --- sql/llx_timesheet_week.sql | 2 -- 1 file changed, 2 deletions(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index ab06fdf..3a4f254 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -47,7 +47,6 @@ entity, private, module, type_template, -code, label, lang, position, @@ -68,7 +67,6 @@ SELECT 'timesheetweek', 'timesheetweek', 'TIMESHEETWEEK_REMINDER', -'Timesheetweek - Rappel des feuilles d''heures', 'fr_FR', 0, 1, From b1f05b18bcbc50dcb8f08c0963255eeba826136a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:09:29 +0100 Subject: [PATCH 08/96] Update llx_timesheet_week.sql --- sql/llx_timesheet_week.sql | 157 ------------------------------------- 1 file changed, 157 deletions(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index 3a4f254..b4522a5 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -96,163 +96,6 @@ AND entity IN (0, 1) AND code = 'TIMESHEETWEEK_REMINDER' ); --- EN: Insert default weekly reminder email template when code exists but simplified email columns -INSERT INTO llx_c_email_templates ( -entity, -private, -module, -type_template, -code, -label, -lang, -position, -active, -enabled, -topic, -subject, -content -) -SELECT -0, -0, -'timesheetweek', -'timesheetweek', -'TIMESHEETWEEK_REMINDER', -'Timesheetweek - Rappel des feuilles d''heures', -'fr_FR', -0, -1, -1, -'Rappel d''envoi des feuilles d''heures', -'Rappel d''envoi des feuilles d''heures', -'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' -WHERE EXISTS ( -SELECT 1 -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME = 'code' -) -AND NOT EXISTS ( -SELECT 1 -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME = 'email_cc' -) -AND NOT EXISTS ( -SELECT 1 -FROM llx_c_email_templates -WHERE module = 'timesheetweek' -AND entity IN (0, 1) -AND code = 'TIMESHEETWEEK_REMINDER' -); - --- EN: Insert default weekly reminder email template when full email columns exist without code -INSERT INTO llx_c_email_templates ( -entity, -private, -module, -type_template, -label, -lang, -position, -active, -enabled, -joinfiles, -email_from, -email_to, -email_cc, -email_bcc, -topic, -subject, -content -) -SELECT -0, -0, -'timesheetweek', -'timesheetweek', -'Timesheetweek - Rappel des feuilles d''heures', -'fr_FR', -0, -1, -1, -0, -'', -'', -'', -'', -'Rappel d''envoi des feuilles d''heures', -'Rappel d''envoi des feuilles d''heures', -'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' -WHERE NOT EXISTS ( -SELECT 1 -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME = 'code' -) -AND EXISTS ( -SELECT 1 -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME IN ('email_cc', 'email_bcc', 'email_from', 'email_to', 'joinfiles') -GROUP BY TABLE_NAME -HAVING COUNT(DISTINCT COLUMN_NAME) = 5 -) -AND NOT EXISTS ( -SELECT 1 -FROM llx_c_email_templates -WHERE module = 'timesheetweek' -AND entity IN (0, 1) -AND (type_template = 'timesheetweek' OR type_template IS NULL) -); - --- EN: Insert default weekly reminder email template when code is missing and email columns are simplified -INSERT INTO llx_c_email_templates ( -entity, -private, -module, -type_template, -label, -lang, -position, -active, -enabled, -topic, -subject, -content -) -SELECT -0, -0, -'timesheetweek', -'timesheetweek', -'Timesheetweek - Rappel des feuilles d''heures', -'fr_FR', -0, -1, -1, -'Rappel d''envoi des feuilles d''heures', -'Rappel d''envoi des feuilles d''heures', -'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' -WHERE NOT EXISTS ( -SELECT 1 -FROM information_schema.COLUMNS -WHERE TABLE_SCHEMA = DATABASE() -AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME IN ('code', 'email_cc') -) -AND NOT EXISTS ( -SELECT 1 -FROM llx_c_email_templates -WHERE module = 'timesheetweek' -AND entity IN (0, 1) -AND (type_template = 'timesheetweek' OR type_template IS NULL) -); - -- TimesheetWeek - lines CREATE TABLE IF NOT EXISTS llx_timesheet_week_line ( rowid INT AUTO_INCREMENT PRIMARY KEY, From 61984b39ff49043f2540f5135572d74e1436de16 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:13:06 +0100 Subject: [PATCH 09/96] Rename email_cc and email_bcc to email_tocc and email_tobcc --- sql/llx_timesheet_week.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index b4522a5..5ee6f5b 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -55,8 +55,8 @@ enabled, joinfiles, email_from, email_to, -email_cc, -email_bcc, +email_tocc, +email_tobcc, topic, subject, content From 116eabcb246cbd0ba84c9a3775b9f94e050a5f75 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:15:54 +0100 Subject: [PATCH 10/96] Remove duplicate subject field from SQL query --- sql/llx_timesheet_week.sql | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index 5ee6f5b..a46a821 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -58,7 +58,6 @@ email_to, email_tocc, email_tobcc, topic, -subject, content ) SELECT @@ -77,14 +76,13 @@ SELECT '', '', 'Rappel d''envoi des feuilles d''heures', -'Rappel d''envoi des feuilles d''heures', 'Bonjour __TSW_USER_FIRSTNAME__,\\nMerci de soumettre votre feuille d''heures de la semaine pour lundi 8h.\\n__TSW_TIMESHEET_NEW_URL__\\nBon weekend, __TSW_DOLIBARR_TITLE__' WHERE EXISTS ( SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'llx_c_email_templates' -AND COLUMN_NAME IN ('code', 'email_cc', 'email_bcc', 'email_from', 'email_to', 'joinfiles') +AND COLUMN_NAME IN ('email_tocc', 'email_tobcc', 'email_from', 'email_to', 'joinfiles') GROUP BY TABLE_NAME HAVING COUNT(DISTINCT COLUMN_NAME) = 6 ) From a206e5220c3fe4aa7b8b056973466810dc931e0f Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:17:55 +0100 Subject: [PATCH 11/96] Change condition from code to label in SQL query --- sql/llx_timesheet_week.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/llx_timesheet_week.sql b/sql/llx_timesheet_week.sql index a46a821..48fedc9 100644 --- a/sql/llx_timesheet_week.sql +++ b/sql/llx_timesheet_week.sql @@ -91,7 +91,7 @@ SELECT 1 FROM llx_c_email_templates WHERE module = 'timesheetweek' AND entity IN (0, 1) -AND code = 'TIMESHEETWEEK_REMINDER' +AND label = 'TIMESHEETWEEK_REMINDER' ); -- TimesheetWeek - lines From 221a93b5f622537c68d8d1b8b2622b1993e9d41f Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:10:56 +0100 Subject: [PATCH 12/96] =?UTF-8?q?S=C3=A9curiser=20les=20mises=20=C3=A0=20j?= =?UTF-8?q?our=20de=20sch=C3=A9ma=20timesheet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/modules/modTimesheetWeek.class.php | 88 +++++++++++++++++-------- sql/update_all.sql | 5 +- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 60b2ed6..0dc646d 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -777,37 +777,71 @@ public function init($options = '') $extrafields->fetch_name_optionals_label('user'); $dailyRateVisibility = '-1'; $dailyRateSharedEntity = '0'; - if (empty($extrafields->attributes['user']['label']['lmdb_daily_rate'])) { - // EN: Register the daily rate toggle on employees when the module is activated. - // FR: Enregistre l'option de forfait jour sur les salariés lors de l'activation du module. - $extrafields->addExtraField('lmdb_daily_rate', 'TimesheetWeekDailyRateLabel', 'boolean', 100, '', 'user', 0, 0, '', '', 0, '', $dailyRateVisibility, '', '', $dailyRateSharedEntity, 'timesheetweek@timesheetweek', 'isModEnabled("timesheetweek")', 0, 0); - } else { - // EN: Align the existing daily rate toggle with the latest visibility and sharing rules. - // FR: Aligne l'option de forfait jour existante avec les nouvelles règles de visibilité et de partage. - $extrafields->updateExtraField('lmdb_daily_rate', 'TimesheetWeekDailyRateLabel', 'boolean', 100, '', 'user', 0, 0, '', '', 0, '', $dailyRateVisibility, '', '', $dailyRateSharedEntity, 'timesheetweek@timesheetweek', 'isModEnabled("timesheetweek")', 0, 0); - } + if (empty($extrafields->attributes['user']['label']['lmdb_daily_rate'])) { + // EN: Register the daily rate toggle on employees when the module is activated. + // FR: Enregistre l'option de forfait jour sur les salariés lors de l'activation du module. + $extrafields->addExtraField('lmdb_daily_rate', 'TimesheetWeekDailyRateLabel', 'boolean', 100, '', 'user', 0, 0, '', '', 0, '', $dailyRateVisibility, '', '', $dailyRateSharedEntity, 'timesheetweek@timesheetweek', 'isModEnabled("timesheetweek")', 0, 0); + } else { + // EN: Avoid reapplying updates on the daily rate toggle to prevent redundant schema operations. + // FR: Éviter de réappliquer les mises à jour du forfait jour pour prévenir les opérations de schéma redondantes. + $currentVisibility = (string) ($extrafields->attributes['user']['visible']['lmdb_daily_rate'] ?? ''); + $currentSharedEntity = (string) ($extrafields->attributes['user']['shared']['lmdb_daily_rate'] ?? ''); + $currentType = (string) ($extrafields->attributes['user']['type']['lmdb_daily_rate'] ?? ''); + $requiresUpdate = ($currentType !== 'boolean' || $currentVisibility !== $dailyRateVisibility || $currentSharedEntity !== $dailyRateSharedEntity); + if ($requiresUpdate) { + // EN: Refresh the existing daily rate toggle only when its definition diverges from the expected one. + // FR: Rafraîchir l'option de forfait jour existante uniquement lorsque sa définition diverge de celle attendue. + $resultUpdateDailyRate = $extrafields->updateExtraField('lmdb_daily_rate', 'TimesheetWeekDailyRateLabel', 'boolean', 100, '', 'user', 0, 0, '', '', 0, '', $dailyRateVisibility, '', '', $dailyRateSharedEntity, 'timesheetweek@timesheetweek', 'isModEnabled("timesheetweek")', 0, 0); + if ($resultUpdateDailyRate < 0) { + $this->error = $extrafields->error; + return -1; + } + } + } - // EN: Ensure existing installations receive the daily_rate column for time entries. - // FR: Garantit que les installations existantes reçoivent la colonne daily_rate pour les lignes de temps. - $sqlCheckDailyRate = "SHOW COLUMNS FROM ".$this->db->prefix()."timesheet_week_line LIKE 'daily_rate'"; - $resqlCheckDailyRate = $this->db->query($sqlCheckDailyRate); - if (!$resqlCheckDailyRate) { - // EN: Abort activation when the structure verification query fails. - // FR: Interrompt l'activation si la requête de vérification de structure échoue. - $this->error = $this->db->lasterror(); - return -1; - } - $hasDailyRateColumn = (bool) $this->db->num_rows($resqlCheckDailyRate); - $this->db->free($resqlCheckDailyRate); - if (!$hasDailyRateColumn) { - $sqlAdd = "ALTER TABLE ".MAIN_DB_PREFIX."timesheet_week_line ADD COLUMN daily_rate INT NOT NULL DEFAULT 0"; - if (!$this->db->query($sqlAdd)) { - // EN: Stop activation when adding the column fails to keep database consistent. - // FR: Stoppe l'activation si l'ajout de la colonne échoue pour conserver une base cohérente. + // EN: Ensure existing installations receive the daily_rate column for time entries. + // FR: Garantit que les installations existantes reçoivent la colonne daily_rate pour les lignes de temps. + $sqlCheckDailyRate = "SHOW COLUMNS FROM ".$this->db->prefix()."timesheet_week_line LIKE 'daily_rate'"; + $resqlCheckDailyRate = $this->db->query($sqlCheckDailyRate); + if (!$resqlCheckDailyRate) { + // EN: Abort activation when the structure verification query fails. + // FR: Interrompt l'activation si la requête de vérification de structure échoue. $this->error = $this->db->lasterror(); return -1; } - } + $hasDailyRateColumn = (bool) $this->db->num_rows($resqlCheckDailyRate); + $this->db->free($resqlCheckDailyRate); + if (!$hasDailyRateColumn) { + $sqlAdd = "ALTER TABLE ".MAIN_DB_PREFIX."timesheet_week_line ADD COLUMN daily_rate INT NOT NULL DEFAULT 0"; + if (!$this->db->query($sqlAdd)) { + // EN: Stop activation when adding the column fails to keep database consistent. + // FR: Stoppe l'activation si l'ajout de la colonne échoue pour conserver une base cohérente. + $this->error = $this->db->lasterror(); + return -1; + } + } + + // EN: Ensure existing installations keep the PDF model column on weekly sheets. + // FR: Garantit que les installations existantes conservent la colonne du modèle PDF sur les feuilles hebdomadaires. + $sqlCheckModelPdf = "SHOW COLUMNS FROM ".$this->db->prefix()."timesheet_week LIKE 'model_pdf'"; + $resqlCheckModelPdf = $this->db->query($sqlCheckModelPdf); + if (!$resqlCheckModelPdf) { + // EN: Abort activation when the PDF model check fails. + // FR: Interrompre l'activation si la vérification du modèle PDF échoue. + $this->error = $this->db->lasterror(); + return -1; + } + $hasModelPdfColumn = (bool) $this->db->num_rows($resqlCheckModelPdf); + $this->db->free($resqlCheckModelPdf); + if (!$hasModelPdfColumn) { + $sqlAddModelPdf = "ALTER TABLE ".MAIN_DB_PREFIX."timesheet_week ADD COLUMN model_pdf VARCHAR(255) DEFAULT NULL AFTER status"; + if (!$this->db->query($sqlAddModelPdf)) { + // EN: Stop activation if adding the PDF model column fails to preserve schema consistency. + // FR: Stopper l'activation si l'ajout de la colonne de modèle PDF échoue pour préserver la cohérence du schéma. + $this->error = $this->db->lasterror(); + return -1; + } + } // Permissions $this->remove($options); diff --git a/sql/update_all.sql b/sql/update_all.sql index 96f6434..5bb856a 100644 --- a/sql/update_all.sql +++ b/sql/update_all.sql @@ -1,2 +1,3 @@ --- EN: Add the PDF model column to existing tables. -ALTER TABLE llx_timesheet_week ADD COLUMN model_pdf VARCHAR(255) DEFAULT NULL AFTER status; +-- EN: Add the PDF model column to existing tables when missing. +-- FR: Ajouter la colonne du modèle PDF aux tables existantes lorsqu'elle est absente. +ALTER TABLE llx_timesheet_week ADD COLUMN IF NOT EXISTS model_pdf VARCHAR(255) DEFAULT NULL AFTER status; From 3273dfcf0d3fb03113a5427052774fe3da130851 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Wed, 3 Dec 2025 16:34:38 +0100 Subject: [PATCH 13/96] Rendre l'upgrade model_pdf compatible MySQL --- sql/update_all.sql | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sql/update_all.sql b/sql/update_all.sql index 5bb856a..bf0d64e 100644 --- a/sql/update_all.sql +++ b/sql/update_all.sql @@ -1,3 +1,16 @@ -- EN: Add the PDF model column to existing tables when missing. --- FR: Ajouter la colonne du modèle PDF aux tables existantes lorsqu'elle est absente. -ALTER TABLE llx_timesheet_week ADD COLUMN IF NOT EXISTS model_pdf VARCHAR(255) DEFAULT NULL AFTER status; +SET @tsw_has_model_pdf := ( + SELECT COUNT(*) + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'llx_timesheet_week' + AND COLUMN_NAME = 'model_pdf' +); +SET @tsw_add_model_pdf := IF( + @tsw_has_model_pdf = 0, + 'ALTER TABLE llx_timesheet_week ADD COLUMN model_pdf VARCHAR(255) DEFAULT NULL AFTER status', + 'SELECT 1' +); +PREPARE tsw_stmt FROM @tsw_add_model_pdf; +EXECUTE tsw_stmt; +DEALLOCATE PREPARE tsw_stmt; From d45d6417b85d26e66e88f01e3862e61ac7416d3c Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 20:51:41 +0100 Subject: [PATCH 14/96] Remove weekly reminder email template functions Removed the email template management functions related to weekly reminders. --- core/modules/modTimesheetWeek.class.php | 182 ------------------------ 1 file changed, 182 deletions(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 0dc646d..4539fb6 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -921,188 +921,6 @@ public function init($options = '') return $resultInit; } - - /** - * Ensure the weekly reminder email template exists and set the default constant when missing. - * - * @param Conf $conf - * @param Translate $langs - * @return void - */ - protected function setupReminderEmailTemplate($conf, $langs) - { - global $user; - - $templateId = $this->findReminderTemplateId($conf); - if ($templateId <= 0) { - $templateId = $this->createReminderTemplate($conf, $langs, $user); - } - - if ($templateId > 0 && (int) getDolGlobalInt("TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE") === 0) { - dolibarr_set_const($this->db, "TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE", (int) $templateId, "chaine", 0, "", $conf->entity); - } - } - - /** - * Search for the existing weekly reminder template. - * - * @param Conf $conf - * @return int - */ - protected function findReminderTemplateId($conf) - { - $hasCodeColumn = $this->emailTemplateHasCodeColumn(); - $sql = 'SELECT rowid FROM ' . MAIN_DB_PREFIX."c_email_templates WHERE module = 'timesheetweek' AND entity IN (0, ".((int) $conf->entity).')'; - if ($hasCodeColumn) { - $sql .= " AND code = 'TIMESHEETWEEK_REMINDER'"; - } - $sql .= ' ORDER BY entity DESC'; - $resql = $this->db->query($sql); - if (!$resql) { - return 0; - } - - $templateId = 0; - if ($obj = $this->db->fetch_object($resql)) { - $templateId = (int) $obj->rowid; - } - - $this->db->free($resql); - - return $templateId; - } - - /** - * Create the default weekly reminder email template. - * - * @param Conf $conf - * @param mixed $langs - * @param User $user - * @return int - */ - protected function createReminderTemplate($conf, $langs, $user) - { - $templateClass = $this->resolveEmailTemplateClass(); - if (empty($templateClass)) { - return 0; - } - - dol_include_once("/core/class/CMailFile.class.php"); - $template = new $templateClass($this->db); - - if (property_exists($template, "entity")) { - $template->entity = 0; - } - if (property_exists($template, "module")) { - $template->module = "timesheetweek"; - } - if (property_exists($template, "type_template") && empty($template->type_template)) { - $template->type_template = "timesheetweek"; - } - if ($this->emailTemplateHasCodeColumn() && property_exists($template, "code")) { - $template->code = "TIMESHEETWEEK_REMINDER"; - } - - $template->label = $langs->transnoentities("TimesheetWeekReminderTemplateLabel"); - if (property_exists($template, "topic")) { - $template->topic = $langs->transnoentities("TimesheetWeekReminderTemplateSubject"); - } - if (property_exists($template, "subject")) { - $template->subject = $langs->transnoentities("TimesheetWeekReminderTemplateSubject"); - } - if (property_exists($template, "content")) { - $template->content = $langs->transnoentities("TimesheetWeekReminderTemplateBody"); - } - if (property_exists($template, "lang")) { - $template->lang = "fr_FR"; - } - if (property_exists($template, "private")) { - $template->private = 0; - } - if (property_exists($template, "fk_user")) { - $template->fk_user = (int) $user->id; - } - if (property_exists($template, "active")) { - $template->active = 1; - } - if (property_exists($template, "enabled")) { - $template->enabled = 1; - } - if (property_exists($template, "email_from")) { - $template->email_from = ""; - } - if (property_exists($template, "email_to")) { - $template->email_to = ""; - } - if (property_exists($template, "email_cc")) { - $template->email_cc = ""; - } - if (property_exists($template, "email_bcc")) { - $template->email_bcc = ""; - } - if (property_exists($template, "joinfiles")) { - $template->joinfiles = 0; - } - if (property_exists($template, "position")) { - $template->position = 0; - } - - if (method_exists($template, "create")) { - $res = $template->create($user); - if ($res > 0) { - if (!empty($template->id)) { - return (int) $template->id; - } - if (!empty($template->rowid)) { - return (int) $template->rowid; - } - return (int) $this->db->last_insert_id(MAIN_DB_PREFIX."c_email_templates"); - } - } - - return 0; - } - - /** - * Resolve the email template class available in the current Dolibarr version. - * - * @return string - */ - protected function resolveEmailTemplateClass() - { - $templateClass = ""; - if (is_readable(DOL_DOCUMENT_ROOT."/core/class/cemailtemplates.class.php")) { - dol_include_once("/core/class/cemailtemplates.class.php"); - } - if (is_readable(DOL_DOCUMENT_ROOT."/core/class/emailtemplates.class.php")) { - dol_include_once("/core/class/emailtemplates.class.php"); - } - if (class_exists("CEmailTemplates")) { - $templateClass = "CEmailTemplates"; - } elseif (class_exists("EmailTemplates")) { - $templateClass = "EmailTemplates"; - } - - return $templateClass; - } - - /** - * Determine if the email template table exposes the code column. - * - * @return bool - */ - protected function emailTemplateHasCodeColumn() - { - $sql = "SHOW COLUMNS FROM ".MAIN_DB_PREFIX."c_email_templates LIKE 'code'"; - $resql = $this->db->query($sql); - if ($resql) { - $hasColumn = ($this->db->num_rows($resql) > 0); - $this->db->free($resql); - return $hasColumn; - } - - return false; - } /** * Function called when module is disabled. From 2724a648687afe763622e29e08ebce05d1d8e90b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 20:56:42 +0100 Subject: [PATCH 15/96] Create data.sql --- sql/data.sql | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 sql/data.sql diff --git a/sql/data.sql b/sql/data.sql new file mode 100644 index 0000000..34a8ef0 --- /dev/null +++ b/sql/data.sql @@ -0,0 +1,7 @@ +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) + VALUES ( + 1,'timesheetweek','timesheetweek_reminder','fr_FR', 0,NULL, NOW(), + 'Rappel du vendredi soir', + 1,1,1, + "Rappel Feuilles d\'heures hebodmadaires", + "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From a60b2fb3a4e214edb14a1ac1a0e469be62fbead2 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:04:07 +0100 Subject: [PATCH 16/96] Update modTimesheetWeek.class.php --- core/modules/modTimesheetWeek.class.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 4539fb6..0417782 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -916,9 +916,7 @@ public function init($options = '') if ($resultInit <= 0) { return $resultInit; } - - $this->setupReminderEmailTemplate($conf, $langs); - + return $resultInit; } From d87ff5c9f8a887066082a85f0ebec504a8468e0a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:22:49 +0100 Subject: [PATCH 17/96] Update data.sql --- sql/data.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/data.sql b/sql/data.sql index 34a8ef0..b9132d0 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -1,7 +1,7 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) VALUES ( - 1,'timesheetweek','timesheetweek_reminder','fr_FR', 0,NULL, NOW(), + 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', - 1,1,1, + 100,'isModEnabled("timesheetweek")',0, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From de6bce30f3fd3d444895267eed17671fa8f961f7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:26:12 +0100 Subject: [PATCH 18/96] Update data.sql --- sql/data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index b9132d0..3de3c5e 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -2,6 +2,6 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u VALUES ( 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', - 100,'isModEnabled("timesheetweek")',0, + 100,"isModEnabled(\'timesheetweek\')",0, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 843a8c40646a10b8cc471d6ed84216c0902f72e8 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:30:00 +0100 Subject: [PATCH 19/96] Update data.sql --- sql/data.sql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index 3de3c5e..75837ea 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -2,6 +2,8 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u VALUES ( 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', - 100,"isModEnabled(\'timesheetweek\')",0, + 100, + "isModEnabled(\'timesheetweek\')", + 0, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 95ec4f23a2de461979b7fec0de5b6796b58fe96d Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:32:05 +0100 Subject: [PATCH 20/96] Update data.sql --- sql/data.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/data.sql b/sql/data.sql index 75837ea..628337e 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -1,9 +1,9 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) VALUES ( - 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), + 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, - "isModEnabled(\'timesheetweek\')", + 'isModEnabled("supplier_invoice")', 0, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 18f0da743943faa2bf526c802c01e3ed2c95003f Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:33:22 +0100 Subject: [PATCH 21/96] Update data.sql --- sql/data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index 628337e..b525432 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -3,7 +3,7 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, - 'isModEnabled("supplier_invoice")', + 1, 0, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 1df17ecee2af2dc118d7eec6d371d14fd75ba08c Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:33:49 +0100 Subject: [PATCH 22/96] Update data.sql --- sql/data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index b525432..57a21ac 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -4,6 +4,6 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u 'Rappel du vendredi soir', 100, 1, - 0, + NULL, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From ea36dcb5a1de47d4e605feba15439ff972546a02 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:34:50 +0100 Subject: [PATCH 23/96] Update data.sql --- sql/data.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/data.sql b/sql/data.sql index 57a21ac..eeca015 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -1,9 +1,9 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) VALUES ( - 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), + 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, - 1, + 'isModEnabled("timesheetweek")', NULL, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 4642391d2b82e97db1746d3bb558ee6a08ef4652 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:37:08 +0100 Subject: [PATCH 24/96] Update data.sql --- sql/data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index eeca015..0b02ded 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -1,6 +1,6 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) VALUES ( - 0,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), + 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, 'isModEnabled("timesheetweek")', From 1cd66bf0e0a0de398b4313fab09ec97317c5894f Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:38:48 +0100 Subject: [PATCH 25/96] Update data.sql --- sql/data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index 0b02ded..97908a2 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -3,7 +3,7 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, - 'isModEnabled("timesheetweek")', + 'isModEnabled(\"timesheetweek\")', NULL, "Rappel Feuilles d\'heures hebodmadaires", "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); From 92d64d7d56510e3bed0570472e35e2ea8669a68a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:41:59 +0100 Subject: [PATCH 26/96] Update data.sql --- sql/data.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index 97908a2..8d51ab8 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -1,8 +1,9 @@ -INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,joinfiles,topic,content) +INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_user,datec,label,position,active,enabled,joinfiles,topic,content) VALUES ( 1,'timesheetweek','actioncomm_send','fr_FR', 0,NULL, NOW(), 'Rappel du vendredi soir', 100, + 1, 'isModEnabled(\"timesheetweek\")', NULL, "Rappel Feuilles d\'heures hebodmadaires", From 6068ad566679bf7eaa5aa37c238bb10fbdd35e69 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:55:01 +0100 Subject: [PATCH 27/96] Update setup.php --- admin/setup.php | 60 +++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 7d19608..d2db6ff 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -63,10 +63,33 @@ $scanDir = GETPOST('scan_dir', 'alpha'); $reminderAction = GETPOST('reminder_action', 'aZ09'); -if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php')) { - dol_include_once('/core/class/cemailtemplates.class.php'); -} elseif (is_readable(DOL_DOCUMENT_ROOT.'/core/class/emailtemplates.class.php')) { - dol_include_once('/core/class/emailtemplates.class.php'); +dol_include_once('/core/class/cemailtemplates.class.php'); + +if (!class_exists('FormSetup')) { + // For retrocompatibility Dolibarr < 16.0 + if (floatval(DOL_VERSION) < 16.0 && !class_exists('FormSetup')) { + require_once __DIR__.'/../backport/v16/core/class/html.formsetup.class.php'; + } else { + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; + } +} + +$formSetup = new FormSetup($db); +$form = new Form($db); + +$sql = "SELECT rowid, label "; +$sql.= "FROM ".MAIN_DB_PREFIX."c_email_templates "; +$sql.= "WHERE enabled='1' "; +$sql.= "AND active='1' "; +$sql.= "AND type_template = 'actioncomm_send' "; +$sql.= "AND entity='".getEntity('timesheetweek')."' "; +//$sql.= "GROUP BY label"; +$result = $db->query($sql); +$options = array(); +if ($result) { + while ($obj = $db->fetch_object($result)) { + $options[$obj->label] = $obj->label; + } } // EN: Helper to enable a PDF model in the database. @@ -594,37 +617,10 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print ''; -$templateOptions = array(0 => $langs->trans('None')); -foreach ($emailTemplates as $templateItem) { - $templateId = 0; - if (!empty($templateItem->id)) { - $templateId = (int) $templateItem->id; - } elseif (!empty($templateItem->rowid)) { - $templateId = (int) $templateItem->rowid; - } - - if (empty($templateId)) { - continue; - } - - $templateLabel = ''; - if (!empty($templateItem->label)) { - $templateLabel = $templateItem->label; - } elseif (!empty($templateItem->ref)) { - $templateLabel = $templateItem->ref; - } elseif (!empty($templateItem->topic)) { - $templateLabel = $templateItem->topic; - } else { - $templateLabel = '#'.$templateId; - } - - $templateOptions[$templateId] = $templateLabel; -} - print ''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplate').''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''; -print ''.$form->selectarray('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $templateOptions, $reminderTemplateId, 0, 0, 0, '', 0, 0, 0, '', '', 1).''; +print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; print ''; print ''; From ef46fcda476b73fcdc0de42c62d41dae458b1dbe Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:59:30 +0100 Subject: [PATCH 28/96] Update setup.php --- admin/setup.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index d2db6ff..8bdd76e 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -592,6 +592,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''.$langs->trans('TimesheetWeekReminderEnabledHelp').''; print ''; print ''; +$formSetup->newItem('STANCER_AUTO_MAIL_NOTIFICATIONS_PAYMENT_DETAILS')->setAsYesNo(); print ''; print ''; @@ -620,7 +621,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplate').''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''; -print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; +$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options);//print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; print ''; print ''; From 7a56c5f1f4420c407d83c5495f73115b49b1646e Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:03:07 +0100 Subject: [PATCH 29/96] Update setup.php --- admin/setup.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/admin/setup.php b/admin/setup.php index 8bdd76e..1b5c9e1 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -623,6 +623,14 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''; $formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options);//print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; print ''; +if ($action == 'edit') { + print $formSetup->generateOutput(true); +} else { + print $formSetup->generateOutput(); + print '
'; + print ''.$langs->trans("Modify").''; + print '
'; +} print ''; print '
'; From fa29c460d0e9e9d2169b66d9fd00ab1b35749200 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:21:24 +0100 Subject: [PATCH 30/96] Update setup.php --- admin/setup.php | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 1b5c9e1..8c096ac 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -592,7 +592,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''.$langs->trans('TimesheetWeekReminderEnabledHelp').''; print ''; print ''; -$formSetup->newItem('STANCER_AUTO_MAIL_NOTIFICATIONS_PAYMENT_DETAILS')->setAsYesNo(); print ''; print ''; @@ -621,24 +620,16 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplate').''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''; -$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options);//print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; +print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; print ''; -if ($action == 'edit') { - print $formSetup->generateOutput(true); -} else { - print $formSetup->generateOutput(); - print '
'; - print ''.$langs->trans("Modify").''; - print '
'; -} print ''; print '
'; print '
'; -print ''; +print '';//''.$langs->trans('Save').''; print ' '; -print ''; +print ''.$langs->trans('TimesheetWeekReminderSendTest').''; print '
'; print ''; From 0722eb7d8545a1fc42401826104f28e8440101e6 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:29:48 +0100 Subject: [PATCH 31/96] Update setup.php --- admin/setup.php | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 8c096ac..d3315d3 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -65,22 +65,12 @@ dol_include_once('/core/class/cemailtemplates.class.php'); -if (!class_exists('FormSetup')) { - // For retrocompatibility Dolibarr < 16.0 - if (floatval(DOL_VERSION) < 16.0 && !class_exists('FormSetup')) { - require_once __DIR__.'/../backport/v16/core/class/html.formsetup.class.php'; - } else { - require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php'; - } -} - -$formSetup = new FormSetup($db); $form = new Form($db); $sql = "SELECT rowid, label "; $sql.= "FROM ".MAIN_DB_PREFIX."c_email_templates "; -$sql.= "WHERE enabled='1' "; -$sql.= "AND active='1' "; +$sql.= "WHERE active='1' "; +//$sql.= "AND enabled='1' "; $sql.= "AND type_template = 'actioncomm_send' "; $sql.= "AND entity='".getEntity('timesheetweek')."' "; //$sql.= "GROUP BY label"; @@ -90,6 +80,7 @@ while ($obj = $db->fetch_object($result)) { $options[$obj->label] = $obj->label; } + var_dump($result); } // EN: Helper to enable a PDF model in the database. @@ -620,7 +611,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplate').''; print ''.$langs->trans('TimesheetWeekReminderEmailTemplateHelp').''; -print ''.$formSetup->newItem('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE')->setAsSelect($options).''; +print ''.$form->selectarray('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $templateOptions, $reminderTemplateId, 0, 0, 0, '', 0, 0, 0, '', '', 1).''; print ''; print ''; From ccc5ff64e78389aa7bf8a8a0e1d7579de3c487af Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:33:12 +0100 Subject: [PATCH 32/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index d3315d3..b6a6bca 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -72,7 +72,7 @@ $sql.= "WHERE active='1' "; //$sql.= "AND enabled='1' "; $sql.= "AND type_template = 'actioncomm_send' "; -$sql.= "AND entity='".getEntity('timesheetweek')."' "; +//$sql.= "AND entity='".getEntity('timesheetweek')."' "; //$sql.= "GROUP BY label"; $result = $db->query($sql); $options = array(); From d7c01b8d1fb9a5bfea97c6bb27c43ceef51bc607 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:36:01 +0100 Subject: [PATCH 33/96] Update setup.php --- admin/setup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index b6a6bca..4dbef82 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -75,10 +75,10 @@ //$sql.= "AND entity='".getEntity('timesheetweek')."' "; //$sql.= "GROUP BY label"; $result = $db->query($sql); -$options = array(); +$templateOptions = array(); if ($result) { while ($obj = $db->fetch_object($result)) { - $options[$obj->label] = $obj->label; + $templateOptions[$obj->label] = $obj->label; } var_dump($result); } From 8a66b6d88acfdfd67e3a3d6227a2c88d5ab971a9 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:41:02 +0100 Subject: [PATCH 34/96] Update setup.php --- admin/setup.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/setup.php b/admin/setup.php index 4dbef82..50dfbf8 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -618,6 +618,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print '
'; +print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=ask_validate&token='.$token); print '';//''.$langs->trans('Save').''; print ' '; print ''.$langs->trans('TimesheetWeekReminderSendTest').''; From f6cc4ec1209b96704a7185bb5661a9cdab2f9c04 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:45:26 +0100 Subject: [PATCH 35/96] Update setup.php --- admin/setup.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 50dfbf8..20d5796 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -359,7 +359,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } } -if ($reminderAction === 'savereminder') { +if ($action === 'savereminder') { $reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); $reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); $reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); @@ -400,7 +400,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } } - if ($reminderAction === 'testreminder') { + if ($action === 'testreminder') { $resultTest = TimesheetweekReminder::sendTest($db, $user); if ($resultTest > 0) { setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); @@ -618,10 +618,11 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print '
'; print '
'; -print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=ask_validate&token='.$token); -print '';//''.$langs->trans('Save').''; +print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=savereminder&token='.$token); +//print '';//''.$langs->trans('Save').''; print ' '; -print ''.$langs->trans('TimesheetWeekReminderSendTest').''; +print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=testreminder&token='.$token); +//print ''.$langs->trans('TimesheetWeekReminderSendTest').''; print '
'; print ''; From a67d553d81dcbd50c227ad2060716dd687082284 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:47:15 +0100 Subject: [PATCH 36/96] Update setup.php --- admin/setup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 20d5796..a517f40 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -618,10 +618,10 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print '
'; -print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=savereminder&token='.$token); +print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=savereminder&token='.$pageToken); //print '';//''.$langs->trans('Save').''; print ' '; -print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=testreminder&token='.$token); +print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=testreminder&token='.$pageToken); //print ''.$langs->trans('TimesheetWeekReminderSendTest').''; print '
'; print ''; From cf2f49ed2b084402754cde93297869be4700497a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:50:07 +0100 Subject: [PATCH 37/96] Update setup.php --- admin/setup.php | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index a517f40..abad7df 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -80,7 +80,6 @@ while ($obj = $db->fetch_object($result)) { $templateOptions[$obj->label] = $obj->label; } - var_dump($result); } // EN: Helper to enable a PDF model in the database. From 986b05896cca4a1ee8fa034c2522c0e4bc509f5b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:51:20 +0100 Subject: [PATCH 38/96] Update setup.php --- admin/setup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index abad7df..f89690b 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -395,8 +395,8 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a setEventMessages($langs->trans('Error'), null, 'errors'); } else { setEventMessages($langs->trans('SetupSaved'), null, 'mesgs'); -} -} + } + } } if ($action === 'testreminder') { From 0cdf9d50a167fd82042b92aef94a40bf816e40ea Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:53:27 +0100 Subject: [PATCH 39/96] Update setup.php --- admin/setup.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index f89690b..c9d7f4a 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -359,9 +359,9 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } if ($action === 'savereminder') { -$reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); -$reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); -$reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); + $reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); + $reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); + $reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); $reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); $error = 0; @@ -617,10 +617,10 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print '
'; -print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=savereminder&token='.$pageToken); +print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?action=savereminder&token='.$pageToken); //print '';//''.$langs->trans('Save').''; print ' '; -print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=testreminder&token='.$pageToken); +print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?action=testreminder&token='.$pageToken); //print ''.$langs->trans('TimesheetWeekReminderSendTest').''; print '
'; print ''; From f9141c2e545a7329caaaa44d5994b484d14f3237 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 22:58:21 +0100 Subject: [PATCH 40/96] Update setup.php --- admin/setup.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index c9d7f4a..981ed28 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -359,10 +359,10 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } if ($action === 'savereminder') { - $reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); - $reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); - $reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); - $reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); + $reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); var_dump($reminderEnabledValue); + $reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); var_dump($reminderWeekdayValue); + $reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); var_dump($reminderHourValue); + $reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); var_dump($reminderTemplateValue); $error = 0; From ba1017db75f4e733d7145a7eaf835c77ad75b7bc Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:07:24 +0100 Subject: [PATCH 41/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index 981ed28..7ea736e 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -290,7 +290,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } } -if (in_array($reminderAction, array('savereminder', 'testreminder'), true)) { +if (in_array($action, array('savereminder', 'testreminder'), true)) { if (function_exists('dol_verify_token')) { if (empty($token) || dol_verify_token($token) <= 0) { accessforbidden(); From 49c8fe5a65e78901dd1d83959472583377325ec2 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:12:03 +0100 Subject: [PATCH 42/96] Update setup.php --- admin/setup.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 7ea736e..0ca3c83 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -282,7 +282,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Verify CSRF token when the request changes the configuration. -if (in_array($action, array('setmodule', 'setdoc', 'setdocmodel', 'delmodel', 'setquarterday'), true)) { +if (in_array($action, array('setmodule', 'setdoc', 'setdocmodel', 'delmodel', 'setquarterday','savereminder', 'testreminder'), true)) { if (function_exists('dol_verify_token')) { if (empty($token) || dol_verify_token($token) <= 0) { accessforbidden(); @@ -290,14 +290,6 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } } -if (in_array($action, array('savereminder', 'testreminder'), true)) { - if (function_exists('dol_verify_token')) { - if (empty($token) || dol_verify_token($token) <= 0) { - accessforbidden(); - } - } -} - // EN: Persist the chosen numbering module. if ($action === 'setmodule' && !empty($value)) { $result = dolibarr_set_const($db, 'TIMESHEETWEEK_ADDON', $value, 'chaine', 0, '', $conf->entity); From 077bafc18c7913f6fa706d49bf120339d0cc9183 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:15:36 +0100 Subject: [PATCH 43/96] Update setup.php --- admin/setup.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 0ca3c83..354e2f5 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -61,7 +61,6 @@ // EN: Capture additional parameters used to reproduce Dolibarr's document model toggles. $docLabel = GETPOST('label', 'alphanohtml'); $scanDir = GETPOST('scan_dir', 'alpha'); -$reminderAction = GETPOST('reminder_action', 'aZ09'); dol_include_once('/core/class/cemailtemplates.class.php'); @@ -282,7 +281,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } // EN: Verify CSRF token when the request changes the configuration. -if (in_array($action, array('setmodule', 'setdoc', 'setdocmodel', 'delmodel', 'setquarterday','savereminder', 'testreminder'), true)) { +if (in_array($action, array('setmodule', 'setdoc', 'setdocmodel', 'delmodel', 'setquarterday', 'savereminder', 'testreminder'), true)) { if (function_exists('dol_verify_token')) { if (empty($token) || dol_verify_token($token) <= 0) { accessforbidden(); From 7e1e4a2ae401c12b7c98d846b0837754b2705f3b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:44:18 +0100 Subject: [PATCH 44/96] Fix reminder form submission --- admin/setup.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 354e2f5..9362a0a 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -350,10 +350,10 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } if ($action === 'savereminder') { - $reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); var_dump($reminderEnabledValue); - $reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); var_dump($reminderWeekdayValue); - $reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); var_dump($reminderHourValue); - $reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); var_dump($reminderTemplateValue); +$reminderEnabledValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_ENABLED', 'int'); +$reminderWeekdayValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_WEEKDAY', 'int'); +$reminderHourValue = trim(GETPOST('TIMESHEETWEEK_REMINDER_HOUR', 'alphanohtml')); +$reminderTemplateValue = (int) GETPOST('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 'int'); $error = 0; @@ -608,11 +608,9 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print '
'; -print dolGetButtonAction('', ($langs->trans("Save")!='Save'?$langs->trans("Save"):'Enregistrer'), 'default', $_SERVER["PHP_SELF"].'?action=savereminder&token='.$pageToken); -//print '';//''.$langs->trans('Save').''; +print ''; print ' '; -print dolGetButtonAction('', ($langs->trans("TimesheetWeekReminderSendTest")!='Send a test e-mail'?$langs->trans("TimesheetWeekReminderSendTest"):'Envoyer un mail de test'), 'default', $_SERVER["PHP_SELF"].'?action=testreminder&token='.$pageToken); -//print ''.$langs->trans('TimesheetWeekReminderSendTest').''; +print ''; print '
'; print ''; From 9a5a0349e497a1e51f85f04c7e3f6b9f9b4291b3 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:50:32 +0100 Subject: [PATCH 45/96] Update setup.php --- admin/setup.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 9362a0a..30ffc6c 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -40,6 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php'; // EN: Load document helper functions required for model toggles. require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; dol_include_once('/timesheetweek/lib/timesheetweek.lib.php'); @@ -62,8 +63,6 @@ $docLabel = GETPOST('label', 'alphanohtml'); $scanDir = GETPOST('scan_dir', 'alpha'); -dol_include_once('/core/class/cemailtemplates.class.php'); - $form = new Form($db); $sql = "SELECT rowid, label "; From 1c02ecbfec863161b4ee26b6cb3e935d9ede7d7d Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:52:01 +0100 Subject: [PATCH 46/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index 30ffc6c..acef28d 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -40,7 +40,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/lib/pdf.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/cemailtemplate.class.php'; // EN: Load document helper functions required for model toggles. require_once DOL_DOCUMENT_ROOT.'/core/lib/doc.lib.php'; dol_include_once('/timesheetweek/lib/timesheetweek.lib.php'); From 5c32147cf9004217306336302e987c596e5fc5a2 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Thu, 4 Dec 2025 23:54:12 +0100 Subject: [PATCH 47/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index acef28d..e4b1ce3 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -76,7 +76,7 @@ $templateOptions = array(); if ($result) { while ($obj = $db->fetch_object($result)) { - $templateOptions[$obj->label] = $obj->label; + $templateOptions[(int) $obj->rowid] = $obj->label; } } From 624b5cd1afa4bcf7aca42a5331c1764c839493f7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:03:29 +0100 Subject: [PATCH 48/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index b0de9cb..d08d22f 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -39,11 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplates.class.php')) { - dol_include_once('/core/class/cemailtemplates.class.php'); -} elseif (is_readable(DOL_DOCUMENT_ROOT.'/core/class/emailtemplates.class.php')) { - dol_include_once('/core/class/emailtemplates.class.php'); -} +dol_include_once('/core/class/cemailtemplate.class.php'); dol_include_once('/timesheetweek/class/timesheetweek.class.php'); From ae298ff9a3226490a5f104f07f18fe394b7130b9 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:05:20 +0100 Subject: [PATCH 49/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index d08d22f..40ae472 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -39,7 +39,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -dol_include_once('/core/class/cemailtemplate.class.php'); +require_once DOL_DOCUMENT_ROOT.'/core/class/cemailtemplate.class.php'; dol_include_once('/timesheetweek/class/timesheetweek.class.php'); From 7128da62f13192e83ed93019b745c730d11982ec Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:07:52 +0100 Subject: [PATCH 50/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 40ae472..713525e 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -120,10 +120,8 @@ public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds } $emailTemplateClass = ''; - if (class_exists('CEmailTemplates')) { - $emailTemplateClass = 'CEmailTemplates'; - } elseif (class_exists('EmailTemplates')) { - $emailTemplateClass = 'EmailTemplates'; + if (class_exists('CEmailTemplate')) { + $emailTemplateClass = 'CEmailTemplate'; } if (empty($emailTemplateClass)) { From 65e3c4c4ebd968ef974fa2a3b091bcaa6cbf97b3 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:13:10 +0100 Subject: [PATCH 51/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 713525e..9b89638 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -89,6 +89,7 @@ public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds } $templateIdConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $conf->entity); + var_dump($templateIdConst); $templateId = !empty($templateIdConst) ? (int) $templateIdConst : 0; if (empty($templateId)) { dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); From 777f098195ce32284fc02b2f8cc984a9a6060221 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:28:46 +0100 Subject: [PATCH 52/96] Use CEmailTemplate apifetch for reminders --- class/timesheetweek_reminder.class.php | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 9b89638..c777bf9 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -89,7 +89,6 @@ public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds } $templateIdConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $conf->entity); - var_dump($templateIdConst); $templateId = !empty($templateIdConst) ? (int) $templateIdConst : 0; if (empty($templateId)) { dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); @@ -119,19 +118,26 @@ public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds return 0; } } - - $emailTemplateClass = ''; + + $emailTemplate = null; + $templateFetch = 0; if (class_exists('CEmailTemplate')) { - $emailTemplateClass = 'CEmailTemplate'; + $emailTemplate = new CEmailTemplate($db); + if (method_exists($emailTemplate, 'apifetch')) { + $templateFetch = $emailTemplate->apifetch($templateId); + } else { + $templateFetch = $emailTemplate->fetch($templateId); + } + } elseif (class_exists('EmailTemplate')) { + $emailTemplate = new EmailTemplate($db); + $templateFetch = $emailTemplate->fetch($templateId); } - if (empty($emailTemplateClass)) { + if (empty($emailTemplate)) { dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_ERR); return -1; } - $emailTemplate = new $emailTemplateClass($db); - $templateFetch = $emailTemplate->fetch($templateId); if ($templateFetch <= 0) { dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); return 0; From 5f6461448b3b91a4c2a40a45c8611272598b0f0b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:38:39 +0100 Subject: [PATCH 53/96] Handle cron reminder without explicit db argument --- class/timesheetweek_reminder.class.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index c777bf9..ca3b1c3 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -59,10 +59,20 @@ class TimesheetweekReminder * @param array $targetUserIds Limit execution to specific user ids when provided * @return int <0 if KO, >=0 if OK (number of emails sent) */ - public static function run($db, $limit = 0, $forcerun = 0, array $targetUserIds = array()) + public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { global $conf, $langs; + $db = $dbInstance; + if (empty($db) && !empty($GLOBALS['db'])) { + $db = $GLOBALS['db']; + } + + if (empty($db)) { + dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); + return -1; + } + $langs->loadLangs(array('timesheetweek@timesheetweek')); dol_syslog(__METHOD__, LOG_DEBUG); From b8d064059061eff22cf78453c6262c5e3e1f53f7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:51:34 +0100 Subject: [PATCH 54/96] Fix reminder globals and cron activation --- class/timesheetweek_reminder.class.php | 20 ++-- core/modules/modTimesheetWeek.class.php | 144 +++++++++++++----------- 2 files changed, 88 insertions(+), 76 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index ca3b1c3..efd6b66 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -44,14 +44,12 @@ dol_include_once('/timesheetweek/class/timesheetweek.class.php'); /** - * EN: Cron helper used to send weekly reminders. - * FR: Assistant cron utilisé pour envoyer les rappels hebdomadaires. + * Cron helper used to send weekly reminders. */ class TimesheetweekReminder { - /** - * EN: Run cron job to send weekly reminder emails. - * FR: Exécuter la tâche planifiée pour envoyer les rappels hebdomadaires par email. +/** + * Run cron job to send weekly reminder emails. * * @param DoliDB $db Database handler * @param int $limit Optional limit for recipients @@ -77,29 +75,25 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array dol_syslog(__METHOD__, LOG_DEBUG); - $reminderEnabledConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_ENABLED', $conf->entity); - $reminderEnabled = !empty($reminderEnabledConst) ? (int) $reminderEnabledConst : 0; + $reminderEnabled = getDolGlobalInt('TIMESHEETWEEK_REMINDER_ENABLED', 0, $conf->entity); if (empty($reminderEnabled) && empty($forcerun)) { dol_syslog('TimesheetweekReminder: reminder disabled', LOG_INFO); return 0; } - $reminderWeekdayConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_WEEKDAY', $conf->entity); - $reminderWeekday = !empty($reminderWeekdayConst) ? (int) $reminderWeekdayConst : 1; + $reminderWeekday = getDolGlobalInt('TIMESHEETWEEK_REMINDER_WEEKDAY', 1, $conf->entity); if ($reminderWeekday < 1 || $reminderWeekday > 7) { dol_syslog($langs->trans('TimesheetWeekReminderWeekdayInvalid'), LOG_ERR); return -1; } - $reminderHourConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_HOUR', $conf->entity); - $reminderHour = !empty($reminderHourConst) ? $reminderHourConst : '18:00'; + $reminderHour = getDolGlobalString('TIMESHEETWEEK_REMINDER_HOUR', '18:00', $conf->entity); if (!preg_match('/^(?:[01]\\d|2[0-3]):[0-5]\\d$/', $reminderHour)) { dol_syslog($langs->trans('TimesheetWeekReminderHourInvalid'), LOG_ERR); return -1; } - $templateIdConst = dolibarr_get_const($db, 'TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', $conf->entity); - $templateId = !empty($templateIdConst) ? (int) $templateIdConst : 0; + $templateId = getDolGlobalInt('TIMESHEETWEEK_REMINDER_EMAIL_TEMPLATE', 0, $conf->entity); if (empty($templateId)) { dol_syslog($langs->trans('TimesheetWeekReminderTemplateMissing'), LOG_WARNING); return 0; diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 0417782..d446e60 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -319,7 +319,7 @@ public function __construct($db) 'comment' => 'TimesheetWeekReminderCronComment', 'frequency' => 1, 'unitfrequency' => 86400, - 'status' => 0, + 'status' => 1, 'test' => 'isModEnabled("timesheetweek")', 'priority' => 50, ), @@ -879,88 +879,106 @@ public function init($options = '') dolibarr_set_const($this->db, 'TIMESHEETWEEK_ADDON_PDF', 'standard_timesheetweek', 'chaine', 0, '', $conf->entity); } - // EN: Register Multicompany sharing metadata when the module is enabled. - // FR: Enregistrer les métadonnées de partage Multicompany lors de l'activation du module. - dol_include_once('/timesheetweek/class/actions_timesheetweek.class.php'); - - // EN: Start from the current external module sharing configuration or an empty set. - // FR: Partir de la configuration de partage des modules externes actuelle ou d'un ensemble vide. - $externalmodule = json_decode((string) ($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING ?? ''), true); - if (!is_array($externalmodule)) { - // EN: Guarantee an array structure even when the constant is missing or invalid. - // FR: Garantir une structure de tableau même lorsque la constante est absente ou invalide. - $externalmodule = array(); - } + // Register Multicompany sharing metadata when the module is enabled. + dol_include_once('/timesheetweek/class/actions_timesheetweek.class.php'); - // EN: Initialize the parameters container before filling it with sharing data. - // FR: Initialiser le conteneur de paramètres avant de le remplir avec les données de partage. - $params = array(); - if (class_exists('ActionsTimesheetweek')) { - // EN: Reuse the hook helper to expose the sharing parameters to Multicompany. - // FR: Réutiliser l'assistant de hook pour exposer les paramètres de partage à Multicompany. - $params = ActionsTimesheetweek::getMulticompanySharingDefinition(); - } + // Start from the current external module sharing configuration or an empty set. + $externalmodule = json_decode((string) ($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING ?? ''), true); + if (!is_array($externalmodule)) { + // Guarantee an array structure even when the constant is missing or invalid. + $externalmodule = array(); + } + + // Initialize the parameters container before filling it with sharing data. + $params = array(); + if (class_exists('ActionsTimesheetweek')) { + // Reuse the hook helper to expose the sharing parameters to Multicompany. + $params = ActionsTimesheetweek::getMulticompanySharingDefinition(); + } if (!empty($params)) { - // EN: Merge TimesheetWeek definitions with any existing external module configuration. - // FR: Fusionner les définitions TimesheetWeek avec toute configuration de module externe existante. + // Merge TimesheetWeek definitions with any existing external module configuration. $externalmodule = array_merge($externalmodule, $params); - - // EN: Persist the refreshed configuration in the Dolibarr constants table. - // FR: Persister la configuration actualisée dans la table des constantes de Dolibarr. + + // Persist the refreshed configuration in the Dolibarr constants table. $jsonformat = json_encode($externalmodule); - dolibarr_set_const($this->db, "MULTICOMPANY_EXTERNAL_MODULES_SHARING", $jsonformat, "chaine", 0, "", $conf->entity); + dolibarr_set_const($this->db, 'MULTICOMPANY_EXTERNAL_MODULES_SHARING', $jsonformat, 'chaine', 0, '', $conf->entity); } - + $resultInit = $this->_init($sql, $options); if ($resultInit <= 0) { return $resultInit; } - + + $cronStatus = $this->setReminderCronStatus(1); + if ($cronStatus < 0) { + return $cronStatus; + } + return $resultInit; } /** - * Function called when module is disabled. - * Remove from database constants, boxes and permissions from Dolibarr database. - * Data directories are not deleted + * Function called when module is disabled. + * Remove from database constants, boxes and permissions from Dolibarr database. + * Data directories are not deleted * - * @param string $options Options when enabling module ('', 'noboxes') - * @return int<-1,1> 1 if OK, <=0 if KO + * @param string $options Options when enabling module ('', 'noboxes') + * @return int<-1,1> 1 if OK, <=0 if KO */ public function remove($options = '') { - // EN: Access the global configuration to manipulate stored constants. - // FR: Accéder à la configuration globale pour manipuler les constantes stockées. - global $conf; - - // EN: Load the hook helper to clean the sharing definition on deactivation. - // FR: Charger l'assistant de hook pour nettoyer la définition de partage à la désactivation. - dol_include_once('/timesheetweek/class/actions_timesheetweek.class.php'); - - // EN: Decode the current external module sharing configuration safely. - // FR: Décoder prudemment la configuration de partage des modules externes actuelle. - $externalmodule = json_decode((string) ($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING ?? ''), true); - if (!is_array($externalmodule)) { - // EN: Fallback to an empty array when the stored value is not valid JSON. - // FR: Revenir à un tableau vide lorsque la valeur stockée n'est pas un JSON valide. - $externalmodule = array(); - } + // Access the global configuration to manipulate stored constants. + global $conf; + + // Load the hook helper to clean the sharing definition on deactivation. + dol_include_once('/timesheetweek/class/actions_timesheetweek.class.php'); + + // Decode the current external module sharing configuration safely. + $externalmodule = json_decode((string) ($conf->global->MULTICOMPANY_EXTERNAL_MODULES_SHARING ?? ''), true); + if (!is_array($externalmodule)) { + // Fallback to an empty array when the stored value is not valid JSON. + $externalmodule = array(); + } - // EN: Determine the key used to store TimesheetWeek sharing data. - // FR: Déterminer la clé utilisée pour stocker les données de partage TimesheetWeek. - $sharingKey = class_exists('ActionsTimesheetweek') ? ActionsTimesheetweek::MULTICOMPANY_SHARING_ROOT_KEY : 'timesheetweek'; + // Determine the key used to store TimesheetWeek sharing data. + $sharingKey = class_exists('ActionsTimesheetweek') ? ActionsTimesheetweek::MULTICOMPANY_SHARING_ROOT_KEY : 'timesheetweek'; - // EN: Remove the module definition so Multicompany forgets our sharing options. - // FR: Retirer la définition du module pour que Multicompany oublie nos options de partage. - unset($externalmodule[$sharingKey]); + // Remove the module definition so Multicompany forgets our sharing options. + unset($externalmodule[$sharingKey]); - // EN: Persist the cleaned configuration back into Dolibarr constants. - // FR: Persister la configuration nettoyée dans les constantes Dolibarr. - $jsonformat = json_encode($externalmodule); - dolibarr_set_const($this->db, 'MULTICOMPANY_EXTERNAL_MODULES_SHARING', $jsonformat, 'chaine', 0, '', $conf->entity); + // Persist the cleaned configuration back into Dolibarr constants. + $jsonformat = json_encode($externalmodule); + dolibarr_set_const($this->db, 'MULTICOMPANY_EXTERNAL_MODULES_SHARING', $jsonformat, 'chaine', 0, '', $conf->entity); - $sql = array(); - return $this->_remove($sql, $options); - } + $this->setReminderCronStatus(0); + + $sql = array(); + return $this->_remove($sql, $options); + } + + /** + * Update the cron status for the reminder job. + * + * @param int $status Target status (1 enabled, 0 disabled) + * @return int 1 if OK, <0 if error + */ + protected function setReminderCronStatus($status) + { + if (empty($this->db)) { + return -1; + } + + $statusValue = ((int) $status === 1) ? 1 : 0; + $sql = 'UPDATE '.MAIN_DB_PREFIX."cronjob SET status = ".$statusValue; + $sql .= " WHERE jobtype = 'method' AND class = '/timesheetweek/class/timesheetweek_reminder.class.php' AND method = 'run'"; + + $resql = $this->db->query($sql); + if (!$resql) { + $this->error = $this->db->lasterror(); + return -1; + } + + return 1; + } } From 1460794a4485d3bc1f17aa597ef7ceea0f9d453f Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:56:45 +0100 Subject: [PATCH 55/96] Update modTimesheetWeek.class.php --- core/modules/modTimesheetWeek.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index d446e60..9115b21 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -971,7 +971,7 @@ protected function setReminderCronStatus($status) $statusValue = ((int) $status === 1) ? 1 : 0; $sql = 'UPDATE '.MAIN_DB_PREFIX."cronjob SET status = ".$statusValue; - $sql .= " WHERE jobtype = 'method' AND class = '/timesheetweek/class/timesheetweek_reminder.class.php' AND method = 'run'"; + $sql .= " WHERE jobtype = 'method' AND classesname = '/timesheetweek/class/timesheetweek_reminder.class.php' AND method = 'run'"; $resql = $this->db->query($sql); if (!$resql) { From ab45046921197b0090ae3cf9fef9f139d8464674 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:59:08 +0100 Subject: [PATCH 56/96] Update modTimesheetWeek.class.php --- core/modules/modTimesheetWeek.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 9115b21..9ec4027 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -971,7 +971,7 @@ protected function setReminderCronStatus($status) $statusValue = ((int) $status === 1) ? 1 : 0; $sql = 'UPDATE '.MAIN_DB_PREFIX."cronjob SET status = ".$statusValue; - $sql .= " WHERE jobtype = 'method' AND classesname = '/timesheetweek/class/timesheetweek_reminder.class.php' AND method = 'run'"; + $sql .= " WHERE jobtype = 'method' AND classesname = '/timesheetweek/class/timesheetweek_reminder.class.php' AND methodename = 'run'"; $resql = $this->db->query($sql); if (!$resql) { From c351d4d59db939266855f0a1bb473e137a250cf7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 00:59:32 +0100 Subject: [PATCH 57/96] Update modTimesheetWeek.class.php --- core/modules/modTimesheetWeek.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 9ec4027..23b699b 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -112,7 +112,7 @@ public function __construct($db) } // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated', 'experimental_deprecated' or a version string like 'x.y.z' - $this->version = '1.5.0'; + $this->version = '1.6.0'; // Url to the file with your last numberversion of this module $this->url_last_version = 'https://moduleversion.lesmetiersdubatiment.fr/ver.php?m=timesheetweek'; From 94c328ed1097a454c219dfa022498e6da0b5683b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 01:01:13 +0100 Subject: [PATCH 58/96] Update setup.php --- admin/setup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index e4b1ce3..159f73f 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -607,9 +607,9 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a print ''; print '
'; -print ''; +print ''; print ' '; -print ''; +print ''; print '
'; print ''; From 6a9aa6b903d41b7e2bc072dec4c1c28ec105fcde Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 01:06:41 +0100 Subject: [PATCH 59/96] Update modTimesheetWeek.class.php --- core/modules/modTimesheetWeek.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/modTimesheetWeek.class.php b/core/modules/modTimesheetWeek.class.php index 23b699b..a3a4900 100644 --- a/core/modules/modTimesheetWeek.class.php +++ b/core/modules/modTimesheetWeek.class.php @@ -317,8 +317,8 @@ public function __construct($db) 'method' => 'run', 'parameters' => '', 'comment' => 'TimesheetWeekReminderCronComment', - 'frequency' => 1, - 'unitfrequency' => 86400, + 'frequency' => 5, + 'unitfrequency' => 60, 'status' => 1, 'test' => 'isModEnabled("timesheetweek")', 'priority' => 50, From b7b366ee9bff6e806fc05d22a5ba3cc4c07f0971 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 01:12:39 +0100 Subject: [PATCH 60/96] Fix reminder cron email template loading --- class/timesheetweek_reminder.class.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index efd6b66..2a38910 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -39,7 +39,6 @@ require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -require_once DOL_DOCUMENT_ROOT.'/core/class/cemailtemplate.class.php'; dol_include_once('/timesheetweek/class/timesheetweek.class.php'); @@ -73,6 +72,22 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $langs->loadLangs(array('timesheetweek@timesheetweek')); + $emailTemplateClassFile = ''; + if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplate.class.php')) { + $emailTemplateClassFile = '/core/class/cemailtemplate.class.php'; + } elseif (is_readable(DOL_DOCUMENT_ROOT.'/core/class/emailtemplate.class.php')) { + $emailTemplateClassFile = '/core/class/emailtemplate.class.php'; + } + + if (!empty($emailTemplateClassFile)) { + dol_include_once($emailTemplateClassFile); + } + + if (!class_exists('CEmailTemplate') && !class_exists('EmailTemplate')) { + dol_syslog($langs->trans('ErrorFailedToLoadEmailTemplateClass'), LOG_ERR); + return -1; + } + dol_syslog(__METHOD__, LOG_DEBUG); $reminderEnabled = getDolGlobalInt('TIMESHEETWEEK_REMINDER_ENABLED', 0, $conf->entity); From bee5c7599270a3bcba7ec6a0434d6b5b37927763 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 01:28:19 +0100 Subject: [PATCH 61/96] Allow forced reminder cron execution --- class/timesheetweek_reminder.class.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 2a38910..d9eec08 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -72,6 +72,11 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $langs->loadLangs(array('timesheetweek@timesheetweek')); + $forceExecution = !empty($forcerun); + if (!$forceExecution) { + $forceExecution = ((int) GETPOST('forcerun', 'int') > 0); + } + $emailTemplateClassFile = ''; if (is_readable(DOL_DOCUMENT_ROOT.'/core/class/cemailtemplate.class.php')) { $emailTemplateClassFile = '/core/class/cemailtemplate.class.php'; @@ -91,7 +96,7 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array dol_syslog(__METHOD__, LOG_DEBUG); $reminderEnabled = getDolGlobalInt('TIMESHEETWEEK_REMINDER_ENABLED', 0, $conf->entity); - if (empty($reminderEnabled) && empty($forcerun)) { + if (empty($reminderEnabled) && empty($forceExecution)) { dol_syslog('TimesheetweekReminder: reminder disabled', LOG_INFO); return 0; } @@ -126,15 +131,15 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $windowMinutes = 60; $lowerBound = max(0, $targetMinutes - $windowMinutes); $upperBound = min(1440, $targetMinutes + $windowMinutes); - - if (empty($forcerun)) { + + if (empty($forceExecution)) { if ($currentWeekdayIso !== $reminderWeekday) { - dol_syslog('TimesheetweekReminder: not the configured day, skipping execution', LOG_DEBUG); - return 0; + dol_syslog('TimesheetweekReminder: not the configured day, skipping execution', LOG_DEBUG); + return 0; } if ($currentMinutes < $lowerBound || $currentMinutes > $upperBound) { - dol_syslog('TimesheetweekReminder: outside configured time window, skipping execution', LOG_DEBUG); - return 0; + dol_syslog('TimesheetweekReminder: outside configured time window, skipping execution', LOG_DEBUG); + return 0; } } @@ -177,7 +182,7 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $substitutions = getCommonSubstitutionArray($langs, 0, null, null, null); complete_substitutions_array($substitutions, $langs, null); - + $eligibleRights = array( 45000301, // read own 45000302, // read child @@ -192,7 +197,7 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array 45000314, // seal 45000315, // unseal ); - + $entityFilter = getEntity('user'); $sql = 'SELECT DISTINCT u.rowid, u.lastname, u.firstname, u.email'; $sql .= ' FROM '.MAIN_DB_PREFIX."user AS u"; From 47030d04997f747c6204dda90e70e6898cebc42e Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 01:46:48 +0100 Subject: [PATCH 62/96] Handle forced reminder triggers and HTML content --- class/timesheetweek_reminder.class.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index d9eec08..d680529 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -74,7 +74,14 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $forceExecution = !empty($forcerun); if (!$forceExecution) { - $forceExecution = ((int) GETPOST('forcerun', 'int') > 0); + $forceExecution = ((int) GETPOST('forcerun', 'int') > 0); + } + if (!$forceExecution) { + $action = GETPOST('action', 'aZ09'); + $confirm = GETPOST('confirm', 'alpha'); + if ($action === 'confirm_execute' && $confirm === 'yes') { + $forceExecution = true; + } } $emailTemplateClassFile = ''; @@ -246,7 +253,12 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $preparedSubject = make_substitutions($subject, $userSubstitutions); $preparedBody = make_substitutions($body, $userSubstitutions); - $mail = new CMailFile($preparedSubject, $recipient, $from, $preparedBody, array(), array(), array(), '', '', 0, 0, '', '', '', 'utf-8'); + $preparedSubject = dol_string_nohtmltag(html_entity_decode($preparedSubject, ENT_QUOTES, 'UTF-8')); + $preparedBodyHtml = html_entity_decode($preparedBody, ENT_QUOTES, 'UTF-8'); + $isHtmlBody = (!empty($preparedBodyHtml) && preg_match('/<[^>]+>/', $preparedBodyHtml)) ? 1 : 0; + $preparedBodyFinal = $isHtmlBody ? $preparedBodyHtml : dol_string_nohtmltag($preparedBodyHtml); + + $mail = new CMailFile($preparedSubject, $recipient, $from, $preparedBodyFinal, array(), array(), array(), '', '', 0, $isHtmlBody, '', '', '', 'utf-8'); $resultSend = $mail->sendfile(); if ($resultSend) { $emailsSent++; From a83d48d157eef99c2f413d15ccfdaa90c47b8f64 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:28:36 +0100 Subject: [PATCH 63/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index d680529..1a6ae53 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -135,9 +135,9 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array list($targetHour, $targetMinute) = explode(':', $reminderHour); $targetMinutes = ((int) $targetHour * 60) + (int) $targetMinute; - $windowMinutes = 60; + $windowMinutes = 5; $lowerBound = max(0, $targetMinutes - $windowMinutes); - $upperBound = min(1440, $targetMinutes + $windowMinutes); + $upperBound = min(120, $targetMinutes + $windowMinutes); if (empty($forceExecution)) { if ($currentWeekdayIso !== $reminderWeekday) { From f8b637051fd2aee78db4395f51aad3294a1f1862 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:39:35 +0100 Subject: [PATCH 64/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 1a6ae53..b09e18e 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -271,11 +271,21 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $db->free($resql); - if ($errors > 0) { +/* if ($errors > 0) { return -$errors; - } - - return $emailsSent; + }*/ + +// return $emailsSent; + + if ($errors) { + $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); + return 1; + }else{ + $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); + return 0; + } } /** From 0f9e92b102184aafdcf7625a28c1e5ca24d2a492 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:42:37 +0100 Subject: [PATCH 65/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index b09e18e..facfde7 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -278,12 +278,12 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array // return $emailsSent; if ($errors) { - $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; - dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); + $cron_error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + dol_syslog(__METHOD__." end - ".$cron_error, LOG_ERR); return 1; }else{ - $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; - dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); + $cron_output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + dol_syslog(__METHOD__." end - ".$cron_output, LOG_INFO); return 0; } } From 703a81f5748eb74cffcad44f50c5713657e0e30e Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:46:58 +0100 Subject: [PATCH 66/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index facfde7..13840a4 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -42,6 +42,20 @@ dol_include_once('/timesheetweek/class/timesheetweek.class.php'); +/** + * Constructor + * + * @param DoliDB $db Database handler + */ +public function __construct(DoliDB $db) +{ + global $conf, $langs ; + $this->db = $db; + //var_dump($db); + $this->ismultientitymanaged = 1; + $this->isextrafieldmanaged = 1; +} + /** * Cron helper used to send weekly reminders. */ @@ -278,12 +292,12 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array // return $emailsSent; if ($errors) { - $cron_error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; - dol_syslog(__METHOD__." end - ".$cron_error, LOG_ERR); + $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); return 1; }else{ - $cron_output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; - dol_syslog(__METHOD__." end - ".$cron_output, LOG_INFO); + $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); return 0; } } From aa5927f01cf7a0110d228d19d6f3ac52511261ab Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:48:04 +0100 Subject: [PATCH 67/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 27 +++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 13840a4..420bcd4 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -42,25 +42,26 @@ dol_include_once('/timesheetweek/class/timesheetweek.class.php'); -/** - * Constructor - * - * @param DoliDB $db Database handler - */ -public function __construct(DoliDB $db) -{ - global $conf, $langs ; - $this->db = $db; - //var_dump($db); - $this->ismultientitymanaged = 1; - $this->isextrafieldmanaged = 1; -} /** * Cron helper used to send weekly reminders. */ class TimesheetweekReminder { + /** + * Constructor + * + * @param DoliDB $db Database handler + */ + public function __construct(DoliDB $db) + { + global $conf, $langs ; + $this->db = $db; + //var_dump($db); + $this->ismultientitymanaged = 1; + $this->isextrafieldmanaged = 1; + } + /** * Run cron job to send weekly reminder emails. * From 285d839ebbcdcfc6c781ac05204e6461eeed5e70 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:51:02 +0100 Subject: [PATCH 68/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 420bcd4..a62d254 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -73,18 +73,19 @@ public function __construct(DoliDB $db) */ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { - global $conf, $langs; + global $db, $conf, $langs; $db = $dbInstance; + /* if (empty($db) && !empty($GLOBALS['db'])) { $db = $GLOBALS['db']; } - + if (empty($db)) { dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); return -1; } - + */ $langs->loadLangs(array('timesheetweek@timesheetweek')); $forceExecution = !empty($forcerun); From 46fd9ada2737dd74d80388f756aaf26948441906 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:52:02 +0100 Subject: [PATCH 69/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index a62d254..12e4671 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -75,8 +75,8 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array { global $db, $conf, $langs; - $db = $dbInstance; /* + $db = $dbInstance; if (empty($db) && !empty($GLOBALS['db'])) { $db = $GLOBALS['db']; } From 53c38601fb665f714c9f1bf70142351ae7953bff Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:53:20 +0100 Subject: [PATCH 70/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 12e4671..c641b44 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -48,19 +48,6 @@ */ class TimesheetweekReminder { - /** - * Constructor - * - * @param DoliDB $db Database handler - */ - public function __construct(DoliDB $db) - { - global $conf, $langs ; - $this->db = $db; - //var_dump($db); - $this->ismultientitymanaged = 1; - $this->isextrafieldmanaged = 1; - } /** * Run cron job to send weekly reminder emails. @@ -73,9 +60,8 @@ public function __construct(DoliDB $db) */ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { - global $db, $conf, $langs; + global $conf, $langs; - /* $db = $dbInstance; if (empty($db) && !empty($GLOBALS['db'])) { $db = $GLOBALS['db']; @@ -85,7 +71,7 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); return -1; } - */ + $langs->loadLangs(array('timesheetweek@timesheetweek')); $forceExecution = !empty($forcerun); From 78e8e2acb99f4968566f63856e076667230dd83b Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:00:54 +0100 Subject: [PATCH 71/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index c641b44..a5fc457 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -280,13 +280,15 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array // return $emailsSent; if ($errors) { - $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; - dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); - return 1; + $result = 1; + $result->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + dol_syslog(__METHOD__." end - ".$result->error, LOG_ERR); + return $result; }else{ - $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; - dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); - return 0; + $result = 0; + $result->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + dol_syslog(__METHOD__." end - ".$result->output, LOG_INFO); + return $result; } } From 8e66ac118653ed370ff2deee607ef0d2e09473c9 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:09:18 +0100 Subject: [PATCH 72/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 30 ++++++++++++++++---------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index a5fc457..fda3db4 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -48,9 +48,17 @@ */ class TimesheetweekReminder { - -/** - * Run cron job to send weekly reminder emails. + public $db; + public $error; + public $errors = array(); + public $output; + + public function __construct(DoliDB $db) + { + $this->db = $db; + } + /** + * Run cron job to send weekly reminder emails. * * @param DoliDB $db Database handler * @param int $limit Optional limit for recipients @@ -58,9 +66,9 @@ class TimesheetweekReminder * @param array $targetUserIds Limit execution to specific user ids when provided * @return int <0 if KO, >=0 if OK (number of emails sent) */ - public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) + public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { - global $conf, $langs; + global $db, $conf, $user, $langs; $db = $dbInstance; if (empty($db) && !empty($GLOBALS['db'])) { @@ -280,14 +288,14 @@ public static function run($dbInstance = null, $limit = 0, $forcerun = 0, array // return $emailsSent; if ($errors) { - $result = 1; - $result->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; - dol_syslog(__METHOD__." end - ".$result->error, LOG_ERR); + //$result = 1; + $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); return $result; }else{ - $result = 0; - $result->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; - dol_syslog(__METHOD__." end - ".$result->output, LOG_INFO); + //$result = 0; + $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); return $result; } } From afcef97b657b2846eb1fc0b59fa67d102e4d9377 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:12:21 +0100 Subject: [PATCH 73/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index fda3db4..085e633 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -69,12 +69,12 @@ public function __construct(DoliDB $db) public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { global $db, $conf, $user, $langs; - + /* $db = $dbInstance; if (empty($db) && !empty($GLOBALS['db'])) { $db = $GLOBALS['db']; } - + */ if (empty($db)) { dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); return -1; From 550ab23c2f78cfc4b5ad477aa5d53715d974412a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:13:56 +0100 Subject: [PATCH 74/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 085e633..c0311da 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -309,6 +309,6 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target */ public static function sendTest($db, User $user) { - return self::run($db, 1, 1, array((int) $user->id)); + return self:run($db, 1, 1, array((int) $user->id)); } } From b5aee602deebb3acdd1c75d522e7204f9dbd065a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:45:09 +0100 Subject: [PATCH 75/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index c0311da..4866fbc 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -46,7 +46,7 @@ /** * Cron helper used to send weekly reminders. */ -class TimesheetweekReminder +class TimesheetweekReminder extends CommonObject { public $db; public $error; @@ -309,6 +309,6 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target */ public static function sendTest($db, User $user) { - return self:run($db, 1, 1, array((int) $user->id)); + return self::run($db, 1, 1, array((int) $user->id)); } } From 0729a02d9c5a32120b54c3206832987abe39dbe8 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:46:16 +0100 Subject: [PATCH 76/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 4866fbc..7a92832 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -309,6 +309,6 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target */ public static function sendTest($db, User $user) { - return self::run($db, 1, 1, array((int) $user->id)); + return run($db, 1, 1, array((int) $user->id)); } } From 3f3e3bef33b22273fbf7fe9bf046a5b2d0d0f227 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 09:47:09 +0100 Subject: [PATCH 77/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 7a92832..6748512 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -307,8 +307,8 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target * @param User $user Current user * @return int <0 if KO, >=0 if OK (number of emails sent) */ - public static function sendTest($db, User $user) + public function sendTest($db, User $user) { - return run($db, 1, 1, array((int) $user->id)); + return self::run($db, 1, 1, array((int) $user->id)); } } From ccab5b550838f01b1bb07082c863af34a73ca62a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:50:12 +0100 Subject: [PATCH 78/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 6748512..e0ae3dd 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -291,12 +291,12 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target //$result = 1; $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); - return $result; + return 1; }else{ //$result = 0; $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); - return $result; + return 0; } } From 000d05bb406590f371bca36cba6b1bcc3f2934b1 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:52:31 +0100 Subject: [PATCH 79/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index 159f73f..6e3507e 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -390,7 +390,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } if ($action === 'testreminder') { - $resultTest = TimesheetweekReminder::sendTest($db, $user); + $resultTest = sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); if ($resultTest > 0) { setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); } else { From 55c4d7b080f5f9e70d4a500f7d10e07c166c1b21 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:00:02 +0100 Subject: [PATCH 80/96] Update setup.php --- admin/setup.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index 6e3507e..80f8a8d 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -390,7 +390,8 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a } if ($action === 'testreminder') { - $resultTest = sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); + $reminder = new TimesheetweekReminder($db); + $resultTest = $reminder->sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); if ($resultTest > 0) { setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); } else { From 402f2ec17915fd13c4cf039ca19bf928f0bc5bc7 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:05:27 +0100 Subject: [PATCH 81/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index e0ae3dd..fac77aa 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -309,6 +309,6 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target */ public function sendTest($db, User $user) { - return self::run($db, 1, 1, array((int) $user->id)); + return $this->run($db, 1, 1, array((int) $user->id)); } } From edad7993a45cff17754e6bf2ae15757e48b916d1 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:07:26 +0100 Subject: [PATCH 82/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index fac77aa..caafe5d 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -69,12 +69,14 @@ public function __construct(DoliDB $db) public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { global $db, $conf, $user, $langs; - /* - $db = $dbInstance; - if (empty($db) && !empty($GLOBALS['db'])) { - $db = $GLOBALS['db']; + + if($dbInstance) { + $db = $dbInstance; + if (empty($db) && !empty($GLOBALS['db'])) { + $db = $GLOBALS['db']; + } } - */ + if (empty($db)) { dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); return -1; From 3c015617afc6988e1c81ff274caec5736f09dd81 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:08:20 +0100 Subject: [PATCH 83/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index caafe5d..c70dfbb 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -69,14 +69,13 @@ public function __construct(DoliDB $db) public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) { global $db, $conf, $user, $langs; - - if($dbInstance) { + + /* $db = $dbInstance; if (empty($db) && !empty($GLOBALS['db'])) { $db = $GLOBALS['db']; } - } - + */ if (empty($db)) { dol_syslog($langs->transnoentitiesnoconv('ErrorNoDatabase'), LOG_ERR); return -1; From afbef8e3501808fe1bce6bbaccfb529fb5217b90 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:12:17 +0100 Subject: [PATCH 84/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index c70dfbb..a9d7b74 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -289,12 +289,10 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target // return $emailsSent; if ($errors) { - //$result = 1; $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); return 1; }else{ - //$result = 0; $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); return 0; From 89bf6afb4d219dc431521c23446bde15a43121bb Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:13:33 +0100 Subject: [PATCH 85/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index a9d7b74..d5bab8d 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -66,7 +66,7 @@ public function __construct(DoliDB $db) * @param array $targetUserIds Limit execution to specific user ids when provided * @return int <0 if KO, >=0 if OK (number of emails sent) */ - public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) + public function run($limit = 0, $forcerun = 0, array $targetUserIds = array()) //$dbInstance = null, { global $db, $conf, $user, $langs; From 588295ab99ce6cd23d95119e85432deb037b7ebb Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:18:25 +0100 Subject: [PATCH 86/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index d5bab8d..73671a0 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -308,6 +308,6 @@ public function run($limit = 0, $forcerun = 0, array $targetUserIds = array()) / */ public function sendTest($db, User $user) { - return $this->run($db, 1, 1, array((int) $user->id)); + return self::run($db, 1, 1, array((int) $user->id)); } } From 03570c7adbbf4610d30ac872a74ad2f76cf02f3a Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:19:31 +0100 Subject: [PATCH 87/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 73671a0..9b2c8e4 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -66,7 +66,7 @@ public function __construct(DoliDB $db) * @param array $targetUserIds Limit execution to specific user ids when provided * @return int <0 if KO, >=0 if OK (number of emails sent) */ - public function run($limit = 0, $forcerun = 0, array $targetUserIds = array()) //$dbInstance = null, + public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $targetUserIds = array()) //$dbInstance = null, { global $db, $conf, $user, $langs; From f6f082f88725965cfa2813582522f58b2bd9f591 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:22:32 +0100 Subject: [PATCH 88/96] Update setup.php --- admin/setup.php | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/setup.php b/admin/setup.php index 80f8a8d..35a39d4 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -392,6 +392,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a if ($action === 'testreminder') { $reminder = new TimesheetweekReminder($db); $resultTest = $reminder->sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); + var_dump($resultTest); if ($resultTest > 0) { setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); } else { From 4c7df2f9860a0377202b96f52c50a1b661d99b78 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:28:41 +0100 Subject: [PATCH 89/96] Update setup.php --- admin/setup.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/setup.php b/admin/setup.php index 35a39d4..17363ee 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -393,7 +393,7 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a $reminder = new TimesheetweekReminder($db); $resultTest = $reminder->sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); var_dump($resultTest); - if ($resultTest > 0) { + if ($resultTest == 0) { setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); } else { setEventMessages($langs->trans('TimesheetWeekReminderTestError'), null, 'errors'); From db79e2c6e3027d7ef1c959b7fd38ef5b60793b46 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:30:25 +0100 Subject: [PATCH 90/96] Update setup.php --- admin/setup.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/setup.php b/admin/setup.php index 17363ee..ca49120 100644 --- a/admin/setup.php +++ b/admin/setup.php @@ -392,9 +392,9 @@ function timesheetweekListDocumentModels(array $directories, Translate $langs, a if ($action === 'testreminder') { $reminder = new TimesheetweekReminder($db); $resultTest = $reminder->sendTest($db, $user); //$resultTest = TimesheetweekReminder::sendTest($db, $user); - var_dump($resultTest); + //var_dump($resultTest); if ($resultTest == 0) { - setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess', $resultTest), null, 'mesgs'); + setEventMessages($langs->trans('TimesheetWeekReminderTestSuccess'), null, 'mesgs'); } else { setEventMessages($langs->trans('TimesheetWeekReminderTestError'), null, 'errors'); } From 66efcdac4ee2f81a583e413e54cf4273b1e54b31 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:30:42 +0100 Subject: [PATCH 91/96] Update timesheetweek.lang --- langs/fr_FR/timesheetweek.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langs/fr_FR/timesheetweek.lang b/langs/fr_FR/timesheetweek.lang index 3c992fa..d5aa9f3 100644 --- a/langs/fr_FR/timesheetweek.lang +++ b/langs/fr_FR/timesheetweek.lang @@ -45,7 +45,7 @@ TimesheetWeekReminderTemplateMissing = Le modèle d'email de rappel n'est pas co TimesheetWeekReminderSendFailed = Échec de l'envoi du rappel à %s. TimesheetWeekReminderSendSuccess = Rappel envoyé avec succès à %s. TimesheetWeekReminderSendTest = Envoyer un mail de test -TimesheetWeekReminderTestSuccess = Mail de test envoyé (%s) +TimesheetWeekReminderTestSuccess = Mail de test envoyé TimesheetWeekReminderTestError = Échec de l'envoi du mail de test. TimesheetWeekReminderTemplateLabel = Timesheetweek - Rappel des feuilles d'heures TimesheetWeekReminderTemplateSubject = Rappel d'envoi des feuilles d'heures From 950028457120c7cb7f3a18bf86acb65a310c87ec Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:30:59 +0100 Subject: [PATCH 92/96] Update timesheetweek.lang --- langs/en_US/timesheetweek.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/langs/en_US/timesheetweek.lang b/langs/en_US/timesheetweek.lang index fb26c68..7c0ea4b 100644 --- a/langs/en_US/timesheetweek.lang +++ b/langs/en_US/timesheetweek.lang @@ -45,7 +45,7 @@ TimesheetWeekReminderTemplateMissing = Reminder email template is not configured TimesheetWeekReminderSendFailed = Failed to send the reminder email to %s. TimesheetWeekReminderSendSuccess = Reminder email successfully sent to %s. TimesheetWeekReminderSendTest = Send test email -TimesheetWeekReminderTestSuccess = Test reminder email sent (%s) +TimesheetWeekReminderTestSuccess = Test reminder email sent TimesheetWeekReminderTestError = Unable to send the test reminder email. TimesheetWeekReminderTemplateLabel = Timesheetweek - Timesheet reminder TimesheetWeekReminderTemplateSubject = Timesheet submission reminder From 0fb144119187e721e344dff91cc659062ef89137 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:40:35 +0100 Subject: [PATCH 93/96] Update data.sql --- sql/data.sql | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/data.sql b/sql/data.sql index 8d51ab8..de5725e 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -7,4 +7,5 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u 'isModEnabled(\"timesheetweek\")', NULL, "Rappel Feuilles d\'heures hebodmadaires", - "Bonjour,
Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.
Bon week-end."); + "Bonjour,

Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.

Bon week-end.
+; From 0c63a1f28dc3ed6f45511d27deac78ba4b27dbb3 Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:41:06 +0100 Subject: [PATCH 94/96] Avoid overriding global user during reminder run --- class/timesheetweek_reminder.class.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 9b2c8e4..11ed7f0 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -246,20 +246,20 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target continue; } - $user = new User($db); - $fetchUser = $user->fetch($obj->rowid); + $recipientUser = new User($db); + $fetchUser = $recipientUser->fetch($obj->rowid); if ($fetchUser < 0) { - dol_syslog($user->error, LOG_ERR); + dol_syslog($recipientUser->error, LOG_ERR); $errors++; continue; } $userSubstitutions = $substitutions; - $userSubstitutions['__USER_FIRSTNAME__'] = $user->firstname; - $userSubstitutions['__USER_LASTNAME__'] = $user->lastname; - $userSubstitutions['__USER_FULLNAME__'] = dolGetFirstLastname($user->firstname, $user->lastname); + $userSubstitutions['__USER_FIRSTNAME__'] = $recipientUser->firstname; + $userSubstitutions['__USER_LASTNAME__'] = $recipientUser->lastname; + $userSubstitutions['__USER_FULLNAME__'] = dolGetFirstLastname($recipientUser->firstname, $recipientUser->lastname); $userSubstitutions['__USER_EMAIL__'] = $recipient; - complete_substitutions_array($userSubstitutions, $langs, null, $user); + complete_substitutions_array($userSubstitutions, $langs, null, $recipientUser); $preparedSubject = make_substitutions($subject, $userSubstitutions); $preparedBody = make_substitutions($body, $userSubstitutions); From d29f8f1a2dd73882ea62dc6d9f9a07e7fdc647eb Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:46:41 +0100 Subject: [PATCH 95/96] Update timesheetweek_reminder.class.php --- class/timesheetweek_reminder.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class/timesheetweek_reminder.class.php b/class/timesheetweek_reminder.class.php index 9b2c8e4..e65d605 100644 --- a/class/timesheetweek_reminder.class.php +++ b/class/timesheetweek_reminder.class.php @@ -289,11 +289,11 @@ public function run($dbInstance = null, $limit = 0, $forcerun = 0, array $target // return $emailsSent; if ($errors) { - $this->error = $langs->trans('TimesheetWeekReminderSendFailed').' '.$errors; + $this->error = $langs->trans('TimesheetWeekReminderSendFailed', $errors); dol_syslog(__METHOD__." end - ".$this->error, LOG_ERR); return 1; }else{ - $this->output = $langs->trans('TimesheetWeekReminderSendSuccess')." ".$emailsSent."."; + $this->output = $langs->trans('TimesheetWeekReminderSendSuccess', $emailsSent); dol_syslog(__METHOD__." end - ".$this->output, LOG_INFO); return 0; } From 0b1ba51316c773ea8fca716ee0e5ee0aa2aec7bc Mon Sep 17 00:00:00 2001 From: Pierre Ardoin <32256817+mapiolca@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:50:59 +0100 Subject: [PATCH 96/96] Update data.sql --- sql/data.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/data.sql b/sql/data.sql index de5725e..3df3103 100644 --- a/sql/data.sql +++ b/sql/data.sql @@ -7,5 +7,5 @@ INSERT INTO llx_c_email_templates (entity,module,type_template,lang,private,fk_u 'isModEnabled(\"timesheetweek\")', NULL, "Rappel Feuilles d\'heures hebodmadaires", - "Bonjour,

Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.

Bon week-end.
-; + "Bonjour,

Merci de soumettre vos feuilles d\'heures de la semaine pour lundi matin 8h.

Bon week-end.
" + );