forked from Wavyzz/dolibarr
Merge branch '22_accfydefault' of https://github.com/aspangaro/dolibarr into 22_accfydefault
This commit is contained in:
103
ChangeLog
103
ChangeLog
@@ -238,6 +238,109 @@ The following changes may create regressions for some external modules, but were
|
||||
* If you were using the substitution key __MEMBER_CIVILITY__, you must now use __MEMBER_TITLE__
|
||||
|
||||
|
||||
***** ChangeLog for 20.0.4 compared to 20.0.2 *****
|
||||
FIX: $this->origin_object can not be instance of CommandeFournisseur if it is already an instanceof CommonObject
|
||||
FIX: 17.0 API endpoints "PUT": prevent overwriting all extrafields if only some are supplied in the request cf. PR #29237
|
||||
FIX: 17.0 - collisions in cache for dol_getIdFromCode
|
||||
FIX: #18713
|
||||
FIX: 20.0 - PHP8 fatal when creating a reception unless corresponding PDF model is enabled
|
||||
FIX: #21294 Stock import sql query
|
||||
FIX: #26250 fatal error on kit
|
||||
FIX: #28702
|
||||
FIX: #29624 - substitution of __DATE_DELIVERY__
|
||||
FIX: #32113
|
||||
FIX: #32186
|
||||
FIX: #32339 Delete a loan settlement is partial
|
||||
FIX: #32387
|
||||
FIX: #32477 Loan - Insurance amount need decimals
|
||||
FIX: #32611
|
||||
FIX: #32736 + avoid php warning
|
||||
FIX: #32743
|
||||
FIX: #32765 JS Error: Uncaught TypeError
|
||||
FIX: #32801 VAT type is inverted in form VAT selector
|
||||
FIX: #32840
|
||||
FIX: #32843
|
||||
FIX: #32880 - Tags are using a special rendering.
|
||||
FIX: add other fields
|
||||
FIX: autofill price with multicurrency on supplier doc
|
||||
FIX: avoid phan error
|
||||
FIX: avoid php8 warnings
|
||||
FIX: avoid warning with the new Dolistore website
|
||||
FIX: backport from develop to avoid php warning
|
||||
FIX: Bad calculation of the theoretical stock. Did not take into account
|
||||
FIX: bad dispatched quantities for batches on shipment card
|
||||
FIX: Brian is in the kitchen
|
||||
FIX: broken feature, compatibility with "Default search filters"
|
||||
FIX: broken feature with check $pa_ht_isemptystring
|
||||
FIX: Bug on select user on time.php (all project list)
|
||||
FIX: can not delete files in task card
|
||||
FIX: Check "$search_sale" only if it's an internal user
|
||||
FIX: clean unique extrafields when create product combination
|
||||
FIX: code not visible correctly into view of dictionary
|
||||
FIX: compatibility between next_prev_filter and hook return
|
||||
FIX: compatibility with multicompany
|
||||
FIX: Complete path was started in #17243 for pdf_cannelle
|
||||
FIX: Continue for eagle_proforma
|
||||
FIX: country id is not saved when we provide country_code only
|
||||
FIX: #CVE-2024-34051
|
||||
FIX: delete supplier order when at least one line linked to customer order line
|
||||
FIX: display error when loan can't be deleted
|
||||
FIX: display full tree on shipment card when a kit contains a same component in other sub-kit
|
||||
FIX: DROP INDEX IF EXISTS is not possible !
|
||||
FIX: extrafields lost during creation from rec invoice
|
||||
FIX: FEC import
|
||||
FIX: Fiscal year - missing translation on status
|
||||
FIX: Fix return value of hook sendMail when hook return -1 who must be return false in sendfile() function
|
||||
FIX: GETPOST('private_message')
|
||||
FIX: glob is better for search files with wildcard + avoid warning
|
||||
FIX: if $force_entity = 0 ($force_entity != 'default') = false
|
||||
FIX: Loan - Insurance amount need decimals
|
||||
FIX: Many status on invoice linked object block
|
||||
FIX: merge problem
|
||||
FIX: missing company name if dontaion is linked to third party
|
||||
FIX: missing default values if $objsrc or $soc fields are empty
|
||||
FIX: missing edit extrafields inline for member card
|
||||
FIX: missing quick edit for extrafields
|
||||
FIX: more bugs and warnings
|
||||
FIX: Multilangs : PDF lines description
|
||||
FIX: Must not have both thirdparty and member.
|
||||
FIX: ODT substitution when many HTML tags in string
|
||||
FIX: on the road again
|
||||
FIX: pdf_cannelle (supplier_invoice) add background - Complete #17243
|
||||
FIX: Prices didn't update when clone a propale with update prices
|
||||
FIX: product variants copy: also copy multiprice variations
|
||||
FIX: refactorize (maybe broken feature for not received completely)
|
||||
FIX: remove debug trace
|
||||
FIX: remove socid when cloning a project without third parties
|
||||
FIX: removes traces of <<<HEAD conflicts following the postponement of branch 13 modifications (#32014)
|
||||
FIX: remove unused code
|
||||
FIX: same broken feature for propal and invoice
|
||||
FIX: select 2 no record found translate
|
||||
FIX: selectcontact is loading all contacts if socid is empty and MAIN_ACTIONCOM_CAN_ADD_ANY_CONTACT is not set
|
||||
FIX: selectcontact is loading all contacts when update event
|
||||
FIX: select group and severity search fields on ticket list
|
||||
FIX: send email to assigned user on ticket create
|
||||
FIX: sql error with the new sql forge filter
|
||||
FIX: sql "order by" is defined twice
|
||||
FIX: status ticket update for new message
|
||||
FIX: swap tests
|
||||
FIX: switch on/off status of a page of the second website.
|
||||
FIX: There were many status indicator in the invoice linked object block (propal card)
|
||||
FIX: uniformize code
|
||||
FIX: units used scale and scale is an integer
|
||||
FIX: wrong alias table
|
||||
FIX: wrong file path + avoid warning
|
||||
FIX: wrong filter format
|
||||
FIX: wrong "fournisseur" var value checking
|
||||
FIX: wrong left margin
|
||||
FIX: wrong message on update shipment
|
||||
FIX: wrong ODT path for multicompany
|
||||
FIX: wrong path for odt models
|
||||
FIX: wrong search filter, empty product unit is "none"
|
||||
FIX: wrong update function parameter
|
||||
FIX: some wrong var type
|
||||
FIX: some wrong var name
|
||||
|
||||
***** ChangeLog for 20.0.3 compared to 20.0.2 *****
|
||||
FIX: 17.0 - missing error handling for FactureRec::fetch in card-rec.php
|
||||
FIX: 17.0 - warnings due to uninitialized variables + delete code that doesn't apply to recurring invoices (AFAIK, there is no recurring credit note feature)
|
||||
|
||||
@@ -36,7 +36,7 @@ $PUBLISHBETARC="dolibarr\@vmprod1.dolibarr.org:/home/dolibarr/asso.dolibarr.org/
|
||||
"RPM_FEDORA"=>"rpmbuild",
|
||||
"RPM_MANDRIVA"=>"rpmbuild",
|
||||
"RPM_OPENSUSE"=>"rpmbuild",
|
||||
"DEB"=>"dpkg",
|
||||
"DEB"=>"dpkg,po2debconf", # need also debhelper
|
||||
"FLATPACK"=>"flatpack",
|
||||
"EXEDOLIWAMP"=>"ISCC.exe",
|
||||
"SNAPSHOT"=>"tar"
|
||||
@@ -85,8 +85,9 @@ if (! $ENV{"DESTIBETARC"} || ! $ENV{"DESTISTABLE"})
|
||||
print "set DESTIBETARC=c:/tmp\n";
|
||||
print "set DESTISTABLE=c:/tmp\n";
|
||||
print "\n";
|
||||
print "Example: DESTIBETARC='/media/HDDATA1_LD/Mes Sites/Web/Dolibarr/dolibarr.org/files/lastbuild'\n";
|
||||
print "Example: DESTISTABLE='/media/HDDATA1_LD/Mes Sites/Web/Dolibarr/dolibarr.org/files/stable'\n";
|
||||
print "Example in .bashrc:\n";
|
||||
print "export DESTIBETARC='/mnt/HDDATA1_LD/Mes Archives/Doli/dolibarr/lastbuild'\n";
|
||||
print "export DESTISTABLE='/mnt/HDDATA1_LD/Mes Archives/Doli/dolibarr/stable'\n";
|
||||
sleep 2;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
@@ -44,8 +44,22 @@ the project: `pre-commit-config.yaml`.
|
||||
The good file redirects output to the error channel so your IDE will be able to catch the error.
|
||||
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
* If you get error "ModuleNotFoundError: No module named 'platformdirs'"
|
||||
|
||||
Install the python package with
|
||||
`pip3 install platformdirs` or `pip3 install platformdirs --break-system-packages`
|
||||
|
||||
* If you get error "ERROR: PHP_CodeSniffer requires the tokenizer, xmlwriter and SimpleXML extensions to be enabled. Please enable xmlwriter and SimpleXML."
|
||||
|
||||
Install the PHP package xml
|
||||
`sudo apt install php-simplexml`
|
||||
|
||||
|
||||
### Tips
|
||||
|
||||
|
||||
After installing `pre-commit` onto your local git clone, pre-commit will run
|
||||
on every commit. The first time, all tools required by pre-commit will be installed
|
||||
into ~/.cache/pre-commit
|
||||
|
||||
@@ -100,14 +100,14 @@ $formother = new FormOther($db);
|
||||
$form = new Form($db);
|
||||
|
||||
if (empty($search_date_start) && !GETPOSTISSET('formfilteraction')) {
|
||||
$sql = "SELECT date_start, date_end";
|
||||
$sql .=" FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
|
||||
if (getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT')) {
|
||||
$sql .= " WHERE rowid = " . getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT');
|
||||
} else {
|
||||
$sql .= " WHERE date_start < '" . $db->idate(dol_now()) . "' and date_end > '" . $db->idate(dol_now()) . "'";
|
||||
}
|
||||
$sql .= $db->plimit(1);
|
||||
$sql = "SELECT date_start, date_end";
|
||||
$sql .=" FROM ".MAIN_DB_PREFIX."accounting_fiscalyear ";
|
||||
if (getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT')) {
|
||||
$sql .= " WHERE rowid = " . getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT');
|
||||
} else {
|
||||
$sql .= " WHERE date_start < '" . $db->idate(dol_now()) . "' and date_end > '" . $db->idate(dol_now()) . "'";
|
||||
}
|
||||
$sql .= $db->plimit(1);
|
||||
$res = $db->query($sql);
|
||||
|
||||
if ($db->num_rows($res) > 0) {
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formaccounting.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfiscalyear.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/accounting.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
@@ -881,14 +880,6 @@ if ($massactionbutton && $contextpage != 'poslist') {
|
||||
$selectedfields .= $form->showCheckAddButtons('checkforselect', 1);
|
||||
}
|
||||
|
||||
if (getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT')) {
|
||||
$fiscalYear = getDolGlobalInt('ACCOUNTANCY_FISCALYEAR_DEFAULT');
|
||||
$useempty = 0;
|
||||
} else {
|
||||
$fiscalYear = 0;
|
||||
$useempty = 1;
|
||||
}
|
||||
|
||||
$moreforfilter = '';
|
||||
$moreforfilter .= '<div class="divsearchfield">';
|
||||
$moreforfilter .= $langs->trans('AccountingCategory').': ';
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
|
||||
require_once '../lib/ai.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT."/ai/lib/ai.lib.php";
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
@@ -39,6 +39,8 @@ require_once '../lib/ai.lib.php';
|
||||
|
||||
$langs->loadLangs(array("admin", "website", "other"));
|
||||
|
||||
$arrayofaifeatures = getLitOfAIFeatures();
|
||||
|
||||
// Parameters
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$backtopage = GETPOST('backtopage', 'alpha');
|
||||
@@ -81,18 +83,6 @@ $setupnotempty += count($formSetup->items);
|
||||
|
||||
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
|
||||
|
||||
// List of AI features
|
||||
$arrayofaifeatures = array(
|
||||
'textgenerationemail' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("EmailContent").')', 'picto'=>'', 'status'=>'development'),
|
||||
'textgenerationwebpage' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("WebsitePage").')', 'picto'=>'', 'status'=>'development'),
|
||||
'textgeneration' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("Other").')', 'picto'=>'', 'status'=>'notused'),
|
||||
'imagegeneration' => array('label' => 'ImageGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'videogeneration' => array('label' => 'VideoGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'audiogeneration' => array('label' => 'AudioGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'transcription' => array('label' => 'Transcription', 'picto'=>'', 'status'=>'notused'),
|
||||
'translation' => array('label' => 'Translation', 'picto'=>'', 'status'=>'notused')
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
* Actions
|
||||
@@ -213,7 +203,7 @@ print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
|
||||
|
||||
// Configuration header
|
||||
$head = aiAdminPrepareHead();
|
||||
print dol_get_fiche_head($head, 'custom', $langs->trans($title), -1, "fa-microchip");
|
||||
print dol_get_fiche_head($head, 'custom', $langs->trans($title), -1, "ai");
|
||||
|
||||
//$newbutton = '<a href="'.$_SERVER["PHP_SELF"].'?action=create">'.$langs->trans("New").'</a>';
|
||||
$newbutton = '';
|
||||
@@ -279,6 +269,7 @@ if ($action == 'edit' || $action == 'deleteproperty') {
|
||||
|
||||
$out .= '</td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
$out .= '<tr class="oddeven">';
|
||||
$out .= '<td class="col-setup-title">';
|
||||
$out .= '<span id="prePrompt" class="spanforparamtooltip">';
|
||||
@@ -314,6 +305,7 @@ if ($action == 'edit' || $action == 'deleteproperty') {
|
||||
|
||||
$out .= $form->buttonsSaveCancel("Add", "");
|
||||
$out .= '</form>';
|
||||
|
||||
$out .= '<br><br><br>';
|
||||
|
||||
print $out;
|
||||
@@ -374,7 +366,7 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
||||
$out .= '<tr>';
|
||||
$out .= '<td></td>';
|
||||
$out .= '<td>';
|
||||
$out .= '<input type="submit" class="button small submitBtn reposition" name="modify" data-index="'.$key.'" value="'.dol_escape_htmltag($langs->trans("Modify")).'"/>';
|
||||
$out .= '<input type="submit" class="button small submitBtn reposition" name="modify" data-index="'.$key.'" value="'.dol_escape_htmltag($langs->trans("Save")).'"/>';
|
||||
$out .= ' ';
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
@@ -383,6 +375,8 @@ if ($action == 'edit' || $action == 'create' || $action == 'deleteproperty') {
|
||||
$formmail = new FormMail($db);
|
||||
$htmlname = $key;
|
||||
|
||||
$out .= '<br><br>';
|
||||
|
||||
// Fill $out
|
||||
include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
|
||||
require_once '../lib/ai.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT."/core/class/doleditor.class.php";
|
||||
require_once DOL_DOCUMENT_ROOT."/ai/lib/ai.lib.php";
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
@@ -38,7 +39,9 @@ require_once '../lib/ai.lib.php';
|
||||
* @var User $user
|
||||
*/
|
||||
|
||||
$langs->loadLangs(array("admin"));
|
||||
$langs->loadLangs(array("admin", "website", "other"));
|
||||
|
||||
$arrayofaifeatures = getLitOfAIFeatures();
|
||||
|
||||
// Parameters
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
@@ -49,10 +52,7 @@ if (empty($action)) {
|
||||
$action = 'edit';
|
||||
}
|
||||
|
||||
$value = GETPOST('value', 'alpha');
|
||||
$label = GETPOST('label', 'alpha');
|
||||
$scandir = GETPOST('scan_dir', 'alpha');
|
||||
$type = 'myobject';
|
||||
$content = GETPOST('content');
|
||||
|
||||
$error = 0;
|
||||
$setupnotempty = 0;
|
||||
@@ -69,6 +69,7 @@ $formSetup = new FormSetup($db);
|
||||
|
||||
// List all available IA
|
||||
$arrayofia = array(
|
||||
'-1' => $langs->trans('SelectAService'),
|
||||
'chatgpt' => 'ChatGPT',
|
||||
'groq' => 'Groq',
|
||||
'custom' => 'Custom'
|
||||
@@ -89,14 +90,14 @@ foreach ($arrayofia as $ia => $ialabel) {
|
||||
$item->nameText = $langs->trans("AI_API_KEY").' ('.$ialabel.')';
|
||||
$item->defaultFieldValue = '';
|
||||
$item->fieldParams['hideGenerateButton'] = 1;
|
||||
$item->fieldParams['trClass'] = $ia;
|
||||
$item->cssClass = 'minwidth500 text-security';
|
||||
$item->fieldParams['trClass'] = 'iaservice '.$ia;
|
||||
$item->cssClass = 'minwidth500 text-security input'.$ia;
|
||||
|
||||
$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';
|
||||
$item->fieldParams['trClass'] = 'iaservice '.$ia;
|
||||
$item->cssClass = 'minwidth500 input'.$ia;
|
||||
}
|
||||
|
||||
$setupnotempty = + count($formSetup->items);
|
||||
@@ -140,7 +141,7 @@ print load_fiche_titre($langs->trans($title), $linkback, 'title_setup');
|
||||
|
||||
// Configuration header
|
||||
$head = aiAdminPrepareHead();
|
||||
print dol_get_fiche_head($head, 'settings', $langs->trans($title), -1, "fa-microchip");
|
||||
print dol_get_fiche_head($head, 'settings', $langs->trans($title), -1, "ai");
|
||||
|
||||
|
||||
if ($action == 'edit') {
|
||||
@@ -160,8 +161,86 @@ if (empty($setupnotempty)) {
|
||||
print '<br>'.$langs->trans("NothingToSetup");
|
||||
}
|
||||
|
||||
print '<script type="text/javascript">
|
||||
jQuery(document).ready(function() {
|
||||
function showHideAIService(aiservice) {
|
||||
console.log("We select the AI service "+aiservice);
|
||||
jQuery(".iaservice").hide();
|
||||
|
||||
if (aiservice != "-1") {
|
||||
jQuery(".iaservice."+aiservice).show();
|
||||
}
|
||||
}
|
||||
|
||||
jQuery("#AI_API_SERVICE").change(function() {
|
||||
var aiservice = $(this).val();
|
||||
|
||||
showHideAIService(aiservice);
|
||||
});
|
||||
|
||||
showHideAIService("'.getDolGlobalString("AI_API_SERVICE").'");
|
||||
});
|
||||
</script>';
|
||||
|
||||
// Page end
|
||||
print dol_get_fiche_end();
|
||||
|
||||
|
||||
if (getDolGlobalString("AI_API_SERVICE")) {
|
||||
// Section to test
|
||||
print '<form action="'.$_SERVER["PHP_SELF"].'" method="POST">';
|
||||
print '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
print '<input type="hidden" name="action" value="add">';
|
||||
print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
|
||||
|
||||
$functioncode = GETPOST('functioncode');
|
||||
$out = '';
|
||||
|
||||
if ($functioncode) {
|
||||
$labeloffeature = empty($arrayofaifeatures[GETPOST('functioncode')]['label']) ? 'Undefined' : $arrayofaifeatures[GETPOST('functioncode')]['label'];
|
||||
|
||||
//$out .= $langs->trans("Test").' '.$labeloffeature.'...<br><br>';
|
||||
|
||||
if (GETPOST('functioncode') == 'textgenerationemail') {
|
||||
$key = 'textgenerationemail'; // The HTML ID of field to fill
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
|
||||
$showlinktoai = $key; // 'textgeneration', 'imagegeneration', ...
|
||||
$showlinktoailabel = $langs->trans("Test").' '.$labeloffeature;
|
||||
$showlinktolayout = 0;
|
||||
$formmail = new FormMail($db);
|
||||
$htmlname = $key;
|
||||
|
||||
// Fill $out
|
||||
include DOL_DOCUMENT_ROOT.'/core/tpl/formlayoutai.tpl.php';
|
||||
|
||||
$out .= '<div id="'.$key.'"></div>';
|
||||
} else {
|
||||
$out .= $langs->trans("FeatureNotYetAvailable").'<br><br>';
|
||||
$functioncode = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$functioncode) {
|
||||
// Combo list of AI features
|
||||
$out .= '<select name="functioncode" id="functioncode" class="flat minwidth300" placeholder="Test feature">';
|
||||
$out .= '<option value="-1">'.$langs->trans("SelectFeatureToTest").'</option>';
|
||||
foreach ($arrayofaifeatures as $key => $val) {
|
||||
$labelhtml = $langs->trans($arrayofaifeatures[$key]['label']).($arrayofaifeatures[$key]['status'] == 'notused' ? ' <span class="opacitymedium">('.$langs->trans("NotYetAvailable").')</span>' : "");
|
||||
$labeltext = $langs->trans($arrayofaifeatures[$key]['label']);
|
||||
$out .= '<option value="'.$key.'" data-html="'.dol_escape_htmltag($labelhtml).'"';
|
||||
$out .= (GETPOST('functioncode') == $key ? ' selected="selected"' : '');
|
||||
$out .= '>'.dol_escape_htmltag($labeltext).'</option>';
|
||||
}
|
||||
$out .= '</select>';
|
||||
$out .= ajax_combobox("functioncode");
|
||||
|
||||
$out .= '<input class="button small" type="submit" name="testmode" value="'.$langs->trans("Test").'">';
|
||||
}
|
||||
print $out;
|
||||
|
||||
print '</form>';
|
||||
}
|
||||
|
||||
llxFooter();
|
||||
$db->close();
|
||||
|
||||
@@ -81,15 +81,17 @@ $format = empty($jsonData['format']) ? '' : $jsonData['format'];
|
||||
|
||||
$generatedContent = $ai->generateContent($instructions, 'auto', $function, $format);
|
||||
|
||||
if (is_array($generatedContent) && $generatedContent['error']) {
|
||||
if (is_null($generatedContent) || (is_array($generatedContent) && $generatedContent['error'])) {
|
||||
// Output error
|
||||
if (!empty($generatedContent['code']) && $generatedContent['code'] == 429) {
|
||||
print "Quota or allowed period exceeded. Retry Later !";
|
||||
} elseif ($generatedContent['code'] >= 400) {
|
||||
} elseif (!empty($generatedContent['code']) && $generatedContent['code'] >= 400) {
|
||||
print "Error : " . $generatedContent['message'];
|
||||
print '<br><a href="'.DOL_MAIN_URL_ROOT.'/ai/admin/setup.php">'.$langs->trans('ErrorGoToModuleSetup').'</a>';
|
||||
} else {
|
||||
} elseif (!empty($generatedContent['message'])) {
|
||||
print "Error returned by API call: " . $generatedContent['message'];
|
||||
} else {
|
||||
print "Error API returned no answer";
|
||||
}
|
||||
} else {
|
||||
if ($function == 'textgenerationemail' || $function == 'textgenerationwebpage') {
|
||||
|
||||
@@ -80,6 +80,8 @@ class Ai
|
||||
*/
|
||||
public function generateContent($instructions, $model = 'auto', $function = 'textgeneration', $format = '')
|
||||
{
|
||||
global $dolibarr_main_data_root;
|
||||
|
||||
if (empty($this->apiKey)) {
|
||||
return array('error' => true, 'message' => 'API key is not defined for the AI enabled service ('.$this->apiService.')');
|
||||
}
|
||||
@@ -192,14 +194,14 @@ class Ai
|
||||
|
||||
if (isset($configurations[$function])) {
|
||||
if (isset($configurations[$function]['prePrompt'])) {
|
||||
$prePrompt = $configurations[$function]['prePrompt']; // TODO We can send prePrompt into a separated message with role system.
|
||||
$prePrompt = $configurations[$function]['prePrompt'];
|
||||
}
|
||||
|
||||
if (isset($configurations[$function]['postPrompt'])) {
|
||||
$postPrompt = $configurations[$function]['postPrompt'];
|
||||
}
|
||||
}
|
||||
$fullInstructions = ($prePrompt ? $prePrompt.' ' : '').$instructions.($postPrompt ? '. '.$postPrompt : '');
|
||||
$fullInstructions = $instructions.($postPrompt ? (preg_match('/[\.\!\?]$/', $instructions) ? '' : '.').' '.$postPrompt : '');
|
||||
|
||||
// Set payload string
|
||||
/*{
|
||||
@@ -224,18 +226,48 @@ class Ai
|
||||
"temperature": 0.7,
|
||||
"top_p": 0.95
|
||||
}*/
|
||||
$payload = json_encode([
|
||||
'messages' => [
|
||||
['role' => 'user', 'content' => $fullInstructions]
|
||||
],
|
||||
'model' => $model,
|
||||
//'stream' => false
|
||||
]);
|
||||
|
||||
$headers = ([
|
||||
$arrayforpayload = array(
|
||||
'messages' => array(array('role' => 'user', 'content' => $fullInstructions)),
|
||||
'model' => $model,
|
||||
);
|
||||
|
||||
// Add a system message
|
||||
$addDateTimeContext = false;
|
||||
if ($addDateTimeContext) { // @phpstan-ignore-line
|
||||
$prePrompt = ($prePrompt ? $prePrompt.(preg_match('/[\.\!\?]$/', $prePrompt) ? '' : '.').' ' : '').'Today we are '.dol_print_date(dol_now(), 'dayhourtext');
|
||||
}
|
||||
if ($prePrompt) {
|
||||
$arrayforpayload['messages'][] = array('role' => 'system', 'content' => $prePrompt);
|
||||
}
|
||||
|
||||
/*
|
||||
$arrayforpayload['temperature'] = 0.7;
|
||||
$arrayforpayload['max_tokens'] = -1;
|
||||
$arrayforpayload['stream'] = false;
|
||||
*/
|
||||
|
||||
$payload = json_encode($arrayforpayload);
|
||||
|
||||
$headers = array(
|
||||
'Authorization: Bearer ' . $this->apiKey,
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
);
|
||||
|
||||
if (getDolGlobalString("AI_DEBUG")) {
|
||||
if (@is_writable($dolibarr_main_data_root)) { // Avoid fatal error on fopen with open_basedir
|
||||
$outputfile = $dolibarr_main_data_root."/dolibarr_ai.log";
|
||||
$fp = fopen($outputfile, "w"); // overwrite
|
||||
|
||||
if ($fp) {
|
||||
fwrite($fp, var_export($headers, true)."\n");
|
||||
fwrite($fp, var_export($payload, true)."\n");
|
||||
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$localurl = 2; // Accept both local and external endpoints
|
||||
$response = getURLContent($this->apiEndpoint, 'POST', $payload, 1, $headers, array('http', 'https'), $localurl);
|
||||
@@ -248,7 +280,17 @@ class Ai
|
||||
}
|
||||
|
||||
if (getDolGlobalString("AI_DEBUG")) {
|
||||
dol_syslog("response content = ".var_export($response['content'], true));
|
||||
if (@is_writable($dolibarr_main_data_root)) { // Avoid fatal error on fopen with open_basedir
|
||||
$outputfile = $dolibarr_main_data_root."/dolibarr_ai.log";
|
||||
$fp = fopen($outputfile, "a");
|
||||
|
||||
if ($fp) {
|
||||
fwrite($fp, var_export((empty($response['content']) ? 'No content result' : $response['content']), true)."\n");
|
||||
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Decode JSON response
|
||||
|
||||
@@ -23,6 +23,30 @@
|
||||
* \brief Library files with common functions for Ai
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Prepare admin pages header
|
||||
*
|
||||
* @return array<string,array<string,string>>
|
||||
*/
|
||||
function getLitOfAIFeatures()
|
||||
{
|
||||
global $langs;
|
||||
|
||||
$arrayofaifeatures = array(
|
||||
'textgenerationemail' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("EmailContent").')', 'picto'=>'', 'status'=>'dolibarr'),
|
||||
'textgenerationwebpage' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("WebsitePage").')', 'picto'=>'', 'status'=>'dolibarr'),
|
||||
'textgeneration' => array('label' => $langs->trans('TextGeneration').' ('.$langs->trans("Other").')', 'picto'=>'', 'status'=>'notused'),
|
||||
'imagegeneration' => array('label' => 'ImageGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'videogeneration' => array('label' => 'VideoGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'audiogeneration' => array('label' => 'AudioGeneration', 'picto'=>'', 'status'=>'notused'),
|
||||
'transcription' => array('label' => 'Transcription', 'picto'=>'', 'status'=>'notused'),
|
||||
'translation' => array('label' => 'Translation', 'picto'=>'', 'status'=>'notused')
|
||||
);
|
||||
|
||||
return $arrayofaifeatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare admin pages header
|
||||
*
|
||||
|
||||
@@ -53,10 +53,7 @@ require_once DOL_DOCUMENT_ROOT.'/core/class/infobox.class.php';
|
||||
|
||||
$boxid = GETPOSTINT('boxid');
|
||||
$boxorder = GETPOST('boxorder');
|
||||
$zone = GETPOST('zone'); // Can be key for zone
|
||||
if ($zone !== '') {
|
||||
$zone = (int) $zone;
|
||||
}
|
||||
$zone = GETPOST('zone'); // Can be '0' or '1' or 'pagename'...
|
||||
$userid = GETPOSTINT('userid');
|
||||
|
||||
// Security check
|
||||
@@ -91,7 +88,7 @@ if ($boxorder && $zone != '' && $userid > 0) {
|
||||
// boxorder value is the target order: "A:idboxA1,idboxA2,A-B:idboxB1,idboxB2,B"
|
||||
dol_syslog("AjaxBox boxorder=".$boxorder." zone=".$zone." userid=".$userid, LOG_DEBUG);
|
||||
|
||||
$result = InfoBox::saveboxorder($db, (int) $zone, $boxorder, $userid);
|
||||
$result = InfoBox::saveboxorder($db, $zone, $boxorder, $userid);
|
||||
if ($result > 0) {
|
||||
$langs->load("boxes");
|
||||
if (!GETPOST('closing')) {
|
||||
|
||||
@@ -1483,24 +1483,26 @@ class CMailFile
|
||||
$outputfile = $dolibarr_main_data_root."/dolibarr_mail.log";
|
||||
$fp = fopen($outputfile, "w"); // overwrite
|
||||
|
||||
if ($this->sendmode == 'mail') {
|
||||
fwrite($fp, $this->headers);
|
||||
fwrite($fp, $this->eol); // This eol is added by the mail function, so we add it in log
|
||||
fwrite($fp, $this->message);
|
||||
} elseif ($this->sendmode == 'smtps') {
|
||||
fwrite($fp, $this->smtps->log); // this->smtps->log is filled only if MAIN_MAIL_DEBUG was set to on
|
||||
} elseif ($this->sendmode == 'swiftmailer') {
|
||||
fwrite($fp, "smtpheader=\n".$this->message->getHeaders()->toString()."\n");
|
||||
fwrite($fp, $this->logger->dump()); // this->logger is filled only if MAIN_MAIL_DEBUG was set to on
|
||||
}
|
||||
if ($fp) {
|
||||
if ($this->sendmode == 'mail') {
|
||||
fwrite($fp, $this->headers);
|
||||
fwrite($fp, $this->eol); // This eol is added by the mail function, so we add it in log
|
||||
fwrite($fp, $this->message);
|
||||
} elseif ($this->sendmode == 'smtps') {
|
||||
fwrite($fp, $this->smtps->log); // this->smtps->log is filled only if MAIN_MAIL_DEBUG was set to on
|
||||
} elseif ($this->sendmode == 'swiftmailer') {
|
||||
fwrite($fp, "smtpheader=\n".$this->message->getHeaders()->toString()."\n");
|
||||
fwrite($fp, $this->logger->dump()); // this->logger is filled only if MAIN_MAIL_DEBUG was set to on
|
||||
}
|
||||
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
|
||||
// Move dolibarr_mail.log into a dolibarr_mail.log.v123456789
|
||||
if (getDolGlobalInt('MAIN_MAIL_DEBUG_LOG_WITH_DATE')) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
archiveOrBackupFile($outputfile, getDolGlobalInt('MAIN_MAIL_DEBUG_LOG_WITH_DATE'));
|
||||
// Move dolibarr_mail.log into a dolibarr_mail.log.v123456789
|
||||
if (getDolGlobalInt('MAIN_MAIL_DEBUG_LOG_WITH_DATE')) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
archiveOrBackupFile($outputfile, getDolGlobalInt('MAIN_MAIL_DEBUG_LOG_WITH_DATE'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10360,9 +10360,9 @@ abstract class CommonObject
|
||||
/**
|
||||
* Create object in the database
|
||||
*
|
||||
* @param User $user User that creates
|
||||
* @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
|
||||
* @return int<-1,max> Return integer <0 if KO, Id of created object if OK
|
||||
* @param User $user User that creates
|
||||
* @param int<0,1> $notrigger 0=launch triggers after, 1=disable triggers
|
||||
* @return int<-1,max> Return integer <0 if KO, Id of created object if OK
|
||||
*/
|
||||
public function createCommon(User $user, $notrigger = 0)
|
||||
{
|
||||
@@ -10382,6 +10382,7 @@ abstract class CommonObject
|
||||
$fieldvalues['date_creation'] = $this->db->idate($now);
|
||||
$this->date_creation = $this->db->idate($now);
|
||||
}
|
||||
// For backward compatibility, if a property ->fk_user_creat exists and not filled.
|
||||
if (array_key_exists('fk_user_creat', $fieldvalues) && !($fieldvalues['fk_user_creat'] > 0)) {
|
||||
$fieldvalues['fk_user_creat'] = $user->id;
|
||||
$this->fk_user_creat = $user->id;
|
||||
|
||||
@@ -1493,6 +1493,7 @@ class FormMail extends Form
|
||||
* @param string $format Format for output ('', 'html', ...)
|
||||
* @param string $htmlContent HTML name of WYSIWYG field
|
||||
* @return string HTML code to ask AI instruction and autofill result
|
||||
* TODO Move into a file html.formai.class.php
|
||||
*/
|
||||
public function getSectionForAIPrompt($function = 'textgeneration', $format = '', $htmlContent = 'message')
|
||||
{
|
||||
@@ -1502,7 +1503,7 @@ class FormMail extends Form
|
||||
|
||||
$htmlContent = preg_replace('/[^a-z0-9_]/', '', $htmlContent);
|
||||
|
||||
$out = '<div id="ai_input'.$htmlContent.'" class="hidden paddingtop paddingbottom">';
|
||||
$out = '<div id="ai_input'.$htmlContent.'" class="ai_input'.$htmlContent.' hidden paddingtop paddingbottom">';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions'.$htmlContent.'" name="instruction" placeholder="'.$langs->trans("EnterYourAIPromptHere").'..." />';
|
||||
$out .= '<input id="generate_button'.$htmlContent.'" type="button" class="button smallpaddingimp" value="'.$langs->trans('Generate').'"/>';
|
||||
$out .= '<div id="ai_status_message'.$htmlContent.'" class="fieldrequired hideobject marginrightonly margintoponly">';
|
||||
@@ -1526,7 +1527,7 @@ class FormMail extends Form
|
||||
});
|
||||
|
||||
$('#generate_button".$htmlContent."').click(function() {
|
||||
console.log('We click on generate_button".$htmlContent." ai button');
|
||||
console.log('We click on generate_button".$htmlContent." ai button, so we make an ajax on url /ai/ajax/generate_content.php');
|
||||
|
||||
var instructions = $('#ai_instructions".$htmlContent."').val();
|
||||
var timeoutfinished = 0;
|
||||
@@ -1589,49 +1590,50 @@ class FormMail extends Form
|
||||
CKEDITOR.instances.".$htmlContent.".setReadOnly(1);
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".currentToken()."',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'format': '".dol_escape_js($format)."', /* the format for output */
|
||||
'function': '".dol_escape_js($function)."', /* the AI feature to call */
|
||||
'instructions': instructions, /* the prompt string */
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log('Add response into field \'#".$htmlContent."\': '+response);
|
||||
$.ajax({
|
||||
url: '". DOL_URL_ROOT."/ai/ajax/generate_content.php?token=".currentToken()."',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'format': '".dol_escape_js($format)."', /* the format for output */
|
||||
'function': '".dol_escape_js($function)."', /* the AI feature to call */
|
||||
'instructions': instructions, /* the prompt string */
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log('Add response into field \'#".$htmlContent."\': '+response);
|
||||
|
||||
jQuery('#".$htmlContent."').val(response); // If #htmlcontent is a input name or textarea
|
||||
jQuery('#".$htmlContent."').html(response); // If #htmlContent is a div
|
||||
//jQuery('#".$htmlContent."preview').val(response);
|
||||
jQuery('#".$htmlContent."').val(response); // If #htmlcontent is a input name or textarea
|
||||
jQuery('#".$htmlContent."').html(response); // If #htmlContent is a div
|
||||
//jQuery('#".$htmlContent."preview').val(response);
|
||||
|
||||
if (CKEDITOR.instances) {
|
||||
var editorInstance = CKEDITOR.instances.".$htmlContent.";
|
||||
if (editorInstance) {
|
||||
editorInstance.setReadOnly(0);
|
||||
editorInstance.setData(response);
|
||||
if (CKEDITOR.instances) {
|
||||
var editorInstance = CKEDITOR.instances.".$htmlContent.";
|
||||
if (editorInstance) {
|
||||
editorInstance.setReadOnly(0);
|
||||
editorInstance.setData(response);
|
||||
}
|
||||
//var editorInstancepreview = CKEDITOR.instances.".$htmlContent."preview;
|
||||
//if (editorInstancepreview) {
|
||||
// editorInstancepreview.setData(response);
|
||||
//}
|
||||
}
|
||||
//var editorInstancepreview = CKEDITOR.instances.".$htmlContent."preview;
|
||||
//if (editorInstancepreview) {
|
||||
// editorInstancepreview.setData(response);
|
||||
//}
|
||||
}
|
||||
|
||||
// remove readonly
|
||||
$('#ai_instructions".$htmlContent."').val('');
|
||||
// remove readonly
|
||||
$('#ai_instructions".$htmlContent."').val('');
|
||||
|
||||
apicallfinished = 1;
|
||||
if (timeoutfinished) {
|
||||
apicallfinished = 1;
|
||||
if (timeoutfinished) {
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert(error);
|
||||
console.error('error ajax', status, error);
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
alert(error);
|
||||
console.error('error ajax', status, error);
|
||||
$('#ai_status_message".$htmlContent."').hide();
|
||||
}
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@@ -1658,7 +1660,7 @@ class FormMail extends Form
|
||||
$websitepage = new WebsitePage($this->db);
|
||||
$arrayofblogs = $websitepage->fetchAll('', 'DESC', 'date_creation', 0, 0, array('type_container' => 'blogpost'));
|
||||
|
||||
$out = '<div id="template-selector" class="email-layout-container hidden" style="display:none;">';
|
||||
$out = '<div id="template-selector" class="template-selector email-layout-container hidden" style="display:none;">';
|
||||
|
||||
// Define list of email layouts to use
|
||||
$layouts = array(
|
||||
|
||||
@@ -217,11 +217,11 @@ class InfoBox
|
||||
/**
|
||||
* Save order of boxes for area and user
|
||||
*
|
||||
* @param DoliDB $dbs Database handler
|
||||
* @param int $zone Key of area (0 for Homepage, ...)
|
||||
* @param string $boxorder List of boxes with correct order 'A:123,456,...-B:789,321...'
|
||||
* @param int $userid Id of user
|
||||
* @return int Return integer <0 if KO, 0=Nothing done, > 0 if OK
|
||||
* @param DoliDB $dbs Database handler
|
||||
* @param int|string $zone Key of area ('0' for Homepage, '1', 'pagename', ...)
|
||||
* @param string $boxorder List of boxes with correct order 'A:123,456,...-B:789,321...'
|
||||
* @param int $userid Id of user
|
||||
* @return int Return integer <0 if KO, 0=Nothing done, > 0 if OK
|
||||
*/
|
||||
public static function saveboxorder($dbs, $zone, $boxorder, $userid = 0)
|
||||
{
|
||||
@@ -252,6 +252,10 @@ class InfoBox
|
||||
return -3;
|
||||
}
|
||||
|
||||
if (!is_numeric($zone)) {
|
||||
$zone = '0'; // Force $zone to a numeric value string
|
||||
}
|
||||
|
||||
// Delete all lines
|
||||
$sql = "DELETE FROM ".$dbs->prefix()."boxes";
|
||||
$sql .= " WHERE entity = ".$conf->entity;
|
||||
|
||||
@@ -123,70 +123,87 @@ class TimeSpent extends CommonObject
|
||||
'datec' => array('type' => 'datetime', 'label' => 'datec', 'enabled' => 1, 'position' => 16, 'notnull' => 0, 'visible' => -1,),
|
||||
'note' => array('type' => 'text', 'label' => 'note', 'enabled' => 1, 'position' => 18, 'notnull' => 0, 'visible' => -1,),
|
||||
);
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $rowid;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $import_key;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $fk_element;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $elementtype;
|
||||
|
||||
/**
|
||||
* @var int|string
|
||||
*/
|
||||
public $element_date;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $element_datehour;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $element_date_withhour;
|
||||
|
||||
/**
|
||||
* @var int Note seems to be int (seconds) even if declared as double in DB.
|
||||
*/
|
||||
public $element_duration;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $fk_product;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $fk_user;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
public $thm;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $invoice_id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $invoice_line_id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $intervention_id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $intervention_line_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var ?int Date creation
|
||||
*/
|
||||
public $datec;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
|
||||
@@ -51,6 +51,10 @@ function getURLContent($url, $postorget = 'GET', $param = '', $followlocation =
|
||||
|
||||
dol_syslog("getURLContent postorget=".$postorget." URL=".$url." param=".$param);
|
||||
|
||||
if (!function_exists('curl_init')) {
|
||||
return array('http_code' => 500, 'content' => '', 'curl_error_no' => 1, 'curl_error_msg' => 'PHP curl library must be installed');
|
||||
}
|
||||
|
||||
//setting the curl parameters.
|
||||
$ch = curl_init();
|
||||
|
||||
|
||||
@@ -182,13 +182,12 @@ class modAdherent extends DolibarrModules
|
||||
[
|
||||
"MEMBER_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/members",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/members",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
// Boxes
|
||||
//-------
|
||||
$this->boxes = array(
|
||||
@@ -439,8 +438,8 @@ class modAdherent extends DolibarrModules
|
||||
|
||||
// ODT template
|
||||
/*
|
||||
$src=DOL_DOCUMENT_ROOT.'/install/doctemplates/orders/template_order.odt';
|
||||
$dirodt=DOL_DATA_ROOT.'/doctemplates/orders';
|
||||
$src=DOL_DOCUMENT_ROOT.'/install/doctemplates/members/template_member.odt';
|
||||
$dirodt=DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/members';
|
||||
$dest=$dirodt.'/template_order.odt';
|
||||
|
||||
if (file_exists($src) && ! file_exists($dest)) {
|
||||
|
||||
@@ -128,7 +128,7 @@ class modBom extends DolibarrModules
|
||||
$this->const = array(
|
||||
1 => array('BOM_ADDON_PDF', 'chaine', 'generic_bom_odt', 'Name of PDF model of BOM', 0),
|
||||
2 => array('BOM_ADDON', 'chaine', 'mod_bom_standard', 'Name of numbering rules of BOM', 0),
|
||||
3 => array('BOM_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/boms', '', 0)
|
||||
3 => array('BOM_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/boms', '', 0)
|
||||
);
|
||||
|
||||
// Some keys to add into the overwriting translation tables
|
||||
@@ -480,7 +480,7 @@ class modBom extends DolibarrModules
|
||||
|
||||
// ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/boms/template_bom.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/boms';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/boms';
|
||||
$dest = $dirodt.'/template_bom.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -87,7 +87,7 @@ class modContrat extends DolibarrModules
|
||||
[
|
||||
"CONTRACT_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/contracts",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/contracts",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
@@ -231,7 +231,7 @@ class modContrat extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/contracts/template_contract.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/contracts';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/contracts';
|
||||
$dest = $dirodt.'/template_contract.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -100,7 +100,7 @@ class modExpedition extends DolibarrModules
|
||||
[
|
||||
"EXPEDITION_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/shipments",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/shipments",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
@@ -121,7 +121,7 @@ class modExpedition extends DolibarrModules
|
||||
[
|
||||
"DELIVERY_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/deliveries",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/deliveries",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
@@ -133,6 +133,7 @@ class modExpedition extends DolibarrModules
|
||||
0,
|
||||
],
|
||||
];
|
||||
|
||||
// Boxes
|
||||
$this->boxes = array(
|
||||
0 => array('file'=>'box_shipments.php', 'enabledbydefaulton'=>'Home'),
|
||||
@@ -344,7 +345,7 @@ class modExpedition extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/shipments/template_shipment.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/shipments';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/shipments';
|
||||
$dest = $dirodt.'/template_shipment.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -118,7 +118,7 @@ class modFournisseur extends DolibarrModules
|
||||
// Add ability ODT for Supplier orders
|
||||
$this->const[$r][0] = "SUPPLIER_ORDER_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/supplier_orders";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_orders";
|
||||
$this->const[$r][3] = '';
|
||||
$this->const[$r][4] = 0;
|
||||
$r++;
|
||||
@@ -126,7 +126,7 @@ class modFournisseur extends DolibarrModules
|
||||
// Add ability ODT for Supplier Invoices
|
||||
$this->const[$r][0] = "SUPPLIER_INVOICE_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_invoices";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
$r++;
|
||||
@@ -973,7 +973,7 @@ class modFournisseur extends DolibarrModules
|
||||
|
||||
//ODT template for Supplier Orders
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_orders/template_supplier_order.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_orders';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_orders';
|
||||
$dest = $dirodt.'/template_supplier_order.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
@@ -994,7 +994,7 @@ class modFournisseur extends DolibarrModules
|
||||
|
||||
//ODT template for Supplier Invoice
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_invoices/template_supplier_invoices.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_invoices';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_invoices';
|
||||
$dest = $dirodt.'/template_supplier_invoices.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -111,7 +111,7 @@ class modHoliday extends DolibarrModules
|
||||
|
||||
$this->const[$r][0] = "HOLIDAY_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/holiday";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/holiday";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
$r++;
|
||||
@@ -308,7 +308,7 @@ class modHoliday extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
/*$src=DOL_DOCUMENT_ROOT.'/install/doctemplates/holiday/template_holiday.odt';
|
||||
$dirodt=DOL_DATA_ROOT.'/doctemplates/holiday';
|
||||
$dirodt=DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/holiday';
|
||||
$dest=$dirodt.'/template_order.odt';
|
||||
|
||||
if (file_exists($src) && ! file_exists($dest))
|
||||
|
||||
@@ -138,7 +138,7 @@ class modMrp extends DolibarrModules
|
||||
$this->const = array(
|
||||
//1=>array('MRP_MO_ADDON_PDF', 'chaine', 'vinci', 'Name of default PDF model of MO', 0),
|
||||
2=>array('MRP_MO_ADDON', 'chaine', 'mod_mo_standard', 'Name of numbering rules of MO', 0),
|
||||
3=>array('MRP_MO_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/mrps', '', 0)
|
||||
3=>array('MRP_MO_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/mrps', '', 0)
|
||||
);
|
||||
|
||||
// Some keys to add into the overwriting translation tables
|
||||
@@ -534,7 +534,7 @@ class modMrp extends DolibarrModules
|
||||
|
||||
// ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/mrps/template_mo.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/mrps';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/mrps';
|
||||
$dest = $dirodt.'/template_mo.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -92,7 +92,7 @@ class modProjet extends DolibarrModules
|
||||
[
|
||||
"PROJECT_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/projects",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/projects",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
@@ -113,7 +113,7 @@ class modProjet extends DolibarrModules
|
||||
[
|
||||
"PROJECT_TASK_ADDON_PDF_ODT_PATH",
|
||||
"chaine",
|
||||
"DOL_DATA_ROOT/doctemplates/tasks",
|
||||
"DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/tasks",
|
||||
"",
|
||||
0,
|
||||
],
|
||||
@@ -380,7 +380,7 @@ class modProjet extends DolibarrModules
|
||||
|
||||
//ODT template for project
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/projects/template_project.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/projects';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/projects';
|
||||
$dest = $dirodt.'/template_project.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
@@ -396,7 +396,7 @@ class modProjet extends DolibarrModules
|
||||
|
||||
//ODT template for tasks
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/tasks/template_task_summary.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/tasks';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tasks';
|
||||
$dest = $dirodt.'/template_task_summary.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -92,7 +92,7 @@ class modReception extends DolibarrModules
|
||||
|
||||
$this->const[$r][0] = "RECEPTION_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/receptions";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/receptions";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
$r++;
|
||||
@@ -267,7 +267,7 @@ class modReception extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/reception/template_reception.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/reception';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/reception';
|
||||
$dest = $dirodt.'/template_reception.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -102,7 +102,7 @@ class modSociete extends DolibarrModules
|
||||
|
||||
$this->const[$r][0] = "COMPANY_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/thirdparties";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/thirdparties";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
$r++;
|
||||
@@ -1034,7 +1034,7 @@ class modSociete extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/thirdparties/template_thirdparty.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/thirdparties';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/thirdparties';
|
||||
$dest = $dirodt.'/template_thirdparty.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -97,14 +97,14 @@ class modStock extends DolibarrModules
|
||||
$r++;
|
||||
$this->const[$r][0] = "STOCK_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/stocks";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
|
||||
$r++;
|
||||
$this->const[$r][0] = "MOUVEMENT_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/stocks/movements";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/stocks/movements";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
|
||||
@@ -554,7 +554,7 @@ class modStock extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/stocks/template_warehouse.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/stocks';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/stocks';
|
||||
$dest = $dirodt.'/template_warehouse.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -93,7 +93,7 @@ class modSupplierProposal extends DolibarrModules
|
||||
|
||||
$this->const[$r][0] = "SUPPLIER_PROPOSAL_ADDON_PDF_ODT_PATH";
|
||||
$this->const[$r][1] = "chaine";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT/doctemplates/supplier_proposals";
|
||||
$this->const[$r][2] = "DOL_DATA_ROOT".($conf->entity > 1 ? '/'.$conf->entity : '')."/doctemplates/supplier_proposals";
|
||||
$this->const[$r][3] = "";
|
||||
$this->const[$r][4] = 0;
|
||||
|
||||
@@ -164,7 +164,7 @@ class modSupplierProposal extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/supplier_proposals/template_supplier_proposal.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/supplier_proposals';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/supplier_proposals';
|
||||
$dest = $dirodt.'/template_supplier_proposal.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -110,7 +110,7 @@ class modTicket extends DolibarrModules
|
||||
$this->const = array(
|
||||
1 => array('TICKET_ENABLE_PUBLIC_INTERFACE', 'chaine', '0', 'Enable ticket public interface', 0),
|
||||
2 => array('TICKET_ADDON', 'chaine', 'mod_ticket_simple', 'Ticket ref module', 0),
|
||||
3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0),
|
||||
3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT'.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0),
|
||||
4 => array('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'chaine', 0, 'Automatically mark ticket as read when created from backend', 0),
|
||||
5 => array('TICKET_DELAY_BEFORE_FIRST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time before a first answer to a ticket (in hours). Display a warning in tickets list if not respected.', 0),
|
||||
6 => array('TICKET_DELAY_SINCE_LAST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time between two answers on the same ticket (in hours). Display a warning in tickets list if not respected.', 0),
|
||||
@@ -414,7 +414,7 @@ class modTicket extends DolibarrModules
|
||||
|
||||
//ODT template
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/tickets/template_ticket.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/tickets';
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/tickets';
|
||||
$dest = $dirodt.'/template_ticket.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -15,26 +15,22 @@
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Need to have the following variables defined:
|
||||
* $conf
|
||||
* $formmail
|
||||
* $formwebsite (optional)
|
||||
* $showlinktolayout='emailing', 'email', 'websitepage', ...
|
||||
* $showlinktolayoutlabel='...'
|
||||
* $showlinktoai ('' or 'textgeneration', 'textgenerationemail', 'textgenerationwebpage', ...)
|
||||
* $showlinktoailabel='...'
|
||||
* $htmlname
|
||||
*/
|
||||
/**
|
||||
|
||||
/**
|
||||
* @var Conf $conf
|
||||
* @var ?FormMail $formmail
|
||||
* @var ?FormWebsite $formwebsite
|
||||
* @var string $htmlname
|
||||
* @var string $showlinktolayout
|
||||
* @var string $showlinktolayoutlabel
|
||||
* @var ?FormMail $formmail
|
||||
* @var ?FormWebsite $formwebsite
|
||||
* @var string $htmlname
|
||||
* @var string $showlinktolayout 'emailing', 'email', 'websitepage', ...
|
||||
* @var string $showlinktolayoutlabel '...'
|
||||
* @var string $showlinktoai '' or 'textgeneration', 'textgenerationemail', 'textgenerationwebpage', ...
|
||||
* @var string $showlinktoailabel '...'
|
||||
* @var string $htmlname
|
||||
* @var ?string $out
|
||||
*/
|
||||
// Protection to avoid direct call of template
|
||||
|
||||
//Protection to avoid direct call of template
|
||||
if (empty($conf) || !is_object($conf)) {
|
||||
print "Error, template page can't be called as URL";
|
||||
exit(1);
|
||||
@@ -59,11 +55,12 @@ if (empty($htmlname)) {
|
||||
@phan-var-force ?string $out
|
||||
';
|
||||
|
||||
if (!isset($out)) {
|
||||
if (!isset($out)) { // Init to empty string if not defined
|
||||
$out = '';
|
||||
}
|
||||
|
||||
// Add link to add layout
|
||||
if ($showlinktolayout) {
|
||||
if ($showlinktolayout) { // May be set only if MAIN_EMAIL_USE_LAYOUT is set
|
||||
$out .= '<a href="#" id="linkforlayouttemplates" class="notasortlink inline-block alink marginrightonly">';
|
||||
$out .= img_picto($showlinktolayoutlabel, 'layout', 'class="paddingrightonly"');
|
||||
$out .= $showlinktolayoutlabel.'...';
|
||||
@@ -72,10 +69,10 @@ if ($showlinktolayout) {
|
||||
$out .= '<script>
|
||||
$(document).ready(function() {
|
||||
$("#linkforlayouttemplates").click(function() {
|
||||
console.log("We click on linkforlayouttemplates");
|
||||
console.log("We click on linkforlayouttemplates, we toggle .template-selector");
|
||||
event.preventDefault();
|
||||
jQuery("#template-selector").toggle();
|
||||
jQuery("#ai_input'.$htmlname.'").hide();
|
||||
jQuery(".template-selector").toggle();
|
||||
jQuery(".ai_input'.$htmlname.'").hide();
|
||||
jQuery("#pageContent").show(); // May exists for website page only
|
||||
});
|
||||
});
|
||||
@@ -92,10 +89,10 @@ if ($showlinktoai) {
|
||||
$out .= '<script>
|
||||
$(document).ready(function() {
|
||||
$("#linkforaiprompt'.$showlinktoai.'").click(function() {
|
||||
console.log("formlayoutai.tpl: We click on linkforaiprompt'.$showlinktoai.', we toggle #ai_input'.$showlinktoai.'");
|
||||
console.log("formlayoutai.tpl: We click on linkforaiprompt'.$showlinktoai.', we toggle .ai_input'.$showlinktoai.'");
|
||||
event.preventDefault();
|
||||
jQuery("#ai_input'.$htmlname.'").toggle();
|
||||
jQuery("#template-selector").hide();
|
||||
jQuery(".ai_input'.$htmlname.'").toggle();
|
||||
jQuery(".template-selector").hide();
|
||||
jQuery(".email-layout-container").hide();
|
||||
if (!jQuery("#ai_input'.$htmlname.'").is(":hidden")) {
|
||||
console.log("Set focus on input field #ai_instructions'.$htmlname.'");
|
||||
|
||||
@@ -2508,7 +2508,7 @@ UrlPublicInterfaceLabelAdmin=Alternative URL for public interface
|
||||
UrlPublicInterfaceHelpAdmin=It is possible to define an alias to the web server and thus make available the public interface with another URL (the virtual host server must act as a proxy on the standard URL)
|
||||
ExportUseForce=Use the parameter -f
|
||||
ExportUseForceHelp=Force to continue the export even when an error is found (Backup may not be reliable)
|
||||
CustomPrompt=Custom prompts
|
||||
CustomPrompt=Custom prompts and models
|
||||
AiDescription=AI (Artificial Intelligence) features
|
||||
AiDescriptionLong=Provides AI (Artificial Intelligence) features in different parts of the application. Need external AI API.
|
||||
AI_API_KEY=Key for AI api
|
||||
@@ -2614,3 +2614,5 @@ Privileges=Privileges
|
||||
FieldsLinked=Fields Linked
|
||||
PDF_XXX_SHOW_PRICE_INCL_TAX=Show column Price including tax
|
||||
AvailableWithSomePDFTemplatesOnly=Feature not supported on old PDF templates
|
||||
SelectAService=Select the kind of service to use
|
||||
SelectFeatureToTest=Select the feature to test
|
||||
|
||||
@@ -283,6 +283,7 @@ ImportDataset_tax_contrib=Social/fiscal taxes
|
||||
ImportDataset_tax_vat=VAT payments
|
||||
ErrorBankAccountNotFound=Error: Bank account not found
|
||||
FiscalPeriod=Accounting period
|
||||
ErrorNoFiscalyearDefined=Error, no fiscal year defined (See %s - %s - %s)
|
||||
FiscalYearSetAsDefault=Fiscal year (%s) defined as default
|
||||
FiscalYearFromTo=Period from %s to %s
|
||||
FiscalYearOpened=Fiscal year opened
|
||||
|
||||
@@ -497,7 +497,7 @@ class modMyModule extends DolibarrModules
|
||||
foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
|
||||
if ($myTmpObjectArray['includerefgeneration']) {
|
||||
$src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_myobjects.odt';
|
||||
$dirodt = DOL_DATA_ROOT.'/doctemplates/'.$moduledir;
|
||||
$dirodt = DOL_DATA_ROOT.($conf->entity > 1 ? '/'.$conf->entity : '').'/doctemplates/'.$moduledir;
|
||||
$dest = $dirodt.'/template_myobjects.odt';
|
||||
|
||||
if (file_exists($src) && !file_exists($dest)) {
|
||||
|
||||
@@ -655,7 +655,7 @@ if (isModEnabled('stock') && $user->hasRight('stock', 'mouvement', 'read')) {
|
||||
$db->free($resql);
|
||||
|
||||
if (empty($num)) {
|
||||
$colspan = 4;
|
||||
$colspan = 5;
|
||||
if (isModEnabled('productbatch')) {
|
||||
$colspan++;
|
||||
}
|
||||
|
||||
@@ -208,13 +208,15 @@ class Task extends CommonObjectLine
|
||||
* @var int|string
|
||||
*/
|
||||
public $timespent_datehour; // More accurate start date (same than timespent_date but includes hours, minutes and seconds)
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
public $timespent_withhour; // 1 = we entered also start hours for timesheet line
|
||||
public $timespent_withhour; // 0 or 1 = we have entered also start hours for timesheet line
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
||||
public $timespent_fk_user;
|
||||
/**
|
||||
* @var float
|
||||
@@ -1656,10 +1658,9 @@ class Task extends CommonObjectLine
|
||||
$timespent->fk_user = $this->timespent_fk_user;
|
||||
$timespent->fk_product = $this->timespent_fk_product;
|
||||
$timespent->note = $this->timespent_note;
|
||||
$timespent->datec = $this->db->idate($now);
|
||||
$timespent->datec = $now;
|
||||
|
||||
$result = $timespent->create($user);
|
||||
|
||||
if ($result > 0) {
|
||||
$ret = $result;
|
||||
$this->timespent_id = $result;
|
||||
|
||||
@@ -189,7 +189,6 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
|
||||
$search_year = '';
|
||||
$search_note = '';
|
||||
$search_duration = '';
|
||||
$search_value = '';
|
||||
$search_date_startday = '';
|
||||
$search_date_startmonth = '';
|
||||
$search_date_startyear = '';
|
||||
@@ -261,6 +260,7 @@ if ($action == 'addtimespent' && $user->hasRight('projet', 'time')) {
|
||||
$object->timespent_withhour = 1;
|
||||
} else {
|
||||
$object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timemonth"), GETPOSTINT("timeday"), GETPOSTINT("timeyear"));
|
||||
$object->timespent_withhour = 0;
|
||||
}
|
||||
$object->timespent_fk_user = GETPOSTINT("userid");
|
||||
$object->timespent_fk_product = GETPOSTINT("fk_product");
|
||||
@@ -309,6 +309,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us
|
||||
$object->timespent_withhour = 1;
|
||||
} else {
|
||||
$object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear"));
|
||||
$object->timespent_withhour = 0;
|
||||
}
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
$object->timespent_fk_product = GETPOSTINT("fk_product");
|
||||
@@ -338,6 +339,7 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us
|
||||
$object->timespent_withhour = 1;
|
||||
} else {
|
||||
$object->timespent_date = dol_mktime(12, 0, 0, GETPOSTINT("timelinemonth"), GETPOSTINT("timelineday"), GETPOSTINT("timelineyear"));
|
||||
$object->timespent_withhour = 0;
|
||||
}
|
||||
$object->timespent_fk_user = GETPOSTINT("userid_line");
|
||||
$object->timespent_fk_product = GETPOSTINT("fk_product");
|
||||
|
||||
@@ -52,7 +52,7 @@ if (empty($id) && empty($ref)) {
|
||||
$id = $user->id;
|
||||
}
|
||||
|
||||
$expand = $_COOKIE['virtualcard_expand'];
|
||||
$expand = empty($_COOKIE['virtualcard_expand']) ? '' : $_COOKIE['virtualcard_expand'];
|
||||
|
||||
$object = new User($db);
|
||||
if ($id > 0 || !empty($ref)) {
|
||||
|
||||
@@ -3548,7 +3548,7 @@ if (!GETPOST('hide_websitemenu')) {
|
||||
|
||||
print '<span class="websiteselection">';
|
||||
|
||||
print '<input type="image" class="valignmiddle buttonwebsite" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshpage" value="'.$langs->trans("Load").'"'.(($action != 'editsource') ? '' : ' disabled="disabled"').'>';
|
||||
print '<input type="image" class="valignmiddle buttonwebsite hideonsmartphone" src="'.img_picto('', 'refresh', '', 0, 1).'" name="refreshpage" value="'.$langs->trans("Load").'"'.(($action != 'editsource') ? '' : ' disabled="disabled"').'>';
|
||||
|
||||
// Print nav arrows
|
||||
$pagepreviousid = 0;
|
||||
|
||||
Reference in New Issue
Block a user