diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 86a64084532..14f43f24034 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -11372,3 +11372,720 @@ function dolForgeCriteriaCallback($matches) return $db->escape($operand).' '.$db->escape($operator)." ".$tmpescaped; } + + + +/** + * Get timeline icon + * @param ActionComm $actionstatic actioncomm + * @param array $histo histo + * @param int $key key + * @return string + */ +function getTimelineIcon($actionstatic, &$histo, $key) +{ + global $conf, $langs; + $out = ''."\n"; + $iconClass = 'fa fa-comments'; + $img_picto = ''; + $colorClass = ''; + $pictoTitle = ''; + + if ($histo[$key]['percent'] == -1) { + $colorClass = 'timeline-icon-not-applicble'; + $pictoTitle = $langs->trans('StatusNotApplicable'); + } elseif ($histo[$key]['percent'] == 0) { + $colorClass = 'timeline-icon-todo'; + $pictoTitle = $langs->trans('StatusActionToDo').' (0%)'; + } elseif ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100) { + $colorClass = 'timeline-icon-in-progress'; + $pictoTitle = $langs->trans('StatusActionInProcess').' ('.$histo[$key]['percent'].'%)'; + } elseif ($histo[$key]['percent'] >= 100) { + $colorClass = 'timeline-icon-done'; + $pictoTitle = $langs->trans('StatusActionDone').' (100%)'; + } + + if ($actionstatic->code == 'AC_TICKET_CREATE') { + $iconClass = 'fa fa-ticket'; + } elseif ($actionstatic->code == 'AC_TICKET_MODIFY') { + $iconClass = 'fa fa-pencilxxx'; + } elseif ($actionstatic->code == 'TICKET_MSG') { + $iconClass = 'fa fa-comments'; + } elseif ($actionstatic->code == 'TICKET_MSG_PRIVATE') { + $iconClass = 'fa fa-mask'; + } elseif (!empty($conf->global->AGENDA_USE_EVENT_TYPE)) { + if ($actionstatic->type_picto) { + $img_picto = img_picto('', $actionstatic->type_picto); + } else { + if ($actionstatic->type_code == 'AC_RDV') { + $iconClass = 'fa fa-handshake'; + } elseif ($actionstatic->type_code == 'AC_TEL') { + $iconClass = 'fa fa-phone'; + } elseif ($actionstatic->type_code == 'AC_FAX') { + $iconClass = 'fa fa-fax'; + } elseif ($actionstatic->type_code == 'AC_EMAIL') { + $iconClass = 'fa fa-envelope'; + } elseif ($actionstatic->type_code == 'AC_INT') { + $iconClass = 'fa fa-shipping-fast'; + } elseif ($actionstatic->type_code == 'AC_OTH_AUTO') { + $iconClass = 'fa fa-robot'; + } elseif (!preg_match('/_AUTO/', $actionstatic->type_code)) { + $iconClass = 'fa fa-robot'; + } + } + } + + $out .= ''.$img_picto.''."\n"; + return $out; +} + +/** + * getActionCommEcmList + * + * @param ActionComm $object Object ActionComm + * @return array Array of documents in index table + */ +function getActionCommEcmList($object) +{ + global $conf, $db; + + $documents = array(); + + $sql = 'SELECT ecm.rowid as id, ecm.src_object_type, ecm.src_object_id, ecm.filepath, ecm.filename'; + $sql .= ' FROM '.MAIN_DB_PREFIX.'ecm_files ecm'; + $sql .= " WHERE ecm.filepath = 'agenda/".((int) $object->id)."'"; + //$sql.= " ecm.src_object_type = '".$db->escape($object->element)."' AND ecm.src_object_id = ".((int) $object->id); // Old version didn't add object_type during upload + $sql .= ' ORDER BY ecm.position ASC'; + + $resql = $db->query($sql); + if ($resql) { + if ($db->num_rows($resql)) { + while ($obj = $db->fetch_object($resql)) { + $documents[$obj->id] = $obj; + } + } + } + + return $documents; +} + + +/** + * Show html area with actions in messaging format. + * Note: Global parameter $param must be defined. + * + * @param Conf $conf Object conf + * @param Translate $langs Object langs + * @param DoliDB $db Object db + * @param mixed $filterobj Filter on object Adherent|Societe|Project|Product|CommandeFournisseur|Dolresource|Ticket|... to list events linked to an object + * @param Contact $objcon Filter on object contact to filter events on a contact + * @param int $noprint Return string but does not output it + * @param string $actioncode Filter on actioncode + * @param string $donetodo Filter on event 'done' or 'todo' or ''=nofilter (all). + * @param array $filters Filter on other fields + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @return string|void Return html part or void if noprint is 1 + */ +function show_actions_messaging($conf, $langs, $db, $filterobj, $objcon = '', $noprint = 0, $actioncode = '', $donetodo = 'done', $filters = array(), $sortfield = 'a.datep,a.id', $sortorder = 'DESC') +{ + global $user, $conf; + global $form; + + global $param, $massactionbutton; + + dol_include_once('/comm/action/class/actioncomm.class.php'); + + // Check parameters + if (!is_object($filterobj) && !is_object($objcon)) { + dol_print_error('', 'BadParameter'); + } + + $histo = array(); + $numaction = 0; + $now = dol_now(); + + $sortfield_list = explode(',', $sortfield); + $sortfield_label_list = array('a.id' => 'id', 'a.datep' => 'dp', 'a.percent' => 'percent'); + $sortfield_new_list = array(); + foreach ($sortfield_list as $sortfield_value) { + $sortfield_new_list[] = $sortfield_label_list[trim($sortfield_value)]; + } + $sortfield_new = implode(',', $sortfield_new_list); + + if (isModEnabled('agenda')) { + // Search histo on actioncomm + if (is_object($objcon) && $objcon->id > 0) { + $sql = "SELECT DISTINCT a.id, a.label as label,"; + } else { + $sql = "SELECT a.id, a.label as label,"; + } + $sql .= " a.datep as dp,"; + $sql .= " a.note as message,"; + $sql .= " a.datep2 as dp2,"; + $sql .= " a.percent as percent, 'action' as type,"; + $sql .= " a.fk_element, a.elementtype,"; + $sql .= " a.fk_contact,"; + $sql .= " c.code as acode, c.libelle as alabel, c.picto as apicto,"; + $sql .= " u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; + if (is_object($filterobj) && get_class($filterobj) == 'Societe') { + $sql .= ", sp.lastname, sp.firstname"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { + $sql .= ", m.lastname, m.firstname"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { + $sql .= ", o.ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { + $sql .= ", o.ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { + $sql .= ", o.ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { + $sql .= ", o.ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { + $sql .= ", o.ref"; + } + $sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_action"; + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action = c.id"; + + $force_filter_contact = false; + if (is_object($objcon) && $objcon->id > 0) { + $force_filter_contact = true; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as r ON a.id = r.fk_actioncomm"; + $sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".((int) $objcon->id); + } + + if (is_object($filterobj) && get_class($filterobj) == 'Societe') { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."socpeople as sp ON a.fk_contact = sp.rowid"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Dolresource') { + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."element_resources as er"; + $sql .= " ON er.resource_type = 'dolresource'"; + $sql .= " AND er.element_id = a.id"; + $sql .= " AND er.resource_id = ".((int) $filterobj->id); + } elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { + $sql .= ", ".MAIN_DB_PREFIX."adherent as m"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { + $sql .= ", ".MAIN_DB_PREFIX."commande_fournisseur as o"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { + $sql .= ", ".MAIN_DB_PREFIX."product as o"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { + $sql .= ", ".MAIN_DB_PREFIX."ticket as o"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { + $sql .= ", ".MAIN_DB_PREFIX."bom_bom as o"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { + $sql .= ", ".MAIN_DB_PREFIX."contrat as o"; + } + + $sql .= " WHERE a.entity IN (".getEntity('agenda').")"; + if ($force_filter_contact === false) { + if (is_object($filterobj) && in_array(get_class($filterobj), array('Societe', 'Client', 'Fournisseur')) && $filterobj->id) { + $sql .= " AND a.fk_soc = ".((int) $filterobj->id); + } elseif (is_object($filterobj) && get_class($filterobj) == 'Project' && $filterobj->id) { + $sql .= " AND a.fk_project = ".((int) $filterobj->id); + } elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { + $sql .= " AND a.fk_element = m.rowid AND a.elementtype = 'member'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { + $sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'order_supplier'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { + $sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'product'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { + $sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'ticket'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') { + $sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'bom'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') { + $sql .= " AND a.fk_element = o.rowid AND a.elementtype = 'contract'"; + if ($filterobj->id) { + $sql .= " AND a.fk_element = ".((int) $filterobj->id); + } + } + } + + // Condition on actioncode + if (!empty($actioncode)) { + if (empty($conf->global->AGENDA_USE_EVENT_TYPE)) { + if ($actioncode == 'AC_NON_AUTO') { + $sql .= " AND c.type != 'systemauto'"; + } elseif ($actioncode == 'AC_ALL_AUTO') { + $sql .= " AND c.type = 'systemauto'"; + } else { + if ($actioncode == 'AC_OTH') { + $sql .= " AND c.type != 'systemauto'"; + } elseif ($actioncode == 'AC_OTH_AUTO') { + $sql .= " AND c.type = 'systemauto'"; + } + } + } else { + if ($actioncode == 'AC_NON_AUTO') { + $sql .= " AND c.type != 'systemauto'"; + } elseif ($actioncode == 'AC_ALL_AUTO') { + $sql .= " AND c.type = 'systemauto'"; + } else { + $sql .= " AND c.code = '".$db->escape($actioncode)."'"; + } + } + } + if ($donetodo == 'todo') { + $sql .= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))"; + } elseif ($donetodo == 'done') { + $sql .= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))"; + } + if (is_array($filters) && $filters['search_agenda_label']) { + $sql .= natural_search('a.label', $filters['search_agenda_label']); + } + } + + // Add also event from emailings. TODO This should be replaced by an automatic event ? May be it's too much for very large emailing. + if (isModEnabled('mailing') && !empty($objcon->email) + && (empty($actioncode) || $actioncode == 'AC_OTH_AUTO' || $actioncode == 'AC_EMAILING')) { + $langs->load("mails"); + + $sql2 = "SELECT m.rowid as id, m.titre as label, mc.date_envoi as dp, mc.date_envoi as dp2, '100' as percent, 'mailing' as type"; + $sql2 .= ", null as fk_element, '' as elementtype, null as contact_id"; + $sql2 .= ", 'AC_EMAILING' as acode, '' as alabel, '' as apicto"; + $sql2 .= ", u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname"; // User that valid action + if (is_object($filterobj) && get_class($filterobj) == 'Societe') { + $sql2 .= ", '' as lastname, '' as firstname"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') { + $sql2 .= ", '' as lastname, '' as firstname"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') { + $sql2 .= ", '' as ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Product') { + $sql2 .= ", '' as ref"; + } elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') { + $sql2 .= ", '' as ref"; + } + $sql2 .= " FROM ".MAIN_DB_PREFIX."mailing as m, ".MAIN_DB_PREFIX."mailing_cibles as mc, ".MAIN_DB_PREFIX."user as u"; + $sql2 .= " WHERE mc.email = '".$db->escape($objcon->email)."'"; // Search is done on email. + $sql2 .= " AND mc.statut = 1"; + $sql2 .= " AND u.rowid = m.fk_user_valid"; + $sql2 .= " AND mc.fk_mailing=m.rowid"; + } + + if (!empty($sql) && !empty($sql2)) { + $sql = $sql." UNION ".$sql2; + } elseif (empty($sql) && !empty($sql2)) { + $sql = $sql2; + } + + // TODO Add limit in nb of results + if ($sql) { // May not be defined if module Agenda is not enabled and mailing module disabled too + $sql .= $db->order($sortfield_new, $sortorder); + + dol_syslog("function.lib::show_actions_messaging", LOG_DEBUG); + $resql = $db->query($sql); + if ($resql) { + $i = 0; + $num = $db->num_rows($resql); + + while ($i < $num) { + $obj = $db->fetch_object($resql); + + if ($obj->type == 'action') { + $contactaction = new ActionComm($db); + $contactaction->id = $obj->id; + $result = $contactaction->fetchResources(); + if ($result < 0) { + dol_print_error($db); + setEventMessage("actions.lib::show_actions_messaging Error fetch ressource", 'errors'); + } + + //if ($donetodo == 'todo') $sql.= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))"; + //elseif ($donetodo == 'done') $sql.= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))"; + $tododone = ''; + if (($obj->percent >= 0 and $obj->percent < 100) || ($obj->percent == -1 && $obj->datep > $now)) { + $tododone = 'todo'; + } + + $histo[$numaction] = array( + 'type'=>$obj->type, + 'tododone'=>$tododone, + 'id'=>$obj->id, + 'datestart'=>$db->jdate($obj->dp), + 'dateend'=>$db->jdate($obj->dp2), + 'note'=>$obj->label, + 'message'=>$obj->message, + 'percent'=>$obj->percent, + + 'userid'=>$obj->user_id, + 'login'=>$obj->user_login, + 'userfirstname'=>$obj->user_firstname, + 'userlastname'=>$obj->user_lastname, + 'userphoto'=>$obj->user_photo, + + 'contact_id'=>$obj->fk_contact, + 'socpeopleassigned' => $contactaction->socpeopleassigned, + 'lastname'=>$obj->lastname, + 'firstname'=>$obj->firstname, + 'fk_element'=>$obj->fk_element, + 'elementtype'=>$obj->elementtype, + // Type of event + 'acode'=>$obj->acode, + 'alabel'=>$obj->alabel, + 'libelle'=>$obj->alabel, // deprecated + 'apicto'=>$obj->apicto + ); + } else { + $histo[$numaction] = array( + 'type'=>$obj->type, + 'tododone'=>'done', + 'id'=>$obj->id, + 'datestart'=>$db->jdate($obj->dp), + 'dateend'=>$db->jdate($obj->dp2), + 'note'=>$obj->label, + 'message'=>$obj->message, + 'percent'=>$obj->percent, + 'acode'=>$obj->acode, + + 'userid'=>$obj->user_id, + 'login'=>$obj->user_login, + 'userfirstname'=>$obj->user_firstname, + 'userlastname'=>$obj->user_lastname, + 'userphoto'=>$obj->user_photo + ); + } + + $numaction++; + $i++; + } + } else { + dol_print_error($db); + } + } + + // Set $out to sow events + $out = ''; + + if (!isModEnabled('agenda')) { + $langs->loadLangs(array("admin", "errors")); + $out = info_admin($langs->trans("WarningModuleXDisabledSoYouMayMissEventHere", $langs->transnoentitiesnoconv("Module2400Name")), 0, 0, 'warning'); + } + + if (isModEnabled('agenda') || (isModEnabled('mailing') && !empty($objcon->email))) { + $delay_warning = $conf->global->MAIN_DELAY_ACTIONS_TODO * 24 * 60 * 60; + + require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php'; + include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php'; + require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php'; + + $formactions = new FormActions($db); + + $actionstatic = new ActionComm($db); + $userstatic = new User($db); + $contactstatic = new Contact($db); + $userGetNomUrlCache = array(); + + $out .= '