From 617ff5cafb2c95e6e1e7a910d06123cf483f3e62 Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 08:47:41 +0100 Subject: [PATCH 01/38] Updated PHPDoc. Cleaned code. Fixed types. --- htdocs/societe/class/societe.class.php | 40 +++++++++++--------------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index cf7d9aa55b9..2656d6a5bff 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -310,8 +310,7 @@ class Societe extends CommonObject public $status = 1; /** - * Id of region - * @var int + * @var string region code */ public $region_code; @@ -1334,17 +1333,17 @@ class Societe extends CommonObject $now = dol_now(); // Clean parameters - $this->id = $id; - $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity); - $this->name = $this->name ? trim($this->name) : trim($this->nom); - $this->nom = $this->name; // For backward compatibility - $this->name_alias = trim($this->name_alias); + $this->id = $id; + $this->entity = ((isset($this->entity) && is_numeric($this->entity)) ? $this->entity : $conf->entity); + $this->name = $this->name ? trim($this->name) : trim($this->nom); + $this->nom = $this->name; // For backward compatibility + $this->name_alias = trim($this->name_alias); $this->ref_ext = trim($this->ref_ext); - $this->address = $this->address ? trim($this->address) : trim($this->address); - $this->zip = $this->zip ? trim($this->zip) : trim($this->zip); - $this->town = $this->town ? trim($this->town) : trim($this->town); - $this->state_id = trim($this->state_id); - $this->country_id = ($this->country_id > 0) ? $this->country_id : 0; + $this->address = trim($this->address); + $this->zip = trim($this->zip); + $this->town = trim($this->town); + $this->state_id = (is_numeric($this->state_id)) ? (int) trim($this->state_id) : 0; + $this->country_id = ($this->country_id > 0) ? $this->country_id : 0; $this->phone = trim($this->phone); $this->phone = preg_replace("/\s/", "", $this->phone); $this->phone = preg_replace("/\./", "", $this->phone); @@ -1361,14 +1360,14 @@ class Societe extends CommonObject $this->idprof4 = trim($this->idprof4); $this->idprof5 = (!empty($this->idprof5) ? trim($this->idprof5) : ''); $this->idprof6 = (!empty($this->idprof6) ? trim($this->idprof6) : ''); - $this->prefix_comm = trim($this->prefix_comm); + $this->prefix_comm = trim($this->prefix_comm); $this->outstanding_limit = price2num($this->outstanding_limit); $this->order_min_amount = price2num($this->order_min_amount); $this->supplier_order_min_amount = price2num($this->supplier_order_min_amount); - $this->tva_assuj = trim($this->tva_assuj); + $this->tva_assuj = (is_numeric($this->tva_assuj)) ? (int) trim($this->tva_assuj) : 0; $this->tva_intra = dol_sanitizeFileName($this->tva_intra, ''); - $this->vat_reverse_charge = empty($this->vat_reverse_charge) ? '0' : '1'; + $this->vat_reverse_charge = empty($this->vat_reverse_charge) ? 0 : 1; if (empty($this->status)) { $this->status = 0; } @@ -1388,12 +1387,7 @@ class Societe extends CommonObject $this->localtax1_value = trim($this->localtax1_value); $this->localtax2_value = trim($this->localtax2_value); - if ($this->capital != '') { - $this->capital = price2num(trim($this->capital)); - } - if (!is_numeric($this->capital)) { - $this->capital = ''; // '' = undef - } + $this->capital = (!empty($this->capital)) ? (float) price2num(trim($this->capital)) : 0; $this->effectif_id = trim($this->effectif_id); $this->forme_juridique_code = trim($this->forme_juridique_code); @@ -1550,7 +1544,7 @@ class Societe extends CommonObject $sql .= ",localtax2_value =0.000"; } - $sql .= ",capital = ".($this->capital == '' ? "null" : $this->capital); + $sql .= ",capital = ".($this->capital == 0 ? "null" : $this->capital); $sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null"); @@ -1913,7 +1907,7 @@ class Societe extends CommonObject $this->state_id = $obj->state_id; $this->state_code = $obj->state_code; $this->region_id = $obj->region_id; - $this->region_code = $obj->region_code; + $this->region_code = $obj->region_code; $this->state = ($obj->state != '-' ? $obj->state : ''); $transcode = $langs->trans('StatusProspect'.$obj->fk_stcomm); From 49d10bb491032a8280bfba39ebfc1eeacfa4191f Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 11:05:34 +0100 Subject: [PATCH 02/38] Refactored & cleaned isACompany method --- htdocs/societe/class/societe.class.php | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 2656d6a5bff..cb69b5b27d0 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3988,30 +3988,27 @@ class Societe extends CommonObject } /** - * Return if third party is a company (Business) or an end user (Consumer) + * Check if third party is a company (Business) or an end user (Consumer) * - * @return boolean true=is a company, false=a and user + * @return boolean if a company: true || if a user: false */ public function isACompany() { - global $conf; - // Define if third party is treated as company (or not) when nature is unknown - $isacompany = !getDolGlobalString('MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES') ? 0 : 1; // 0 by default + $isACompany = !getDolGlobalString('MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES') ? false : true; if (!empty($this->tva_intra)) { - $isacompany = 1; + $isACompany = true; } elseif (!empty($this->idprof1) || !empty($this->idprof2) || !empty($this->idprof3) || !empty($this->idprof4) || !empty($this->idprof5) || !empty($this->idprof6)) { - $isacompany = 1; + $isACompany = true; } elseif (!empty($this->typent_code) && $this->typent_code != 'TE_UNKNOWN') { // TODO Add a field is_a_company into dictionary if (preg_match('/^TE_PRIVATE/', $this->typent_code)) { - $isacompany = 0; + $isACompany = false; } else { - $isacompany = 1; + $isACompany = true; } } - - return $isacompany; + return $isACompany; } /** From 465a49107327749657d56d0c0231a11406626802 Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 11:24:12 +0100 Subject: [PATCH 03/38] Cleaned country_id type --- htdocs/societe/class/societe.class.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index cb69b5b27d0..623310be452 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -929,7 +929,7 @@ class Societe extends CommonObject if ($this->code_client == -1 || $this->code_client === 'auto') { $this->get_codeclient($this, 0); } - if ($this->code_fournisseur == -1 || $this->code_fournisseur === 'auto') { + if ($this->code_fournisseur == '-1' || $this->code_fournisseur === 'auto') { $this->get_codefournisseur($this, 1); } @@ -1399,7 +1399,7 @@ class Societe extends CommonObject if ($this->code_client == -1 || $this->code_client === 'auto') { $this->get_codeclient($this, 0); } - if ($this->code_fournisseur == -1 || $this->code_fournisseur === 'auto') { + if ($this->code_fournisseur == '-1' || $this->code_fournisseur === 'auto') { $this->get_codefournisseur($this, 1); } @@ -4229,7 +4229,7 @@ class Societe extends CommonObject $this->client = 1; // A member is a customer by default $this->code_client = ($customercode ? $customercode : -1); - $this->code_fournisseur = -1; + $this->code_fournisseur = '-1'; $this->typent_code = ($member->morphy == 'phy' ? 'TE_PRIVATE' : 0); $this->typent_id = $this->typent_code ? dol_getIdFromCode($this->db, $this->typent_code, 'c_typent', 'id', 'code') : 0; @@ -4303,10 +4303,11 @@ class Societe extends CommonObject $this->note_private = getDolGlobalString('MAIN_INFO_SOCIETE_NOTE'); // We define country_id, country_code and country - $country_id = $country_code = $country_label = ''; + $country_id = 0; + $country_code = $country_label = ''; if (getDolGlobalString('MAIN_INFO_SOCIETE_COUNTRY')) { $tmp = explode(':', getDolGlobalString('MAIN_INFO_SOCIETE_COUNTRY')); - $country_id = $tmp[0]; + $country_id = (is_numeric($tmp[0])) ? (int) $tmp[0] : 0; if (!empty($tmp[1])) { // If $conf->global->MAIN_INFO_SOCIETE_COUNTRY is "id:code:label" $country_code = $tmp[1]; $country_label = $tmp[2]; From a7f2acfc972bd3f1a11348899f49a45632bf2d1c Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 11:28:08 +0100 Subject: [PATCH 04/38] Cleaned capital type --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 623310be452..31bc938eba3 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -4390,7 +4390,7 @@ class Societe extends CommonObject $this->idprof6 = getDolGlobalString('MAIN_INFO_PROFID6'); $this->tva_intra = getDolGlobalString('MAIN_INFO_TVAINTRA'); // VAT number, not necessarily INTRA. $this->managers = getDolGlobalString('MAIN_INFO_SOCIETE_MANAGERS'); - $this->capital = getDolGlobalString('MAIN_INFO_CAPITAL'); + $this->capital = is_numeric(getDolGlobalString('MAIN_INFO_CAPITAL')) ? (float) price2num(getDolGlobalString('MAIN_INFO_CAPITAL')) : 0; $this->forme_juridique_code = getDolGlobalString('MAIN_INFO_SOCIETE_FORME_JURIDIQUE'); $this->email = getDolGlobalString('MAIN_INFO_SOCIETE_MAIL'); $this->default_lang = getDolGlobalString('MAIN_LANG_DEFAULT', 'auto'); From 73bd62b48db0441bc0dbb19de385110631f00988 Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 11:31:59 +0100 Subject: [PATCH 05/38] Cleaned tva_assuj type --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 31bc938eba3..39ef740cad4 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -4402,7 +4402,7 @@ class Societe extends CommonObject $this->logo_squarred_mini = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI'); // Define if company use vat or not - $this->tva_assuj = getDolGlobalString('FACTURE_TVAOPTION'); + $this->tva_assuj = (is_numeric(getDolGlobalString('FACTURE_TVAOPTION'))) ? (int) getDolGlobalString('FACTURE_TVAOPTION') : 0; // Define if company use local taxes $this->localtax1_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX1_OPTION) && (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == '1' || getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')) ? 1 : 0); From d17b6712e6c70eae488c23d58af7c6bac6810460 Mon Sep 17 00:00:00 2001 From: William Mead Date: Thu, 25 Jan 2024 11:52:08 +0100 Subject: [PATCH 06/38] Added contributor details --- htdocs/societe/class/societe.class.php | 1 + 1 file changed, 1 insertion(+) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 39ef740cad4..6a232bb47f5 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -19,6 +19,7 @@ * Copyright (C) 2020 Open-Dsi * Copyright (C) 2022 ButterflyOfFire * Copyright (C) 2023 Alexandre Janniaux + * Copyright (C) 2024 William Mead * * 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 From 6facd01c484cbb84418ddcbb020a7fdcb02d5014 Mon Sep 17 00:00:00 2001 From: William Mead Date: Fri, 26 Jan 2024 08:49:08 +0100 Subject: [PATCH 07/38] Refactored isACompany method --- htdocs/societe/class/societe.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 6a232bb47f5..58485c3c15d 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3996,20 +3996,20 @@ class Societe extends CommonObject public function isACompany() { // Define if third party is treated as company (or not) when nature is unknown - $isACompany = !getDolGlobalString('MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES') ? false : true; + $isACompany = getDolGlobalInt('MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES'); if (!empty($this->tva_intra)) { - $isACompany = true; + $isACompany = 1; } elseif (!empty($this->idprof1) || !empty($this->idprof2) || !empty($this->idprof3) || !empty($this->idprof4) || !empty($this->idprof5) || !empty($this->idprof6)) { - $isACompany = true; + $isACompany = 1; } elseif (!empty($this->typent_code) && $this->typent_code != 'TE_UNKNOWN') { // TODO Add a field is_a_company into dictionary if (preg_match('/^TE_PRIVATE/', $this->typent_code)) { - $isACompany = false; + $isACompany = 0; } else { - $isACompany = true; + $isACompany = 1; } } - return $isACompany; + return boolval($isACompany); } /** From c8b1e705a43314b3ae2f5f6bac3d70e8f894ebc3 Mon Sep 17 00:00:00 2001 From: William Mead Date: Fri, 26 Jan 2024 08:55:00 +0100 Subject: [PATCH 08/38] Cleaned code --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 58485c3c15d..616d97338b3 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -4403,7 +4403,7 @@ class Societe extends CommonObject $this->logo_squarred_mini = getDolGlobalString('MAIN_INFO_SOCIETE_LOGO_SQUARRED_MINI'); // Define if company use vat or not - $this->tva_assuj = (is_numeric(getDolGlobalString('FACTURE_TVAOPTION'))) ? (int) getDolGlobalString('FACTURE_TVAOPTION') : 0; + $this->tva_assuj = getDolGlobalInt('FACTURE_TVAOPTION'); // Define if company use local taxes $this->localtax1_assuj = ((isset($conf->global->FACTURE_LOCAL_TAX1_OPTION) && (getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == '1' || getDolGlobalString('FACTURE_LOCAL_TAX1_OPTION') == 'localtax1on')) ? 1 : 0); From 6f6d5fa6d81220fb4db546a25809c282e0aa4149 Mon Sep 17 00:00:00 2001 From: William Mead Date: Fri, 26 Jan 2024 09:11:50 +0100 Subject: [PATCH 09/38] Refactored capital property update --- htdocs/societe/class/societe.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 616d97338b3..fb17d2ffe08 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1388,7 +1388,7 @@ class Societe extends CommonObject $this->localtax1_value = trim($this->localtax1_value); $this->localtax2_value = trim($this->localtax2_value); - $this->capital = (!empty($this->capital)) ? (float) price2num(trim($this->capital)) : 0; + $this->capital = ($this->capital != '') ? (float) price2num(trim($this->capital)) : null; $this->effectif_id = trim($this->effectif_id); $this->forme_juridique_code = trim($this->forme_juridique_code); @@ -1545,7 +1545,7 @@ class Societe extends CommonObject $sql .= ",localtax2_value =0.000"; } - $sql .= ",capital = ".($this->capital == 0 ? "null" : $this->capital); + $sql .= ",capital = ".($this->capital == null ? "null" : $this->capital); $sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null"); From dea1978171b7f0ecbc72176ca1b24f59127d0180 Mon Sep 17 00:00:00 2001 From: William Mead Date: Fri, 26 Jan 2024 09:17:02 +0100 Subject: [PATCH 10/38] Fixed 0 values --- htdocs/societe/class/societe.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index fb17d2ffe08..370c538764b 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -1545,7 +1545,7 @@ class Societe extends CommonObject $sql .= ",localtax2_value =0.000"; } - $sql .= ",capital = ".($this->capital == null ? "null" : $this->capital); + $sql .= ",capital = ".($this->capital === null ? "null" : $this->capital); $sql .= ",prefix_comm = ".(!empty($this->prefix_comm) ? "'".$this->db->escape($this->prefix_comm)."'" : "null"); From a615672525fcfba21695bd931f948175bf5bc843 Mon Sep 17 00:00:00 2001 From: William Mead Date: Mon, 29 Jan 2024 09:23:11 +0100 Subject: [PATCH 11/38] Added client code to order export --- htdocs/core/modules/modCommande.class.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/modules/modCommande.class.php b/htdocs/core/modules/modCommande.class.php index eb276ea8c3d..005ae6490be 100644 --- a/htdocs/core/modules/modCommande.class.php +++ b/htdocs/core/modules/modCommande.class.php @@ -200,7 +200,7 @@ class modCommande extends DolibarrModules $this->export_label[$r] = 'CustomersOrdersAndOrdersLines'; // Translation key (used only if key ExportDataset_xxx_z not found) $this->export_permission[$r] = array(array("commande", "commande", "export")); $this->export_fields_array[$r] = array( - 's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 'ps.nom'=>'ParentCompany', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'd.nom'=>'State', 'co.label'=>'Country', + 's.rowid'=>"IdCompany", 's.nom'=>'CompanyName', 'ps.nom'=>'ParentCompany', 's.code_client'=>'CustomerCode', 's.address'=>'Address', 's.zip'=>'Zip', 's.town'=>'Town', 'd.nom'=>'State', 'co.label'=>'Country', 'co.code'=>"CountryCode", 's.phone'=>'Phone', 's.siren'=>'ProfId1', 's.siret'=>'ProfId2', 's.ape'=>'ProfId3', 's.idprof4'=>'ProfId4', 'c.rowid'=>"Id", 'c.ref'=>"Ref", 'c.ref_client'=>"RefCustomer", 'c.fk_soc'=>"IdCompany", 'c.date_creation'=>"DateCreation", 'c.date_commande'=>"OrderDate", 'c.date_livraison'=>"DateDeliveryPlanned", 'c.amount_ht'=>"Amount", 'c.total_ht'=>"TotalHT", @@ -233,7 +233,7 @@ class modCommande extends DolibarrModules // 'p.rowid'=>'List:product:ref','p.ref'=>'Text','p.label'=>'Text' //); $this->export_TypeFields_array[$r] = array( - 's.nom'=>'Text', 'ps.nom'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'co.label'=>'List:c_country:label:label', 'co.code'=>'Text', 's.phone'=>'Text', + 's.nom'=>'Text', 'ps.nom'=>'Text', 's.code_client'=>'Text', 's.address'=>'Text', 's.zip'=>'Text', 's.town'=>'Text', 'co.label'=>'List:c_country:label:label', 'co.code'=>'Text', 's.phone'=>'Text', 's.siren'=>'Text', 's.siret'=>'Text', 's.ape'=>'Text', 's.idprof4'=>'Text', 'c.ref'=>"Text", 'c.ref_client'=>"Text", 'c.date_creation'=>"Date", 'c.date_commande'=>"Date", 'c.date_livraison'=>"Date", 'sm.code'=>"Text", 'c.amount_ht'=>"Numeric", 'c.total_ht'=>"Numeric", 'c.total_ttc'=>"Numeric", 'c.facture'=>"Boolean", 'c.fk_statut'=>'Status', 'c.note_public'=>"Text", 'pj.ref'=>'Text', @@ -242,7 +242,7 @@ class modCommande extends DolibarrModules 'c.entity'=>'List:entity:label:rowid', ); $this->export_entities_array[$r] = array( - 's.rowid'=>"company", 's.nom'=>'company', 'ps.nom'=>'company', 's.address'=>'company', 's.zip'=>'company', 's.town'=>'company', 'd.nom'=>'company', 'co.label'=>'company', + 's.rowid'=>"company", 's.nom'=>'company', 'ps.nom'=>'company', 's.code_client'=>'company', 's.address'=>'company', 's.zip'=>'company', 's.town'=>'company', 'd.nom'=>'company', 'co.label'=>'company', 'co.code'=>'company', 's.phone'=>'company', 's.siren'=>'company', 's.ape'=>'company', 's.idprof4'=>'company', 's.siret'=>'company', 'c.rowid'=>"order", 'c.ref'=>"order", 'c.ref_client'=>"order", 'c.fk_soc'=>"order", 'c.date_creation'=>"order", 'c.date_commande'=>"order", 'c.amount_ht'=>"order", 'c.total_ht'=>"order", 'c.total_ttc'=>"order", 'c.facture'=>"order", 'c.fk_statut'=>"order", 'c.note'=>"order", From 3cc15d416373798ea216a5aa338e8f8cbd503a4b Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 29 Jan 2024 15:38:13 +0100 Subject: [PATCH 12/38] New display for template email in boxes --- htdocs/ai/admin/setup.php | 2 - htdocs/ai/class/ai.class.php | 33 +++++--- htdocs/ai/css/style.css | 89 ++++++++++++++++++++ htdocs/core/class/html.formmail.class.php | 99 +++++++++++++++++++---- htdocs/langs/en_US/mails.lang | 6 +- 5 files changed, 198 insertions(+), 31 deletions(-) create mode 100644 htdocs/ai/css/style.css diff --git a/htdocs/ai/admin/setup.php b/htdocs/ai/admin/setup.php index 33d4954ea2d..00e3623dab5 100644 --- a/htdocs/ai/admin/setup.php +++ b/htdocs/ai/admin/setup.php @@ -67,8 +67,6 @@ foreach ($arrayofia as $ia) { $item->defaultFieldValue = ''; } -// Retrieve existing API Key -//$apiKey = dolibarr_get_const($db, 'MAIN_AI_CHATGPT_API_KEY'); $setupnotempty =+ count($formSetup->items); diff --git a/htdocs/ai/class/ai.class.php b/htdocs/ai/class/ai.class.php index 3a1e5de3ad1..dd103c837e0 100644 --- a/htdocs/ai/class/ai.class.php +++ b/htdocs/ai/class/ai.class.php @@ -19,6 +19,7 @@ * along with this program. If not, see . * or see https://www.gnu.org/ */ +require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; /** * Class for AI @@ -43,33 +44,39 @@ class Ai /** * Constructor * - * @param string $apiEndpoint Endpoint of api - * @param string $apiKey key of api + * @param DoliDB $db Database handler + * */ - public function __construct($apiEndpoint, $apiKey) + public function __construct($db) { - $this->apiEndpoint = $apiEndpoint; - $this->apiKey = $apiKey; + $this->db = $db; + $this->apiEndpoint = dolibarr_get_const($this->db, 'AI_API_ENDPOINT'); + $this->apiKey = dolibarr_get_const($this->db, 'AI_KEY_API_CHATGPT'); } /** * Generate response of instructions * @param string $instructions instruction for generate content + * @param string $model model name (chat,text,image...) * @return mixed $response */ - public function generateContent($instructions) + public function generateContent($instructions, $model = 'gpt-3.5-turbo') { try { $ch = curl_init($this->apiEndpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['prompt' => $instructions])); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([ + 'messages' => [ + ['role' => 'user', 'content' => $instructions] + ], + 'model' => $model + ])); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $this->apiKey, 'Content-Type: application/json' ]); $response = curl_exec($ch); - if (curl_errno($ch)) { throw new Exception('cURL error: ' . curl_error($ch)); } @@ -78,11 +85,15 @@ class Ai if ($statusCode != 200) { throw new Exception('API request failed with status code ' . $statusCode); } + // Decode JSON response + $decodedResponse = json_decode($response, true); - return $response; + // Extraction content + $generatedEmailContent = $decodedResponse['choices'][0]['message']['content']; + + return $generatedEmailContent; } catch (Exception $e) { - error_log($e->getMessage()); - return null; + return array('error' => true, 'message' => $e->getMessage()); } finally { curl_close($ch); } diff --git a/htdocs/ai/css/style.css b/htdocs/ai/css/style.css new file mode 100644 index 00000000000..22a06705912 --- /dev/null +++ b/htdocs/ai/css/style.css @@ -0,0 +1,89 @@ +.template-container { + display: flex; + justify-content: space-between; + padding: 10px; + background: #f5f5f5; + border: 1px solid #d3d3d3; + border-radius: 5px; + margin-bottom: 15px; + } + + .template-option { + flex: 1; + text-align: center; + padding: 10px; + margin: 0 5px; + background: #e9e9e9; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + height: 80px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .template-option:hover { + font-weight: bold; + background: var(--butactionbg); + color: var(--textbutaction); + border-radius: 8px; + border-collapse: collapse; + border: none; + } + + .template-option[data-template="ai"] { + background: #c5f7c5; + } + + .template-option[data-template="ai"]:hover { + font-weight: bold; + background: var(--butactionbg); + color: var(--textbutaction); + border-radius: 8px; + border-collapse: collapse; + border: none; + } + + .template-option.selected { + font-weight: bold; + background: var(--butactionbg); + color: var(--textbutaction); + border-radius: 8px; + border-collapse: collapse; + border: none; +} + + #template-selector { + width: 100%; + max-width: 80%; + height: auto; + padding: 10px; + border: 1px solid #d3d3d3; + border-radius: 5px; + margin-bottom: 10px; + margin-top: 10px; + } + + .template-option i { + font-size: 42px; + margin-bottom: 5px; + +} +.template-option-text { + padding-top: 5px; + font-size: 12px; +} + +#ai_input { + display: none; +} + +.template-option img { + display: block; + width: 100%; + height: 100%; + margin: 0 5px; + padding: auto; +} \ No newline at end of file diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 9592ed0a291..6c610e9bacc 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -755,7 +755,7 @@ class FormMail extends Form if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) { $out .= ''; $out .= $langs->trans("MailToCCUsers"); - $out .= ''; + $out .= ''; // multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time $tmparray = $this->withtoccuser; @@ -889,8 +889,8 @@ class FormMail extends Form //input prompt AI require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; - if (isModEnabled('ai') && getDolGlobalString('AI_CHATGPT_API_KEY')) { - $out .= $this->getHtmlForInstruction(); + if (isModEnabled('ai')) { + $out .= $this->getModelEmailTemplate(); } // Message if (!empty($this->withbody)) { @@ -1002,7 +1002,7 @@ class FormMail extends Form $out .= ''; if ($this->withbodyreadonly) { $out .= nl2br($defaultmessage); - $out .= ''; + $out .= ''; } else { if (!isset($this->ckeditortoolbar)) { $this->ckeditortoolbar = 'dolibarr_mailings'; @@ -1386,39 +1386,57 @@ class FormMail extends Form { global $langs, $form; - $baseUrl = dol_buildpath('/', 1); - - $out = ''; + $out = ''; $out .= ''; $out .= $form->textwithpicto($langs->trans('helpWithAi'), $langs->trans("YouCanMakeSomeInstructionForEmail")); $out .= ''; $out .= ''; - $out .= ''; - $out .= ''; - $out .= ''; + $out .= ''; + $out .= ''; $out .= "\n"; + + $out .= ""; + $out .= ""; + $out .= $this->getHtmlForInstruction(); + return $out; + } /** diff --git a/htdocs/langs/en_US/mails.lang b/htdocs/langs/en_US/mails.lang index 2de7dbbbdc3..aaddd278084 100644 --- a/htdocs/langs/en_US/mails.lang +++ b/htdocs/langs/en_US/mails.lang @@ -184,5 +184,7 @@ EmailOptedOut=Email owner has requested to not contact him with this email anymo EvenUnsubscribe=Include opt-out emails EvenUnsubscribeDesc=Include opt-out emails when you select emails as targets. Useful for mandatory service emails for example. XEmailsDoneYActionsDone=%s emails pre-qualified, %s emails successfully processed (for %s record/actions done) -helpWithAi=Add instructions -YouCanMakeSomeInstructionForEmail=You can add some instructions for your email (Example: generate image in email template...) +helpWithAi=Generate message from AI +YouCanMakeSomeInstructionForEmail=You Can Make Some Instruction For your Email (Exemple: generate image in email template...) +ModelTemplate=Email template +YouCanChooseAModelForYouMailContent= You can shoose one of models or generate one with Ai \ No newline at end of file From 17ce61b82f09e7f6898daf5946df196469665310 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 29 Jan 2024 16:03:11 +0100 Subject: [PATCH 13/38] fix name in input message --- htdocs/core/class/html.formmail.class.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 6c610e9bacc..83f3edbb9d1 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1002,7 +1002,7 @@ class FormMail extends Form $out .= ''; if ($this->withbodyreadonly) { $out .= nl2br($defaultmessage); - $out .= ''; + $out .= ''; } else { if (!isset($this->ckeditortoolbar)) { $this->ckeditortoolbar = 'dolibarr_mailings'; From fc9e833318b16144236a927fd00278d6c5f5023c Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 29 Jan 2024 16:17:42 +0100 Subject: [PATCH 14/38] add script for generate email template --- .../generate_content.php} | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) rename htdocs/ai/{lib/generate_content.lib.php => ajax/generate_content.php} (82%) diff --git a/htdocs/ai/lib/generate_content.lib.php b/htdocs/ai/ajax/generate_content.php similarity index 82% rename from htdocs/ai/lib/generate_content.lib.php rename to htdocs/ai/ajax/generate_content.php index 898bd2205ca..d2efc05de34 100644 --- a/htdocs/ai/lib/generate_content.lib.php +++ b/htdocs/ai/ajax/generate_content.php @@ -41,30 +41,27 @@ if (!defined('NOREQUIRESOC')) { define('NOREQUIRESOC', '1'); } -require_once '../../main.inc.php'; +require '../../main.inc.php'; + require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php'; +top_httphead(); //get data from AJAX $rawData = file_get_contents('php://input'); $jsonData = json_decode($rawData, true); if (is_null($jsonData)) { - dol_print_error(null, 'data with format JSON valide.'); + dol_print_error('data with format JSON valide.'); } -$token = GETPOST('token'); -if ($token !== currentToken()) { // Remplacez 'newToken' par le nom de votre variable de session contenant le token - dol_print_error(null, 'CSRF token validation failed.'); - exit; -} -$chatGPT = new Ai('API_ENDPOINT', 'API_KEY'); +$chatGPT = new Ai($db); $instructions = dol_string_nohtmltag($jsonData['instructions'], 1, 'UTF-8'); $generatedContent = $chatGPT->generateContent($instructions); -if ($generatedContent) { - print $generatedContent; +if (is_array($generatedContent) && $generatedContent['error']) { + print "Error : " . $generatedContent['message']; } else { - dol_print_error(null, 'error!!'); -} + print $generatedContent; +} \ No newline at end of file From c92b8709f2615cf3ff7ace1e8f7f8be739142a80 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 29 Jan 2024 16:17:49 +0100 Subject: [PATCH 15/38] add script for generate email template --- htdocs/ai/ajax/generate_content.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/ai/ajax/generate_content.php b/htdocs/ai/ajax/generate_content.php index d2efc05de34..c38ab4ef54b 100644 --- a/htdocs/ai/ajax/generate_content.php +++ b/htdocs/ai/ajax/generate_content.php @@ -64,4 +64,4 @@ if (is_array($generatedContent) && $generatedContent['error']) { print "Error : " . $generatedContent['message']; } else { print $generatedContent; -} \ No newline at end of file +} From 586230adbedf2b7b2b4510e71e37a6c0c5ff7587 Mon Sep 17 00:00:00 2001 From: Lamrani Abdel Date: Mon, 29 Jan 2024 17:31:23 +0100 Subject: [PATCH 16/38] add image for boxes --- htdocs/ai/css/style.css | 28 +++++++++++++----- htdocs/core/class/html.formmail.class.php | 6 ++-- htdocs/theme/common/mailtemplate/basic.png | Bin 0 -> 1400 bytes htdocs/theme/common/mailtemplate/commerce.png | Bin 0 -> 2490 bytes htdocs/theme/common/mailtemplate/empty.png | Bin 0 -> 2150 bytes htdocs/theme/common/mailtemplate/news.png | Bin 0 -> 2346 bytes htdocs/theme/common/mailtemplate/text.png | Bin 0 -> 1183 bytes 7 files changed, 23 insertions(+), 11 deletions(-) create mode 100644 htdocs/theme/common/mailtemplate/basic.png create mode 100644 htdocs/theme/common/mailtemplate/commerce.png create mode 100644 htdocs/theme/common/mailtemplate/empty.png create mode 100644 htdocs/theme/common/mailtemplate/news.png create mode 100644 htdocs/theme/common/mailtemplate/text.png diff --git a/htdocs/ai/css/style.css b/htdocs/ai/css/style.css index 22a06705912..29ed800d134 100644 --- a/htdocs/ai/css/style.css +++ b/htdocs/ai/css/style.css @@ -17,7 +17,7 @@ border: 1px solid #ccc; border-radius: 5px; cursor: pointer; - height: 80px; + height: 90px; display: flex; flex-direction: column; align-items: center; @@ -66,14 +66,25 @@ margin-top: 10px; } - .template-option i { + .template-option[data-template="ai"] i { font-size: 42px; - margin-bottom: 5px; + display: block; + width: 80%; + max-height: 80px; + margin: 0 5px; + padding-top: 5px; + border-radius: 5px; } +.template-option[data-template="ai"] span { + padding-top: 30px; + font-size: 14px; + +} + .template-option-text { - padding-top: 5px; - font-size: 12px; + padding-top: 3px; + font-size: 14px; } #ai_input { @@ -82,8 +93,9 @@ .template-option img { display: block; - width: 100%; - height: 100%; + width: 80%; + max-height: 80px; margin: 0 5px; - padding: auto; + padding-top: 5px; + border-radius: 7px; } \ No newline at end of file diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php index 83f3edbb9d1..54f69f0e5fa 100644 --- a/htdocs/core/class/html.formmail.class.php +++ b/htdocs/core/class/html.formmail.class.php @@ -1463,11 +1463,11 @@ class FormMail extends Form $templates = array('empty', 'basic', 'news', 'commerce', 'text'); foreach ($templates as $template) { $out .= '
'; - $out .= 'Gray rectangle'; - $out .= ucfirst($template); + $out .= ''.$template.''; + $out .= ''.ucfirst($template).''; $out .= '
'; } - $out .= '
Generate with AI
'; + $out .= '
Generate with AI
'; $out .= ''; $out .= ''; $out .= "