forked from Wavyzz/dolibarr
Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -19,6 +19,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
* 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);
|
||||
}
|
||||
|
||||
101
htdocs/ai/css/style.css
Normal file
101
htdocs/ai/css/style.css
Normal file
@@ -0,0 +1,101 @@
|
||||
.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: 90px;
|
||||
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[data-template="ai"] i {
|
||||
font-size: 42px;
|
||||
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: 3px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#ai_input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.template-option img {
|
||||
display: block;
|
||||
width: 80%;
|
||||
max-height: 80px;
|
||||
margin: 0 5px;
|
||||
padding-top: 5px;
|
||||
border-radius: 7px;
|
||||
}
|
||||
@@ -241,7 +241,6 @@ jQuery(document).ready(function() {
|
||||
}).done(function(data) {
|
||||
|
||||
console.log(data);
|
||||
var data = JSON.parse(data);
|
||||
$("#fk_unit").val(data).change();
|
||||
});
|
||||
|
||||
@@ -254,9 +253,7 @@ jQuery(document).ready(function() {
|
||||
,'idproduct' : idproduct
|
||||
}
|
||||
}).done(function(data) {
|
||||
var data = JSON.parse(data);
|
||||
$('#idworkstations').val(data.defaultWk).select2();
|
||||
|
||||
});
|
||||
});
|
||||
<?php } ?>
|
||||
|
||||
@@ -63,7 +63,7 @@ class Tva extends CommonObject
|
||||
public $num_payment;
|
||||
|
||||
/**
|
||||
* @var DateTime
|
||||
* @var int Creation date
|
||||
*/
|
||||
public $datec;
|
||||
|
||||
@@ -82,11 +82,6 @@ class Tva extends CommonObject
|
||||
*/
|
||||
public $rappro;
|
||||
|
||||
/**
|
||||
* @var integer|string totalpaid
|
||||
*/
|
||||
public $totalpaid;
|
||||
|
||||
/**
|
||||
* @var string label
|
||||
*/
|
||||
@@ -426,9 +421,9 @@ class Tva extends CommonObject
|
||||
$this->amount = '';
|
||||
$this->label = '';
|
||||
$this->note = '';
|
||||
$this->fk_bank = '';
|
||||
$this->fk_user_creat = '';
|
||||
$this->fk_user_modif = '';
|
||||
$this->fk_bank = 0;
|
||||
$this->fk_user_creat = 0;
|
||||
$this->fk_user_modif = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ class Ccountry extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
@@ -195,7 +195,7 @@ class Ccountry extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class CGenericDic extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Insert request
|
||||
@@ -321,7 +321,7 @@ class CGenericDic extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
|
||||
@@ -94,7 +94,7 @@ class Cregion extends CommonDict
|
||||
$this->cheflieu = trim($this->cheflieu);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
@@ -224,7 +224,7 @@ class Cregion extends CommonDict
|
||||
$this->cheflieu = trim($this->cheflieu);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class Cstate extends CommonDict
|
||||
$this->nom = trim($this->nom);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
@@ -194,7 +194,7 @@ class Cstate extends CommonDict
|
||||
$this->name = trim($this->name);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
|
||||
@@ -64,7 +64,7 @@ class Ctypent extends CommonDict
|
||||
// Clean parameters
|
||||
|
||||
if (isset($this->id)) {
|
||||
$this->id = trim($this->id);
|
||||
$this->id = (int) $this->id;
|
||||
}
|
||||
if (isset($this->code)) {
|
||||
$this->code = trim($this->code);
|
||||
@@ -73,7 +73,7 @@ class Ctypent extends CommonDict
|
||||
$this->libelle = trim($this->libelle);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
if (isset($this->module)) {
|
||||
$this->module = trim($this->module);
|
||||
@@ -193,7 +193,7 @@ class Ctypent extends CommonDict
|
||||
$this->libelle = trim($this->libelle);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
if (isset($this->module)) {
|
||||
$this->module = trim($this->module);
|
||||
|
||||
@@ -80,7 +80,7 @@ class Ctyperesource extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Insert request
|
||||
@@ -277,7 +277,7 @@ class Ctyperesource extends CommonDict
|
||||
$this->label = trim($this->label);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
@@ -433,7 +433,7 @@ class Ctyperesource extends CommonDict
|
||||
|
||||
$this->code = '';
|
||||
$this->label = '';
|
||||
$this->active = '';
|
||||
$this->active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,7 @@ class CUnits extends CommonDict
|
||||
$this->active = trim($this->unit_type);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
if (isset($this->scale)) {
|
||||
$this->scale = trim($this->scale);
|
||||
@@ -318,7 +318,7 @@ class CUnits extends CommonDict
|
||||
$this->scale = trim($this->scale);
|
||||
}
|
||||
if (isset($this->active)) {
|
||||
$this->active = trim($this->active);
|
||||
$this->active = (int) $this->active;
|
||||
}
|
||||
|
||||
// Check parameters
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
* \brief Fichier de la class permettant la generation du formulaire html d'envoi de mail unitaire
|
||||
*/
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/modelemail.lib.php';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -755,7 +757,7 @@ class FormMail extends Form
|
||||
if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
|
||||
$out .= '<tr><td>';
|
||||
$out .= $langs->trans("MailToCCUsers");
|
||||
$out .= '</td></td>';
|
||||
$out .= '</td><td>';
|
||||
|
||||
// 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 +891,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 +1004,7 @@ class FormMail extends Form
|
||||
$out .= '<td colspan="2">';
|
||||
if ($this->withbodyreadonly) {
|
||||
$out .= nl2br($defaultmessage);
|
||||
$out .= '<input type="hidden" id="message" name="message" value="'.$defaultmessage.'" />';
|
||||
$out .= '<input type="hidden" id="message" name="message" disabled value="'.$defaultmessage.'" />';
|
||||
} else {
|
||||
if (!isset($this->ckeditortoolbar)) {
|
||||
$this->ckeditortoolbar = 'dolibarr_mailings';
|
||||
@@ -1386,39 +1388,57 @@ class FormMail extends Form
|
||||
{
|
||||
global $langs, $form;
|
||||
|
||||
$baseUrl = dol_buildpath('/', 1);
|
||||
|
||||
$out = '<tr>';
|
||||
$out = '<tr id="ai_input">';
|
||||
$out .= '<td>';
|
||||
$out .= $form->textwithpicto($langs->trans('helpWithAi'), $langs->trans("YouCanMakeSomeInstructionForEmail"));
|
||||
$out .= '</td>';
|
||||
|
||||
$out .= '<td>';
|
||||
$out .= '<input type="hidden" id="csrf_token" name="token" value="'.newToken().'">';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions" name="instruction" placeholder="message with AI"/>';
|
||||
$out .= '<button id="generate_button" type="button" class="button smallpaddingimp">'.$langs->trans('Generate').'</button>';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions" name="instruction" placeholder="message with AI" />';
|
||||
$out .= '<input id="generate_button" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
|
||||
$out .= "</td></tr>\n";
|
||||
|
||||
|
||||
$out .= "<script type='text/javascript'>
|
||||
$(document).ready(function() {
|
||||
|
||||
//for keydown
|
||||
$('#ai_instructions').keydown(function(event) {
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
$('#generate_button').click();
|
||||
}
|
||||
});
|
||||
|
||||
$('#generate_button').click(function() {
|
||||
var instructions = $('#ai_instructions').val();
|
||||
var token = $('#csrf_token').val();
|
||||
//editor on readonly
|
||||
if (CKEDITOR.instances.message) {
|
||||
CKEDITOR.instances.message.setReadOnly(1);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '".$baseUrl."ai/lib/generate_content.lib.php',
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".newToken()."',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'token': token,
|
||||
'instructions': instructions,
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
if (".getDolGlobalString('FCKEDITOR_ENABLE_MAIL').") {
|
||||
CKEDITOR.instances.message.setData(response);
|
||||
}
|
||||
else {
|
||||
tinymce.get('message').setContent(response);
|
||||
}
|
||||
// remove readonly
|
||||
CKEDITOR.instances.message.setReadOnly(0);
|
||||
$('#ai_instructions').val('');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('error ajax', status, error);
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1427,6 +1447,73 @@ class FormMail extends Form
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get models template email in boxes
|
||||
* @return string HTML for model email boxes
|
||||
|
||||
*/
|
||||
public function getModelEmailTemplate()
|
||||
{
|
||||
|
||||
global $langs, $form;
|
||||
$out = '<tr>';
|
||||
$out .= '<td>';
|
||||
$out .= $form->textwithpicto($langs->trans('ModelTemplate'), $langs->trans("YouCanChooseAModelForYouMailContent"));
|
||||
$out .= '</td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<div id="template-selector" class="template-container">';
|
||||
$templates = array(
|
||||
'empty' => 'empty_template',
|
||||
'basic' => 'basic_template',
|
||||
'news' => 'news_template',
|
||||
'commerce' => 'commerce_template',
|
||||
'text' => 'text_template'
|
||||
);
|
||||
|
||||
foreach ($templates as $template => $templateFunction) {
|
||||
if (function_exists($templateFunction)) {
|
||||
$contentHtml = $templateFunction();
|
||||
}
|
||||
$out .= '<div class="template-option" data-template="'.$template.'" data-content="'.htmlentities($contentHtml).'">';
|
||||
$out .= '<img alt="'.$template.'" src="'.DOL_URL_ROOT.'/theme/common/mailtemplate/'.$template.'.png" />';
|
||||
$out .= '<span class="template-option-text">'.ucfirst($template).'</span>';
|
||||
$out .= '</div>';
|
||||
}
|
||||
$out .= '<div class="template-option" data-template="ai"><i class="fas fa-edit"></i><span >Generate with AI</span></div>';
|
||||
$out .= '</div>';
|
||||
$out .= '</td></tr>';
|
||||
$out .= "<script type='text/javascript'>
|
||||
var cssLink = document.createElement('link');
|
||||
cssLink.href = '".DOL_URL_ROOT."/ai/css/style.css';
|
||||
cssLink.rel = 'stylesheet';
|
||||
cssLink.type = 'text/css';
|
||||
document.head.appendChild(cssLink);</script>";
|
||||
$out .= "<script type='text/javascript'>
|
||||
$(document).ready(function() {
|
||||
$('.template-option').click(function() {
|
||||
$('.template-option').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
|
||||
var template = $(this).data('template');
|
||||
var contentHtml = $(this).data('content');
|
||||
|
||||
var editorInstance = CKEDITOR.instances.message;
|
||||
if (editorInstance) {
|
||||
editorInstance.setData(contentHtml);
|
||||
}
|
||||
// display input for generate with IA
|
||||
if(template === 'ai') {
|
||||
$('#ai_input').show();
|
||||
} else {
|
||||
$('#ai_input').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>";
|
||||
$out .= $this->getHtmlForInstruction();
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,15 +31,30 @@
|
||||
class Utils
|
||||
{
|
||||
/**
|
||||
* @var DoliDB Database handler.
|
||||
* @var DoliDB Database handler
|
||||
*/
|
||||
public $db;
|
||||
|
||||
/**
|
||||
* @var string Error message
|
||||
* @see $errors
|
||||
*/
|
||||
public $error;
|
||||
|
||||
/**
|
||||
* @var string[] Array of error messages
|
||||
*/
|
||||
public $errors;
|
||||
|
||||
public $output; // Used by Cron method to return message
|
||||
public $result; // Used by Cron method to return data
|
||||
/**
|
||||
* @var string Used by Cron method to return message
|
||||
*/
|
||||
public $output;
|
||||
|
||||
/**
|
||||
* @var array{'commandbackuplastdone': string, 'commandbackuptorun': string} Used by Cron method to return data
|
||||
*/
|
||||
public $result;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
||||
@@ -11371,7 +11371,7 @@ function isVisibleToUserType($type_user, &$menuentry, &$listofmodulesforexternal
|
||||
*/
|
||||
function roundUpToNextMultiple($n, $x = 5)
|
||||
{
|
||||
$result = (ceil($n) % $x === 0) ? ceil($n) : round(($n + $x / 2) / $x) * $x;
|
||||
$result = (ceil($n) % $x === 0) ? ceil($n) : (round(($n + $x / 2) / $x) * $x);
|
||||
return (int) $result;
|
||||
}
|
||||
|
||||
|
||||
185
htdocs/core/lib/modelemail.lib.php
Normal file
185
htdocs/core/lib/modelemail.lib.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/* Copyright (C) 2005 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
||||
* Copyright (C) 2004-2018 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2024 Alexandre Janniaux <alexandre.janniaux@gmail.com>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file htdocs/core/lib/emailmodel.lib.php
|
||||
*
|
||||
* \brief File for getting email html models
|
||||
*/
|
||||
|
||||
/**
|
||||
* get empty html
|
||||
* @return string $out html content
|
||||
*/
|
||||
function empty_template()
|
||||
{
|
||||
$out = '';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get basic html
|
||||
* @return string $out html content
|
||||
*/
|
||||
function basic_template()
|
||||
{
|
||||
$out = '
|
||||
<div >
|
||||
<div >
|
||||
<img alt="Gray rectangle" style="margin-left:150px;" width="800px" height="100px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
<h3 style="margin-left:150px;">Lorem, ipsum dolor sit amet consectetur adipisicing elit.</h3>
|
||||
<h3 style="margin-left:150px;">Lorem, ipsum dolor sit amet consectetur</h3>
|
||||
<!-- Les paragraphes de texte -->
|
||||
<div class="email-template-text">
|
||||
<p style="margin-left:150px;">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Aperiam non blanditiis delectus accusamus reprehenderit voluptates repellat.<br> Excepturi illo delectus nisi labore, iste voluptatibus dignissimos explicabo, corrupti voluptatum et facere cum?</p>
|
||||
</div>
|
||||
<div class="email-template-text">
|
||||
<p style="margin-left:150px;">Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
|
||||
</div>
|
||||
<div class="email-template-text">
|
||||
<p style="margin-left:150px;">Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
|
||||
</div>
|
||||
|
||||
<img alt="Gray rectangle" style="margin-left:150px;" width="15%" height="50px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
|
||||
</div>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get news html
|
||||
* @return string $out html content
|
||||
*/
|
||||
function news_template()
|
||||
{
|
||||
$out = '
|
||||
<h1 style="margin-left:120px;">Lorem, ipsum dolor sit amet consectetur adipisicing elit sit amet consectetur</h1>
|
||||
<h2 style="margin-left:120px;">Lorem, ipsum dolor sit amet consectetur adipisicing elitsit amet consectetur adipisicing </h2>
|
||||
|
||||
<div style="display: flex; align-items: center; justify-content: start; width: 100%; max-width: 600px;margin-top:0">
|
||||
<div style="flex-grow: 1; margin-right: 10px; margin-left:120px;width:200px">
|
||||
<h2>Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur</h2>
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur
|
||||
adipiscing elit. Sed do eiusmod temxwshslkdsdsslpor incididunt ut labore et dolore magna <br>aliqua. Lorem, ipsum dolor sit amet consectetur adipisicing elit. Totam sit<br> autem nihil omnis! Odit ipsum repellat, voluptas accusantium dolores adipisci ut voluptates eius cumque dicta obcaecati
|
||||
<img alt="Gray rectangle" style="margin-top:10px" width="15%" height="20px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
|
||||
</div>
|
||||
<div style="flex-shrink: 0;">
|
||||
<!-- Ici, ajoutez votre image -->
|
||||
<img alt="Gray rectangle" style="" width="130px" height="130px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; align-items: center; justify-content: start; width: 100%; max-width: 600px;margin-top:40px">
|
||||
<div style="flex-grow: 1; margin-right: 10px; margin-left:120px;width:200px">
|
||||
<h2>Lorem ipsum dolor sit amet, consectetur Lorem ipsum dolor sit amet, consectetur</h2>
|
||||
|
||||
Lorem ipsum dolor sit amet, consectetur
|
||||
adipiscing elit. Sed do eiusmod temxwshslkdsdsslpor incididunt ut labore et dolore magna <br>aliqua. Lorem, ipsum dolor sit amet consectetur adipisicing elit. Totam sit<br> autem nihil omnis! Odit ipsum repellat, voluptas accusantium dolores adipisci ut voluptates eius cumque dicta obcaecati
|
||||
<img alt="Gray rectangle" style="margin-top:10px" width="15%" height="20px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
|
||||
</div>
|
||||
<div style="flex-shrink: 0;">
|
||||
<!-- Ici, ajoutez votre image -->
|
||||
<img alt="Gray rectangle" style="" width="130px" height="130px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
</div>';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get commerce html
|
||||
* @return string $out html content
|
||||
*/
|
||||
function commerce_template()
|
||||
{
|
||||
$out = '
|
||||
<h1 style="margin-left:120px;">Lorem, ipsum dolor sit amet consectetur adipisicing elit sit amet consectetur</h1>
|
||||
<h2 style="margin-left:120px;">Lorem, ipsum dolor sit amet consectetur adipisicing elitsit amet consectetur adipisicing </h2>
|
||||
|
||||
<div style="font-family: Arial, sans-serif; background-color: #f7f7f7; padding: 16px; max-width: 600px; margin: 0 auto; box-sizing: border-box;">
|
||||
<div style="display: flex;">
|
||||
<div style="margin-bottom: 50px; flex: 1; padding-right: 8px;">
|
||||
<div>
|
||||
<img alt="Gray rectangle" style="margin-left:120px;margin-top:30px;" width="350px" height="100px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
<div style="margin-left:120px;background-color: #e0e0e0; padding: 8px; margin-bottom: 8px; text-indent: 50px;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<div style="margin-bottom: 10px; flex: 1; padding-left: 8px;">
|
||||
<div>
|
||||
<img alt="Gray rectangle" style="margin-left:120px;margin-top:30px;" width="350px" height="100px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
<div style="margin-left:120px;background-color: #e0e0e0; padding: 8px; margin-bottom: 8px; text-indent: 50px;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;">
|
||||
<div style="margin-bottom: 50px; flex: 1; padding-right: 8px;">
|
||||
<div>
|
||||
<img alt="Gray rectangle" style="margin-left:120px;margin-top:30px;" width="350px" height="100px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
<div style="margin-left:120px;background-color: #e0e0e0; padding: 8px; margin-bottom: 8px; text-indent: 50px;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit...
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<div style="margin-bottom: 10px; flex: 1; padding-left: 8px;">
|
||||
<div>
|
||||
<img alt="Gray rectangle" style="margin-left:120px;margin-top:30px;" width="350px" height="100px" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAABkCAIAAABM5OhcAAABGklEQVR4nO3SwQ3AIBDAsNLJb3SWIEJC9gR5ZM3MB6f9twN4k7FIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIuEsUgYi4SxSBiLhLFIGIvEBtxYAkgpLmAeAAAAAElFTkSuQmCC" />
|
||||
</div>
|
||||
<div style="margin-left:120px;background-color: #e0e0e0; padding: 8px; margin-bottom: 8px; text-indent: 50px;">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit<br>Lorem ipsum dolor sit amet, consectetur adipiscing elit...
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
';
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get basic html
|
||||
* @return string $out html content
|
||||
*/
|
||||
function text_template()
|
||||
{
|
||||
$out = '
|
||||
<h1 style="margin-left:150px">Lorem ipsum dolor sit amet consectetur adipisicing elit sit amet consectetur adipisicing elit.</h1>
|
||||
<h3 style="margin-left:150px">Lorem ipsum dolor sit amet consectetur adipisicing elit sit amet consectetur adipisicing elit.</h3>
|
||||
<p style="margin-left:150px">
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
Lorem ipsum dolor sit amet consectetur adipisicing elit. Commodi impedit molestias voluptatibus. Natus nulla sint totam illo? Hic name consequuntur id harum pariatur, quo illo quaerat minima tempore.
|
||||
</p>';
|
||||
|
||||
return $out;
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -110,7 +110,7 @@ class Cronjob extends CommonObject
|
||||
public $datelastresult = '';
|
||||
|
||||
/**
|
||||
* @var string Last result from end job execution
|
||||
* @var int Last result from end job execution
|
||||
*/
|
||||
public $lastresult;
|
||||
|
||||
@@ -263,10 +263,10 @@ class Cronjob extends CommonObject
|
||||
$this->unitfrequency = trim($this->unitfrequency);
|
||||
}
|
||||
if (isset($this->frequency)) {
|
||||
$this->frequency = trim($this->frequency);
|
||||
$this->frequency = (int) $this->frequency;
|
||||
}
|
||||
if (isset($this->status)) {
|
||||
$this->status = trim($this->status);
|
||||
$this->status = (int) $this->status;
|
||||
}
|
||||
if (isset($this->note_private)) {
|
||||
$this->note_private = trim($this->note_private);
|
||||
@@ -710,10 +710,10 @@ class Cronjob extends CommonObject
|
||||
$this->unitfrequency = trim($this->unitfrequency);
|
||||
}
|
||||
if (isset($this->frequency)) {
|
||||
$this->frequency = trim($this->frequency);
|
||||
$this->frequency = (int) $this->frequency;
|
||||
}
|
||||
if (isset($this->status)) {
|
||||
$this->status = trim($this->status);
|
||||
$this->status = (int) $this->status;
|
||||
}
|
||||
if (isset($this->note_private)) {
|
||||
$this->note_private = trim($this->note_private);
|
||||
@@ -945,7 +945,7 @@ class Cronjob extends CommonObject
|
||||
public function initAsSpecimen()
|
||||
{
|
||||
$this->id = 0;
|
||||
$this->ref = 0;
|
||||
$this->ref = '';
|
||||
$this->entity = 0;
|
||||
$this->tms = '';
|
||||
$this->datec = '';
|
||||
@@ -967,7 +967,7 @@ class Cronjob extends CommonObject
|
||||
$this->lastoutput = '';
|
||||
$this->lastresult = '';
|
||||
$this->unitfrequency = '';
|
||||
$this->frequency = '';
|
||||
$this->frequency = 0;
|
||||
$this->status = 0;
|
||||
$this->processing = 0;
|
||||
$this->pid = null;
|
||||
@@ -975,7 +975,7 @@ class Cronjob extends CommonObject
|
||||
$this->fk_user_author = 0;
|
||||
$this->fk_user_mod = 0;
|
||||
$this->note_private = '';
|
||||
$this->nbrun = '';
|
||||
$this->nbrun = 0;
|
||||
$this->maxrun = 100;
|
||||
$this->libname = '';
|
||||
}
|
||||
|
||||
@@ -662,7 +662,7 @@ class EcmFiles extends CommonObject
|
||||
$this->share = trim($this->share);
|
||||
}
|
||||
if (isset($this->entity)) {
|
||||
$this->entity = trim($this->entity);
|
||||
$this->entity = (int) $this->entity;
|
||||
}
|
||||
if (isset($this->filename)) {
|
||||
$this->filename = preg_replace('/\.noexe$/', '', trim($this->filename));
|
||||
@@ -690,7 +690,7 @@ class EcmFiles extends CommonObject
|
||||
$this->extraparams = trim($this->extraparams);
|
||||
}
|
||||
if (isset($this->fk_user_m)) {
|
||||
$this->fk_user_m = trim($this->fk_user_m);
|
||||
$this->fk_user_m = (int) $this->fk_user_m;
|
||||
}
|
||||
if (isset($this->acl)) {
|
||||
$this->acl = trim($this->acl);
|
||||
@@ -979,7 +979,7 @@ class EcmFiles extends CommonObject
|
||||
$this->date_c = (dol_now() - 3600 * 24 * 10);
|
||||
$this->date_m = '';
|
||||
$this->fk_user_c = $user->id;
|
||||
$this->fk_user_m = '';
|
||||
$this->fk_user_m = $user->id;
|
||||
$this->acl = '';
|
||||
$this->src_object_type = 'product';
|
||||
$this->src_object_id = 1;
|
||||
|
||||
@@ -758,8 +758,8 @@ if (empty($reshook)) {
|
||||
$stockLocation = 0;
|
||||
$qty = "qtyl".$line_id;
|
||||
$line->id = $line_id;
|
||||
$line->entrepot_id = GETPOST($stockLocation, 'int');
|
||||
$line->qty = GETPOST($qty, 'int');
|
||||
$line->entrepot_id = GETPOSTINT($stockLocation);
|
||||
$line->qty = GETPOSTFLOAT($qty);
|
||||
if ($line->update($user) < 0) {
|
||||
setEventMessages($line->error, $line->errors, 'errors');
|
||||
$error++;
|
||||
|
||||
@@ -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
|
||||
@@ -45,7 +45,7 @@ if ($user->socid > 0) {
|
||||
$socid = $user->socid;
|
||||
}
|
||||
$nowyear = dol_print_date(dol_now('gmt'), "%Y", 'gmt');
|
||||
$year = GETPOST('year') > 0 ? GETPOST('year') : $nowyear;
|
||||
$year = GETPOSTINT('year') > 0 ? GETPOSTINT('year') : $nowyear;
|
||||
$startyear = $year - (!getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS') ? 2 : max(1, min(10, getDolGlobalString('MAIN_STATS_GRAPHS_SHOW_N_YEARS'))));
|
||||
$endyear = $year;
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ if ($action == 'update' && !GETPOST("cancel") && $user->hasRight('projet', 'cree
|
||||
$object->date_start = dol_mktime(GETPOST('date_starthour', 'int'), GETPOST('date_startmin', 'int'), 0, GETPOST('date_startmonth', 'int'), GETPOST('date_startday', 'int'), GETPOST('date_startyear', 'int'));
|
||||
$object->date_end = dol_mktime(GETPOST('date_endhour', 'int'), GETPOST('date_endmin', 'int'), 0, GETPOST('date_endmonth', 'int'), GETPOST('date_endday', 'int'), GETPOST('date_endyear', 'int'));
|
||||
$object->progress = price2num(GETPOST('progress', 'alphanohtml'));
|
||||
$object->budget_amount = price2num(GETPOST('budget_amount', 'alphanohtml'));
|
||||
$object->budget_amount = GETPOSTFLOAT('budget_amount');
|
||||
|
||||
// Fill array 'array_options' with data from add form
|
||||
$ret = $extrafields->setOptionalsFromPost(null, $object, '@GETPOSTISSET');
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
* Copyright (C) 2020 Open-Dsi <support@open-dsi.fr>
|
||||
* Copyright (C) 2022 ButterflyOfFire <butterflyoffire+dolibarr@protonmail.com>
|
||||
* Copyright (C) 2023 Alexandre Janniaux <alexandre.janniaux@gmail.com>
|
||||
* Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
|
||||
*
|
||||
* 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
|
||||
@@ -310,8 +311,7 @@ class Societe extends CommonObject
|
||||
public $status = 1;
|
||||
|
||||
/**
|
||||
* Id of region
|
||||
* @var int
|
||||
* @var string region code
|
||||
*/
|
||||
public $region_code;
|
||||
|
||||
@@ -954,7 +954,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);
|
||||
}
|
||||
|
||||
@@ -1364,10 +1364,10 @@ class Societe extends CommonObject
|
||||
$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->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);
|
||||
@@ -1390,9 +1390,9 @@ class Societe extends CommonObject
|
||||
$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;
|
||||
}
|
||||
@@ -1412,12 +1412,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 = ($this->capital != '') ? (float) price2num(trim($this->capital)) : null;
|
||||
|
||||
$this->effectif_id = trim($this->effectif_id);
|
||||
$this->forme_juridique_code = trim($this->forme_juridique_code);
|
||||
@@ -1429,7 +1424,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);
|
||||
}
|
||||
|
||||
@@ -1574,7 +1569,7 @@ class Societe extends CommonObject
|
||||
$sql .= ",localtax2_value =0.000";
|
||||
}
|
||||
|
||||
$sql .= ",capital = ".($this->capital == '' ? "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");
|
||||
|
||||
@@ -4018,30 +4013,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 = getDolGlobalInt('MAIN_UNKNOWN_CUSTOMERS_ARE_COMPANIES');
|
||||
if (!empty($this->tva_intra)) {
|
||||
$isacompany = 1;
|
||||
$isACompany = 1;
|
||||
} elseif (!empty($this->idprof1) || !empty($this->idprof2) || !empty($this->idprof3) || !empty($this->idprof4) || !empty($this->idprof5) || !empty($this->idprof6)) {
|
||||
$isacompany = 1;
|
||||
$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 = 0;
|
||||
$isACompany = 0;
|
||||
} else {
|
||||
$isacompany = 1;
|
||||
$isACompany = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $isacompany;
|
||||
return boolval($isACompany);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4262,7 +4254,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;
|
||||
|
||||
@@ -4336,10 +4328,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];
|
||||
@@ -4422,7 +4415,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');
|
||||
@@ -4434,7 +4427,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 = 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);
|
||||
|
||||
BIN
htdocs/theme/common/mailtemplate/basic.png
Normal file
BIN
htdocs/theme/common/mailtemplate/basic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
BIN
htdocs/theme/common/mailtemplate/commerce.png
Normal file
BIN
htdocs/theme/common/mailtemplate/commerce.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
BIN
htdocs/theme/common/mailtemplate/empty.png
Normal file
BIN
htdocs/theme/common/mailtemplate/empty.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
htdocs/theme/common/mailtemplate/news.png
Normal file
BIN
htdocs/theme/common/mailtemplate/news.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
BIN
htdocs/theme/common/mailtemplate/text.png
Normal file
BIN
htdocs/theme/common/mailtemplate/text.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -2078,7 +2078,7 @@ class Website extends CommonObject
|
||||
$userId = fileowner($desfFile);
|
||||
if ($userId !== false) {
|
||||
// Obtain user information from the ID
|
||||
if (function_exists('posix_getpwuid')&& function_exists('posix_getpwuid')) {
|
||||
if (function_exists('posix_geteuid') && function_exists('posix_getpwuid')) {
|
||||
$uid = posix_geteuid();
|
||||
$userInfoM = posix_getpwuid($uid);
|
||||
|
||||
|
||||
@@ -1797,4 +1797,29 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* testRoundUpToNextMultiple
|
||||
*
|
||||
* @return void;
|
||||
*/
|
||||
public function testRoundUpToNextMultiple()
|
||||
{
|
||||
$this->assertEquals(roundUpToNextMultiple(39.5), 40);
|
||||
$this->assertEquals(roundUpToNextMultiple(40), 40);
|
||||
$this->assertEquals(roundUpToNextMultiple(40.4), 45);
|
||||
$this->assertEquals(roundUpToNextMultiple(40.5), 45);
|
||||
$this->assertEquals(roundUpToNextMultiple(44.5), 45);
|
||||
|
||||
$this->assertEquals(roundUpToNextMultiple(39.5, 10), 40);
|
||||
$this->assertEquals(roundUpToNextMultiple(40, 10), 40);
|
||||
$this->assertEquals(roundUpToNextMultiple(40.5, 10), 50);
|
||||
$this->assertEquals(roundUpToNextMultiple(44.5, 10), 50);
|
||||
|
||||
$this->assertEquals(roundUpToNextMultiple(39.5, 6), 42);
|
||||
$this->assertEquals(roundUpToNextMultiple(40, 6), 42);
|
||||
$this->assertEquals(roundUpToNextMultiple(40.5, 6), 42);
|
||||
$this->assertEquals(roundUpToNextMultiple(44.5, 6), 48);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user