Help with Custom Trigger

I have a problem with writing a Trigger. I want the trigger to calculate the time elapsed between the date and time in field 1 and the date and time in field 2. I created three fields in the Dolibarr Task module: stage_1_start_time (Type Date and time), stage_1_stop_time (Type Date and time), and stage_1_total_time (Type String 1 line). I created a trigger named interface_99_all_CalculateTaskTotalTime.class.php and placed it in the htdocs/core/triggers folder. Unfortunately, the trigger code does not calculate the time (or does not save it correctly), and I do not understand why. I do not fully understand how triggers work, and the documentation does not explain it clearly for me (Triggers system - Dolibarr ERP CRM Wiki). Dolibarr, for example, creates a table with names like options_stage_1_start_time, options_stage_1_stop_time… and places the date and time in the timestamp format, while my fields in the database save data in the date and time format. I am not sure whether to perform operations on the data from the database (Date and time) or the data from the Array (timestamp). The trigger appears correctly in Admin Tools → Triggers. One more question: If instead of -all_ I would like to name the trigger with the module name, should I name it interface_99_modProjet_CalculateTaskTotalTime.class.php (since Task is part of the Projet module), or interface_99_modTask_CalculateTaskTotalTime.class.php? My code: <?php class InterfaceCalculateTaskTotalTime extends DolibarrTriggers
{
public function run_trigger($action, $object, User $user, Translate $langs, Conf $conf)
{
dol_syslog(“Trigger InterfaceCalculateTaskTotalTime triggered with action: $action”, LOG_DEBUG);

    // Sprawdzenie, czy jest aktywowany moduł, jeśli to jest wymagane
    if (!isModEnabled('projet')) {
        return 0; // Moduł nieaktywny, nie robimy nic
    }

    // Sprawdzenie akcji tworzenia lub modyfikacji zadania
    if ($action == 'TASK_CREATE' || $action == 'TASK_MODIFY') {
        // Upewnij się, że obiekt jest instancją klasy Task
        if (is_a($object, 'Task')) {
            // Ładowanie wartości pól z obiektu
            $start_time = isset($object->array_options['options_stage_1_start_time']) ? $object->array_options['options_stage_1_start_time'] : '';
            $stop_time = isset($object->array_options['options_stage_1_stop_time']) ? $object->array_options['options_stage_1_stop_time'] : '';

            // Sprawdź, czy pola są wypełnione
            if (!empty($start_time) && !empty($stop_time)) {
                // Obliczenia
                $time_diff = intval($stop_time) - intval($start_time);
                if ($time_diff >= 0) {
                    $days = floor($time_diff / (60 * 60 * 24));
                    $hours = floor(($time_diff % (60 * 60 * 24)) / (60 * 60));
                    $minutes = floor(($time_diff % (60 * 60)) / 60);

                    // Formatowanie czasu
                    $total_time = sprintf("%d Days, %dH:%dM", $days, $hours, $minutes);

                    // Ustawienie wyniku w array_options
                    $object->array_options['options_stage_1_total_time'] = $total_time;

                    // Zapisz zmiany w obiekcie
                    if ($object->update($user) < 0) {
                        $this->setErrorsFromObject($object);
                        return -1; // Wystąpił błąd podczas aktualizacji obiektu
                    }

                    dol_syslog("Processed total time for task ID: " . $object->id . " with total time: " . $total_time, LOG_DEBUG);
                }
            }
        }
    }

    return 0; // zwraca 0, jeśli nic się nie zmienia
}

}

I only use triggers for email notifications. What if you use a hook to call an external program that uses the API to for fetching the data, do the calculation and then put the result back using the API?

You missed to insert a formula in the field stage_1_total_time.

Insert it like this:

and you will get this:

Btw, your file should be named interface_99_modProjet_CalculateTaskTotalTime.class.php

Tested with Version 17.0.2

@DG-Rilling It’s not exactly what I had in mind, but it’s more than enough to start with and very simple to implement. Thank you!