diff --git a/htdocs/admin/mails.php b/htdocs/admin/mails.php
index d74df8ceac90a..8f797ea25e5d1 100644
--- a/htdocs/admin/mails.php
+++ b/htdocs/admin/mails.php
@@ -1113,7 +1113,7 @@ function change_smtp_auth_method() {
print dol_get_fiche_head(array(), '', '', -1);
- // Cree l'objet formulaire mail
+ // Create form object
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db);
$formmail->trackid = (($action == 'testhtml') ? "testhtml" : "test");
@@ -1132,7 +1132,7 @@ function change_smtp_auth_method() {
$formmail->withtopic = (GETPOSTISSET('subject') ? GETPOST('subject') : $langs->trans("Test"));
$formmail->withtopicreadonly = 0;
$formmail->withfile = 2;
- $formmail->withlayout = 1;
+ $formmail->withlayout = 1; // Not MAIN_EMAIL_USE_LAYOUT must be set
$formmail->withaiprompt = ($action == 'testhtml' ? 'html' : 'text');
$formmail->withbody = (GETPOSTISSET('message') ? GETPOST('message', 'restricthtml') : ($action == 'testhtml' ? $langs->transnoentities("PredefinedMailTestHtml") : $langs->transnoentities("PredefinedMailTest")));
$formmail->withbodyreadonly = 0;
diff --git a/htdocs/ai/admin/custom_prompt.php b/htdocs/ai/admin/custom_prompt.php
index 92b42924dd654..aa8e1b86292f5 100644
--- a/htdocs/ai/admin/custom_prompt.php
+++ b/htdocs/ai/admin/custom_prompt.php
@@ -34,8 +34,15 @@
// Parameters
$action = GETPOST('action', 'aZ09');
$backtopage = GETPOST('backtopage', 'alpha');
+$cancel = GETPOST('cancel');
$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
+$functioncode = GETPOST('functioncode', 'alpha');
+$pre_prompt = GETPOST('prePrompt');
+$post_prompt = GETPOST('postPrompt');
+$blacklists = GETPOST('blacklists');
+$test = GETPOST('test');
+
if (empty($action)) {
$action = 'edit';
}
@@ -83,20 +90,16 @@
* Actions
*/
-$functioncode = GETPOST('functioncode', 'alpha');
-$pre_prompt = GETPOST('prePrompt');
-$post_prompt = GETPOST('postPrompt');
-$blacklists = GETPOST('blacklists');
// get all configs in const AI
$currentConfigurationsJson = getDolGlobalString('AI_CONFIGURATIONS_PROMPT');
$currentConfigurations = json_decode($currentConfigurationsJson, true);
-if ($action == 'update' && GETPOST('cancel')) {
+if ($action == 'update' && $cancel) {
$action = 'edit';
}
-if ($action == 'update' && !GETPOST('cancel')) {
+if ($action == 'update' && !$cancel && !$test) {
$error = 0;
if (empty($functioncode)) {
$error++;
@@ -135,7 +138,8 @@
$action = 'edit';
}
-if ($action == 'updatePrompts') {
+// Update entry
+if ($action == 'updatePrompts' && !$test) {
$key = GETPOST('key', 'alpha');
$blacklistArray = array_filter(array_map('trim', explode(',', $blacklists)));
@@ -149,17 +153,21 @@
$newConfigurationsJson = json_encode($currentConfigurations, JSON_UNESCAPED_UNICODE);
$result = dolibarr_set_const($db, 'AI_CONFIGURATIONS_PROMPT', $newConfigurationsJson, 'chaine', 0, '', $conf->entity);
if (!$error) {
- $action = '';
+ $action = 'edit';
if ($result) {
- header("Location: ".$_SERVER['PHP_SELF']);
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
- exit;
} else {
setEventMessages($langs->trans("ErrorUpdating"), null, 'errors');
}
}
}
+// Test entry
+if ($action == 'updatePrompts' && $test) {
+ $action = 'edit';
+}
+
+// Delete entry
if ($action == 'confirm_deleteproperty' && GETPOST('confirm') == 'yes') {
$key = GETPOST('key', 'alpha');
@@ -311,12 +319,12 @@
$out .= '';
$out .= '';
$out .= '';
+ $out .= '';
$out .= '
';
$out .= '';
$out .= '';
$out .= ''.$arrayofaifeatures[$key]['picto'].' '.$langs->trans($arrayofaifeatures[$key]['label']);
- $out .= ''.img_edit().'';
$out .= ''.img_delete().'';
$out .= ' | ';
$out .= ' | ';
@@ -329,7 +337,7 @@
$out .= ''.$langs->trans("Pre-Prompt").'';
$out .= '';
$out .= '';
- $out .= '';
+ $out .= '';
$out .= ' | ';
$out .= '
';
@@ -338,21 +346,34 @@
$out .= ''.$langs->trans("Post-Prompt").'';
$out .= '';
$out .= '';
- $out .= '';
+ $out .= '';
$out .= ' | ';
$out .= '';
$out .= '';
$out .= ''.$langs->trans("BlackListWords").' | ';
$out .= '';
- $out .= '';
+ $out .= '';
$out .= ' | ';
$out .= '
';
$out .= '';
$out .= ' | ';
$out .= '';
- $out .= '';
+ $out .= '';
+ $out .= ' ';
+
+ include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
+ $showlinktoai = $key; // 'textgeneration', 'imagegeneration', ...
+ $showlinktoailabel = $langs->trans("ToTest");
+ $formmail = new FormMail($db);
+ $htmlname = $key;
+
+ // Fill $out
+ include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
+
+ $out .= '';
+
$out .= ' | ';
$out .= '
';
@@ -363,51 +384,6 @@
}
}
-
- $out .= "";
-
print $out;
print '
';
diff --git a/htdocs/ai/admin/setup.php b/htdocs/ai/admin/setup.php
index 8cd4e7e5bbb2b..b2dc936407392 100644
--- a/htdocs/ai/admin/setup.php
+++ b/htdocs/ai/admin/setup.php
@@ -81,11 +81,13 @@
$item->nameText = $langs->trans("AI_API_KEY").' ('.$ialabel.')';
$item->defaultFieldValue = '';
$item->fieldParams['hideGenerateButton'] = 1;
+ $item->fieldParams['trClass'] = $ia;
$item->cssClass = 'minwidth500 text-security';
$item = $formSetup->newItem('AI_API_'.strtoupper($ia).'_URL'); // Name of constant must end with _KEY so it is encrypted when saved into database.
$item->nameText = $langs->trans("AI_API_URL").' ('.$ialabel.')';
$item->defaultFieldValue = '';
+ $item->fieldParams['trClass'] = $ia;
$item->cssClass = 'minwidth500';
}
diff --git a/htdocs/ai/ajax/generate_content.php b/htdocs/ai/ajax/generate_content.php
index 4ee6a4c170cff..251f6689bdfa2 100644
--- a/htdocs/ai/ajax/generate_content.php
+++ b/htdocs/ai/ajax/generate_content.php
@@ -46,6 +46,10 @@
require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php';
+if (!isModEnabled('ai')) {
+ accessforbidden('Module AI not enabled');
+}
+
/*
* View
@@ -63,7 +67,7 @@
$ai = new Ai($db);
// Get parameters
-$function = empty($jsonData['function']) ? 'textgeneration' : $jsonData['function']; // Default value. Can also be 'textgenerationemail', 'textgenerationwebpage', ...
+$function = empty($jsonData['function']) ? 'textgeneration' : $jsonData['function']; // Default value. Can also be 'textgeneration', 'textgenerationemail', 'textgenerationwebpage', 'imagegeneration', 'videogeneration', ...
$instructions = dol_string_nohtmltag($jsonData['instructions'], 1, 'UTF-8');
$format = empty($jsonData['format']) ? '' : $jsonData['format'];
@@ -80,5 +84,16 @@
print "Error returned by API call: " . $generatedContent['message'];
}
} else {
- print $generatedContent;
+ if ($function == 'textgenerationemail' || $function == 'textgenerationwebpage') {
+ print dolPrintHTML($generatedContent); // Note that common HTML tags are NOT escaped (but a sanitization is done)
+ } elseif ($function == 'imagegeneration') {
+ // TODO
+ } elseif ($function == 'videogeneration') {
+ // TODO
+ } elseif ($function == 'audiogeneration') {
+ // TODO
+ } else {
+ // Default case 'textgeneration'
+ print dolPrintText($generatedContent); // Note that common HTML tags are NOT escaped (but a sanitization is done)
+ }
}
diff --git a/htdocs/ai/class/ai.class.php b/htdocs/ai/class/ai.class.php
index dc496174b561b..2e45d37914be9 100644
--- a/htdocs/ai/class/ai.class.php
+++ b/htdocs/ai/class/ai.class.php
@@ -71,11 +71,11 @@ public function __construct($db)
/**
* Generate response of instructions
*
- * @param string $instructions Instruction to generate content
- * @param string $model Model name ('gpt-3.5-turbo', 'gpt-4-turbo', 'dall-e-3', ...)
- * @param string $function Code of the feature we want to use ('textgeneration', 'transcription', 'audiogeneration', 'imagegeneration', 'translation')
- * @param string $format Format for output ('', 'html', ...)
- * @return mixed $response
+ * @param string $instructions Instruction to generate content
+ * @param string $model Model name ('gpt-3.5-turbo', 'gpt-4-turbo', 'dall-e-3', ...)
+ * @param string $function Code of the feature we want to use ('textgeneration', 'transcription', 'audiogeneration', 'imagegeneration', 'translation')
+ * @param string $format Format for output ('', 'html', ...)
+ * @return string|array $response Text or array if error
*/
public function generateContent($instructions, $model = 'auto', $function = 'textgeneration', $format = '')
{
@@ -83,96 +83,100 @@ public function generateContent($instructions, $model = 'auto', $function = 'tex
return array('error' => true, 'message' => 'API key is not defined for the AI enabled service ('.$this->apiService.')');
}
+ // $this->apiEndpoint is set here only if forced.
+ // In most cases, it is empty and we must get it from $function and $this->apiService
if (empty($this->apiEndpoint)) {
if ($function == 'imagegeneration') {
if ($this->apiService == 'chatgpt') {
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/images/generations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CHATGPT_MODEL_IMAGE', 'dall-e-3');
- }
} elseif ($this->apiService == 'groq') {
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/images/generations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_GROK_MODEL_IMAGE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
- }
} elseif ($this->apiService == 'custom') {
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/images/generations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CUSTOM_MODEL_IMAGE', 'dall-e-3');
- }
}
} elseif ($function == 'audiogeneration') {
if ($this->apiService == 'chatgpt') {
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/audio/speech';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CHATGPT_MODEL_AUDIO', 'tts-1');
- }
} elseif ($this->apiService == 'groq') {
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/audio/speech';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_GROK_MODEL_AUDIO', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
- }
} elseif ($this->apiService == 'custom') {
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/audio/speech';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CUSTOM_MODEL_AUDIO', 'tts-1');
- }
}
} elseif ($function == 'transcription') {
if ($this->apiService == 'chatgpt') {
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/transcriptions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSCRIPT', 'whisper-1');
- }
} elseif ($this->apiService == 'groq') {
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/transcriptions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_GROK_MODEL_TRANSCRIPT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
- }
} elseif ($this->apiService == 'custom') {
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/transcriptions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CUSTOM_TRANSCRIPT', 'whisper-1');
- }
}
} elseif ($function == 'translation') {
if ($this->apiService == 'chatgpt') {
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/translations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSLATE', 'whisper-1');
- }
} elseif ($this->apiService == 'groq') {
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/translations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_GROK_MODEL_TRANSLATE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
- }
} elseif ($this->apiService == 'custom') {
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/translations';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CUSTOM_TRANSLATE', 'whisper-1');
- }
}
} else { // else textgeneration...
if ($this->apiService == 'chatgpt') {
$this->apiEndpoint = getDolGlobalString('AI_API_CHATGPT_URL', 'https://api.openai.com/v1').'/chat/completions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TEXT', 'gpt-3.5-turbo');
- }
} elseif ($this->apiService == 'groq') {
$this->apiEndpoint = getDolGlobalString('AI_API_GROK_URL', 'https://api.groq.com/openai/v1').'/chat/completions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_GROK_MODEL_TEXT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
- }
} elseif ($this->apiService == 'custom') {
$this->apiEndpoint = getDolGlobalString('AI_API_CUSTOM_URL', '').'/chat/completions';
- if ($model == 'auto') {
- $model = getDolGlobalString('AI_API_CUSTOM_MODEL_TEXT', 'gpt-3.5-turbo');
- }
}
}
}
- dol_syslog("Call API for apiEndpoint=".$this->apiEndpoint." apiKey=".substr($this->apiKey, 0, 3).'***********, model='.$model);
+ // $model may be undefined or 'auto'.
+ // If this is the case, we must get it from $function and $this->apiService
+ if (empty($model) || $model == 'auto') {
+ // Return the endpoint and the model from $this->apiService.
+ if ($function == 'imagegeneration') {
+ if ($this->apiService == 'chatgpt') {
+ $model = getDolGlobalString('AI_API_CHATGPT_MODEL_IMAGE', 'dall-e-3');
+ } elseif ($this->apiService == 'groq') {
+ $model = getDolGlobalString('AI_API_GROK_MODEL_IMAGE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
+ } elseif ($this->apiService == 'custom') {
+ $model = getDolGlobalString('AI_API_CUSTOM_MODEL_IMAGE', 'dall-e-3');
+ }
+ } elseif ($function == 'audiogeneration') {
+ if ($this->apiService == 'chatgpt') {
+ $model = getDolGlobalString('AI_API_CHATGPT_MODEL_AUDIO', 'tts-1');
+ } elseif ($this->apiService == 'groq') {
+ $model = getDolGlobalString('AI_API_GROK_MODEL_AUDIO', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
+ } elseif ($this->apiService == 'custom') {
+ $model = getDolGlobalString('AI_API_CUSTOM_MODEL_AUDIO', 'tts-1');
+ }
+ } elseif ($function == 'transcription') {
+ if ($this->apiService == 'chatgpt') {
+ $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSCRIPT', 'whisper-1');
+ } elseif ($this->apiService == 'groq') {
+ $model = getDolGlobalString('AI_API_GROK_MODEL_TRANSCRIPT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
+ } elseif ($this->apiService == 'custom') {
+ $model = getDolGlobalString('AI_API_CUSTOM_TRANSCRIPT', 'whisper-1');
+ }
+ } elseif ($function == 'translation') {
+ if ($this->apiService == 'chatgpt') {
+ $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TRANSLATE', 'whisper-1');
+ } elseif ($this->apiService == 'groq') {
+ $model = getDolGlobalString('AI_API_GROK_MODEL_TRANSLATE', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
+ } elseif ($this->apiService == 'custom') {
+ $model = getDolGlobalString('AI_API_CUSTOM_TRANSLATE', 'whisper-1');
+ }
+ } else { // else textgeneration...
+ if ($this->apiService == 'chatgpt') {
+ $model = getDolGlobalString('AI_API_CHATGPT_MODEL_TEXT', 'gpt-3.5-turbo');
+ } elseif ($this->apiService == 'groq') {
+ $model = getDolGlobalString('AI_API_GROK_MODEL_TEXT', 'mixtral-8x7b-32768'); // 'llama3-8b-8192', 'gemma-7b-it'
+ } elseif ($this->apiService == 'custom') {
+ $model = getDolGlobalString('AI_API_CUSTOM_MODEL_TEXT', 'tinyllama-1.1b'); // with JAN: 'tinyllama-1.1b', 'mistral-ins-7b-q4'
+ }
+ }
+ }
+
+ dol_syslog("Call API for apiKey=".substr($this->apiKey, 0, 3).'***********, apiEndpoint='.$this->apiEndpoint.", model=".$model);
try {
if (empty($this->apiEndpoint)) {
@@ -187,42 +191,72 @@ public function generateContent($instructions, $model = 'auto', $function = 'tex
if (isset($configurations[$function])) {
if (isset($configurations[$function]['prePrompt'])) {
- $prePrompt = $configurations[$function]['prePrompt'];
+ $prePrompt = $configurations[$function]['prePrompt']; // TODO We can send prePrompt into a separated message with role system.
}
if (isset($configurations[$function]['postPrompt'])) {
$postPrompt = $configurations[$function]['postPrompt'];
}
}
- $fullInstructions = $prePrompt.' '.$instructions.' .'.$postPrompt;
-
+ $fullInstructions = ($prePrompt ? $prePrompt.' ' : '').$instructions.($postPrompt ? '. '.$postPrompt : '');
+ // Set payload string
+ /*{
+ "messages": [
+ {
+ "content": "You are a helpful assistant.",
+ "role": "system"
+ },
+ {
+ "content": "Hello!",
+ "role": "user"
+ }
+ ],
+ "model": "tinyllama-1.1b",
+ "stream": true,
+ "max_tokens": 2048,
+ "stop": [
+ "hello"
+ ],
+ "frequency_penalty": 0,
+ "presence_penalty": 0,
+ "temperature": 0.7,
+ "top_p": 0.95
+ }*/
$payload = json_encode([
'messages' => [
['role' => 'user', 'content' => $fullInstructions]
],
- 'model' => $model
+ 'model' => $model,
+ //'stream' => false
]);
$headers = ([
'Authorization: Bearer ' . $this->apiKey,
'Content-Type: application/json'
]);
- $response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers);
+
+ $localurl = 2; // Accept both local and external endpoints
+ $response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers, array('http', 'https'), $localurl);
if (empty($response['http_code'])) {
throw new Exception('API request failed. No http received');
}
if (!empty($response['http_code']) && $response['http_code'] != 200) {
- throw new Exception('API request on endpoint '.$this->apiEndpoint.' failed with status code ' . $response['http_code']);
+ throw new Exception('API request on AI endpoint '.$this->apiEndpoint.' failed with status code '.$response['http_code'].(empty($response['content']) ? '' : ' - '.$response['content']));
+ }
+
+ if (getDolGlobalString("AI_DEBUG")) {
+ dol_syslog("response content = ".var_export($response['content'], true));
}
+
// Decode JSON response
$decodedResponse = json_decode($response['content'], true);
// Extraction content
$generatedContent = $decodedResponse['choices'][0]['message']['content'];
- dol_syslog("generatedContent=".$generatedContent);
+ dol_syslog("generatedContent=".dol_trunc($generatedContent, 50));
// If content is not HTML, we convert it into HTML
if ($format == 'html') {
diff --git a/htdocs/compta/prelevement/class/bonprelevement.class.php b/htdocs/compta/prelevement/class/bonprelevement.class.php
index 9f60156c6a81e..e8770f12f0ea0 100644
--- a/htdocs/compta/prelevement/class/bonprelevement.class.php
+++ b/htdocs/compta/prelevement/class/bonprelevement.class.php
@@ -2211,13 +2211,13 @@ public function EnregDestinataireSEPA($row_code_client, $row_nom, $row_address,
$XML_DEBITOR .= ' false' . $CrLf;
$XML_DEBITOR .= ' ' . $CrLf;
$XML_DEBITOR .= ' ' . $CrLf;
+ $XML_DEBITOR .= ' ' . $CrLf;
+ $XML_DEBITOR .= ' ' . $CrLf;
if (getDolGlobalInt('WITHDRAWAL_WITHOUT_BIC')==0) {
- $XML_DEBITOR .= ' ' . $CrLf;
- $XML_DEBITOR .= ' ' . $CrLf;
$XML_DEBITOR .= ' ' . $row_bic . '' . $CrLf;
- $XML_DEBITOR .= ' ' . $CrLf;
- $XML_DEBITOR .= ' ' . $CrLf;
}
+ $XML_DEBITOR .= ' ' . $CrLf;
+ $XML_DEBITOR .= ' ' . $CrLf;
$XML_DEBITOR .= ' ' . $CrLf;
$XML_DEBITOR .= ' ' . dolEscapeXML(strtoupper(dol_string_nospecial(dol_string_unaccent($row_nom), ' '))) . '' . $CrLf;
$XML_DEBITOR .= ' ' . $CrLf;
diff --git a/htdocs/core/boxes/box_factures_imp.php b/htdocs/core/boxes/box_factures_imp.php
index 4c7473046d551..f5ac81853497a 100644
--- a/htdocs/core/boxes/box_factures_imp.php
+++ b/htdocs/core/boxes/box_factures_imp.php
@@ -139,10 +139,9 @@ public function loadBox($max = 5)
while ($line < min($num, $this->max)) {
$objp = $this->db->fetch_object($result);
- $datelimite = $this->db->jdate($objp->datelimite);
$date = $this->db->jdate($objp->date);
$datem = $this->db->jdate($objp->tms);
- $datelimit = $this->db->jdate(datelimite);
+ $datelimit = $this->db->jdate($obj->datelimite);
$facturestatic->id = $objp->facid;
$facturestatic->ref = $objp->ref;
@@ -182,7 +181,7 @@ public function loadBox($max = 5)
$late = '';
if ($facturestatic->hasDelay()) {
// @phan-suppress-next-line PhanPluginPrintfVariableFormatString
- $late = img_warning(sprintf($l_due_date, dol_print_date($datelimite, 'day', 'tzuserrel')));
+ $late = img_warning(sprintf($l_due_date, dol_print_date($datelimit, 'day', 'tzuserrel')));
}
$this->info_box_contents[$line][] = array(
@@ -204,8 +203,8 @@ public function loadBox($max = 5)
);
$this->info_box_contents[$line][] = array(
- 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateDue").': '.dol_print_date($datelimite, 'day', 'tzuserrel')).'"',
- 'text' => dol_print_date($datelimite, 'day', 'tzuserrel'),
+ 'td' => 'class="center nowraponall" title="'.dol_escape_htmltag($langs->trans("DateDue").': '.dol_print_date($datelimit, 'day', 'tzuserrel')).'"',
+ 'text' => dol_print_date($datelimit, 'day', 'tzuserrel'),
);
$this->info_box_contents[$line][] = array(
diff --git a/htdocs/core/class/html.formmail.class.php b/htdocs/core/class/html.formmail.class.php
index 84a7a948fa4f9..0b8f66126f5be 100644
--- a/htdocs/core/class/html.formmail.class.php
+++ b/htdocs/core/class/html.formmail.class.php
@@ -63,17 +63,17 @@ class FormMail extends Form
public $frommail;
/**
- * @var string user, company, robot
+ * @var string user, company, robot
*/
public $fromtype;
/**
- * @var int from ID
+ * @var int from ID
*/
public $fromid;
/**
- * @var int also from robot
+ * @var int Add also the robot email as possible senders
*/
public $fromalsorobot;
@@ -93,7 +93,7 @@ class FormMail extends Form
public $replytoname;
/**
- * @var string replyto email
+ * @var string Reply-to email
*/
public $replytomail;
@@ -1419,42 +1419,38 @@ public function getSectionForAIPrompt($function = 'textgeneration', $format = ''
$htmlContent = preg_replace('/[^a-z0-9_]/', '', $htmlContent);
- $out = '';
- $out .= '';
- //$out .= $form->textwithpicto($langs->trans('HelpWithAI'), $langs->trans("YouCanMakeSomeInstructionForEmail"));
- $out .= ' | ';
-
- $out .= '';
- $out .= '';
- $out .= '';
- $out .= ' |
\n";
+
+ $out .= "\n";
$out .= "