diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 9d567ade0f6..0e63c42d4a2 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -10835,6 +10835,9 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null, $substitutionarray['__AMOUNT_TEXT__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, '', true) : ''; $substitutionarray['__AMOUNT_TEXTCURRENCY__'] = is_object($object) ? dol_convertToWord($object->total_ttc, $outputlangs, $conf->currency, true) : ''; + $substitutionarray['__DEPOSIT_PERCENT__'] = is_object($object) ? $object->deposit_percent : ''; + $substitutionarray['__DEPOSIT_AMOUNT__'] = is_object($object) ? price2num($object->total_ttc * ($object->deposit_percent / 100), 'MT') : ''; + $substitutionarray['__AMOUNT_REMAIN__'] = is_object($object) ? price2num($object->total_ttc - $already_payed_all, 'MT') : ''; $substitutionarray['__AMOUNT_VAT__'] = is_object($object) ? (isset($object->total_vat) ? $object->total_vat : $object->total_tva) : ''; diff --git a/htdocs/core/modules/modHoliday.class.php b/htdocs/core/modules/modHoliday.class.php index aa805118980..c401510320f 100644 --- a/htdocs/core/modules/modHoliday.class.php +++ b/htdocs/core/modules/modHoliday.class.php @@ -150,6 +150,21 @@ class modHoliday extends DolibarrModules 'status' => 1, 'test' => '$conf->holiday->enabled', 'datestart' => $datestart + ), + 1 => array( + 'label' => 'SendPreviousMonthHRInformations:holiday', + 'jobtype' => 'method', + 'class' => 'holiday/class/holiday.class.php', + 'objectname' => 'Holiday', + 'method' => 'sendPreviousMonthHRInformations', + 'parameters' => 'emailaddress, EmailTemplateCode', + 'comment' => 'Send HR information to the defined email address. EmailTemplateCode can be id or label of emailtemplate to send', + 'frequency' => 1, + 'unitfrequency' => 3600 * 24 * 31, + 'priority' => 50, + 'status' => 0, + 'test' => '$conf->holiday->enabled', + 'datestart' => $datestart ) ); diff --git a/htdocs/core/modules/syslog/mod_syslog_syslog.php b/htdocs/core/modules/syslog/mod_syslog_syslog.php index 80706c439c7..1481577cf86 100644 --- a/htdocs/core/modules/syslog/mod_syslog_syslog.php +++ b/htdocs/core/modules/syslog/mod_syslog_syslog.php @@ -86,7 +86,7 @@ class mod_syslog_syslog extends LogHandler { global $langs; - $facility = constant(getDolGlobalString('SYSLOG_FACILITY')); + $facility = defined(getDolGlobalString('SYSLOG_FACILITY')) ? constant(getDolGlobalString('SYSLOG_FACILITY')) : null; if ($facility) { // Only LOG_USER supported on Windows @@ -117,8 +117,8 @@ class mod_syslog_syslog extends LogHandler return; // Global option to disable output of this handler } - if (getDolGlobalString('SYSLOG_FACILITY')) { // Example LOG_USER - $facility = constant($conf->global->SYSLOG_FACILITY); + if (getDolGlobalString('SYSLOG_FACILITY') && defined(getDolGlobalString('SYSLOG_FACILITY'))) { // Example LOG_USER + $facility = constant(getDolGlobalString('SYSLOG_FACILITY')); } else { $facility = constant('LOG_USER'); } diff --git a/htdocs/holiday/class/holiday.class.php b/htdocs/holiday/class/holiday.class.php index 19c1e119251..90cb5b5c1d3 100644 --- a/htdocs/holiday/class/holiday.class.php +++ b/htdocs/holiday/class/holiday.class.php @@ -2624,4 +2624,195 @@ class Holiday extends CommonObject $return .= ''; return $return; } + + /** + * Send a mail with previous month Hr information + * CAN BE A CRON TASK + * + * @param string $mailto Email address to send to + * @param string $template Id or Label of mail template to use + * @param string $newlang Force a lang or empty for auto + * + * @return int 0 if OK, <> 0 if KO (this function is used also by cron so only 0 is OK) + */ + public function sendPreviousMonthHRInformations($mailto = "", $template = "", $newlang = "") + { + global $conf, $langs, $user; + + $db = $this->db; + $outputlangs = $langs; + + $error = 0; + $this->output=''; + $this->error=''; + $arrayfields = array( + 'user' => 'Employee', + 'type' => 'Type', + 'date_start' => 'DateDebCP', + 'date_end' => 'DateFinCP', + 'used_days' => 'NbUseDaysCPShort', + ); + + if (!empty($newlang)) { + $outputlangs = new Translate("", $conf); + $outputlangs->setDefaultLang($newlang); + } + $outputlangs->loadLangs(array('main', 'holiday', 'hrm')); + + if (empty($mailto) || !isValidEmail($mailto)) { + $this->errors[] = 'Bad value for parameter mailto. Must be a valid email address.'; + return 1; + } + + $typeleaves = $this->getTypes(1, -1); + $arraytypeleaves = array(); + foreach ($typeleaves as $key => $val) { + $labeltoshow = ($outputlangs->trans($val['code']) != $val['code'] ? $outputlangs->trans($val['code']) : $val['label']); + $arraytypeleaves[$val['rowid']] = $labeltoshow; + } + $listhalfday = array('morning' => $outputlangs->trans("Morning"), "afternoon" => $outputlangs->trans("Afternoon")); + + $datenow = dol_getdate(dol_now()); + $prev_month = dol_get_prev_month($datenow["mon"], $datenow["year"]); + $year_month = sprintf("%04d", $prev_month["year"]).'-'.sprintf("%02d", $prev_month["month"]); + $arrayleaves = array(); + + $sql = "SELECT cp.rowid, cp.ref, cp.fk_user, cp.date_debut, cp.date_fin, cp.fk_type, cp.description, cp.halfday, cp.statut as status"; + $sql .= " FROM ".MAIN_DB_PREFIX."holiday cp"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user u ON cp.fk_user = u.rowid"; + $sql .= " WHERE cp.entity IN (".getEntity('holiday').") AND cp.rowid > 0"; + $sql .= " AND cp.statut = ".Holiday::STATUS_APPROVED; + $sql .= " AND ("; + $sql .= " (date_format(cp.date_debut, '%Y-%m') = '".$this->db->escape($year_month)."' OR date_format(cp.date_fin, '%Y-%m') = '".$this->db->escape($year_month)."')"; + $sql .= " OR"; // For leave over several months + $sql .= " (date_format(cp.date_debut, '%Y-%m') < '".$this->db->escape($year_month)."' AND date_format(cp.date_fin, '%Y-%m') > '".$this->db->escape($year_month)."') "; + $sql .= " )"; + $sql .= $this->db->order("cp.fk_user, cp.date_debut", "ASC"); + $resql = $this->db->query($sql); + if (empty($resql)) { + $this->errors[] = $this->db->lasterror(); + return 1; + } + $num = $this->db->num_rows($resql); + if ($num > 0) { + $tmpuser = new User($this->db); + while ($obj = $this->db->fetch_object($resql)) { + $tmpuser->fetch($obj->fk_user); + + $date_start = $this->db->jdate($obj->date_debut, true); + $date_end = $this->db->jdate($obj->date_fin, true); + + $tmpstart = dol_getdate($date_start); + $tmpend = dol_getdate($date_end); + + $starthalfday = ($obj->halfday == -1 || $obj->halfday == 2) ? 'afternoon' : 'morning'; + $endhalfday = ($obj->halfday == 1 || $obj->halfday == 2) ? 'morning' : 'afternoon'; + + $halfdayinmonth = $obj->halfday; + $starthalfdayinmonth = $starthalfday; + $endhalfdayinmonth = $endhalfday; + + //0:Full days, 2:Start afternoon end morning, -1:Start afternoon end afternoon, 1:Start morning end morning + + // Set date_start_gmt and date_end_gmt that are date to show for the selected month + $date_start_inmonth = $this->db->jdate($obj->date_debut, true); + $date_end_inmonth = $this->db->jdate($obj->date_fin, true); + if ($tmpstart['year'] < $prev_month["year"] || $tmpstart['mon'] < $prev_month["month"]) { + $date_start_inmonth = dol_get_first_day($prev_month["year"], $prev_month["month"], true); + $starthalfdayinmonth = 'morning'; + if ($halfdayinmonth == 2) { + $halfdayinmonth = 1; + } + if ($halfdayinmonth == -1) { + $halfdayinmonth = 0; + } + } + if ($tmpend['year'] > $prev_month["year"] || $tmpend['mon'] > $prev_month["month"]) { + $date_end_inmonth = dol_get_last_day($prev_month["year"], $prev_month["month"], true) - ((24 * 3600) - 1); + $endhalfdayinmonth = 'afternoon'; + if ($halfdayinmonth == 2) { + $halfdayinmonth = -1; + } + if ($halfdayinmonth == 1) { + $halfdayinmonth = 0; + } + } + $arrayleaves[] = array( + "user" => $tmpuser->getNomUrl(0, 'nolink', 0, 0, 24, 1), + "type" => $arraytypeleaves[$obj->fk_type], + "date_start" => dol_print_date($date_start_inmonth, 'day') . '('.$outputlangs->trans($listhalfday[$starthalfdayinmonth]).')', + "date_end" => dol_print_date($date_end_inmonth, 'day') . '('.$outputlangs->trans($listhalfday[$endhalfdayinmonth]).')', + "used_days" => num_open_day($date_start_inmonth, $date_end_inmonth, 0, 1, $halfdayinmonth, $tmpuser->country_id) + ); + } + } + + $outputarrayleaves = '
'; + $outputarrayleaves .= ''; + foreach ($arrayfields as $key => $label) { + $outputarrayleaves .= ''; + } + $outputarrayleaves .= ''; + + if (!empty($arrayleaves)) { + foreach ($arrayleaves as $key => $fields) { + $outputarrayleaves .= ''; + foreach ($fields as $field => $value) { + $outputarrayleaves .= ''; + } + $outputarrayleaves .= ''; + } + } else { + $outputarrayleaves .= ''; + $outputarrayleaves .= ''; + $outputarrayleaves .= ''; + } + $outputarrayleaves .= '
'; + $outputarrayleaves .= $outputlangs->trans($label); + $outputarrayleaves .= '
'; + $outputarrayleaves .= $value; + $outputarrayleaves .= '
'; + $outputarrayleaves .= $outputlangs->trans("None"); + $outputarrayleaves .= '
'; + + include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; + include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php'; + + $formmail = new FormMail($this->db); + $templateId = 0; + $templateLabel = ''; + if (empty($template) || $template == 'EmailTemplateCode') { + $templateLabel = '(HolidayHrInformationsPreviousMonth)'; + } else { + if (is_numeric($template)) { + $templateId = $template; + } else { + $templateLabel = $template; + } + } + $mailtemplate = $formmail->getEMailTemplate($this->db, "holiday", $user, $outputlangs, $templateId, 1, $templateLabel); + $substitutionarray = getCommonSubstitutionArray($outputlangs, 0, null, $this); + complete_substitutions_array($substitutionarray, $outputlangs, $this); + + $subject = make_substitutions($mailtemplate->topic, $substitutionarray, $outputlangs); + $msg = make_substitutions($mailtemplate->content, $substitutionarray, $outputlangs); + $from = dol_string_nospecial(getDolGlobalString('MAIN_INFO_SOCIETE_NOM'), ' ', array(",")).' <' . getDolGlobalString('MAIN_INFO_SOCIETE_MAIL').'>'; + + $msg = preg_replace('/__ARRAY_EMPLOYEE_STARTDAY_ENDDAY_DAYS__/', $outputarrayleaves, $msg); + $cmail = new CMailFile($subject, $mailto, $from, $msg, array(), array(), array(), '', '', 0, 1); + $result = $cmail->sendfile(); + if (!$result || !empty($cmail->error) || !empty($cmail->errors)) { + $this->errors[] = $cmail->error; + if (is_array($cmail->errors) && count($cmail->errors) > 0) { + $this->errors = array_merge($this->errors, $cmail->errors); + $error++; + } + } + + if (!empty($this->errors)) { + $this->output .= "\n"; + // The $this->errors will be concatenated to the output by the function that call this method. + } + return ($error ? 1 : 0); + } } diff --git a/htdocs/install/mysql/migration/23.0.0-24.0.0.sql b/htdocs/install/mysql/migration/23.0.0-24.0.0.sql index e7e1252c21b..05cfa10d287 100644 --- a/htdocs/install/mysql/migration/23.0.0-24.0.0.sql +++ b/htdocs/install/mysql/migration/23.0.0-24.0.0.sql @@ -189,6 +189,7 @@ ALTER TABLE llx_societe_remise_except ADD COLUMN localtax1_type varchar(10) NUL ALTER TABLE llx_societe_remise_except ADD COLUMN localtax2_tx double(7,4) DEFAULT 0 NOT NULL AFTER localtax1_type; ALTER TABLE llx_societe_remise_except ADD COLUMN localtax2_type varchar(10) NULL AFTER localtax2_tx; -INSERT INTO llx_c_email_templates (entity, module, type_template, lang, private, fk_user, datec, label, position, enabled, active, topic, content, content_lines, joinfiles) VALUES (0, 'holiday', 'holiday', '', 0, null, null, '(HolidayHrInformationsPreviousMonth)', 100,'isModEnabled("holiday")', 1, '__(HolidayHrInformationsPreviousMonthTopic)__', '__(HolidayHrInformationsPreviousMonthContent)__:
__ARRAY_EMPLOYEE_STARTDAY_ENDDAY_DAYS__', null, 0) +INSERT INTO llx_c_email_templates (entity, module, type_template, lang, private, fk_user, datec, label, position, enabled, active, topic, content, content_lines, joinfiles) VALUES (0, 'holiday', 'holiday', '', 0, null, null, '(HolidayHrInformationsPreviousMonth)', 100,'isModEnabled("holiday")', 1, '__(HolidayHrInformationsPreviousMonthTopic)__', '__(HolidayHrInformationsPreviousMonthContent)__:
__ARRAY_EMPLOYEE_STARTDAY_ENDDAY_DAYS__', null, 0); +ALTER TABLE llx_c_ticket_category ADD COLUMN fk_ticket_type integer NULL; -- end of migration diff --git a/htdocs/install/mysql/tables/llx_c_ticket_category-ticket.sql b/htdocs/install/mysql/tables/llx_c_ticket_category-ticket.sql index 971fb844ce3..d4d3021d256 100644 --- a/htdocs/install/mysql/tables/llx_c_ticket_category-ticket.sql +++ b/htdocs/install/mysql/tables/llx_c_ticket_category-ticket.sql @@ -31,5 +31,6 @@ create table llx_c_ticket_category force_severity varchar(32) NULL, -- To force the severity if we choosed this category description varchar(255), -- A long description of ticket pos integer DEFAULT 0 NOT NULL, - active integer DEFAULT 1 + active integer DEFAULT 1, + fk_ticket_type integer NULL )ENGINE=innodb; diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index c1e62959e8a..e9aaef56d25 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -132,21 +132,25 @@ class Thirdparties extends DolibarrApi * Get a list of third parties * * @since 3.8.0 Initial implementation + * @since 21.0.0 Data pagination * - * @param string $sortfield S ort field + * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit List limit * @param int $page Page number - * @param int $mode Set to 0 to show all third parties, Set to 1 to show only customers, 2 for prospects, 3 for neither customer or prospect, 4 for suppliers + * @param int $mode Set to 0 to show all third parties, Set to 1 to show only customers, 2 for prospects, 3 for neither customer nor prospect, 4 for suppliers * @param int $category Use this param to filter the list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "((t.nom:like:'TheCompany%') or (t.name_alias:like:'TheCompany%')) and (t.datec:<:'20160101')" * @param string $properties Restrict the data returned to these properties. Ignored if empty. Comma separated list of properties names - * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0* - * @return array Array of thirdparty objects + * @param bool $pagination_data If this parameter is set to true, the response will include pagination data. The default value is false. Page starts from 0* + * @return array Array of third party objects * @phan-return Societe[]|array{data:Societe[],pagination:array{total:int,page:int,page_count:int,limit:int}} * @phpstan-return Societe[]|array{data:Societe[],pagination:array{total:int,page:int,page_count:int,limit:int}} * - * @throws RestException + * @throws RestException 400 + * @throws RestException 403 + * @throws RestException 404 + * @throws RestException 503 */ public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $properties = '', $pagination_data = false) { @@ -176,9 +180,7 @@ class Thirdparties extends DolibarrApi $sql .= ", ".MAIN_DB_PREFIX."categorie_fournisseur as cc"; } } - $sql .= ", ".MAIN_DB_PREFIX."c_stcomm as st"; $sql .= " WHERE t.entity IN (".getEntity('societe').")"; - $sql .= " AND t.fk_stcomm = st.id"; if ($mode == 1) { $sql .= " AND t.client IN (1, 3)"; } elseif ($mode == 2) { @@ -188,7 +190,7 @@ class Thirdparties extends DolibarrApi } elseif ($mode == 4) { $sql .= " AND t.fournisseur IN (1)"; } - // Select thirdparties of given category + // Select third parties of a given category if ($category > 0) { if (!empty($mode) && $mode != 4) { $sql .= " AND c.fk_categorie = ".((int) $category)." AND c.fk_soc = t.rowid"; @@ -248,7 +250,7 @@ class Thirdparties extends DolibarrApi $i++; } } else { - throw new RestException(503, 'Error when retrieve thirdparties : '.$this->db->lasterror()); + throw new RestException(503, 'Error when retrieve third parties : '.$this->db->lasterror()); } if (!count($obj_ret)) { $message = ''; @@ -271,7 +273,7 @@ class Thirdparties extends DolibarrApi throw new RestException(404, $message); } - //if $pagination_data is true the response will contain element data with all values and element pagination with pagination data(total,page,limit) + //if $pagination_data is true, the response will contain element data with all values and element pagination with pagination data(total,page,limit) if ($pagination_data) { $totalsResult = $this->db->query($sqlTotals); $total = $this->db->fetch_object($totalsResult)->total;