Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop

This commit is contained in:
Laurent Destailleur 2020-09-01 16:36:26 +02:00
commit def2bd5d6d
11 changed files with 220 additions and 24 deletions

View File

@ -28,6 +28,12 @@
*/
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/commonobject.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncommreminder.class.php';
/**
@ -1954,7 +1960,7 @@ class ActionComm extends CommonObject
*/
public function sendEmailsReminder()
{
global $conf, $langs;
global $conf, $langs, $user;
$error = 0;
$this->output = '';
@ -1977,17 +1983,118 @@ class ActionComm extends CommonObject
dol_syslog(__METHOD__, LOG_DEBUG);
$this->db->begin();
$this->db->begin();
// TODO Scan events of type 'email' into table llx_actioncomm_reminder with status todo, send email, then set status to done
//Select all action comm reminder
$sql = "SELECT rowid as id FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
$sql .= " WHERE typeremind = 'email' AND status = 0";
$sql .= " AND dateremind <= '".$this->db->idate(dol_now())."'";
$sql .= $this->db->order("dateremind", "ASC");
$resql = $this->db->query($sql);
// Delete also very old past events (we do not keep more than 1 month record in past)
$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder WHERE dateremind < '".$this->db->jdate($now - (3600 * 24 * 32))."'";
$this->db->query($sql);
if ($resql) {
$formmail = new FormMail($this->db);
$actionCommReminder = new ActionCommReminder($this->db);
$this->db->commit();
while ($obj = $this->db->fetch_object($resql)){
$res = $actionCommReminder->fetch($obj->id);
if ($res < 0) {
$error++;
$errorsMsg[] = "Failed to load invoice ActionComm Reminder";
}
if (!$error)
{
//Select email template
$arraymessage = $formmail->getEMailTemplate($this->db, 'actioncomm_send', $user, $langs, (!empty($actionCommReminder->fk_email_template)) ? $actionCommReminder->fk_email_template : -1, 1);
// Load event
$res = $this->fetch($actionCommReminder->fk_actioncomm);
if ($res > 0)
{
// PREPARE EMAIL
// Make substitution in email content
$substitutionarray = getCommonSubstitutionArray($langs, 0, '', $this);
complete_substitutions_array($substitutionarray, $langs, $this);
// Content
$sendContent = make_substitutions($langs->trans($arraymessage->content), $substitutionarray);
//Topic
$sendTopic = (!empty($arraymessage->topic)) ? $arraymessage->topic : html_entity_decode($langs->trans('EventReminder'));
// Recipient
$recipient = new User($this->db);
$res = $recipient->fetch($actionCommReminder->fk_user);
if ($res > 0 && !empty($recipient->email)) $to = $recipient->email;
else {
$errorsMsg[] = "Failed to load recipient";
$error++;
}
// Sender
$from = $conf->global->MAIN_MAIL_EMAIL_FROM;
if (empty($from)) {
$errorsMsg[] = "Failed to load recipient";
$error++;
}
// Errors Recipient
$errors_to = $conf->global->MAIN_MAIL_ERRORS_TO;
// Mail Creation
$cMailFile = new CMailFile($sendTopic, $to, $from, $sendContent, array(), array(), array(), '', "", 0, 1, $errors_to, '', '', '', '', '');
// Sending Mail
if ($cMailFile->sendfile())
{
$actionCommReminder->status = $actionCommReminder::STATUS_DONE;
$res = $actionCommReminder->update($user);
if ($res < 0)
{
$errorsMsg[] = "Failed to update status of ActionComm Reminder";
$error++;
}
else $nbMailSend++;
}
else {
$errorsMsg[] = $cMailFile->error.' : '.$to;
$error++;
}
}
else {
$error++;
}
}
}
} else {
$error++;
}
if (!$error)
{
// Delete also very old past events (we do not keep more than 1 month record in past)
$sql = "DELETE FROM ".MAIN_DB_PREFIX."actioncomm_reminder";
$sql .= " WHERE dateremind < '".$this->db->idate($now - (3600 * 24 * 32))."'";
$resql = $this->db->query($sql);
if (!$resql) {
$errorsMsg[] = 'Failed to delete old reminders';
$error ++;
}
}
if (!$error) {
$this->db->commit();
return 0;
}
else {
$this->db->rollback();
return (!empty($errorsMsg)) ? end($errorsMsg) : $error;
}
return $error;
}
/**

View File

@ -142,7 +142,7 @@ if (!empty($conf->global->MAIN_SEARCH_FORM_ON_HOME_AREAS)) // This is useles
/*
* Draft proposals
* Draft customer proposals
*/
if (!empty($conf->propal->enabled) && $user->rights->propal->lire)
{
@ -256,7 +256,7 @@ if (!empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposa
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th colspan="3">'.$langs->trans("SupplierProposalsDraft").($num ? '<span class="badge marginleftonlyshort">'.$num.'</span>' : '').'</th></tr>';
print '<th colspan="3">'.$langs->trans("SupplierProposalsDraft").' <a href="'.DOL_URL_ROOT.'/supplier_proposal/list.php?search_status=0"><span class="badge">'.$num.'</span></a></th></tr>';
if ($num > 0)
{
@ -309,7 +309,7 @@ if (!empty($conf->supplier_proposal->enabled) && $user->rights->supplier_proposa
/*
* Draft orders
* Draft customer orders
*/
if (!empty($conf->commande->enabled) && $user->rights->commande->lire)
{
@ -338,7 +338,7 @@ if (!empty($conf->commande->enabled) && $user->rights->commande->lire)
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th colspan="3">'.$langs->trans("DraftOrders").($num ? '<span class="badge marginleftonlyshort">'.$num.'</span>' : '').'</th></tr>';
print '<th colspan="3">'.$langs->trans("DraftOrders").' <a href="'.DOL_URL_ROOT.'/commande/list.php?search_status=0"><span class="badge">'.$num.'</span></a></th></tr>';
if ($num > 0)
{
@ -425,7 +425,7 @@ if ((!empty($conf->fournisseur->enabled) && empty($conf->global->MAIN_USE_NEW_SU
print '<div class="div-table-responsive-no-min">';
print '<table class="noborder centpercent">';
print '<tr class="liste_titre">';
print '<th colspan="3">'.$langs->trans("DraftSuppliersOrders").($num ? '<span class="badge marginleftonlyshort">'.$num.'</span>' : '').'</th></tr>';
print '<th colspan="3">'.$langs->trans("DraftSuppliersOrders").' <a href="'.DOL_URL_ROOT.'/fourn/commande/list.php?search_status=0"><span class="badge">'.$num.'</span></a></th></tr>';
if ($num > 0)
{

View File

@ -1253,6 +1253,8 @@ class FormMail extends Form
$defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendShipping");
} elseif ($type_template == 'fichinter_send') {
$defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendFichInter");
} elseif ($type_template == 'actioncomm_send') {
$defaultmessage = $outputlangs->transnoentities("PredefinedMailContentSendActionComm");
} elseif (!empty($type_template)) {
$defaultmessage = $outputlangs->transnoentities("PredefinedMailContentGeneric");
}

View File

@ -6244,6 +6244,13 @@ function getCommonSubstitutionArray($outputlangs, $onlykey = 0, $exclude = null,
if (is_object($object) && $object->element == 'commande') $substitutionarray['__URL_ORDER__'] = DOL_MAIN_URL_ROOT."/commande/card.php?id=".$object->id;
if (is_object($object) && $object->element == 'facture') $substitutionarray['__URL_INVOICE__'] = DOL_MAIN_URL_ROOT."/compta/facture/card.php?id=".$object->id;
}
if (is_object($object) && $object->element == 'action')
{
$substitutionarray['__EVENT_LABEL__'] = $object->label;
$substitutionarray['__EVENT_DATE__'] = dol_print_date($object->datep, '%A %d %b %Y');
$substitutionarray['__EVENT_TIME__'] = dol_print_date($object->datep, '%H:%M:%S');
}
}
}
if (empty($exclude) || !in_array('objectamount', $exclude))

View File

@ -165,4 +165,5 @@ TimeType=Duration type
ReminderType=Callback type
AddReminder=Create an automatic reminder notification for this event
ErrorReminderActionCommCreation=Error creating the reminder notification for this event
BrowserPush=Browser Notification
BrowserPush=Browser Notification
EventReminder=Event Reminder

View File

@ -117,6 +117,7 @@ SendingEmailOnMemberValidation=Sending email on new member validation
SendingEmailOnNewSubscription=Sending email on new subscription
SendingReminderForExpiredSubscription=Sending reminder for expired subscriptions
SendingEmailOnCancelation=Sending email on cancelation
SendingReminderActionComm=Sending reminder for agenda event
# Topic of email templates
YourMembershipRequestWasReceived=Your membership was received.
YourMembershipWasValidated=Your membership was validated

View File

@ -99,6 +99,7 @@ PredefinedMailContentSendShipping=__(Hello)__\n\nPlease find shipping __REF__ at
PredefinedMailContentSendFichInter=__(Hello)__\n\nPlease find intervention __REF__ attached\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentLink=You can click on the link below to make your payment if it is not already done.\n\n%s\n\n
PredefinedMailContentGeneric=__(Hello)__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentSendActionComm=Event reminder "__EVENT_LABEL__" on __EVENT_DATE__ at __EVENT_TIME__<br><br>This is an automatic message, please do not reply.
DemoDesc=Dolibarr is a compact ERP/CRM supporting several business modules. A demo showcasing all modules makes no sense as this scenario never occurs (several hundred available). So, several demo profiles are available.
ChooseYourDemoProfil=Choose the demo profile that best suits your needs...
ChooseYourDemoProfilMore=...or build your own profile<br>(manual module selection)

View File

@ -160,9 +160,10 @@ DateStartPlusOne=Date de début + 1 heure
SetAllEventsToTodo=Réglez tous les événements à "A faire"
SetAllEventsToInProgress=Définir tous les événements à "En cours"
SetAllEventsToFinished=Définir tous les événements sur "Terminés"
ReminderTime=Reminder period before the event
TimeType=Duration type
ReminderType=Callback type
AddReminder=Create an automatic reminder notification for this event
ErrorReminderActionCommCreation=Error creating the reminder notification for this event
BrowserPush=Browser Notification
ReminderTime=Délai de rappel avant l'événement
TimeType=Type de durée
ReminderType=Type de rappel
AddReminder=Créer une notification de rappel automatique pour cet évènement
ErrorReminderActionCommCreation=Erreur lors de la création de la notification de rappel de cet événement
BrowserPush=Notification navigateur
EventReminder=Rappel événement

View File

@ -97,8 +97,12 @@ PredefinedMailContentSendSupplierOrder=__(Hello)__\n\nVeuillez trouver, ci-joint
PredefinedMailContentSendSupplierInvoice=__(Hello)__\n\nVeuillez trouver, ci-joint, la facture __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentSendShipping=__(Hello)__\n\nVeuillez trouver, ci-joint, le bon d'expédition __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentSendFichInter=__(Hello)__\n\nVeuillez trouver, ci-joint, la fiche intervention __REF__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentThirdparty=__(Hello)__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentContact=__(Hello)__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentUser=__(Hello)__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentLink=Vous pouvez cliquer sur le lien ci-dessous pour effectuer votre paiement si ce n'est déjà fait.\n\n%s\n\n
PredefinedMailContentGeneric=__(Hello)__\n\n\n__(Sincerely)__\n\n__USER_SIGNATURE__
PredefinedMailContentSendActionComm=Rappel événement "__EVENT_LABEL__" le __EVENT_DATE__ à __EVENT_TIME__<br><br>Ceci est un message automatique, merci de ne pas répondre.
DemoDesc=Dolibarr est un logiciel de gestion proposant plusieurs modules métiers. Une démonstration qui inclut tous ces modules n'a pas de sens car ce cas n'existe jamais (plusieurs centaines de modules disponibles). Aussi, quelques profils type de démo sont disponibles.
ChooseYourDemoProfil=Veuillez choisir le profil de démonstration qui correspond le mieux à votre activité…
ChooseYourDemoProfilMore=...ou construisez votre propre profil<br>(sélection manuelle des modules)

View File

@ -85,7 +85,7 @@ class Thirdparties extends DolibarrApi
* @param string $email Email of third party to load
* @return array|mixed data without useless information
*
* @url GET byEmail/{email}
* @url GET email/{email}
*
* @throws RestException
*/

View File

@ -1,6 +1,6 @@
<?php
/* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
/* Copyright (C) 2030 Thibault FOUCART <support@ptibogxiv.net>
/* Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
*
* 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
@ -143,13 +143,13 @@ class Users extends DolibarrApi
/**
* Get properties of an user object
* Return an array with user informations
*
* @param int $id ID of user
* @param int $includepermissions Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)
* @return array|mixed data without useless information
*
* @throws RestException
* @throws RestException 401 Insufficient rights
* @throws RestException 404 User or group not found
*/
public function get($id, $includepermissions = 0)
{
@ -175,6 +175,78 @@ class Users extends DolibarrApi
return $this->_cleanObjectDatas($this->useraccount);
}
/**
* Get properties of an user object by login
*
* @param string $login Login of user
* @param int $includepermissions Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)
* @return array|mixed data without useless information
*
* @url GET login/{login}
*
* @throws RestException 401 Insufficient rights
* @throws RestException 404 User or group not found
*/
public function getByLogin($login, $includepermissions = 0)
{
//if (!DolibarrApiAccess::$user->rights->user->user->lire) {
//throw new RestException(401);
//}
$result = $this->useraccount->fetch('', $login);
if (!$result)
{
throw new RestException(404, 'User not found');
}
if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user'))
{
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if ($includepermissions) {
$this->useraccount->getRights();
}
return $this->_cleanObjectDatas($this->useraccount);
}
/**
* Get properties of an user object by Email
*
* @param string $email Email of user
* @param int $includepermissions Set this to 1 to have the array of permissions loaded (not done by default for performance purpose)
* @return array|mixed data without useless information
*
* @url GET email/{email}
*
* @throws RestException 401 Insufficient rights
* @throws RestException 404 User or group not found
*/
public function getByEmail($email, $includepermissions = 0)
{
//if (!DolibarrApiAccess::$user->rights->user->user->lire) {
//throw new RestException(401);
//}
$result = $this->useraccount->fetch('', '', '', 0, -1, $email);
if (!$result)
{
throw new RestException(404, 'User not found');
}
if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user'))
{
throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
}
if ($includepermissions) {
$this->useraccount->getRights();
}
return $this->_cleanObjectDatas($this->useraccount);
}
/**
* Get properties of user connected
*