From 4d01969a4c6bc88796b96f866c0dd79b9a58365d Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Wed, 2 Feb 2022 16:45:12 +0100 Subject: [PATCH 01/14] Societe: add method to find parent companies --- htdocs/societe/class/societe.class.php | 31 ++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 89eeeaca8e5..8d0a836ae86 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3462,6 +3462,37 @@ class Societe extends CommonObject } } + /** + * Get parents for company + * + * @param int $company_id ID of company to search parent + * @param array $parents List of companies ID found + * @return array + */ + public function getParentsForCompany($company_id, $parents = []) + { + global $langs; + + if ($company_id > 0) { + $sql = "SELECT parent FROM " . MAIN_DB_PREFIX . "societe WHERE rowid = $company_id"; + $resql = $this->db->query($sql); + if ($resql) { + if ($obj = $this->db->fetch_object($resql)) { + $parent = $obj->parent; + if ($parent > 0 && !in_array($parent, $parents)) { + $parents[] = $parent; + return $this->getParentsForCompany($parent, $parents); + } else { + return $parents; + } + } + $this->db->free($resql); + } else { + setEventMessage($langs->trans('GetCompanyParentsError', $this->db->lasterror()), 'errors'); + } + } + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Returns if a profid sould be verified to be unique From a14a63fdad4d0f13469c9424c872405fb03ab526 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 3 Feb 2022 10:01:20 +0100 Subject: [PATCH 02/14] Contrat->getListOfContracts(): allow to sort contracts by contract status, product category, and line status. --- htdocs/contrat/class/contrat.class.php | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index 4e4437c1b2c..e6c73164f26 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2130,19 +2130,27 @@ class Contrat extends CommonObject /** * Return list of other contracts for same company than current contract * - * @param string $option 'all' or 'others' - * @return array|int Array of contracts id or <0 if error + * @param string $option 'all' or 'others' + * @param array $status sort contracts having these status + * @param array $product_categories sort contracts containing these product categories + * @param array $line_status sort contracts where lines have these status + * @return array|int Array of contracts id or <0 if error */ - public function getListOfContracts($option = 'all') + public function getListOfContracts($option = 'all', $status = [], $product_categories = [], $line_status = [] ) { $tab = array(); $sql = "SELECT c.rowid, c.ref"; $sql .= " FROM ".MAIN_DB_PREFIX."contrat as c"; - $sql .= " WHERE fk_soc =".((int) $this->socid); - if ($option == 'others') { - $sql .= " AND c.rowid <> ".((int) $this->id); + if (!empty($product_categories)) { + $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."contratdet as cd ON cd.fk_contrat = c.rowid"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON cp.fk_product = cd.fk_product AND cp.fk_categorie IN (".implode(', ', $product_categories).")"; } + $sql .= " WHERE c.fk_soc =".((int) $this->socid); + $sql .= ($option == 'others') ? " AND c.rowid <> ".((int) $this->id) : ""; + $sql .= (!empty($status)) ? " AND c.statut IN (".implode(', ', $status).")" : ""; + $sql .= (!empty($line_status)) ? " AND cd.statut IN (".implode(', ', $line_status).")" : ""; + $sql .= " GROUP BY c.rowid"; dol_syslog(get_class($this)."::getOtherContracts()", LOG_DEBUG); $resql = $this->db->query($sql); From 90ab7da40d37120caca3373a5b2256d30fca3872 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 3 Feb 2022 11:01:07 +0100 Subject: [PATCH 03/14] Workflow : sort contracts when automatic linking to ticket. Introduces constants TICKET_PRODUCT_CATEGORY and WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS. Rename constant TICKET_AUTO_ASSIGN_CONTRACT_CREATE to WORKFLOW_TICKET_LINK_CONTRACT. --- ...e_20_modWorkflow_WorkflowManager.class.php | 35 +++++++++++++++++++ .../install/mysql/migration/15.0.0-16.0.0.sql | 2 ++ htdocs/langs/en_US/interventions.lang | 1 + htdocs/langs/en_US/ticket.lang | 2 ++ htdocs/ticket/card.php | 17 +-------- 5 files changed, 41 insertions(+), 16 deletions(-) diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 048dc170c0a..1e98ec885bd 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -424,6 +424,41 @@ class InterfaceWorkflowManager extends DolibarrTriggers } } + if ($action == 'TICKET_CREATE') { + dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); + // Auto link contract + if (!empty($conf->contract->enabled) && !empty($conf->ticket->enabled) && !empty($conf->ficheinter->enabled) && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_LINK_CONTRACT) && !empty($conf->global->TICKET_PRODUCT_CATEGORY) && !empty($object->fk_soc)) { + + $societe = new Societe($this->db); + $company_ids = (empty($conf->global->WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS)) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]); + + $contrat = new Contrat($this->db); + $number_contracts_found = 0; + foreach ($company_ids as $company_id) { + $contrat->socid = $company_id; + + $list = $contrat->getListOfContracts($option = 'all', $status = [Contrat::STATUS_DRAFT, Contrat::STATUS_VALIDATED], $product_categories = [$conf->global->TICKET_PRODUCT_CATEGORY], $line_status = [ContratLigne::STATUS_INITIAL, ContratLigne::STATUS_OPEN]); + if (is_array($list) && !empty($list)) { + $number_contracts_found = count($list); + if ($number_contracts_found == 1) { + $contractid = $list[0]->id; + $object->setContract($contractid); + break; + } elseif ($number_contracts_found > 1) { + foreach($list as $linked_contract) { + $object->setContract($linked_contract->id); + // don't set '$contractid' so it is not used when creating an intervention. + } + setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings'); + break; + } + } + } + if ($number_contracts_found == 0) { + setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs'); + } + } + } return 0; } diff --git a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql index 5e9a0250a38..042ae751e06 100644 --- a/htdocs/install/mysql/migration/15.0.0-16.0.0.sql +++ b/htdocs/install/mysql/migration/15.0.0-16.0.0.sql @@ -110,6 +110,8 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) value ALTER TABLE llx_ticket ADD COLUMN date_last_msg_sent datetime AFTER date_read; +UPDATE llx_const SET name = 'WORKFLOW_TICKET_LINK_CONTRACT' WHERE name = 'TICKET_AUTO_ASSIGN_CONTRACT_CREATE'; + CREATE TABLE llx_stock_mouvement_extrafields ( rowid integer AUTO_INCREMENT PRIMARY KEY, tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, diff --git a/htdocs/langs/en_US/interventions.lang b/htdocs/langs/en_US/interventions.lang index ef5df43e546..7c117fcd1f2 100644 --- a/htdocs/langs/en_US/interventions.lang +++ b/htdocs/langs/en_US/interventions.lang @@ -66,3 +66,4 @@ RepeatableIntervention=Template of intervention ToCreateAPredefinedIntervention=To create a predefined or recurring intervention, create a common intervention and convert it into intervention template ConfirmReopenIntervention=Are you sure you want to open back the intervention %s? GenerateInter=Generate intervention +FichinterNoContractLinked=Intervention %s has been created without a linked contract. diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index 310ac8dd7f6..204f7c0ed60 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -258,6 +258,8 @@ TicketNotCreatedFromPublicInterface=Not available. Ticket was not created from p ErrorTicketRefRequired=Ticket reference name is required TicketsDelayForFirstResponseTooLong=Too much time elapsed since ticket opening without any answer. TicketsDelayFromLastResponseTooLong=Too much time elapsed since last answer on this ticket. +TicketNoContractFoundToLink=No contract was found to be automatically linked to this ticket. Please link a contract manually. +TicketManyContractsLinked=Many contracts have been automatically linked to this ticket. Make sure to verify which should be chosen. # # Logs diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index aa34c07c361..9afca68c2eb 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -255,22 +255,6 @@ if (empty($reshook)) { $object->add_contact($user->id, "SUPPORTTEC", 'internal'); } - // Auto assign contrat - $contractid = 0; - if (!empty($conf->global->TICKET_AUTO_ASSIGN_CONTRACT_CREATE)) { - $contrat = new Contrat($db); - $contrat->socid = $object->fk_soc; - $list = $contrat->getListOfContracts(); - - if (is_array($list) && !empty($list)) { - if (count($list) == 1) { - $contractid = $list[0]->id; - $object->setContract($contractid); - } else { - } - } - } - // Auto create fiche intervention if (!empty($conf->global->TICKET_AUTO_CREATE_FICHINTER_CREATE)) { $fichinter = new Fichinter($db); @@ -292,6 +276,7 @@ if (empty($reshook)) { setEventMessages($fichinter->error, null, 'errors'); } } + } if (!$error) { From 8d997de3bbbf8ed9d599ca3e8db4130f8a2f3797 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 8 Feb 2022 11:54:52 +0100 Subject: [PATCH 04/14] add options in workflow admin panel : WORKFLOW_TICKET_LINK_CONTRACT, WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS --- htdocs/admin/workflow.php | 21 ++++++++++++++++++++- htdocs/core/modules/modWorkflow.class.php | 4 +++- htdocs/langs/en_US/workflow.lang | 7 ++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/htdocs/admin/workflow.php b/htdocs/admin/workflow.php index a58c3378ecd..da82f163a7f 100644 --- a/htdocs/admin/workflow.php +++ b/htdocs/admin/workflow.php @@ -161,7 +161,21 @@ $workflowcodes = array( 'position' => 90, 'enabled' => ! empty($conf->expedition->enabled) && ! empty($conf->facture->enabled), 'picto' => 'shipment' - ) + ), + + // Automatic link ticket -> contract + 'WORKFLOW_TICKET_LINK_CONTRACT' => array( + 'family' => 'link_ticket', + 'position' => 75, + 'enabled' => ! empty($conf->ticket->enabled) && ! empty($conf->contract->enabled), + 'picto' => 'ticket' + ), + 'WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS' => array( + 'family' => 'link_ticket', + 'position' => 76, + 'enabled' => ! empty($conf->ticket->enabled) && ! empty($conf->contract->enabled), + 'picto' => 'ticket' + ), ); if (!empty($conf->modules_parts['workflow']) && is_array($conf->modules_parts['workflow'])) { @@ -237,6 +251,11 @@ foreach ($workflowcodes as $key => $params) { if ($reg[1] == 'shipping') { $header .= ' - '.$langs->trans('Shipment'); } + } elseif (preg_match('/link_(.*)/', $params['family'], $reg)) { + $header = $langs->trans("AutomaticLinking"); + if ($reg[1] == 'ticket') { + $header .= ' - '.$langs->trans('Ticket'); + } } else { $header = $langs->trans("Description"); } diff --git a/htdocs/core/modules/modWorkflow.class.php b/htdocs/core/modules/modWorkflow.class.php index 4122f347664..dc05bf9dc66 100644 --- a/htdocs/core/modules/modWorkflow.class.php +++ b/htdocs/core/modules/modWorkflow.class.php @@ -93,7 +93,9 @@ class modWorkflow extends DolibarrModules 6=>array('WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION', 'chaine', '1', 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION', 0, 'current', 0), 7=>array('WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED', 'chaine', '1', 'WORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED', 0, 'current', 0), 8=>array('WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER', 'chaine', '1', 'WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER', 0, 'current', 0), - 9=>array('WORKFLOW_BILL_ON_RECEPTION', 'chaine', '1', 'WORKFLOW_BILL_ON_RECEPTION', 0, 'current', 0) + 9=>array('WORKFLOW_BILL_ON_RECEPTION', 'chaine', '1', 'WORKFLOW_BILL_ON_RECEPTION', 0, 'current', 0), + 10=>array('WORKFLOW_TICKET_LINK_CONTRACT', 'chaine', '0', 'Automatically link a ticket to available contracts', 0, 'current', 0), + 11=>array('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS', 'chaine', '0', 'Search among parent companies contracts when automatically linking a ticket to available contracts', 0, 'current', 0) ); // Boxes diff --git a/htdocs/langs/en_US/workflow.lang b/htdocs/langs/en_US/workflow.lang index b65f8449fef..6ddf8d9c6a3 100644 --- a/htdocs/langs/en_US/workflow.lang +++ b/htdocs/langs/en_US/workflow.lang @@ -22,9 +22,14 @@ descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase o descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update) # Autoclassify purchase invoice descWORKFLOW_BILL_ON_RECEPTION=Classify receptions to "billed" when a linked supplier order is validated +# Automatically link ticket to contract +descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty +descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies # Autoclose intervention descWORKFLOW_TICKET_CLOSE_INTERVENTION=Close all interventions linked to the ticket when a ticket is closed AutomaticCreation=Automatic creation AutomaticClassification=Automatic classification # Autoclassify shipment -descWORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE=Classify linked source shipment as closed when customer invoice is validated \ No newline at end of file +descWORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE=Classify linked source shipment as closed when customer invoice is validated +AutomaticClosing=Automatic closing +AutomaticLinking=Automatic linking From 2cf433019e25ff0e9bfd8fa183b1797fb8bd3e20 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 3 Feb 2022 16:03:25 +0100 Subject: [PATCH 05/14] FormCategory : create method to select the product category --- htdocs/core/class/html.form.class.php | 1 - htdocs/core/class/html.formcategory.class.php | 40 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index ea6d145641a..2b300b580cd 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -3708,7 +3708,6 @@ class Form } } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Load into cache list of payment terms diff --git a/htdocs/core/class/html.formcategory.class.php b/htdocs/core/class/html.formcategory.class.php index 1a2c02deb54..707b5d5d0ac 100644 --- a/htdocs/core/class/html.formcategory.class.php +++ b/htdocs/core/class/html.formcategory.class.php @@ -60,4 +60,44 @@ class FormCategory extends Form return $filter; } + + /** + * Prints a select form for products categories + * @param string $selected Id category pre-selection + * @param string $htmlname Name of HTML field + * @param int $showempty Add an empty field + * @return integer|null + */ + public function selectProductCategory($selected = 0, $htmlname = 'product_category_id', $showempty = 0) + { + global $conf; + + $sql = "SELECT cp.fk_categorie as cat_index, cat.label FROM `llx_categorie_product` as cp INNER JOIN llx_categorie as cat ON cat.rowid = cp.fk_categorie GROUP BY cp.fk_categorie;"; + + dol_syslog(get_class($this)."::selectProductCategory", LOG_DEBUG); + $resql = $this->db->query($sql); + if ($resql) { + print ''); + + return $num_rows; + } else { + dol_print_error($this->db); + } + } } From 5fba0dc237c0c9e294d8bf3ddb32510ab0cde9d0 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 28 Feb 2022 17:51:37 +0100 Subject: [PATCH 06/14] ticket config : select product type matching tickets. --- htdocs/admin/ticket.php | 41 +++++++++++++++++++++++++++++----- htdocs/langs/en_US/ticket.lang | 2 ++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index 68f256e2009..aa5acd273d6 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -26,6 +26,7 @@ require '../main.inc.php'; require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; require_once DOL_DOCUMENT_ROOT."/ticket/class/ticket.class.php"; require_once DOL_DOCUMENT_ROOT."/core/lib/ticket.lib.php"; +require_once DOL_DOCUMENT_ROOT."/core/class/html.formcategory.class.php"; // Load translation files required by the page $langs->loadLangs(array("admin", "ticket")); @@ -157,6 +158,14 @@ if ($action == 'setvarworkflow') { } } +if ($action == 'setvarworkflowother' || $action == 'setvarworkflow') { + $param_ticket_product_category = GETPOST('product_category_id', 'int'); + $res = dolibarr_set_const($db, 'TICKET_PRODUCT_CATEGORY', $param_ticket_product_category, 'chaine', 0, '', $conf->entity); + if (!($res > 0)) { + $error++; + } +} + if ($action == 'setvarother') { $param_must_exists = GETPOST('TICKET_EMAIL_MUST_EXISTS', 'alpha'); $res = dolibarr_set_const($db, 'TICKET_EMAIL_MUST_EXISTS', $param_must_exists, 'chaine', 0, '', $conf->entity); @@ -219,7 +228,7 @@ if ($action == 'setvarother') { $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); -$form = new Form($db); +$form = new FormCategory($db); $help_url = "FR:Module_Ticket"; $page_name = "TicketSetup"; @@ -489,8 +498,7 @@ foreach ($dirmodels as $reldir) { print ''; print '
'; - -if (!$conf->use_javascript_ajax) { +if (empty($conf->use_javascript_ajax)) { print '
'; print ''; print ''; @@ -551,10 +559,33 @@ print $form->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp"), 1, ' print ''; print ''; -if (!$conf->use_javascript_ajax) { - print '
'; +// Choose which product category is used for tickets +if ($conf->use_javascript_ajax) { + print '
'; + print ''; + print ''; } +print ''.$langs->trans("TicketChooseProductCategory").''; +print ''; + $form->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); + if ($conf->use_javascript_ajax) { + print ajax_combobox('select_'.$htmlname); + } +print ''; +print ''; +print $form->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); +print ''; +print ''; + +print '
'; + +print '
'; +print ''; +print '
'; + +print '
'; + // Define wanted maximum time elapsed before answers to tickets print '
'; print ''; diff --git a/htdocs/langs/en_US/ticket.lang b/htdocs/langs/en_US/ticket.lang index 204f7c0ed60..edd54911bad 100644 --- a/htdocs/langs/en_US/ticket.lang +++ b/htdocs/langs/en_US/ticket.lang @@ -145,6 +145,8 @@ TicketsDelayBetweenAnswersHelp=If an unresolved ticket that has already received TicketsAutoNotifyClose=Automatically notify thirdparty when closing a ticket TicketsAutoNotifyCloseHelp=When closing a ticket, you will be proposed to send a message to one of thirdparty's contacts. On mass closing, a message will be sent to one contact of the thirdparty linked to the ticket. TicketWrongContact=Provided contact is not part of current ticket contacts. Email not sent. +TicketChooseProductCategory=Product category for ticket support +TicketChooseProductCategoryHelp=Select the product category of ticket support. This will be used to automatically link a contract to a ticket. # # Index & list page From f92154d057aae2876893a49e3ba10a91092967c1 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 3 Feb 2022 17:00:21 +0100 Subject: [PATCH 07/14] declare ticket-related constants in modTicket.class.php --- htdocs/core/modules/modTicket.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/core/modules/modTicket.class.php b/htdocs/core/modules/modTicket.class.php index 86841ce5932..ff7eb1ee18f 100644 --- a/htdocs/core/modules/modTicket.class.php +++ b/htdocs/core/modules/modTicket.class.php @@ -111,6 +111,7 @@ class modTicket extends DolibarrModules 5 => array('TICKET_DELAY_BEFORE_FIRST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time before a first answer to a ticket (in hours). Display a warning in tickets list if not respected.', 0), 6 => array('TICKET_DELAY_SINCE_LAST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time between two answers on the same ticket (in hours). Display a warning in tickets list if not respected.', 0), 7 => array('TICKET_NOTIFY_AT_CLOSING', 'chaine', '0', 'Default notify contacts when closing a module', 0), + 8 => array('TICKET_PRODUCT_CATEGORY', 'chaine', 0, 'The category of product that is being used for ticket accounting', 0) ); From c745237ee92459bbbc2d3470e432e0b34dd4e7b4 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 8 Feb 2022 15:23:56 +0100 Subject: [PATCH 08/14] Stickler corrections --- htdocs/admin/ticket.php | 8 ++++---- htdocs/contrat/class/contrat.class.php | 2 +- .../interface_20_modWorkflow_WorkflowManager.class.php | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index aa5acd273d6..42a800c9f42 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -568,10 +568,10 @@ if ($conf->use_javascript_ajax) { print ''.$langs->trans("TicketChooseProductCategory").''; print ''; - $form->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); - if ($conf->use_javascript_ajax) { - print ajax_combobox('select_'.$htmlname); - } +$form->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); +if ($conf->use_javascript_ajax) { + print ajax_combobox('select_'.$htmlname); +} print ''; print ''; print $form->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index e6c73164f26..aea577cccda 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2136,7 +2136,7 @@ class Contrat extends CommonObject * @param array $line_status sort contracts where lines have these status * @return array|int Array of contracts id or <0 if error */ - public function getListOfContracts($option = 'all', $status = [], $product_categories = [], $line_status = [] ) + public function getListOfContracts($option = 'all', $status = [], $product_categories = [], $line_status = []) { $tab = array(); diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 1e98ec885bd..740abb4a1b9 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -428,7 +428,6 @@ class InterfaceWorkflowManager extends DolibarrTriggers dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id); // Auto link contract if (!empty($conf->contract->enabled) && !empty($conf->ticket->enabled) && !empty($conf->ficheinter->enabled) && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_TICKET_LINK_CONTRACT) && !empty($conf->global->TICKET_PRODUCT_CATEGORY) && !empty($object->fk_soc)) { - $societe = new Societe($this->db); $company_ids = (empty($conf->global->WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS)) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]); @@ -445,7 +444,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers $object->setContract($contractid); break; } elseif ($number_contracts_found > 1) { - foreach($list as $linked_contract) { + foreach ($list as $linked_contract) { $object->setContract($linked_contract->id); // don't set '$contractid' so it is not used when creating an intervention. } From c68e16c087144efb8a146b0aad98a8e84965ddf0 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 28 Feb 2022 18:06:41 +0100 Subject: [PATCH 09/14] admin/ticket.php: correct parameters table --- htdocs/admin/ticket.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index 42a800c9f42..6341e641194 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -578,14 +578,6 @@ print $form->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), print ''; print ''; -print '
'; - -print '
'; -print ''; -print '
'; - -print ''; - // Define wanted maximum time elapsed before answers to tickets print '
'; print ''; @@ -612,10 +604,14 @@ print $form->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), print ''; print ''; -print '
'; - print '
'; +print '
'; +print ''; +print '
'; + +print ''; + // Admin var of module print load_fiche_titre($langs->trans("Notification"), '', ''); From ac37c7e4ca822b33b11f22e72e4f9b831206c0f6 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 28 Feb 2022 18:16:19 +0100 Subject: [PATCH 10/14] link intervention to a ticket contract --- htdocs/ticket/card.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 9afca68c2eb..42ec518c585 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -260,7 +260,7 @@ if (empty($reshook)) { $fichinter = new Fichinter($db); $fichinter->socid = $object->fk_soc; $fichinter->fk_project = $projectid; - $fichinter->fk_contrat = $contractid; + $fichinter->fk_contrat = $object->fk_contract; $fichinter->author = $user->id; $fichinter->model_pdf = 'soleil'; $fichinter->origin = $object->element; From 3a82817ad984ff084826bf2150d7abe549e30cb6 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 28 Feb 2022 18:37:09 +0100 Subject: [PATCH 11/14] avoid displaying warning messages on the public interface --- .../interface_20_modWorkflow_WorkflowManager.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php index 740abb4a1b9..4e98af5c6c7 100644 --- a/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php +++ b/htdocs/core/triggers/interface_20_modWorkflow_WorkflowManager.class.php @@ -448,13 +448,13 @@ class InterfaceWorkflowManager extends DolibarrTriggers $object->setContract($linked_contract->id); // don't set '$contractid' so it is not used when creating an intervention. } - setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings'); + if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketManyContractsLinked'), 'warnings'); break; } } } if ($number_contracts_found == 0) { - setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs'); + if (empty(NOLOGIN)) setEventMessage($langs->trans('TicketNoContractFoundToLink'), 'mesgs'); } } } From fc7f097c25a143474b5d02d09a40bd0e6d10929f Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Mon, 28 Feb 2022 18:58:01 +0100 Subject: [PATCH 12/14] stickler corrections --- htdocs/ticket/card.php | 1 - 1 file changed, 1 deletion(-) diff --git a/htdocs/ticket/card.php b/htdocs/ticket/card.php index 42ec518c585..326e42781d0 100755 --- a/htdocs/ticket/card.php +++ b/htdocs/ticket/card.php @@ -276,7 +276,6 @@ if (empty($reshook)) { setEventMessages($fichinter->error, null, 'errors'); } } - } if (!$error) { From 14d9bf032295b4c651d22eca758c4c490790cf31 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Tue, 1 Mar 2022 09:17:56 +0100 Subject: [PATCH 13/14] fix non-sanitize string in SQL request --- htdocs/contrat/class/contrat.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/contrat/class/contrat.class.php b/htdocs/contrat/class/contrat.class.php index aea577cccda..b051c69e252 100644 --- a/htdocs/contrat/class/contrat.class.php +++ b/htdocs/contrat/class/contrat.class.php @@ -2144,12 +2144,12 @@ class Contrat extends CommonObject $sql .= " FROM ".MAIN_DB_PREFIX."contrat as c"; if (!empty($product_categories)) { $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."contratdet as cd ON cd.fk_contrat = c.rowid"; - $sql .= " INNER JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON cp.fk_product = cd.fk_product AND cp.fk_categorie IN (".implode(', ', $product_categories).")"; + $sql .= " INNER JOIN ".MAIN_DB_PREFIX."categorie_product as cp ON cp.fk_product = cd.fk_product AND cp.fk_categorie IN (".$this->db->sanitize(implode(', ', $product_categories)).")"; } $sql .= " WHERE c.fk_soc =".((int) $this->socid); $sql .= ($option == 'others') ? " AND c.rowid <> ".((int) $this->id) : ""; - $sql .= (!empty($status)) ? " AND c.statut IN (".implode(', ', $status).")" : ""; - $sql .= (!empty($line_status)) ? " AND cd.statut IN (".implode(', ', $line_status).")" : ""; + $sql .= (!empty($status)) ? " AND c.statut IN (".$this->db->sanitize(implode(', ', $status)).")" : ""; + $sql .= (!empty($line_status)) ? " AND cd.statut IN (".$this->db->sanitize(implode(', ', $line_status)).")" : ""; $sql .= " GROUP BY c.rowid"; dol_syslog(get_class($this)."::getOtherContracts()", LOG_DEBUG); From 2709e69a32610f2152209fd37a910f8794586653 Mon Sep 17 00:00:00 2001 From: Thomas Negre Date: Thu, 24 Mar 2022 10:59:18 +0100 Subject: [PATCH 14/14] rename $form into $formcategory --- htdocs/admin/ticket.php | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/htdocs/admin/ticket.php b/htdocs/admin/ticket.php index 6341e641194..ebf4187eabf 100644 --- a/htdocs/admin/ticket.php +++ b/htdocs/admin/ticket.php @@ -228,7 +228,7 @@ if ($action == 'setvarother') { $dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']); -$form = new FormCategory($db); +$formcategory = new FormCategory($db); $help_url = "FR:Module_Ticket"; $page_name = "TicketSetup"; @@ -335,7 +335,7 @@ foreach ($dirmodels as $reldir) { } print ''; - print $form->textwithpicto('', $htmltooltip, 1, 0); + print $formcategory->textwithpicto('', $htmltooltip, 1, 0); print ''; print ''; @@ -473,7 +473,7 @@ foreach ($dirmodels as $reldir) { print ''; - print $form->textwithpicto('', $htmltooltip, 1, 0); + print $formcategory->textwithpicto('', $htmltooltip, 1, 0); print ''; // Preview @@ -520,11 +520,11 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND); + print $formcategory->selectarray("TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND", $arrval, $conf->global->TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND); } print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketsAutoReadTicketHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketsAutoReadTicketHelp"), 1, 'help'); print ''; print ''; @@ -536,11 +536,11 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('TICKET_AUTO_ASSIGN_USER_CREATE'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("TICKET_AUTO_ASSIGN_USER_CREATE", $arrval, $conf->global->TICKET_AUTO_ASSIGN_USER_CREATE); + print $formcategory->selectarray("TICKET_AUTO_ASSIGN_USER_CREATE", $arrval, $conf->global->TICKET_AUTO_ASSIGN_USER_CREATE); } print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketsAutoAssignTicketHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketsAutoAssignTicketHelp"), 1, 'help'); print ''; print ''; @@ -551,11 +551,11 @@ if ($conf->use_javascript_ajax) { print ajax_constantonoff('TICKET_NOTIFY_AT_CLOSING'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("TICKET_NOTIFY_AT_CLOSING", $arrval, $conf->global->TICKET_NOTIFY_AT_CLOSING); + print $formcategory->selectarray("TICKET_NOTIFY_AT_CLOSING", $arrval, $conf->global->TICKET_NOTIFY_AT_CLOSING); } print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp"), 1, 'help'); print ''; print ''; @@ -568,13 +568,13 @@ if ($conf->use_javascript_ajax) { print ''.$langs->trans("TicketChooseProductCategory").''; print ''; -$form->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); +$formcategory->selectProductCategory($conf->global->TICKET_PRODUCT_CATEGORY, 'product_category_id'); if ($conf->use_javascript_ajax) { print ajax_combobox('select_'.$htmlname); } print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketChooseProductCategoryHelp"), 1, 'help'); print ''; print ''; @@ -589,7 +589,7 @@ print ' '; print ''; -print $form->textwithpicto('', $langs->trans("TicketsDelayBeforeFirstAnswerHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBeforeFirstAnswerHelp"), 1, 'help'); print ''; print ''; @@ -600,7 +600,7 @@ print ' '; print ''; -print $form->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketsDelayBetweenAnswersHelp"), 1, 'help'); print ''; print ''; @@ -639,7 +639,7 @@ print ''.$langs->trans("TicketEmailNotificationFrom").'< print ''; print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketEmailNotificationFromHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketEmailNotificationFromHelp"), 1, 'help'); print ''; print ''; @@ -648,7 +648,7 @@ print ''.$langs->trans("TicketEmailNotificationTo").' (' print ''; print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketEmailNotificationToHelp"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketEmailNotificationToHelp"), 1, 'help'); print ''; print ''; @@ -660,11 +660,11 @@ if ($conf->global->MAIN_FEATURES_LEVEL >= 2) { print ajax_constantonoff('TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS'); } else { $arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes")); - print $form->selectarray("TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS", $arrval, $conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS); + print $formcategory->selectarray("TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS", $arrval, $conf->global->TICKET_NOTIFICATION_ALSO_MAIN_ADDRESS); } print ''; print ''; - print $form->textwithpicto('', $langs->trans("TicketsEmailAlsoSendToMainAddressHelp"), 1, 'help'); + print $formcategory->textwithpicto('', $langs->trans("TicketsEmailAlsoSendToMainAddressHelp"), 1, 'help'); print ''; print ''; } @@ -678,7 +678,7 @@ $doleditor = new DolEditor('TICKET_MESSAGE_MAIL_INTRO', $mail_intro, '100%', 120 $doleditor->Create(); print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketMessageMailIntroHelpAdmin"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketMessageMailIntroHelpAdmin"), 1, 'help'); print ''; // Texte de signature @@ -690,12 +690,12 @@ $doleditor = new DolEditor('TICKET_MESSAGE_MAIL_SIGNATURE', $mail_signature, '10 $doleditor->Create(); print ''; print ''; -print $form->textwithpicto('', $langs->trans("TicketMessageMailSignatureHelpAdmin"), 1, 'help'); +print $formcategory->textwithpicto('', $langs->trans("TicketMessageMailSignatureHelpAdmin"), 1, 'help'); print ''; print ''; -print $form->buttonsSaveCancel("Save", ''); +print $formcategory->buttonsSaveCancel("Save", ''); print '';